/**************************************************************** * * a new FSEL placed in public domain by D N Korte 26 Dec 86. * Do with it whatever you want... * * modified for undelete program & GNU c by T Blight, Dec 1992 * *****************************************************************/ #include #include #include #include #include #include #include #include #include "undel.h" #define QUIT 0 #define CONTINUE 1 #define MAXFILES 144 /* abs max 327 (overflow FS_calc_curfirst) */ #define WINDSIZE 9 /* size of file window */ #define DIAMOND_THINGY 7 /*** indexes into rs_object ***/ #define CANCBUT 2 #define OKBUT 3 #define NEWNAME 4 #define WINDOW 5 #define DRVA 6 #define DRVB 7 #define DRVC 8 #define DRVD 9 #define DRVE 10 #define DRVF 11 #define SLEXTN0 12 #define SLEXTN1 13 #define SLEXTN2 14 #define SLEXTN3 15 #define SLEXTN4 16 #define EXTN3 17 #define EXTN4 18 #define FNAM1 19 #define FNAM2 20 #define FNAM3 21 #define FNAM4 22 #define FNAM5 23 #define FNAM6 24 #define FNAM7 25 #define FNAM8 26 #define FNAM9 27 #define FILEBOX 28 #define TOPBAR 29 #define UARROW 30 #define SLIDBOX 31 #define MVSLIDE 32 #define DARROW 33 #define TOPTEXT 34 struct finfo { char name[9]; /* name of file */ char extn[4]; /* extension of it */ BOOL dirflag; /* FALSE if not a directory, TRUE if is directory */ }; PRIVATE void FS_dir_dis( struct finfo[], int[], int, int); PRIVATE void FS_dir_select_good( int, const char *, const char *, const char *, char *, char *, struct finfo[], int, int[], int *, int *); PRIVATE int FS_dir_read(char *drivs, char *path, struct finfo files[], int *numfiles, char *dispath); PRIVATE void FS_shift_curfirst(int, int, int *); PRIVATE void FS_calc_curfirst(int, int, int *); PRIVATE void FS_calc_slid_box(int, int, BOOL); PRIVATE void FS_setname( int, char *); PRIVATE void FS_path_lengthen( char *, int, struct finfo[], char *); PRIVATE void FS_path_shorten( char *, char *); PRIVATE void FS_pathtrunc( char *, const char *); PRIVATE BOOL FS_wildmatch( const char *, const char *); PRIVATE void FS_exchinfo( struct finfo *, struct finfo *); PRIVATE int FS_find_last_delim(char, char *); PRIVATE void FS_strxcpy(char *, const char*); PRIVATE char file_ids[WINDSIZE][17]; /* spot for (10) 16-char formatted filenames in menu */ PRIVATE TEDINFO rs_tedinfo[] = { NULL,"________.___","FFFFFFFFFFF",3,0,0,0x1180,0, 0,0,13, /* 0 for newname */ NULL,".___", "", 3,0,2,0x1180,0,-2,0,5, /* 1 for extn0 */ NULL,".___", "", 3,0,2,0x1180,0,-2,0,5, /* 2 for extn1 */ NULL,".___", "", 3,0,2,0x1180,0,-2,0,5, /* 3 for extn2 */ NULL,".___", "FFF", 3,0,2,0x1180,0,-2,0,5, /* 4 for extn3 */ NULL,".___", "FFF", 3,0,2,0x1180,0,-2,0,5, /* 5 for extn4 */ NULL,"", "", 3,0,2,0x1180,0, 0,0,0 /* 6 for pathname in TOPBAR */ }; /* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | +-- te_tmplen length of template (+1 for null) | | | | | | | | | ----- te_txtlen length of text (+1 for null) | | | | | | | | +------ te_thickness border thickness (-) outside | | | | | | | +--------- te_junk2 | | | | | | +-------------- te_color packed color information | | | | | +------------------ te_just 0=left 1=right 2=centered | | | | +-------------------- te_junk1 | | | +---------------------- te_font 3=system 5=small | | +------------------------------- *te_pvalid ptr to validation chars | +---------------------------------------------- *te_ptmplt ptr to template +------------------------------------------------------- *te_ptext ptr to text */ PRIVATE OBJECT rs_object[] = { -1,1,34,G_BOX, NONE, OUTLINED, 0x21100L, 0, 0,38,15, /* 0 dialog box */ 2,-1,-1,G_STRING, NONE, NORMAL, 0L, 2, 1,34,1, /* 1 TITLE */ 3,-1,-1,G_BUTTON, SELECTABLE|EXIT, NORMAL,(unsigned long)"CANCEL",22, 3, 6,1, /* 2 CANCBUT */ 4,-1,-1,G_BUTTON, SELECTABLE|EXIT|DEFAULT, NORMAL,(unsigned long)"OK",30, 3, 6,1, /* 3 OKBUT */ 5,-1,-1,G_FTEXT, EDITABLE, NORMAL,(unsigned long)&rs_tedinfo[0],22, 5,12,1, /* 4 NEWNAME */ 6,-1,-1,G_IBOX, NONE, NORMAL, 0xFF1100L, 2, 3,18,11, /* 5 WINDOW (outline of pretend window) */ 7,-1,-1,G_BUTTON, SELECTABLE|EXIT|RBUTTON, NORMAL,(unsigned long)"A:",22, 7, 4,1, /* 6 DRVA */ 8,-1,-1,G_BUTTON, SELECTABLE|EXIT|RBUTTON, NORMAL,(unsigned long)"B:",27, 7, 4,1, /* 7 DRVB */ 9,-1,-1,G_BUTTON, SELECTABLE|EXIT|RBUTTON, NORMAL,(unsigned long)"C:",32, 7, 4,1, /* 8 DRVC */ 10,-1,-1,G_BUTTON, SELECTABLE|EXIT|RBUTTON, NORMAL,(unsigned long)"D:",22, 9, 4,1, /* 9 DRVD */ 11,-1,-1,G_BUTTON, SELECTABLE|EXIT|RBUTTON, NORMAL,(unsigned long)"E:",27, 9, 4,1, /* 10 DRVE */ 12,-1,-1,G_BUTTON, SELECTABLE|EXIT|RBUTTON, NORMAL,(unsigned long)"F:",32, 9, 4,1, /* 11 DRVF */ 13,-1,-1,G_FBOXTEXT,SELECTABLE|TOUCHEXIT, NORMAL,(unsigned long)&rs_tedinfo[1],22,11, 4,1, /* 12 SLEXTN0 */ 14,-1,-1,G_FBOXTEXT,SELECTABLE|TOUCHEXIT, NORMAL,(unsigned long)&rs_tedinfo[2],27,11, 4,1, /* 13 SLEXTN1 */ 15,-1,-1,G_FBOXTEXT,SELECTABLE|TOUCHEXIT, NORMAL,(unsigned long)&rs_tedinfo[3],32,11, 4,1, /* 14 SLEXTN2 */ 16,-1,-1,G_BOX, SELECTABLE|TOUCHEXIT, NORMAL, 0xFE1100L,22,13, 2,1, /* 15 SLEXTN3 */ 17,-1,-1,G_BOX, SELECTABLE|TOUCHEXIT, NORMAL, 0xFE1100L,30,13, 2,1, /* 16 SLEXTN4 */ 18,-1,-1,G_FBOXTEXT,EDITABLE, NORMAL,(unsigned long)&rs_tedinfo[4],24,13, 4,1, /* 17 EXTN3 */ 28,-1,-1,G_FBOXTEXT,EDITABLE, NORMAL,(unsigned long)&rs_tedinfo[5],32,13, 4,1, /* 18 EXTN4 */ 20,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[0][0], 0, 0,15,1, /* 19 FNAM1 (note that for doubleclick */ 21,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[1][0], 0, 1,15,1, /* 20 FNAM2 (to work, these objects must */ 22,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[2][0], 0, 2,15,1, /* 21 FNAM3 (be G_STRING and must have */ 23,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[3][0], 0, 3,15,1, /* 22 FNAM4 (ob_flags exactly as shown. */ 24,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[4][0], 0, 4,15,1, /* 23 FNAM5 (When selected, bit 15 of */ 25,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[5][0], 0, 5,15,1, /* 24 FNAM6 (form_do return will be */ 26,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[6][0], 0, 6,15,1, /* 25 FNAM7 (set if gotten by a */ 27,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[7][0], 0, 7,15,1, /* 26 FNAM8 (doubleclick. */ 28,-1,-1,G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,(unsigned long)&file_ids[8][0], 0, 8,15,1, /* 27 FNAM9 */ 29,19,27,G_BOX, NONE, NORMAL, 0x011100L, 2, 4,15,10, /* 28 FILEBOX (box is parent for FNAMs) */ 30,-1,-1,G_BOX, NONE, NORMAL, 0xFF1121L, 2, 3,18,1, /* 29 TOPBAR */ 31,-1,-1,G_BOXCHAR, TOUCHEXIT, NORMAL, 0x01011180L,17, 4, 3,1, /* 30 UARROW (adjust y later) */ 33,32,32,G_BOX, TOUCHEXIT, NORMAL, 0x011111L,17, 5, 3,7, /* 31 SLIDBOX (adjust y later) */ 31,-1,-1,G_BOX, TOUCHEXIT, NORMAL, 0x011100L, 0, 0, 3,1, /* 32 MVSLIDE */ 34,-1,-1,G_BOXCHAR, TOUCHEXIT, NORMAL, 0x02011100L,17,12, 3,1, /* 33 DARROW (adjust y and h later) */ 0,-1,-1,G_TEXT, LASTOB, NORMAL, (unsigned long)&rs_tedinfo[6], 3, 3,16,1 /* 34 TOPTEXT */ }; /* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | +-- ob_height height of obj (now chars, but | | | | | | | | | +---- ob_width width of obj (must cnvt to pixels | | | | | | | | +------- ob_y y coord relative to parent | | | | | | | +---------- ob_x x coord relative to parent | | | | | | +--------------------- ob_spec obj determines meaning (p11-55,60) | | | | | +------------------------------ ob_state current state of obj (p.11-61 MM) | | | | +----------------------------------------------------------- ob_flags attributes for obj (p.11-60 MM) | | | +----------------------------------------------------------------------- ob_type object type (p. 11-59 MM) | | +---------------------------------------------------------------------------- ob_tail ptr to last child of obj or -1 | +------------------------------------------------------------------------------ ob_head ptr to first child of obj or -1 +--------------------------------------------------------------------------------- ob_next ptr to next sibling or -1 */ PRIVATE int xdial,ydial,wdial,hdial; /* co-ord for dialog box */ PRIVATE int firstcall = TRUE; /* for first-run initialization */ /************************************************************************* * * Function fsel () * This is what we're here for !!! * Can't say much more 'cuz MM editor is almost full of characters. * * The parameters are as follows: * * stat an integer returned by routine; 0=canc 1=ok * title a string of up to 34 characters which will * be displayed as the title or instructions line * path a string representing the current path. * This must both start and end with a '\' and * may include any number of subdirectories * within it. The selector will return the * user's path selection in this variable too * so it should be a real variable of reasonable * length (don't make it up as text in the * parameter list itself!). * driv An integer indicating which drive to use. * code is as follows; * -1 use current default drive * 0 A: * 1 B: * ... * 5 F: * The selector will return the user's drive * selection in this variable too, so you should * pass the address instead of the value. * sextn An integer which indicates which of the five * extension boxes should be used when matching * filenames. This is bit-mapped such that: * 0x0001 selects extn0 * 0x0002 selects extn1 * 0x0004 selects extn2 * 0x0008 selects extn3 * 0x0010 selects extn4 * More than one may be selected. As above, the * selector returns the user's suggestions, so * this should be passed as an address too. * extn0 ... * extn4 There are 5 extension text variables. These * should all be 3 characters long (plus the * terminator of course) and should not include * the '.' (dot) which normally preceeds an * extension. The first three will not be * changed by the selector and so may be defined * as constants in the calling line if desired. * The last two will be modified by the selector * and thus must be defined as real variables. * In all cases, the string must have all 3 * characters defined (use trailing blanks or * underscores for short extensions). A '*' * will match anything; a '?' in any position * will match any character in that position. * fullname This is where the selector returns the user's * selected name and path. The string should be * long enough to hold the largest anticipated * string. The returned string will include * the drive specifier (i.e. A:), the full path * specified, and the file name itself. */ int fsel(const char *title, /* I display title for box */ char *path, /* IO initial path spec \ ... \ no drive; returns selected path */ int *driv, /* IO selects drive -1=default 0=A: .. 5=F: */ int *sextn, /* IO bitmap selected extn boxes : * 0x0001 = extn0 0x0002 = extn1 0x0004 = extn2 * 0x0008 = extn3 0x0010 = extn4 */ char *extn0, char *extn1, /* I extension text not including "." for each of 1st 3 extn boxes */ char *extn2, /* NOTE for all 5 boxes this should be 3 chars long, even if spaces */ char *extn3, char *extn4, /* IO extension text for last 2 extn boxes (editable) */ char *fullname) /* O returns complete path and file */ { struct finfo files[MAXFILES]; /* holds name, extn, dir for all files */ char newname[12], /* holds user-typed name */ fnam[13], /* will build return filename here */ c, drivs[3], /* current dir as string i.e. "B:" */ dispath[17]; /* displayable pathname (trunc to 16 chars max) */ int i,fp,ret,x,y,w,h; int action, /* flag */ button, /* button code from dialog box */ slidpsn, /* slider position 0-1000 */ goodfiles[MAXFILES], /* has indices into 'files[]' of files matching extn specifications */ numfiles, /* total number of files in 'files[]' */ numgood, /* number of files noted in 'goodfiles[]' */ curfirst, /* index into 'goodfiles[]' of first displayable file */ hchar, /* height of character in pixels */ my, /* mouse position y coordinate */ doubleclick, /* TRUE if double-clicked on item, else FALSE */ editfield; /* index of field to edit */ int t; /* holds drivemap */ /* * On the very first call to this subroutine we must do some * setup stuff... Primarily adjustments to the resource table * to adjust for screen resolution, and to adjust element locations * which do not live on even character boundaries. */ if (firstcall) { firstcall = FALSE; for(i=0; i<=HIGH(rs_object); i++) rsrc_obfix(rs_object,i); /* chg coord from char to pixel */ /* * also adjust size of SLIDBOX and xxARROWs into half-char sizes * because 1 char tall is too short to allow boxchar to display the arrows, * but 2 chars tall looks silly. */ i=graf_handle(&ret,&hchar,&ret,&ret); rs_object[UARROW].ob_height += hchar/2; rs_object[DARROW].ob_y += hchar/2; rs_object[DARROW].ob_height += hchar/2; rs_object[SLIDBOX].ob_y += hchar/2; /* * and similarly, adjust position of filenames in menu box * so that 9 fit nicely into a box that tightly fits 10 */ for (i=0; i (ydial+rs_object[SLIDBOX].ob_y+rs_object[MVSLIDE].ob_y)) FS_shift_curfirst(WINDSIZE,numgood,&curfirst); else FS_shift_curfirst(-WINDSIZE,numgood,&curfirst); FS_calc_slid_box(numgood,curfirst,TRUE); FS_dir_dis(files,goodfiles,numgood,curfirst); FS_setname(-1,newname); break; case UARROW: FS_shift_curfirst(-1,numgood,&curfirst); FS_calc_slid_box(numgood,curfirst,TRUE); FS_dir_dis(files,goodfiles,numgood,curfirst); FS_setname(-1,newname); break; case DARROW: FS_shift_curfirst(1,numgood,&curfirst); FS_calc_slid_box(numgood,curfirst,TRUE); FS_dir_dis(files,goodfiles,numgood,curfirst); FS_setname(-1,newname); break; /* * to get to EXTN3 then EXTN3 must have been TOUCHEXIT * which means that SLEXTN3 must have been SELECTED. * When we touched on the EXTN3 field we signify that we * want to edit it -- therefore we unSELECT the box so * that we can force a directory read when it next gets selected. */ case EXTN3: rs_object[EXTN3].ob_flags = EDITABLE; objc_change(&rs_object,SLEXTN3,0,xdial,ydial,wdial,hdial,NORMAL,1); *sextn &= ~0x0008; editfield = EXTN3; break; /* similar logic here... */ case EXTN4: rs_object[EXTN4].ob_flags = EDITABLE; objc_change(&rs_object,SLEXTN4,0,xdial,ydial,wdial,hdial,NORMAL,1); *sextn &= ~0x0010; editfield = EXTN4; break; } /* end of switch(button) */ } /* end of while(action) */ form_dial (2,x,y,w,h,xdial,ydial,wdial,hdial); /* shrink dialog box */ form_dial (3,x,y,w,h,xdial,ydial,wdial,hdial); /* release its room */ for (i=0; i<8; i++) { /* build formatted filename from newname */ if ((c=newname[i]) == ' ') break ; /* (scan name part until ends at space */ if ( c == '_' ) break; /* (also stops at _ in case no name was ever selected! */ fnam[i] = c; fnam[i+1] = '\0'; } if((newname[8] != ' ') AND (newname[8] != '_')) { /* (if there is an extension) */ fnam[i++] = '.'; fnam[i] = '\0'; strcat(&fnam[i],&newname[8]); } strcpy(fullname,drivs); /* finally, build a returnable name with full path info too */ strcat(fullname,path); strcat(fullname,fnam); if (button == CANCBUT) return (0); /* then return */ return(1); } /* fsel() */ /************************************************************ * function FS_shift_curfirst() is called when the slider * is moved by an arrow key or a pageup/pagedn request. * it returns a new value for curfirst (index into goodfiles) */ PRIVATE void FS_shift_curfirst(int inc, /* typically -1,1 (arrow), -9,+9 pagedn,pageup */ int numgood, /* total number of good files */ int *curfirst) /* returns new value for curfirst */ { *curfirst += inc; /* change it as requested */ /* then fix it if necessary */ if (*curfirst > (numgood-WINDSIZE)) *curfirst = numgood-WINDSIZE; if (*curfirst < 0) *curfirst = 0; } /* FS_shift_curfirst() */ /********************************************************* * function FS_calc_curfirst() is called after * a boxslide operation to find new value for curfirst. */ PRIVATE void FS_calc_curfirst(int slidpsn, /* slider psn as returned from graf_slidbox 0-1000 */ int numgood, /* total number of good files */ int *curfirst) /* returned index into goodfiles */ { *curfirst = (numgood * (slidpsn/10)) / 100 ; /* funny scaling to avoid arith overflow */ if (*curfirst > (numgood - WINDSIZE)) *curfirst = numgood - WINDSIZE; } /* FS_calc_curfirst() */ /***************************************************** * function FS_calc_slid_box() is called to calculate * new dimensions for the moving box, and draw it if necessary. */ PRIVATE void FS_calc_slid_box(int numgood, /* number of good files */ int curfirst, /* index into goodfiles[] */ BOOL drawit) /* FALSE = don't draw, TRUE = please draw */ { if (numgood <= WINDSIZE) { /* then sliding box is full size */ rs_object[MVSLIDE].ob_y = 0; /* position at top (rel to parent) */ rs_object[MVSLIDE].ob_height = rs_object[SLIDBOX].ob_height; } else { rs_object[MVSLIDE].ob_height = (rs_object[SLIDBOX].ob_height * WINDSIZE) / numgood ; rs_object[MVSLIDE].ob_y = (rs_object[SLIDBOX].ob_height * curfirst) / numgood ; } if (drawit) objc_draw(&rs_object,SLIDBOX,2,xdial,ydial,wdial,hdial); } /* FS_calc_slid_box() */ /*************************************************************** * function FS_setname() sets a filename or blanks into the NEWNAME field * if i== -1 then blanks are set, otherwise file_ids[i] is set */ PRIVATE void FS_setname( int i, char *newname) { if (i == -1) strcpy(newname,"___________"); else { strncpy(newname,&file_ids[i][2],8); strncpy(&newname[8],&file_ids[i][11],3); } objc_draw(&rs_object,NEWNAME,1,xdial,ydial,wdial,hdial); } /* FS_setname() */ /*************************************** * function FS_dir_read() reads specified directory * and stores names in 'files' array. Also adjusts numfiles. * function returns 0 on error 1 on success */ PRIVATE int FS_dir_read(char *drivs, char *path, struct finfo files[], int *numfiles, char *dispath) { char fullname[14]; /* full name of file from dta */ int dotat,error,i,numdirs,exch; char fullpath[80]; /* full path spec with driv, pathlist, and *.* */ struct _dta *dtap; *numfiles = 0; /* no files found yet */ dtap = (struct _dta *)Fgetdta(); do { strcpy(fullpath, drivs); strcat(fullpath, path); strcat(fullpath, "*.*"); error = d_First(drivs, path, FA_DIR); if (error == -33) { i = form_alert(2,"[1][You have specified either|an empty disk or a nonexistant path...][CONTINUE|RETRY|BACKUP PATH]"); switch(i) { case 1: return(1); /* quit indicating success (?) */ case 2: break; /* just do it again */ case 3: FS_path_shorten(path,dispath); } } else if (error != 0) { char emsg[80]; sprintf( emsg, "[1][%s|%s][QUIT]", sys_errlist[-error], fullpath); form_alert(1,emsg); exit(1); /* quit */ } /* if */ } while (error == -33); while (error == 0) { strcpy(fullname,dtap->dta_name); if(fullname[0] == '.') { /* then a directory . or .. */ strcpy(files[*numfiles].name,fullname); strcpy(files[*numfiles].extn,""); } else { /* a real file */ dotat = FS_find_last_delim('.',fullname); if (dotat == -1) { strcpy(files[*numfiles].extn,""); strcpy(files[*numfiles].name,fullname); } else { strcpy(files[*numfiles].extn,&fullname[dotat+1]); strncpy(files[*numfiles].name,fullname,dotat); files[*numfiles].name[dotat] = '\0'; } } files[*numfiles].dirflag = (dtap->dta_attribute & FA_DIR) != 0; (*numfiles)++; /* count the discovered file */ if (*numfiles > MAXFILES-1) { /* is this possible??? */ *numfiles = MAXFILES-1; /* if so, just ignore later files */ return(1); /* kinda sloppy huh ??? */ } error = d_Next(); /* then look for another */ } /* while */ /* now find all directories and put at beginning of list */ numdirs = 0; for (i=0; i< *numfiles; i++) { if(files[i].dirflag) { FS_exchinfo(&files[numdirs],&files[i]); /* if dir, swap to beginning of list */ numdirs++; /* and count it */ } } /* now sort the directories */ if ((numdirs) > 1) { do { exch = FALSE; for(i=0; i 0) { FS_exchinfo(&files[i],&files[i+1]); } } } while (exch == TRUE); } /* and now sort real files */ if ((*numfiles-numdirs) > 1) { do { exch = FALSE; for(i=numdirs; i< *numfiles-1; i++) { /* for all files */ if(strcmp(files[i].name,files[i+1].name) > 0) { FS_exchinfo(&files[i],&files[i+1]); exch = TRUE; } } } while (exch == TRUE); } /* all done so return status */ if (error == -ENMFILES) return (1) ; /* success if error = "no more files" */ return(0); /* else a problem */ } /* FS_dir_read() */ /************************************************** * function FS_dir_select_good() scans files[] for files matching at least one of * specified extensions. Counts matches in numgood, stores index (into files[]) * in goodfiles[]. Also sets curfirst = 0 so later display will start at beginning. */ PRIVATE void FS_dir_select_good( int sextn, /* the mask specifying checkable extensions */ const char *extn0, /* the extensions to try matching */ const char *extn1, const char *extn2, char *extn3, char *extn4, struct finfo files[], int numfiles, int goodfiles[], int *numgood, int *curfirst) { int i; *curfirst = 0; *numgood = 0; for (i=0; i= numgood) break; /* in case not enough good files to fill window */ FS_strxcpy(&file_ids[i][2],files[goodfiles[j]].name); /* put in basic filename */ if (strlen(files[goodfiles[j]].extn) > 0) { /* if there is an extension... */ file_ids[i][10] = '.'; FS_strxcpy(&file_ids[i][11],files[goodfiles[j]].extn); } if (files[goodfiles[j]].dirflag) file_ids[i][0] = DIAMOND_THINGY; /* put in funny box if its a directory */ } /* and finally 'print' all to screen */ for (i=0; i< WINDSIZE; i++) rs_object[FNAM1+i].ob_state = NORMAL; /* unselect all filenames */ objc_draw(&rs_object,FILEBOX,2,xdial,ydial,wdial,hdial); /* blank the FILEBOX then write in all filenames */ FS_calc_slid_box(numgood,curfirst,1); /* redraw sliding box too */ objc_draw(&rs_object,TOPBAR, 0,xdial,ydial,wdial,hdial); /* redraw TOPBAR to erase old path name */ objc_draw(&rs_object,TOPTEXT,0,xdial,ydial,wdial,hdial); /* then redraw TOPTEXT so that new path is shown */ } /******************************************************* * function FS_path_lengthen() is called to add a newly * selected name to the current pathlist. It is assumed that * the newly selected name is a directory... */ PRIVATE void FS_path_lengthen( char *path, /* the current path name (ends with '\') */ int index, /* index into FS_files[] of name to add */ struct finfo files[], char * dispath) /* the truncated displayable version of same */ { strcat(path,files[index].name); /* add the name itself */ if (strlen(files[index].extn) > 0) { /* (if there is an extension */ strcat(path,"."); /* then append it */ strcat(path,files[index].extn); } strcat(path,"\\"); /* and put on trailing backslash */ FS_pathtrunc(dispath,path); /* make displayable version */ } /* FS_path_lengthen() */ /* * function FS_path_shorten() shortens the current path. * It is called after click on ".." * Note that the path must always start and end with a '\' * character (will always have a length of at least 1). */ PRIVATE void FS_path_shorten( char *path, char *dispath) { int len,i; len=strlen(path); if (len == 1) return; /* already minimum path */ i=len-2; /* points at char before trailing slash */ while(path[i] != '\\') i-- ; /* keep looking for a slash */ path[i+1] = '\0' ; /* and put a terminator after it */ FS_pathtrunc(dispath,path); /* make displayable version */ } /* * function pathtrunc() truncates real pathname into shorter displayable version */ PRIVATE void FS_pathtrunc( char *dpath, /* the output (destination) string */ const char *spath) /* the (maybe too long) source str */ { int slen,i,is,id; if((slen=strlen(spath)) <= 16) strcpy(dpath,spath); /* the trivial case */ else { is = slen - 1 ; /* index of last char in string */ id = 15 ; /* last position in destination string */ for(i=0; i<14; i++) /* copy 14 chars into 16 char field */ dpath[id--] = spath[is--]; dpath[0] = '<'; /* and put little flags at beginning */ dpath[1] = '<'; } } /* * function FS_wildmatch() checks a specified extension * against a mask value for match, and returns TRUE if matched, else FALSE. * Cases causing match are as follows: * exact match * mask value is "*" * match on all existing characters, with any '?' in mask matching anything * Note that the mask value may have trailing spaces (" ") or underbars ("_") as * a result of the object template process. These are considered junk and are * removed from the comparison process. */ PRIVATE BOOL FS_wildmatch( const char *mask, const char *candidate) { int masklen,i; if(mask[0]=='*') return(TRUE); /* a '*' in mask matches anything */ masklen = strlen(mask); /* will elim trailing spaces and underbars */ for(i=masklen-1; i>0; i--) /* check all but first char to see if it is ignorable */ if((mask[i]==' ') OR (mask[i]=='_')) masklen=i; /* adjust length word to effect ignorance */ if(strlen(candidate) > masklen) return(FALSE); /* candidate .OLD should not match mask .O */ for(i=0; i