/**************************************************************************** * * FileRequest() - File Name Requester * * By Kevin Lee Clague * 408 Tortolla Way * San Jose, Ca 95033 * 408-258-9891 work 408-737-5481 * * Copyright (C) 1986. All rights reserved. * * This program is freely distributable as long as this copyright notice * is retained. It intended for personal, non-commercial use. * * This file name requester is modeled after Deluxe Paints file name * requester. The dimensions/locations of all borders, gadgets and text were * arrived at empirically. Besides being a great program, Deluxe Paint is a * trade mark of Electronics Arts. * * The knowledge on how to get at the entries in the directories was drawn * from Mike (I'll be melow when I'm dead) Meyer's "Browser". * ***************************************************************************/ /*************************************************************************** * * Things to do: * 1. Dynamically allocate space for file name strings as they are gotten * from the disk, rather than static allocation of them in arrays. * 2. Fence off intuition events while getting file names from disk * directory (and put up the zz sleepy cloud in place of the arrow * mouse cursor.) * 3. Be a little more diligent with my use of RefreshGadgets. * ***************************************************************************/ #include "Requester.h" BOOL IsDir(); BOOL WaitRequester(); struct Requester FileRequester; UBYTE *FullPath; struct Window *window; struct IntuiMessage *message; struct FileInfoBlock FileInfo; USHORT FileCount; /* Number of files in current dir */ UBYTE FileListEntry[MAXFILES][40]; /* File (dir) names in current dir */ USHORT FirstFile; #define PATHNAMELEN 80 /**************************************************************************** * The Gadget String ***************************************************************************/ /****************************** * The File Name Gadget stuff * *****************************/ struct IntuiText FileText = { 0,1, JAM2, /* frontpen, packpen, drawmode */ -46,0, /* left,top */ NULL, /* font */ "File:", /* text */ NULL /* next */ }; UBYTE FileName[40]; UBYTE Backup[40]; struct StringInfo FileString = { &FileName, /* input buffer */ &Backup, /* undo buffer */ 0, /* Buffer position */ 32, /* buffer size */ 0, /* disp position*/ 0,0,0,0,0,NULL,0,NULL /* undo position*/ }; SHORT DrawerPoints[] = { -2, -2, 185,-2, 185,10, -2, 10, -2, -2 }; struct Border DrawerBorder = { 0,0, 0,1,JAM1, 5, &DrawerPoints[0], NULL }; struct Gadget FileGadget = { /* File string */ NULL, /* next gadget */ 67,113, /* location */ 185,8, GADGHCOMP, /* flags */ 0, /* activation */ STRGADGET|REQGADGET, /* type */ (APTR) &DrawerBorder, /* rendering */ NULL, /* rendering */ &FileText, /* text */ 0, /* mutual exlcude */ &FileString, /* string info */ NULL, /* gadget id */ NULL /* special info*/ }; /******************************** * The Drawer Name Gadget stuff * *******************************/ struct IntuiText DrawerText = { 0,1, JAM2, /* frontpen, packpen, drawmode */ -62,0, /* left,top */ NULL, /* font */ "Drawer:", /* text */ NULL /* next */ }; UBYTE DrawerName[40]; struct StringInfo DrawerString = { &DrawerName, /* input buffer */ &Backup, /* undo buffer */ 0, /* Buffer position */ 32, /* buffer size */ 0, /* disp position*/ 0,0,0,0,0,NULL,0,NULL /* undo position*/ }; struct Gadget DrawerGadget = { /* Drawer string */ &FileGadget, /* next gadget */ 67,98, /* location */ 185,8, GADGHCOMP, /* flags */ RELVERIFY, /* activation */ STRGADGET|REQGADGET, /* type */ (APTR) &DrawerBorder, /* rendering */ NULL, /* rendering */ &DrawerText, /* text */ 0, /* mutual exlcude */ &DrawerString, /* string info */ DRAWERGADGET, /* gadget id */ NULL /* special info*/ }; /**************************************** * The File list selection Gadget stuff * ***************************************/ UBYTE PickNames[8][40]; struct IntuiText FileList[] = { { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[0][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[1][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[2][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[3][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[4][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[5][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[6][0], /* text */ NULL /* next */ }, { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ &PickNames[7][0], /* text */ NULL /* next */ } }; struct Gadget FileListGadget[] = { { /* File name selection 0 */ &FileListGadget[1], /* next gadget */ 5,14, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[0], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE0GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 1 */ &FileListGadget[2], /* next gadget */ 5,24, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[1], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE1GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 2 */ &FileListGadget[3], /* next gadget */ 5,34, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[2], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE2GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 3 */ &FileListGadget[4], /* next gadget */ 5,44, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[3], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE3GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 4 */ &FileListGadget[5], /* next gadget */ 5,54, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[4], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE4GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 5 */ &FileListGadget[6], /* next gadget */ 5,64, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[5], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE5GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 6 */ &FileListGadget[7], /* next gadget */ 5,74, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[6], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE6GADGET, /* gadget id */ NULL /* special info*/ }, { /* File name selection 7 */ &DrawerGadget, /* next gadget */ 5,84, /* location */ 244,8, GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ NULL, /* rendering */ NULL, /* rendering */ &FileList[7], /* text */ 0, /* mutual exlcude */ NULL, /* string info */ FILE7GADGET, /* gadget id */ NULL /* special info*/ } }; /******************************** * The Load Button gadget stuff * *******************************/ SHORT ButtonPoints1[] = { -4, -4, 66, -4, 66, 12, -4, 12, -4, -4 }; struct Border ButtonBorder1 = { 0,0, 2,1,JAM1, 5, &ButtonPoints1[0], NULL }; SHORT ButtonPoints0[] = { -3, -2, 65, -2, 65, 10, -3, 10, -3, -2 }; struct Border ButtonBorder0 = { 0,0, 0,1,JAM1, 5, &ButtonPoints0[0], &ButtonBorder1 }; struct IntuiText LoadText = { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ NULL, /* text */ NULL /* next */ }; struct Gadget LoadGadget = { /* Load button */ &FileListGadget[0], /* next gadget */ 14,130, /* location */ 64,8, GADGHCOMP, /* flags */ GADGIMMEDIATE|ENDGADGET, /* activation */ BOOLGADGET|REQGADGET, /* type */ (APTR) &ButtonBorder0, /* rendering */ NULL, /* rendering */ &LoadText, /* text */ 0, /* mutual exlcude */ NULL, /* string info */ LOADGADGET, /* gadget id */ NULL /* special info*/ }; /********************************** * The Cancel Button gadget stuff * *********************************/ struct IntuiText CancelText = { 0,1, JAM2, /* frontpen, packpen, drawmode */ 0,0, /* left,top */ NULL, /* font */ "Cancel", /* text */ NULL /* next */ }; struct Gadget CancelGadget = { /* Cancel button */ &LoadGadget, /* next gadget */ 187,130, /* location */ 64,8, GADGHCOMP, /* flags */ GADGIMMEDIATE|ENDGADGET, /* activation */ BOOLGADGET|REQGADGET, /* type */ (APTR) &ButtonBorder0, /* rendering */ NULL, /* rendering */ &CancelText, /* text */ 0, /* mutual exlcude */ NULL, /* string info */ CANCELGADGET, /* gadget id */ NULL /* special info*/ }; /*********************************************** * The Scroll Selection List up (arrow) gadget * **********************************************/ UWORD UpArrowData[15] = { 0xfffc, 0xfcfc, 0xf87c, 0xf03c, 0xe01c, 0xc00c, 0x8004, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfffc }; struct Image UpArrow = { 0,0, 14, 14, 1, &UpArrowData[0], 0x1, 0x0, NULL }; struct Gadget UpGadget = { /* Up a file gadget */ &CancelGadget, /* next gadget */ 247,13, /* location */ 12,15, GADGIMAGE|GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ (APTR) &UpArrow, /* rendering */ NULL, /* rendering */ NULL, /* text */ 0, /* mutual exlcude */ NULL, /* string info */ UPGADGET, /* gadget id */ NULL /* special info*/ }; /************************************************* * The Scroll Selection List down (arrow) gadget * ************************************************/ UWORD DownArrowData[15] = { 0xfffc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0x8004, 0xc00c, 0xe01c, 0xf03c, 0xf87c, 0xfcfc, 0xfffc }; struct Image DownArrow = { 0,0, 14, 14, 1, &DownArrowData[0], 0x1, 0x0, NULL }; struct Gadget DownGadget = { /* Down a file gadget */ &UpGadget, /* next gadget */ 247,79, /* location */ 12,15, GADGIMAGE|GADGHNONE, /* flags */ GADGIMMEDIATE, /* activation */ BOOLGADGET|REQGADGET, /* type */ (APTR) &DownArrow, /* rendering */ NULL, /* rendering */ NULL, /* text */ 0, /* mutual exlcude */ NULL, /* string info */ DOWNGADGET, /* gadget id */ NULL /* special info*/ }; /*************************************************** * The Scroll Selection list up down Potentiometer * **************************************************/ struct PropInfo KnobInfo = { AUTOKNOB | FREEVERT | PROPBORDERLESS, 0, 0, /* VertPot */ 0, 0x7fff, /* VertBody */ 0,0,0,0,0,0 }; struct Image KnobImage = { 0,0, 0,0,0, NULL, 0,0, NULL }; struct Gadget PotGadget = { /* Potentiometer file gadget */ &DownGadget, /* next gadget */ 247,28, /* location */ 14,50, GADGHNONE, /* flags */ RELVERIFY, /* activation */ PROPGADGET|REQGADGET, /* type */ (APTR) &KnobImage, /* rendering */ NULL, /* rendering */ NULL, /* text */ 0, /* mutual exlcude */ &KnobInfo, /* string info */ POTGADGET, /* gadget id */ NULL /* special info*/ }; /*************************************************************************** * Other Requester structures * ***************************************************************************/ struct IntuiText HeadingText = { 2,1, JAM2, /* frontpen, packpen, drawmode */ 4,3, /* left,top */ NULL, /* font */ NULL, /* text */ NULL /* next */ }; SHORT Requester0Points[] = { 2,1, 261,1, 261,144, 2,144, 2,1 }; struct Border Requester0Border = { 0,0, 0,1,JAM1, 5, &Requester0Points[0], NULL }; SHORT Requester1Points[] = { 2,12, 261,12 }; struct Border Requester1Border = { 0,0, 0,1,JAM1, 2, &Requester1Points[0], &Requester0Border }; SHORT Requester2Points[] = { 2,93, 261,93 }; struct Border Requester2Border = { 0,0, 0,1,JAM1, 2, &Requester2Points[0], &Requester1Border }; SHORT Requester3Points[] = { 246,12, 246,93, 246,78, 261,78, 261,27, 247,27 }; struct Border Requester3Border = { 0,0, 0,1,JAM1, 6, &Requester3Points[0], &Requester2Border }; /**************************************************************************** * The Code part of the requester ***************************************************************************/ BOOL FileRequest(FileType,Action,FullName,ReqWindow) UBYTE *FileType; UBYTE *Action; UBYTE *FullName; struct Window *ReqWindow; { UBYTE *StrPtr; BOOL RetCode; window = ReqWindow; /* make pointer to window and name global */ FullPath = FullName; HeadingText.IText = FileType; /* Center requester title */ HeadingText.LeftEdge = (256-IntuiTextLength(&HeadingText))/2; LoadText.IText = Action; InitFNR(); /* Separate the path from the file name. Set the file name in the gadget */ if (StrPtr = rindex(FullName,'/')) { strcpy(FileString.Buffer,StrPtr + 1); *StrPtr = '\0'; } else if (StrPtr = rindex(FullName,':')) { strcpy(FileString.Buffer,StrPtr + 1); *(StrPtr+1) = '\0'; } else { *FileString.Buffer = '\0'; *DrawerString.Buffer = '\0'; *FullName = '\0'; } /* Separate the last dir in path and put it in drawer gadget */ if (StrPtr = rindex(FullName,'/')) strcpy(DrawerString.Buffer,StrPtr + 1); else if (StrPtr = rindex(FullName,':')) if (*(StrPtr+1)) strcpy(DrawerString.Buffer,StrPtr + 1); else strcpy(DrawerString.Buffer,FullName); else *DrawerString.Buffer = '\0'; /* Put up the requester and list the dir into it */ Request(&FileRequester,window); ListDir(FullName); SetNewFile(&FileGadget,FileString.Buffer); /* why do I have to do this? */ SetNewFile(&DrawerGadget,DrawerString.Buffer); RetCode = WaitRequester(); /* do everything till Cancel or Load */ /* Put file name and path back together */ if (FullName[strlen(FullName)-1] != ':') strcat(FullName,"/"); strcat(FullName,FileString.Buffer); return(RetCode); } /* LoadRequest */ /* * Init the file name requester */ InitFNR() { InitRequester(&FileRequester); FileRequester.LeftEdge = 6; FileRequester.TopEdge = 12; FileRequester.Width = 264; FileRequester.Height = 146; FileRequester.ReqGadget = &PotGadget; FileRequester.ReqText = &HeadingText; FileRequester.BackFill = 1; FileRequester.Flags = 0; FileRequester.ReqBorder = &Requester3Border; } /* InitFNR */ /* * WaitRequester - List dirs, scroll, and set drawer and file strings until * one of the LOAD(SAVE) or CANCEL buttons pushed. */ BOOL WaitRequester() { ULONG class = GADGETDOWN; USHORT choice = CANCELGADGET; struct Gadget *gadget; while (class != REQCLEAR) { if ((message=(struct IntuiMessage *) GetMsg(window->UserPort)) == 0L) { Wait(1L<UserPort->mp_SigBit); continue; } class = message->Class; gadget = (struct Gadget *) message->IAddress; ReplyMsg(message); switch (class) { case GADGETDOWN: switch (gadget->GadgetID >> CLASSBITS) { case UPDOWNCLASS: ScrollList(gadget); /* scroll up/down 1 file */ break; case CHOICECLASS: /* set the name in string gads */ if (IsDir(gadget->GadgetText->IText)) SetNewDrawer(&DrawerGadget,gadget->GadgetText->IText); else SetNewFile(&FileGadget,gadget->GadgetText->IText); break; case BUTTONCLASS: /* LOAD or CANCEL */ choice = gadget->GadgetID & GADGETNUM; } case GADGETUP: switch (gadget->GadgetID >> CLASSBITS) { case UPDOWNCLASS: /* Potentiometer scroll */ PotScrollList(gadget); break; case STRINGCLASS: /* They typed drawer name in */ ThrowTrailing(DrawerString.Buffer); strcpy(FullPath,DrawerString.Buffer); SetNewFile(&FileGadget,""); ListDir(DrawerString.Buffer); } } } return(choice==LOAD); } /* WaitRequester */ /* * SetNewDrawer - Used Mouse to pick directory from selection list gadgets. */ SetNewDrawer(Gadget,Text) struct Gadget *Gadget; UBYTE *Text; { SetNewFile(&FileGadget,""); /* clear file name string */ SetNewFile(Gadget,Text); /* set new drawer into gadget */ if (FullPath[strlen(FullPath)-1] != ':') /* make new path */ strncat(FullPath,"/",PATHNAMELEN); strncat(FullPath,Text,PATHNAMELEN); ListDir(FullPath); /* List new files into Sel List */ } /* SetNewDrawer */ /* * SetNewFile - Have to remove gadgets change strings and add them */ SetNewFile(Gadget,Text) struct Gadget *Gadget; UBYTE *Text; { USHORT Pos, RemoveGadget(); if (Text[0] != ' ') { Pos = RemoveGadget(window,Gadget); ThrowTrailing(Text); /* get rid of trailing blanks */ strcpy(Gadget->SpecialInfo->Buffer,Text); AddGadget(window,Gadget,Pos); RefreshGadgets(&DownGadget,window,&FileRequester); } } /* SetNewFile */ /* * ListDir - List the directory into array of string names. */ ListDir(dir) char *dir; { struct FileLock *my_lock, *Lock() ; FileCount = 0; FirstFile = 0; if ((my_lock = Lock(dir, ACCESS_READ)) != NULL) { if (Examine(my_lock, &FileInfo)) { ExNext(my_lock, &FileInfo); while (IoErr() != ERROR_NO_MORE_ENTRIES && FileCount < MAXFILES) { strcpy(&FileListEntry[FileCount][0], FileInfo.fib_FileName); if (FileInfo.fib_DirEntryType > 0) strcat(&FileListEntry[FileCount][0]," (dir)"); FileCount++; ExNext(my_lock, &FileInfo); } UnLock(my_lock) ; } } AttachList(FirstFile); if (FileCount > 8) ModifyProp(&PotGadget,window,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,0,0,0xffff/(FileCount-6)*8); else ModifyProp(&PotGadget,window,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,0,0,0xffff); } /* ListDir */ /* * AttachList - Attach list of file (directory) names to Selection gadgets */ AttachList(Start) USHORT Start; { USHORT Gadget; USHORT Pos, RemoveGadget(); for (Gadget = 0; Gadget <= 7 && Gadget+Start < FileCount; Gadget++) { Pos = RemoveGadget(window,&FileListGadget[Gadget]); strcpy(FileList[Gadget].IText,&FileListEntry[Start + Gadget][0]); strncat(FileList[Gadget].IText," ",24-strlen(FileList[Gadget].IText)); AddGadget(window,&FileListGadget[Gadget],Pos); } for (; Gadget <= 7; Gadget++) { Pos = RemoveGadget(window,&FileListGadget[Gadget]); strncpy(FileList[Gadget].IText," ",24); AddGadget(window,&FileListGadget[Gadget],Pos); } RefreshGadgets(&DownGadget,window,&FileRequester); } /* AttachList */ /* * ScrollList - Scroll the list up or down 1 file if possible */ ScrollList(gadget) struct Gadget *gadget; { ULONG VertPot = 0; switch(gadget->GadgetID & GADGETNUM) { case DOWN: if (FileCount > FirstFile + 8) ++FirstFile; break; case UP: if (FirstFile > 0) --FirstFile; } if (FileCount > 8) VertPot = 0xffff/(FileCount-6)*FirstFile; ModifyProp(&PotGadget,window,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,VertPot,0,KnobInfo.VertBody); AttachList(FirstFile); } /* ScrollList */ /* * PotScrollList - Calculate the file number from Pot value and attach * names to Selector List gadgets. */ PotScrollList(gadget) struct Gadget *gadget; { switch (gadget->GadgetID & GADGETNUM) { case POT: FirstFile = (FileCount-6)*KnobInfo.VertPot >> 16; AttachList(FirstFile); } } /* PotScrollList */ /* * IsDir - Simple minded routine to find " (dir)" in file name */ BOOL IsDir(Name) UBYTE *Name; { UBYTE *Dir; if (Dir = rindex(Name,'(')) if (strcmp(Dir,"(dir)")) { Dir[0] = '\0'; ThrowTrailing(Name); return(TRUE); } else return(FALSE); else return(FALSE); } /* IsDir */ /* * ThrowTrailing - Remove trailing blanks from string */ ThrowTrailing(String) UBYTE *String; { SHORT I; I = strlen(String) - 1; while (String[I] == ' ' && I > 0) String[I--] = '\0'; } /* ThrowTrailing */