/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by Olaf Barthel & MXM * * Name .....: Icon.c * Created ..: Friday 10-May-91 16:58 * Revision .: 0 * * Date Author Comment * ========= ======== ==================== * 10-May-91 Olsen Created this file! * * $Revision Header ********************************************************/ /* A quick set of file types we are able to provide icons for. */ enum { TYPE_DIR,TYPE_FILE,TYPE_ICON, TYPE_TEXT, TYPE_C,TYPE_H, TYPE_ASM,TYPE_I, TYPE_MOD, TYPE_REXX, TYPE_BASIC, TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB, TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB, TYPE_OBJECT,TYPE_LIB, TYPE_EXECUTABLE, TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER, TYPE_GIF,TYPE_ILBM,TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM, TYPE_IMPLODER,TYPE_POWERPACKER, TYPE_ARC,TYPE_LHARC,TYPE_ZOO,TYPE_ZIP,TYPE_DMS,TYPE_WARP,TYPE_ZOOM, }; /* Name of the global handshake port. */ #define PORTNAME "Icon Rendezvous" /* Library vector offsets for a bunch of routines. */ #define EXAMINE -102 #define EXNEXT -108 #define OPEN -30 #define CLEARMENUSTRIP -54 /* This structure describes the global handshake port. */ struct IconPort { struct MsgPort VanillaPort; BPTR Segment; VOID (*Remove)(); }; /* A structure containing both a file name suffix and the * approriate file type. */ struct Suffix { UBYTE *Name; UBYTE Type; }; /* A structure containing an icon file name and a special * purpose flag. */ struct NameInfo { UBYTE *Name; BYTE IsPresent; }; /* A table of valid ASCII characters (7 bits). */ BYTE ValidTab[256] = { 0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0, 0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* A table of clearly invalid ASCII characters (8 bits). */ BYTE InvalidTab[256] = { 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, 1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* Some file name suffixes for text files and the approriate * file types. */ struct Suffix TextSuffix[] = { ".C", TYPE_C, ".CP", TYPE_C, ".CC", TYPE_C, ".H", TYPE_H, ".ASM", TYPE_ASM, ".A", TYPE_ASM, ".S", TYPE_ASM, ".I", TYPE_I, ".BAS", TYPE_BASIC, ".GFA", TYPE_BASIC, ".REXX",TYPE_REXX, ".CED", TYPE_REXX, ".VLT", TYPE_REXX, ".CPR", TYPE_REXX, ".TxEd",TYPE_REXX, ".TEX", TYPE_TEX, ".STY", TYPE_TEX, ".MF", TYPE_METAFONT, ".MOD", TYPE_MOD, ".DEF", TYPE_MOD }; /* Some more file name suffixes for executable files and the * approriate file types. */ struct Suffix ExecutableSuffix[] = { ".device", TYPE_DEVICE, ".library", TYPE_LIBRARY, "FileSystem", TYPE_FILESYS, "Handler", TYPE_HANDLER }; /* This list contains the names of all icon files which can be * attached to the files to be identified. The flag byte indicates * whether an icon is available or not. */ struct NameInfo NameInfo[] = { NULL, FALSE, NULL, FALSE, NULL, FALSE, "text", FALSE, "c", FALSE, "h", FALSE, "asm", FALSE, "i", FALSE, "mod", FALSE, "rexx", FALSE, "basic", FALSE, "tex", FALSE, "metafont", FALSE, "gf", FALSE, "pk", FALSE, "dvi", FALSE, "flib", FALSE, "manx3object", FALSE, "manx5object", FALSE, "manx3lib", FALSE, "manx5lib", FALSE, "object", FALSE, "lib", FALSE, NULL, FALSE, "library", FALSE, "device", FALSE, "filesys", FALSE, "handler", FALSE, "gif", FALSE, "pic", FALSE, "anim", FALSE, "sound", FALSE, "score", FALSE, "ftxt", FALSE, "pref", FALSE, "term", FALSE, "imploder", FALSE, "powerpacker", FALSE, "arc", FALSE, "lharc", FALSE, "zoo", FALSE, "zip", FALSE, "dms", FALSE, "warp", FALSE, "zoom", FALSE }; /* Prototypes for functions in this module and Bypass.asm */ extern LONG __asm MyExamine(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo); LONG __saveds __asm NewExamine(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo); extern LONG __asm MyExNext(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo); LONG __saveds __asm NewExNext(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo); extern BPTR __asm MyOpen(register __d1 UBYTE *Name,register __d2 LONG Mode); BPTR __saveds __asm NewOpen(register __d1 UBYTE *Name,register __d2 LONG Mode); extern VOID __asm MyClearMenuStrip(register __a0 struct Window *Window); VOID __saveds __asm NewClearMenuStrip(register __a0 struct Window *Window); VOID __saveds RemoveIcon(VOID); BYTE InstallIcon(VOID); struct Node * MyFindName(struct List *List,UBYTE *Name); UBYTE Local2Upper(UBYTE c); UBYTE StrCmp(UBYTE *a,UBYTE *b); VOID DeleteNode(struct Node *Node); struct Node * CreateNode(UBYTE *Name); VOID AddName(UBYTE *FileName,UBYTE Type); ULONG __saveds Main(VOID); /* Global and shared library identifiers. */ struct ExecBase *SysBase; struct DosLibrary *DOSBase; struct IntuitionBase *IntuitionBase; /* Pointers to the old library routines. */ APTR OldExamine; APTR OldExNext; APTR OldOpen; APTR OldClearMenuStrip; /* The list containing the files which do not have an icon and the * access semaphore. */ struct SignalSemaphore NameSemaphore; struct List NameList; /* The node being scanned. */ struct Node *ScanNode; /* True if ExNext is to perform fake scanning, else false. */ BYTE FakeScan; /* Global handshake port. */ struct IconPort *IconPort; /* Main(): * * Program entry point. */ ULONG __saveds Main() { struct Process *ThisProcess; /* Set up SysBase. */ SysBase = *(struct ExecBase **)4; /* Look who we are. */ ThisProcess = (struct Process *)SysBase -> ThisTask; /* Started from Shell? */ if(ThisProcess -> pr_CLI) { /* Open the DOS library. */ if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) { Printf("\33[1m\33[33mIcon\33[31m © \33[0mCopyright 1991 by Olaf Barthel, "); /* If the port is available remove an * already running `Icon'. */ if(IconPort = (struct IconPort *)FindPort(PORTNAME)) { Flush(ThisProcess -> pr_COS); Printf("Removing patch... "); Flush(ThisProcess -> pr_COS); Forbid(); IconPort -> Remove(); Permit(); Printf("done.\n"); CloseLibrary(DOSBase); } else { /* Install `Icon'. */ Flush(ThisProcess -> pr_COS); Printf("Installing patch... "); Flush(ThisProcess -> pr_COS); if(InstallIcon()) Printf("done.\n"); else { Printf("failed!\a\n"); CloseLibrary(DOSBase); } } } else return(RETURN_FAIL); } else { struct Message *Message; /* Wait for Workbench startup message. */ Message = (struct Message *)WaitPort(&ThisProcess -> pr_MsgPort); Forbid(); /* And reply it. */ ReplyMsg(Message); } return(RETURN_OK); } /* MyFindName(struct List *List,UBYTE *Name): * * Find a node in a list, scan for the name ignoring * case. */ struct Node * MyFindName(struct List *List,UBYTE *Name) { struct Node *Node; Node = List -> lh_Head; while(Node -> ln_Succ) { if(!StrCmp(Node -> ln_Name,Name)) return(Node); Node = Node -> ln_Succ; } return(NULL); } /* RemoveIcon(): * * Remove a previously installed `Icon'. */ VOID __saveds RemoveIcon() { struct Node *Node,*NextNode; BPTR Segment; /* Look for the port. */ IconPort = (struct IconPort *)FindPort(PORTNAME); Segment = IconPort -> Segment; /* Remove it. */ RemPort(&IconPort -> VanillaPort); FreeVec(IconPort); Node = NameList . lh_Head; /* Delete all the nodes in the list if necessary. */ while(Node -> ln_Succ) { NextNode = Node -> ln_Succ; DeleteNode(Node); Node = NextNode; } /* Restore the system library vectors if possible. */ SetFunction(DOSBase, EXAMINE, OldExamine); SetFunction(DOSBase, EXNEXT, OldExNext); SetFunction(DOSBase, OPEN, OldOpen); SetFunction(IntuitionBase, CLEARMENUSTRIP, OldClearMenuStrip); /* Remove the `Icon' program. */ UnLoadSeg(Segment); /* Close the libraries. */ CloseLibrary(IntuitionBase); CloseLibrary(DOSBase); } /* InstallIcon(): * * Install `Icon' and get it running. */ BYTE InstallIcon() { /* Create the global port. */ if(IconPort = (struct IconPort *)AllocVec(sizeof(struct IconPort) + sizeof(PORTNAME),MEMF_PUBLIC|MEMF_CLEAR)) { IconPort -> VanillaPort . mp_Node . ln_Name = (UBYTE *)(IconPort + 1); strcpy(IconPort -> VanillaPort . mp_Node . ln_Name,PORTNAME); IconPort -> VanillaPort . mp_Flags = PA_IGNORE; /* Open Intuition. */ if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",36)) { /* Set up the name list. */ InitSemaphore(&NameSemaphore); NewList(&NameList); /* Modify system functions. */ OldExamine = (APTR)SetFunction(DOSBase, EXAMINE, NewExamine); OldExNext = (APTR)SetFunction(DOSBase, EXNEXT, NewExNext); OldOpen = (APTR)SetFunction(DOSBase, OPEN, NewOpen); OldClearMenuStrip = (APTR)SetFunction(IntuitionBase, CLEARMENUSTRIP, NewClearMenuStrip); /* Remember setup data. */ IconPort -> Remove = RemoveIcon; IconPort -> Segment = ((struct CommandLineInterface *)BADDR(((struct Process *)SysBase -> ThisTask) -> pr_CLI)) -> cli_Module; /* Make the port public. */ AddPort(&IconPort -> VanillaPort); /* Make the Shell believe that `Icon' has * already terminated. */ ((struct CommandLineInterface *)BADDR(((struct Process *)SysBase -> ThisTask) -> pr_CLI)) -> cli_Module = NULL; return(TRUE); } /* Clear the port. */ FreeVec(IconPort); } return(FALSE); } /* Local2Upper(UBYTE c): * * Custom version of toupper, will also handle international * characters. */ UBYTE Local2Upper(UBYTE c) { return((UBYTE)((((c) >= 224 && (c) <= 254) || ((c) >= 'a' && (c) <= 'z')) ? (c) - 32 : c)); } /* StrCmp(UBYTE *a,UBYTE *b): * * Custom version of strcmp, compares ignoring case. */ UBYTE StrCmp(UBYTE *a,UBYTE *b) { for( ; Local2Upper(*a) == Local2Upper(*b) ; a++, b++) { if(!(*a)) return(0); } return((UBYTE)(Local2Upper(*a) - Local2Upper(*b))); } /* DeleteNode(struct Node *Node): * * Delete a node from a list and free the memory it * occupies. */ VOID DeleteNode(struct Node *Node) { Remove(Node); FreeVec(Node); } /* CreateNode(UBYTE *Name): * * Create a node, allocate some extra space for the name * and initialize it. */ struct Node * CreateNode(UBYTE *Name) { struct Node *Node; if(Node = (struct Node *)AllocVec(sizeof(struct Node) + strlen(Name) + 1,MEMF_PUBLIC|MEMF_CLEAR)) { Node -> ln_Name = (UBYTE *)(Node + 1); strcpy(Node -> ln_Name,Name); } return(Node); } /* Identify(UBYTE *Name): * * Heuristically identify the type of a file. */ UBYTE Identify(UBYTE *Name) { ULONG *Buffer; UBYTE Type = TYPE_FILE; SHORT i,Len = strlen(Name); /* Allocate a buffer for the first 400 bytes of the * file. */ if(Buffer = (ULONG *)AllocVec(400,MEMF_PUBLIC)) { BPTR File,Size; /* Open the file. */ if(File = Open(Name,MODE_OLDFILE)) { /* Read the first 400 bytes. */ if((Size = Read(File,Buffer,400)) >= sizeof(ULONG)) { /* Examine the first longword. */ switch(Buffer[0]) { case 0x03E7: Type = TYPE_OBJECT; break; case 0x03F3: Type = TYPE_EXECUTABLE; break; case 0x03FA: Type = TYPE_LIB; break; case 0xF7593647:Type = TYPE_TEXFONT; break; case 0xF7020183:Type = TYPE_TEXDVI; break; case 0xF7832020:Type = TYPE_GF; break; case 'FLIB': Type = TYPE_FLIB; break; case 'FORM': switch(Buffer[2]) { case 'ILBM': Type = TYPE_ILBM; break; case 'ANIM': Type = TYPE_ANIM; break; case '8SVX': Type = TYPE_8SVX; break; case 'SMUS': Type = TYPE_SMUS; break; case 'FTXT': Type = TYPE_FTXT; break; case 'PREF': Type = TYPE_PREFS; break; case 'TERM': Type = TYPE_TERM; break; } break; case 'IMP!': Type = TYPE_IMPLODER; break; case 'PP20': Type = TYPE_POWERPACKER; break; case 'DMS!': Type = TYPE_DMS; break; case 'Warp': Type = TYPE_WARP; break; case 'ZOOM': Type = TYPE_ZOOM; break; case 0x504B0304:Type = TYPE_ZIP; break; case 'ZOO ': Type = TYPE_ZOO; break; case 'GIF8': Type = TYPE_GIF; break; default: break; } /* No match yet, see if it's an * ASCII file. */ if(Type == TYPE_FILE) { UBYTE *CharBuffer = (UBYTE *)Buffer; SHORT Count = 0; for(i = 0 ; i < Size ; i++) { if(ValidTab[CharBuffer[i]]) Count++; else { if(InvalidTab[CharBuffer[i]]) { Count = 0; break; } } } /* If more than 75% of the * characters in the first * 400 bytes are legal * ASCII characters this * file is supposed to be * a text file. */ if(Count > 3 * (Size / 4)) Type = TYPE_TEXT; } /* Still no match, have another try... */ if(Type == TYPE_FILE) { if((Buffer[0] & 0xFFFF0000) == 0x1A080000) Type = TYPE_ARC; else { if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00) Type = TYPE_LHARC; else { switch(Buffer[0] & 0xFFFF0000) { case 0x434A0000: Type = TYPE_NEWMANX; break; case 0x414A0000: Type = TYPE_OLDMANX; break; case 0x636A0000: Type = TYPE_NEWMANXLIB; break; case 0x616A0000: Type = TYPE_OLDMANXLIB; break; case 0xF5000000: Type = TYPE_BASIC; break; default: break; } } } } /* Take a look at the file name * suffixes. */ switch(Type) { case TYPE_TEXT: for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++) { Size = strlen(TextSuffix[i] . Name); if(Len >= Size) { if(!StrCmp(&Name[Len - Size],TextSuffix[i] . Name)) { Type = TextSuffix[i] . Type; break; } } } break; case TYPE_EXECUTABLE: for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++) { Size = strlen(ExecutableSuffix[i] . Name); if(Len >= Size) { if(!StrCmp(&Name[Len - Size],ExecutableSuffix[i] . Name)) { Type = ExecutableSuffix[i] . Type; break; } } } break; case TYPE_OBJECT: if(Len >= 4) { if(!StrCmp(&Name[Len - 4],".LIB")) Type = TYPE_LIB; } break; default: break; } } Close(File); } FreeVec(Buffer); } return(Type); } /* AddName(UBYTE *FileName,UBYTE Type): * * Add another name to the list of file names. */ VOID AddName(UBYTE *FileName,UBYTE Type) { struct Node *Node; UBYTE Name[108]; SHORT i; BYTE HasInfo = FALSE; /* Make sure that we will be able to handle the file type. */ if(StrCmp(FileName,".info") && StrCmp(FileName,"Disk.info") && FileName[strlen(FileName) - 1] != ':') { strcpy(Name,FileName); /* Check if the file name has an `.info' suffix. */ for(i = strlen(Name) - 1; i >= 0; i--) { if(Name[i] == '.') { if(!StrCmp(&Name[i],".info")) { Name[i] = 0; HasInfo = TRUE; break; } } } ObtainSemaphore(&NameSemaphore); if(HasInfo) { /* This is probably an icon, see if there's * a file with this name. If there is, * remove the node from the list. */ if(Node = (struct Node *)MyFindName(&NameList,Name)) DeleteNode(Node); else { /* Add another icon to the list. */ if(Node = CreateNode(FileName)) { Node -> ln_Type = TYPE_ICON; AddTail(&NameList,Node); } } } else { strcat(Name,".info"); /* Look if there's already an icon in the * list. If there is one, remove it. */ if(Node = (struct Node *)MyFindName(&NameList,Name)) DeleteNode(Node); else { /* Add the file to the list. */ if(Node = CreateNode(FileName)) { Node -> ln_Type = Type; AddTail(&NameList,Node); } } } ReleaseSemaphore(&NameSemaphore); } } /* NewExamine(): * * Patched dos.library routine, stuffs all files encountered * by Workbench scan into a list. */ LONG __saveds __asm NewExamine(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo) { /* Is it Workbench who's calling? */ if(!strcmp(SysBase -> ThisTask -> tc_Node . ln_Name,"Workbench")) { /* Are there still nodes in the scan list? * If so, clear the list. */ if(NameList . lh_Head -> ln_Succ) { struct Node *Node,*NextNode; ObtainSemaphore(&NameSemaphore); Node = NameList . lh_Head; while(Node -> ln_Succ) { NextNode = Node -> ln_Succ; DeleteNode(Node); Node = NextNode; } ReleaseSemaphore(&NameSemaphore); ScanNode = NULL; } /* Jump back into original dos.library routine. */ if(MyExamine(FileLock,FileInfo)) { /* If enabled identify the file type * and add the file to the list. */ if(FakeScan) { if(StrCmp(FileInfo -> fib_FileName,".info") && StrCmp(FileInfo -> fib_FileName,"Disk.info") && FileInfo -> fib_FileName[strlen(FileInfo -> fib_FileName) - 1] != ':') { UBYTE Type = FileInfo -> fib_DirEntryType < 0 ? TYPE_FILE : TYPE_DIR; if(Type == TYPE_FILE) Type = Identify(FileInfo -> fib_FileName); AddName(FileInfo -> fib_FileName,Type); if(Type != TYPE_EXECUTABLE) FileInfo -> fib_Protection |= FIBF_EXECUTE; } } return(DOSTRUE); } else return(DOSFALSE); } /* Jump into original routine. */ return(MyExamine(FileLock,FileInfo)); } /* NewExNext(): * * Patched dos.library routine, stuffs all files encountered * by Workbench scan into a list. */ LONG __saveds __asm NewExNext(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo) { /* Is it Workbench who's calling? */ if(!strcmp(SysBase -> ThisTask -> tc_Node . ln_Name,"Workbench")) { /* If enabled identify the file type * and add the file to the list. */ if(FakeScan) { /* If ScanNode is nonzero we are actually * faking icons. */ if(ScanNode) { /* Scan the list for approriate files. */ while(ScanNode -> ln_Succ) { /* Are we able to produce and * icon for this file? */ if(ScanNode -> ln_Type != TYPE_ICON && ScanNode -> ln_Type != TYPE_DIR && NameInfo[ScanNode -> ln_Type] . IsPresent) { /* Clear the contents of the FileInfoBlock. */ memset(FileInfo,0,sizeof(struct FileInfoBlock)); /* Set the entries to default values. */ FileInfo -> fib_DirEntryType = -1; FileInfo -> fib_Size = 42; FileInfo -> fib_NumBlocks = 1; FileInfo -> fib_Protection = FIBF_EXECUTE; /* Provide a simple date. */ DateStamp(&FileInfo -> fib_Date); /* Produce and icon. */ SPrintf(FileInfo -> fib_FileName,"%s.info",ScanNode -> ln_Name); ScanNode = ScanNode -> ln_Succ; return(DOSTRUE); } ScanNode = ScanNode -> ln_Succ; } /* End of list reached. */ SetIoErr(ERROR_NO_MORE_ENTRIES); return(DOSFALSE); } /* Jump into original dos.library routine. */ if(MyExNext(FileLock,FileInfo)) { /* Identify file type and add it to the list. */ if(StrCmp(FileInfo -> fib_FileName,".info") && StrCmp(FileInfo -> fib_FileName,"Disk.info") && FileInfo -> fib_FileName[strlen(FileInfo -> fib_FileName) - 1] != ':') { UBYTE Type = FileInfo -> fib_DirEntryType < 0 ? TYPE_FILE : TYPE_DIR; if(Type == TYPE_FILE) Type = Identify(FileInfo -> fib_FileName); AddName(FileInfo -> fib_FileName,Type); if(Type != TYPE_EXECUTABLE) FileInfo -> fib_Protection |= FIBF_EXECUTE; } return(DOSTRUE); } else { struct Node *Node; UBYTE Buffer[40]; BPTR FileLock; SHORT i; /* We have just reached the end of list, there are no more * directory entries. Now it's time to see if all icons * are available and to determine the files to produce * icons for. */ ObtainSemaphore(&NameSemaphore); /* Clear the list entry flags. */ for(i = 0 ; i < sizeof(NameInfo) / sizeof(struct NameInfo) ; i++) NameInfo[i] . IsPresent = -1; Node = NameList . lh_Head; /* Scan the name list. At this point there are only those * files in the list which are not accompanied by an icon. */ while(Node -> ln_Succ) { if(NameInfo[Node -> ln_Type] . IsPresent == -1 && NameInfo[Node -> ln_Type] . Name) { SPrintf(Buffer,"ENV:sys/def_%s.info",NameInfo[Node -> ln_Type] . Name); /* Is the default icon available? */ if(FileLock = Lock(Buffer,ACCESS_READ)) { NameInfo[Node -> ln_Type] . IsPresent = TRUE; ScanNode = NameList . lh_Head; UnLock(FileLock); } else NameInfo[Node -> ln_Type] . IsPresent = FALSE; } Node = Node -> ln_Succ; } /* If there is an icon available produce the first * fake icon. */ if(ScanNode) { while(ScanNode -> ln_Succ) { if(ScanNode -> ln_Type != TYPE_ICON && ScanNode -> ln_Type != TYPE_DIR && NameInfo[ScanNode -> ln_Type] . IsPresent) { memset(FileInfo,0,sizeof(struct FileInfoBlock)); FileInfo -> fib_DirEntryType = -1; FileInfo -> fib_Size = 42; FileInfo -> fib_NumBlocks = 1; FileInfo -> fib_Protection = FIBF_EXECUTE; DateStamp(&FileInfo -> fib_Date); SPrintf(FileInfo -> fib_FileName,"%s.info",ScanNode -> ln_Name); ScanNode = ScanNode -> ln_Succ; ReleaseSemaphore(&NameSemaphore); return(DOSTRUE); } ScanNode = ScanNode -> ln_Succ; } } ReleaseSemaphore(&NameSemaphore); SetIoErr(ERROR_NO_MORE_ENTRIES); return(DOSFALSE); } } } /* Jump into original routine. */ return(MyExNext(FileLock,FileInfo)); } /* NewOpen(): * * Patched dos.library routine, opens the fake icon files * produced by the patched Examine/ExNext routines. */ BPTR __saveds __asm NewOpen(register __d1 UBYTE *Name,register __d2 LONG Mode) { UBYTE Buffer[108]; /* Is it Workbench who's calling? */ if(!strcmp(SysBase -> ThisTask -> tc_Node . ln_Name,"Workbench")) { /* Is there a list to scan? */ if(ScanNode) { struct Node *Node; SHORT i; /* Extract the base file name. */ strcpy(Buffer,Name); for(i = strlen(Buffer) ; i >= 0; i--) { if(!StrCmp(&Buffer[i],".info")) { Buffer[i] = 0; break; } } /* Try to find the approriate icon file. */ if(Node = (struct Node *)MyFindName(&NameList,Buffer)) { /* Change the name of the icon file * into the approriate default icon * type. */ SPrintf(Buffer,"ENV:sys/def_%s.info",NameInfo[Node -> ln_Type] . Name); Name = Buffer; } } } /* Jump into original routine. */ return(MyOpen(Name,Mode)); } /* NewClearMenuStrip(): * * Patched intuition.libary routine, checks the Workbench menu * to determine whether we are to create fake icons or not. */ VOID __saveds __asm NewClearMenuStrip(register __a0 struct Window *Window) { struct Menu *Menu; struct MenuItem *MenuItem,*SubItem; FakeScan = FALSE; /* Is this a Workbench window? */ if(Window -> Flags & WFLG_WBENCHWINDOW) { Menu = Window -> MenuStrip; /* Walk through the menus... */ while(Menu && !FakeScan) { MenuItem = Menu -> FirstItem; /* Walk through the menu items... */ while(MenuItem && !FakeScan) { SubItem = MenuItem -> SubItem; /* Walk through the sub items... */ while(SubItem && !FakeScan) { /* Sub item with item text? */ if(SubItem -> Flags & ITEMTEXT) { /* Is it the `All Files' * subitem? */ if(!strcmp(((struct IntuiText *)SubItem -> ItemFill) -> IText,"All Files")) { /* See if it's * checked. */ if(SubItem -> Flags & CHECKED) FakeScan = TRUE; else FakeScan = FALSE; } } SubItem = SubItem -> NextItem; } MenuItem = MenuItem -> NextItem; } Menu = Menu -> NextMenu; } } /* Jump into original routine. */ MyClearMenuStrip(Window); }