home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 553.lha / Icon_v1.0 / Icon.c < prev    next >
C/C++ Source or Header  |  1991-09-09  |  26KB  |  1,275 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by Olaf Barthel & MXM
  4.  *
  5.  *    Name .....: Icon.c
  6.  *    Created ..: Friday 10-May-91 16:58
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    10-May-91       Olsen           Created this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15.     /* A quick set of file types we are able to provide icons for. */
  16.  
  17. enum    {    TYPE_DIR,TYPE_FILE,TYPE_ICON,
  18.         TYPE_TEXT,
  19.         TYPE_C,TYPE_H,
  20.         TYPE_ASM,TYPE_I,
  21.         TYPE_MOD,
  22.         TYPE_REXX,
  23.         TYPE_BASIC,
  24.         TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB,
  25.         TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB,
  26.         TYPE_OBJECT,TYPE_LIB,
  27.         TYPE_EXECUTABLE,
  28.         TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER,
  29.         TYPE_GIF,TYPE_ILBM,TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM,
  30.         TYPE_IMPLODER,TYPE_POWERPACKER,
  31.         TYPE_ARC,TYPE_LHARC,TYPE_ZOO,TYPE_ZIP,TYPE_DMS,TYPE_WARP,TYPE_ZOOM,
  32.     };
  33.  
  34.     /* Name of the global handshake port. */
  35.  
  36. #define PORTNAME    "Icon Rendezvous"
  37.  
  38.     /* Library vector offsets for a bunch of routines. */
  39.  
  40. #define EXAMINE        -102
  41. #define EXNEXT        -108
  42. #define OPEN        -30
  43. #define CLEARMENUSTRIP    -54
  44.  
  45.     /* This structure describes the global handshake port. */
  46.  
  47. struct IconPort
  48. {
  49.     struct MsgPort     VanillaPort;
  50.  
  51.     BPTR         Segment;
  52.     VOID        (*Remove)();
  53. };
  54.  
  55.     /* A structure containing both a file name suffix and the
  56.      * approriate file type.
  57.      */
  58.  
  59. struct Suffix
  60. {
  61.     UBYTE    *Name;
  62.     UBYTE     Type;
  63. };
  64.  
  65.     /* A structure containing an icon file name and a special
  66.      * purpose flag.
  67.      */
  68.  
  69. struct NameInfo
  70. {
  71.     UBYTE    *Name;
  72.     BYTE     IsPresent;
  73. };
  74.  
  75.     /* A table of valid ASCII characters (7 bits). */
  76.  
  77. BYTE ValidTab[256] =
  78. {
  79.     0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,
  80.     0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
  81.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  82.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  83.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  84.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  85.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  86.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  87.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  88.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  89.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  90.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  91.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  92.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  93.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  94.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  95. };
  96.  
  97.     /* A table of clearly invalid ASCII characters (8 bits). */
  98.  
  99. BYTE InvalidTab[256] =
  100. {
  101.     1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
  102.     1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
  103.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  104.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  105.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  106.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  107.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  108.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  109.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  110.     1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
  111.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  112.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  113.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  114.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  115.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  116.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  117. };
  118.  
  119.     /* Some file name suffixes for text files and the approriate
  120.      * file types.
  121.      */
  122.  
  123. struct Suffix TextSuffix[] =
  124. {
  125.     ".C",    TYPE_C,
  126.     ".CP",    TYPE_C,
  127.     ".CC",    TYPE_C,
  128.     ".H",    TYPE_H,
  129.     ".ASM",    TYPE_ASM,
  130.     ".A",    TYPE_ASM,
  131.     ".S",    TYPE_ASM,
  132.     ".I",    TYPE_I,
  133.     ".BAS",    TYPE_BASIC,
  134.     ".GFA",    TYPE_BASIC,
  135.     ".REXX",TYPE_REXX,
  136.     ".CED",    TYPE_REXX,
  137.     ".VLT",    TYPE_REXX,
  138.     ".CPR",    TYPE_REXX,
  139.     ".TxEd",TYPE_REXX,
  140.     ".TEX",    TYPE_TEX,
  141.     ".STY",    TYPE_TEX,
  142.     ".MF",    TYPE_METAFONT,
  143.     ".MOD",    TYPE_MOD,
  144.     ".DEF",    TYPE_MOD
  145. };
  146.  
  147.     /* Some more file name suffixes for executable files and the
  148.      * approriate file types.
  149.      */
  150.  
  151. struct Suffix ExecutableSuffix[] =
  152. {
  153.     ".device",    TYPE_DEVICE,
  154.     ".library",    TYPE_LIBRARY,
  155.     "FileSystem",    TYPE_FILESYS,
  156.     "Handler",    TYPE_HANDLER
  157. };
  158.  
  159.     /* This list contains the names of all icon files which can be
  160.      * attached to the files to be identified. The flag byte indicates
  161.      * whether an icon is available or not.
  162.      */
  163.  
  164. struct NameInfo NameInfo[] =
  165. {
  166.     NULL,        FALSE,
  167.     NULL,        FALSE,
  168.     NULL,        FALSE,
  169.     "text",        FALSE,
  170.     "c",        FALSE,
  171.     "h",        FALSE,
  172.     "asm",        FALSE,
  173.     "i",        FALSE,
  174.     "mod",        FALSE,
  175.     "rexx",        FALSE,
  176.     "basic",    FALSE,
  177.     "tex",        FALSE,
  178.     "metafont",    FALSE,
  179.     "gf",        FALSE,
  180.     "pk",        FALSE,
  181.     "dvi",        FALSE,
  182.     "flib",        FALSE,
  183.     "manx3object",    FALSE,
  184.     "manx5object",    FALSE,
  185.     "manx3lib",    FALSE,
  186.     "manx5lib",    FALSE,
  187.     "object",    FALSE,
  188.     "lib",        FALSE,
  189.     NULL,        FALSE,
  190.     "library",    FALSE,
  191.     "device",    FALSE,
  192.     "filesys",    FALSE,
  193.     "handler",    FALSE,
  194.     "gif",        FALSE,
  195.     "pic",        FALSE,
  196.     "anim",        FALSE,
  197.     "sound",    FALSE,
  198.     "score",    FALSE,
  199.     "ftxt",        FALSE,
  200.     "pref",        FALSE,
  201.     "term",        FALSE,
  202.     "imploder",    FALSE,
  203.     "powerpacker",    FALSE,
  204.     "arc",        FALSE,
  205.     "lharc",    FALSE,
  206.     "zoo",        FALSE,
  207.     "zip",        FALSE,
  208.     "dms",        FALSE,
  209.     "warp",        FALSE,
  210.     "zoom",        FALSE
  211. };
  212.  
  213.     /* Prototypes for functions in this module and Bypass.asm */
  214.  
  215. extern LONG __asm    MyExamine(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo);
  216. LONG __saveds __asm    NewExamine(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo);
  217.  
  218. extern LONG __asm    MyExNext(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo);
  219. LONG __saveds __asm    NewExNext(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo);
  220.  
  221. extern BPTR __asm    MyOpen(register __d1 UBYTE *Name,register __d2 LONG Mode);
  222. BPTR __saveds __asm    NewOpen(register __d1 UBYTE *Name,register __d2 LONG Mode);
  223.  
  224. extern VOID __asm    MyClearMenuStrip(register __a0 struct Window *Window);
  225. VOID __saveds __asm    NewClearMenuStrip(register __a0 struct Window *Window);
  226.  
  227. VOID __saveds        RemoveIcon(VOID);
  228. BYTE            InstallIcon(VOID);
  229.  
  230. struct Node *        MyFindName(struct List *List,UBYTE *Name);
  231. UBYTE            Local2Upper(UBYTE c);
  232. UBYTE            StrCmp(UBYTE *a,UBYTE *b);
  233. VOID            DeleteNode(struct Node *Node);
  234. struct Node *        CreateNode(UBYTE *Name);
  235. VOID            AddName(UBYTE *FileName,UBYTE Type);
  236.  
  237. ULONG __saveds        Main(VOID);
  238.  
  239.     /* Global and shared library identifiers. */
  240.  
  241. struct ExecBase        *SysBase;
  242. struct DosLibrary    *DOSBase;
  243. struct IntuitionBase    *IntuitionBase;
  244.  
  245.     /* Pointers to the old library routines. */
  246.  
  247. APTR             OldExamine;
  248. APTR             OldExNext;
  249. APTR             OldOpen;
  250. APTR             OldClearMenuStrip;
  251.  
  252.     /* The list containing the files which do not have an icon and the
  253.      * access semaphore.
  254.      */
  255.  
  256. struct SignalSemaphore     NameSemaphore;
  257. struct List         NameList;
  258.  
  259.     /* The node being scanned. */
  260.  
  261. struct Node        *ScanNode;
  262.  
  263.     /* True if ExNext is to perform fake scanning, else false. */
  264.  
  265. BYTE             FakeScan;
  266.  
  267.     /* Global handshake port. */
  268.  
  269. struct IconPort        *IconPort;
  270.  
  271.     /* Main():
  272.      *
  273.      *    Program entry point.
  274.      */
  275.  
  276. ULONG __saveds
  277. Main()
  278. {
  279.     struct Process *ThisProcess;
  280.  
  281.         /* Set up SysBase. */
  282.  
  283.     SysBase = *(struct ExecBase **)4;
  284.  
  285.         /* Look who we are. */
  286.  
  287.     ThisProcess = (struct Process *)SysBase -> ThisTask;
  288.  
  289.         /* Started from Shell? */
  290.  
  291.     if(ThisProcess -> pr_CLI)
  292.     {
  293.             /* Open the DOS library. */
  294.  
  295.         if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36))
  296.         {
  297.             Printf("\33[1m\33[33mIcon\33[31m © \33[0mCopyright 1991 by Olaf Barthel, ");
  298.  
  299.                 /* If the port is available remove an
  300.                  * already running `Icon'.
  301.                  */
  302.  
  303.             if(IconPort = (struct IconPort *)FindPort(PORTNAME))
  304.             {
  305.                 Flush(ThisProcess -> pr_COS);
  306.  
  307.                 Printf("Removing patch... ");
  308.  
  309.                 Flush(ThisProcess -> pr_COS);
  310.  
  311.                 Forbid();
  312.  
  313.                 IconPort -> Remove();
  314.  
  315.                 Permit();
  316.  
  317.                 Printf("done.\n");
  318.  
  319.                 CloseLibrary(DOSBase);
  320.             }
  321.             else
  322.             {
  323.                     /* Install `Icon'. */
  324.  
  325.                 Flush(ThisProcess -> pr_COS);
  326.  
  327.                 Printf("Installing patch... ");
  328.  
  329.                 Flush(ThisProcess -> pr_COS);
  330.  
  331.                 if(InstallIcon())
  332.                     Printf("done.\n");
  333.                 else
  334.                 {
  335.                     Printf("failed!\a\n");
  336.  
  337.                     CloseLibrary(DOSBase);
  338.                 }
  339.             }
  340.         }
  341.         else
  342.             return(RETURN_FAIL);
  343.     }
  344.     else
  345.     {
  346.         struct Message *Message;
  347.  
  348.             /* Wait for Workbench startup message. */
  349.  
  350.         Message = (struct Message *)WaitPort(&ThisProcess -> pr_MsgPort);
  351.  
  352.         Forbid();
  353.  
  354.             /* And reply it. */
  355.  
  356.         ReplyMsg(Message);
  357.     }
  358.  
  359.     return(RETURN_OK);
  360. }
  361.  
  362.     /* MyFindName(struct List *List,UBYTE *Name):
  363.      *
  364.      *    Find a node in a list, scan for the name ignoring
  365.      *    case.
  366.      */
  367.  
  368. struct Node *
  369. MyFindName(struct List *List,UBYTE *Name)
  370. {
  371.     struct Node *Node;
  372.  
  373.     Node = List -> lh_Head;
  374.  
  375.     while(Node -> ln_Succ)
  376.     {
  377.         if(!StrCmp(Node -> ln_Name,Name))
  378.             return(Node);
  379.  
  380.         Node = Node -> ln_Succ;
  381.     }
  382.  
  383.     return(NULL);
  384. }
  385.  
  386.     /* RemoveIcon():
  387.      *
  388.      *    Remove a previously installed `Icon'.
  389.      */
  390.  
  391. VOID __saveds
  392. RemoveIcon()
  393. {
  394.     struct Node    *Node,*NextNode;
  395.     BPTR         Segment;
  396.  
  397.         /* Look for the port. */
  398.  
  399.     IconPort = (struct IconPort *)FindPort(PORTNAME);
  400.  
  401.     Segment = IconPort -> Segment;
  402.  
  403.         /* Remove it. */
  404.  
  405.     RemPort(&IconPort -> VanillaPort);
  406.  
  407.     FreeVec(IconPort);
  408.  
  409.     Node = NameList . lh_Head;
  410.  
  411.         /* Delete all the nodes in the list if necessary. */
  412.  
  413.     while(Node -> ln_Succ)
  414.     {
  415.         NextNode = Node -> ln_Succ;
  416.  
  417.         DeleteNode(Node);
  418.  
  419.         Node = NextNode;
  420.     }
  421.  
  422.         /* Restore the system library vectors if possible. */
  423.  
  424.     SetFunction(DOSBase,        EXAMINE,    OldExamine);
  425.     SetFunction(DOSBase,        EXNEXT,        OldExNext);
  426.     SetFunction(DOSBase,        OPEN,        OldOpen);
  427.     SetFunction(IntuitionBase,    CLEARMENUSTRIP,    OldClearMenuStrip);
  428.  
  429.         /* Remove the `Icon' program. */
  430.  
  431.     UnLoadSeg(Segment);
  432.  
  433.         /* Close the libraries. */
  434.  
  435.     CloseLibrary(IntuitionBase);
  436.     CloseLibrary(DOSBase);
  437. }
  438.  
  439.     /* InstallIcon():
  440.      *
  441.      *    Install `Icon' and get it running.
  442.      */
  443.  
  444. BYTE
  445. InstallIcon()
  446. {
  447.         /* Create the global port. */
  448.  
  449.     if(IconPort = (struct IconPort *)AllocVec(sizeof(struct IconPort) + sizeof(PORTNAME),MEMF_PUBLIC|MEMF_CLEAR))
  450.     {
  451.         IconPort -> VanillaPort . mp_Node . ln_Name = (UBYTE *)(IconPort + 1);
  452.  
  453.         strcpy(IconPort -> VanillaPort . mp_Node . ln_Name,PORTNAME);
  454.  
  455.         IconPort -> VanillaPort . mp_Flags = PA_IGNORE;
  456.  
  457.             /* Open Intuition. */
  458.  
  459.         if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",36))
  460.         {
  461.                 /* Set up the name list. */
  462.  
  463.             InitSemaphore(&NameSemaphore);
  464.  
  465.             NewList(&NameList);
  466.  
  467.                 /* Modify system functions. */
  468.  
  469.             OldExamine        = (APTR)SetFunction(DOSBase,        EXAMINE,    NewExamine);
  470.             OldExNext        = (APTR)SetFunction(DOSBase,        EXNEXT,        NewExNext);
  471.             OldOpen            = (APTR)SetFunction(DOSBase,        OPEN,        NewOpen);
  472.             OldClearMenuStrip    = (APTR)SetFunction(IntuitionBase,    CLEARMENUSTRIP,    NewClearMenuStrip);
  473.  
  474.                 /* Remember setup data. */
  475.  
  476.             IconPort -> Remove    = RemoveIcon;
  477.             IconPort -> Segment    = ((struct CommandLineInterface *)BADDR(((struct Process *)SysBase -> ThisTask) -> pr_CLI)) -> cli_Module;
  478.  
  479.                 /* Make the port public. */
  480.  
  481.             AddPort(&IconPort -> VanillaPort);
  482.  
  483.                 /* Make the Shell believe that `Icon' has
  484.                  * already terminated.
  485.                  */
  486.  
  487.             ((struct CommandLineInterface *)BADDR(((struct Process *)SysBase -> ThisTask) -> pr_CLI)) -> cli_Module = NULL;
  488.  
  489.             return(TRUE);
  490.         }
  491.  
  492.             /* Clear the port. */
  493.  
  494.         FreeVec(IconPort);
  495.     }
  496.  
  497.     return(FALSE);
  498. }
  499.  
  500.     /* Local2Upper(UBYTE c):
  501.      *
  502.      *    Custom version of toupper, will also handle international
  503.      *    characters.
  504.      */
  505.  
  506. UBYTE
  507. Local2Upper(UBYTE c)
  508. {
  509.     return((UBYTE)((((c) >= 224 && (c) <= 254) || ((c) >= 'a' && (c) <= 'z')) ? (c) - 32 : c));
  510. }
  511.  
  512.     /* StrCmp(UBYTE *a,UBYTE *b):
  513.      *
  514.      *    Custom version of strcmp, compares ignoring case.
  515.      */
  516.  
  517. UBYTE
  518. StrCmp(UBYTE *a,UBYTE *b)
  519. {
  520.     for( ; Local2Upper(*a) == Local2Upper(*b) ; a++, b++)
  521.     {
  522.         if(!(*a))
  523.             return(0);
  524.     }
  525.  
  526.     return((UBYTE)(Local2Upper(*a) - Local2Upper(*b)));
  527. }
  528.  
  529.     /* DeleteNode(struct Node *Node):
  530.      *
  531.      *    Delete a node from a list and free the memory it
  532.      *    occupies.
  533.      */
  534.  
  535. VOID
  536. DeleteNode(struct Node *Node)
  537. {
  538.     Remove(Node);
  539.  
  540.     FreeVec(Node);
  541. }
  542.  
  543.     /* CreateNode(UBYTE *Name):
  544.      *
  545.      *    Create a node, allocate some extra space for the name
  546.      *    and initialize it.
  547.      */
  548.  
  549. struct Node *
  550. CreateNode(UBYTE *Name)
  551. {
  552.     struct Node *Node;
  553.  
  554.     if(Node = (struct Node *)AllocVec(sizeof(struct Node) + strlen(Name) + 1,MEMF_PUBLIC|MEMF_CLEAR))
  555.     {
  556.         Node -> ln_Name = (UBYTE *)(Node + 1);
  557.  
  558.         strcpy(Node -> ln_Name,Name);
  559.     }
  560.  
  561.     return(Node);
  562. }
  563.  
  564.     /* Identify(UBYTE *Name):
  565.      *
  566.      *    Heuristically identify the type of a file.
  567.      */
  568.  
  569. UBYTE
  570. Identify(UBYTE *Name)
  571. {
  572.     ULONG    *Buffer;
  573.     UBYTE     Type = TYPE_FILE;
  574.     SHORT     i,Len = strlen(Name);
  575.  
  576.         /* Allocate a buffer for the first 400 bytes of the
  577.          * file.
  578.          */
  579.  
  580.     if(Buffer = (ULONG *)AllocVec(400,MEMF_PUBLIC))
  581.     {
  582.         BPTR File,Size;
  583.  
  584.             /* Open the file. */
  585.  
  586.         if(File = Open(Name,MODE_OLDFILE))
  587.         {
  588.                 /* Read the first 400 bytes. */
  589.  
  590.             if((Size = Read(File,Buffer,400)) >= sizeof(ULONG))
  591.             {
  592.                     /* Examine the first longword. */
  593.  
  594.                 switch(Buffer[0])
  595.                 {
  596.                     case 0x03E7:    Type = TYPE_OBJECT;
  597.                             break;
  598.  
  599.                     case 0x03F3:    Type = TYPE_EXECUTABLE;
  600.                             break;
  601.  
  602.                     case 0x03FA:    Type = TYPE_LIB;
  603.                             break;
  604.  
  605.                     case 0xF7593647:Type = TYPE_TEXFONT;
  606.                             break;
  607.  
  608.                     case 0xF7020183:Type = TYPE_TEXDVI;
  609.                             break;
  610.  
  611.                     case 0xF7832020:Type = TYPE_GF;
  612.                             break;
  613.  
  614.                     case 'FLIB':    Type = TYPE_FLIB;
  615.                             break;
  616.  
  617.                     case 'FORM':    switch(Buffer[2])
  618.                             {
  619.                                 case 'ILBM':    Type = TYPE_ILBM;
  620.                                         break;
  621.  
  622.                                 case 'ANIM':    Type = TYPE_ANIM;
  623.                                         break;
  624.  
  625.                                 case '8SVX':    Type = TYPE_8SVX;
  626.                                         break;
  627.  
  628.                                 case 'SMUS':    Type = TYPE_SMUS;
  629.                                         break;
  630.  
  631.                                 case 'FTXT':    Type = TYPE_FTXT;
  632.                                         break;
  633.  
  634.                                 case 'PREF':    Type = TYPE_PREFS;
  635.                                         break;
  636.  
  637.                                 case 'TERM':    Type = TYPE_TERM;
  638.                                         break;
  639.                             }
  640.  
  641.                             break;
  642.  
  643.                     case 'IMP!':    Type = TYPE_IMPLODER;
  644.                             break;
  645.  
  646.                     case 'PP20':    Type = TYPE_POWERPACKER;
  647.                             break;
  648.  
  649.                     case 'DMS!':    Type = TYPE_DMS;
  650.                             break;
  651.  
  652.                     case 'Warp':    Type = TYPE_WARP;
  653.                             break;
  654.  
  655.                     case 'ZOOM':    Type = TYPE_ZOOM;
  656.                             break;
  657.  
  658.                     case 0x504B0304:Type = TYPE_ZIP;
  659.                             break;
  660.  
  661.                     case 'ZOO ':    Type = TYPE_ZOO;
  662.                             break;
  663.  
  664.                     case 'GIF8':    Type = TYPE_GIF;
  665.                             break;
  666.  
  667.                     default:    break;
  668.                 }
  669.  
  670.                     /* No match yet, see if it's an
  671.                      * ASCII file.
  672.                      */
  673.  
  674.                 if(Type == TYPE_FILE)
  675.                 {
  676.                     UBYTE    *CharBuffer = (UBYTE *)Buffer;
  677.                     SHORT     Count = 0;
  678.  
  679.                     for(i = 0 ; i < Size ; i++)
  680.                     {
  681.                         if(ValidTab[CharBuffer[i]])
  682.                             Count++;
  683.                         else
  684.                         {
  685.                             if(InvalidTab[CharBuffer[i]])
  686.                             {
  687.                                 Count = 0;
  688.  
  689.                                 break;
  690.                             }
  691.                         }
  692.                     }
  693.  
  694.                         /* If more than 75% of the
  695.                          * characters in the first
  696.                          * 400 bytes are legal
  697.                          * ASCII characters this
  698.                          * file is supposed to be
  699.                          * a text file.
  700.                          */
  701.  
  702.                     if(Count > 3 * (Size / 4))
  703.                         Type = TYPE_TEXT;
  704.                 }
  705.  
  706.                     /* Still no match, have another try... */
  707.  
  708.                 if(Type == TYPE_FILE)
  709.                 {
  710.                     if((Buffer[0] & 0xFFFF0000) == 0x1A080000)
  711.                         Type = TYPE_ARC;
  712.                     else
  713.                     {
  714.                         if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00)
  715.                             Type = TYPE_LHARC;
  716.                         else
  717.                         {
  718.                             switch(Buffer[0] & 0xFFFF0000)
  719.                             {
  720.                                 case 0x434A0000:    Type = TYPE_NEWMANX;
  721.                                             break;
  722.  
  723.                                 case 0x414A0000:    Type = TYPE_OLDMANX;
  724.                                             break;
  725.  
  726.                                 case 0x636A0000:    Type = TYPE_NEWMANXLIB;
  727.                                             break;
  728.  
  729.                                 case 0x616A0000:    Type = TYPE_OLDMANXLIB;
  730.                                             break;
  731.  
  732.                                 case 0xF5000000:    Type = TYPE_BASIC;
  733.                                             break;
  734.  
  735.                                 default:        break;
  736.                             }
  737.                         }
  738.                     }
  739.                 }
  740.  
  741.                     /* Take a look at the file name
  742.                      * suffixes.
  743.                      */
  744.  
  745.                 switch(Type)
  746.                 {
  747.                     case TYPE_TEXT:
  748.                             for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++)
  749.                             {
  750.                                 Size = strlen(TextSuffix[i] . Name);
  751.  
  752.                                 if(Len >= Size)
  753.                                 {
  754.                                     if(!StrCmp(&Name[Len - Size],TextSuffix[i] . Name))
  755.                                     {
  756.                                         Type = TextSuffix[i] . Type;
  757.                                         break;
  758.                                     }
  759.                                 }
  760.                             }
  761.  
  762.                             break;
  763.  
  764.                     case TYPE_EXECUTABLE:
  765.                             for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++)
  766.                             {
  767.                                 Size = strlen(ExecutableSuffix[i] . Name);
  768.  
  769.                                 if(Len >= Size)
  770.                                 {
  771.                                     if(!StrCmp(&Name[Len - Size],ExecutableSuffix[i] . Name))
  772.                                     {
  773.                                         Type = ExecutableSuffix[i] . Type;
  774.                                         break;
  775.                                     }
  776.                                 }
  777.                             }
  778.  
  779.                             break;
  780.  
  781.                     case TYPE_OBJECT:
  782.                             if(Len >= 4)
  783.                             {
  784.                                 if(!StrCmp(&Name[Len - 4],".LIB"))
  785.                                     Type = TYPE_LIB;
  786.                             }
  787.  
  788.                             break;
  789.  
  790.                     default:    break;
  791.                 }
  792.             }
  793.  
  794.             Close(File);
  795.         }
  796.  
  797.         FreeVec(Buffer);
  798.     }
  799.  
  800.     return(Type);
  801. }
  802.  
  803.     /* AddName(UBYTE *FileName,UBYTE Type):
  804.      *
  805.      *    Add another name to the list of file names.
  806.      */
  807.  
  808. VOID
  809. AddName(UBYTE *FileName,UBYTE Type)
  810. {
  811.     struct Node    *Node;
  812.     UBYTE         Name[108];
  813.     SHORT         i;
  814.     BYTE         HasInfo = FALSE;
  815.  
  816.         /* Make sure that we will be able to handle the file type. */
  817.  
  818.     if(StrCmp(FileName,".info") && StrCmp(FileName,"Disk.info") && FileName[strlen(FileName) - 1] != ':')
  819.     {
  820.         strcpy(Name,FileName);
  821.  
  822.             /* Check if the file name has an `.info' suffix. */
  823.  
  824.         for(i = strlen(Name) - 1; i >= 0; i--)
  825.         {
  826.             if(Name[i] == '.')
  827.             {
  828.                 if(!StrCmp(&Name[i],".info"))
  829.                 {
  830.                     Name[i] = 0;
  831.  
  832.                     HasInfo = TRUE;
  833.  
  834.                     break;
  835.                 }
  836.             }
  837.         }
  838.  
  839.         ObtainSemaphore(&NameSemaphore);
  840.  
  841.         if(HasInfo)
  842.         {
  843.                 /* This is probably an icon, see if there's
  844.                  * a file with this name. If there is,
  845.                  * remove the node from the list.
  846.                  */
  847.  
  848.             if(Node = (struct Node *)MyFindName(&NameList,Name))
  849.                 DeleteNode(Node);
  850.             else
  851.             {
  852.                     /* Add another icon to the list. */
  853.  
  854.                 if(Node = CreateNode(FileName))
  855.                 {
  856.                     Node -> ln_Type = TYPE_ICON;
  857.  
  858.                     AddTail(&NameList,Node);
  859.                 }
  860.             }
  861.         }
  862.         else
  863.         {
  864.             strcat(Name,".info");
  865.  
  866.                 /* Look if there's already an icon in the
  867.                  * list. If there is one, remove it.
  868.                  */
  869.  
  870.             if(Node = (struct Node *)MyFindName(&NameList,Name))
  871.                 DeleteNode(Node);
  872.             else
  873.             {
  874.                     /* Add the file to the list. */
  875.  
  876.                 if(Node = CreateNode(FileName))
  877.                 {
  878.                     Node -> ln_Type = Type;
  879.  
  880.                     AddTail(&NameList,Node);
  881.                 }
  882.             }
  883.         }
  884.  
  885.         ReleaseSemaphore(&NameSemaphore);
  886.     }
  887. }
  888.  
  889.     /* NewExamine():
  890.      *
  891.      *    Patched dos.library routine, stuffs all files encountered
  892.      *    by Workbench scan into a list.
  893.      */
  894.  
  895. LONG __saveds __asm
  896. NewExamine(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo)
  897. {
  898.         /* Is it Workbench who's calling? */
  899.  
  900.     if(!strcmp(SysBase -> ThisTask -> tc_Node . ln_Name,"Workbench"))
  901.     {
  902.             /* Are there still nodes in the scan list?
  903.              * If so, clear the list.
  904.              */
  905.  
  906.         if(NameList . lh_Head -> ln_Succ)
  907.         {
  908.             struct Node *Node,*NextNode;
  909.  
  910.             ObtainSemaphore(&NameSemaphore);
  911.  
  912.             Node = NameList . lh_Head;
  913.  
  914.             while(Node -> ln_Succ)
  915.             {
  916.                 NextNode = Node -> ln_Succ;
  917.  
  918.                 DeleteNode(Node);
  919.  
  920.                 Node = NextNode;
  921.             }
  922.  
  923.             ReleaseSemaphore(&NameSemaphore);
  924.  
  925.             ScanNode = NULL;
  926.         }
  927.  
  928.             /* Jump back into original dos.library routine. */
  929.  
  930.         if(MyExamine(FileLock,FileInfo))
  931.         {
  932.                 /* If enabled identify the file type
  933.                  * and add the file to the list.
  934.                  */
  935.  
  936.             if(FakeScan)
  937.             {
  938.                 if(StrCmp(FileInfo -> fib_FileName,".info") && StrCmp(FileInfo -> fib_FileName,"Disk.info") && FileInfo -> fib_FileName[strlen(FileInfo -> fib_FileName) - 1] != ':')
  939.                 {
  940.                     UBYTE Type = FileInfo -> fib_DirEntryType < 0 ? TYPE_FILE : TYPE_DIR;
  941.  
  942.                     if(Type == TYPE_FILE)
  943.                         Type = Identify(FileInfo -> fib_FileName);
  944.  
  945.                     AddName(FileInfo -> fib_FileName,Type);
  946.  
  947.                     if(Type != TYPE_EXECUTABLE)
  948.                         FileInfo -> fib_Protection |= FIBF_EXECUTE;
  949.                 }
  950.             }
  951.  
  952.             return(DOSTRUE);
  953.         }
  954.         else
  955.             return(DOSFALSE);
  956.     }
  957.  
  958.         /* Jump into original routine. */
  959.  
  960.     return(MyExamine(FileLock,FileInfo));
  961. }
  962.  
  963.     /* NewExNext():
  964.      *
  965.      *    Patched dos.library routine, stuffs all files encountered
  966.      *    by Workbench scan into a list.
  967.      */
  968.  
  969. LONG __saveds __asm
  970. NewExNext(register __d1 BPTR FileLock,register __d2 struct FileInfoBlock *FileInfo)
  971. {
  972.         /* Is it Workbench who's calling? */
  973.  
  974.     if(!strcmp(SysBase -> ThisTask -> tc_Node . ln_Name,"Workbench"))
  975.     {
  976.             /* If enabled identify the file type
  977.              * and add the file to the list.
  978.              */
  979.  
  980.         if(FakeScan)
  981.         {
  982.                 /* If ScanNode is nonzero we are actually
  983.                  * faking icons.
  984.                  */
  985.  
  986.             if(ScanNode)
  987.             {
  988.                     /* Scan the list for approriate files. */
  989.  
  990.                 while(ScanNode -> ln_Succ)
  991.                 {
  992.                         /* Are we able to produce and
  993.                          * icon for this file?
  994.                          */
  995.  
  996.                     if(ScanNode -> ln_Type != TYPE_ICON && ScanNode -> ln_Type != TYPE_DIR && NameInfo[ScanNode -> ln_Type] . IsPresent)
  997.                     {
  998.                             /* Clear the contents of the FileInfoBlock. */
  999.  
  1000.                         memset(FileInfo,0,sizeof(struct FileInfoBlock));
  1001.  
  1002.                             /* Set the entries to default values. */
  1003.  
  1004.                         FileInfo -> fib_DirEntryType    = -1;
  1005.                         FileInfo -> fib_Size        = 42;
  1006.                         FileInfo -> fib_NumBlocks    = 1;
  1007.                         FileInfo -> fib_Protection    = FIBF_EXECUTE;
  1008.  
  1009.                             /* Provide a simple date. */
  1010.  
  1011.                         DateStamp(&FileInfo -> fib_Date);
  1012.  
  1013.                             /* Produce and icon. */
  1014.  
  1015.                         SPrintf(FileInfo -> fib_FileName,"%s.info",ScanNode -> ln_Name);
  1016.  
  1017.                         ScanNode = ScanNode -> ln_Succ;
  1018.  
  1019.                         return(DOSTRUE);
  1020.                     }
  1021.  
  1022.                     ScanNode = ScanNode -> ln_Succ;
  1023.                 }
  1024.  
  1025.                     /* End of list reached. */
  1026.  
  1027.                 SetIoErr(ERROR_NO_MORE_ENTRIES);
  1028.  
  1029.                 return(DOSFALSE);
  1030.             }
  1031.  
  1032.                 /* Jump into original dos.library routine. */
  1033.  
  1034.             if(MyExNext(FileLock,FileInfo))
  1035.             {
  1036.                     /* Identify file type and add it to the list. */
  1037.  
  1038.                 if(StrCmp(FileInfo -> fib_FileName,".info") && StrCmp(FileInfo -> fib_FileName,"Disk.info") && FileInfo -> fib_FileName[strlen(FileInfo -> fib_FileName) - 1] != ':')
  1039.                 {
  1040.                     UBYTE Type = FileInfo -> fib_DirEntryType < 0 ? TYPE_FILE : TYPE_DIR;
  1041.  
  1042.                     if(Type == TYPE_FILE)
  1043.                         Type = Identify(FileInfo -> fib_FileName);
  1044.  
  1045.                     AddName(FileInfo -> fib_FileName,Type);
  1046.  
  1047.                     if(Type != TYPE_EXECUTABLE)
  1048.                         FileInfo -> fib_Protection |= FIBF_EXECUTE;
  1049.                 }
  1050.  
  1051.                 return(DOSTRUE);
  1052.             }
  1053.             else
  1054.             {
  1055.                 struct Node    *Node;
  1056.                 UBYTE         Buffer[40];
  1057.                 BPTR         FileLock;
  1058.                 SHORT         i;
  1059.  
  1060.                     /* We have just reached the end of list, there are no more
  1061.                      * directory entries. Now it's time to see if all icons
  1062.                      * are available and to determine the files to produce
  1063.                      * icons for.
  1064.                      */
  1065.  
  1066.                 ObtainSemaphore(&NameSemaphore);
  1067.  
  1068.                     /* Clear the list entry flags. */
  1069.  
  1070.                 for(i = 0 ; i < sizeof(NameInfo) / sizeof(struct NameInfo) ; i++)
  1071.                     NameInfo[i] . IsPresent = -1;
  1072.  
  1073.                 Node = NameList . lh_Head;
  1074.  
  1075.                     /* Scan the name list. At this point there are only those
  1076.                      * files in the list which are not accompanied by an icon.
  1077.                      */
  1078.  
  1079.                 while(Node -> ln_Succ)
  1080.                 {
  1081.                     if(NameInfo[Node -> ln_Type] . IsPresent == -1 && NameInfo[Node -> ln_Type] . Name)
  1082.                     {
  1083.                         SPrintf(Buffer,"ENV:sys/def_%s.info",NameInfo[Node -> ln_Type] . Name);
  1084.  
  1085.                             /* Is the default icon available? */
  1086.  
  1087.                         if(FileLock = Lock(Buffer,ACCESS_READ))
  1088.                         {
  1089.                             NameInfo[Node -> ln_Type] . IsPresent = TRUE;
  1090.  
  1091.                             ScanNode = NameList . lh_Head;
  1092.  
  1093.                             UnLock(FileLock);
  1094.                         }
  1095.                         else
  1096.                             NameInfo[Node -> ln_Type] . IsPresent = FALSE;
  1097.                     }
  1098.  
  1099.                     Node = Node -> ln_Succ;
  1100.                 }
  1101.  
  1102.                     /* If there is an icon available produce the first
  1103.                      * fake icon.
  1104.                      */
  1105.  
  1106.                 if(ScanNode)
  1107.                 {
  1108.                     while(ScanNode -> ln_Succ)
  1109.                     {
  1110.                         if(ScanNode -> ln_Type != TYPE_ICON && ScanNode -> ln_Type != TYPE_DIR && NameInfo[ScanNode -> ln_Type] . IsPresent)
  1111.                         {
  1112.                             memset(FileInfo,0,sizeof(struct FileInfoBlock));
  1113.  
  1114.                             FileInfo -> fib_DirEntryType    = -1;
  1115.                             FileInfo -> fib_Size        = 42;
  1116.                             FileInfo -> fib_NumBlocks    = 1;
  1117.                             FileInfo -> fib_Protection    = FIBF_EXECUTE;
  1118.  
  1119.                             DateStamp(&FileInfo -> fib_Date);
  1120.  
  1121.                             SPrintf(FileInfo -> fib_FileName,"%s.info",ScanNode -> ln_Name);
  1122.  
  1123.                             ScanNode = ScanNode -> ln_Succ;
  1124.  
  1125.                             ReleaseSemaphore(&NameSemaphore);
  1126.  
  1127.                             return(DOSTRUE);
  1128.                         }
  1129.  
  1130.                         ScanNode = ScanNode -> ln_Succ;
  1131.                     }
  1132.                 }
  1133.  
  1134.                 ReleaseSemaphore(&NameSemaphore);
  1135.  
  1136.                 SetIoErr(ERROR_NO_MORE_ENTRIES);
  1137.  
  1138.                 return(DOSFALSE);
  1139.             }
  1140.         }
  1141.     }
  1142.  
  1143.         /* Jump into original routine. */
  1144.  
  1145.     return(MyExNext(FileLock,FileInfo));
  1146. }
  1147.  
  1148.     /* NewOpen():
  1149.      *
  1150.      *    Patched dos.library routine, opens the fake icon files
  1151.      *    produced by the patched Examine/ExNext routines.
  1152.      */
  1153.  
  1154. BPTR __saveds __asm
  1155. NewOpen(register __d1 UBYTE *Name,register __d2 LONG Mode)
  1156. {
  1157.     UBYTE Buffer[108];
  1158.  
  1159.         /* Is it Workbench who's calling? */
  1160.  
  1161.     if(!strcmp(SysBase -> ThisTask -> tc_Node . ln_Name,"Workbench"))
  1162.     {
  1163.             /* Is there a list to scan? */
  1164.  
  1165.         if(ScanNode)
  1166.         {
  1167.             struct Node    *Node;
  1168.             SHORT         i;
  1169.  
  1170.                 /* Extract the base file name. */
  1171.  
  1172.             strcpy(Buffer,Name);
  1173.  
  1174.             for(i = strlen(Buffer) ; i >= 0; i--)
  1175.             {
  1176.                 if(!StrCmp(&Buffer[i],".info"))
  1177.                 {
  1178.                     Buffer[i] = 0;
  1179.                     break;
  1180.                 }
  1181.             }
  1182.  
  1183.                 /* Try to find the approriate icon file. */
  1184.  
  1185.             if(Node = (struct Node *)MyFindName(&NameList,Buffer))
  1186.             {
  1187.                     /* Change the name of the icon file
  1188.                      * into the approriate default icon
  1189.                      * type.
  1190.                      */
  1191.  
  1192.                 SPrintf(Buffer,"ENV:sys/def_%s.info",NameInfo[Node -> ln_Type] . Name);
  1193.  
  1194.                 Name = Buffer;
  1195.             }
  1196.         }
  1197.     }
  1198.  
  1199.         /* Jump into original routine. */
  1200.  
  1201.     return(MyOpen(Name,Mode));
  1202. }
  1203.  
  1204.     /* NewClearMenuStrip():
  1205.      *
  1206.      *    Patched intuition.libary routine, checks the Workbench menu
  1207.      *    to determine whether we are to create fake icons or not.
  1208.      */
  1209.  
  1210. VOID __saveds __asm
  1211. NewClearMenuStrip(register __a0 struct Window *Window)
  1212. {
  1213.     struct Menu    *Menu;
  1214.     struct MenuItem    *MenuItem,*SubItem;
  1215.  
  1216.     FakeScan = FALSE;
  1217.  
  1218.         /* Is this a Workbench window? */
  1219.  
  1220.     if(Window -> Flags & WFLG_WBENCHWINDOW)
  1221.     {
  1222.         Menu = Window -> MenuStrip;
  1223.  
  1224.             /* Walk through the menus... */
  1225.  
  1226.         while(Menu && !FakeScan)
  1227.         {
  1228.             MenuItem = Menu -> FirstItem;
  1229.  
  1230.                 /* Walk through the menu items... */
  1231.  
  1232.             while(MenuItem && !FakeScan)
  1233.             {
  1234.                 SubItem = MenuItem -> SubItem;
  1235.  
  1236.                     /* Walk through the sub items... */
  1237.  
  1238.                 while(SubItem && !FakeScan)
  1239.                 {
  1240.                         /* Sub item with item text? */
  1241.  
  1242.                     if(SubItem -> Flags & ITEMTEXT)
  1243.                     {
  1244.                             /* Is it the `All Files'
  1245.                              * subitem?
  1246.                              */
  1247.  
  1248.                         if(!strcmp(((struct IntuiText *)SubItem -> ItemFill) -> IText,"All Files"))
  1249.                         {
  1250.                                 /* See if it's
  1251.                                  * checked.
  1252.                                  */
  1253.  
  1254.                             if(SubItem -> Flags & CHECKED)
  1255.                                 FakeScan = TRUE;
  1256.                             else
  1257.                                 FakeScan = FALSE;
  1258.                         }
  1259.                     }
  1260.  
  1261.                     SubItem = SubItem -> NextItem;
  1262.                 }
  1263.  
  1264.                 MenuItem = MenuItem -> NextItem;
  1265.             }
  1266.  
  1267.             Menu = Menu -> NextMenu;
  1268.         }
  1269.     }
  1270.  
  1271.         /* Jump into original routine. */
  1272.  
  1273.     MyClearMenuStrip(Window);
  1274. }
  1275.