/* * This file contains a function, get_dir_list() that will get a directory * listing and put all the names into a table (an array of char *'s table) * and return it to you (along with the number of entries in the directory * if desired). The table is NULL terminated (i.e. the entry after the last * one is a NULL), and is just like an argv style array. * * If an error occurs (memory allocation, bad directory name, etc), you * will get a NULL back. * * Each entry of the returned table points to a NULL-terminated string * that contains the name of a file in the directory. If the name is * a directory, it has a slash appended to it. * * When you are done with the table, you should free it manually, or you * can call the function free_table() provided down below. * * See the sample main() down below for how to use it. Ignore (or steal * if you'd like) the other code that isn't particularly relevant (i.e. * the support functions). * * Dominic Giampaolo * dbg@sgi.com */ #include #include #include #include #include #include #include #include #include #include #include "xrmap.h" #include "numdefs.h" extern Display * dpy; extern int scr; extern GC gc; extern Window cmdwin, explwin; extern int char_width; extern XFontStruct * xfont[6]; extern int fonth[6], fontasc[6]; extern unsigned int explwin_width0, explwin_width, explwin_height, explwin_on; extern int explwin_x, explwin_y; extern Pixmap explpix; extern int expl_table_entries; extern int expl_lines; extern int expl_shift; extern int expl_output; extern int caret_pos; extern int line_clicked; extern char expl_currdir[256]; extern char *expl_implicit; extern char **expl_dirtable; extern char *file_filter; extern char *cmd_string; extern char **msg; extern char *editor_cmd, *im_viewer, *ps_viewer, *svg_viewer, *html_viewer, *midi_cmd; extern char *prog_cmd[7]; extern void draw_win_string(ImageLayout *scene, Window win, char *s, int position); extern void do_activate(ImageLayout * scene, KeySym keysym); void free_table(char **table, int n) { char **orig = table; for (; n > 0; n--, table++) { if (*table) free(*table); } free(orig); } void free_dirlist(char **table) { char **orig = table; while(*table) { free(*table); table++; } free(orig); } int dup_strcmp(char **a, char **b) { return strcmp(*a, *b); } char *get_file_name(struct dirent *d) { struct stat s; char *name; if (d == NULL) { fprintf(stderr, "BUG (got a NULL in get_file_name()).\n"); return NULL; } if (stat(d->d_name, &s) < 0) { perror(d->d_name); return NULL; } if (S_ISDIR(s.st_mode)) { name = (char *)malloc(strlen(d->d_name)+2); if (name == NULL) return NULL; sprintf(name, "%s/", d->d_name); } else { name = (char *)strdup(d->d_name); } return name; } int file_filter_check(char *scanit) { struct stat buf; if (scanit == NULL) return 1; if (!strcmp(scanit, "./")) return 1; stat(scanit, &buf); if (S_ISDIR(buf.st_mode)) return 0; if (file_filter==NULL) return 0; if (*file_filter==0) return 0; if (strstr(scanit, file_filter)) return 0; else return 1; } #define CHUNK 100 char **get_dir_list(char *dirname, int *num_entries) { int i,size=CHUNK; char **table, old_dir[MAXPATHLEN]; DIR *dir; struct dirent *dirent; getcwd(old_dir, MAXPATHLEN); if (dirname && chdir(dirname) < 0) return NULL; dir = opendir("."); if (dir == NULL) { chdir(old_dir); return NULL; } table = (char **)calloc(size, sizeof(char *)); if (table == NULL) { closedir(dir); chdir(old_dir); return NULL; } dirent = NULL; i = 0; for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) { table[i] = get_file_name(dirent); if (file_filter_check(table[i])) continue; /* continue if table[i] is void or doesn't match the filter */ i++; if (i == size) { char **table2; size *= 2; table2 = (char **)realloc(table, size * sizeof(char *)); if (table2 == NULL) { free_table(table, i); closedir(dir); chdir(old_dir); return NULL; } table = table2; } } table[i] = NULL; /* make sure the table ends with a NULL */ if (num_entries) *num_entries = i; closedir(dir); chdir(old_dir); return table; } void show_explwin(ImageLayout *scene, int x, int y) { static int expl_shift_old = -1; int i, j, b, d, w, p, h, ht, h_skip, hp_skip, char_space; int activate; char *s; char *banner[4] = { "home", "share", " /", " ."}; XSizeHints xsh; activate = 0; if (!explwin_on) { activate = 1; expl_shift = 0; explwin_on = 1; if (explwin_x>-100000) { xsh.flags = USPosition | PPosition; xsh.x = explwin_x; xsh.y = explwin_y; XSetWMNormalHints(dpy, explwin, &xsh); } } XMapRaised(dpy, explwin); d = 3*char_width/2; char_space = char_width * 4; h_skip = fonth[0]+8; XSetFont(dpy, gc, xfont[0]->fid); if (y == 0) { activate = 1; XClearArea(dpy, explwin, 0, 0, explwin_width, h_skip, False); w = 8 * char_space; XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix); XFillRectangle(dpy, explwin, gc, 0, 0, w, h_skip); w = explwin_width - 2*char_space; XSetForeground(dpy, gc, scene->color[C_BG_ESCAPE].pix); XFillRectangle(dpy, explwin, gc, w, 0, explwin_width, h_skip); XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix); for (i=0; i<=4; i++) { w = 2*i*char_space; s = banner[i]; if (i<=3) XDrawString(dpy, explwin, gc, d+w, fontasc[0]+4, s, strlen(s)); if (i>=1) XDrawLine(dpy, explwin, gc, w, 0, w, h_skip); } w = explwin_width - 2*char_space; s = msg[ESCAPE]; XDrawString(dpy, explwin, gc, d+w, fontasc[0]+4, s, strlen(s)); XDrawLine(dpy, explwin, gc, w, 0, w, h_skip); XDrawLine(dpy, explwin, gc, 0, h_skip, explwin_width, h_skip); } parse_again: if (y <= 1) { activate = 1; XClearArea(dpy, explwin, 0, h_skip+1, explwin_width, explwin_height, False); XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix); XDrawString(dpy, explwin, gc, d, fontasc[0] + h_skip + 4, expl_currdir, strlen(expl_currdir)); h = 2*h_skip; XDrawLine(dpy, explwin, gc, 0, h, explwin_width, h); } if (!expl_dirtable) { activate = 1; expl_dirtable = get_dir_list(expl_currdir, &expl_table_entries); if (expl_dirtable) qsort(expl_dirtable, expl_table_entries, sizeof(char *), (int (*)(const void *, const void *))dup_strcmp); } if (!expl_dirtable) { char *error = msg[DIRECTORY_INEXISTENT_OR_INACCESSIBLE]; XClearArea(dpy, explwin, 0, 2 * h_skip + 1, explwin_width, explwin_height, False); XSetForeground(dpy, gc, scene->color[C_FG_IMAGE].pix); XDrawString(dpy, explwin, gc, d, 3*h_skip, error, strlen(error)); expl_shift_old = -1; return; } hp_skip = (5*h_skip)/6; expl_lines = (explwin_height-2*h_skip)/hp_skip; if (y <= 2) { if (!activate && expl_shift_old == expl_shift) return; expl_shift_old = expl_shift; XClearArea(dpy, explwin, 0, 2 * h_skip + 1, explwin_width - 13, explwin_height, False); XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix); XFillRectangle(dpy, explwin, gc, explwin_width - 12, 2 * h_skip + 12, 12, explwin_height - 2*h_skip - 24); XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix); XDrawLine(dpy, explwin, gc, explwin_width - 13, 2*h_skip, explwin_width - 13, explwin_height); /* Drawing small triangular icons */ w = explwin_width - 6; h = 2 * h_skip + 1; for (i=0; i<=10; i++) XDrawLine(dpy,explwin, gc, w-i/2, h+i, w+i/2, h+i); h = explwin_height-1; for (i=0; i<=10; i++) XDrawLine(dpy, explwin, gc, w-i/2, h-i, w+i/2, h-i); /* drawing the thumb */ w = explwin_width - 10; p = explwin_height - 2 * h_skip - 28; ht = p * (expl_lines+1) / (expl_table_entries+1); if (ht<20) ht = 20; if (ht>p/2) ht = p/2; p = p - ht; h = 2 * h_skip + 14; if (expl_table_entries>2) h += (expl_shift * p)/(expl_table_entries-2); XDrawRectangle(dpy, explwin, gc, w, h, 7, ht); } else XClearArea(dpy, explwin, 2, 2 * h_skip + 1, 3, explwin_height, False); for (i=0; i=3) { p = (y-2*h_skip)/hp_skip; if (p==i && x<=XTextWidth(xfont[0], s, strlen(s))+8) { if (b==-1) { if (!strcmp(s, "../")) { i = strlen(expl_currdir)-1; if (expl_currdir[i]=='/' && i>0) { expl_currdir[i] = '\0'; --i; s = rindex(expl_currdir, '/'); if (s) s[1] = '\0'; } } else strcat(expl_currdir, s); free_dirlist(expl_dirtable); expl_dirtable = NULL; expl_shift = 0; y = 1; goto parse_again; } XSetForeground(dpy, gc, scene->color[C_FG_TICKS].pix); XFillRectangle(dpy, explwin, gc, d/4, j-5, 3, 4); if (expl_output) { char *cmd_old; cmd_old = cmd_string; cmd_string = malloc(strlen(expl_currdir)+strlen(s)+4); if (!strncmp(expl_currdir, expl_implicit, strlen(expl_implicit))) { sprintf(cmd_string, "%s%s", expl_currdir+strlen(expl_implicit), s); } else sprintf(cmd_string, "%s%s", expl_currdir, s); caret_pos = strlen(cmd_string); draw_win_string(scene, cmdwin, cmd_string, BOTTOM); if (!strcmp(cmd_old, cmd_string) && line_clicked>=1) { str2value(scene, line_clicked, cmd_string); draw_win_cmd(scene, 2); } if (cmd_old) free(cmd_old); } else { char cmd[512]; prog_cmd[0] = editor_cmd; prog_cmd[1] = im_viewer; prog_cmd[2] = ps_viewer; prog_cmd[3] = svg_viewer; prog_cmd[4] = html_viewer; prog_cmd[5] = midi_cmd; prog_cmd[6] = "xrmap -rcfile"; sprintf(cmd, "%s %s%s &", prog_cmd[b], expl_currdir, s); system(cmd); } } } if (b==-1) XSetForeground(dpy, gc, scene->color[C_FG_DIR].pix); else if (b==1) XSetForeground(dpy, gc, scene->color[C_FG_IMAGE].pix); else XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix); XDrawString(dpy, explwin, gc, d, j, s, strlen(s)); } } void close_explwin() { get_window_placement(explwin, &explwin_x, &explwin_y, &explwin_width, &explwin_height); XUnmapWindow(dpy, explwin); explwin_on = 0; }