/* flist.c: file listbox for CSCR curses/Allegro text wrapper library By L. Ross Raszewski two functions used in this library are platform-dependant: _fixpath(in,out) canonicalizes a path name and __file_exists(in) returns nonzero if the given file exists Documentation: This library provides a function, get_flbox, which displays a file list box in a cscr video window. int get_flbox(char *_from, char *to, char *_filter, int flags) _from: the directory to start in. to: the output file name is stored here. get_flbox does no range checking, so this must be large enough. MAX_FILENAME is a good size. An initial value will be used as the default. if to appears to contain a path name, that path will be used unless F_NOCHDIR is specified _filter: the initial filter. only files mathcing the given pattern will be displayed. flags: bitwise-OR of zero or more of the following constants: FL_NOFILTER: Do not allow the user to change the filter FL_EXIST: Do not return files which do not exist FL_NOTYPE: Do not allow the user to type a name in by hand FL_NOCANCEL: Do not honor user cancel requests FL_NOCHDIR: Do not allow the user to change the directory (note that to may still contain a user-inputted directory) return values: FL_OK: the user selected a file FL_CANCEL: the user pressed escape to cancel */ #include #include #include #include #include #include #include "cscr.h" #include #include #include "flist.h" #ifdef UNIX #define __file_exists(x) (!access((x),F_OK)) #include #define _fixpath(x,y) realpath(x,y) #include int isdir(char *s) { struct stat b; stat(s,&b); return S_ISDIR(b.st_mode); } static char *basename(char *s) { char *c=strrchr(s,'/'); if (c) return c; else return s; } static char *dirname(char *s) { char *o=malloc(strlen(s)+1); char *c; strcpy(o,s); if (isdir(o)) return o; if ((c=strrchr(o,'/'))) *c=0; return o; } #endif #define FLIST_HEIGHT (cscr_getlines()-11) #define FLIST_WIDTH (cscr_getcols()/4) // Render the whole listbox static void render_listbox(char *files[], int f, int fs, char *dirs[], int d, int ds, char *filter, char *from, char *to) { int fm=f, dm = d; int i; if ((fm-fs)>= FLIST_HEIGHT) fm = fs +FLIST_HEIGHT+1; if ((dm-ds)> FLIST_HEIGHT) dm = ds +FLIST_HEIGHT+1; cscr_clear(); cscr_moveyx(1,1); cscr_printw("%s",from); cscr_moveyx(3,2); cscr_printw("Files:"); cscr_moveyx(3,FLIST_WIDTH*2); cscr_printw("Directories:"); if (fs > 0) { cscr_moveyx(3,FLIST_WIDTH); cscr_printw("[%d]",fs); } if (fm != f) { cscr_moveyx(FLIST_HEIGHT+5,FLIST_WIDTH); cscr_printw("[%d]",f-fm); } if (ds > 0) { cscr_moveyx(3,FLIST_WIDTH*3); cscr_printw("[%d]",ds); } if (dm != d) { cscr_moveyx(FLIST_HEIGHT+5,FLIST_WIDTH*3); cscr_printw("[%d]",d-dm); } for(i=fs; id_name); #ifdef UNIX if (!isdir(buff)) #else if (access(buff,D_OK)) #endif { if (!fnmatch(filter,d->d_name,0)) files[f++]=strdup(d->d_name); } else if (strcmp(d->d_name,".")) dirs[ds++]=strdup(d->d_name); } closedir(dir); qsort(files,f,sizeof(char *),sort_string); qsort(dirs,ds,sizeof(char *),sort_string); render_listbox(files,f,0,dirs, ds,0, filter, from,to); ifp=strlen(to); ffp=strlen(filter); while(1) { cscr_moveyx(fp-fs+4,2); cscr_addch('>'); cscr_moveyx(dp-dss+4,2*FLIST_WIDTH); cscr_addch('>'); if (focus==1 && flags & FL_NOFILTER) focus=2; if (focus==3 && flags & FL_NOCHDIR) focus=0; switch(focus) { case 0: cscr_moveyx(cscr_getlines()-5,7+ifp); break; case 1: cscr_moveyx(cscr_getlines()-4,9+ffp); break; case 2: cscr_moveyx(fp-fs+4,2); break; case 3: cscr_moveyx(dp-dss+4,2*FLIST_WIDTH); break; } cscr_refresh(); cscr_blinkey(); c = cscr_getch(); cscr_blinkey(); if (c=='\t') focus = (focus + 1) % 4; else if (c==27 && !(flags & FL_NOCANCEL)) { for(i=0;i strlen(to)) ifp=strlen(to); render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c == 330 && ifp < strlen(to)) { memmove(to+ifp,to+ifp+1,strlen(to)-ifp+1); render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c== 8 && ifp > 0) { ifp--; memmove(to+ifp,to+ifp+1,strlen(to)-ifp+1); render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c < 32 || c > 127) break; memmove(to+ifp+1,to+ifp,strlen(to)-ifp+1); to[ifp++]=c; cscr_addstr(to+ifp-1); break; case 1: if (c == KEY_HOME) { ffp=0; break; } if (c == KEY_END) { ffp = strlen(filter); break; } if (c == 13) { goto top; } if (c == KEY_LEFT) { ffp--; if (ffp < 0) ffp=0; break; } if (c==KEY_RIGHT) { ffp++; if (ffp > strlen(filter)) ffp=strlen(filter); render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c == 330 && ffp < strlen(filter)) { memmove(filter+ffp,filter+ffp+1,strlen(filter)-ffp+1); render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c== 8 && ffp > 0) { ffp--; memmove(filter+ffp,filter+ffp+1,strlen(filter)-ffp+1); render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c < 32 || c > 127) break; memmove(filter+ffp+1,filter+ffp,strlen(filter)-ffp+1); filter[ffp++]=c; cscr_addstr(filter+ffp-1); break; case 2: if (c==KEY_HOME) { fp=0; fs=0; render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c == KEY_END) { fp = f-1; fs = fp - FLIST_HEIGHT; if (fs < 0) fs = 0; render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c==13) { strcpy(to,files[fp]); ifp=strlen(to); focus=0; render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c == KEY_UP) { cscr_addch(' '); fp--; if (fp<0) fp = 0; if (fp=f) fp = f-1; if (fp>(fs+FLIST_HEIGHT)) fs ++; } else { int i; for(i=fp+1;i(fs+FLIST_HEIGHT)) fs++; while (fp <(fs)) fs--; } render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; case 3: if (c==KEY_HOME) { dp=0; dss=0; render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c == KEY_END) { dp = ds-1; dss = dp - FLIST_HEIGHT; if (dss < 0) dss = 0; render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); break; } if (c==13) { strcat(from,"/"); strcat(from,dirs[dp]); goto top; } if (c == KEY_UP) { cscr_addch(' '); dp--; if (dp<0) dp = 0; if (dp=ds) dp = ds-1; if (dp>(dss+FLIST_HEIGHT)) dss ++; } else { int i; for(i=dp+1;i(dss+FLIST_HEIGHT)) dss++; while (dp <(dss)) dss--; } render_listbox(files,f,fs,dirs,ds,dss,filter,from,to); } } }