page@swan.ulowell.edu (Bob Page) (10/25/88)
Submitted-by: dillon@cory.berkeley.edu (Matt Dillon) Posting-number: Volume 2, Issue 19 Archive-name: dos/fs/files12.1 # This is a shell archive. Remove anything before this line # then unpack it by saving it in a file and typing "sh file" # (Files unpacked will be owned by you and have default permissions). # This archive contains the following files: # Makefile # README # TODO # filereq.c # files.c # files.h # gadget.c # main.c # memory.c # menu.c # newwildcmp.c # if `test ! -s Makefile` then echo "writing Makefile" cat > Makefile << '\Rogue\Monster\' # Makefile # # -include:local must exist and my support library too SYMS= include:symbols.m SYMC= include:local/makesymbols.c CFLAGS= +L +I$(SYMS) DEST= srcc:files SR1 = main.c SR2 = gadget.c SR3 = menu.c SR4 = files.c SR5 = memory.c SR6 = newwildcmp.c SR7 = filereq.c OB1 = T:main.o OB2 = T:gadget.o OB3 = T:menu.o OB4 = T:files.o OB5 = T:memory.o OB6 = T:newwildcmp.o OB7 = T:filereq.o SRCS= $(SR1) $(SR2) $(SR3) $(SR4) $(SR5) $(SR6) $(SR7) OBJS= $(OB1) $(OB2) $(OB3) $(OB4) $(OB5) $(OB6) $(OB7) $(DEST): $(SYMS) $(OBJS) ln +Q $(OBJS) -lsup32 -lc32 -o $(DEST) $(OB1): $(SR1) cc $(CFLAGS) $(SR1) -o $(OB1) $(OB2): $(SR2) cc $(CFLAGS) $(SR2) -o $(OB2) $(OB3): $(SR3) cc $(CFLAGS) $(SR3) -o $(OB3) $(OB4): $(SR4) cc $(CFLAGS) $(SR4) -o $(OB4) $(OB5): $(SR5) cc $(CFLAGS) $(SR5) -o $(OB5) $(OB6): $(SR6) cc $(CFLAGS) $(SR6) -o $(OB6) $(OB7): $(SR7) cc $(CFLAGS) $(SR7) -o $(OB7) $(SYMS): $(SYMC) make -f include:local/Makefile \Rogue\Monster\ else echo "will not over write Makefile" fi if [ `wc -c Makefile | awk '{printf $1}'` -ne 977 ] then echo `wc -c Makefile | awk '{print "Got " $1 ", Expected " 977}'` fi if `test ! -s README` then echo "writing README" cat > README << '\Rogue\Monster\' COMPILER NOTES: Be sure that you have working NewModifyProp() and AddGList() calls. Aztec 3.4a screwed up the library call sequence for these. The source requires my support library SUP32.LIB to compile, as well as a precompiled symbol table with all amiga includes (*/*.h), but not high level includes (*.h ... stdio, etc...). \Rogue\Monster\ else echo "will not over write README" fi if [ `wc -c README | awk '{printf $1}'` -ne 354 ] then echo `wc -c README | awk '{print "Got " $1 ", Expected " 354}'` fi if `test ! -s TODO` then echo "writing TODO" cat > TODO << '\Rogue\Monster\' -string gadget is 'invisible' -colon preceding the volume string gadget not lined up -shift click several files to select them, slide-clicking \Rogue\Monster\ else echo "will not over write TODO" fi if [ `wc -c TODO | awk '{printf $1}'` -ne 157 ] then echo `wc -c TODO | awk '{print "Got " $1 ", Expected " 157}'` fi if `test ! -s filereq.c` then echo "writing filereq.c" cat > filereq.c << '\Rogue\Monster\' /* * STDFILE -- Standard File Requestor. Version 2.0a 15 June 1987 * * AUTHOR -- Peter da Silva US (713) 497-4372 * * Reorganized by Matthew Dillon for use with * and ?. Added: * -device name in File string gadget transfered to directory * gadget without closing the window. * -bug when requesting volume ""... current directory lock would * get unlocked! * -additional intuitive features added * -coding reorganized * * Copyright (c) 1987 Peter da Silva, all rights reserved. * Changes (c)Copyright 1987 Matthew Dillon, all rights reserved. * * This module may be freely used in any product, commercial or * otherwise, provided credit is given for this module and * and provided this notice remains intact in the source. The * intent of this module is to provide a standard file requestor * such as is available on the Macintosh, in GEM on the IBM-PC * and Atari ST, and in the Microsoft Windows software on the * IBM-PC. The advantage this module has over other requestors * is that it minimises disk accesses: an important consideration * given the structure of AmigaDos directories. If you need to * modify it for your needs, by all means go ahead... but please * conform to the intent of this program as stated above. If you * have suggestions for improvements, by all means call me at * the number listed above. * * Enhancements in the current version: * * Gadgets now boxed. Display generally cleaned up. * * True "dictionary order" for searches. * * Default pattern can now be specified. Default file name now * specified in a single argument. * * Directories always match. * * Null pattern converted to "#?" universal wildcard. * * If you attempt to build a file name longer than 128 characters the * screen will flash and the operation will be aborted. * * "Volumes" gadget, using the device list code in "mounted". This * gadget brings up a list of all currently mounted volumes for * selection. Volumes leaves the directory specification intact, so * you can quickly return to where you left off. * * With these enhancements it is now possible to select any file on * any device without touching the keyboard. This is now release 2.0, * as it is significantly better than 1.0. * * Acknowledgements: * * Thanks to Jeff Lydiatt for the pattern matching code in PatMatch.c * Thanks to Jay Miner, =RJ= and the whole Amiga team for the Amiga * itself. * * Environment: * * IntuitionBase and GfxBase must be open. dos.library must be open * under the name "DosLibrary". Link with PatMatch.o and VolList.o. * * Usage: * * #define MAXFILENAME 128 * * int stdfile(title, default_file, default_pat, name); * char *title; * char *default_file; * char *default_pattern; * char name[MAXFILENAME]; * * +-----------------------------------+ * |o| Title ------------------- | | | title parameter, or "File Name" * |-----------------------------------| * | Directory: [ ] | Directory parameter, or current. * | File name: [ ] | Default parameter, or empty. * | Pattern: [ ] | Initially empty, if the user * | +-------------------------------+ | enters anything here it will * | | [Filename] | | | be used to select files. The * | | [Filename] | | | file display will also be empty * | | [Filename] |@@| | to start with to avoid excess * | | [Filename] |@@| | disk I/O. If the user selects * | | |@@| | here the directory will be * | | |@@| | scanned looking for files * | | | | | matching the specified pattern, * | | | | | or "*" if no pattern is given. * | | | | | * | +-------------------------------+ | ACCEPT returns 1. CANCEL * | [ACCEPT] [VOLUMES] [CANCEL] | or the close gadget return 0. * +-----------------------------------+ VOLUMES displays volume names. * * The number of filenames displayed is specified at compile time in the * constant MAXFILES. The maximum size of a filename is specified in the * constant MAXNAME. The parameter "Default file" will be broken into * directory and file parts. */ char *Copyright = "stdfile V2.0a. Copyright (c) 1987 Peter da Silva. All rights reserved."; #include <intuition/intuitionbase.h> #include <intuition/intuition.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <exec/memory.h> typedef unsigned char ubyte; typedef unsigned short uword; typedef unsigned long ulong; typedef struct FileInfoBlock FIB; typedef struct DeviceList DEVLIST; typedef struct DosLibrary DOSLIB; typedef struct DosInfo DOSINFO; typedef struct RootNode ROOTNODE; typedef struct IntuiMessage IMESS; extern void CalcPropGadget(); extern void ProcessFileName(); extern void *malloc(); extern void *GetMsg(); extern struct Window *OpenWindow(); #define MAXFILES 8 #define MAXNAME 32 #define MAXFULL (MAXNAME*4) /* SIZING PARAMS */ #define Z NULL #define INDENT 6 #define LEFTMAR (INDENT-1) #define BORDER 3 #define CHSIZ 8 #define HT CHSIZ #define BASELINE 6 /* GADGET BORDERS */ #define IN1 LEFTMAR+10*CHSIZ #define IN3 LEFTMAR+3 #define IN4 -(INDENT+6*CHSIZ+1) #define IN5 -(INDENT+CHSIZ*2) #define IN6 ((WINWD-WD6)/2) #define WD1 -(INDENT+IN1) #define WD3 (6*CHSIZ) #define WD4 (6*CHSIZ) #define WD5 (CHSIZ*2+2) #define WD6 (7*CHSIZ) #define TP1 (CHSIZ+BORDER) #define TP2 (TP1+HT+1) #define TP3 (TP2+HT+1) #define TP4 -(BORDER+HT4-1) #define TP5 (TP3+HT+BORDER) #define HT4 (HT+1) #define HT5 CHSIZ*MAXFILES+INDENT #define WINHT (TP5 + HT5 + (-TP4) + BORDER) #define WINWD (INDENT*4 + (MAXNAME+2)*CHSIZ) #define WININ (640-WINWD)/2 #define WINTP (200-WINHT)/2 #define HOMEX (INDENT+LEFTMAR) #define HOMEY (TP5+BORDER) #define LASTX (HOMEX+MAXNAME*CHSIZ) #define LASTY (HOMEY+MAXFILES*CHSIZ) #define BTP TP5 #define BIN LEFTMAR #define BWD (WINWD-INDENT-BIN) #define BHT (WINHT-BTP-(-TP4+BORDER+1)) #define SF GADGHCOMP|GRELWIDTH #define SEL SELECTED #define BF1 GADGHCOMP|GRELBOTTOM #define BF2 GADGHCOMP|GRELBOTTOM|GRELRIGHT #define PF GRELRIGHT #define SA RELVERIFY #define CEN STRINGCENTER #define BA RELVERIFY #define PA RELVERIFY #define SI(n) (APTR)&STD_String[n] #define G(n) &STD_Gadget[n] #define IMAG (APTR)&STD_Image #define PROP (APTR)&STD_Prop #define SG STRGADGET #define BG BOOLGADGET #define PG PROPGADGET #define FP AUTOBACKPEN #define BP AUTOFRONTPEN #define OKTEXT &STD_OK #define NOTEXT &STD_CANCEL #define VLTEXT &STD_VOLUME static int DoneFlag; #define DirName SBuffer[0] #define FileName SBuffer[1] #define PatName SBuffer[2] #define STRINGS 3 static UBYTE SBuffer[STRINGS][MAXFULL]; static UBYTE Undo[MAXFULL]; static struct StringInfo STD_String[STRINGS] = { {SBuffer[0],Undo,0,MAXFULL,0}, {SBuffer[1],Undo,0,MAXFULL,0}, {SBuffer[2],Undo,0,MAXFULL,0} }; static struct PropInfo STD_Prop = { AUTOKNOB|FREEVERT, 0, 0, 0, 0 }; static struct IntuiText STD_OK = { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"ACCEPT", Z }; static struct IntuiText STD_CANCEL = { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"CANCEL", Z }; static struct IntuiText STD_VOLUME = { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"VOLUMES", Z }; #define BUTTONS 3 #define BUTVEC 8 static SHORT butvecs[BUTTONS][BUTVEC*2] = { { -2, HT4, -2, -1, WD3+1,-1, WD3+1,HT4, -3, HT4, -3,-1, WD3+2,-1, WD3+2, HT4 }, { -2, HT4, -2, -1, WD4+1,-1, WD4+1,HT4, -3, HT4, -3,-1, WD4+2,-1, WD4+2, HT4 }, { -2, HT4, -2, -1, WD6+1,-1, WD6+1,HT4, -3, HT4, -3,-1, WD6+2,-1, WD6+2, HT4 } }; static struct Border ButBorder[BUTTONS] = { {0, 0, FP, BP, JAM1, BUTVEC, butvecs[0], NULL}, {0, 0, FP, BP, JAM1, BUTVEC, butvecs[1], NULL}, {0, 0, FP, BP, JAM1, BUTVEC, butvecs[2], NULL} }; #define BB(n) (APTR)&ButBorder[n] static struct Image STD_Image; #define DIRID 0 #define FILID 1 #define PATID 2 #define YESID 3 #define CANID 4 #define VOLID 5 #define BARID 6 #define GADGETS 7 static struct Gadget STD_Gadget[GADGETS] = { /*NEXT, LFT, TP,WDTH, H, FLAG, ACT, TYP, REND, Z, TXT, Z, SPEC, ID, Z */ { G(1), IN1,TP1, WD1,HT, SF, SA, SG, Z, Z, Z, Z, SI(0), 0, 0 }, { G(2), IN1,TP2, WD1,HT, SF|SEL, SA, SG, Z, Z, Z, Z, SI(1), 1, 0 }, { G(3), IN1,TP3, WD1,HT, SF, SA, SG, Z, Z, Z, Z, SI(2), 2, 0 }, { G(4), IN3,TP4, WD3,HT4,BF1, BA, BG,BB(0), Z, OKTEXT, Z, Z, 3, 0 }, { G(5), IN4,TP4, WD4,HT4,BF2, BA, BG,BB(1), Z, NOTEXT, Z, Z, 4, 0 }, { G(6), IN6,TP4, WD6,HT4,BF1, BA, BG,BB(2), Z, VLTEXT, Z, Z, 5, 0 }, { NULL, IN5,TP5, WD5,HT5,PF, PA, PG, IMAG, Z, Z, Z, PROP, 6, 0 } }; static struct NewWindow STD_NewWindow = { WININ, WINTP, WINWD, WINHT, -1, -1, REFRESHWINDOW|MOUSEBUTTONS|GADGETUP|CLOSEWINDOW, WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SIMPLE_REFRESH|ACTIVATE, G(0), NULL, (ubyte *)"File Name Requestor", NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN }; static struct Window *STD_Window; #define NVEC 6 static SHORT Vectors[NVEC*2] = { BIN+1, BTP, BIN+1, BTP+BHT, BIN+BWD, BTP+BHT, BIN+BWD, BTP, BIN, BTP, BIN, BTP+BHT }; static struct Border STD_FileBox = { 0, 0, FP, BP, JAM1, NVEC, Vectors, NULL }; static struct IntuiText STD_Text[3] = { { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Directory:", NULL }, { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"File Name:", NULL }, { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Pattern:", NULL } }; static OpenFileWindow() { extern struct IntuitionBase *IntuitionBase; int i; /* Rebuild gadget list */ STD_NewWindow.FirstGadget = &STD_Gadget[0]; for(i = 0; i < GADGETS; i++) STD_Gadget[i].NextGadget = (i==GADGETS-1)?(0):(&STD_Gadget[i+1]); for(i = 0; i < STRINGS; i++) { STD_String[i].BufferPos = strlen(SBuffer[i]); STD_String[i].DispPos = 0; } STD_Prop.VertBody = 0xFFFF; STD_Prop.VertPot = 0; if (!(STD_Window = OpenWindow(&STD_NewWindow))) return(0); /* This optional line will activate a string gadget */ if (IntuitionBase->LibNode.lib_Version > 32) ActivateGadget(G(1),STD_Window,0L); CalcPropGadget(); PaintFileWindow(); return (1); } static CloseFileWindow() { STD_NewWindow.LeftEdge = STD_Window->LeftEdge; STD_NewWindow.TopEdge = STD_Window->TopEdge; if (STD_Window) CloseWindow(STD_Window); } static int State; #define INITIAL 0 #define DIRECTORY 1 static PaintFileWindow() { DrawBorder(STD_Window->RPort, &STD_FileBox, 0, 0); PrintIText(STD_Window->RPort, &STD_Text[0], LEFTMAR, TP1); PrintIText(STD_Window->RPort, &STD_Text[1], LEFTMAR, TP2); PrintIText(STD_Window->RPort, &STD_Text[2], LEFTMAR, TP3); if (State == DIRECTORY) PrintFileNames(); } static int FirstFile; static int Selected; static int NumFiles; static struct dirent { struct dirent *nextfile; SHORT filetype; char *filename; } *NameList, **NameTable; #define FILETYPE 0 #define DIRTYPE 1 #define VOLTYPE 2 static PrintFileNames() { int i; for (i = 0; i < MAXFILES; ++i) { SetBPen(STD_Window->RPort, BP); SetAPen(STD_Window->RPort, BP); RectFill(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ, LASTX, HOMEY+(i+1)*CHSIZ); if (i+FirstFile < NumFiles) PrintName(i+FirstFile, i+FirstFile == Selected); } } static PrintName(file, hilite) int file; int hilite; { int i; i = file - FirstFile; Move(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ+BASELINE); if (hilite == 0) { SetBPen(STD_Window->RPort, BP); if(NameTable[file]->filetype == FILETYPE) SetAPen(STD_Window->RPort, FP); else SetAPen(STD_Window->RPort, 3); } else { SetAPen(STD_Window->RPort, BP); if(NameTable[file]->filetype == FILETYPE) SetBPen(STD_Window->RPort, FP); else SetBPen(STD_Window->RPort, 3); } Text(STD_Window->RPort, NameTable[file]->filename, strlen(NameTable[file]->filename)); } static void CalcPropGadget() { int VertPot, VertBody; if (State == INITIAL) return; if (NumFiles <= MAXFILES) { VertBody = 0xFFFF; VertPot = 0; FirstFile = 0; } else { VertBody = ((MAXFILES<<16)-1) / NumFiles; VertPot = 0; FirstFile = 0; } ModifyProp(&STD_Gadget[BARID], STD_Window, NULL, STD_Prop.Flags, 0, VertPot, 0, VertBody ); } static void CalcFilePosition() { short old_pos; if (State == INITIAL) return; old_pos = FirstFile; if (NumFiles<=MAXFILES) { FirstFile = 0; } else { int VertPot = STD_Prop.VertPot; FirstFile = ((VertPot+1)*(NumFiles-MAXFILES))>>16; } if (old_pos != FirstFile) PrintFileNames(); } FreeList(list) struct dirent *list; { struct dirent *ptr; while(list) { ptr = list->nextfile; if (list->filename) free(list->filename); free(list); list = ptr; } } static ReadNewDir() { struct dirent *NewList, **NewTable, *ptr; int NewCount; FIB *fib; BPTR dirlock; if (State != DIRECTORY) { NameTable = 0; NameList = 0; } if (DirName[0]) { dirlock = Lock(DirName, ACCESS_READ); } else { BPTR ram; if (ram = Lock("RAM:", ACCESS_READ)) { dirlock = CurrentDir(ram); CurrentDir(dirlock); dirlock = DupLock(dirlock); /* added */ UnLock(ram); } } if (!dirlock) return(0); if ((fib = (FIB *)malloc(sizeof(FIB))) == NULL) { UnLock(dirlock); return 0; } if (!Examine(dirlock, fib)) { UnLock(dirlock); free(fib); return 0; } if (fib->fib_DirEntryType < 0) { UnLock(dirlock); free(fib); return 0; } NewList = 0; NewCount = 0; while(ExNext(dirlock, fib)) { NewCount += 1; ptr = (struct dirent *)malloc(sizeof(struct dirent)); if (ptr == 0) { FreeList(NewList); UnLock(dirlock); free(fib); return(0); } ptr->nextfile = NewList; ptr->filetype = (fib->fib_DirEntryType<0)?FILETYPE:DIRTYPE; ptr->filename = malloc(strlen(fib->fib_FileName)+1); if (ptr->filename == 0) { FreeList(ptr); UnLock(dirlock); free(fib); return(0); } strcpy(ptr->filename, fib->fib_FileName); NewList = ptr; } free(fib); if (DirName[0]) UnLock(dirlock); NewTable = malloc(sizeof(struct dirent *) * NewCount); if (NewTable==0) { FreeList(NewList); return(0); } FreeList(NameList); NameList = NewList; if (NameTable) free(NameTable); NameTable = NewTable; if (PatName[0]==0) SetPatName("*"); State = DIRECTORY; Selected = -1; ReCalcPattern(); } static ReadVol() { struct dirent *NewList, **NewTable, *ptr; int NewCount; char name[MAXNAME]; if (State != DIRECTORY) { NameTable = 0; NameList = 0; } OpenVolList(); NewList = 0; NewCount = 0; while(ReadVolList(name)) { if (strcmp(name, "RAM Disk:") == 0) strcpy(name, "ram:"); NewCount += 1; ptr = (struct dirent *)malloc(sizeof(struct dirent)); if (ptr==0) { FreeList(NewList); return(0); } ptr->nextfile = NewList; ptr->filetype = VOLTYPE; ptr->filename = malloc(strlen(name)+1); if (ptr->filename == 0) { FreeList(ptr); return(0); } strcpy(ptr->filename, name); NewList = ptr; } CloseVolList(); NewTable = malloc(sizeof(struct dirent *)*NewCount); if (NewTable==0) { FreeList(NewList); return(0); } FreeList(NameList); NameList = NewList; if (NameTable) free(NameTable); NameTable = NewTable; if (PatName[0]==0) SetPatName("*"); State = DIRECTORY; Selected = -1; ReCalcPattern(); } /* this routine does a true dictionary search: * * Devs < devs but Devs > devices */ static table_compare(p1, p2) struct dirent **p1, **p2; { char *s1, *s2; char c1, c2; char firstdiff; s1 = (*p1)->filename; s2 = (*p2)->filename; firstdiff = 0; while(*s1 && *s2) { c1 = *s1++; c2 = *s2++; if (firstdiff==0) firstdiff = c1 - c2; if (c1 >= 'A' && c1 <= 'Z') c1 = c1+'@'; if (c2 >= 'A' && c2 <= 'Z') c2 = c2+'@'; if (c1 != c2) return c1 - c2; } return firstdiff; } static sort_table() { qsort(NameTable, NumFiles, sizeof(struct dirent *), table_compare); return 1; } static ReCalcPattern() { if (State != DIRECTORY) { ReadNewDir(); } else { struct dirent *ptr; if (!PatName[0]) SetPatName("*"); NumFiles = 0; for (ptr = NameList; ptr; ptr=ptr->nextfile) { /* Directories always match. Is this good? */ if (ptr->filetype == DIRTYPE || ptr->filetype == VOLTYPE || newwildcmp(PatName, ptr->filename)) { NameTable[NumFiles] = ptr; NumFiles++; } } sort_table(); CalcPropGadget(); Selected = -1; PrintFileNames(); } } static SetGadgetText(id, text) int id; char *text; { int position; position = RemoveGadget(STD_Window, G(id)); if (position != -1) { strcpy(SBuffer[id], text); STD_String[id].BufferPos = strlen(text); position = AddGadget(STD_Window, G(id), -1); if (position != -1) RefreshGadgets(G(id), STD_Window, NULL); } } static SetDirName(name) char *name; { char buffer[MAXFULL+1], *ptr; int index; char lastchar; /* Can't enter a file name too long. */ if (strlen(DirName) + strlen(name) + 1 > MAXFULL) { DisplayBeep(); return(0); } index = 0; lastchar = 0; for (ptr = (char *)DirName; *ptr; ptr++) buffer[index++] = lastchar = *ptr; if (lastchar != ':' && lastchar != 0) buffer[index++] = '/'; strcpy(&buffer[index], name); SetGadgetText(DIRID, buffer); SetGadgetText(FILID, ""); return(1); } static SetFileName(name) char *name; { /* Can't enter a file name too long. */ if (strlen(DirName) + strlen(name) + 1 > MAXFULL) { DisplayBeep(); return(0); } SetGadgetText(FILID, name); return(1); } static SetPatName(name) char *name; { SetGadgetText(PATID, name); } static ProcessGadget(id) int id; { switch(id) { case DIRID: ReadNewDir(); break; case FILID: ProcessFileName(); break; case PATID: ReCalcPattern(); break; case BARID: CalcFilePosition(); break; case YESID: DoneFlag = 1; break; case CANID: DoneFlag = -1; break; case VOLID: ReadVol(); break; } } /* * ProcessFileName() added by Matthew Dillon. If the requested file is * actually a directory, do a ReadNewDir() instead of quiting. */ void ProcessFileName() { register char *ptr; register short len; BPTR fillock; char buf[128]; FIB *fib = (FIB *)malloc(sizeof(FIB)); if (fib == NULL) { DoneFlag = 1; return; } for (ptr = (char *)FileName; *ptr; ++ptr) { if (*ptr == ':') { DirName[0] = '\0'; break; } } strcpy(buf, DirName); if (FileName[0]) { if (len = strlen(buf)) { if (buf[len-1]!=':') strcat(buf, "/"); } strcat(buf, FileName); if (fillock = Lock(buf, ACCESS_READ)) { if (Examine(fillock, fib)) { if (fib->fib_DirEntryType > 0) { SetGadgetText(DIRID, buf); SetGadgetText(FILID, ""); ReadNewDir(); free(fib); UnLock(fillock); return; } } UnLock(fillock); } } free(fib); DoneFlag = 1; } static ProcessMouse(x, y, code, seconds, micros) { int NewSelected; static int oseconds = 0, omicros = 0; if (x < HOMEX || y < HOMEY || x >= LASTX || y >= LASTY) return; if ((code & SELECTUP) == SELECTUP) return; if (State != DIRECTORY) { ReadNewDir(); return; } NewSelected = (y-HOMEY)/CHSIZ + FirstFile; if (NewSelected == Selected) { if (Selected != -1) { if (DoubleClick(oseconds, omicros, seconds, micros)) { if (NameTable[Selected]->filetype == DIRTYPE) { if (SetDirName(NameTable[Selected]->filename)) ReadNewDir(); } else if (NameTable[Selected]->filetype == VOLTYPE) { SetGadgetText(DIRID, NameTable[Selected]->filename); SetGadgetText(FILID, ""); ReadNewDir(); } else if (!SetFileName(NameTable[Selected]->filename)) { Selected = -1; DoneFlag = 1; } } } } else { if (Selected != -1 && Selected >= FirstFile && Selected < FirstFile+MAXFILES) PrintName(Selected, 0); Selected = NewSelected; if (Selected >= NumFiles) { Selected = -1; } else { if (SetFileName(NameTable[Selected]->filename)) PrintName(Selected, 1); else Selected = -1; if (IntuitionBase->LibNode.lib_Version > 32) ActivateGadget(G(1),STD_Window,0L); } } oseconds = seconds; omicros = micros; } stdfile(title, deffile, defpat, name) char *title, *deffile, *defpat, *name; { IMESS *im; if(title) STD_NewWindow.Title = (UBYTE *)title; else STD_NewWindow.Title = (UBYTE *)"Enter File Name"; if (deffile) { int i; for (i = strlen(deffile)-1; i >= 0; --i) { if (deffile[i]==':' || deffile[i]=='/') { int hold; strcpy(FileName, &deffile[i+1]); if (deffile[i]==':') i++; hold = deffile[i]; deffile[i] = 0; strcpy(DirName, deffile); deffile[i] = hold; break; } } if (i < 0) { strcpy(FileName, deffile); DirName[0] = 0; } } else { DirName[0] = 0; FileName[0] = 0; } if (defpat) strcpy(PatName, defpat); else PatName[0] = 0; State = INITIAL; NameTable = 0; NameList = 0; if(!OpenFileWindow()) return(0); DoneFlag = 0; while (!DoneFlag) { Wait(1<<STD_Window->UserPort->mp_SigBit); while(im = GetMsg(STD_Window->UserPort)) { switch(im->Class) { case CLOSEWINDOW: DoneFlag = -1; break; case MOUSEBUTTONS: ProcessMouse(im->MouseX, im->MouseY, im->Code, im->Seconds, im->Micros); break; case GADGETUP: ProcessGadget(((struct Gadget *)im->IAddress)->GadgetID); break; case REFRESHWINDOW: BeginRefresh(STD_Window); PaintFileWindow(); EndRefresh(STD_Window, 1); break; } ReplyMsg(im); } } CloseFileWindow(); FreeList(NameList); if (NameTable) free(NameTable); if (DoneFlag == 1) { int len; strcpy(name, DirName); if (FileName[0]) { if (len = strlen(name)) { if (name[len-1]!=':') strcat(name, "/"); } strcat(name, FileName); return(1); } } return(0); } /* * VOLLIST.C */ #define toAPTR(b) ((b)<<2) #define toBPTR(a) ((a)>>2) struct DeviceList *list; OpenVolList() { extern DOSLIB *DOSBase; ROOTNODE *root; DOSINFO *info; root = (ROOTNODE *)DOSBase->dl_Root; info = (DOSINFO *)toAPTR(root->rn_Info); list = (DEVLIST *)toAPTR(info->di_DevInfo); } ReadVolList(name) char *name; { register DEVLIST *next; while(list) { next = (DEVLIST *)toAPTR(list->dl_Next); if (list->dl_Type == DLT_VOLUME) { char *ptr; int count; ptr = (char *)toAPTR((BPTR)list->dl_Name); count = *ptr++; if (count > 30) count = 30; strncpy(name, ptr, count); name[count++] = ':'; name[count] = 0; list = next; return(1); } list = next; } return(0); } CloseVolList() { } \Rogue\Monster\ else echo "will not over write filereq.c" fi if [ `wc -c filereq.c | awk '{printf $1}'` -ne 22956 ] then echo `wc -c filereq.c | awk '{print "Got " $1 ", Expected " 22956}'` fi if `test ! -s files.c` then echo "writing files.c" cat > files.c << '\Rogue\Monster\' /* * FILES.C * * File Manager! * * (c)Copyright 1987 Matthew Dillon, All Rights Reserved. */ #include "files.h" extern LOCK *Lock(); extern LOCK *ParentDir(), *CurrentDir(); extern void *malloc(); extern void addentry(); RECORD *Rbase; /* All entries */ RECORD *DisplayTop; /* Entry at the display top */ RECORD *Highlighted; /* Highlighted entry */ short MaxNameLen; long NumEntries; long NumSelected; long NumTop; long NewNumTop; FIB *Fib; short Modified; short Xs, Xe, Ys, Ye, Rows, Cols; char Title[80]; redisplay(newtop) { short i; short noscroll = 0; uword percent, fill; RECORD *rec; bigboxbounds(&Xs,&Xe,&Ys,&Ye); Rows = (Ye-Ys)/Rp->TxHeight; Cols = (Xe-Xs)/Rp->TxWidth; if (newtop) { long delta = NumTop - NewNumTop; if (delta < 0) delta = -delta; if (delta >= Rows) noscroll = 1; } while (DisplayTop && !(DisplayTop->flags & R_SELECTED)) DisplayTop = DisplayTop->next; if (newtop) { while (NewNumTop != NumTop && DisplayTop) { if (NewNumTop < NumTop) { do { DisplayTop = DisplayTop->prev; } while (DisplayTop && !(DisplayTop->flags & R_SELECTED)); --NumTop; if (DisplayTop && !noscroll) { ScrollRaster(Rp, 0, -Rp->TxHeight, Xs, Ys, Xe-1, Ye-1); displayat(DisplayTop, 0); } } else { do { DisplayTop = DisplayTop->next; } while (DisplayTop && !(DisplayTop->flags & R_SELECTED)); ++NumTop; if (DisplayTop && !noscroll) { ScrollRaster(Rp, 0, Rp->TxHeight, Xs, Ys, Xe-1, Ye-1); displayrow(Rows-1); } } } if (DisplayTop && !noscroll) return(0); } sprintf(Title, "%ld/%ld", NumSelected, NumEntries); title(Title); if (DisplayTop == NULL) { DisplayTop = Rbase; NumTop = 0; } if (!newtop) { percent = fill = 0xFFFF; if (NumSelected) { if (NumTop+(Rows>>1) > NumSelected) percent = 0xFFFF; else percent = (NumTop + (Rows>>1)) * 0xFFFF / NumSelected; fill = Rows * 0xFFFF / NumSelected; if (Rows > NumSelected) fill = 0xFFFF; } setslider(percent, fill); } SetAPen(Rp, 0); RectFill(Rp, Xs, Ys, Xe-1, Ye-1); SetAPen(Rp, 1); for (rec = DisplayTop, i = 0; rec && i < Rows; rec = rec->next) { if (!(rec->flags & R_SELECTED)) continue; displayat(rec, i); ++i; } } redisplayone(rec) RECORD *rec; { RECORD *nrec; short i; for (i = 0, nrec = DisplayTop; nrec && i < Rows; nrec = nrec->next) { if (!(nrec->flags & R_SELECTED)) continue; if (nrec == rec) break; ++i; } if (i < Rows && nrec == rec) { SetAPen(Rp, 0); RectFill(Rp, Xs, Ys + (Rp->TxHeight*i), Xe-1, Ys + (Rp->TxHeight*i) + Rp->TxHeight - 1); SetAPen(Rp, 1); displayat(rec, i); } } displayrow(row) { register RECORD *rec = DisplayTop; register short i = row; while (i && rec) { rec = rec->next; while (rec && !(rec->flags & R_SELECTED)) rec = rec->next; --i; } if (rec && row < Rows) displayat(rec, row); } displayat(rec, i) RECORD *rec; { short len; len = strlen(rec->name); if (len > Cols) len = Cols; if (rec == Highlighted) { SetAPen(Rp, 0); SetBPen(Rp, 1); } Move(Rp, Xs, Ys + (Rp->TxHeight*i) + Rp->TxBaseline); Text(Rp, rec->name, len); if (Cols > MaxNameLen && rec->comment) { len = strlen(rec->comment); if (len > Cols - MaxNameLen) len = Cols - MaxNameLen; Move(Rp, Xs + MaxNameLen * Rp->TxWidth, Ys + (Rp->TxHeight * i) + Rp->TxBaseline); Text(Rp, rec->comment, len); } if (rec == Highlighted) { SetAPen(Rp, 1); SetBPen(Rp, 0); } } bigboxhit(y, up) { RECORD *hl = Highlighted; short row; Highlighted = NULL; if (hl) redisplayone(hl); row = (y - Ys) / Rp->TxHeight; if (row >= Rows || Rows < 0) return(0); for (hl = DisplayTop; hl && !(hl->flags & R_SELECTED); hl = hl->next); while (hl && row) { if (hl->flags & R_SELECTED) --row; hl = hl->next; } for (; hl && !(hl->flags & R_SELECTED); hl = hl->next); if (Highlighted = hl) { redisplayone(hl); setcomment((hl->comment) ? hl->comment : ""); if (up) activate_com(); } } sliderhit() { uword pos, fill; getsliderpos(&pos, &fill); NewNumTop = pos * (NumSelected - Rows + 1) / 0xFFFF; redisplay(1); } /* * Add a disk volume to the list. Determine * the root and add entries beginning at the * specification. */ void add_volume(str) char *str; { LOCK *lock; char path[128]; int len; Highlighted = NULL; Fib = malloc(sizeof(FIB)); if (Fib == NULL) return; resetsort(); /* also cleans up the database */ path[0] = 0; if (lock = Lock(str, ACCESS_READ)) { if (Examine(lock, Fib)) { buildpath(lock, path); len = strlen(path); if (path[len-1] == ':' || path[len-1] == '/') { path[len] = '*'; path[len+1] = 0; select_pattern(path, 1); path[len] = 0; } Examine(lock, Fib); if (Fib->fib_DirEntryType < 0) { addentry(path, Fib->fib_Comment, Fib->fib_Size); } else { RECORD *base; /* find start of killpatterns, if any */ for (base = Rbase; base; base = base->next) { if (strcmp(base->name, KILLNAME) < 0) continue; break; } title("Wait.. Scanning"); scandir(lock, path, base); } title("Wait.. Update"); rem_selected(NULL, 1); } UnLock(lock); } free(Fib); strcat(path, "*"); title("Select path"); select_pattern(path, 0); } buildpath(lock, path) LOCK *lock; char *path; { LOCK *parent; short plen, nlen; plen = strlen(path); nlen = strlen(Fib->fib_FileName) + 1; if (nlen == 1) { /* RAM: */ strcpy(Fib->fib_FileName, "ram"); nlen = 4; } bmov(path, path + nlen, plen + 1); strcpy(path, Fib->fib_FileName); if (Fib->fib_DirEntryType >= 0) path[nlen-1] = '/'; if (parent = ParentDir(lock)) { if (Examine(parent, Fib)) { buildpath(parent, path); } UnLock(parent); } else { path[nlen-1] = ':'; } } scandir(lock, path, base) LOCK *lock; char *path; RECORD *base; { short restorelen = strlen(path); short len = restorelen; LOCK *olddirlock; if (path[restorelen-1] != ':' && path[restorelen-1] != '/') { strcpy(path + restorelen, "/"); ++len; } olddirlock = CurrentDir(lock); if (notkilled(path, base)) addentry(path, Fib->fib_Comment, Fib->fib_Size); while (ExNext(lock, Fib)) { strcpy(path+len, Fib->fib_FileName); if (Fib->fib_DirEntryType < 0) { if (notkilled(path, base)) addentry(path, Fib->fib_Comment, Fib->fib_Size); } else { LOCK *lock = Lock(Fib->fib_FileName, ACCESS_READ); if (lock) { FIB *oldfib = Fib; if (Fib = malloc(sizeof(FIB))) { Examine(lock, Fib); scandir(lock, path, base); UnLock(lock); free(Fib); } Fib = oldfib; } } } CurrentDir(olddirlock); path[restorelen] = 0; } notkilled(path,base) char *path; RECORD *base; { while (base && strcmp(base->name, KILLNAME) == 0) { if (base->comment && newwildcmp(base->comment, path)) return(0); base = base->next; } return(1); } load_database(fi) FILE *fi; { char name[132]; char comm[132]; char size[32]; fgets(name, 128, fi); /* # entries per item */ Highlighted = NULL; resetsort(); title("Wait... Loading"); while (fgets(name, 128, fi) && fgets(comm, 128, fi) && fgets(size, 32, fi)) { name[strlen(name)-1] = 0; /* remove newlines */ comm[strlen(comm)-1] = 0; addentry(name, comm, atoi(size)); } rem_selected(NULL, 1); selectall(); redisplay(0); } save_database(fi) FILE *fi; { RECORD *rec; char buf[32]; cleanup(); title("Saving..."); fputs("3\n", fi); for (rec = Rbase; rec; rec = rec->next) { fwrite(rec->name, strlen(rec->name), 1, fi); putc('\n', fi); if (rec->comment) fwrite(rec->comment, strlen(rec->comment), 1, fi); putc('\n', fi); sprintf(buf, "%ld\n", rec->bytes); fputs(buf, fi); if (ferror(fi)) break; } } selectall() { RECORD *rec; short len; Highlighted = NULL; DisplayTop = NULL; MaxNameLen = 0; for (rec = Rbase; rec; rec = rec->next) { if (rec->flags & R_KILLPAT) continue; len = strlen(rec->name); if (MaxNameLen <= len) MaxNameLen = len + 1; rec->flags |= R_SELECTED; } NumSelected = NumEntries; } select_pattern(str, noref) char *str; { register RECORD *rec; register short len; short which = 0; if (*str == '+') /* ADD selected patterns */ ++str, which = 1; if (*str == '-') /* REMOVE selected patterns*/ ++str, which = 2; DisplayTop = NULL; Highlighted= NULL; switch(which) { case 0: NumSelected = 0; MaxNameLen = 0; for (rec = Rbase; rec; rec = rec->next) { rec->flags &= ~R_SELECTED; if (rec->flags & R_KILLPAT) continue; if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) { if (noref) { rec->flags |= R_UPDATE; } else { rec->flags |= R_SELECTED; ++NumSelected; if ((len = strlen(rec->name)) >= MaxNameLen) MaxNameLen = len + 1; } } } break; case 1: for (rec = Rbase; rec; rec = rec->next) { if ((rec->flags & R_KILLPAT) || (rec->flags & R_SELECTED)) continue; if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) { rec->flags |= R_SELECTED; ++NumSelected; if ((len = strlen(rec->name)) >= MaxNameLen) MaxNameLen = len + 1; } } break; case 2: for (rec = Rbase; rec; rec = rec->next) { if (!(rec->flags & R_SELECTED)) continue; if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) { rec->flags &= ~R_SELECTED; --NumSelected; } } break; } if (!noref) redisplay(0); } /* * If onerec != NULL, remove the one record, * else remove all SELECTED records. */ rem_selected(onerec, noref) RECORD *onerec; { register RECORD *rec; register long len, maxlen; Highlighted = NULL; cleanup(); if (onerec) { if (onerec->flags & R_SELECTED) { onerec->flags &= ~R_SELECTED; --NumSelected; } onerec->flags |= R_KILLPAT; --NumEntries; } else { maxlen = 0; for (rec = Rbase; rec; rec = rec->next) { if (noref) { if (rec->flags & R_UPDATE) { rec->flags &= ~R_UPDATE; rec->flags |= R_KILLPAT; --NumEntries; } } else { if (rec->flags & R_SELECTED) { rec->flags &= ~R_SELECTED; rec->flags |= R_KILLPAT; --NumEntries; } } if (!(rec->flags & R_KILLPAT) && (len=strlen(rec->name)) > maxlen) maxlen = len; } if (!noref) NumSelected = 0; MaxNameLen = maxlen+1; } if (noref) cleanup(); else redisplay(0); } undo() { RECORD *rec; Highlighted = NULL; for (rec = Rbase; rec; rec = rec->next) { if (rec->flags & R_KILLPAT) { rec->flags &= ~R_KILLPAT; rec->flags |= R_SELECTED; ++NumSelected; ++NumEntries; if (strlen(rec->name) >= MaxNameLen) MaxNameLen = strlen(rec->name)+1; } } redisplay(0); } cleanup() { RECORD *rec, *nrec; for (rec = Rbase; rec; rec = nrec) { nrec = rec->next; if (rec->flags & R_KILLPAT) { if (rec == DisplayTop) DisplayTop = nrec; rmrecord(rec); } } } rmrecord(rec) RECORD *rec; { if (rec->flags & R_SOFTERR) { puts("panic: soft error"); exit(1); } if (rec->prev) rec->prev->next = rec->next; else Rbase = rec->next; if (rec->next) rec->next->prev = rec->prev; rec->flags |= R_SOFTERR; freestr(rec->name); freestr(rec->comment); freerecord(rec); } /* * modify the comment field for the highlighted * item. */ mod_comment(str) char *str; { if (Highlighted) { Modified = 1; freestr(Highlighted->comment); if (str[0]) { Highlighted->comment = allocstr(str); if (Highlighted->comment == NULL) title("OUT OF MEMORY!"); } else { Highlighted->comment = NULL; } redisplayone(Highlighted); } } static RECORD *Cache; resetsort() { cleanup(); Cache = Rbase; } void addentry(name, comm, size) char *name; char *comm; long size; { RECORD *rec; short n; Modified = 1; rec = allocrecord(); if (rec == NULL) { title("OUT OF MEMORY!"); return; } rec->name = allocstr(name); if (rec->name == NULL) { rmrecord(rec); title("OUT OF MEMORY!"); return; } rec->comment = NULL; if (strlen(comm)) { rec->comment = allocstr(comm); if (rec->comment == NULL) { freestr(rec->name); rmrecord(rec); title("OUT OF MEMORY!"); return; } } rec->bytes = size; if (Rbase == NULL) { Rbase = rec; rec->prev = NULL; rec->next = NULL; } else { short n = strcmp(name, Cache->name); if (n == 0 && strcmp(name, KILLNAME) == 0) n = 1; if (n < 0) { /* name < Cache, move backwards */ while ((Cache = Cache->prev) && (n=strcmp(name, Cache->name)) < 0); } else if (n > 0) { /* name > Cache, move forwards */ while (Cache->next && (n=strcmp(name, Cache->next->name)) > 0) Cache = Cache->next; if (Cache->next && n == 0) Cache = Cache->next; } if (Cache) { rec->next = Cache->next; /* insert after cache */ rec->prev = Cache; Cache->next = rec; } else { /* or at beginning */ rec->next = Rbase; rec->prev = NULL; Rbase = rec; } if (rec->next) rec->next->prev = rec; if (n == 0) { /* replace if exact */ if (Cache->comment) { char *swap = Cache->comment; Cache->comment = rec->comment; rec->comment = swap; Cache->flags |= R_UPDATE; } } } rec->flags = R_SELECTED; ++NumSelected; ++NumEntries; if (MaxNameLen <= strlen(rec->name)) MaxNameLen = strlen(rec->name) + 1; Cache = rec; } \Rogue\Monster\ else echo "will not over write files.c" fi if [ `wc -c files.c | awk '{printf $1}'` -ne 13874 ] then echo `wc -c files.c | awk '{print "Got " $1 ", Expected " 13874}'` fi if `test ! -s files.h` then echo "writing files.h" cat > files.h << '\Rogue\Monster\' /* * FILES.H * */ #include <stdio.h> #include <local/typedefs.h> #define GAD_INFO 1 #define GAD_DEL 2 #define GAD_UNDO 3 #define GAD_ALL 4 #define GAD_VOLUME 8 #define GAD_PATTERN 9 #define GAD_COMMENT 10 #define GAD_SLIDER 11 #define GAD_BIGBOX 12 #define MEN_SAVE 1 #define MEN_SAVEAS 2 #define MEN_LOAD 3 #define MEN_LOADEF 4 #define MEN_QUIT 5 #define MEN_KILLPAT 6 #define title(str) SetWindowTitles(Win,(str),NULL) #define KILLNAME "@@KILLPAT" #define RECORD struct _RECORD /* * Each record is stored in the following structure. */ #define R_SELECTED 0x01 /* A selected item */ #define R_KILLPAT 0x02 /* deleted item (undoable) */ #define R_UPDATE 0x04 /* flag delete (used for updating a volume) */ #define R_SOFTERR 0x08 /* software error if ever encountered! */ RECORD { RECORD *next; /* record list, doubly linked */ RECORD *prev; char *comment; /* comment */ char *name; /* entire file name */ long bytes; /* file size */ short flags; }; extern WIN *OpenWindow(); extern void *malloc(); extern void *GetMsg(); extern void *AllocMem(); extern RECORD *allocrecord(); extern char *allocstr(); extern RECORD *Rbase; extern RECORD *Highlighted; extern WIN *Win; extern RP *Rp; extern long NumEntries; extern short Modified; \Rogue\Monster\ else echo "will not over write files.h" fi if [ `wc -c files.h | awk '{printf $1}'` -ne 1405 ] then echo `wc -c files.h | awk '{print "Got " $1 ", Expected " 1405}'` fi if `test ! -s gadget.c` then echo "writing gadget.c" cat > gadget.c << '\Rogue\Monster\' /* * GADGET.C * * (c)Copyright 1987 Matthew Dillon, All Rights Reserved. * */ #include "files.h" #define NI 0 static BORDER Bdr[10]; static ITEXT BText[] = { { 3,0,JAM2,1,0,NULL,(ubyte *)"info"}, { 3,0,JAM2,1,0,NULL,(ubyte *)"del" }, { 3,0,JAM2,1,0,NULL,(ubyte *)"undo"}, { 3,0,JAM2,1,0,NULL,(ubyte *)"all" } }; static ITEXT SText[] = { { 3,0,JAM2,NI,-2,NULL,(ubyte *)"Volume: " }, { 3,0,JAM2,NI,-2,NULL,(ubyte *)"Pattern: " }, { 3,0,JAM2,NI,-2,NULL,(ubyte *)"Comment: " } }; ubyte Buf1_vol[128]; ubyte Buf2_vol[128]; ubyte Buf1_pat[128]; ubyte Buf2_pat[128]; ubyte Buf1_com[128]; ubyte Buf2_com[128]; STRINGINFO Si_vol = { Buf1_vol,Buf2_vol,0,sizeof(Buf1_vol),0,0,0,0,0,0 }; STRINGINFO Si_pat = { Buf1_pat,Buf2_pat,0,sizeof(Buf2_pat),0,0,0,0,0,0 }; STRINGINFO Si_com = { Buf1_com,Buf2_com,0,sizeof(Buf2_com),0,0,0,0,0,0 }; GADGET Gad_vol = { NULL , NI, 0, NI, NI, GADGHCOMP|GRELWIDTH,GADGIMMEDIATE|RELVERIFY,STRGADGET,NI,NULL,&SText[0],NULL,(APTR)&Si_vol }; GADGET Gad_pat = { &Gad_vol , NI, 1, NI, NI, GADGHCOMP|GRELWIDTH,GADGIMMEDIATE|RELVERIFY,STRGADGET,NI,NULL,&SText[1],NULL,(APTR)&Si_pat }; GADGET Gad_com = { &Gad_pat , NI, 2, NI, NI, GADGHCOMP|GRELWIDTH,GADGIMMEDIATE|RELVERIFY,STRGADGET,NI,NULL,&SText[2],NULL,(APTR)&Si_com }; GADGET Gad_info= { &Gad_com , 5 ,-15, NI, NI, GADGHCOMP|GRELBOTTOM,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,NI,NULL,&BText[0] }; GADGET Gad_del = { &Gad_info , 50,-15, NI, NI, GADGHCOMP|GRELBOTTOM,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,NI,NULL,&BText[1] }; GADGET Gad_undo= { &Gad_del ,-110,-15, NI, NI,GADGHCOMP|GRELRIGHT|GRELBOTTOM,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,NI,NULL,&BText[2] }; GADGET Gad_all = { &Gad_undo , -50,-15, NI, NI, GADGHCOMP|GRELRIGHT|GRELBOTTOM,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,NI,NULL,&BText[3] }; GADGET *FirstGadget = &Gad_all; GADGET Gad_box = { NULL , NI, NI, NI, NI, GADGHNONE|GRELWIDTH|GRELHEIGHT,GADGIMMEDIATE|RELVERIFY|FOLLOWMOUSE,BOOLGADGET,NULL,NULL,NULL }; PROPINFO Prop_slid = { AUTOKNOB|FREEVERT, 0, 0, 0x30, 0x30 }; IMAGE Imag_slid = { 0,0,2,1,1,NULL,1,0,NULL }; GADGET Gad_slid = { NULL, -20, 12, 20, -30, GADGHCOMP|GRELHEIGHT|GRELRIGHT,GADGIMMEDIATE|RELVERIFY|RIGHTBORDER|FOLLOWMOUSE,PROPGADGET,(APTR)&Imag_slid,NULL,NULL,0,(APTR)&Prop_slid }; initslider(nw) NW *nw; { nw->FirstGadget = &Gad_slid; } initstructs() { register short i; register GADGET *gad; for (i = 0; i < sizeof(Bdr)/sizeof(Bdr[0]); ++i) { register BORDER *b = &Bdr[i]; register short *xy= malloc(5 * 2 * sizeof(short)); /*b->LeftEdge = b->TopEdge = -2;*/ b->FrontPen = 1; b->DrawMode = JAM2; b->Count = 5; b->XY = xy; bzero(xy, 5 * 2 * sizeof(short)); xy[2] = i * Win->RPort->TxWidth + 4; xy[4] = xy[2]; xy[5] = Win->RPort->TxHeight + 2; xy[7] = Win->RPort->TxHeight + 2; } for (i = 0; i < sizeof(SText)/sizeof(SText[0]); ++i) { register ITEXT *it = &SText[i]; it->LeftEdge = -strlen(it->IText) * Win->RPort->TxWidth + 2; it->TopEdge += 2; } for (i = 0; i < sizeof(BText)/sizeof(BText[0]); ++i) { register ITEXT *it = &BText[i]; it->LeftEdge+= 2; it->TopEdge += 2; } for (gad = FirstGadget; gad; gad = gad->NextGadget) { register ubyte *str = gad->GadgetText->IText; gad->Height = Win->RPort->TxHeight + 3; gad->Width = strlen(str) * Win->RPort->TxWidth + 5; if (gad->GadgetType == STRGADGET) { gad->LeftEdge = Win->BorderLeft + strlen(str) * Win->RPort->TxWidth + 2; gad->Width = -gad->LeftEdge - Win->BorderRight; gad->TopEdge = gad->TopEdge * (Win->RPort->TxHeight + 2) + Win->BorderTop; gad->GadgetText->LeftEdge = -strlen(str) * Win->RPort->TxWidth; } else { gad->GadgetRender = (APTR)&Bdr[strlen(str)]; } } Gad_box.LeftEdge= Win->BorderLeft; Gad_box.TopEdge = Gad_com.TopEdge + Win->RPort->TxHeight + 2; Gad_box.Width = -Gad_box.LeftEdge - Win->BorderRight; Gad_box.Height = -Gad_box.TopEdge + Gad_undo.TopEdge - 2; } addgadgets() { register GADGET *gad, *ngad; int i = 0; initstructs(Win); for (gad = FirstGadget; gad; gad = ngad) { ngad = gad->NextGadget; AddGadget(Win, gad, i); ++i; } AddGadget(Win, &Gad_box, i); RefreshGList(FirstGadget, Win, NULL, -1); } remgadgets() { } fixgadgets() { } getgadget(im, sel, str) IMESS *im; short *sel; ubyte **str; { GADGET *gad = (GADGET *)im->IAddress; *sel = gad->Flags & SELECTED; if (gad == &Gad_info) return(GAD_INFO); if (gad == &Gad_del) return(GAD_DEL); if (gad == &Gad_undo) return(GAD_UNDO); if (gad == &Gad_all) return(GAD_ALL); if (gad == &Gad_slid) return(GAD_SLIDER); if (gad == &Gad_box) return(GAD_BIGBOX); if (gad == &Gad_vol || gad == &Gad_pat || gad == &Gad_com) { *str = ((STRINGINFO *)gad->SpecialInfo)->Buffer; if (gad == &Gad_vol) return(GAD_VOLUME); if (gad == &Gad_pat) return(GAD_PATTERN); if (gad == &Gad_com) return(GAD_COMMENT); } return(0); } bigboxbounds(xs,xe,ys,ye) short *xs,*xe,*ys,*ye; { *xs = Gad_box.LeftEdge; *xe = *xs + Gad_box.Width + Win->Width; *ys = Gad_box.TopEdge; *ye = *ys + Gad_box.Height+ Win->Height; if (*xe <= *xs) *xe = *xs + 1; if (*ye <= *ys) *ye = *ys + 1; } getsliderpos(pot, full) short *pot, *full; { *pot = Prop_slid.VertPot; *full= Prop_slid.VertBody; } getboxpos(im) IMESS *im; { return(im->MouseY - Gad_box.TopEdge); } setslider(pos, fatness) { NewModifyProp(&Gad_slid, Win, NULL, AUTOKNOB|FREEVERT,0,pos,0,fatness,1); } setcomment(str) char *str; { strcpy(Buf1_com, str); RefreshGList(&Gad_com, Win, NULL, 1); } activate_vol() { ActivateGadget(&Gad_vol, Win, NULL); } activate_pat() { ActivateGadget(&Gad_pat, Win, NULL); } activate_com() { ActivateGadget(&Gad_com, Win, NULL); } \Rogue\Monster\ else echo "will not over write gadget.c" fi if [ `wc -c gadget.c | awk '{printf $1}'` -ne 5780 ] then echo `wc -c gadget.c | awk '{print "Got " $1 ", Expected " 5780}'` fi if `test ! -s main.c` then echo "writing main.c" cat > main.c << '\Rogue\Monster\' /* * MAIN.C * * FILES * * A file catalog program by Matthew Dillon. * * (c)Copyright 1987 Matthew Dillon, All Rights Reserved. * */ #include "files.h" #include <local/xmisc.h> short Deemu[] = { 'ST','RT', 0, 0, 'NW',' ', 0, 8, -16, -8, 320, 100, 'TE','XT', 0,42, 'De','fa','ul','t\0','s:','ca','ta','lo','g.','db',0,0,0,0,0,0,0,0,0,0,0, 'EN','D ', 0, 0 }; #define NWOFF 8 #define DEFFILE 16 NW Nw = { 0, 0, 0, 0, -1, -1, NEWSIZE|MOUSEBUTTONS|MOUSEMOVE|GADGETDOWN|GADGETUP|MENUPICK|CLOSEWINDOW, WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|NOCAREREFRESH|ACTIVATE, NULL, NULL, (ubyte *)"V1.2 by Matthew Dillon, Catalog Utility.", NULL, NULL, 182, 66, -1, -1, WBENCHSCREEN }; WIN *Win; RP *Rp; char FileName[128]; main() { char resized = 0; char notdone = 1; char movebox = 0; char moveslider = 0; char addactive = 0; char noload = 1; char dontquit = 0; char mmove = 0; short mmy; IMESS *im; SCR Scr; openlibs(INTUITION_LIB|GRAPHICS_LIB); GetScreenData(&Scr, sizeof(Scr), WBENCHSCREEN, NULL); initslider(&Nw); Nw.LeftEdge = Deemu[NWOFF+0]; Nw.TopEdge = Deemu[NWOFF+1]; Nw.Width = Deemu[NWOFF+2]; Nw.Height = Deemu[NWOFF+3]; if (Nw.Width <= 0) Nw.Width += Scr.Width; if (Nw.Height <= 0) Nw.Height += Scr.Height; if (Nw.LeftEdge < 0) Nw.LeftEdge += Scr.Width - Nw.Width; if (Nw.TopEdge < 0) Nw.TopEdge += Scr.Height- Nw.Height; if (Nw.LeftEdge < 0 || Nw.TopEdge < 0 || Nw.LeftEdge + Nw.Width > Scr.Width || Nw.TopEdge + Nw.Height > Scr.Height) { Nw.LeftEdge = Nw.TopEdge = 0; Nw.Width = 320; Nw.Height= 100; } { register char *ptr = (char *)(Deemu + DEFFILE); strcpy(FileName, ptr + strlen(ptr) + 1); } Win = OpenWindow(&Nw); failfalse(Win, "Unable to open window"); Rp = Win->RPort; addmenus(); addgadgets(); again: for (; notdone || dontquit;) { if (dontquit) notdone = 1; dontquit = 0; WaitPort(Win->UserPort); while (im = GetMsg(Win->UserPort)) { switch(im->Class) { case NEWSIZE: resized = 1; break; case MOUSEBUTTONS: break; case MOUSEMOVE: mmove = 1; mmy = im->MouseY; break; case GADGETDOWN: { char *str = NULL; short sel; switch(getgadget(im, &sel, &str)) { case GAD_SLIDER: moveslider = 1; movebox = 0; sliderhit(); break; case GAD_BIGBOX: moveslider = 0; movebox = 1; bigboxhit(im->MouseY, 0); break; } } break; case GADGETUP: { char *str = NULL; short sel; switch(getgadget(im, &sel, &str)) { case GAD_INFO: { long fh = Open("raw:10/24/600/150/INFO", 1006); if (fh) { char buf[8]; fhprintf(fh, "\n\r\n\rVersion 1.1 Written by Matthew Dillon\n\r"); fhprintf(fh, "(c)Copyright 1987 Matthew Dillon, All Rights Reserved.\n\n\r"); fhprintf(fh, " dillon@ucbvax.berkeley.edu (ARPANET)\n\r"); fhprintf(fh, " ...!ihnp4!ucbvax!dillon (USENET)\n\r"); fhprintf(fh, "Matthew Dillon, 891 Regal Rd. Berkeley, Ca. 94708\n\n\r"); fhprintf(fh, "This software is freely redistributable only. This\n\r"); fhprintf(fh, "software is NOT shareware\n\n\r"); fhprintf(fh, "Thanks to Peter Da Silva for providing the filerequestor\n\r"); fhprintf(fh, "\n\n Any key to continue\n\r"); Read(fh, buf, 1); Close(fh); } } break; case GAD_DEL: rem_selected(Highlighted, 0); break; case GAD_UNDO: undo(); break; case GAD_ALL: selectall(); redisplay(0); break; case GAD_VOLUME: if (str[0]) add_volume(str); activate_vol(); break; case GAD_PATTERN: if (str[0]) { title("Wait"); select_pattern(str, 0); } activate_pat(); break; case GAD_COMMENT: mod_comment(str); break; case GAD_SLIDER: moveslider = 0; sliderhit(); break; case GAD_BIGBOX: movebox = 0; bigboxhit(im->MouseY, 1); break; } } break; case MENUPICK: switch(getmenu(im)) { case MEN_SAVE: { FILE *fi; if (noload && NumEntries == 0) { title("Did I just save you from making a mistake?"); break; } fi = fopen(FileName, "w"); if (fi) { save_database(fi); if (ferror(fi)) { title("File Error"); dontquit = 1; } else { title("Saved ok"); Modified = 0; } fclose(fi); } else { title("Unable to open file for write"); } } break; case MEN_SAVEAS: { FILE *fi; if (stdfile("SAVE DATABASE", FileName, "", FileName)) { noload = 0; if (fi = fopen(FileName, "w")) { save_database(fi); if (ferror(fi)) { title("File Error"); dontquit = 1; } else { title("Saved ok"); Modified = 0; } fclose(fi); } else { title("Unable to open file for write"); } } } break; case MEN_LOADEF: { FILE *fi = fopen(FileName, "r"); long entries = NumEntries; if (fi) { noload = 0; load_database(fi); if (!entries) Modified = 0; fclose(fi); } else { title("Unable to open file for read"); } } break; case MEN_LOAD: { FILE *fi; long entries = NumEntries; if (stdfile("LOAD DATABASE", FileName, "", FileName)) { noload = 0; if (fi = fopen(FileName, "r")) { load_database(fi); if (!entries) Modified = 0; fclose(fi); } else { title("Unable to open file for read"); } } } break; case MEN_QUIT: notdone = 0; break; case MEN_KILLPAT: resetsort(); addentry(KILLNAME, "", 0); select_pattern(KILLNAME, 0); break; } break; case CLOSEWINDOW: notdone = 0; break; } ReplyMsg(im); if (resized) { fixgadgets(); redisplay(0); } resized = 0; } if (mmove) { if (moveslider) sliderhit(); if (movebox) bigboxhit(mmy, 0); mmove = 0; } } if (Modified) { title("MODIFICATIONS MADE! HIT CLOSE-BOX AGAIN TO VERIFY"); Modified = 0; notdone = 1; goto again; } failfalse(NULL, NULL); } failfalse(val, str) long val; char *str; { if (val == NULL) { if (str) puts(str); if (Win) { remmenus(); remgadgets(); CloseWindow(Win); Win = NULL; } closelibs(-1); exit((str)? 1 : 0); } } failtrue(val, str) long val; char *str; { if (val) failfalse(NULL, str); } \Rogue\Monster\ else echo "will not over write main.c" fi if [ `wc -c main.c | awk '{printf $1}'` -ne 6575 ] then echo `wc -c main.c | awk '{print "Got " $1 ", Expected " 6575}'` fi if `test ! -s memory.c` then echo "writing memory.c" cat > memory.c << '\Rogue\Monster\' /* * MEMORY.C * * (c)Copyright 1987 Matthew Dillon, All Rights Reserved. * */ #include "files.h" #define BLKSIZE 256 /* # of records to allocate at once */ #define STRBLKSIZE 4096 #define MAXSTRLEN 64 /* maximum string len for cached strings */ static RECORD *Freelist; static RECORD *Blk; static short Bi; static char *Strs[MAXSTRLEN]; static char *Sbuf; static short Si; RECORD * allocrecord() { register RECORD *rec; if (rec = Freelist) { Freelist = Freelist->next; return(rec); } if (!Bi) { Blk = (RECORD *)malloc(sizeof(RECORD) * BLKSIZE); if (!Blk) return(NULL); Bi = 256; } --Bi; return(Blk++); } void freerecord(rec) RECORD *rec; { rec->next = Freelist; Freelist = rec; } char * allocstr(str) char *str; { register short bytes = strlen(str) + 1; register char *ptr; if (bytes >= 4 && bytes < MAXSTRLEN) { if (Strs[bytes]) { ptr = Strs[bytes]; Strs[bytes] = *(char **)ptr; } else { bytes = (bytes + 1) & ~1; if (Si < bytes) { Sbuf = malloc(STRBLKSIZE); if (!Sbuf) return(NULL); Si = STRBLKSIZE; } ptr = Sbuf; Sbuf += bytes; Si -= bytes; } } else { ptr = malloc(bytes); if (!ptr) return(NULL); } strcpy(ptr, str); return(ptr); } void freestr(ptr) char *ptr; { register short len; if (ptr) { len = strlen(ptr) + 1; if (len >= 4 && len < MAXSTRLEN) { *(char **)ptr = Strs[len]; Strs[len] = ptr; } else { free(ptr); } } } \Rogue\Monster\ else echo "will not over write memory.c" fi if [ `wc -c memory.c | awk '{printf $1}'` -ne 1531 ] then echo `wc -c memory.c | awk '{print "Got " $1 ", Expected " 1531}'` fi if `test ! -s menu.c` then echo "writing menu.c" cat > menu.c << '\Rogue\Monster\' /* * MENU.C * * (c)Copyright 1987 Matthew Dillon, All Rights Reserved. * */ #include "files.h" #define NI 0 /* means 'not initialized' */ static ITEXT IText[] = { { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Save" }, { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"SaveAs" }, { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Load" }, { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"LoadDefault" }, { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Quit" }, { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"AddKillPat" }, }; static ITEM Item[] = { { &Item[1], 0, NI, NI, NI, 0, 0, (APTR)&IText[0], NULL }, { &Item[2], 0, NI, NI, NI, 0, 0, (APTR)&IText[1], NULL }, { &Item[3], 0, NI, NI, NI, 0, 0, (APTR)&IText[2], NULL }, { &Item[4], 0, NI, NI, NI, 0, 0, (APTR)&IText[3], NULL }, { NULL , 0, NI, NI, NI, 0, 0, (APTR)&IText[4], NULL }, { NULL , 0, NI, NI, NI, 0, 0, (APTR)&IText[5], NULL }, }; static MENU Menu[] = { { &Menu[1], NI, 0, NI, NI, NI, "Project" , NI }, { NULL , NI, 0, NI, NI, NI, "Control", NI } }; addmenus() { MENU *menu; ITEM *item, *nit; short left = 5; short height; short width; for (menu = Menu, item = Item; menu; menu = menu->NextMenu) { height = 0; width = strlen(menu->MenuName); menu->FirstItem = item; for (item = menu->FirstItem; item; item = item->NextItem) { if (width < strlen(((ITEXT *)item->ItemFill)->IText)) width = strlen(((ITEXT *)item->ItemFill)->IText); } width *= Win->RPort->TxWidth; for (item = menu->FirstItem; item; nit = item, item = item->NextItem) { item->Width = width; item->Height = Win->RPort->TxHeight + 2; item->TopEdge = height; item->Flags |= ITEMTEXT|ITEMENABLED|HIGHCOMP; height += item->Height; } menu->LeftEdge = left; menu->Width = width; menu->Height = height; menu->Flags = MENUENABLED; item = nit + 1; left += width + 4; } SetMenuStrip(Win, Menu); } remmenus() { ClearMenuStrip(Win); } getmenu(im) IMESS *im; { register short mn = MENUNUM(im->Code); register short in = ITEMNUM(im->Code); switch(mn) { case 0: switch(in) { case 0: return(MEN_SAVE); case 1: return(MEN_SAVEAS); case 2: return(MEN_LOAD); case 3: return(MEN_LOADEF); case 4: return(MEN_QUIT); } break; case 1: switch(in) { case 0: return(MEN_KILLPAT); } break; } return(0); } \Rogue\Monster\ else echo "will not over write menu.c" fi if [ `wc -c menu.c | awk '{printf $1}'` -ne 2411 ] then echo `wc -c menu.c | awk '{print "Got " $1 ", Expected " 2411}'` fi if `test ! -s newwildcmp.c` then echo "writing newwildcmp.c" cat > newwildcmp.c << '\Rogue\Monster\' /* * NEWWILDCMP.C * * (c)Copyright 1987 Matthew Dillon, All Rights Reserved. * * Compare a wild card name with a normal name * * This function replaces wildcmp() in SUP32.LIB (as not everybody will * have the latest SUP32.LIB). The only difference is that this call * is case insensitive. Later releases of SUP32.LIB will fix the * case-sensitive bug. */ #define MAXB 8 newwildcmp(wild, name) char *wild, *name; { register char *w = wild; register char *n = name; char *back[MAXB][2]; register short bi = 0; register char c1, c2; while (*n || *w) { switch (*w) { case '*': if (bi == MAXB) { puts ("Too many levels of '*'"); return (0); } back[bi][0] = w; back[bi][1] = n; ++bi; ++w; continue; goback: --bi; while (bi >= 0 && *back[bi][1] == '\0') --bi; if (bi < 0) return (0); w = back[bi][0] + 1; n = ++back[bi][1]; ++bi; continue; case '?': if (!*n) { if (bi) goto goback; return (0); } break; default: c1 = *n; c2 = *w; if (c1 >= 'A' && c1 <= 'Z') /* to lower case */ c1 |= 0x20; if (c2 >= 'A' && c2 <= 'Z') c2 |= 0x20; if (c1 != c2) { if (bi) goto goback; return (0); } break; } if (*n) ++n; if (*w) ++w; } return (1); } \Rogue\Monster\ else echo "will not over write newwildcmp.c" fi if [ `wc -c newwildcmp.c | awk '{printf $1}'` -ne 1351 ] then echo `wc -c newwildcmp.c | awk '{print "Got " $1 ", Expected " 1351}'` fi echo "Finished archive 1 of 1" # if you want to concatenate archives, remove anything after this line exit -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.