/* -------------------------------------------------------------------- * FS1.C - PathMaster(tm) Super File Selector control code. * Copyright © 1987-1989 by Justin V. McCormick. All Rights Reserved. * -------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fs.h" #ifdef LATTICE #define strlen strlen #include #include #include #include #include #include #endif #ifdef AZTEC_C #include #endif /* Extern CODE */ #ifdef BENCHMARK extern VOID __stdargs StartTime __ARGS((VOID)); extern VOID __stdargs StopTime __ARGS((BYTE *)); #endif extern BYTE *__stdargs FibFileDate __ARGS((struct DateStamp *)); extern BYTE *__stdargs myrindex __ARGS((BYTE *, LONG)); extern LONG __stdargs AllocFSFib __ARGS((VOID)); extern LONG __stdargs FSCheckFlagChange __ARGS((VOID)); extern LONG __stdargs FSGetNextFib __ARGS((VOID)); extern LONG __stdargs ioerrnum __ARGS((LONG)); extern LONG __stdargs lstrcmp __ARGS((BYTE *, BYTE *)); extern struct dev_node *__stdargs AllocDevNode __ARGS((VOID)); extern struct file_node *__stdargs AllocFileNode __ARGS((VOID)); extern VOID __stdargs CheckFSArrows __ARGS((VOID)); extern VOID __stdargs FillFileNode __ARGS((struct file_node *)); extern VOID __stdargs FreeAllDNodes __ARGS((VOID)); extern VOID __stdargs FreeAllFNodes __ARGS((VOID)); extern VOID __stdargs FreeFileSelect __ARGS((VOID)); extern VOID __stdargs FSAssignEntryText __ARGS((struct file_node *, LONG)); extern VOID __stdargs FSClearLock __ARGS((VOID)); extern VOID __stdargs FSDisableAllFGads __ARGS((VOID)); extern VOID __stdargs FSDoFileGad __ARGS((LONG)); extern VOID __stdargs FSDoGadget __ARGS((ULONG)); extern VOID __stdargs FSDoSlideGadget __ARGS((VOID)); extern VOID __stdargs FSDoSortGadget __ARGS((LONG)); extern VOID __stdargs FSEndString __ARGS((VOID)); extern VOID __stdargs FSMatchPattern __ARGS((VOID)); extern VOID __stdargs FSPutPath __ARGS((VOID)); extern VOID __stdargs FSResetKnob __ARGS((VOID)); extern VOID __stdargs FSScrollFileGads __ARGS((LONG)); extern VOID __stdargs FSSetFileGads __ARGS((VOID)); extern VOID __stdargs FSSetKnob __ARGS((VOID)); extern VOID __stdargs FSStartScrollGad __ARGS((ULONG)); extern VOID __stdargs FSUpdateSort __ARGS((VOID)); extern VOID __stdargs FSWinTitle __ARGS((VOID)); extern VOID __stdargs HCompEntry __ARGS((ULONG)); extern VOID __stdargs MakePathString __ARGS((struct FileLock *, BYTE *)); extern VOID __stdargs MyActivateGad __ARGS((struct Gadget *, struct Window *)); extern VOID __stdargs safestrcpy __ARGS((BYTE *, BYTE *, LONG)); extern VOID __stdargs SetDevGads __ARGS((VOID)); /* Extern DATA from fsdata.c */ #ifdef STANDALONE extern struct TextFont *FSTextFont; extern struct TextAttr Def8Text; #else extern struct TextFont Def8TextData; #endif extern BPTR FSLock; extern BYTE *fserrmsgs[]; extern BYTE *FSPathBuf; extern BYTE *OldFSPathBuf; extern BYTE fserrmsg22[]; extern BYTE fserrmsg24[]; extern BYTE fserrmsg27[]; extern BYTE fserrmsg28[]; extern BYTE fserrmsg29[]; extern BYTE FSIgnorePat[]; extern BYTE FSPatternUndoBuffer[]; extern BYTE FSWinTitleStr[]; extern BYTE FSwstr[]; extern BYTE RamDirNameStr[]; extern BYTE SplatStr[]; extern BYTE TimerName[]; extern struct DateStamp FSdirstamp; extern struct dev_node *lastdev; extern struct DosLibrary *DOSBase; extern struct FileInfoBlock *FSFib; extern struct file_node *FSFileNodes[]; extern struct file_node *topfin; extern struct FSRequest *FSReq; extern struct Gadget FSFileGad; extern struct Gadget FSPathGad; extern struct Gadget FSSelectGad; extern struct Gadget FSUserGad; extern struct IntuiText FSCancelTxt; extern struct IntuiText FSFileTxt; extern struct IntuiText FSPathTxt; extern struct IntuiText FSSelectTxt; extern struct IntuiText FSUserTxt; extern struct List *devList; extern struct List *fnList; extern struct MsgPort *FSTimerPort; extern struct NewWindow FSnw; extern struct RastPort *FSRPort; extern struct StringInfo FSFileInfo; extern struct StringInfo FSPathInfo; extern struct StringInfo FSPatternInfo; extern struct timerequest *FSDelayReq; extern struct Window *FSWin; extern UBYTE FSFileLabelStr[]; extern UBYTE FSPathLabelStr[]; extern ULONG fscursecs, fscurmicros; extern ULONG fsoldsecs, fsoldmicros; extern ULONG FSSignal; extern ULONG FSSignalMask; extern ULONG FSUserSignal; extern UWORD fsflags; extern WORD FSCountDown; extern WORD fsdirlocked; extern WORD FSDone; extern WORD fsnumentries; extern WORD fsstartedstr; extern WORD fstitlelength; extern WORD fstitstatus; extern WORD fsvirgindir; /* Local CODE */ LONG CreateVBTimer __ARGS((BYTE *, struct MsgPort **, struct timerequest **)); LONG FSGetDevs __ARGS((VOID)); LONG FSGrabEntry __ARGS((VOID)); LONG FSLockDir __ARGS((VOID)); LONG FSTestOldLock __ARGS((VOID)); LONG InitFSVBDelay __ARGS((VOID)); LONG InitFSWindow __ARGS((VOID)); VOID AbortAsyncIO __ARGS((struct IORequest *)); VOID CheckFSIDCMP __ARGS((VOID)); VOID FreeFSVBDelay __ARGS((VOID)); VOID FreeVBTimer __ARGS((struct MsgPort **, struct timerequest **)); VOID __stdargs FSVBDelay __ARGS((ULONG)); LONG FileSelect __ARGS((struct FSRequest *)); /* -------------------------------------------------------------------- * FileSelect * -------------------------------------------------------------------- */ LONG FileSelect(fsrequest) struct FSRequest *fsrequest; { LONG i, status, newpat; ULONG signals; /* (Re)Initialize things */ FSReq = fsrequest; /* Init global filereq struct pointer */ /* Set pattern to match files */ newpat = 0; /* Assume no pattern changes at first */ FSPatternInfo.Buffer = (UBYTE *)fsrequest->matchpattern; FSPatternInfo.BufferPos = strlen(FSPatternInfo.Buffer); if (FSPatternInfo.Buffer[0] == 0) /* Put splat back if no matchpattern */ (VOID)strcpy(FSPatternInfo.Buffer, SplatStr); if (lstrcmp(FSPatternUndoBuffer, FSPatternInfo.Buffer) != 0) { safestrcpy(FSPatternUndoBuffer, FSPatternInfo.Buffer, (LONG)(MATCHSTRSIZE - 1)); newpat = 1; } /* Set pattern to ignore files */ if (lstrcmp(FSIgnorePat, fsrequest->ignorepattern) != 0) { safestrcpy(FSIgnorePat, fsrequest->ignorepattern, (LONG)(FILESTRSIZE - 1)); newpat = 1; } /* Update fsflags if FSReq->flags has changed, reset state if needed */ if (FSCheckFlagChange() != 0) newpat = 1; /* Set initial directory */ FSPathInfo.Buffer = (UBYTE *)fsrequest->dirname; FSPathInfo.BufferPos = strlen(FSPathInfo.Buffer); if (lstrcmp(FSPathInfo.Buffer, FSPathBuf) != 0) { fsvirgindir = 1; } /* Set initial filename */ FSFileInfo.Buffer = (UBYTE *)fsrequest->filename; FSFileInfo.BufferPos = strlen(FSFileInfo.Buffer); /* Open and initialize everything, start IDCMP processing */ status = InitFSWindow(); if (status != 0) { FSWinTitle(); /* Redisplay buffered data if still valid */ if (FSTestOldLock() != 0 && fsvirgindir <= 0) { if (newpat != 0) /* Pattern changed, but still have old data */ { FSMatchPattern(); } else /* Otherwise just redraw them from static data */ { FSSetFileGads(); FSDisableAllFGads(); } } FSDone = 0; while (FSDone == 0) { if (fsvirgindir != 0) { if (FSGrabEntry() == 0) goto FSFailed; signals = FSSignal | FSUserSignal; } else { signals = Wait((LONG)FSSignalMask); } if ((signals & FSUserSignal) != 0) { i = (FSReq->userfunc)(FSReq, FSWin); if (i != 0) fsvirgindir = 1; } if ((signals & FSSignal) != 0) CheckFSIDCMP(); } } /***********/ FSFailed: /***********/ if (FSRPort != 0) { FreeMem(FSRPort, (LONG)sizeof(struct RastPort)); FSRPort = 0; } #ifdef STANDALONE if (FSTextFont != 0) { CloseFont(FSTextFont); FSTextFont = 0; } #endif if (FSWin != 0) { FSReq->leftedge = FSWin->LeftEdge; FSReq->topedge = FSWin->TopEdge; CloseWindow(FSWin); FSWin = 0; } #ifdef STANDALONE FreeFSVBDelay(); #endif return(status); } /* -------------------------------------------------------------------- */ LONG InitFSWindow() { LONG i, xinc, xleft, xmax; struct Gadget *tgad; /* Initialize a timer device for delays */ #ifdef STANDALONE if (InitFSVBDelay() == 0) { return(0L); } #endif /* Initialize FSWin title string */ safestrcpy(FSWinTitleStr, FSReq->titlestr, 28L); (VOID)strcat(FSWinTitleStr, " "); fstitlelength = strlen(FSWinTitleStr); fserrmsgs[27] = FSReq->readingstr; fserrmsgs[28] = FSReq->sortingstr; fserrmsgs[22] = FSReq->emptydirstr; fserrmsgs[24] = FSReq->nomatchstr; fserrmsgs[29] = FSReq->selectfilestr; if (fserrmsgs[27] == 0) fserrmsgs[27] = fserrmsg27; if (fserrmsgs[28] == 0) fserrmsgs[28] = fserrmsg28; if (fserrmsgs[22] == 0) fserrmsgs[22] = fserrmsg22; if (fserrmsgs[24] == 0) fserrmsgs[24] = fserrmsg24; if (fserrmsgs[29] == 0) fserrmsgs[29] = fserrmsg29; if (FSReq->pathgadstr != 0) FSPathTxt.IText = (UBYTE *)FSReq->pathgadstr; else FSPathTxt.IText = FSPathLabelStr; if (FSReq->filegadstr != 0) FSFileTxt.IText = (UBYTE *)FSReq->filegadstr; else FSFileTxt.IText = FSFileLabelStr; /* Set our directory gadget names to whatever the user has out there */ if (devList == 0) /* If already set, don't reset */ { if (FSGetDevs() == 0) { return(0L); } SetDevGads(); } /* Set Select and Cancel gadget texts */ FSSelectTxt.IText = (UBYTE *)FSReq->selectstr; FSSelectTxt.LeftEdge = 37 - strlen(FSReq->selectstr) * 4; FSCancelTxt.IText = (UBYTE *)FSReq->cancelstr; FSCancelTxt.LeftEdge = 37 - strlen(FSReq->cancelstr) * 4; /* Center the Select, Cancel, and LastDir gadgets */ if (FSReq->specgadstr != 0) { FSnw.FirstGadget = &FSUserGad; FSUserTxt.IText = (UBYTE *)FSReq->specgadstr; FSUserTxt.LeftEdge = 37 - strlen(FSReq->specgadstr) * 4; xleft = 4; xmax = 4; xinc = 75; } else { FSnw.FirstGadget = &FSSelectGad; xleft = 38; xmax = 3; xinc = 95; } tgad = FSnw.FirstGadget; for (i = 0; i < xmax; i++) { tgad->LeftEdge = xleft + i * xinc; tgad = tgad->NextGadget; } /* Determine which screen to open the FileSelect Window on */ if (FSReq->userscreen == 0) { FSnw.Type = WBENCHSCREEN; FSnw.Screen = 0; } else { FSnw.Type = CUSTOMSCREEN; FSnw.Screen = FSReq->userscreen; } FSnw.LeftEdge = FSReq->leftedge; FSnw.TopEdge = FSReq->topedge; if (FSReq->windowflags != 0) FSnw.Flags = FSReq->windowflags; if ((FSWin = OpenWindow(&FSnw)) == 0) { return(0L); } else { /* Allocate/clone/initialize RastPort copy for rendering Text */ #ifdef STANDALONE if ((FSTextFont = OpenFont(&Def8Text)) == 0) return(0L); #endif if ((FSRPort = (struct RastPort *)AllocMem((LONG)sizeof(struct RastPort), 0L)) == 0) return(0L); CopyMem((BYTE *)FSWin->RPort, (BYTE *)FSRPort, (LONG)sizeof(struct RastPort)); #ifdef STANDALONE SetFont(FSRPort, FSTextFont); #else SetFont(FSRPort, &Def8TextData); #endif if (FSReq->initfunc != 0) (VOID)(FSReq->initfunc)(FSReq, FSWin); FSSignal = 1L << FSWin->UserPort->mp_SigBit; FSSignalMask = FSSignal; if (FSReq->userport != 0 && FSReq->userfunc != 0) { FSUserSignal = 1L << FSReq->userport->mp_SigBit; FSSignalMask |= FSUserSignal; } else FSUserSignal = 0; ScreenToFront(FSWin->WScreen); PrintIText(FSWin->RPort, &FSPathTxt, 4L, 125L); MyActivateGad(&FSFileGad, FSWin); FSCountDown = 0; return(1L); } } /* -------------------------------------------------------------------- */ LONG CreateVBTimer(name, pport, ptreq) BYTE *name; struct MsgPort **pport; struct timerequest **ptreq; { if ((*pport = CreatePort(name, 0L)) != 0) { if ((*ptreq = (struct timerequest *)CreateExtIO(*pport, (LONG)sizeof(struct timerequest))) != 0) { if (OpenDevice(TimerName, (LONG)UNIT_VBLANK, (struct IORequest *)*ptreq, 0L) == 0) { return(1L); } } } return(0L); } /* -------------------------------------------------------------------- * Initialize a VBLANK timer for scroll arrow timings * -------------------------------------------------------------------- */ LONG InitFSVBDelay() { return(CreateVBTimer(0L, &FSTimerPort, &FSDelayReq)); } /* -------------------------------------------------------------------- * Free above timer. * -------------------------------------------------------------------- */ VOID FreeFSVBDelay() { FreeVBTimer(&FSTimerPort, &FSDelayReq); } /* -------------------------------------------------------------------- */ VOID FreeVBTimer(pport, ptreq) struct MsgPort **pport; struct timerequest **ptreq; { struct timerequest *treq; if (*pport != 0) { if ((treq = *ptreq) != 0) { if (treq->tr_node.io_Device != 0) { AbortAsyncIO((struct IORequest *)treq); CloseDevice((struct IORequest *)treq); } DeleteExtIO((struct IORequest *)treq); *ptreq = 0; } DeletePort(*pport); *pport = 0; } } /* -------------------------------------------------------------------- */ VOID __stdargs FSVBDelay(timedelay) ULONG timedelay; { FSDelayReq->tr_node.io_Command = TR_ADDREQUEST; FSDelayReq->tr_time.tv_micro = timedelay * 20000; FSDelayReq->tr_time.tv_secs = 0; (VOID)DoIO((struct IORequest *)FSDelayReq); } /* -------------------------------------------------------------------- * Clean out any pending async IO in a given IORequest type struct. * -------------------------------------------------------------------- */ VOID AbortAsyncIO(req) struct IORequest *req; { if (req->io_Command != 0 && CheckIO(req) == 0) { (VOID)AbortIO(req); (VOID)WaitIO(req); } } /* -------------------------------------------------------------------- */ LONG FSGrabEntry() { struct file_node *tnode; if (fsvirgindir > 0) /* Brand new list */ { fstitstatus = 27; /* Set our windowtitle to Reading */ FSWinTitle(); FreeAllFNodes(); /* Clean out old list */ FSSetKnob(); /* Show full height knob now */ FSDisableAllFGads(); if (FSLockDir() == 0) /* Try to lock the new path */ goto CrapOut1; /* Lock failed */ } if (fnList == 0) { if ((fnList = AllocMem ((LONG)sizeof(struct MinList), 0L)) == 0) goto CrapOut0; NewList (fnList); } if (FSGetNextFib() <= 0) /* Try to Examine entry */ goto CrapOut1; /* We are done!? */ /* Initialize new node */ if ((tnode = AllocFileNode()) == 0) goto CrapOut0; if (fsvirgindir > 0) /* New list, needs new head! */ fsvirgindir = -1; /* Still TRUE, but avoid relocking dir */ /* Fill in the info */ FillFileNode(tnode); return(1L); CrapOut0: FreeFileSelect(); fstitstatus = 26; FSWinTitle(); return(0L); CrapOut1: if ((fsflags & FS_DELAYED_SORT) == 0) FSUpdateSort(); if (fsnumentries > 10 && (fsnumentries & 0x01) != 0) FSResetKnob(); fsvirgindir = 0; FSClearLock(); FSWinTitle(); return(1L); } /* -------------------------------------------------------------------- */ LONG FSLockDir() { LONG namlen; struct CommandLineInterface *thiscli; struct Process *thisproc; struct Window *oldwin; UBYTE *tstr; /* Inhibit System Requesters */ thisproc = (struct Process *)FindTask(0L); oldwin = (struct Window *)thisproc->pr_WindowPtr; thisproc->pr_WindowPtr = (APTR)-1L; /* Backup last locked pathname and set new pathname */ (VOID)strcpy(OldFSPathBuf, FSPathBuf); (VOID)strcpy(FSPathBuf, FSPathInfo.Buffer); /* Make sure we release previous lock */ FSClearLock(); /* Allocate a fileinfoblock, if we have to */ if (AllocFSFib() == 0) { fstitstatus = 26; goto SNAFUDIR; } /* Lock new path */ locknewpath: if (FSPathBuf[0] != 0) /* Path is named, no guesswork */ { FSPutPath(); if ((FSLock = (BPTR)Lock(FSPathBuf, (LONG)ACCESS_READ)) == 0) { fstitstatus = ioerrnum(IoErr()); goto SNAFUDIR; } fsdirlocked = 1; /* Got a live one here! */ } else /* Use current directory */ { if (thisproc->pr_CurrentDir == 0) { fstitstatus = 3; goto SNAFUDIR; } FSLock = (BPTR)thisproc->pr_CurrentDir; fsdirlocked = 0; } /* Get a FileInfoBlock for this lock */ if (Examine((BPTR)FSLock, FSFib) == 0) { fstitstatus = ioerrnum(IoErr()); goto SNAFUDIR; } else { if (FSFib->fib_DirEntryType < 0) { fstitstatus = 2; goto SNAFUDIR; } } /* Copy DateStamp for later comparison */ FSdirstamp = FSFib->fib_Date; if (FSPathBuf[0] == (BYTE)0) /* Try to extract pathname from AmigaDOS */ { if (thisproc->pr_CLI != 0) /* is this a CLI? */ { thiscli = (struct CommandLineInterface *)((ULONG)thisproc->pr_CLI << 2L); tstr = (UBYTE *)((ULONG)thiscli->cli_SetName << 2L); namlen = (LONG)*tstr; safestrcpy(FSPathBuf, (BYTE *)((ULONG)tstr + 1L), (LONG)namlen); } else /* must be WorkBench, use Fib name */ { MakePathString((struct FileLock *)FSLock, FSPathBuf); } /* Copy path to StringInfo buffer, display */ (VOID)strcpy(FSPathInfo.Buffer, FSPathBuf); FSPutPath(); } thisproc->pr_WindowPtr = (APTR)oldwin; return(1L); /* In case of dire directory problem */ SNAFUDIR: thisproc->pr_WindowPtr = (APTR)oldwin; return(0L); } /* -------------------------------------------------------------------- * Called when diskremoved, to see if the disk we are displaying has * changed and needs to be re-read. * -------------------------------------------------------------------- */ LONG FSTestOldLock() { LONG locked; LONG status, oldtitstatus; struct FileInfoBlock *fib; struct FileLock *flock = 0; struct Process *proc; struct Window *oldwin; status = 0; locked = 0; oldtitstatus = fstitstatus; proc = (struct Process *)FindTask(0L); oldwin = (struct Window *)proc->pr_WindowPtr; proc->pr_WindowPtr = (APTR)-1L; /* Allocate a fileinfoblock */ if ((fib = (struct FileInfoBlock *)AllocMem((LONG)sizeof(struct FileInfoBlock), MEMF_CLEAR)) == 0) { fstitstatus = 26; goto BadLock; } /* Try to lock path */ if (FSPathBuf[0] != 0) /* Path is named, no guesswork */ { if ((flock = (struct FileLock *)Lock(FSPathBuf, (LONG)ACCESS_READ)) == 0) { fstitstatus = ioerrnum(IoErr()); goto BadLock; } locked = 1; } else /* Use current directory */ flock = (struct FileLock *)proc->pr_CurrentDir; /* Examine the root block */ if (Examine((BPTR)flock, fib) == 0) { fstitstatus = ioerrnum(IoErr()); goto BadLock; } else { if (fib->fib_DirEntryType < 0) { fstitstatus = 3; goto BadLock; } } if (FSdirstamp.ds_Days == fib->fib_Date.ds_Days && FSdirstamp.ds_Minute == fib->fib_Date.ds_Minute && FSdirstamp.ds_Tick == fib->fib_Date.ds_Tick) status = 1; else status = 0; /* In case of dire directory problem */ BadLock: proc->pr_WindowPtr = (APTR)oldwin; if (locked != 0) { UnLock((BPTR)flock); } if (fib != 0) { FreeMem(fib, (LONG)sizeof(struct FileInfoBlock)); } if (status == 0) { fsvirgindir = 1; FSdirstamp.ds_Days = FSdirstamp.ds_Minute = FSdirstamp.ds_Tick = 0; if (fstitstatus != oldtitstatus) FSWinTitle(); } return(status); } /* -------------------------------------------------------------------- * Constructs a circular doubly-linked list of device name nodes * -------------------------------------------------------------------- */ LONG FSGetDevs() { LONG blen; LONG ramflag = 0; /* Flag whether RAM: device found */ struct DeviceNode *dn; struct dev_node *tnode; struct DosInfo *di; struct RootNode *root; UBYTE *bstring; /* Allocate a MinList for use */ if (devList == 0) { if ((devList = AllocMem((LONG)sizeof(struct MinList), 0L)) == 0) return (0L); } NewList (devList); /* Grab pointer to DosInfo device root */ root = (struct RootNode *)DOSBase->dl_Root; di = (struct DosInfo *)BADDR(root->rn_Info); dn = (struct DeviceNode *) BADDR(di->di_DevInfo); /* Don't let other processes muck with us during this sneaky stuff */ Forbid(); /* Starting with root devinfo, set devnames till out of devices */ for (; dn != 0; dn = (struct DeviceNode *)BADDR(dn->dn_Next)) { /* Found a device? */ if ((dn->dn_Type == 0) && (dn->dn_Task != 0) && (dn->dn_Name != 0)) { if ((tnode = AllocDevNode()) != 0) /* Try to allocate a node */ { bstring = (UBYTE *)BADDR(dn->dn_Name); /* Pointer to BSTR name */ blen = (LONG)bstring[0]; /* Length of BSTR */ CopyMem((BYTE *)(bstring + 1), tnode->name, (LONG)blen); bstring = tnode->name; bstring[blen] = ':'; /* Append a colon to copy of name */ if (lstrcmp(bstring, RamDirNameStr) == 0) ramflag = 1; AddHead(devList, (struct Node *)tnode); } else /* Can't allocate a node, free 'em all and crap out */ { Permit(); FreeAllDNodes(); return(0L); } } } Permit(); if (ramflag == 0) /* Ram device wasn't out there, add it to list */ { if ((tnode = AllocDevNode()) == 0) { FreeAllDNodes(); return(0L); } (VOID)strcpy((BYTE *)tnode->name, RamDirNameStr); AddHead(devList, (struct Node *)tnode); } lastdev = tnode; /* This is the first node, start display with this */ return(1L); } /* -------------------------------------------------------------------- */ VOID CheckFSIDCMP() { BYTE *tstr1, *tstr2; LONG my; struct Gadget *tgadget; struct IntuiMessage *imsg; ULONG class, qualifier; ULONG code; ULONG secs, micros; while ((imsg = (struct IntuiMessage *)GetMsg(FSWin->UserPort)) != 0) { class = imsg->Class; qualifier = imsg->Qualifier; code = imsg->Code; micros = imsg->Micros; secs = imsg->Seconds; my = imsg->MouseY; tgadget = (struct Gadget *)imsg->IAddress; ReplyMsg((struct Message *)imsg); switch (class) { case INTUITICKS: CheckFSArrows(); break; case RAWKEY: switch (code) { case 0x45: /* Escape */ FSDone = 1; FSReq->fullname[0] = (BYTE)0; break; case 0x4c: /* Up cursor */ FSScrollFileGads(1L); break; case 0x4d: /* Down cursor */ FSScrollFileGads(0L); break; } break; case MOUSEBUTTONS: if (code == SELECTDOWN) { if (fsstartedstr != 0) FSEndString(); } else if (code == MENUUP) { if (fsstartedstr != 2) MyActivateGad(&FSPathGad, FSWin); else MyActivateGad(&FSFileGad, FSWin); } break; case GADGETDOWN: if (fsstartedstr != 0) { FSEndString(); } code = tgadget->GadgetID; switch (code) { case 10: /* Alpha */ case 11: /* Size */ case 12: /* Time */ FSDoSortGadget((LONG)code - 10); break; case 30: /* FSPatternGad */ fsstartedstr = 3; break; case 31: /* FSFileGad */ fsstartedstr = 1; break; case 32: /* FSPathGad */ fsstartedstr = 2; break; case 33: /* SlideGad */ case 40: /* Up Arrow */ case 41: /* Down Arrow */ case 42: /* Up Device */ case 43: /* Down Device */ FSStartScrollGad(code); break; case 50: /* FSFileGad0 */ code = (my - 12) / 11; if (FSFileNodes[code] != 0) { fscursecs = secs; fscurmicros = micros; HCompEntry(code); FSVBDelay(5L); HCompEntry(code); FSDoFileGad((LONG)my); fsoldsecs = secs; fsoldmicros = micros; } break; } break; case GADGETUP: code = tgadget->GadgetID; if (fsstartedstr != 0) { if ((qualifier & 0x0003) != 0) { if (fsstartedstr == 1) { MyActivateGad(&FSPathGad, FSWin); } else { MyActivateGad(&FSFileGad, FSWin); } code = 100; } else { if (fsstartedstr == 1) { if ((tstr1 = myrindex(FSFileInfo.Buffer, (LONG)'/')) != 0) { *tstr1 = '\x0'; tstr1++; (VOID)strcpy(FSwstr, tstr1); } else { if ((tstr2 = myrindex(FSFileInfo.Buffer, (LONG)':')) != 0) { tstr2++; (VOID)strcpy(FSwstr, tstr2); *tstr2 = (BYTE)0; } } if (tstr1 != 0 || tstr2 != 0) { (VOID)strcpy(FSPathInfo.Buffer, FSFileInfo.Buffer); (VOID)strcpy(FSPathBuf, FSFileInfo.Buffer); (VOID)strcpy(FSFileInfo.Buffer, FSwstr); FSFileInfo.BufferPos = strlen(FSFileInfo.Buffer); RefreshGList(&FSFileGad, FSWin, 0L, 2L); MyActivateGad(&FSFileGad, FSWin); fsvirgindir = 1; } } } fsstartedstr = 0; } FSDoGadget(code); break; case DISKREMOVED: case DISKINSERTED: if (fsvirgindir == 0) /* If the disk has stopped spinning... */ (VOID)FSTestOldLock(); /* See if we can lock our old place still */ break; } } }