home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
utility
/
disk
/
undelete
/
fsel.c
next >
Wrap
C/C++ Source or Header
|
1993-02-14
|
44KB
|
916 lines
/****************************************************************
*
* 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 <aesbind.h>
#include <gemfast.h>
#include <osbind.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#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<WINDSIZE; i++) {
rs_object[FNAM1+i].ob_y += hchar/2;
} /* for */
} /* if (firstcall) ... */
strcpy(newname,"___________");
rs_tedinfo[0].te_ptext = newname;
rs_tedinfo[1].te_ptext = extn0 ;
rs_tedinfo[2].te_ptext = extn1 ;
rs_tedinfo[3].te_ptext = extn2 ;
rs_tedinfo[4].te_ptext = extn3 ;
rs_tedinfo[5].te_ptext = extn4 ;
rs_tedinfo[6].te_ptext = dispath ;
for (i=0; i<=HIGH(rs_tedinfo); i++) {
rs_tedinfo[i].te_txtlen = strlen(rs_tedinfo[i].te_ptext) + 1 ;
}
rs_object[1].ob_spec = (unsigned long)title;
FS_pathtrunc(dispath,path);
for (i=0; i<WINDSIZE; i++) strcpy(&file_ids[i][0]," ");
editfield = NEWNAME;
/*
* If user passed blanks for editable extensions, this is good
* but it will look funny -- put in initial underscores instead,
* also if he just passed unitialized (empty) string do it too.
* We must assume that string will be long enough...
*/
if((extn3[0] == ' ') OR (strlen(extn3) == 0)) strcpy(extn3,"___");
if((extn4[0] == ' ') OR (strlen(extn4) == 0)) strcpy(extn4,"___");
if (*sextn & 0x0001) rs_object[SLEXTN0].ob_state |= SELECTED;
if (*sextn & 0x0002) rs_object[SLEXTN1].ob_state |= SELECTED;
if (*sextn & 0x0004) rs_object[SLEXTN2].ob_state |= SELECTED;
if (*sextn & 0x0008) rs_object[SLEXTN3].ob_state |= SELECTED;
if (*sextn & 0x0010) rs_object[SLEXTN4].ob_state |= SELECTED;
if (*driv == -1) *driv = Dgetdrv(); /* get cur logged drive if needed */
rs_object[(*driv)+DRVA].ob_state |= SELECTED;
drivs[0] = (*driv) +'A' ; drivs[1] = ':' ; drivs[2] = '\0' ;
t = Drvmap();
if ((t & 0x01) == 0) rs_object[DRVA].ob_state = DISABLED;
if ((t & 0x02) == 0) rs_object[DRVB].ob_state = DISABLED;
if ((t & 0x04) == 0) rs_object[DRVC].ob_state = DISABLED;
if ((t & 0x08) == 0) rs_object[DRVD].ob_state = DISABLED;
if ((t & 0x10) == 0) rs_object[DRVE].ob_state = DISABLED;
if ((t & 0x20) == 0) rs_object[DRVF].ob_state = DISABLED;
form_center (&rs_object,&xdial,&ydial,&wdial,&hdial);
x=y=w=h=0;
form_dial (0,x,y,w,h,xdial,ydial,wdial,hdial); /* reserve room */
form_dial (1,x,y,w,h,xdial,ydial,wdial,hdial); /* grow box */
objc_draw (&rs_object,0,2,xdial,ydial,wdial,hdial); /* draw the dialog box */
FS_dir_read(drivs, path, files, &numfiles, dispath);
FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
files, numfiles, goodfiles, &numgood, &curfirst);
FS_calc_slid_box(numgood,curfirst,FALSE); /* calculate initial slider position */
FS_dir_dis(files,goodfiles,numgood,curfirst);
action = CONTINUE; /* look for new button press */
while (action == CONTINUE) { /* loop while operator plays */
if (rs_object[SLEXTN3].ob_state & SELECTED) /* setup status of (SL)EXTN3 click-ability */
rs_object[EXTN3].ob_flags = TOUCHEXIT;
else
rs_object[EXTN3].ob_flags = EDITABLE;
if (rs_object[SLEXTN4].ob_state & SELECTED) /* setup status of (SL)EXTN4 click-ability */
rs_object[EXTN4].ob_flags = TOUCHEXIT;
else
rs_object[EXTN4].ob_flags = EDITABLE;
button = form_do(&rs_object,editfield); /* manage user's actions until a button press */
if (button & 0x8000) { /* if double-click ... */
doubleclick = TRUE;
button &= ~0x8000; /* (remove double-click bit from botton code) */
}
else
doubleclick = FALSE;
switch (button) { /* now prepare to act upon user's request */
case CANCBUT: action = QUIT; rs_object[CANCBUT].ob_state &= ~SELECTED; break;
case OKBUT: action = QUIT; rs_object[OKBUT].ob_state &= ~SELECTED; break;
case DRVA:
case DRVB:
case DRVC:
case DRVD:
case DRVE:
case DRVF: *driv = button - DRVA;
drivs[0] = (*driv) + 'A'; drivs[1] = ':'; drivs[2] = '\0';
strcpy(path,"\\");
FS_pathtrunc(dispath,path);
FS_dir_read(drivs,path,files,&numfiles,dispath);
FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
files,numfiles,goodfiles,&numgood,&curfirst);
FS_dir_dis(files,goodfiles,numgood,curfirst);
FS_setname(-1,newname);
break;
case SLEXTN0:
case SLEXTN1:
case SLEXTN2:
case SLEXTN3:
case SLEXTN4: i = 0x01 << (button - SLEXTN0);
*sextn ^= i ;
FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
files,numfiles,goodfiles,&numgood,&curfirst);
FS_dir_dis(files,goodfiles,numgood,curfirst);
FS_setname(-1,newname);
break;
case FNAM1:
case FNAM2:
case FNAM3:
case FNAM4:
case FNAM5:
case FNAM6:
case FNAM7:
case FNAM8:
case FNAM9: i = button - FNAM1;
fp= goodfiles[curfirst+i] ; /* (fp points into files[]) */
if (files[fp].dirflag) { /* if a directory of any flavor */
if (strcmp(files[fp].name,".") == 0) /* current directory */
/* do nothing special */ ;
else if (strcmp(files[fp].name,"..") == 0) { /* parent directory */
FS_path_shorten(path,dispath);
FS_dir_read(drivs,path,files,&numfiles,dispath);
FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
files,numfiles,goodfiles,&numgood,&curfirst);
}
else { /* another directory */
FS_path_lengthen(path,fp,files,dispath);
FS_dir_read(drivs,path,files,&numfiles,dispath);
FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
files,numfiles,goodfiles,&numgood,&curfirst);
}
FS_dir_dis(files,goodfiles,numgood,curfirst); /* then always display the selected directory */
FS_setname(-1,newname);
} /* end of 'if a directory' stuff */
else { /* here it must be just a file */
FS_setname(i,newname);
if (doubleclick) { /* a doubleclick causes default OKBUT too */
action = QUIT;
button = OKBUT;
}
}
break;
case MVSLIDE: if (rs_object[SLIDBOX].ob_height==rs_object[MVSLIDE].ob_height) break; /* do nothing if full size */
slidpsn = graf_slidebox(&rs_object,SLIDBOX,MVSLIDE,1);
FS_calc_curfirst(slidpsn,numgood,&curfirst);
FS_calc_slid_box(numgood,curfirst,TRUE);
FS_dir_dis(files,goodfiles,numgood,curfirst);
FS_setname(-1,newname);
break;
case SLIDBOX: graf_mkstate(&ret,&my,&ret,&ret);
if (my > (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<numdirs-1; i++) { /* for all directories */
if(strcmp(files[i].name,files[i+1].name) > 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<numfiles; i++) { /* always match directories */
if(files[i].dirflag) {
goodfiles[(*numgood)++] = i;
continue;
}
if((sextn & 0x01) AND FS_wildmatch(extn0,files[i].extn)) {
goodfiles[(*numgood)++] = i;
continue;
}
if((sextn & 0x02) AND FS_wildmatch(extn1,files[i].extn)) {
goodfiles[(*numgood)++] = i;
continue;
}
if((sextn & 0x04) AND FS_wildmatch(extn2,files[i].extn)) {
goodfiles[(*numgood)++] = i;
continue;
}
if((sextn & 0x08) AND FS_wildmatch(extn3,files[i].extn)) {
goodfiles[(*numgood)++] = i;
continue;
}
if((sextn & 0x10) AND FS_wildmatch(extn4,files[i].extn)) {
goodfiles[(*numgood)++] = i;
continue;
}
}
}
/*
* function FS_dir_dis() displays current directory in window. It displays
* at max WINDSIZE names, starting at 'curfirst' in files[].
*/
PRIVATE void
FS_dir_dis( struct finfo files[],
int goodfiles[],
int numgood,
int curfirst)
{
int i,j;
/* first, clear out display strings */
for (i=0; i<WINDSIZE; i++) {
for(j=0; j<16; j++)
file_ids[i][j] = ' ';
file_ids[i][16] = '\0';
}
/* now build at most WINDSIZE filenames */
for (i=0,j=curfirst; i<WINDSIZE; i++,j++) {
if (j >= 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<masklen; i++) { /* now look at all valid chars to check for match */
if(mask[i] == '?') continue; /* a '?' in mask matches anything in that position */
if(toupper(mask[i]) != toupper(candidate[i])) return(FALSE); /* oops -- no match */
}
return(TRUE); /* must have matched ! */
}
/*
* function FS_exchinfo() exchanges contents of two 'finfo' style structures
*/
PRIVATE void FS_exchinfo( struct finfo *x, struct finfo *y)
{
struct finfo t;
t = *x; /* caution -- */
*x = *y; /* this all-in-one assignment is an extension that works in MM C */
*y = t; /* other C's take care ... */
}
PRIVATE int FS_find_last_delim(char delim, char *string)
{
int i,spot;
spot = -1;
for (i=0; i<strlen(string); i++)
if (string[i] == delim) spot = i;
return(spot);
}
/*
* function FS_strxcpy() is just like strcpy except it does not copy
* the terminating \0
*/
PRIVATE void FS_strxcpy(char *dest, const char *sour)
{
char c;
while ((c=*sour++) != '\0') *dest++ = c ;
}
/************************* end of fsel.c ************************/