home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 180.lha / Files_v1.2 / src / filereq.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  23KB  |  979 lines

  1.  
  2. /*
  3.  *  STDFILE -- Standard File Requestor. Version 2.0a 15 June 1987
  4.  *
  5.  *  AUTHOR -- Peter da Silva      US (713) 497-4372
  6.  *
  7.  *  Reorganized by Matthew Dillon for use with * and ?.  Added:
  8.  *    -device name in File string gadget transfered to directory
  9.  *     gadget without closing the window.
  10.  *    -bug when requesting volume ""... current directory lock would
  11.  *     get unlocked!
  12.  *    -additional intuitive features added
  13.  *    -coding reorganized
  14.  *
  15.  *    Copyright (c) 1987 Peter da Silva, all rights reserved.
  16.  *    Changes (c)Copyright 1987 Matthew Dillon, all rights reserved.
  17.  *
  18.  *    This module may be freely used in any product, commercial or
  19.  *    otherwise, provided credit is given for this module and
  20.  *    and provided this notice remains intact in the source. The
  21.  *    intent of this module is to provide a standard file requestor
  22.  *    such as is available on the Macintosh, in GEM on the IBM-PC
  23.  *    and Atari ST, and in the Microsoft Windows software on the
  24.  *    IBM-PC. The advantage this module has over other requestors
  25.  *    is that it minimises disk accesses: an important consideration
  26.  *    given the structure of AmigaDos directories. If you need to
  27.  *    modify it for your needs, by all means go ahead... but please
  28.  *    conform to the intent of this program as stated above. If you
  29.  *    have suggestions for improvements, by all means call me at
  30.  *    the number listed above.
  31.  *
  32.  * Enhancements in the current version:
  33.  *
  34.  *    Gadgets now boxed. Display generally cleaned up.
  35.  *
  36.  *    True "dictionary order" for searches.
  37.  *
  38.  *    Default pattern can now be specified. Default file name now
  39.  *    specified in a single argument.
  40.  *
  41.  *    Directories always match.
  42.  *
  43.  *    Null pattern converted to "#?" universal wildcard.
  44.  *
  45.  *    If you attempt to build a file name longer than 128 characters the
  46.  *    screen will flash and the operation will be aborted.
  47.  *
  48.  *    "Volumes" gadget, using the device list code in "mounted". This
  49.  *    gadget brings up a list of all currently mounted volumes for
  50.  *    selection. Volumes leaves the directory specification intact, so
  51.  *    you can quickly return to where you left off.
  52.  *
  53.  *    With these enhancements it is now possible to select any file on
  54.  *    any device without touching the keyboard. This is now release 2.0,
  55.  *    as it is significantly better than 1.0.
  56.  *
  57.  * Acknowledgements:
  58.  *
  59.  *    Thanks to Jeff Lydiatt for the pattern matching code in PatMatch.c
  60.  *    Thanks to Jay Miner, =RJ= and the whole Amiga team for the Amiga
  61.  *    itself.
  62.  *
  63.  * Environment:
  64.  *
  65.  *    IntuitionBase and GfxBase must be open. dos.library must be open
  66.  *    under the name "DosLibrary". Link with PatMatch.o and VolList.o.
  67.  *
  68.  * Usage:
  69.  *
  70.  *    #define MAXFILENAME 128
  71.  *
  72.  *    int stdfile(title, default_file, default_pat, name);
  73.  *    char *title;
  74.  *    char *default_file;
  75.  *    char *default_pattern;
  76.  *    char name[MAXFILENAME];
  77.  *
  78.  *    +-----------------------------------+
  79.  *    |o| Title ------------------- |  |  | title parameter, or "File Name"
  80.  *    |-----------------------------------|
  81.  *    | Directory: [              ] | Directory parameter, or current.
  82.  *    | File name: [              ] | Default parameter, or empty.
  83.  *    | Pattern:   [              ] | Initially empty, if the user
  84.  *    | +-------------------------------+ | enters anything here it will
  85.  *    | | [Filename]               |  | | be used to select files. The
  86.  *    | | [Filename]               |  | | file display will also be empty
  87.  *    | | [Filename]               |@@| | to start with to avoid excess
  88.  *    | | [Filename]               |@@| | disk I/O. If the user selects
  89.  *    | |                   |@@| | here the directory will be
  90.  *    | |                   |@@| | scanned looking for files
  91.  *    | |                   |  | | matching the specified pattern,
  92.  *    | |                   |  | | or "*" if no pattern is given.
  93.  *    | |                   |  | |
  94.  *    | +-------------------------------+ | ACCEPT returns 1. CANCEL
  95.  *    | [ACCEPT]    [VOLUMES]    [CANCEL] | or the close gadget return 0.
  96.  *    +-----------------------------------+ VOLUMES displays volume names.
  97.  *
  98.  *    The number of filenames displayed is specified at compile time in the
  99.  *    constant MAXFILES. The maximum size of a filename is specified in the
  100.  *    constant MAXNAME. The parameter "Default file" will be broken into
  101.  *    directory and file parts.
  102.  */
  103.  
  104. char *Copyright =
  105. "stdfile V2.0a. Copyright (c) 1987 Peter da Silva. All rights reserved.";
  106.  
  107. #include <intuition/intuitionbase.h>
  108. #include <intuition/intuition.h>
  109. #include <libraries/dos.h>
  110. #include <libraries/dosextens.h>
  111. #include <exec/memory.h>
  112.  
  113. typedef unsigned char  ubyte;
  114. typedef unsigned short uword;
  115. typedef unsigned long  ulong;
  116. typedef struct FileInfoBlock FIB;
  117. typedef struct DeviceList    DEVLIST;
  118. typedef struct DosLibrary    DOSLIB;
  119. typedef struct DosInfo         DOSINFO;
  120. typedef struct RootNode      ROOTNODE;
  121. typedef struct IntuiMessage  IMESS;
  122.  
  123. extern void CalcPropGadget();
  124. extern void ProcessFileName();
  125.  
  126. extern void *malloc();
  127. extern void *GetMsg();
  128. extern struct Window *OpenWindow();
  129.  
  130. #define MAXFILES 8
  131. #define MAXNAME 32
  132. #define MAXFULL (MAXNAME*4)
  133.  
  134. /* SIZING PARAMS */
  135.  
  136. #define Z        NULL
  137. #define INDENT        6
  138. #define LEFTMAR     (INDENT-1)
  139. #define BORDER        3
  140. #define CHSIZ        8
  141. #define HT        CHSIZ
  142. #define BASELINE    6
  143.  
  144. /* GADGET BORDERS */
  145.  
  146. #define IN1        LEFTMAR+10*CHSIZ
  147. #define IN3        LEFTMAR+3
  148. #define IN4        -(INDENT+6*CHSIZ+1)
  149. #define IN5        -(INDENT+CHSIZ*2)
  150. #define IN6        ((WINWD-WD6)/2)
  151. #define WD1        -(INDENT+IN1)
  152. #define WD3        (6*CHSIZ)
  153. #define WD4        (6*CHSIZ)
  154. #define WD5        (CHSIZ*2+2)
  155. #define WD6        (7*CHSIZ)
  156. #define TP1        (CHSIZ+BORDER)
  157. #define TP2        (TP1+HT+1)
  158. #define TP3        (TP2+HT+1)
  159. #define TP4        -(BORDER+HT4-1)
  160. #define TP5        (TP3+HT+BORDER)
  161. #define HT4        (HT+1)
  162. #define HT5        CHSIZ*MAXFILES+INDENT
  163.  
  164. #define WINHT        (TP5 + HT5 + (-TP4) + BORDER)
  165. #define WINWD        (INDENT*4 + (MAXNAME+2)*CHSIZ)
  166. #define WININ        (640-WINWD)/2
  167. #define WINTP        (200-WINHT)/2
  168.  
  169. #define HOMEX        (INDENT+LEFTMAR)
  170. #define HOMEY        (TP5+BORDER)
  171. #define LASTX        (HOMEX+MAXNAME*CHSIZ)
  172. #define LASTY        (HOMEY+MAXFILES*CHSIZ)
  173.  
  174. #define BTP        TP5
  175. #define BIN        LEFTMAR
  176. #define BWD        (WINWD-INDENT-BIN)
  177. #define BHT        (WINHT-BTP-(-TP4+BORDER+1))
  178.  
  179. #define SF        GADGHCOMP|GRELWIDTH
  180. #define SEL        SELECTED
  181. #define BF1        GADGHCOMP|GRELBOTTOM
  182. #define BF2        GADGHCOMP|GRELBOTTOM|GRELRIGHT
  183. #define PF        GRELRIGHT
  184.  
  185. #define SA        RELVERIFY
  186. #define CEN        STRINGCENTER
  187. #define BA        RELVERIFY
  188. #define PA        RELVERIFY
  189.  
  190. #define SI(n)      (APTR)&STD_String[n]
  191. #define G(n)       &STD_Gadget[n]
  192. #define IMAG       (APTR)&STD_Image
  193. #define PROP       (APTR)&STD_Prop
  194.  
  195. #define SG       STRGADGET
  196. #define BG       BOOLGADGET
  197. #define PG       PROPGADGET
  198.  
  199. #define FP       AUTOBACKPEN
  200. #define BP       AUTOFRONTPEN
  201.  
  202. #define OKTEXT       &STD_OK
  203. #define NOTEXT       &STD_CANCEL
  204. #define VLTEXT       &STD_VOLUME
  205.  
  206. static int DoneFlag;
  207.  
  208. #define DirName    SBuffer[0]
  209. #define FileName   SBuffer[1]
  210. #define PatName    SBuffer[2]
  211. #define STRINGS    3
  212.  
  213. static UBYTE SBuffer[STRINGS][MAXFULL];
  214. static UBYTE Undo[MAXFULL];
  215.  
  216. static struct StringInfo STD_String[STRINGS] = {
  217.     {SBuffer[0],Undo,0,MAXFULL,0},
  218.     {SBuffer[1],Undo,0,MAXFULL,0},
  219.     {SBuffer[2],Undo,0,MAXFULL,0}
  220. };
  221.  
  222. static struct PropInfo STD_Prop = { AUTOKNOB|FREEVERT, 0, 0, 0, 0 };
  223.  
  224. static struct IntuiText STD_OK =
  225.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"ACCEPT", Z };
  226. static struct IntuiText STD_CANCEL =
  227.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"CANCEL", Z };
  228. static struct IntuiText STD_VOLUME =
  229.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"VOLUMES", Z };
  230.  
  231. #define BUTTONS 3
  232. #define BUTVEC 8
  233.  
  234. static SHORT butvecs[BUTTONS][BUTVEC*2] = {
  235.     { -2, HT4, -2, -1, WD3+1,-1, WD3+1,HT4, -3, HT4, -3,-1, WD3+2,-1, WD3+2, HT4 },
  236.     { -2, HT4, -2, -1, WD4+1,-1, WD4+1,HT4, -3, HT4, -3,-1, WD4+2,-1, WD4+2, HT4 },
  237.     { -2, HT4, -2, -1, WD6+1,-1, WD6+1,HT4, -3, HT4, -3,-1, WD6+2,-1, WD6+2, HT4 }
  238. };
  239.  
  240. static struct Border ButBorder[BUTTONS] = {
  241.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[0], NULL},
  242.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[1], NULL},
  243.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[2], NULL}
  244. };
  245.  
  246. #define BB(n) (APTR)&ButBorder[n]
  247.  
  248. static struct Image STD_Image;
  249.  
  250. #define DIRID 0
  251. #define FILID 1
  252. #define PATID 2
  253. #define YESID 3
  254. #define CANID 4
  255. #define VOLID 5
  256. #define BARID 6
  257. #define GADGETS 7
  258.  
  259. static struct Gadget STD_Gadget[GADGETS] = {
  260.     /*NEXT, LFT, TP,WDTH, H, FLAG,  ACT, TYP, REND, Z, TXT, Z, SPEC, ID, Z */
  261.     { G(1), IN1,TP1, WD1,HT, SF,     SA,  SG,    Z, Z,   Z, Z, SI(0), 0, 0 },
  262.     { G(2), IN1,TP2, WD1,HT, SF|SEL, SA,  SG,    Z, Z,   Z, Z, SI(1), 1, 0 },
  263.     { G(3), IN1,TP3, WD1,HT, SF,     SA,  SG,    Z, Z,   Z, Z, SI(2), 2, 0 },
  264.     { G(4), IN3,TP4, WD3,HT4,BF1,    BA,  BG,BB(0), Z, OKTEXT, Z,  Z, 3, 0 },
  265.     { G(5), IN4,TP4, WD4,HT4,BF2,    BA,  BG,BB(1), Z, NOTEXT, Z,  Z, 4, 0 },
  266.     { G(6), IN6,TP4, WD6,HT4,BF1,    BA,  BG,BB(2), Z, VLTEXT, Z,  Z, 5, 0 },
  267.     { NULL, IN5,TP5, WD5,HT5,PF,     PA,  PG, IMAG, Z,     Z, Z,    PROP, 6, 0 }
  268. };
  269.  
  270. static struct NewWindow STD_NewWindow = {
  271.     WININ, WINTP, WINWD, WINHT, -1, -1,
  272.     REFRESHWINDOW|MOUSEBUTTONS|GADGETUP|CLOSEWINDOW,
  273.     WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SIMPLE_REFRESH|ACTIVATE,
  274.     G(0), NULL, (ubyte *)"File Name Requestor",
  275.     NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
  276. };
  277.  
  278. static struct Window *STD_Window;
  279.  
  280. #define NVEC 6
  281.  
  282. static SHORT Vectors[NVEC*2] = {
  283.     BIN+1, BTP,
  284.     BIN+1, BTP+BHT,
  285.     BIN+BWD, BTP+BHT,
  286.     BIN+BWD, BTP,
  287.     BIN, BTP,
  288.     BIN, BTP+BHT
  289. };
  290.  
  291. static struct Border STD_FileBox = {
  292.     0, 0, FP, BP, JAM1, NVEC, Vectors, NULL
  293. };
  294.  
  295. static struct IntuiText STD_Text[3] = {
  296.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Directory:", NULL },
  297.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"File Name:", NULL },
  298.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Pattern:", NULL }
  299. };
  300.  
  301. static
  302. OpenFileWindow()
  303. {
  304.     extern struct IntuitionBase *IntuitionBase;
  305.     int i;
  306.  
  307.     /* Rebuild gadget list */
  308.  
  309.     STD_NewWindow.FirstGadget = &STD_Gadget[0];
  310.     for(i = 0; i < GADGETS; i++)
  311.     STD_Gadget[i].NextGadget = (i==GADGETS-1)?(0):(&STD_Gadget[i+1]);
  312.     for(i = 0; i < STRINGS; i++) {
  313.     STD_String[i].BufferPos = strlen(SBuffer[i]);
  314.     STD_String[i].DispPos = 0;
  315.     }
  316.     STD_Prop.VertBody = 0xFFFF;
  317.     STD_Prop.VertPot = 0;
  318.  
  319.     if (!(STD_Window = OpenWindow(&STD_NewWindow)))
  320.     return(0);
  321.  
  322.     /* This optional line will activate a string gadget     */
  323.     if (IntuitionBase->LibNode.lib_Version > 32)
  324.     ActivateGadget(G(1),STD_Window,0L);
  325.     CalcPropGadget();
  326.     PaintFileWindow();
  327.     return (1);
  328. }
  329.  
  330. static
  331. CloseFileWindow()
  332. {
  333.     STD_NewWindow.LeftEdge = STD_Window->LeftEdge;
  334.     STD_NewWindow.TopEdge = STD_Window->TopEdge;
  335.     if (STD_Window)
  336.     CloseWindow(STD_Window);
  337. }
  338.  
  339. static int State;
  340.  
  341. #define INITIAL 0
  342. #define DIRECTORY 1
  343.  
  344. static
  345. PaintFileWindow()
  346. {
  347.     DrawBorder(STD_Window->RPort, &STD_FileBox, 0, 0);
  348.     PrintIText(STD_Window->RPort, &STD_Text[0], LEFTMAR, TP1);
  349.     PrintIText(STD_Window->RPort, &STD_Text[1], LEFTMAR, TP2);
  350.     PrintIText(STD_Window->RPort, &STD_Text[2], LEFTMAR, TP3);
  351.     if (State == DIRECTORY)
  352.     PrintFileNames();
  353. }
  354.  
  355. static int FirstFile;
  356. static int Selected;
  357. static int NumFiles;
  358.  
  359. static struct dirent {
  360.     struct dirent *nextfile;
  361.     SHORT filetype;
  362.     char *filename;
  363. } *NameList, **NameTable;
  364.  
  365. #define FILETYPE 0
  366. #define DIRTYPE 1
  367. #define VOLTYPE 2
  368.  
  369. static
  370. PrintFileNames()
  371. {
  372.     int i;
  373.  
  374.     for (i = 0; i < MAXFILES; ++i) {
  375.     SetBPen(STD_Window->RPort, BP);
  376.     SetAPen(STD_Window->RPort, BP);
  377.     RectFill(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ, LASTX, HOMEY+(i+1)*CHSIZ);
  378.     if (i+FirstFile < NumFiles)
  379.         PrintName(i+FirstFile, i+FirstFile == Selected);
  380.     }
  381. }
  382.  
  383. static
  384. PrintName(file, hilite)
  385. int file;
  386. int hilite;
  387. {
  388.     int i;
  389.  
  390.     i = file - FirstFile;
  391.  
  392.     Move(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ+BASELINE);
  393.     if (hilite == 0) {
  394.     SetBPen(STD_Window->RPort, BP);
  395.     if(NameTable[file]->filetype == FILETYPE)
  396.         SetAPen(STD_Window->RPort, FP);
  397.     else
  398.         SetAPen(STD_Window->RPort, 3);
  399.     } else {
  400.     SetAPen(STD_Window->RPort, BP);
  401.     if(NameTable[file]->filetype == FILETYPE)
  402.         SetBPen(STD_Window->RPort, FP);
  403.     else
  404.         SetBPen(STD_Window->RPort, 3);
  405.     }
  406.     Text(STD_Window->RPort, NameTable[file]->filename, strlen(NameTable[file]->filename));
  407. }
  408.  
  409. static
  410. void
  411. CalcPropGadget()
  412. {
  413.     int VertPot, VertBody;
  414.  
  415.     if (State == INITIAL)
  416.     return;
  417.     if (NumFiles <= MAXFILES) {
  418.     VertBody = 0xFFFF;
  419.     VertPot = 0;
  420.     FirstFile = 0;
  421.     } else {
  422.     VertBody = ((MAXFILES<<16)-1) / NumFiles;
  423.     VertPot = 0;
  424.     FirstFile = 0;
  425.     }
  426.     ModifyProp(&STD_Gadget[BARID], STD_Window, NULL,
  427.     STD_Prop.Flags, 0, VertPot, 0, VertBody
  428.     );
  429. }
  430.  
  431. static
  432. void
  433. CalcFilePosition()
  434. {
  435.     short old_pos;
  436.  
  437.     if (State == INITIAL)
  438.      return;
  439.     old_pos = FirstFile;
  440.     if (NumFiles<=MAXFILES) {
  441.     FirstFile = 0;
  442.     } else {
  443.     int VertPot = STD_Prop.VertPot;
  444.     FirstFile = ((VertPot+1)*(NumFiles-MAXFILES))>>16;
  445.     }
  446.     if (old_pos != FirstFile)
  447.     PrintFileNames();
  448. }
  449.  
  450. FreeList(list)
  451. struct dirent *list;
  452. {
  453.     struct dirent *ptr;
  454.  
  455.     while(list) {
  456.     ptr = list->nextfile;
  457.     if (list->filename)
  458.         free(list->filename);
  459.     free(list);
  460.     list = ptr;
  461.     }
  462. }
  463.  
  464. static
  465. ReadNewDir()
  466. {
  467.     struct dirent *NewList, **NewTable, *ptr;
  468.     int NewCount;
  469.     FIB *fib;
  470.     BPTR dirlock;
  471.  
  472.     if (State != DIRECTORY) {
  473.     NameTable = 0;
  474.     NameList = 0;
  475.     }
  476.     if (DirName[0]) {
  477.         dirlock = Lock(DirName, ACCESS_READ);
  478.     } else {
  479.     BPTR ram;
  480.     if (ram = Lock("RAM:", ACCESS_READ)) {
  481.         dirlock = CurrentDir(ram);
  482.         CurrentDir(dirlock);
  483.         dirlock = DupLock(dirlock); /*  added */
  484.         UnLock(ram);
  485.     }
  486.     }
  487.     if (!dirlock)
  488.     return(0);
  489.     if ((fib = (FIB *)malloc(sizeof(FIB))) == NULL) {
  490.     UnLock(dirlock);
  491.     return 0;
  492.     }
  493.     if (!Examine(dirlock, fib)) {
  494.     UnLock(dirlock);
  495.     free(fib);
  496.     return 0;
  497.     }
  498.     if (fib->fib_DirEntryType < 0) {
  499.     UnLock(dirlock);
  500.     free(fib);
  501.     return 0;
  502.     }
  503.     NewList = 0;
  504.     NewCount = 0;
  505.     while(ExNext(dirlock, fib)) {
  506.     NewCount += 1;
  507.     ptr = (struct dirent *)malloc(sizeof(struct dirent));
  508.     if (ptr == 0) {
  509.         FreeList(NewList);
  510.         UnLock(dirlock);
  511.         free(fib);
  512.         return(0);
  513.     }
  514.     ptr->nextfile = NewList;
  515.     ptr->filetype = (fib->fib_DirEntryType<0)?FILETYPE:DIRTYPE;
  516.     ptr->filename = malloc(strlen(fib->fib_FileName)+1);
  517.     if (ptr->filename == 0) {
  518.         FreeList(ptr);
  519.         UnLock(dirlock);
  520.         free(fib);
  521.         return(0);
  522.     }
  523.     strcpy(ptr->filename, fib->fib_FileName);
  524.     NewList = ptr;
  525.     }
  526.     free(fib);
  527.     if (DirName[0])
  528.     UnLock(dirlock);
  529.     NewTable = malloc(sizeof(struct dirent *) * NewCount);
  530.     if (NewTable==0) {
  531.     FreeList(NewList);
  532.     return(0);
  533.     }
  534.     FreeList(NameList);
  535.     NameList = NewList;
  536.     if (NameTable)
  537.     free(NameTable);
  538.     NameTable = NewTable;
  539.     if (PatName[0]==0)
  540.     SetPatName("*");
  541.     State = DIRECTORY;
  542.     Selected = -1;
  543.     ReCalcPattern();
  544. }
  545.  
  546.  
  547. static
  548. ReadVol()
  549. {
  550.     struct dirent *NewList, **NewTable, *ptr;
  551.     int NewCount;
  552.     char name[MAXNAME];
  553.  
  554.     if (State != DIRECTORY) {
  555.     NameTable = 0;
  556.     NameList = 0;
  557.     }
  558.     OpenVolList();
  559.     NewList = 0;
  560.     NewCount = 0;
  561.     while(ReadVolList(name)) {
  562.     if (strcmp(name, "RAM Disk:") == 0)
  563.         strcpy(name, "ram:");
  564.     NewCount += 1;
  565.     ptr = (struct dirent *)malloc(sizeof(struct dirent));
  566.     if (ptr==0) {
  567.         FreeList(NewList);
  568.         return(0);
  569.     }
  570.     ptr->nextfile = NewList;
  571.     ptr->filetype = VOLTYPE;
  572.     ptr->filename = malloc(strlen(name)+1);
  573.     if (ptr->filename == 0) {
  574.         FreeList(ptr);
  575.         return(0);
  576.     }
  577.     strcpy(ptr->filename, name);
  578.     NewList = ptr;
  579.     }
  580.     CloseVolList();
  581.     NewTable = malloc(sizeof(struct dirent *)*NewCount);
  582.     if (NewTable==0) {
  583.     FreeList(NewList);
  584.     return(0);
  585.     }
  586.     FreeList(NameList);
  587.     NameList = NewList;
  588.     if (NameTable)
  589.     free(NameTable);
  590.     NameTable = NewTable;
  591.  
  592.     if (PatName[0]==0)
  593.     SetPatName("*");
  594.  
  595.     State = DIRECTORY;
  596.     Selected = -1;
  597.  
  598.     ReCalcPattern();
  599. }
  600.  
  601. /* this routine does a true dictionary search:
  602.  *
  603.  *        Devs < devs but Devs > devices
  604.  */
  605.  
  606. static
  607. table_compare(p1, p2)
  608. struct dirent **p1, **p2;
  609. {
  610.     char *s1, *s2;
  611.     char c1, c2;
  612.     char firstdiff;
  613.  
  614.     s1 = (*p1)->filename;
  615.     s2 = (*p2)->filename;
  616.     firstdiff = 0;
  617.  
  618.     while(*s1 && *s2) {
  619.     c1 = *s1++;
  620.     c2 = *s2++;
  621.     if (firstdiff==0)
  622.         firstdiff = c1 - c2;
  623.     if (c1 >= 'A' && c1 <= 'Z') c1 = c1+'@';
  624.     if (c2 >= 'A' && c2 <= 'Z') c2 = c2+'@';
  625.     if (c1 != c2)
  626.         return c1 - c2;
  627.     }
  628.     return firstdiff;
  629. }
  630.  
  631. static
  632. sort_table()
  633. {
  634.     qsort(NameTable, NumFiles, sizeof(struct dirent *), table_compare);
  635.     return 1;
  636. }
  637.  
  638. static
  639. ReCalcPattern()
  640. {
  641.     if (State != DIRECTORY) {
  642.     ReadNewDir();
  643.     } else {
  644.     struct dirent *ptr;
  645.  
  646.     if (!PatName[0])
  647.         SetPatName("*");
  648.     NumFiles = 0;
  649.     for (ptr = NameList; ptr; ptr=ptr->nextfile) {
  650.         /* Directories always match. Is this good? */
  651.         if (ptr->filetype == DIRTYPE || ptr->filetype == VOLTYPE || newwildcmp(PatName, ptr->filename)) {
  652.         NameTable[NumFiles] = ptr;
  653.         NumFiles++;
  654.         }
  655.     }
  656.     sort_table();
  657.     CalcPropGadget();
  658.     Selected = -1;
  659.     PrintFileNames();
  660.     }
  661. }
  662.  
  663. static
  664. SetGadgetText(id, text)
  665. int id;
  666. char *text;
  667. {
  668.     int position;
  669.  
  670.     position = RemoveGadget(STD_Window, G(id));
  671.     if (position != -1) {
  672.     strcpy(SBuffer[id], text);
  673.     STD_String[id].BufferPos = strlen(text);
  674.     position = AddGadget(STD_Window, G(id), -1);
  675.     if (position != -1)
  676.         RefreshGadgets(G(id), STD_Window, NULL);
  677.     }
  678. }
  679.  
  680.  
  681. static
  682. SetDirName(name)
  683. char *name;
  684. {
  685.     char buffer[MAXFULL+1], *ptr;
  686.     int  index;
  687.     char lastchar;
  688.  
  689.     /* Can't enter a file name too long. */
  690.  
  691.     if (strlen(DirName) + strlen(name) + 1 > MAXFULL) {
  692.     DisplayBeep();
  693.     return(0);
  694.     }
  695.     index = 0;
  696.     lastchar = 0;
  697.     for (ptr = (char *)DirName; *ptr; ptr++)
  698.     buffer[index++] = lastchar = *ptr;
  699.     if (lastchar != ':' && lastchar != 0)
  700.     buffer[index++] = '/';
  701.     strcpy(&buffer[index], name);
  702.     SetGadgetText(DIRID, buffer);
  703.     SetGadgetText(FILID, "");
  704.     return(1);
  705. }
  706.  
  707. static
  708. SetFileName(name)
  709. char *name;
  710. {
  711.     /* Can't enter a file name too long. */
  712.     if (strlen(DirName) + strlen(name) + 1 > MAXFULL) {
  713.     DisplayBeep();
  714.     return(0);
  715.     }
  716.     SetGadgetText(FILID, name);
  717.     return(1);
  718. }
  719.  
  720. static
  721. SetPatName(name)
  722. char *name;
  723. {
  724.     SetGadgetText(PATID, name);
  725. }
  726.  
  727. static
  728. ProcessGadget(id)
  729. int id;
  730. {
  731.     switch(id) {
  732.     case DIRID: ReadNewDir();       break;
  733.     case FILID: ProcessFileName();  break;
  734.     case PATID: ReCalcPattern();    break;
  735.     case BARID: CalcFilePosition(); break;
  736.     case YESID: DoneFlag = 1;        break;
  737.     case CANID: DoneFlag = -1;        break;
  738.     case VOLID: ReadVol();          break;
  739.     }
  740. }
  741.  
  742. /*
  743.  *  ProcessFileName() added by Matthew Dillon.  If the requested file is
  744.  *  actually a directory, do a ReadNewDir() instead of quiting.
  745.  */
  746.  
  747. void
  748. ProcessFileName()
  749. {
  750.     register char *ptr;
  751.     register short len;
  752.     BPTR fillock;
  753.     char buf[128];
  754.     FIB *fib = (FIB *)malloc(sizeof(FIB));
  755.  
  756.     if (fib == NULL) {
  757.     DoneFlag = 1;
  758.     return;
  759.     }
  760.     for (ptr = (char *)FileName; *ptr; ++ptr) {
  761.     if (*ptr == ':') {
  762.         DirName[0] = '\0';
  763.         break;
  764.     }
  765.     }
  766.     strcpy(buf, DirName);
  767.     if (FileName[0]) {
  768.     if (len = strlen(buf)) {
  769.         if (buf[len-1]!=':')
  770.         strcat(buf, "/");
  771.     }
  772.     strcat(buf, FileName);
  773.     if (fillock = Lock(buf, ACCESS_READ)) {
  774.         if (Examine(fillock, fib)) {
  775.         if (fib->fib_DirEntryType > 0) {
  776.             SetGadgetText(DIRID, buf);
  777.             SetGadgetText(FILID, "");
  778.             ReadNewDir();
  779.             free(fib);
  780.             UnLock(fillock);
  781.             return;
  782.         }
  783.         }
  784.         UnLock(fillock);
  785.     }
  786.     }
  787.     free(fib);
  788.     DoneFlag = 1;
  789. }
  790.  
  791.  
  792. static
  793. ProcessMouse(x, y, code, seconds, micros)
  794. {
  795.     int NewSelected;
  796.     static int oseconds = 0, omicros = 0;
  797.  
  798.     if (x < HOMEX || y < HOMEY || x >= LASTX || y >= LASTY)
  799.     return;
  800.     if ((code & SELECTUP) == SELECTUP)
  801.     return;
  802.     if (State != DIRECTORY) {
  803.     ReadNewDir();
  804.     return;
  805.     }
  806.     NewSelected = (y-HOMEY)/CHSIZ + FirstFile;
  807.     if (NewSelected == Selected) {
  808.     if (Selected != -1) {
  809.         if (DoubleClick(oseconds, omicros, seconds, micros)) {
  810.         if (NameTable[Selected]->filetype == DIRTYPE) {
  811.             if (SetDirName(NameTable[Selected]->filename))
  812.             ReadNewDir();
  813.         } else if (NameTable[Selected]->filetype == VOLTYPE) {
  814.             SetGadgetText(DIRID, NameTable[Selected]->filename);
  815.             SetGadgetText(FILID, "");
  816.             ReadNewDir();
  817.         } else if (!SetFileName(NameTable[Selected]->filename)) {
  818.             Selected = -1;
  819.             DoneFlag = 1;
  820.         }
  821.         }
  822.     }
  823.     } else {
  824.     if (Selected != -1 && Selected >= FirstFile && Selected < FirstFile+MAXFILES)
  825.         PrintName(Selected, 0);
  826.     Selected = NewSelected;
  827.     if (Selected >= NumFiles) {
  828.         Selected = -1;
  829.     } else {
  830.         if (SetFileName(NameTable[Selected]->filename))
  831.         PrintName(Selected, 1);
  832.         else
  833.         Selected = -1;
  834.         if (IntuitionBase->LibNode.lib_Version > 32)
  835.         ActivateGadget(G(1),STD_Window,0L);
  836.     }
  837.     }
  838.     oseconds = seconds;
  839.     omicros = micros;
  840. }
  841.  
  842. stdfile(title, deffile, defpat, name)
  843. char *title, *deffile, *defpat, *name;
  844. {
  845.     IMESS *im;
  846.  
  847.     if(title)
  848.     STD_NewWindow.Title = (UBYTE *)title;
  849.     else
  850.     STD_NewWindow.Title = (UBYTE *)"Enter File Name";
  851.     if (deffile) {
  852.     int i;
  853.     for (i = strlen(deffile)-1; i >= 0; --i) {
  854.         if (deffile[i]==':' || deffile[i]=='/') {
  855.         int hold;
  856.         strcpy(FileName, &deffile[i+1]);
  857.         if (deffile[i]==':')
  858.             i++;
  859.         hold = deffile[i];
  860.         deffile[i] = 0;
  861.         strcpy(DirName, deffile);
  862.         deffile[i] = hold;
  863.         break;
  864.         }
  865.     }
  866.     if (i < 0) {
  867.         strcpy(FileName, deffile);
  868.         DirName[0] = 0;
  869.     }
  870.     } else {
  871.     DirName[0] = 0;
  872.     FileName[0] = 0;
  873.     }
  874.     if (defpat)
  875.     strcpy(PatName, defpat);
  876.     else
  877.     PatName[0] = 0;
  878.  
  879.     State = INITIAL;
  880.     NameTable = 0;
  881.     NameList = 0;
  882.  
  883.     if(!OpenFileWindow())
  884.     return(0);
  885.     DoneFlag = 0;
  886.     while (!DoneFlag) {
  887.     Wait(1<<STD_Window->UserPort->mp_SigBit);
  888.     while(im = GetMsg(STD_Window->UserPort)) {
  889.         switch(im->Class) {
  890.         case CLOSEWINDOW:
  891.         DoneFlag = -1;
  892.         break;
  893.         case MOUSEBUTTONS:
  894.         ProcessMouse(im->MouseX, im->MouseY, im->Code, im->Seconds, im->Micros);
  895.         break;
  896.         case GADGETUP:
  897.         ProcessGadget(((struct Gadget *)im->IAddress)->GadgetID);
  898.         break;
  899.         case REFRESHWINDOW:
  900.         BeginRefresh(STD_Window);
  901.         PaintFileWindow();
  902.         EndRefresh(STD_Window, 1);
  903.         break;
  904.         }
  905.         ReplyMsg(im);
  906.     }
  907.     }
  908.     CloseFileWindow();
  909.     FreeList(NameList);
  910.  
  911.     if (NameTable)
  912.     free(NameTable);
  913.     if (DoneFlag == 1) {
  914.     int len;
  915.  
  916.     strcpy(name, DirName);
  917.     if (FileName[0]) {
  918.         if (len = strlen(name)) {
  919.         if (name[len-1]!=':')
  920.             strcat(name, "/");
  921.         }
  922.         strcat(name, FileName);
  923.         return(1);
  924.     }
  925.     }
  926.     return(0);
  927. }
  928.  
  929. /*
  930.  *  VOLLIST.C
  931.  */
  932.  
  933. #define toAPTR(b) ((b)<<2)
  934. #define toBPTR(a) ((a)>>2)
  935.  
  936. struct DeviceList *list;
  937.  
  938. OpenVolList()
  939. {
  940.     extern DOSLIB *DOSBase;
  941.     ROOTNODE *root;
  942.     DOSINFO  *info;
  943.  
  944.     root =   (ROOTNODE *)DOSBase->dl_Root;
  945.     info =   (DOSINFO  *)toAPTR(root->rn_Info);
  946.     list = (DEVLIST *)toAPTR(info->di_DevInfo);
  947. }
  948.  
  949. ReadVolList(name)
  950. char *name;
  951. {
  952.     register DEVLIST *next;
  953.  
  954.     while(list) {
  955.     next = (DEVLIST *)toAPTR(list->dl_Next);
  956.     if (list->dl_Type == DLT_VOLUME) {
  957.         char *ptr;
  958.         int count;
  959.         ptr = (char *)toAPTR((BPTR)list->dl_Name);
  960.         count = *ptr++;
  961.         if (count > 30)
  962.         count = 30;
  963.         strncpy(name, ptr, count);
  964.         name[count++] = ':';
  965.         name[count] = 0;
  966.         list = next;
  967.         return(1);
  968.     }
  969.     list = next;
  970.     }
  971.     return(0);
  972. }
  973.  
  974. CloseVolList()
  975. {
  976. }
  977.  
  978.  
  979.