home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 5 / CD_Magazyn_EXEC_nr_5.iso / Programy / Programowanie / FetchRefs2.1.lha / FetchRefs2.1 / Source / FetchRefs / FindRef.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-28  |  20.1 KB  |  776 lines

  1. /* FindRef.c
  2. Originaly written by Anders Melchiorsen, modified by Roland Florac (SAS/C compiler) */
  3.  
  4. #include "FetchRefs.h"
  5.  
  6. static APTR __regargs NewMatchList (struct LayoutHandle * h);
  7. static LONG __regargs BuildRefList (struct FindRefOptions *args, struct LayoutHandle * h);
  8. static void __regargs FindRefInteractive (struct FindRefOptions *args, struct FindRefReturnStruct *ret);
  9. static void __regargs PutRef (struct ListViewNode *item, STRPTR destfile, struct FindRefReturnStruct *ret);
  10. static void SwitchToFileIndex (struct LayoutHandle * handle);
  11. static struct Screen * __regargs FindScreen (STRPTR pubname);
  12.  
  13. APTR ListPool;
  14. static struct List RefsFound;
  15.  
  16.  
  17. struct ListViewNode {
  18.  
  19. /* ln_name in the Node points to the string that is to be shown in the
  20.  * listview. ln_type is 1 for file references, 2 for normal ones.
  21.  *
  22.  * fileentry is a pointer to the FileEntry in which the reference is
  23.  *
  24.  * refsentry is a pointer to the reference to fetch.
  25.  *
  26.  * ListViewText is used if we build a new string for the listview.
  27.  */
  28.  
  29.     struct Node node;
  30.     struct FileEntry *fileentry;
  31.     struct RefsEntry *refsentry;
  32.     UBYTE ListViewText[0];
  33. };
  34.  
  35. /* GTLayout specifications */
  36. enum {    ID_LIST_WINDOW = 1,
  37.     ID_LIST_LIST, ID_LIST_PATTERN, ID_LIST_OK, ID_LIST_FILE, ID_LIST_CANCEL
  38.      };
  39.  
  40. __saveds __asm char * LocaleHookFunc (register __a0 struct Hook * UnusedHook, register __a2 APTR Unused, register __a1 long ID)
  41. {
  42.     return GetString(ID);
  43. }
  44.  
  45. struct Hook LocaleHook = { 0, 0, (HOOKFUNC) LocaleHookFunc, 0, 0 };
  46.  
  47. static void __regargs New_Horizontal_group (struct LayoutHandle * Handle, long frame)
  48. {   long i = 1;
  49.     struct TagItem tags[6];
  50.     tags[0].ti_Tag = LA_Type;
  51.     tags[0].ti_Data = HORIZONTAL_KIND;
  52.     if (frame)
  53.     {    tags[i].ti_Tag = LAGR_SameSize; tags[i].ti_Data = TRUE; i++;
  54.     tags[i].ti_Tag = LAGR_Frame;    tags[i].ti_Data = TRUE; i++;
  55.     }
  56.     tags[i].ti_Tag = TAG_DONE;
  57.     LT_NewA (Handle, tags);
  58. }
  59.  
  60. static void __regargs New_Vertical_group (struct LayoutHandle * Handle, long frame)
  61. {   long i = 1;
  62.     struct TagItem tags[4];
  63.     tags[0].ti_Tag = LA_Type;
  64.     tags[0].ti_Data = VERTICAL_KIND;
  65.     if (frame)
  66.     {    tags[i].ti_Tag = LAGR_Frame;    tags[i].ti_Data = TRUE;     i++;    }
  67.     tags[i].ti_Tag = TAG_DONE;
  68.     LT_NewA (Handle, tags);
  69. }
  70.  
  71. void TellWeStopOutline (void)
  72. {
  73.     struct LayoutHandle * h;
  74.     struct Window * w;
  75.  
  76.     h = LT_CreateHandleTags (0, LAHN_LocaleHook, &LocaleHook, TAG_DONE);
  77.     if (h)
  78.     {
  79.     New_Vertical_group (h, 1);
  80.     {
  81.         LT_New (h,
  82.         LA_Type,    BOX_KIND,
  83.         LABX_AlignText, ALIGNTEXT_Centered,
  84.         LABX_Line,    GetString(TEXTE_REMOVE),
  85.         LABX_DrawBox,    TRUE,
  86.         LABX_DrawBox,    FALSE,
  87.         TAG_DONE);
  88.         LT_EndGroup (h);
  89.     }
  90.     w = LT_Build (h,
  91.         LAWN_Title,     "FetchRefs "VERSION,
  92.         WA_DepthGadget, TRUE,
  93.         WA_RMBTrap,     TRUE,
  94.         WA_DragBar,     TRUE,
  95.         WA_Activate,    FALSE,
  96.     TAG_DONE);
  97.     if (w)
  98.         Delay (TICKS_PER_SECOND);
  99.     LT_DeleteHandle (h);
  100.     }
  101. }
  102.  
  103. static struct LayoutHandle * __regargs ReferenceList (struct Screen * scr)
  104. {
  105.     struct LayoutHandle * h;
  106.     struct Window * w;
  107.  
  108.     h = LT_CreateHandleTags (scr, LAHN_LocaleHook, &LocaleHook, TAG_DONE);
  109.     if (h)
  110.     {
  111.  
  112.     New_Vertical_group (h, 0);
  113.     {
  114.         LT_New (h,
  115.         LA_Type,    LISTVIEW_KIND,
  116.         GTLV_Selected,    0,
  117.         LALV_Link,    NIL_LINK,
  118.         LA_Chars,    60,
  119.         LALV_CursorKey, TRUE,
  120.         LALV_ResizeY,    TRUE,
  121.         LALV_ResizeX,    TRUE,
  122.         LALV_MinLines,    10,
  123.         LALV_Lines,    scr->Height > 256 ? 20 : 10,
  124.         GTLV_Labels,    &RefsFound,
  125.         LA_ID,        ID_LIST_LIST,
  126.         TAG_DONE);
  127.         New_Horizontal_group (h, 0);
  128.         {
  129.         LT_New (h,
  130.             LA_Type,        STRING_KIND,
  131.             LA_LabelID,     TEXTE_FIND_PATTERN,
  132.             LA_LabelPlace,  PLACE_Left,
  133.             LA_ID,        ID_LIST_PATTERN,
  134.             LA_Chars,        48,
  135.         TAG_DONE);
  136.         LT_EndGroup (h);
  137.         }
  138.         New_Horizontal_group (h, 1);
  139.         {
  140.         LT_New (h,
  141.             LA_Type,    BUTTON_KIND,
  142.             LA_ID,    ID_LIST_OK,
  143.             LA_LabelID, TEXTE_FETCHREF,
  144.             LABT_ReturnKey, TRUE,
  145.             LABT_ExtraFat, TRUE,
  146.         TAG_DONE);
  147.         LT_New (h,
  148.             LA_Type,    BUTTON_KIND,
  149.             LA_ID,    ID_LIST_FILE,
  150.             LA_LabelID, TEXTE_LISTE,
  151.         TAG_DONE);
  152.         LT_New (h,
  153.             LA_Type,    BUTTON_KIND,
  154.             LA_ID,    ID_LIST_CANCEL,
  155.             LA_LabelID, TEXTE_CANCEL,
  156.         TAG_DONE);
  157.         LT_EndGroup (h);
  158.         }
  159.         LT_EndGroup (h);
  160.     }
  161.     w = LT_Build (h,
  162.         LAWN_Title,     GetString (TEXTE_REFERENCE),
  163.         WA_ScreenTitle, GetString (TEXTE_VERSION),
  164.         LAWN_IDCMP,     IDCMP_CLOSEWINDOW | CHECKBOXIDCMP | IDCMP_RAWKEY,
  165.         WA_DepthGadget, TRUE,
  166.         WA_RMBTrap,     TRUE,
  167.         WA_DragBar,     TRUE,
  168.         WA_Activate,    TRUE,
  169.         WA_CloseGadget, TRUE,
  170.     TAG_DONE);
  171.     if (w)
  172.         return h;
  173.     LT_DeleteHandle (h);
  174.     }
  175.     return 0;
  176. }
  177.  
  178. static long __regargs compute_string_length (struct List * RefsFound)
  179. {
  180.     struct ListViewNode * vn;
  181.     long len = 0;
  182.  
  183.     for (vn = (struct ListViewNode *) RefsFound->lh_Head;
  184.         vn->node.ln_Succ;
  185.         vn = (struct ListViewNode *) vn->node.ln_Succ)
  186.     {
  187.     len += strlen(vn->fileentry->Name) + 1;
  188.     }
  189.     return len;
  190. }
  191.  
  192. static void __regargs copy_strings (struct List * RefsFound, char * dest)
  193. {
  194.     struct ListViewNode * vn;
  195.     char * r = dest;
  196.  
  197.     for (vn = (struct ListViewNode *) RefsFound->lh_Head;
  198.         vn->node.ln_Succ;
  199.         vn = (struct ListViewNode *) vn->node.ln_Succ)
  200.     {
  201.     strcpy (r, vn->fileentry->Name);
  202.     r += strlen(r);
  203.     if (vn->node.ln_Succ)
  204.     {
  205.         * r = 10;
  206.         r++;
  207.     }
  208.     }
  209.     *r = 0;
  210. }
  211.  
  212. /* FindRef() - interface to fetch a reference to file
  213.  * Actual look-up routine. Copies the reference to 'ref' into a file */
  214. void __regargs FindRef (struct FindRefOptions * args, struct FindRefReturnStruct * ret)
  215. {
  216.     LONG refsfound = 0, l;
  217.     UBYTE pattern[128], * refs;
  218.  
  219.     /* Assume failure until proven wrong */
  220.     ret->Result = RET_FAULT;
  221.     ret->Number = ERROR_NO_FREE_STORE;
  222.  
  223.     if (! NewMatchList(0))
  224.     goto error;
  225.     /* Build a list of references matching the requested one */
  226.  
  227.     /* If the search  pattern  turns out to be blank we show
  228.      * the "references found" window anyway -- to allow the
  229.      * user to enter a new one. */
  230.  
  231.     if (ParsePatternNoCase (args->Reference, pattern, 128) != -1)
  232.     if (MatchPatternNoCase (pattern, ""))
  233.         refsfound = 2;
  234.  
  235.     if (!refsfound)
  236.     {
  237.     refsfound = BuildRefList (args, 0);
  238.  
  239.     if (refsfound > 0)
  240.     {
  241.         ret->Result = refsfound;
  242.         goto error;
  243.     }
  244.     else
  245.         refsfound = -refsfound;
  246.     }
  247.  
  248.     if (args->function == FR_FILE)
  249.     {
  250.     if (refsfound > 0)
  251.     {
  252.         l = compute_string_length (&RefsFound);
  253.         if (refs = AllocVec (l + 1, MEMF_PUBLIC | MEMF_CLEAR))
  254.         {
  255.         copy_strings (&RefsFound, refs);
  256.         args->Reference = refs;
  257.         ret->Result = RET_MATCH;
  258.         }
  259.         else
  260.         ret->Result = RET_NO_MATCH;
  261.     }
  262.     else
  263.         ret->Result = RET_NO_MATCH;
  264.     }
  265.     else if (args->function == FR_REQ)
  266.     FindRefInteractive (args, ret);
  267.     else
  268.     {
  269.     /* If exactly one match was found we simply fetch it. Otherwise we
  270.      * ask the user for further help. */
  271.     if (refsfound == 1)
  272.         PutRef ((struct ListViewNode *) RefsFound.lh_Head, args->DestFile, ret);
  273.     else if (refsfound > 1)
  274.         FindRefInteractive (args, ret);
  275.     else
  276.         ret->Result = RET_NO_MATCH;
  277.     }
  278. error:
  279.     /* Free the list */
  280.     LibDeletePool (ListPool);
  281.     ListPool = NULL;
  282. }
  283.  
  284. /* FindRefInteractive() - open window and ask which reference to use */
  285. static void __regargs FindRefInteractive (struct FindRefOptions *args, struct FindRefReturnStruct * ret)
  286. {
  287.     struct Screen *scr;
  288.     BOOL swappedscreen = FALSE;
  289.     struct LayoutHandle * h;
  290.     ULONG signal;
  291.     struct IntuiMessage * message;
  292.     struct ListViewNode * f;
  293.  
  294.     /* Get a pointer to the Screen to open on. The screen is
  295.      * LockPubScreen()'ed and we must unlock (is done further down).
  296.      */
  297.     if (!(scr = FindScreen (args->PubScreen)))
  298.     return;
  299.  
  300.     /* Bring the screen to the front if it is not already there */
  301.     if (IntuitionBase->FirstScreen != scr)
  302.     {    ScreenToFront (scr);
  303.     swappedscreen = TRUE;
  304.     }
  305.  
  306.     h = ReferenceList (scr);
  307.     if (h)
  308.     {
  309.     if (IsListEmpty (&RefsFound))
  310.     {
  311.         /* Disable fetch gadgets if the references window is empty */
  312.         LT_SetAttributes (h, ID_LIST_FILE, GA_Disabled, TRUE, TAG_END);
  313.         LT_SetAttributes (h, ID_LIST_OK, GA_Disabled, TRUE, TAG_END);
  314.         DisplayBeep(0);
  315.     }
  316.     else
  317.     {
  318.         /* Copy the search pattern into the string gadget buffer */
  319.         LT_SetAttributes (h, ID_LIST_PATTERN, GTST_String, args->Reference, TAG_END);
  320.     }
  321.     args->Reference = (STRPTR) LT_GetAttributes (h, ID_LIST_PATTERN, TAG_DONE);
  322.     ret->Result = RET_NO_MATCH;
  323.     signal = 1 << h->Window->UserPort->mp_SigBit;
  324.     do
  325.     {   Wait (signal);
  326.         while (message = LT_GetIMsg (h))
  327.         {    switch (message->Class)
  328.         {   case IDCMP_CLOSEWINDOW:
  329.             ret->Result = RET_ABORT;
  330.             break;
  331.             case IDCMP_RAWKEY:
  332.             if (message->Code == 0x5F)
  333.                 GiveHelp (scr);
  334.             break;
  335.             case IDCMP_GADGETUP:
  336.             switch (((struct Gadget *) message->IAddress)->GadgetID)
  337.             {
  338.                 case ID_LIST_OK:
  339.                 {
  340. list:
  341.                 LT_LockWindow (h->Window);
  342.                 /* Find the selected node and fetch it */
  343.                 f = ListOffsetToPtr (&RefsFound, LT_GetAttributes (h, ID_LIST_LIST, TAG_DONE));
  344.                 PutRef (f, args->DestFile, ret);
  345.                 LT_UnlockWindow (h->Window);
  346.                 break;
  347.                 }
  348.                 case ID_LIST_FILE:
  349.                 SwitchToFileIndex (h);
  350.                 break;
  351.                 case ID_LIST_CANCEL:
  352.                 ret->Result = RET_ABORT;
  353.                 break;
  354.                 case ID_LIST_PATTERN:
  355.                 LT_LockWindow (h->Window);
  356.  
  357.                 if (BuildRefList (args, h) == 0)
  358.                 {
  359.                     /* Disable fetch and 'list file' gadget if no references are
  360.                      * found. */
  361.                     LT_SetAttributes (h, ID_LIST_FILE, GA_Disabled, TRUE, TAG_END);
  362.                     LT_SetAttributes (h, ID_LIST_OK, GA_Disabled, TRUE, TAG_END);
  363.                 }
  364.                 else
  365.                 {
  366.                     /* As we get a new list we can once again do ID_LIST_FILE
  367.                      * and fetch a reference */
  368.                     LT_SetAttributes (h, ID_LIST_FILE, GA_Disabled, FALSE, TAG_END);
  369.                     LT_SetAttributes (h, ID_LIST_OK, GA_Disabled, FALSE, TAG_END);
  370.                 }
  371.  
  372.                 /* Now actually display the new list */
  373.                 LT_SetAttributes (h, ID_LIST_LIST, GTLV_Labels, (ULONG)&RefsFound, TAG_END);
  374.  
  375.                 /* And finally re-activate the GUI */
  376.                 LT_UnlockWindow (h->Window);
  377.                 break;
  378.             }
  379.             break;
  380.             case IDCMP_IDCMPUPDATE:
  381.             goto list;
  382.         }
  383.         LT_ReplyIMsg (message);
  384.         }
  385.     }
  386.     while (ret->Result == RET_NO_MATCH);
  387.     LT_DeleteHandle (h);
  388.     }
  389.     if (swappedscreen)
  390.     ScreenToBack (scr);
  391.     UnlockPubScreen (NULL, scr);
  392. }
  393.  
  394. /* GiveHelp() - open guide positioned at the help for <id> */
  395. void __regargs GiveHelp (struct Screen * scr)
  396. {
  397.     struct Library *AmigaGuideBase;
  398.     struct NewAmigaGuide nag = { NULL };
  399.     AMIGAGUIDECONTEXT handle;
  400.  
  401.     nag.nag_Name = "FetchRefs_FR.guide";
  402.     nag.nag_Screen = scr;
  403.     nag.nag_Node = "4.";
  404.  
  405.     /* Show the guide */
  406.     if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 34))
  407.     {
  408.     if (handle = OpenAmigaGuideA (&nag, NULL))
  409.         CloseAmigaGuide (handle);
  410.     else
  411.         PostMessage (GetString (TEXTE_GUIDE));
  412.  
  413.     CloseLibrary (AmigaGuideBase);
  414.     }
  415.     else
  416.     PostMessage (GetString (TEXTE_AMIGAGUIDE));
  417. }
  418.  
  419. /* NewMatchList() - free the list (if any) of matches and allocate new one */
  420. static APTR __regargs NewMatchList (struct LayoutHandle * h)
  421. {
  422.     /* Empty the list and create a new, empty one. Empty the listview, too */
  423.     if (h)
  424.     LT_SetAttributes (h, ID_LIST_LIST, GTLV_Labels, (ULONG)~0, TAG_END);
  425.  
  426.     NewList (&RefsFound);
  427.  
  428.     if (h)
  429.     {
  430.     LT_SetAttributes (h, ID_LIST_LIST, GTLV_Labels, (ULONG)&RefsFound, TAG_END);
  431.     LT_SetAttributes (h, ID_LIST_LIST, GTLV_Labels, (ULONG)~0, TAG_END);
  432.     }
  433.  
  434.     LibDeletePool (ListPool);
  435.     return (ListPool = LibCreatePool (NULL, 8192, 8192));
  436. }
  437.  
  438. /* PutRef() - writes a reference to file */
  439. /* Write the reference. Handles the writing both to a normal file and to the
  440.  * clipboard (through iffparse.library). */
  441. #define ID_FTXT MAKE_ID('F','T','X','T')
  442. #define ID_CHRS MAKE_ID('C','H','R','S')
  443. static void __regargs PutRef (struct ListViewNode *item, STRPTR destfile, struct FindRefReturnStruct *ret)
  444. {
  445.     BPTR from;
  446.     STRPTR buf = NULL;
  447.     LONG fetchfrom, fetchlength;
  448.  
  449.     /* Figure out the actual file length if the reference is a complete file.
  450.      * Otherwise just grab the reference size from the list.
  451.      */
  452.     fetchfrom = 0;
  453.     fetchlength = -1;
  454.     if (item->node.ln_Type == 2)
  455.     {
  456.     fetchfrom = item->refsentry->Offset;
  457.     fetchlength = item->refsentry->Length;
  458.     }
  459.     if (fetchlength == -1)
  460.     fetchlength = FileLength (item->fileentry->Name);
  461.  
  462.     /* Attempt to open file, allocate memory, and read reference */
  463.     if (from = Open (item->fileentry->Name, MODE_OLDFILE))
  464.     {
  465.     if (buf = LibAllocPooled (ListPool, fetchlength))
  466.     {
  467.         Seek (from, fetchfrom, OFFSET_BEGINNING);
  468.         Read (from, buf, fetchlength);
  469.     }
  470.  
  471.     Close (from);
  472.     }
  473.     else
  474.     ret->Number = IoErr();
  475.  
  476.     /* Now write the reference */
  477.     if (buf)
  478.     {
  479.     /* Write to a normal file if destination is not "CLIP#?" */
  480.     if (strncmp (destfile, "CLIP", 4) != 0)
  481.     {
  482.         BPTR to;
  483.  
  484.         if (to = Open (destfile, MODE_NEWFILE))
  485.         {
  486.         if (Write (to, buf, fetchlength) == fetchlength)
  487.             ret->Result = RET_MATCH;
  488.         else
  489.             ret->Number = IoErr();
  490.  
  491.         Close (to);
  492.         } else
  493.         ret->Number = IoErr();
  494.  
  495.     }
  496.     else  /* Write to a clipboard unit */
  497.     {
  498.         struct Library *IFFParseBase;
  499.         if (IFFParseBase = OpenLibrary ("iffparse.library", 37))
  500.         {
  501.         struct IFFHandle *iff;
  502.  
  503.         if (iff = AllocIFF())
  504.         {
  505.             if (iff->iff_Stream = (unsigned long) OpenClipboard (atoi(&(destfile[4]))))
  506.             {
  507.             InitIFFasClip(iff);
  508.             if (OpenIFF(iff, IFFF_WRITE) == 0)
  509.             {
  510.                 if (PushChunk (iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN) == 0)
  511.                 {
  512.                 if (PushChunk (iff, 0, ID_CHRS, fetchlength) == 0)
  513.                 {
  514.                     if (WriteChunkBytes (iff, buf, fetchlength) == fetchlength)
  515.                     {
  516.                     if (PopChunk (iff) == 0)
  517.                         ret->Result = RET_MATCH;
  518.                     }
  519.                     PopChunk (iff);
  520.                 }
  521.                 }
  522.                 CloseIFF (iff);
  523.             }
  524.             CloseClipboard ((struct ClipboardHandle *)iff->iff_Stream);
  525.             }
  526.             FreeIFF (iff);
  527.         }
  528.         CloseLibrary (IFFParseBase);
  529.         }
  530.     }
  531.     }
  532.  
  533.     /* If we wrote the reference we can return what line number to jump to.
  534.      * For a file reference this is zero.
  535.      */
  536.     if (ret->Result == RET_MATCH)
  537.     ret->Number = (item->node.ln_Type == 1) ? 0 : item->refsentry->Goto;
  538. }
  539.  
  540. /* BuildRefList() - builds a list of all the matching references */
  541. /* This is a call back function for the sort routine.. */
  542. BOOL __regargs SortListFunct (struct ListViewNode *a, struct ListViewNode *b, ULONG data)
  543. {   BOOL r;
  544.     /* Sort alphabetically */
  545.     if (a->node.ln_Type == b->node.ln_Type)
  546.     {    r = ( stricmp (a->node.ln_Name, b->node.ln_Name) > 0 );
  547.     return r;
  548.     }
  549.  
  550.     /* Put files at the top */
  551.     r = (a->node.ln_Type == 2);
  552.     return r;
  553. }
  554.  
  555. static LONG __regargs BuildRefList (struct FindRefOptions *args, struct LayoutHandle * h)
  556. {
  557.     STRPTR pattern;
  558.     LONG numofrefs = 0, len, res;
  559.     struct RefsEntry *currref;
  560.     struct FileEntry *currfile;
  561.  
  562.     /* First of all: Initialize the list of matching references */
  563.     if (! NewMatchList (h))
  564.     return ERROR_NO_FREE_STORE;
  565.  
  566.     /* Tokenize pattern string */
  567.     len = strlen (args->Reference) * 2 + 2;
  568.  
  569.     /* We just return as fail code is already set above */
  570.     if (! (pattern = LibAllocPooled (ListPool, len)))
  571.     return ERROR_NO_FREE_STORE;
  572.  
  573.     /* Tokenize the search string */
  574.     if (args->Case)
  575.     res = ParsePattern (args->Reference, pattern, len);
  576.     else
  577.     res = ParsePatternNoCase (args->Reference, pattern, len);
  578.  
  579.     if (res == -1)
  580.     return ERROR_TOO_MANY_LEVELS;
  581.  
  582.     /* Pick up all references */
  583.     for (currfile = (struct FileEntry *) FileList.lh_Head;
  584.         currfile->node.ln_Succ;
  585.         currfile = (struct FileEntry *) currfile->node.ln_Succ)
  586.     {
  587.     /* Check for a match on the file name */
  588.     if (args->FileRef)
  589.     {
  590.         UBYTE name[108], *cutptr;
  591.         /* Isolate the base name (eg. 'INCLUDE:libraries/dos.h' -> 'dos') */
  592.         strcpy (name, FilePart (currfile->Name));
  593.         cutptr = name;
  594.         while (*cutptr)
  595.         {
  596.         if ((*cutptr >= 'a' && *cutptr <= 'z') ||
  597.             (*cutptr >= 'A' && *cutptr <= 'Z') ||
  598.             (*cutptr >= '0' && *cutptr <= '9') ||
  599.             (*cutptr == '_'))
  600.             cutptr++;
  601.         else
  602.             *cutptr = 0;
  603.         }
  604.  
  605.         /* Create an item to add to the RefsFound list */
  606.         if ((args->Case) ? MatchPattern(pattern, name) : MatchPatternNoCase(pattern, name))
  607.         {
  608.         struct ListViewNode *r;
  609.  
  610.         if (r = LibAllocPooled (ListPool, sizeof(struct ListViewNode)))
  611.         {
  612.             r->fileentry = currfile;
  613.             r->node.ln_Type = 1;
  614.             r->node.ln_Name = currfile->Name;
  615.  
  616.             AddTail (&RefsFound, &r->node);
  617.             numofrefs++;
  618.         }
  619.         }
  620.     }
  621.  
  622.     /* Check all the RefsEntry's in this FileEntry for a match */
  623.     for (currref = (struct RefsEntry *) currfile->RefsList.lh_Head;
  624.         currref->node.ln_Succ;
  625.         currref = (struct RefsEntry *) currref->node.ln_Succ)
  626.     {
  627.         if ((args->Case) ? MatchPattern(pattern, currref->Name) : MatchPatternNoCase(pattern, currref->Name))
  628.         {
  629.         struct ListViewNode *r;
  630.         if (r = LibAllocPooled (ListPool, sizeof(struct ListViewNode) + strlen(currfile->Name) + strlen(currref->Name) + 5))
  631.         {
  632.             r->fileentry = currfile;
  633.             r->refsentry = currref;
  634.             r->node.ln_Type = 2;
  635.             r->node.ln_Name = r->ListViewText;
  636.  
  637.             SPrintf (r->ListViewText, "%s => %s", currref->Name, currfile->Name);
  638.  
  639.             AddTail (&RefsFound, &r->node);
  640.             numofrefs++;
  641.         }
  642.         }
  643.     }
  644.     }
  645.     SortExecList (&RefsFound, SortListFunct, 0);
  646.  
  647.     /* Negate the number of matches; positive return code means failure */
  648.     return -numofrefs;
  649. }
  650.  
  651. static void SwitchToFileIndex (struct LayoutHandle * h)
  652. {
  653.     struct FileEntry *file;
  654.     struct RefsEntry *selectedref, *ref;
  655.     struct ListViewNode *selected;
  656.     LONG selectedpos = 0;
  657.  
  658.     LT_LockWindow (h->Window);
  659.     LT_SetAttributes (h, ID_LIST_FILE, GA_Disabled, TRUE, TAG_END);
  660.  
  661.     selected = ListOffsetToPtr (&RefsFound, LT_GetAttributes (h, ID_LIST_LIST, TAG_DONE));
  662.     file = selected->fileentry;
  663.     selectedref = selected->refsentry;
  664.  
  665.     if (! NewMatchList (h))
  666.     goto nomem;
  667.  
  668.     /* Build a new list */
  669.     for (ref = (struct RefsEntry *) file->RefsList.lh_Head;
  670.         ref->node.ln_Succ;
  671.         ref = (struct RefsEntry *) ref->node.ln_Succ)
  672.     {
  673.     struct ListViewNode *r;
  674.  
  675.     if (r = LibAllocPooled (ListPool, sizeof(struct ListViewNode) + strlen(ref->Name) + 4 + strlen(file->Name) + 1))
  676.     {
  677.         r->fileentry = file;
  678.         r->refsentry = ref;
  679.         r->node.ln_Type = 2;
  680.         r->node.ln_Name = r->ListViewText;
  681.         SPrintf (r->ListViewText, "%s => %s", ref->Name, file->Name);
  682.  
  683.         AddTail (&RefsFound, &r->node);
  684.     }
  685.     }
  686.  
  687.     SortExecList (&RefsFound, SortListFunct, 0);
  688.  
  689.     /* Figure out where the reference we started with has ended in new list */
  690.     for (selected = (struct ListViewNode *) RefsFound.lh_Head;
  691.         selected->node.ln_Succ;
  692.         selected = (struct ListViewNode *) selected->node.ln_Succ)
  693.     {
  694.     if (selected->refsentry == selectedref)
  695.         break;
  696.     selectedpos++;
  697.     }
  698.     if (!selected->node.ln_Succ)
  699.     selectedpos = 0;
  700.  
  701. nomem:
  702.     /* Update GUI */
  703.     LT_SetAttributes (h, ID_LIST_LIST, GTLV_Labels, (ULONG)&RefsFound, TAG_END);
  704.     LT_SetAttributes (h, ID_LIST_LIST, GTLV_Selected, selectedpos, TAG_END);
  705.     LT_SetAttributes (h, ID_LIST_LIST, GTLV_Top, selectedpos, TAG_END);
  706.  
  707.     LT_UnlockWindow (h->Window);
  708. }
  709.  
  710. /* FindScreen() - return best Screen, based prefered <pubname> PubScr name */
  711. static struct Screen * __regargs FindScreen (STRPTR pubname)
  712. {
  713.     struct Screen *s = NULL;
  714.  
  715.     /* A specific public screen is wanted */
  716.     if (pubname)
  717.     s = LockPubScreen (pubname);
  718.  
  719.     /* Go for the currently active screen */
  720.     if (!s)
  721.     {
  722.     UBYTE wantname[MAXPUBSCREENNAME+1];
  723.     struct Screen *wantscr;
  724.     struct List *publist;
  725.     struct PubScreenNode *pubnode;
  726.  
  727.     publist = LockPubScreenList();
  728.     wantscr = IntuitionBase->ActiveScreen;
  729.     pubnode = (struct PubScreenNode *) publist->lh_Head;
  730.     while (pubnode->psn_Node.ln_Succ)
  731.     {
  732.         if (pubnode->psn_Screen == wantscr)
  733.         strcpy (wantname, pubnode->psn_Node.ln_Name);
  734.         pubnode = (struct PubScreenNode *) pubnode->psn_Node.ln_Succ;
  735.     }
  736.     UnlockPubScreenList();
  737.     s = LockPubScreen (wantname);
  738.     }
  739.  
  740.     /* Last option: default public screen */
  741.     if (!s)
  742.     s = LockPubScreen (NULL);
  743.  
  744.     return s;
  745. }
  746.  
  747. /* FileLength() - returns file length or -1 for failure */
  748. LONG __regargs FileLength (STRPTR name)
  749. {
  750.     BPTR lock;
  751.     __aligned struct FileInfoBlock fib;
  752.  
  753.     if (lock = Lock (name, ACCESS_READ))
  754.     {
  755.     Examine (lock, &fib);
  756.     UnLock (lock);
  757.     return fib.fib_Size;
  758.     }
  759.     else
  760.     return -1;
  761. }
  762.  
  763. void * __regargs ListOffsetToPtr (struct List *l, LONG o)
  764. {
  765.     struct Node *n;
  766.  
  767.     if (o < 0)
  768.     return NULL;
  769.  
  770.     n = l->lh_Head;
  771.     while ((o--) && (n->ln_Succ))
  772.     n = n->ln_Succ;
  773.  
  774.     return (n->ln_Succ) ? n : NULL;
  775. }
  776.