home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 1: Collection A / 17Bit_Collection_A.iso / files / 1065.dms / 1065.adf / TextPlus / SrcE.lzh / SrcE / fs1.c < prev    next >
C/C++ Source or Header  |  1990-08-06  |  27KB  |  992 lines

  1. /* --------------------------------------------------------------------
  2.  * FS1.C - PathMaster(tm) Super File Selector control code.
  3.  * Copyright © 1987-1989 by Justin V. McCormick.  All Rights Reserved.
  4.  * -------------------------------------------------------------------- */
  5.  
  6. #include <exec/types.h>
  7. #include <exec/nodes.h>
  8. #include <exec/lists.h>
  9. #include <exec/memory.h>
  10. #include <exec/ports.h>
  11. #include <exec/io.h>
  12. #include <exec/semaphores.h>
  13. #include <exec/libraries.h>
  14. #include <devices/timer.h>
  15. #include <devices/inputevent.h>
  16. #include <graphics/gfx.h>
  17. #include <graphics/view.h>
  18. #include <graphics/rastport.h>
  19. #include <graphics/layers.h>
  20. #include <graphics/text.h>
  21. #include <intuition/intuition.h>
  22. #include <libraries/dos.h>
  23. #include <libraries/dosextens.h>
  24. #include <libraries/filehandler.h>
  25. #include <stdio.h>
  26.  
  27. #include "fs.h"
  28.  
  29. #ifdef LATTICE
  30. #define strlen strlen
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <proto/exec.h>
  34. #include <proto/graphics.h>
  35. #include <proto/intuition.h>
  36. #include <proto/dos.h>
  37. #endif
  38.  
  39. #ifdef AZTEC_C
  40. #include <functions.h>
  41. extern struct IORequest *CreateExtIO __ARGS((struct MsgPort *, LONG));
  42. #endif
  43.  
  44. /* Extern CODE */
  45. #ifdef BENCHMARK
  46. extern VOID __stdargs StartTime __ARGS((VOID));
  47. extern VOID __stdargs StopTime __ARGS((BYTE *));
  48. #endif
  49.  
  50. extern BYTE *__stdargs FibFileDate __ARGS((struct DateStamp *));
  51. extern BYTE *__stdargs myrindex __ARGS((BYTE *, LONG));
  52. extern LONG __stdargs AllocFSFib __ARGS((VOID));
  53. extern LONG __stdargs FSCheckFlagChange __ARGS((VOID));
  54. extern LONG __stdargs FSGetNextFib __ARGS((VOID));
  55. extern LONG __stdargs ioerrnum __ARGS((LONG));
  56. extern LONG __stdargs lstrcmp __ARGS((BYTE *, BYTE *));
  57. extern struct dev_node *__stdargs AllocDevNode __ARGS((VOID));
  58. extern struct file_node *__stdargs AllocFileNode __ARGS((VOID));
  59. extern VOID __stdargs CheckFSArrows __ARGS((VOID));
  60. extern VOID __stdargs FillFileNode __ARGS((struct file_node *));
  61. extern VOID __stdargs FreeAllDNodes __ARGS((VOID));
  62. extern VOID __stdargs FreeAllFNodes __ARGS((VOID));
  63. extern VOID __stdargs FreeFileSelect __ARGS((VOID));
  64. extern VOID __stdargs FSAssignEntryText __ARGS((struct file_node *, LONG));
  65. extern VOID __stdargs FSClearLock __ARGS((VOID));
  66. extern VOID __stdargs FSDisableAllFGads __ARGS((VOID));
  67. extern VOID __stdargs FSDoFileGad __ARGS((LONG));
  68. extern VOID __stdargs FSDoGadget __ARGS((ULONG));
  69. extern VOID __stdargs FSDoSlideGadget __ARGS((VOID));
  70. extern VOID __stdargs FSDoSortGadget __ARGS((LONG));
  71. extern VOID __stdargs FSEndString __ARGS((VOID));
  72. extern VOID __stdargs FSMatchPattern __ARGS((VOID));
  73. extern VOID __stdargs FSPutPath __ARGS((VOID));
  74. extern VOID __stdargs FSResetKnob __ARGS((VOID));
  75. extern VOID __stdargs FSScrollFileGads __ARGS((LONG));
  76. extern VOID __stdargs FSSetFileGads __ARGS((VOID));
  77. extern VOID __stdargs FSSetKnob __ARGS((VOID));
  78. extern VOID __stdargs FSStartScrollGad __ARGS((ULONG));
  79. extern VOID __stdargs FSUpdateSort __ARGS((VOID));
  80. extern VOID __stdargs FSWinTitle __ARGS((VOID));
  81. extern VOID __stdargs HCompEntry __ARGS((ULONG));
  82. extern VOID __stdargs MakePathString __ARGS((struct FileLock *, BYTE *));
  83. extern VOID __stdargs MyActivateGad __ARGS((struct Gadget *, struct Window *));
  84. extern VOID __stdargs safestrcpy __ARGS((BYTE *, BYTE *, LONG));
  85. extern VOID __stdargs SetDevGads __ARGS((VOID));
  86.  
  87.  
  88. /* Extern DATA from fsdata.c */
  89. #ifdef STANDALONE
  90. extern struct TextFont *FSTextFont;
  91. extern struct TextAttr Def8Text;
  92. #else
  93. extern struct TextFont Def8TextData;
  94. #endif
  95.  
  96. extern BPTR FSLock;
  97. extern BYTE *fserrmsgs[];
  98. extern BYTE *FSPathBuf;
  99. extern BYTE *OldFSPathBuf;
  100. extern BYTE fserrmsg22[];
  101. extern BYTE fserrmsg24[];
  102. extern BYTE fserrmsg27[];
  103. extern BYTE fserrmsg28[];
  104. extern BYTE fserrmsg29[];
  105. extern BYTE FSIgnorePat[];
  106. extern BYTE FSPatternUndoBuffer[];
  107. extern BYTE FSWinTitleStr[];
  108. extern BYTE FSwstr[];
  109. extern BYTE RamDirNameStr[];
  110. extern BYTE SplatStr[];
  111. extern BYTE TimerName[];
  112. extern struct DateStamp FSdirstamp;
  113. extern struct dev_node *lastdev;
  114. extern struct DosLibrary *DOSBase;
  115. extern struct FileInfoBlock *FSFib;
  116. extern struct file_node *FSFileNodes[];
  117. extern struct file_node *topfin;
  118. extern struct FSRequest *FSReq;
  119. extern struct Gadget FSFileGad;
  120. extern struct Gadget FSPathGad;
  121. extern struct Gadget FSSelectGad;
  122. extern struct Gadget FSUserGad;
  123. extern struct IntuiText FSCancelTxt;
  124. extern struct IntuiText FSFileTxt;
  125. extern struct IntuiText FSPathTxt;
  126. extern struct IntuiText FSSelectTxt;
  127. extern struct IntuiText FSUserTxt;
  128. extern struct List *devList;
  129. extern struct List *fnList;
  130. extern struct MsgPort *FSTimerPort;
  131. extern struct NewWindow FSnw;
  132. extern struct RastPort *FSRPort;
  133. extern struct StringInfo FSFileInfo;
  134. extern struct StringInfo FSPathInfo;
  135. extern struct StringInfo FSPatternInfo;
  136. extern struct timerequest *FSDelayReq;
  137. extern struct Window *FSWin;
  138. extern UBYTE FSFileLabelStr[];
  139. extern UBYTE FSPathLabelStr[];
  140. extern ULONG fscursecs, fscurmicros;
  141. extern ULONG fsoldsecs, fsoldmicros;
  142. extern ULONG FSSignal;
  143. extern ULONG FSSignalMask;
  144. extern ULONG FSUserSignal;
  145. extern UWORD fsflags;
  146. extern WORD FSCountDown;
  147. extern WORD fsdirlocked;
  148. extern WORD FSDone;
  149. extern WORD fsnumentries;
  150. extern WORD fsstartedstr;
  151. extern WORD fstitlelength;
  152. extern WORD fstitstatus;
  153. extern WORD fsvirgindir;
  154.  
  155. /* Local CODE */
  156. LONG CreateVBTimer __ARGS((BYTE *, struct MsgPort **, struct timerequest **));
  157. LONG FSGetDevs __ARGS((VOID));
  158. LONG FSGrabEntry __ARGS((VOID));
  159. LONG FSLockDir __ARGS((VOID));
  160. LONG FSTestOldLock __ARGS((VOID));
  161. LONG InitFSVBDelay __ARGS((VOID));
  162. LONG InitFSWindow __ARGS((VOID));
  163. VOID AbortAsyncIO __ARGS((struct IORequest *));
  164. VOID CheckFSIDCMP __ARGS((VOID));
  165. VOID FreeFSVBDelay __ARGS((VOID));
  166. VOID FreeVBTimer __ARGS((struct MsgPort **, struct timerequest **));
  167. VOID __stdargs FSVBDelay __ARGS((ULONG));
  168.  
  169. LONG FileSelect __ARGS((struct FSRequest *));
  170. /* --------------------------------------------------------------------
  171.  *                       FileSelect
  172.  * -------------------------------------------------------------------- */
  173. LONG FileSelect(fsrequest)
  174.   struct FSRequest *fsrequest;
  175. {
  176.   LONG i, status, newpat;
  177.   ULONG signals;
  178.  
  179. /* (Re)Initialize things */
  180.   FSReq = fsrequest;            /* Init global filereq struct pointer */
  181.  
  182. /* Set pattern to match files */
  183.   newpat = 0;                /* Assume no pattern changes at first */
  184.   FSPatternInfo.Buffer = (UBYTE *)fsrequest->matchpattern;
  185.   FSPatternInfo.BufferPos = strlen(FSPatternInfo.Buffer);
  186.   if (FSPatternInfo.Buffer[0] == 0)    /* Put splat back if no matchpattern  */
  187.     (VOID)strcpy(FSPatternInfo.Buffer, SplatStr);
  188.   
  189.   if (lstrcmp(FSPatternUndoBuffer, FSPatternInfo.Buffer) != 0)
  190.   {
  191.     safestrcpy(FSPatternUndoBuffer, FSPatternInfo.Buffer, (LONG)(MATCHSTRSIZE - 1));
  192.     newpat = 1;
  193.   }
  194.  
  195. /* Set pattern to ignore files */
  196.   if (lstrcmp(FSIgnorePat, fsrequest->ignorepattern) != 0)
  197.   {
  198.     safestrcpy(FSIgnorePat, fsrequest->ignorepattern, (LONG)(FILESTRSIZE - 1));
  199.     newpat = 1;
  200.   }
  201.  
  202. /* Update fsflags if FSReq->flags has changed, reset state if needed */
  203.   if (FSCheckFlagChange() != 0)
  204.     newpat = 1;
  205.  
  206. /* Set initial directory */
  207.   FSPathInfo.Buffer = (UBYTE *)fsrequest->dirname;
  208.   FSPathInfo.BufferPos = strlen(FSPathInfo.Buffer);
  209.   if (lstrcmp(FSPathInfo.Buffer, FSPathBuf) != 0)
  210.   {
  211.     fsvirgindir = 1;
  212.   }
  213.  
  214. /* Set initial filename */
  215.   FSFileInfo.Buffer = (UBYTE *)fsrequest->filename;
  216.   FSFileInfo.BufferPos = strlen(FSFileInfo.Buffer);
  217.  
  218. /* Open and initialize everything, start IDCMP processing */
  219.   status = InitFSWindow();
  220.   if (status != 0)
  221.   {
  222.     FSWinTitle();
  223.  
  224. /* Redisplay buffered data if still valid */
  225.     if (FSTestOldLock() != 0 && fsvirgindir <= 0)
  226.     {
  227.       if (newpat != 0)         /* Pattern changed, but still have old data */
  228.       {
  229.         FSMatchPattern();
  230.       }
  231.       else            /* Otherwise just redraw them from static data */
  232.       {
  233.         FSSetFileGads();
  234.         FSDisableAllFGads();
  235.       }
  236.     }
  237.  
  238.     FSDone = 0;
  239.     while (FSDone == 0)
  240.     {
  241.       if (fsvirgindir != 0)
  242.       {
  243.         if (FSGrabEntry() == 0)
  244.           goto FSFailed;
  245.         signals = FSSignal | FSUserSignal;
  246.       }
  247.       else
  248.       {
  249.         signals = Wait((LONG)FSSignalMask);
  250.       }
  251.  
  252.       if ((signals & FSUserSignal) != 0)
  253.       {
  254.         i = (FSReq->userfunc)(FSReq, FSWin);
  255.         if (i != 0)
  256.           fsvirgindir = 1;
  257.       }
  258.  
  259.       if ((signals & FSSignal) != 0)
  260.         CheckFSIDCMP();
  261.     }
  262.   }
  263.  
  264. /***********/
  265.   FSFailed:
  266. /***********/
  267.   if (FSRPort != 0)
  268.   {
  269.     FreeMem(FSRPort, (LONG)sizeof(struct RastPort));
  270.     FSRPort = 0;
  271.   }
  272. #ifdef STANDALONE
  273.   if (FSTextFont != 0)
  274.   {
  275.     CloseFont(FSTextFont);
  276.     FSTextFont = 0;
  277.   }
  278. #endif
  279.   if (FSWin != 0)
  280.   {
  281.     FSReq->leftedge = FSWin->LeftEdge;
  282.     FSReq->topedge = FSWin->TopEdge;
  283.     CloseWindow(FSWin);
  284.     FSWin = 0;
  285.   }
  286. #ifdef STANDALONE
  287.   FreeFSVBDelay();
  288. #endif
  289.   return(status);
  290. }
  291.  
  292. /* -------------------------------------------------------------------- */
  293. LONG InitFSWindow()
  294. {
  295.   LONG i, xinc, xleft, xmax;
  296.   struct Gadget *tgad;
  297.  
  298. /* Initialize a timer device for delays */
  299. #ifdef STANDALONE
  300.   if (InitFSVBDelay() == 0)
  301.   {
  302.     return(0L);
  303.   }
  304. #endif
  305.  
  306. /* Initialize FSWin title string */
  307.   safestrcpy(FSWinTitleStr, FSReq->titlestr, 28L);
  308.   (VOID)strcat(FSWinTitleStr, " ");
  309.   fstitlelength = strlen(FSWinTitleStr);
  310.  
  311.   fserrmsgs[27] = FSReq->readingstr;
  312.   fserrmsgs[28] = FSReq->sortingstr;
  313.   fserrmsgs[22] = FSReq->emptydirstr;
  314.   fserrmsgs[24] = FSReq->nomatchstr;
  315.   fserrmsgs[29] = FSReq->selectfilestr;
  316.   if (fserrmsgs[27] == 0)
  317.     fserrmsgs[27] = fserrmsg27;
  318.   if (fserrmsgs[28] == 0)
  319.     fserrmsgs[28] = fserrmsg28;
  320.   if (fserrmsgs[22] == 0)
  321.     fserrmsgs[22] = fserrmsg22;
  322.   if (fserrmsgs[24] == 0)
  323.     fserrmsgs[24] = fserrmsg24;
  324.   if (fserrmsgs[29] == 0)
  325.     fserrmsgs[29] = fserrmsg29;
  326.  
  327.   if (FSReq->pathgadstr != 0)
  328.     FSPathTxt.IText = (UBYTE *)FSReq->pathgadstr;
  329.   else
  330.     FSPathTxt.IText = FSPathLabelStr;
  331.  
  332.   if (FSReq->filegadstr != 0)
  333.     FSFileTxt.IText = (UBYTE *)FSReq->filegadstr;
  334.   else
  335.     FSFileTxt.IText = FSFileLabelStr;
  336.  
  337. /* Set our directory gadget names to whatever the user has out there */
  338.   if (devList == 0)    /* If already set, don't reset */
  339.   {
  340.     if (FSGetDevs() == 0)
  341.     {
  342.       return(0L);
  343.     }
  344.     SetDevGads();
  345.   }
  346.  
  347. /* Set Select and Cancel gadget texts */
  348.   FSSelectTxt.IText = (UBYTE *)FSReq->selectstr;
  349.   FSSelectTxt.LeftEdge = 37 - strlen(FSReq->selectstr) * 4;
  350.  
  351.   FSCancelTxt.IText = (UBYTE *)FSReq->cancelstr;
  352.   FSCancelTxt.LeftEdge = 37 - strlen(FSReq->cancelstr) * 4;
  353.  
  354. /* Center the Select, Cancel, and LastDir gadgets */
  355.   if (FSReq->specgadstr != 0)
  356.   {
  357.     FSnw.FirstGadget = &FSUserGad;
  358.     FSUserTxt.IText = (UBYTE *)FSReq->specgadstr;
  359.     FSUserTxt.LeftEdge = 37 - strlen(FSReq->specgadstr) * 4;
  360.     xleft = 4;
  361.     xmax = 4;
  362.     xinc = 75;
  363.   }
  364.   else
  365.   {
  366.     FSnw.FirstGadget = &FSSelectGad;
  367.     xleft = 38;
  368.     xmax = 3;
  369.     xinc = 95;
  370.   }
  371.  
  372.   tgad = FSnw.FirstGadget;
  373.   for (i = 0; i < xmax; i++)
  374.   {
  375.     tgad->LeftEdge = xleft + i * xinc;
  376.     tgad = tgad->NextGadget;
  377.   }
  378.  
  379. /* Determine which screen to open the FileSelect Window on */
  380.   if (FSReq->userscreen == 0)
  381.   {
  382.     FSnw.Type = WBENCHSCREEN;
  383.     FSnw.Screen = 0;
  384.   }
  385.   else
  386.   {
  387.     FSnw.Type = CUSTOMSCREEN;
  388.     FSnw.Screen = FSReq->userscreen;
  389.   }
  390.   FSnw.LeftEdge = FSReq->leftedge;
  391.   FSnw.TopEdge = FSReq->topedge;
  392.   if (FSReq->windowflags != 0)
  393.     FSnw.Flags = FSReq->windowflags;
  394.  
  395.   if ((FSWin = OpenWindow(&FSnw)) == 0)
  396.   {
  397.     return(0L);
  398.   }
  399.   else
  400.   {
  401. /* Allocate/clone/initialize RastPort copy for rendering Text */
  402. #ifdef STANDALONE
  403.     if ((FSTextFont = OpenFont(&Def8Text)) == 0)
  404.       return(0L);
  405. #endif
  406.  
  407.     if ((FSRPort = (struct RastPort *)AllocMem((LONG)sizeof(struct RastPort), 0L)) == 0)
  408.       return(0L);
  409.     CopyMem((BYTE *)FSWin->RPort, (BYTE *)FSRPort, (LONG)sizeof(struct RastPort));
  410.  
  411. #ifdef STANDALONE
  412.     SetFont(FSRPort, FSTextFont);
  413. #else
  414.     SetFont(FSRPort, &Def8TextData);
  415. #endif
  416.  
  417.     if (FSReq->initfunc != 0)
  418.       (VOID)(FSReq->initfunc)(FSReq, FSWin);
  419.  
  420.     FSSignal = 1L << FSWin->UserPort->mp_SigBit;
  421.     FSSignalMask = FSSignal;
  422.     if (FSReq->userport != 0 && FSReq->userfunc != 0)
  423.     {
  424.       FSUserSignal = 1L << FSReq->userport->mp_SigBit;
  425.       FSSignalMask |= FSUserSignal;
  426.     }
  427.     else
  428.       FSUserSignal = 0;
  429.  
  430.     ScreenToFront(FSWin->WScreen);
  431.  
  432.     PrintIText(FSWin->RPort, &FSPathTxt, 4L, 125L);
  433.  
  434.     MyActivateGad(&FSFileGad, FSWin);
  435.     FSCountDown = 0;
  436.     return(1L);
  437.   }
  438. }
  439.  
  440. /* -------------------------------------------------------------------- */
  441. LONG CreateVBTimer(name, pport, ptreq)
  442.   BYTE *name;
  443.   struct MsgPort **pport;
  444.   struct timerequest **ptreq;
  445. {
  446.   if ((*pport = CreatePort(name, 0L)) != 0)
  447.   {
  448.     if ((*ptreq = (struct timerequest *)CreateExtIO(*pport, (LONG)sizeof(struct timerequest))) != 0)
  449.     {
  450.       if (OpenDevice(TimerName, (LONG)UNIT_VBLANK, (struct IORequest *)*ptreq, 0L) == 0)
  451.       {
  452.         return(1L);
  453.       }
  454.     }
  455.   }
  456.   return(0L);
  457. }
  458.  
  459. /* --------------------------------------------------------------------
  460.  * Initialize a VBLANK timer for scroll arrow timings
  461.  * -------------------------------------------------------------------- */
  462. LONG InitFSVBDelay()
  463. {
  464.   return(CreateVBTimer(0L, &FSTimerPort, &FSDelayReq));
  465. }
  466.  
  467. /* --------------------------------------------------------------------
  468.  * Free above timer.
  469.  * -------------------------------------------------------------------- */
  470. VOID FreeFSVBDelay()
  471. {
  472.   FreeVBTimer(&FSTimerPort, &FSDelayReq);
  473. }
  474.  
  475. /* -------------------------------------------------------------------- */
  476. VOID FreeVBTimer(pport, ptreq)
  477.   struct MsgPort **pport;
  478.   struct timerequest **ptreq;
  479. {
  480.   struct timerequest *treq;
  481.  
  482.   if (*pport != 0)
  483.   {
  484.     if ((treq = *ptreq) != 0)
  485.     {
  486.       if (treq->tr_node.io_Device != 0)
  487.       {
  488.         AbortAsyncIO((struct IORequest *)treq);
  489.         CloseDevice((struct IORequest *)treq);
  490.       }
  491.       DeleteExtIO((struct IORequest *)treq);
  492.       *ptreq = 0;
  493.     }
  494.     DeletePort(*pport);
  495.     *pport = 0;
  496.   }
  497. }
  498.  
  499. /* -------------------------------------------------------------------- */
  500. VOID __stdargs FSVBDelay(timedelay)
  501.   ULONG timedelay;
  502. {
  503.   FSDelayReq->tr_node.io_Command = TR_ADDREQUEST;
  504.   FSDelayReq->tr_time.tv_micro = timedelay * 20000;
  505.   FSDelayReq->tr_time.tv_secs = 0;
  506.   (VOID)DoIO((struct IORequest *)FSDelayReq);
  507. }
  508.  
  509. /* --------------------------------------------------------------------
  510.  * Clean out any pending async IO in a given IORequest type struct.
  511.  * --------------------------------------------------------------------    */
  512. VOID AbortAsyncIO(req)
  513.   struct IORequest *req;
  514. {
  515.   if (req->io_Command != 0 && CheckIO(req) == 0)
  516.   {
  517.     (VOID)AbortIO(req);
  518.     (VOID)WaitIO(req);
  519.   }
  520. }
  521.  
  522. /* -------------------------------------------------------------------- */
  523. LONG FSGrabEntry()
  524. {
  525.   struct file_node *tnode;
  526.  
  527.   if (fsvirgindir > 0)        /* Brand new list */
  528.   {
  529.     fstitstatus = 27;        /* Set our windowtitle to Reading */
  530.     FSWinTitle();
  531.  
  532.     FreeAllFNodes();        /* Clean out old list */
  533.     FSSetKnob();        /* Show full height knob now */
  534.     FSDisableAllFGads();
  535.  
  536.     if (FSLockDir() == 0)    /* Try to lock the new path */
  537.       goto CrapOut1;         /* Lock failed */
  538.   }
  539.  
  540.   if (fnList == 0)
  541.   {
  542.     if ((fnList = AllocMem ((LONG)sizeof(struct MinList), 0L)) == 0)
  543.       goto CrapOut0;
  544.     NewList (fnList);
  545.   }
  546.  
  547.   if (FSGetNextFib() <= 0)     /* Try to Examine entry */
  548.     goto CrapOut1;        /* We are done!? */
  549.  
  550. /* Initialize new node */
  551.   if ((tnode = AllocFileNode()) == 0)
  552.     goto CrapOut0;
  553.  
  554.   if (fsvirgindir > 0)        /* New list, needs new head! */
  555.     fsvirgindir = -1;         /* Still TRUE, but avoid relocking dir */
  556.   
  557. /* Fill in the info */
  558.   FillFileNode(tnode);
  559.   return(1L);
  560.  
  561. CrapOut0:
  562.   FreeFileSelect();
  563.   fstitstatus = 26;
  564.   FSWinTitle();
  565.   return(0L);
  566.  
  567. CrapOut1:
  568.   if ((fsflags & FS_DELAYED_SORT) == 0)
  569.     FSUpdateSort();
  570.   if (fsnumentries > 10 && (fsnumentries & 0x01) != 0)
  571.     FSResetKnob();
  572.   fsvirgindir = 0;
  573.   FSClearLock();
  574.   FSWinTitle();
  575.   return(1L);
  576. }
  577.  
  578. /* -------------------------------------------------------------------- */
  579. LONG FSLockDir()
  580. {
  581.   LONG namlen;
  582.   struct CommandLineInterface *thiscli;
  583.   struct Process *thisproc;
  584.   struct Window *oldwin;
  585.   UBYTE *tstr;
  586.  
  587. /* Inhibit System Requesters */
  588.   thisproc = (struct Process *)FindTask(0L);
  589.   oldwin = (struct Window *)thisproc->pr_WindowPtr;
  590.   thisproc->pr_WindowPtr = (APTR)-1L;
  591.  
  592. /* Backup last locked pathname and set new pathname */
  593.   (VOID)strcpy(OldFSPathBuf, FSPathBuf);
  594.   (VOID)strcpy(FSPathBuf, FSPathInfo.Buffer);
  595.  
  596. /* Make sure we release previous lock */
  597.   FSClearLock();
  598.  
  599. /* Allocate a fileinfoblock, if we have to */
  600.   if (AllocFSFib() == 0)
  601.   {
  602.     fstitstatus = 26;
  603.     goto SNAFUDIR;
  604.   }
  605.  
  606. /* Lock new path */
  607. locknewpath:
  608.   if (FSPathBuf[0] != 0) /* Path is named, no guesswork */
  609.   {
  610.     FSPutPath();
  611.     if ((FSLock = (BPTR)Lock(FSPathBuf, (LONG)ACCESS_READ)) == 0)
  612.     {
  613.       fstitstatus = ioerrnum(IoErr());
  614.       goto SNAFUDIR;
  615.     }
  616.     fsdirlocked = 1;    /* Got a live one here! */
  617.   }
  618.   else            /* Use current directory */
  619.   {
  620.     if (thisproc->pr_CurrentDir == 0)
  621.     {
  622.       fstitstatus = 3;
  623.       goto SNAFUDIR;
  624.     }
  625.     FSLock = (BPTR)thisproc->pr_CurrentDir;
  626.     fsdirlocked = 0;
  627.   }
  628.  
  629. /* Get a FileInfoBlock for this lock */
  630.   if (Examine((BPTR)FSLock, (BPTR)FSFib) == 0)
  631.   {
  632.     fstitstatus = ioerrnum(IoErr());
  633.     goto SNAFUDIR;
  634.   }
  635.   else
  636.   {
  637.     if (FSFib->fib_DirEntryType < 0)
  638.     {
  639.       fstitstatus = 2;
  640.       goto SNAFUDIR;
  641.     }
  642.   }
  643.  
  644. /* Copy DateStamp for later comparison */
  645.   FSdirstamp = FSFib->fib_Date;
  646.  
  647.   if (FSPathBuf[0] == (BYTE)0) /* Try to extract pathname from AmigaDOS */
  648.   {
  649.     if (thisproc->pr_CLI != 0) /* is this a CLI? */
  650.     {
  651.       thiscli = (struct CommandLineInterface *)((ULONG)thisproc->pr_CLI << 2L);
  652.       tstr = (UBYTE *)((ULONG)thiscli->cli_SetName << 2L);
  653.       namlen = (LONG)*tstr;
  654.       safestrcpy(FSPathBuf, (BYTE *)((ULONG)tstr + 1L), (LONG)namlen);
  655.     }
  656.     else /* must be WorkBench, use Fib name */
  657.     {
  658.       MakePathString((struct FileLock *)FSLock, FSPathBuf);
  659.     }
  660. /* Copy path to StringInfo buffer, display */
  661.     (VOID)strcpy(FSPathInfo.Buffer, FSPathBuf);
  662.     FSPutPath();
  663.   }
  664.   thisproc->pr_WindowPtr = (APTR)oldwin;
  665.   return(1L);
  666.  
  667. /* In case of dire directory problem */
  668. SNAFUDIR:
  669.   thisproc->pr_WindowPtr = (APTR)oldwin;
  670.   return(0L);
  671. }
  672.  
  673. /* --------------------------------------------------------------------
  674.  * Called when diskremoved, to see if the disk we are displaying has
  675.  * changed and needs to be re-read.
  676.  * -------------------------------------------------------------------- */
  677. LONG FSTestOldLock()
  678. {
  679.   LONG locked;
  680.   LONG status, oldtitstatus;
  681.   struct FileInfoBlock *fib;
  682.   struct FileLock *flock = 0;
  683.   struct Process *proc;
  684.   struct Window *oldwin;
  685.  
  686.   status = 0;
  687.   locked = 0;
  688.   oldtitstatus = fstitstatus;
  689.   proc = (struct Process *)FindTask(0L);
  690.   oldwin = (struct Window *)proc->pr_WindowPtr;
  691.   proc->pr_WindowPtr = (APTR)-1L;
  692.  
  693. /* Allocate a fileinfoblock */
  694.   if ((fib = (struct FileInfoBlock *)AllocMem((LONG)sizeof(struct FileInfoBlock), MEMF_CLEAR)) == 0)
  695.   {
  696.     fstitstatus = 26;
  697.     goto BadLock;
  698.   }
  699.  
  700. /* Try to lock path */
  701.   if (FSPathBuf[0] != 0)    /* Path is named, no guesswork */
  702.   {
  703.     if ((flock = (struct FileLock *)Lock(FSPathBuf, (LONG)ACCESS_READ)) == 0)
  704.     {
  705.       fstitstatus = ioerrnum(IoErr());
  706.       goto BadLock;
  707.     }
  708.     locked = 1;
  709.   }
  710.   else    /* Use current directory */
  711.     flock = (struct FileLock *)proc->pr_CurrentDir;
  712.  
  713. /* Examine the root block */
  714.   if (Examine((BPTR)flock, (BPTR)fib) == 0)
  715.   {
  716.     fstitstatus = ioerrnum(IoErr());
  717.     goto BadLock;
  718.   }
  719.   else
  720.   {
  721.     if (fib->fib_DirEntryType < 0)
  722.     {
  723.       fstitstatus = 3;
  724.       goto BadLock;
  725.     }
  726.   }
  727.   if (FSdirstamp.ds_Days == fib->fib_Date.ds_Days &&
  728.       FSdirstamp.ds_Minute == fib->fib_Date.ds_Minute &&
  729.       FSdirstamp.ds_Tick == fib->fib_Date.ds_Tick)
  730.     status = 1;
  731.   else
  732.     status = 0;
  733.  
  734. /* In case of dire directory problem */
  735. BadLock:
  736.   proc->pr_WindowPtr = (APTR)oldwin;
  737.   if (locked != 0)
  738.   {
  739.     UnLock((BPTR)flock);
  740.   }
  741.  
  742.   if (fib != 0)
  743.   {
  744.     FreeMem(fib, (LONG)sizeof(struct FileInfoBlock));
  745.   }
  746.  
  747.   if (status == 0)
  748.   {
  749.     fsvirgindir = 1;
  750.     FSdirstamp.ds_Days = FSdirstamp.ds_Minute = FSdirstamp.ds_Tick = 0;
  751.     if (fstitstatus != oldtitstatus)
  752.       FSWinTitle();
  753.   }
  754.   return(status);
  755. }
  756.  
  757. /* --------------------------------------------------------------------
  758.  * Constructs a circular doubly-linked list of device name nodes
  759.  * --------------------------------------------------------------------    */
  760. LONG FSGetDevs()
  761. {
  762.   LONG blen;
  763.   LONG ramflag = 0;        /* Flag whether RAM: device found */
  764.   struct DeviceNode *dn;
  765.   struct dev_node *tnode;
  766.   struct DosInfo *di;
  767.   struct RootNode *root;
  768.   UBYTE *bstring;
  769.  
  770. /* Allocate a MinList for use */
  771.   if (devList == 0)
  772.   {
  773.     if ((devList = AllocMem((LONG)sizeof(struct MinList), 0L)) == 0)
  774.       return (0L);
  775.   }
  776.   NewList (devList);
  777.  
  778. /* Grab pointer to DosInfo device root */
  779.   root = (struct RootNode *)DOSBase->dl_Root;
  780.   di = (struct DosInfo *)BADDR(root->rn_Info);
  781.   dn = (struct DeviceNode *) BADDR(di->di_DevInfo);
  782.  
  783. /* Don't let other processes muck with us during this sneaky stuff */
  784.   Forbid();
  785.  
  786. /* Starting with root devinfo, set devnames till out of devices */
  787.   for (; dn != 0; dn = (struct DeviceNode *)BADDR(dn->dn_Next))
  788.   {
  789.   /* Found a device? */
  790.     if ((dn->dn_Type == 0) && (dn->dn_Task != 0) && (dn->dn_Name != 0))
  791.     {
  792.       if ((tnode = AllocDevNode()) != 0)    /* Try to allocate a node */
  793.       {
  794.         bstring = (UBYTE *)BADDR(dn->dn_Name);    /* Pointer to BSTR name */
  795.         blen = (LONG)bstring[0];        /* Length of BSTR    */
  796.         CopyMem((BYTE *)(bstring + 1), (char *)tnode->name, (LONG)blen);
  797.         bstring = tnode->name;
  798.         bstring[blen] = ':';    /* Append a colon to copy of name */
  799.  
  800.         if (lstrcmp(bstring, RamDirNameStr) == 0)
  801.           ramflag = 1;
  802.  
  803.     AddHead(devList, (struct Node *)tnode);
  804.       }
  805.       else    /* Can't allocate a node, free 'em all and crap out */
  806.       {
  807.         Permit();
  808.         FreeAllDNodes();
  809.         return(0L);
  810.       }
  811.     }
  812.   }
  813.   Permit();
  814.  
  815.   if (ramflag == 0)    /* Ram device wasn't out there, add it to list */
  816.   {
  817.     if ((tnode = AllocDevNode()) == 0)
  818.     {
  819.       FreeAllDNodes();
  820.       return(0L);
  821.     }
  822.     (VOID)strcpy((BYTE *)tnode->name, RamDirNameStr);
  823.     AddHead(devList, (struct Node *)tnode);
  824.   }
  825.  
  826.   lastdev = tnode;    /* This is the first node, start display with this */
  827.   return(1L);
  828. }
  829.  
  830. /* -------------------------------------------------------------------- */
  831. VOID CheckFSIDCMP()
  832. {
  833.   BYTE *tstr1, *tstr2;
  834.   LONG my;
  835.   struct Gadget *tgadget;
  836.   struct IntuiMessage *imsg;
  837.   ULONG class, qualifier;
  838.   ULONG code;
  839.   ULONG secs, micros;
  840.  
  841.   while ((imsg = (struct IntuiMessage *)GetMsg(FSWin->UserPort)) != 0)
  842.   {
  843.     class = imsg->Class;
  844.     qualifier = imsg->Qualifier;
  845.     code = imsg->Code;
  846.     micros = imsg->Micros;
  847.     secs = imsg->Seconds;
  848.     my = imsg->MouseY;
  849.  
  850.     tgadget = (struct Gadget *)imsg->IAddress;
  851.     ReplyMsg((struct Message *)imsg);
  852.  
  853.     switch (class)
  854.     {
  855.       case INTUITICKS:
  856.         CheckFSArrows();
  857.         break;
  858.       case RAWKEY:
  859.         switch (code)
  860.         {
  861.           case 0x45:            /* Escape */
  862.             FSDone = 1;
  863.             FSReq->fullname[0] = (BYTE)0;
  864.             break;
  865.           case 0x4c:            /* Up cursor     */
  866.             FSScrollFileGads(1L);
  867.             break;
  868.           case 0x4d:            /* Down cursor     */
  869.             FSScrollFileGads(0L);
  870.             break;
  871.         }
  872.         break;
  873.       case MOUSEBUTTONS:
  874.         if (code == SELECTDOWN)
  875.         {
  876.           if (fsstartedstr != 0)
  877.             FSEndString();
  878.         }
  879.         else if (code == MENUUP)
  880.         {
  881.           if (fsstartedstr != 2)
  882.             MyActivateGad(&FSPathGad, FSWin);
  883.           else
  884.             MyActivateGad(&FSFileGad, FSWin);
  885.         }
  886.         break;
  887.       case GADGETDOWN:
  888.         if (fsstartedstr != 0)
  889.         {
  890.           FSEndString();
  891.         }
  892.         code = tgadget->GadgetID;
  893.         switch (code)
  894.         {
  895.           case 10:        /* Alpha */
  896.           case 11:        /* Size  */
  897.           case 12:        /* Time  */
  898.             FSDoSortGadget((LONG)code - 10);
  899.             break;
  900.           case 30:        /* FSPatternGad    */
  901.             fsstartedstr = 3;
  902.             break;
  903.           case 31:        /* FSFileGad */
  904.             fsstartedstr = 1;
  905.             break;
  906.           case 32:        /* FSPathGad */
  907.            fsstartedstr = 2;
  908.            break;
  909.           case 33:        /* SlideGad     */
  910.           case 40:        /* Up Arrow     */
  911.           case 41:        /* Down Arrow    */
  912.           case 42:        /* Up Device    */
  913.           case 43:        /* Down Device    */
  914.             FSStartScrollGad(code);
  915.             break;
  916.           case 50:        /* FSFileGad0    */
  917.             code = (my - 12) / 11;
  918.             if (FSFileNodes[code] != 0)
  919.             {
  920.               fscursecs = secs;
  921.               fscurmicros = micros;
  922.               HCompEntry(code);
  923.               FSVBDelay(5L);
  924.               HCompEntry(code);
  925.               FSDoFileGad((LONG)my);
  926.               fsoldsecs = secs;
  927.               fsoldmicros = micros;
  928.             }
  929.             break;
  930.         }
  931.         break;
  932.       case GADGETUP:
  933.         code = tgadget->GadgetID;
  934.         if (fsstartedstr != 0)
  935.         {
  936.           if ((qualifier & 0x0003) != 0)
  937.           {
  938.             if (fsstartedstr == 1)
  939.             {
  940.               MyActivateGad(&FSPathGad, FSWin);
  941.             }
  942.             else
  943.             {
  944.               MyActivateGad(&FSFileGad, FSWin);
  945.             }
  946.             code = 100;
  947.           }
  948.           else
  949.           {
  950.             if (fsstartedstr == 1)
  951.             {
  952.               if ((tstr1 = myrindex(FSFileInfo.Buffer, (LONG)'/')) != 0)
  953.               {
  954.                 *tstr1 = '\x0';
  955.                 tstr1++;
  956.                 (VOID)strcpy(FSwstr, tstr1);
  957.               }
  958.               else
  959.               {
  960.                 if ((tstr2 = myrindex(FSFileInfo.Buffer, (LONG)':')) != 0)
  961.                 {
  962.                   tstr2++;
  963.                   (VOID)strcpy(FSwstr, tstr2);
  964.                   *tstr2 = (BYTE)0;
  965.                 }
  966.               }
  967.               if (tstr1 != 0 || tstr2 != 0)
  968.               {
  969.                 (VOID)strcpy(FSPathInfo.Buffer, FSFileInfo.Buffer);
  970.                 (VOID)strcpy(FSPathBuf, FSFileInfo.Buffer);
  971.                 (VOID)strcpy(FSFileInfo.Buffer, FSwstr);
  972.                 FSFileInfo.BufferPos = strlen(FSFileInfo.Buffer);
  973.                 RefreshGList(&FSFileGad, FSWin, 0L, 2L);
  974.                 MyActivateGad(&FSFileGad, FSWin);
  975.                 fsvirgindir = 1;
  976.               }
  977.             }
  978.           }
  979.           fsstartedstr = 0;
  980.         }
  981.         FSDoGadget(code);
  982.         break;
  983.       case DISKREMOVED:
  984.       case DISKINSERTED:
  985.         if (fsvirgindir == 0)     /* If the disk has stopped spinning...    */
  986.           (VOID)FSTestOldLock(); /* See if we can lock our old place still */
  987.         break;
  988.     }
  989.   }
  990. }
  991.  
  992.