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 / MessageLoop.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-28  |  9.2 KB  |  349 lines

  1. /* MessageLoop.c
  2. Originaly written by Anders Melchiorsen, modified by Roland Florac
  3. Handles the messages received by FetchRefs (Commodities, ARexx, Break)
  4. Modified from the original version for the ARexx interface */
  5.  
  6. #include "FetchRefs.h"
  7. #include <proto/rexxsyslib.h>
  8.  
  9. static void __regargs traiter_message_ARexx (struct RexxMsg * message);
  10.  
  11. struct Library *CxBase;
  12. struct MsgPort *CxPort, * rexxPort;
  13. CxObj *FRBroker;
  14.  
  15. char *RexxHostName;
  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. /* MessageLoop() - main loop waits for Cx, ARexx, or ^C */
  36. void MessageLoop (void)
  37. {
  38.     /* Main loop - process ARexx commands until we receive a ^C signal */
  39.     for(;;)
  40.     {
  41.     LONG mask;
  42.  
  43.     mask = Wait (SIGBREAKF_CTRL_C | (1 << rexxPort->mp_SigBit) | (1 << CxPort->mp_SigBit));
  44.  
  45.     /* FR_QUIT will signal FindTask(NULL) with ^C. Naturally, a ^C may
  46.      * also be sent by external means like C:Break or anything else.
  47.      */
  48.     if (mask & SIGBREAKF_CTRL_C)
  49.         return;
  50.  
  51.     /* We received an ARexx message. We use the DICE interface to process
  52.      * it. ProcessRexxCommands() will in turn call the DoRexxCommand()
  53.      * below.
  54.      */
  55.     if (mask & (1 << rexxPort->mp_SigBit))
  56.     {   struct RexxMsg * message;
  57.         while (message = (struct RexxMsg *) GetMsg (rexxPort))
  58.         traiter_message_ARexx (message);
  59.     }
  60.  
  61.     /* Handle Commodities message */
  62.     if (mask & (1 << CxPort->mp_SigBit))
  63.         HandleCxMessage ();
  64.     }
  65. }
  66.  
  67. /* The theory of parsing the messages is based on a two pass ReadArgs() parsing.
  68.  *
  69.  * First the entire message is parsed against RexxArgStr, and as all commands
  70.  * are postfixed by /F the entire rest of the line is considered to be the
  71.  * parameter of this single command. If an unrecognised keyword is entered then
  72.  * everything is considered a parameter to DUMMY (as it's the first one); thus
  73.  * out-of-context commands are flushed out here.
  74.  *
  75.  * Having had ReadArgs() put everything but the command name into a string, we
  76.  * can parse this against a template which differs for each command, but as all
  77.  * the templates are in an array we simply need one ReadArgs() call along with
  78.  * the right offset into this array (which is determined by what the command
  79.  * was). After having parsed again (but only if it's a succes), a switch can
  80.  * decide what actions should be made with the parameters parsed last - which
  81.  * depends on what the first parsing resulted in.
  82.  *
  83.  * As clear as mud, right? Anyway, I like it :-).
  84.  *
  85.  * (And later I learned about ARexxBox... :-).
  86.  */
  87.  
  88. /* Templates used by ARexx interface */
  89. UBYTE RexxArgStr[] = "FR_DUMMY/F,FR_QUIT/F,FR_GET/F,FR_CLEAR/F,FR_NEW/F,FR_ADD/F,FR_FILE/F,FR_REQ/F";
  90.  
  91. STRPTR RexxTemplates[] = {
  92. /* FR_DUMMY */    NULL,
  93. /* FR_QUIT  */    NULL,
  94. /* FR_GET   */    "FIND/A,TO/A,PUBSCREEN,FILEREF/S,CASE/S",
  95. /* FR_CLEAR */    NULL,
  96. /* FR_NEW   */    "FILE/M",
  97. /* FR_ADD   */    "FILE/M",
  98. /* FR_FILE  */    "FIND/A,CASE/S",
  99. /* FR_REQ   */    "FIND/A,TO/A,PUBSCREEN,FILEREF/S,CASE/S"
  100. };
  101.  
  102. /* The following routine is called everytime we receive an ARexx msg.
  103.  * Depending on what the message was, different actions are performed.
  104.  */
  105. static __regargs LONG DoRexxCommande (void *msg, char *arg0)
  106. {
  107.     struct FindRefReturnStruct RetCode = { RET_OKAY, 0 };
  108.     UBYTE str[256];
  109.  
  110.     struct RDArgs *RexxArgs, *ArgsArgs;
  111.     STRPTR RexxResult[sizeof(RexxTemplates) / sizeof(RexxTemplates[0])];
  112.     STRPTR ArgsResult[10];
  113.  
  114.     /* Flush out garbage as ReadArgs() allows for pre-initialized values */
  115.     setmem (RexxResult, sizeof(RexxResult), 0);
  116.     setmem (ArgsResult, sizeof(ArgsResult), 0);
  117.  
  118.     /* ReadArgs() needs a '\n' at the end of its strings :-( */
  119.     strcpy (str, arg0);
  120.     strcat (str, "\n");
  121.  
  122.     if ((RexxArgs = AllocDosObject (DOS_RDARGS, NULL)) && (ArgsArgs = AllocDosObject (DOS_RDARGS, NULL)))
  123.     {
  124.     RexxArgs->RDA_Source.CS_Buffer = str;
  125.     RexxArgs->RDA_Source.CS_Length = strlen(str);
  126.     RexxArgs->RDA_Flags = RDAF_NOPROMPT;
  127.     if (ReadArgs (RexxArgStr, (LONG *) RexxResult, RexxArgs))
  128.     {
  129.         LONG argno;
  130.  
  131.         /* Figure out which command we got */
  132.         for (argno = 0;  ! RexxResult[argno];  argno++);
  133.  
  134.         /* If a template is specified: parse the arguments */
  135.         if (RexxTemplates[argno])
  136.         {
  137.         /* We still have to add '\n' to the string due to ReadArgs() */
  138.         strcpy (str, RexxResult[argno]);
  139.         strcat (str, "\n");
  140.  
  141.         /* Now parse the arguments to whatever the command is */
  142.         ArgsArgs->RDA_Source.CS_Buffer = str;
  143.         ArgsArgs->RDA_Source.CS_Length = strlen(str);
  144.         ArgsArgs->RDA_Flags = RDAF_NOPROMPT;
  145.         if (!(ReadArgs (RexxTemplates[argno], (LONG *)ArgsResult, ArgsArgs)))
  146.         {
  147.             RetCode.Result = RET_FAULT;
  148.             RetCode.Number = IoErr();
  149.         }
  150.         }
  151.  
  152.         /* If ReadArgs() failed the return code is changed (above) and
  153.          * therefore the switch() will only be executed if everything
  154.          * is allright so far.
  155.          */
  156.         if (RetCode.Result == RET_OKAY)
  157.         switch (argno)
  158.         {
  159.             case FR_DUMMY:
  160.             RetCode.Result = RET_FAULT;
  161.             RetCode.Number = ERROR_REQUIRED_ARG_MISSING;
  162.             break;
  163.  
  164.             case FR_QUIT:
  165.             Signal (FindTask(NULL), SIGBREAKF_CTRL_C);
  166.             break;
  167.  
  168.             case FR_GET:
  169.             case FR_REQ:
  170.             {
  171.             struct FindRefOptions FindOpts;
  172.             FindOpts.Reference = ArgsResult[0];
  173.             FindOpts.DestFile = ArgsResult[1];
  174.             FindOpts.PubScreen = ArgsResult[2];
  175.             FindOpts.FileRef = (BOOL) ArgsResult[3];
  176.             FindOpts.function = argno;
  177.             FindOpts.Case = (BOOL) ArgsResult[4];
  178.  
  179.             FindRef (&FindOpts, &RetCode);
  180.             }
  181.             break;
  182.  
  183.             case FR_CLEAR:
  184.             FreeRefs();
  185.             break;
  186.  
  187.             case FR_NEW:
  188.             FreeRefs();
  189.  
  190.             /* FR_NEW falls through to FR_ADD. Naturally this requires
  191.              * them to have the same templates. */
  192.  
  193.             case FR_ADD:
  194.             ReadWild ((STRPTR (*)[]) ArgsResult[0]);
  195.             break;
  196.  
  197.             case FR_FILE:
  198.             {
  199.             struct FindRefOptions FindOpts;
  200.  
  201.             FindOpts.Reference = ArgsResult[0];
  202.             FindOpts.Case = (BOOL) ArgsResult[1];
  203.             FindOpts.function = argno;
  204.             FindRef (&FindOpts, &RetCode);
  205.             if (RetCode.Result == RET_MATCH)
  206.             {
  207.                 FreeArgs (RexxArgs);
  208.                 FreeDosObject (DOS_RDARGS, RexxArgs);
  209.                 SetRexxVar (msg, "RC2", FindOpts.Reference, strlen(FindOpts.Reference));
  210.                 FreeVec (FindOpts.Reference);
  211.                 return RETURN_OK;
  212.             }
  213.             }
  214.             break;
  215.         }
  216.     }
  217.     else
  218.     {
  219.         RetCode.Result = RET_FAULT;
  220.         RetCode.Number = IoErr();
  221.     }
  222.  
  223.     FreeArgs (ArgsArgs);
  224.     FreeDosObject (DOS_RDARGS, ArgsArgs);
  225.     }
  226.     else
  227.     {
  228.     RetCode.Result = RET_FAULT;
  229.     RetCode.Number = ERROR_NO_FREE_STORE;
  230.     }
  231.  
  232.     if (RexxArgs)
  233.     {
  234.     FreeArgs (RexxArgs);
  235.     FreeDosObject (DOS_RDARGS, RexxArgs);
  236.     }
  237.  
  238.     /* Find out what the secondary (RC2) return code should be. This is,
  239.      * of course, dependent on the primary (RC) return code.
  240.      */
  241.     switch (RetCode.Result)
  242.     {
  243.     case RET_MATCH:
  244.         SPrintf (str, "%ld", RetCode.Number);
  245.     break;
  246.  
  247.     case RET_NO_MATCH:
  248.         strcpy (str, GetString (TEXTE_NOREF));
  249.     break;
  250.  
  251.     case RET_ABORT:
  252.         strcpy (str, GetString (TEXTE_ABORT));
  253.     break;
  254.  
  255.     case RET_FAULT:
  256.         Fault (RetCode.Number, "FetchRefs", str, 256);
  257.     break;
  258.     }
  259.     SetRexxVar (msg, "RC2", str, strlen(str));
  260.  
  261.     /* Set the return code (RC) to 0, 5, 10 or 20 */
  262.     if ((RetCode.Result == RET_OKAY) || (RetCode.Result == RET_MATCH))
  263.     return RETURN_OK;
  264.     else if (RetCode.Result == RET_ABORT)
  265.     return RETURN_WARN;
  266.     else if (RetCode.Result == RET_NO_MATCH)
  267.     return RETURN_ERROR;
  268.     else
  269.     return RETURN_FAIL;
  270. }
  271.  
  272. static void __regargs traiter_message_ARexx (struct RexxMsg * message)
  273. {   if (message->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)    /* really usefull ? */
  274.     {    DeleteArgstring (message->rm_Args[0]);
  275.     DeleteRexxMsg (message);
  276.     return;
  277.     }
  278.     message->rm_Result2 = 0;
  279.     message->rm_Result1 = DoRexxCommande (message, message->rm_Args[0]);
  280.     ReplyMsg ((struct Message *) message);
  281. }
  282.  
  283. /* HandleCxMessage() - take care of any Cx message */
  284. void HandleCxMessage (void)
  285. {
  286.     CxMsg *msg;
  287.  
  288.     while (msg = (CxMsg *) GetMsg (CxPort))
  289.     {
  290.     ULONG msg_id = CxMsgID(msg), msg_type = CxMsgType(msg);
  291.  
  292.     ReplyMsg ((struct Message *) msg);
  293.  
  294.     if (msg_type == CXM_COMMAND)
  295.         switch (msg_id)
  296.         {
  297.         case CXCMD_DISABLE:
  298.             ActivateCxObj (FRBroker, FALSE);
  299.         break;
  300.  
  301.         case CXCMD_ENABLE:
  302.             ActivateCxObj (FRBroker, TRUE);
  303.         break;
  304.  
  305.         case CXCMD_KILL:
  306.             Signal (FindTask (NULL), SIGBREAKF_CTRL_C);
  307.         break;
  308.         }
  309.     }
  310. }
  311.  
  312.  
  313. /* InstallCx() - set up the Commodities Broker */
  314. void __regargs InstallCx (STRPTR name)
  315. {   static struct NewBroker fr_broker =
  316.     {
  317.     NB_VERSION,
  318.     NULL,
  319.     0,
  320.     0,
  321.     NULL,
  322.     NULL,
  323.     0, NULL, 0
  324.     };
  325.  
  326.     fr_broker.nb_Descr = GetString (TEXTE_RECHERCHE);
  327.     fr_broker.nb_Title = GetString (TEXTE_VERSION);
  328.  
  329.     if (CxBase = OpenLibrary ("commodities.library", 37))
  330.     {
  331.     if (CxPort = CreateMsgPort())
  332.     {
  333.         fr_broker.nb_Name = name;
  334.         fr_broker.nb_Port = CxPort;
  335.  
  336.         if (FRBroker = CxBroker (&fr_broker, NULL))
  337.         ActivateCxObj (FRBroker, TRUE);
  338.     }
  339.     }
  340. }
  341.  
  342. /* RemoveCx() - remove the Commodities Broker if it was set up */
  343. void RemoveCx (void)
  344. {   if (FRBroker)
  345.     DeleteCxObjAll (FRBroker);
  346.     DeleteMsgPort (CxPort);
  347.     CloseLibrary (CxBase);
  348. }
  349.