home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / xref_v1.1.lha / XRef / Tools / golded / XRefAPI.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-29  |  30.6 KB  |  1,085 lines

  1. /*
  2. ** $PROJECT: XRef-GoldEDAPI
  3. **
  4. ** $VER: xrefapi.c 1.4 (16.09.94) 
  5. **
  6. ** by
  7. **
  8. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  9. **
  10. ** (C) Copyright 1994
  11. ** All Rights Reserved !
  12. **
  13. ** $HISTORY:
  14. **
  15. ** 16.09.94 : 001.004 :  some internal improvements
  16. ** 13.09.94 : 001.003 :  select window added
  17. ** 12.09.94 : 001.002 :  rexx command implemented
  18. ** 11.09.94 : 001.001 :  initial
  19. */
  20.  
  21. /* ------------------------------- include -------------------------------- */
  22.  
  23. #include "/source/Def.h"
  24.  
  25. #include <rexx/errors.h>
  26.  
  27. #include "/lib/xrefsupport.h"
  28.  
  29. #include "golded:api/include/golded.h"
  30.  
  31. #include "xrefapi_rev.h"
  32.  
  33. /* ------------------------------- AutoDoc -------------------------------- */
  34.  
  35. /*FS*/ /*"AutoDoc"*/
  36. /*GB*** XRef-Tools/XRefAPI ***************************************************
  37.  
  38. $VER: XRefAPI.doc
  39.  
  40. NAME
  41.     XRefAPI - GoldED API client for use with the xref.library to complete
  42.               phrases
  43.  
  44. FUNCTION
  45.     Just run GoldED and load this as an API-Client ! Then you have the
  46.     following new ARexx command :
  47.  
  48. TEMPLATE
  49.     XREFPHRASE CATEGORY/K,TYPES/K,MATCH/K,COMPLETEBEGIN/S,UPPERCASE/S,
  50.                SPACE/S
  51.  
  52. FORMAT
  53.     XREFPHRASE [CATEGORY <string|pattern>] [TYPES <to search for>]
  54.                [MATCH matchmode] [COMPLETEBEGIN] [UPPERCASE] [SPACE]
  55.  
  56.  
  57.  
  58. FUNCTION
  59.     the XREFPHRASE command tries to complete the current pharse (before 
  60.     the cursor) with the entries from the xref.library. This is done by
  61.     two algorithms :
  62.         - First uppercase letter match :
  63.             This means each character in the phrase must match the
  64.             next uppercase letter in the name ! For example :
  65.             the pharse "ow" matches "OpenWindow()" ("O"pen"W"indow())
  66.         - Second begin match :
  67.             The entry must match the beginning of the phrase !
  68.     There is a automatic two switch between to algorithms :
  69.         - if the pharse consists only of lower case letters the
  70.           uppercase letter match algorithm is used !
  71.         - if in the pharse is a uppercase letter the begin match
  72.           algorithm is used !
  73.     Note the matchmode RECURSIVE uses only the begin match algorithm !
  74.  
  75. INPUTS
  76.     CATEGORY (STRING) - category string|pattern to search in
  77.  
  78.     TYPES (STRING) - types, which would only match ("function","struct",
  79.         "function|struct" or so on)
  80.  
  81.     MATCH (STRING) - one of the following three matchmode strings 
  82.         (default is FIRST) :
  83.         FIRST - always get the first entry, which match the given pharse
  84.         RECURSIVE - much like a Tab-Completion algorithm, it search for
  85.             all entries matches the given phrase and complete it to the
  86.             last character equal to all entries ! If you pass UPPERCASE
  87.             argument the search is case-insenitive !
  88.             If you pass the phrase you passed last and cannot be more
  89.             completed, it switches to the SELECT matchmode and displays
  90.             the window !
  91.             This mode uses everytime the begin match algorithm !!!
  92.         SELECT - it searchs for all entries matching the given phrase and
  93.             if more than one is found, it opens a window you can select
  94.             one !
  95.  
  96.     COMPLETEBEGIN (BOOLEAN) - use the begin match algorithm instead of
  97.         uppercase letter match !
  98.  
  99.     UPPERCASE (BOOLEAN) - convert the phrase to upper
  100.  
  101.     SPACE (BOOLEAN) - if a name is found and inserted place a space behind
  102.  
  103. RESULTS
  104.     the command returns RC_OK, if it could complete the pharse. RC_WARN
  105.     if not !
  106.  
  107. EXAMPLE
  108.     'XREFPHRASE CATEGORY #?AutoDoc TYPES "function"' :
  109.  
  110.     This command will parse all AutoDoc categories and compare the given
  111.     shortcut with any function found in the xreffiles.For example the two
  112.     letters "ow" will completed to "OpenWindow(", if you have the
  113.     sys_autodoc.xref installed from the XRef-System package !
  114.  
  115. SEE ALSO
  116.     XRef-System.guide, GoldED/API, xref.library/ParseXRef(), ParseXRef
  117.  
  118. *****************************************************************************/
  119. /*FE*/
  120.  
  121. /* ------------------------------- defines -------------------------------- */
  122.  
  123. /*FS*/ /*"Defines"*/
  124. #define BUFFER_LEN         512
  125.  
  126. enum {
  127.    COMPLETE_UPPERCASELETTER,     /* complete phrase using characters as upper
  128.                                   * case letters only in the string
  129.                                   */
  130.    COMPLETE_BEGIN,               /* comlete phrase using given WORD as the
  131.                                   * beginning of the WORD
  132.                                   */
  133.    COMPLETE_BEGIN_NOCASE,        /* same as COMPLETE_BEGIN, but case-insensitive
  134.                                   */
  135.    COMPLETE_RECURSIVE,           /* tab-completion like algrorithm */
  136.    COMPLETE_RECURSIVE_NOCASE,    /* same as COMPLETE_RECURSIVE, case-insensitive */
  137.  
  138.    };
  139.  
  140.  
  141. enum {
  142.    MATCH_FIRST,
  143.    MATCH_RECURSIVE,
  144.    MATCH_SELECT,
  145.    };
  146.  
  147. #define XREFPHRASE_ARGS          "CATEGORY/K,TYPES/K,MATCH/K,COMPLETEBEGIN/S,UPPERCASE/S,SPACE/S"
  148.  
  149. #define MAX_PARAMETER            6
  150.  
  151. #define EOS                      '\0'
  152.  
  153. #define USETAG(tag,check)        ((check) ? (tag) : TAG_IGNORE)
  154.  
  155. #define PUDDLE_SIZE              512
  156.  
  157. #define XDISTANCE                8
  158. #define YDISTANCE                4
  159.  
  160. /*FE*/
  161.  
  162. /* ----------------------------- structures ------------------------------- */
  163.  
  164. /*FS*/ /*"Structures"*/
  165. struct RexxCommands
  166. {
  167.    STRPTR rxc_Command;
  168.    LONG (*rxc_Handler) (struct GlobalData *,struct APIMessage *);
  169.    STRPTR rxc_Template;
  170. };
  171.  
  172. struct GlobalData
  173. {
  174.    struct MsgPort *gd_ApiPort;
  175.    struct MsgPort *gd_RexxPort;
  176.  
  177.    STRPTR gd_GoldEDHost;
  178.  
  179.    ULONG gd_Result;
  180.    ULONG gd_Mode;
  181.    ULONG gd_Match;
  182.    LONG gd_Found;
  183.  
  184.    APTR gd_FoundPool;
  185.    struct List gd_FoundList;
  186.  
  187.    struct Hook gd_Hook;
  188.  
  189.    ULONG gd_Para[MAX_PARAMETER];
  190.  
  191.    UBYTE gd_Buffer[BUFFER_LEN];
  192.    UBYTE gd_Name[BUFFER_LEN];
  193.    UBYTE gd_LastName[BUFFER_LEN];
  194.  
  195.    struct Library *gd_XRefBase;
  196. };
  197.  
  198. #define XRefBase     gd->gd_XRefBase
  199. /*FE*/
  200.  
  201. /* ------------------------------ prototypes ------------------------------ */
  202.  
  203. /*FS*/ /*"Prototypes"*/
  204. RegCall GetA4 ULONG hook(REGA0 struct Hook *hook,REGA2 struct XRefFileNode *xref,REGA1 struct xrmXRef *msg);
  205.  
  206. void search_command(struct GlobalData *gd,struct APIMessage *msg);
  207.  
  208. LONG RexxCmd_XRefPhrase(struct GlobalData *gd,struct APIMessage *msg);
  209.  
  210. BOOL alloc_name(struct GlobalData *gd,STRPTR name);
  211.  
  212. BOOL send_rexxcommand(struct GlobalData *gd,STRPTR cmd);
  213.  
  214. struct Node *select_node(struct List *list,struct Screen *screen);
  215.  
  216. void parse_typestring(STRPTR typestr,ULONG *typearray);
  217.  
  218.  
  219. /*FE*/
  220.  
  221. /* -------------------------- static data items --------------------------- */
  222.  
  223. /*FS*/ /*"Contants"*/
  224. static const STRPTR version = VERSTAG;
  225. static const STRPTR prgname = "XRefAPI";
  226.  
  227. static struct RexxCommands rexxcmd[] = {
  228.    {"XREFPHRASE",RexxCmd_XRefPhrase,XREFPHRASE_ARGS},
  229.    {NULL}};
  230.  
  231. static const STRPTR xreftype_names[XREFT_MAXTYPES] = {
  232.    "generic",
  233.    "function",
  234.    "command",
  235.    "include",
  236.    "macro",
  237.    "struct",
  238.    "field",
  239.    "typedef",
  240.    "define"};
  241.  
  242. static struct TagItem xrefapitags[] = {
  243.    {API_Client_Name       ,(ULONG) "XRefAPI"},
  244.    {API_Client_Copyright  ,(ULONG) "©1994 Stefan Ruppert"},
  245.    {API_Client_Purpose    ,(ULONG) VERS "\n\nPhrase completion with xref.library"},
  246.    {API_Client_Template   ,(ULONG) "XREFPHRASE " XREFPHRASE_ARGS},
  247.    {TAG_DONE,}};
  248.  
  249. static STRPTR matchmodes[] = {
  250.    "FIRST",
  251.    "RECURSIVE",
  252.    "SELECT",
  253.    NULL};
  254. /*FE*/
  255.  
  256. /* ------------------------- template definition -------------------------- */
  257.  
  258. /*FS*/ /*"Program Template"*/
  259. #define template    "HOST/K/A"
  260.  
  261. enum {
  262.    ARG_HOST,
  263.    ARG_MAX};
  264. /*FE*/
  265.  
  266. /* --------------------------- main entry point --------------------------- */
  267.  
  268. /*FS*/ /*"int main(void)"*/
  269. int main(void)
  270. {
  271.    struct RDArgs *args;
  272.    LONG para[ARG_MAX];
  273.    STRPTR obj = prgname;
  274.    LONG err = 0;
  275.  
  276.    LONG i;
  277.  
  278.    /* clear args buffer */
  279.    for(i = 0 ; i < ARG_MAX ; i++)
  280.       para[i] = 0;
  281.  
  282.    /* here set your defaults : para[ARG_#?] = default_value; */
  283.  
  284.    if(args = ReadArgs(template,para,NULL))
  285.    {
  286.       struct GlobalData *gd;     
  287.  
  288.       DB(("golded host : %s\n",para[ARG_HOST]));
  289.       if((gd = AllocMem(sizeof(struct GlobalData),MEMF_ANY | MEMF_CLEAR)))
  290.       {
  291.          if((gd->gd_ApiPort = CreateMsgPort()))
  292.          {
  293.             if((gd->gd_RexxPort = CreateMsgPort()))
  294.             {
  295.                gd->gd_GoldEDHost   = (STRPTR)   para[ARG_HOST];
  296.                gd->gd_Hook.h_Entry = (HOOKFUNC) hook;
  297.                gd->gd_Hook.h_Data  = gd;
  298.  
  299.                sprintf(gd->gd_Buffer,"API PORT=%ld MASK=%ld",
  300.                                      gd->gd_ApiPort,
  301.                                      API_CLASS_ROOT | API_CLASS_REXX);
  302.  
  303.                if(send_rexxcommand(gd,gd->gd_Buffer) && gd->gd_Result == RC_OK)
  304.                {
  305.                   struct APIMessage *apimsg;
  306.                   struct APIMessage *msg;
  307.  
  308.                   BOOL active = TRUE;
  309.  
  310.                   DB(("xrefapi active !\n"));
  311.  
  312.                   do
  313.                   {
  314.                      WaitPort(gd->gd_ApiPort);
  315.  
  316.                      while((apimsg = (struct APIMessage *) GetMsg(gd->gd_ApiPort)))
  317.                      {
  318.                         for(msg = apimsg ; msg ; msg = msg->api_Next)
  319.                         {
  320.                            if(msg->api_State == API_STATE_NOTIFY)
  321.                            {
  322.                               switch(msg->api_Class)
  323.                               {
  324.                               case API_CLASS_ROOT:
  325.                                  switch(msg->api_Action)
  326.                                  {
  327.                                  case API_ACTION_DIE:
  328.                                     active = FALSE;
  329.                                     break;
  330.                                  case API_ACTION_INTRODUCE:
  331.                                     msg->api_Data = xrefapitags;
  332.                                     break;
  333.                                  }
  334.                                  break;
  335.                               case API_CLASS_REXX:
  336.                                  switch(msg->api_Action)
  337.                                  {
  338.                                  case API_ACTION_COMMAND:
  339.                                     search_command(gd,msg);
  340.                                     break;
  341.                                  default:
  342.                                     msg->api_Error = API_ERROR_UNKNOWN;
  343.                                  }
  344.                                  break;
  345.                               default:
  346.                                  msg->api_Error = API_ERROR_UNKNOWN;
  347.                               }
  348.                            }
  349.                         }
  350.  
  351.                         ReplyMsg((struct Message *) apimsg);
  352.                      }
  353.                   } while(active);
  354.                   SetIoErr(0);
  355.                }   
  356.                DeleteMsgPort(gd->gd_RexxPort);
  357.             }
  358.             DeleteMsgPort(gd->gd_ApiPort);
  359.          }
  360.          FreeMem(gd,sizeof(struct GlobalData));
  361.       }
  362.       FreeArgs(args);
  363.    }
  364.  
  365.    if(!err)
  366.       err = IoErr();
  367.  
  368.    if(err)
  369.    {
  370.       PrintFault(err,obj);
  371.       return(RETURN_ERROR);
  372.    }
  373.  
  374.    return(RETURN_OK);
  375. }
  376. /*FE*/
  377.  
  378. /* ---------------------- search for a given command ---------------------- */
  379.  
  380. /*FS*/ /*"void search_command(struct GlobalData *gd,struct APIMessage *msg)"*/
  381. void search_command(struct GlobalData *gd,struct APIMessage *msg)
  382. {
  383.    struct APIRexxNotify *notify = (struct APIRexxNotify *) msg->api_Data;
  384.    struct RexxCommands  *rxcmd  = rexxcmd;
  385.    LONG len;
  386.  
  387.    notify->arn_RC = RC_WARN;
  388.  
  389.    while(rxcmd->rxc_Command)
  390.    {
  391.       len = strlen(rxcmd->rxc_Command);
  392.  
  393.       if(!strncmp(notify->arn_Command,rxcmd->rxc_Command,len))
  394.       {
  395.          struct RDArgs *rdargs;
  396.          struct RDArgs *args;
  397.          LONG i;
  398.  
  399.          msg->api_State = API_STATE_CONSUMED;
  400.  
  401.          strncpy(gd->gd_Buffer,¬ify->arn_Command[len],BUFFER_LEN);
  402.          strncat(gd->gd_Buffer,"\n",BUFFER_LEN);
  403.  
  404.          if(rdargs = (struct RDArgs *) AllocDosObject(DOS_RDARGS,NULL))
  405.          {
  406.             rdargs->RDA_Source.CS_Buffer   = gd->gd_Buffer;
  407.             rdargs->RDA_Source.CS_Length   = strlen(gd->gd_Buffer);
  408.  
  409.             for(i=0 ; i < MAX_PARAMETER ; i++)
  410.                gd->gd_Para[i]=0;
  411.  
  412.             DB(("rdargs at : %lx\n",rdargs));
  413.             
  414.             if((args = ReadArgs(rxcmd->rxc_Template,(LONG *) gd->gd_Para,rdargs)))
  415.             {
  416.                DB(("args at %lx\n",args));
  417.  
  418.                notify->arn_RC = rxcmd->rxc_Handler(gd,msg);
  419.  
  420.                FreeArgs(args);
  421.             }
  422.             FreeDosObject(DOS_RDARGS , rdargs);
  423.          }
  424.       }
  425.       rxcmd++;
  426.    }
  427.  
  428.    if(notify->arn_RC != RC_OK)
  429.    {
  430.       Fault(IoErr(),"XRefAPI",gd->gd_Buffer,BUFFER_LEN);
  431.       notify->arn_CommandError = gd->gd_Buffer;
  432.    }
  433. }
  434. /*FE*/
  435.  
  436. /* ----------------------- xrefphrase rexx command ------------------------ */
  437.  
  438. /*FS*/ /*"LONG RexxCmd_XRefPhrase(struct GlobalData *gd,struct APIMessage *msg)"*/
  439.  
  440. /* templates arguments */
  441. enum {
  442.    ARG_CATEGORY,
  443.    ARG_TYPES,
  444.    ARG_MATCH,
  445.    ARG_COMPLETEBEGIN,
  446.    ARG_UPPERCASE,
  447.    ARG_SPACE,
  448.    };
  449.  
  450. LONG RexxCmd_XRefPhrase(struct GlobalData *gd,struct APIMessage *msg)
  451. {
  452.  
  453.    struct EditConfig *config = msg->api_Config;
  454.    LONG *para = gd->gd_Para;
  455.    ULONG types[XREFT_MAXTYPES + 1];
  456.  
  457.    UWORD  column;
  458.    UWORD len;
  459.    STRPTR wrd;
  460.    STRPTR buf;
  461.    STRPTR ptr;
  462.    STRPTR ptr2;
  463.    LONG retval = RC_WARN;
  464.  
  465.    column = config->Column;
  466.    buf    = config->Current;
  467.    wrd    = gd->gd_Buffer;
  468.  
  469.    /* terminate the types array */
  470.    types[0] = ~0;
  471.  
  472.    if(para[ARG_TYPES])
  473.       parse_typestring((STRPTR) para[ARG_TYPES],types);
  474.  
  475.    if(column && (buf[--column] > '@'))
  476.    {
  477.       STRPTR pattern = "#?";
  478.       ULONG xrefmatch = XREFMATCH_PATTERN_CASE;
  479.  
  480.       len = 1;
  481.       for(ptr = buf + column; column && (*(ptr - 1) > '@') ; --column, --ptr)
  482.          len++;
  483.  
  484.       movmem(ptr,wrd,len);
  485.       wrd[len] = 0;
  486.  
  487.       gd->gd_Mode = COMPLETE_UPPERCASELETTER;
  488.  
  489.       for(ptr2 = wrd; *ptr2 ; ptr2++)
  490.          if(isupper(*ptr2))
  491.          {
  492.             gd->gd_Mode = COMPLETE_BEGIN;
  493.             break;
  494.          }
  495.  
  496.       if(para[ARG_COMPLETEBEGIN])
  497.          gd->gd_Mode = COMPLETE_BEGIN;
  498.  
  499.       gd->gd_Match = MATCH_FIRST;
  500.       if(para[ARG_MATCH])
  501.       {
  502.          STRPTR *array = matchmodes;
  503.          ULONG i = MATCH_FIRST;
  504.  
  505.          while(*array)
  506.          {
  507.             if(!Stricmp(*array,(STRPTR) para[ARG_MATCH]))
  508.             {
  509.                gd->gd_Match = i;
  510.                break;
  511.             }
  512.             i++;
  513.             array++;
  514.          }
  515.          DB(("matchmode : %ld\n",gd->gd_Match));
  516.       }
  517.  
  518.       if(gd->gd_Match == MATCH_RECURSIVE)
  519.       {
  520.          if(!Stricmp(gd->gd_LastName,gd->gd_Buffer))
  521.          {
  522.             gd->gd_Match = MATCH_SELECT;
  523.  
  524.             if(para[ARG_UPPERCASE])
  525.                gd->gd_Mode = COMPLETE_BEGIN_NOCASE;
  526.             else
  527.                gd->gd_Mode = COMPLETE_BEGIN;
  528.          } else
  529.          {
  530.             strcpy(gd->gd_LastName,gd->gd_Buffer);
  531.  
  532.             if(para[ARG_UPPERCASE])
  533.                gd->gd_Mode = COMPLETE_RECURSIVE_NOCASE;
  534.             else
  535.                gd->gd_Mode = COMPLETE_RECURSIVE;
  536.          }
  537.       }
  538.  
  539.       if(gd->gd_Mode != COMPLETE_UPPERCASELETTER)
  540.       {
  541.          strcat(gd->gd_Buffer,"#?");
  542.          pattern = gd->gd_Buffer;
  543.  
  544.          if(para[ARG_UPPERCASE])
  545.             xrefmatch = XREFMATCH_PATTERN_NOCASE;
  546.       } else
  547.          for(ptr2 = wrd; *ptr2 ; ptr2++)
  548.             *ptr2 = toupper(*ptr2);
  549.  
  550.       DB(("word : %s\n",gd->gd_Buffer));
  551.  
  552.       /* cleanup */
  553.       NewList(&gd->gd_FoundList);
  554.       gd->gd_FoundPool = NULL;
  555.       gd->gd_Found     = 0;
  556.  
  557.       if((XRefBase = OpenLibrary("xref.library",1)))
  558.       {
  559.          if(ParseXRefTags(pattern,XREFA_XRefHook                               ,&gd->gd_Hook,
  560.                                   XREFA_Matching                               ,xrefmatch,
  561.                                   USETAG(XREFA_Category   ,para[ARG_CATEGORY]) ,para[ARG_CATEGORY],
  562.                                   USETAG(XREFA_AcceptTypes,para[ARG_TYPES])    ,types,
  563.                                   TAG_DONE))
  564.          {
  565.             if(gd->gd_Found > 1 && gd->gd_Match == MATCH_SELECT)
  566.             {
  567.                struct Screen *screen;
  568.  
  569.                if((screen = LockPubScreen(msg->api_Screen)))
  570.                {
  571.                   struct Node *node;
  572.  
  573.                   if((node = select_node(&gd->gd_FoundList,screen)))
  574.                   {
  575.                      strcpy(gd->gd_Name,node->ln_Name);
  576.                      gd->gd_Found =  1;
  577.                   } else
  578.                      gd->gd_Found = -1;
  579.                   UnlockPubScreen(NULL,screen);
  580.                }
  581.             }
  582.  
  583.             if(gd->gd_FoundPool)
  584.             {
  585.                LibDeletePool(gd->gd_FoundPool);
  586.                gd->gd_FoundPool = NULL;
  587.             }
  588.  
  589.             if(gd->gd_Found == 1)
  590.             {
  591.                UWORD newlen = strlen(gd->gd_Name);
  592.  
  593.                if(gd->gd_Name[newlen - 1] == ')')
  594.                {
  595.                   gd->gd_Name[newlen - 1] = 0;
  596.                   newlen--;
  597.                }
  598.  
  599.                if(para[ARG_SPACE])
  600.                {
  601.                   strcat(gd->gd_Name," ");
  602.                   newlen++;
  603.                }
  604.  
  605.                if(newlen != len)
  606.                {
  607.                   movmem(ptr + len, ptr + newlen, config->CurrentLen - (ptr - buf));
  608.  
  609.                   config->CurrentLen += (newlen - len);
  610.                   config->Column     += (newlen - len);
  611.  
  612.                   while(config->Column > config->CurrentLen)
  613.                      buf[(config->CurrentLen)++] = ' ';
  614.                }
  615.  
  616.                movmem(gd->gd_Name, ptr, newlen);
  617.  
  618.                msg->api_Refresh |= API_REFRESH_LINE;
  619.  
  620.                retval = RC_OK;
  621.             } else if(gd->gd_Found == 0)
  622.                SetIoErr(ERROR_OBJECT_NOT_FOUND);
  623.             else if(gd->gd_Found == -1)
  624.                SetIoErr(ERROR_BREAK);
  625.          }
  626.          CloseLibrary(XRefBase);
  627.       }
  628.    } else
  629.       SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  630.  
  631.    return(retval);
  632. }
  633. /*FE*/
  634.  
  635. /* ------------------ callback function for ParseXRef() ------------------- */
  636.  
  637. /*FS*/ /*"ULONG hook(struct Hook *hook,struct XRefFileNode *xref,struct xrmXRef *msg)"*/
  638. RegCall GetA4 ULONG hook(REGA0 struct Hook *hook,REGA2 struct XRefFileNode *xref,REGA1 struct xrmXRef *msg)
  639. {
  640.    struct GlobalData *gd = (struct GlobalData *) hook->h_Data;
  641.  
  642.    if(msg->Msg == XRM_XREF)
  643.    {
  644.       STRPTR name = (STRPTR) GetTagData(ENTRYA_Name,NULL,msg->xref_Attrs);
  645.       STRPTR ptr;
  646.       STRPTR wrd = gd->gd_Buffer;
  647.       ULONG matched = FALSE;
  648.       ULONG num = 0;
  649.                                       
  650.       if((ptr = name))  
  651.       {
  652.          switch(gd->gd_Mode)
  653.          {
  654.          case COMPLETE_BEGIN:
  655.          case COMPLETE_BEGIN_NOCASE:
  656.             /* anything matches, because xref.library compared for us */
  657.             matched = TRUE;
  658.             break;
  659.          case COMPLETE_UPPERCASELETTER:
  660.             while(*ptr)
  661.             {
  662.                if(isupper(*ptr))
  663.                {
  664.                   if(*wrd)
  665.                   {
  666.                      if(*ptr != *wrd)
  667.                         break;
  668.                      else
  669.                         wrd++;
  670.                   }
  671.                   num++;
  672.                }
  673.                ptr++;
  674.             }
  675.             matched = (*wrd == 0 && num == strlen(gd->gd_Buffer));
  676.             break;
  677.          case COMPLETE_RECURSIVE:
  678.             /* build no memory list, just find out the maximal string, which matches */
  679.             if(gd->gd_Found == 0)
  680.                strcpy(gd->gd_Name,name);
  681.             else
  682.             {
  683.                STRPTR ptr = gd->gd_Name;
  684.  
  685.                while(*ptr && *ptr == *name)
  686.                {
  687.                   ptr++;
  688.                   name++;
  689.                }
  690.  
  691.                *ptr = EOS;
  692.  
  693.             }
  694.             gd->gd_Found = 1;
  695.             break;
  696.          case COMPLETE_RECURSIVE_NOCASE:
  697.             /* build no memory list, just find out the maximal string, which matches */
  698.             if(gd->gd_Found == 0)
  699.                strcpy(gd->gd_Name,name);
  700.             else
  701.             {
  702.                STRPTR ptr = gd->gd_Name;
  703.  
  704.                while(*ptr && toupper(*ptr) == toupper(*name))
  705.                {
  706.                   ptr++;
  707.                   name++;
  708.                }
  709.  
  710.                if(*name)
  711.                   gd->gd_Para[ARG_SPACE] = FALSE;
  712.  
  713.                *ptr = EOS;
  714.  
  715.             }
  716.             gd->gd_Found = 1;
  717.             break;
  718.          }
  719.  
  720.          if(matched)
  721.          {
  722.             DB(("found : %s\n",name));
  723.  
  724.             gd->gd_Found++;
  725.  
  726.             if(gd->gd_Match == MATCH_FIRST)
  727.             {
  728.                strcpy(gd->gd_Name,name);
  729.                return(1);
  730.             }
  731.  
  732.             if(gd->gd_Found == 1)
  733.             {
  734.                strcpy(gd->gd_Name,name);
  735.             } else
  736.             {
  737.                if(!gd->gd_FoundPool)
  738.                   gd->gd_FoundPool = LibCreatePool(MEMF_ANY | MEMF_CLEAR,PUDDLE_SIZE,PUDDLE_SIZE);
  739.  
  740.                if(!gd->gd_FoundPool)
  741.                {
  742.                   return(1);
  743.                } else
  744.                {
  745.                   if(gd->gd_Found == 2)
  746.                      alloc_name(gd,gd->gd_Name);
  747.  
  748.                   if(!alloc_name(gd,name))
  749.                      gd->gd_Found--;
  750.                }
  751.             }
  752.          }
  753.       }
  754.    }
  755.    return(0);
  756. }
  757. /*FE*/
  758.  
  759. /* ------------------------- send a Rexx command -------------------------- */
  760.  
  761. /*FS*/ /*"BOOL send_rexxcommand(struct GlobalData *gd,STRPTR cmd)"*/
  762. BOOL send_rexxcommand(struct GlobalData *gd,STRPTR cmd)
  763. {
  764.    struct MsgPort *rexxport;
  765.  
  766.    Forbid();
  767.  
  768.    if((rexxport = FindPort(gd->gd_GoldEDHost)))
  769.    {
  770.       struct RexxMsg *rxmsg;
  771.       struct RexxMsg *answer;
  772.  
  773.       if((rxmsg = CreateRexxMsg(gd->gd_RexxPort, NULL, NULL)))
  774.       {
  775.          if((rxmsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))))
  776.          {
  777.             rxmsg->rm_Action = RXCOMM | RXFF_RESULT;
  778.  
  779.             PutMsg(rexxport, &rxmsg->rm_Node);
  780.  
  781.             do
  782.             {
  783.                WaitPort(gd->gd_RexxPort);
  784.  
  785.                if((answer = (struct RexxMsg *) GetMsg(gd->gd_RexxPort)))
  786.                    gd->gd_Result = answer->rm_Result1;
  787.  
  788.             } while (!answer);
  789.  
  790.             Permit();
  791.  
  792.             if(answer->rm_Result1 == RC_OK)
  793.             {
  794.                if(answer->rm_Result2)
  795.                {
  796.                   if(gd->gd_Buffer)
  797.                       strcpy(gd->gd_Buffer, (char *)answer->rm_Result2);
  798.  
  799.                   DeleteArgstring((char *)answer->rm_Result2);
  800.                }
  801.             }
  802.  
  803.             DeleteArgstring((char *)ARG0(answer));
  804.  
  805.             DeleteRexxMsg(answer);
  806.  
  807.             return(TRUE);
  808.          }
  809.       }
  810.    }
  811.  
  812.    Permit();
  813.  
  814.    return(FALSE);
  815. }
  816. /*FE*/
  817.  
  818. /* ------------------ allocate memory for a found entry ------------------- */
  819.  
  820. /*FS*/ /*"BOOL alloc_name(struct GlobalData *gd,STRPTR name)"*/
  821. BOOL alloc_name(struct GlobalData *gd,STRPTR name)
  822. {
  823.    struct Node *node;
  824.  
  825.    for(node = gd->gd_FoundList.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  826.       if(!strcmp(node->ln_Name,name))
  827.          break;
  828.  
  829.    if(node->ln_Succ)
  830.       return(FALSE);
  831.  
  832.    if((node = LibAllocPooled(gd->gd_FoundPool,sizeof(struct Node) + strlen(name) + 1)))
  833.    {
  834.       node->ln_Name = (STRPTR) (node + 1);
  835.       strcpy(node->ln_Name,name);
  836.       insertbyiname(&gd->gd_FoundList,node);
  837.    }
  838.  
  839.    return(TRUE);
  840. }
  841. /*FE*/
  842.  
  843. /* --------------------- select a node out of a list ---------------------- */
  844.  
  845. /*FS*/ /*"struct Node *select_node(struct List *list,struct Screen *screen)"*/
  846. struct Node *select_node(struct List *list,struct Screen *screen)
  847. {
  848.    struct TextAttr txtattr;
  849.    struct TextFont *font;
  850.    struct Node *selnode = NULL;
  851.    UBYTE fontname[32];
  852.  
  853.    /* get the screen font */
  854.    txtattr = *screen->Font;
  855.  
  856.    strncpy(fontname,txtattr.ta_Name,sizeof(fontname));
  857.    txtattr.ta_Name = fontname;
  858.  
  859.    if((font = OpenFont(&txtattr)))
  860.    {
  861.       struct RastPort rp;
  862.       struct NewGadget ng;
  863.       struct Gadget *glist = NULL;
  864.       struct Gadget *gad;
  865.       struct Node *node;
  866.       ULONG max = 100;
  867.       ULONG x;
  868.  
  869.       UWORD width;
  870.       UWORD height;
  871.       UWORD num = 0;
  872.  
  873.       InitRastPort(&rp);
  874.       SetFont(&rp,font);
  875.  
  876.       for(node = list->lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  877.       {
  878.          if((x = TextLength(&rp,node->ln_Name,strlen(node->ln_Name))) > max)
  879.          {
  880.             max = x;
  881.          }
  882.  
  883.          num++;
  884.       }
  885.  
  886.       width  = max + 20 + 16 + 4;
  887.       height = 10 * font->tf_YSize + 4;
  888.  
  889.       ng.ng_LeftEdge   = XDISTANCE;
  890.       ng.ng_TopEdge    = font->tf_YSize + 1 + YDISTANCE;
  891.       ng.ng_Width      = width;
  892.       ng.ng_Height     = height;
  893.       ng.ng_GadgetText = NULL;
  894.       ng.ng_TextAttr   = &txtattr;
  895.       ng.ng_GadgetID   = 1;
  896.       ng.ng_Flags      = 0;
  897.       ng.ng_VisualInfo = GetVisualInfoA(screen,NULL);
  898.       ng.ng_UserData   = NULL;
  899.  
  900.       if((gad = CreateContext(&glist)))
  901.       {
  902.          if((gad = CreateGadget(LISTVIEW_KIND,gad,&ng,
  903.                                 GTLV_Labels       ,list,
  904.                                 GTLV_ShowSelected ,NULL,
  905.                                 GTLV_Selected     ,0,
  906.                                 TAG_DONE)))
  907.  
  908.  
  909.          {
  910.             struct Window *win;
  911.  
  912.             width  += 2 * XDISTANCE;
  913.             height += 2 * YDISTANCE + font->tf_YSize + 1;
  914.  
  915.             if((win = OpenWindowTags(NULL,
  916.                                      WA_Title        ,prgname,
  917.                                      WA_Left         ,(screen->Width  - width ) >> 1,
  918.                                      WA_Top          ,(screen->Height - height) >> 1,
  919.                                      WA_Width        ,width,
  920.                                      WA_Height       ,height,
  921.                                      WA_AutoAdjust   ,TRUE,
  922.                                      WA_Gadgets      ,glist,
  923.                                      WA_IDCMP        ,IDCMP_RAWKEY | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | LISTVIEWIDCMP ,
  924.                                      WA_Flags        ,WFLG_CLOSEGADGET | WFLG_DEPTHGADGET | WFLG_DRAGBAR | WFLG_NOCAREREFRESH | WFLG_ACTIVATE,
  925.                                      WA_CustomScreen ,screen,
  926.                                      TAG_DONE)))
  927.             {
  928.                struct IntuiMessage *msg;
  929.                ULONG startsec,startmic,endsec,endmic;
  930.                BOOL running  = TRUE;
  931.                BOOL clicked  = FALSE;
  932.                WORD selected = -1;
  933.                WORD actual   = 0;
  934.  
  935.                GT_RefreshWindow(win,NULL);
  936.  
  937.                while(running)
  938.                {
  939.                   WaitPort(win->UserPort);
  940.                   while((msg = GT_GetIMsg(win->UserPort)))
  941.                   {
  942.                      switch(msg->Class)
  943.                      {
  944.                      case IDCMP_GADGETUP:
  945.                         if(!clicked)
  946.                         {
  947.                            CurrentTime(&startsec,&startmic);
  948.                            clicked = TRUE;
  949.                         } else if(msg->Code != actual)
  950.                         {
  951.                            clicked = FALSE;
  952.                         } else
  953.                         {
  954.                            CurrentTime(&endsec,&endmic);
  955.                            if(DoubleClick(startsec,startmic,endsec,endmic))
  956.                            {
  957.                               selected = actual;
  958.                               running = FALSE;
  959.                            }
  960.                            clicked = FALSE;
  961.                         }
  962.                         actual = msg->Code;
  963.                         break;
  964.                      case IDCMP_RAWKEY:
  965.                         switch(msg->Code)
  966.                         {
  967.                         case CURSORUP:
  968.                            if(actual > 0)
  969.                            {
  970.                               if(msg->Qualifier & 0x03)
  971.                               {
  972.                                  actual -= 9;
  973.                                  actual  = MAX(actual,0);
  974.                               } else
  975.                                  actual--;
  976.                               GT_SetGadgetAttrs(gad,win,NULL,
  977.                                                 GTLV_Selected    ,actual,
  978.                                                 GTLV_MakeVisible ,actual,
  979.                                                 (GadToolsBase->lib_Version < 39 ) ? GTLV_Top : TAG_IGNORE ,actual,
  980.                                                 TAG_DONE);
  981.                            }
  982.                            break;
  983.                         case  CURSORDOWN:
  984.                            if(actual < num - 1)
  985.                            {
  986.                               if(msg->Qualifier & 0x03)
  987.                               {
  988.                                  actual += 9;
  989.                                  actual  = MIN(actual,num-1);
  990.                               } else
  991.                                  actual++;
  992.                               GT_SetGadgetAttrs(gad,win,NULL,
  993.                                                 GTLV_Selected    ,actual,
  994.                                                 GTLV_MakeVisible ,actual,
  995.                                                 (GadToolsBase->lib_Version < 39 ) ? GTLV_Top : TAG_IGNORE  ,actual,
  996.                                                 TAG_DONE);
  997.                            }
  998.                            break;
  999.                         }
  1000.                         break;
  1001.                      case IDCMP_VANILLAKEY:
  1002.                         switch(msg->Code)
  1003.                         {
  1004.                         case 13:    /* return */
  1005.                            selected = actual;
  1006.                         case 3:     /* ctrl-c */
  1007.                         case 27:    /* esc */
  1008.                            running = FALSE;
  1009.                            break;
  1010.                         }
  1011.                         break;
  1012.                      case IDCMP_CLOSEWINDOW:
  1013.                         running = FALSE;
  1014.                         break;
  1015.                      }
  1016.                      GT_ReplyIMsg(msg);
  1017.                   }
  1018.                }
  1019.  
  1020.                if(selected > -1)
  1021.                {
  1022.                   for(selnode = list->lh_Head ;
  1023.                       selnode->ln_Succ && selected > 0 ;
  1024.                       selnode = selnode->ln_Succ)
  1025.                   {
  1026.                      selected--;
  1027.                   }
  1028.  
  1029.                   if(!selnode->ln_Succ)
  1030.                      selnode = NULL;
  1031.  
  1032.                }
  1033.  
  1034.                DB(("close window : %lx\n",win));
  1035.  
  1036.                CloseWindow(win);
  1037.             }
  1038.          }
  1039.          FreeGadgets(glist);
  1040.       }
  1041.       CloseFont(font);
  1042.    }
  1043.    return(selnode);
  1044. }
  1045. /*FE*/
  1046.  
  1047. /* -------------------------- support functions --------------------------- */
  1048.  
  1049. /*FS*/ /*"void parse_typestring(STRPTR typestr,ULONG *typearray)"*/
  1050. void parse_typestring(STRPTR typestr,ULONG *typearray)
  1051. {
  1052.    STRPTR end = typestr;
  1053.    STRPTR ptr = typestr;
  1054.    ULONG types = 0;
  1055.    ULONG i;
  1056.  
  1057.    /* convert separator to EOS */
  1058.    while(*end != EOS)
  1059.    {
  1060.       if(*end == '|')
  1061.          *end = EOS;
  1062.       end++;
  1063.    }
  1064.  
  1065.    while(ptr < end)
  1066.    {
  1067.       for(i = 0 ; i < XREFT_MAXTYPES ; i++)
  1068.          if(!Stricmp(ptr,xreftype_names[i]))
  1069.          {
  1070.             DB(("type : %s found -> %ld\n",ptr,i));
  1071.             typearray[types] = i;
  1072.             types++;
  1073.             break;
  1074.          }
  1075.  
  1076.       ptr += strlen(ptr) + 1;
  1077.    }
  1078.  
  1079.    DB(("types : %ld\n",types));
  1080.  
  1081.    typearray[types] = ~0;
  1082. }
  1083. /*FE*/
  1084.  
  1085.