home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / db3.6-beta-src / dbrexx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-09  |  20.5 KB  |  697 lines

  1. /* Rexx support for db */
  2.  
  3. /**********************************************************************/
  4. /*                              Includes                              */
  5. /**********************************************************************/
  6.  
  7. #include <proto/rexxsyslib.h>
  8. #include <proto/utility.h>                      /* Stricmp() */
  9. #include <proto/exec.h>
  10. #include <string.h>
  11. #include <stdlib.h>     /* atoi() */
  12.  
  13. /* Included for compatibility */
  14. #include <libraries/gadtools.h>
  15. #include <intuition/intuition.h>                /* struct EasyStruct */
  16. #include <proto/gadtools.h>
  17. #include <proto/intuition.h>
  18. #include <proto/dos.h>                  /* Unlock() */
  19.  
  20. #include "dbGUI.h"
  21. #include "db.h"
  22. #include "dbRexx.h"
  23. // #include "dbParser.h"
  24.  
  25. /* Included for compatibility */
  26. #include "dbtexts.h"
  27.  
  28. /**********************************************************************/
  29. /*                              Defines                               */
  30. /**********************************************************************/
  31.  
  32. #define REXXPORTNAMELENGTH 50
  33.  
  34. /**********************************************************************/
  35. /*                              Globals                               */
  36. /**********************************************************************/
  37.  
  38. /* ARexx specifics */
  39. struct MsgPort *MyRexxPort = NULL;
  40. char MyRexxPortName[REXXPORTNAMELENGTH] ="\0";
  41.  
  42. int OutstandingRexxCommands = 0;
  43. /* End of Rexx specifics */
  44.  
  45.  
  46. /**********************************************************************/
  47. /*                             Prototypes                             */
  48. /**********************************************************************/
  49.  
  50. extern int DB_SAVE( void );     /* I don't want to include dbGUI.h for this one line */
  51.  
  52. typedef struct {
  53.         char *arg;
  54.         struct RexxMsg *rxmessage;
  55.         int RC;
  56.         char *Result;
  57.         char buf[10];   /* Sometimes Result points here */
  58. } RXInfo;
  59.  
  60. /**********************************************************************/
  61. /*                             Functions                              */
  62. /**********************************************************************/
  63.  
  64. char *NextWord(const char *s)
  65. {
  66.         /* Just steps forward all non space characters + one space character */
  67.         if (!s) return NULL;
  68.         while (*s && (*s++ != ' '));
  69.         return s;
  70. }
  71.  
  72. int GetFldIndex(struct Pro *Pr, char *s)
  73. {
  74.         /* Returns the fieldindex of the matching field or -1 if not found */
  75.         int i=0;
  76.         struct FldInfo *f = Pr->FirstFldInfo;
  77.  
  78.         for (; f; f=f->Next, i++) if (!Stricmp(f->Name, s)) return i;
  79.         return -1;
  80. }
  81.  
  82. Field RXGetFld(struct Pro *Pr, char *fieldname)
  83. {
  84.         /* Returning NULL indicates an error */
  85.         int i;
  86.         if ((i = GetFldIndex(Pr, fieldname)) == -1) return NULL;
  87.         return GetFld(*Pr->Recpp, i);
  88. }
  89.  
  90. LONG EasyRexxRequest(struct Window *w, struct EasyStruct *es, ULONG *idcmp,
  91.  char *string)
  92. {
  93.         BOOL blocked;
  94.         /* Displays an EasyRequest where the strings are locale string-indexes */
  95.         LONG ret_val;
  96.         struct EasyStruct nes;
  97.         nes.es_StructSize = sizeof(struct EasyStruct);
  98.         nes.es_Flags = 0;
  99.         nes.es_Title = GetAppStr((LONG)es->es_Title);
  100.         nes.es_TextFormat = string;
  101.         nes.es_GadgetFormat = GetAppStr((LONG)es->es_GadgetFormat);
  102.         
  103.         blocked = IsInputBlocked();
  104.         if (w) BlockInput(w, TRUE);
  105.         ret_val = EasyRequestArgs(w, &nes, idcmp, NULL);
  106.         if (w && !blocked) FreeInput(w);
  107.         return ret_val;
  108. }
  109.  
  110.  
  111. struct MsgPort *SetupRexxPort(char *basename)
  112. {
  113.         struct MsgPort *port;
  114.         int num=1;
  115.  
  116.         Forbid();       
  117.  
  118.         do {    /* Make a unique portname db.<num> */
  119.                 sprintf(MyRexxPortName, "%s.%d", basename, num++);
  120.         } while (FindPort(MyRexxPortName));
  121.         port = CreatePort(MyRexxPortName, 0L);
  122.  
  123.         Permit();
  124.         return port;
  125. }
  126.  
  127.  
  128. void ReplyRexxCommand(struct RexxMsg *rxmessage, long rc, char *result)
  129. {
  130.         long rc2 = 0;
  131.         if (!rc && (rxmessage->rm_Action & 1L<<RXFB_RESULT))
  132.                 if (result) rc2 = (long)CreateArgstring(result, strlen(result));
  133.         rxmessage->rm_Result1 = rc;
  134.         rxmessage->rm_Result2 = rc2;
  135.         ReplyMsg((struct Message *)rxmessage);
  136. }
  137.  
  138.  
  139. /**********************************************************************/
  140. /*                       ARexx command handlers                       */
  141. /**********************************************************************/
  142.  
  143. extern struct SortInfo {
  144.         struct SortOrder *so;
  145.         size_t norders;
  146.         char SortDir;
  147.         BOOL UnSort;    /* Sort the database based upon each record's address instead */
  148. }SI;
  149.  
  150.  
  151. static void Rx_SortOrder(RXInfo *ri)
  152. {
  153. int order;
  154.  
  155.  
  156.         if(*ri->arg)
  157.           {
  158.           order = atoi(ri->arg);
  159.  
  160.           switch(order)
  161.             {
  162.             case 0:
  163.                SI.SortDir = SORT_DIR_AZ;
  164.                break;
  165.  
  166.             case 1:
  167.                 SI.SortDir = SORT_DIR_ZA;
  168.                 break;
  169.  
  170.             default:
  171.                 ri->RC = RC_ERROR;
  172.                 break;
  173.             }
  174.           }
  175.         else
  176.           {
  177.           stci_d(ri->buf, SI.SortDir);
  178.           ri->Result = ri->buf;
  179.           }
  180.  
  181. }
  182.  
  183.  
  184.  
  185. static void Rx_Add(RXInfo *ri)
  186. {
  187.         DB_ADD();
  188. }
  189.  
  190. static void Rx_Kill(RXInfo *ri)
  191. {
  192.         DB_KILL();
  193. }
  194.  
  195. static void Rx_FirstRecord(RXInfo *ri)
  196. {
  197.         UpdateRecord(CurrentPro);
  198.         if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
  199.         JumpList(CurrentPro, -CurrentPro->RecNum);
  200.         if (CurrentPro->Mode == MODE_NORMAL) {
  201.                 UpdateWindow(CurrentPro);
  202.                 UpdateDragBar(CurrentPro);
  203.         }
  204.         if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  205.  
  206.         stci_d(ri->buf, CurrentPro->RecNum+1);
  207.         ri->Result = ri->buf;
  208. }
  209.  
  210. static void Rx_NextRecord(RXInfo *ri)
  211. {
  212.         if (CurrentPro->RecNum < (CurrentPro->RecSum-1)) {
  213.                 if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
  214.                 JumpList(CurrentPro, 1);
  215.                 if (CurrentPro->Mode == MODE_NORMAL) {
  216.                         UpdateWindow(CurrentPro);
  217.                         UpdateDragBar(CurrentPro);
  218.                 }
  219.                 if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  220.         }
  221.         else ri->RC = RC_WARN;
  222.         stci_d(ri->buf, CurrentPro->RecNum+1);
  223.         ri->Result = ri->buf;
  224. }
  225.  
  226. static void Rx_CurrentRecord(RXInfo *ri)
  227. {
  228.         int recnum;
  229.         if (*ri->arg) {
  230.                 recnum = atoi(ri->arg)-1;
  231.                 if (recnum >= 0 && recnum < CurrentPro->RecSum) {
  232.                         if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
  233.                         JumpList(CurrentPro, -CurrentPro->RecNum+recnum);
  234.                         if (CurrentPro->Mode == MODE_NORMAL) {
  235.                                 UpdateWindow(CurrentPro);
  236.                                 UpdateDragBar(CurrentPro);
  237.                         }
  238.                         if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  239.                 }
  240.                 else ri->RC = RC_WARN;
  241.         }
  242.         stci_d(ri->buf, CurrentPro->RecNum+1);
  243.         ri->Result = ri->buf;
  244. }
  245.  
  246. static void Rx_RecordSum(RXInfo *ri)
  247. {
  248.         stci_d(ri->buf, CurrentPro->RecSum);
  249.         ri->Result = ri->buf;
  250. }
  251.  
  252. static void Rx_FindFirst(RXInfo *ri)
  253. {
  254.         if (!FindRecord(CurrentPro,0,1)) ri->RC = RC_WARN;
  255.         stci_d(ri->buf, CurrentPro->RecNum+1);
  256.         ri->Result = ri->buf;
  257. }
  258.  
  259. static void Rx_FindNext(RXInfo *ri)
  260. {
  261.         if (!FindRecord(CurrentPro,CurrentPro->RecNum+1,1)) ri->RC = RC_WARN;
  262.         stci_d(ri->buf, CurrentPro->RecNum+1);
  263.         ri->Result = ri->buf;
  264. }
  265.  
  266. static void Rx_Cut(RXInfo *ri)
  267. {
  268.         DB_CUT();
  269. }
  270.  
  271. static void Rx_Copy(RXInfo *ri)
  272. {
  273.         DB_COPY();
  274. }
  275.  
  276. static void Rx_Paste(RXInfo *ri)
  277. {
  278.         DB_PASTE();
  279. }
  280.  
  281. static void Rx_Merge(RXInfo *ri)
  282. {
  283.         UpdateRecord(CurrentPro);
  284.         PasteFromClipboard(CurrentPro, *CurrentPro->Recpp);
  285.         CurrentPro->Modified |= PROMODIFIED;
  286.         UpdateGadgets(CurrentPro);
  287. }
  288.  
  289. static void Rx_FirstField(RXInfo *ri)
  290. {
  291.         struct FldInfo *fi;
  292.         if (fi = GetFldInfo(CurrentPro, 0)) {
  293.                 CurrentPro->CurrentFldOffset = 0;
  294.                 ri->Result = fi->Name;
  295.         }
  296.         else ri->RC = RC_WARN;  /* No fields at all */
  297. }
  298.  
  299. static void Rx_NextField(RXInfo *ri)
  300. {
  301.         struct FldInfo *fi;
  302.         if (fi = GetFldInfo(CurrentPro, CurrentPro->CurrentFldOffset+1)) {
  303.                 CurrentPro->CurrentFldOffset++;
  304.                 ri->Result = fi->Name;
  305.         }
  306.         else ri->RC = RC_WARN;
  307. }
  308.  
  309. static void Rx_CurrentField(RXInfo *ri)
  310. {
  311.         int offset;
  312.         struct FldInfo *fi;
  313.  
  314.         if (*ri->arg) {
  315.                 if ((offset = GetFldIndex(CurrentPro, ri->arg)) == -1) {
  316.                         ri->RC = RC_WARN;
  317.                         return;
  318.                 }
  319.                 CurrentPro->CurrentFldOffset = offset;
  320.         }
  321.         if (fi = GetFldInfo(CurrentPro, CurrentPro->CurrentFldOffset)) ri->Result = fi->Name;
  322.         else ri->RC = RC_WARN;  /* Should never happen */
  323. }
  324.  
  325.  
  326. static void Rx_GetField(RXInfo *ri)                                                     /* ri->arg is fieldname */
  327. {
  328.         UpdateRecord(CurrentPro);
  329.         if (*ri->arg) ri->Result = RXGetFld(CurrentPro, ri->arg);
  330.         else ri->Result = GetFld(*CurrentPro->Recpp, CurrentPro->CurrentFldOffset);
  331.         if (!ri->Result) ri->RC = RC_WARN;
  332. }
  333.  
  334.  
  335. static void Rx_PutField(RXInfo *ri)
  336. {
  337.         UpdateRecord(CurrentPro);
  338.         if (UpdateFld(*CurrentPro->Recpp, CurrentPro->CurrentFldOffset, ri->arg) &&
  339.          CurrentPro->Mode == MODE_NORMAL)
  340.                 CurrentPro->Modified |= PROMODIFIED;
  341.         UpdateGadgets(CurrentPro);
  342. }
  343.  
  344. static void Rx_Mode(RXInfo *ri)
  345. {
  346.         if (*ri->arg) {
  347.                 if (!Stricmp(ri->arg, "Normal")) SetProMode(CurrentPro, MODE_NORMAL);
  348.                 else if (!Stricmp(ri->arg, "Find")) SetProMode(CurrentPro, MODE_FIND);
  349.                 else if (!Stricmp(ri->arg, "Sort")) SetProMode(CurrentPro, MODE_SORT);
  350.                 else ri->RC = RC_ERROR;
  351.         }
  352.  
  353.         switch (CurrentPro->Mode) {
  354.                 case MODE_NORMAL:
  355.                         ri->Result = "Normal";
  356.                         break;
  357.                 case MODE_FIND:
  358.                         ri->Result = "Find";
  359.                         break;
  360.                 case MODE_SORT:
  361.                         ri->Result = "Sort";
  362.                         break;
  363.         }
  364. }
  365.  
  366. static void Rx_Save(RXInfo *ri)
  367. {
  368.         DB_SAVE();
  369. }
  370.  
  371. static void Rx_Sort(RXInfo *ri)
  372. {
  373.         DoSort(CurrentPro, -1);
  374. }
  375.  
  376. static void Rx_Quit(RXInfo *ri)
  377. {
  378.         ReplyRexxCommand(ri->rxmessage, RC_OK, 0);
  379.         ByeBye();
  380. }
  381.  
  382. static void Rx_UpdateGUI(RXInfo *ri)
  383. {
  384.         BOOL save = CurrentPro->Quiet;
  385.         CurrentPro->Quiet = FALSE;
  386.         SetProMode(CurrentPro, CurrentPro->Mode);
  387.         CurrentPro->Quiet = save;
  388. }
  389.  
  390. static void Rx_WindowToFront(RXInfo *ri)
  391. {
  392.         if (CurrentPro->CurrentLayout->Window)
  393.                 WindowToFront(CurrentPro->CurrentLayout->Window);
  394.         else ri->RC = RC_WARN;
  395.  
  396. }
  397.  
  398. static void Rx_ScreenToFront(RXInfo *ri)
  399. {
  400.         ScreenToFront(Scr);
  401. }
  402.  
  403. static void Rx_ActivateWindow(RXInfo *ri)
  404. {
  405.         if (CurrentPro->CurrentLayout->Window)
  406.                 ActivateWindow(CurrentPro->CurrentLayout->Window);
  407.         else ri->RC = RC_WARN;
  408. }
  409.  
  410. static void Rx_BlockInput(RXInfo *ri)
  411. {
  412.         BlockInput(CurrentPro->CurrentLayout->Window, TRUE);
  413.         UpdateRecord(CurrentPro);
  414.         CurrentPro->Quiet = TRUE;       /* Don't do any GUI stuff from now on */
  415. }
  416.  
  417. static void Rx_FreeInput(RXInfo *ri)
  418. {
  419.         FreeInput(CurrentPro->CurrentLayout->Window);
  420.         CurrentPro->Quiet = FALSE;              /* Release GUI now */
  421.         Rx_UpdateGUI(ri);
  422. }
  423.  
  424. static void Rx_Dial(RXInfo *ri)
  425. {
  426.         ri->RC = DoDial(ri->arg);
  427. }
  428.  
  429. static void Rx_DisplayBeep(RXInfo *ri)
  430. {
  431.         DisplayBeep(Scr);
  432. }
  433.  
  434. static void Rx_Okay1(RXInfo *ri)
  435. {
  436.         EasyRexxRequest(CurrentPro->CurrentLayout->Window, &ES_RexxOkay1, NULL, ri->arg);
  437. }
  438.  
  439. static void Rx_Okay2(RXInfo *ri)
  440. {
  441.         stci_d(ri->buf, EasyRexxRequest(CurrentPro->CurrentLayout->Window, &ES_RexxOkay2, NULL, ri->arg));
  442.         ri->Result = ri->buf;
  443. }
  444.  
  445. static void Rx_CurrentGadget(RXInfo *ri)
  446. {
  447.         int gadindex;
  448.         struct VisFldInfo *vf;
  449.  
  450.         NextGad = NULL;
  451.         if (*ri->arg) {
  452.                 gadindex = atoi(ri->arg);
  453.                 if (!gadindex--) {      /* string argument, not a number */
  454.                         for(vf=CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next)
  455.                                 if (!Stricmp(ri->arg, vf->Name)) break;
  456.                 }
  457.                 else for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf && gadindex > 0; vf = vf->Next, gadindex--);
  458.                 if (vf) LastGad = vf->Gadget;
  459.         }
  460.         if (LastGad) {
  461.                 for(gadindex=1, vf=CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next, gadindex++)
  462.                         if (vf->Gadget == LastGad) break;
  463.  
  464.                 stci_d(ri->buf, gadindex);
  465.                 ri->Result = ri->buf;
  466.  
  467.         }
  468.         else ri->RC = RC_WARN;
  469. }
  470.  
  471. static void Rx_RetryInput(RXInfo *ri)
  472. {
  473.                 NextGad = NULL; /* Don't activate NextGad if tabcycling */
  474.                 ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  475. }
  476.  
  477. static void Rx_CurrentView(RXInfo *ri)
  478. {
  479.         int viewindex;
  480.         struct Layout *lay = CurrentPro->FirstLayout;
  481.  
  482.         if (*ri->arg) {
  483.                 viewindex = atoi(ri->arg);
  484.                 if (!viewindex--) {     /* string argument, not a number */
  485.                         for (; lay; lay = lay->NextLayout)
  486.                                 if (!Stricmp(ri->arg, lay->Name)) break;
  487.                 } else for (; lay && viewindex; lay = lay->NextLayout, viewindex--);
  488.                 ChangeView(lay);
  489.         }
  490.         else for (viewindex=1; lay != CurrentPro->CurrentLayout; lay = lay->NextLayout, viewindex++);
  491.  
  492.         stci_d(ri->buf, viewindex);
  493.         ri->Result = ri->buf;
  494. }
  495.  
  496. static void Rx_UndoBuffer(RXInfo *ri)
  497. {
  498.         if (LastGad && LastGad->GadgetID == STRING_KIND)
  499.                 ri->Result = ((struct StringInfo *)LastGad->SpecialInfo)->UndoBuffer;
  500.         else ri->RC = RC_WARN;
  501. }
  502.  
  503. static void Rx_GetPortName(RXInfo *ri)  /* Undocumented. The ARexx function Address() should do this job */
  504. {
  505.         ri->Result = MyRexxPortName;
  506. }
  507.  
  508.  
  509. /**********************************************************************/
  510. /*                      ARexx command dispatcher                      */
  511. /**********************************************************************/
  512.  
  513. typedef struct {
  514.         char *name;
  515.         void (*cmd)(RXInfo *);
  516. } Comm;
  517.  
  518. static Comm Commands[] = {
  519.         { "Add", Rx_Add },
  520.         { "Kill", Rx_Kill }, 
  521.         { "FirstRecord", Rx_FirstRecord, },
  522.         { "NextRecord", Rx_NextRecord },
  523.         { "CurrentRecord", Rx_CurrentRecord },
  524.         { "RecordSum", Rx_RecordSum },
  525.         { "FindFirst", Rx_FindFirst },
  526.         { "FindNext", Rx_FindNext },
  527.         { "Cut", Rx_Cut },
  528.         { "Copy", Rx_Copy },
  529.         { "Paste", Rx_Paste },
  530.         { "Merge", Rx_Merge },
  531.         { "FirstField", Rx_FirstField },
  532.         { "NextField", Rx_NextField },
  533.         { "CurrentField", Rx_CurrentField },
  534.         { "GetField", Rx_GetField },
  535.         { "PutField", Rx_PutField },
  536.         { "Mode", Rx_Mode },
  537.         { "Save", Rx_Save },
  538.         { "Sort", Rx_Sort },
  539.         { "SortOrder", Rx_SortOrder },
  540.         { "Quit", Rx_Quit },
  541.         { "UpdateGUI", Rx_UpdateGUI },
  542.         { "WindowToFront", Rx_WindowToFront },
  543.         { "ScreenToFront", Rx_ScreenToFront },
  544.         { "ActivateWindow", Rx_ActivateWindow },
  545.         { "BlockInput", Rx_BlockInput },
  546.         { "FreeInput", Rx_FreeInput },
  547.         { "Dial", Rx_Dial },
  548.         { "DisplayBeep", Rx_DisplayBeep },
  549.         { "Okay1", Rx_Okay1 },
  550.         { "Okay2", Rx_Okay2 },
  551.         { "CurrentGadget", Rx_CurrentGadget },
  552.         { "UndoBuffer", Rx_UndoBuffer },
  553.         { "RetryInput", Rx_RetryInput },
  554.         { "CurrentView", Rx_CurrentView },
  555.         { "GetPortName", Rx_GetPortName },
  556.         { NULL, NULL }
  557. };
  558.  
  559.  
  560. void HandleRexxCommand(struct RexxMsg *rxmessage)
  561. {
  562.         int i, namelen;
  563.         char name[40];
  564.         char *cmdline = ARG0(rxmessage);
  565.         RXInfo ri;
  566.  
  567.         ri.rxmessage = rxmessage;       /* QUIT needs to answer itself */
  568.         ri.RC = RC_OK;
  569.         ri.Result = NULL;       
  570.  
  571.         /* Split cmdline into name and arg without affecting cmdline */
  572.         for (i=0; i<30 && cmdline[i] && cmdline[i] != ' '; i++)
  573.                 name[i] = cmdline[i];
  574.         name[i] = '\0';
  575.         namelen = strlen(name);
  576.         ri.arg = NextWord(cmdline);
  577.  
  578.         /* Do the dispatch */
  579.         for (i=0; Commands[i].name; i++)        {
  580.                 if (!Strnicmp(Commands[i].name, name, namelen)) {
  581.                         Commands[i].cmd(&ri);   /* Run this command */
  582.                         ReplyRexxCommand(rxmessage, ri.RC, ri.Result);
  583.                         return;
  584.                 }
  585.         }
  586.         ReplyRexxCommand(rxmessage,RC_ERROR,NULL);              /* Command not found */
  587. }
  588.  
  589.  
  590. void FreeRexxCommand(struct RexxMsg *rxmessage)
  591. {
  592.         struct Window *win = (CurrentPro->CurrentLayout) ?
  593.          CurrentPro->CurrentLayout->Window : NULL;
  594.  
  595.         if (rxmessage->rm_Result1) {
  596.                 if (rxmessage->rm_Result2 == ERR10_001)         /* Program not found */
  597.                         EasyLocRequest(win, &ES_RexxProgNotFound, NULL, ARG0(rxmessage));
  598.                 else EasyLocRequest(win, &ES_RexxError, NULL, ARG0(rxmessage), rxmessage->rm_Result2);
  599.         }       
  600.         DeleteArgstring(rxmessage->rm_Args[0]); /* The command name */
  601.  
  602.         /* In SendRexxCommand we cd to project's dir, cd back and unlock now */
  603.         UnLock(CurrentDir((BPTR)rxmessage->rm_Args[15]));
  604.         DeleteRexxMsg(rxmessage);
  605.         OutstandingRexxCommands--;
  606. }
  607.  
  608.  
  609. void CloseRexxPort(struct MsgPort *rexxport)
  610. {
  611.         struct RexxMsg *rxmessage;
  612.         
  613.         do {
  614.                 while (rxmessage = (struct RexxMsg *)GetMsg(rexxport)) {
  615.                         if (rxmessage->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  616.                                 FreeRexxCommand(rxmessage);      /* A command finished */
  617.                         else ReplyRexxCommand(rxmessage, ERR10_013, NULL); /* 'Host not found' */
  618.                 }
  619.                 if (OutstandingRexxCommands) WaitPort(rexxport);
  620.         } while (OutstandingRexxCommands);              /* Wait out all commands we've sent */
  621.  
  622.         DeletePort(rexxport);
  623. }
  624.  
  625.  
  626. BOOL SendRexxCommand(char *name)
  627. {
  628.         struct MsgPort *rexxport;       /* System's Rexx port */
  629.         struct RexxMsg *rxmessage;
  630.  
  631.         Forbid();
  632.         if (!(rexxport = FindPort(RXSDIR))) {
  633.                 Permit();
  634.                 return FALSE;
  635.         }
  636.         if (!(rxmessage = CreateRexxMsg(MyRexxPort,
  637.          NULL, MyRexxPort->mp_Node.ln_Name))) {
  638.                 Permit();
  639.                 return FALSE;
  640.         }
  641.  
  642.         if (!(rxmessage->rm_Args[0] = CreateArgstring(name, strlen(name)))) {
  643.                 Permit();
  644.                 return FALSE;
  645.         }
  646.         rxmessage->rm_Action = RXCOMM | RXFB_NOIO;              /* OR a stringcommand here */
  647.  
  648.         /* Change to the directory of the project */
  649.         /* We put the old lock in Args[15] for FreeRexxCommand() */
  650.         rxmessage->rm_Args[15] =
  651.          (STRPTR)CurrentDir(Lock(CurrentPro->Drawer,ACCESS_READ));
  652.         PutMsg(rexxport, (struct Message *)rxmessage);  /* Send it */
  653.         OutstandingRexxCommands++;                                                              /* For graceful cleanup */
  654.         Permit();
  655.         return TRUE;
  656. }
  657.  
  658.  
  659. BOOL SendRexxStrCommand(char *name)
  660. {
  661.         char *str;
  662.         BOOL success;
  663.         int bufsize = strlen(name)+3;
  664.  
  665.         if (!(str = AllocMem(bufsize, 0))) {
  666.                 return FALSE;
  667.         }
  668.         sprintf(str,"\"%s\"", name);
  669.         
  670.         success = SendRexxCommand(str);
  671.         
  672.         FreeMem(str, bufsize);
  673.         return success;
  674. }
  675.  
  676.  
  677. BOOL HandleRexxMessage(struct MsgPort *rexxport)
  678. {
  679.         BOOL finished = FALSE;
  680.         struct RexxMsg *rxmessage;
  681.         /* returns TRUE when command is finished */
  682.  
  683.         /* Is this a reply? ie has a command finished? */
  684.         while (rxmessage = (struct RexxMsg *)GetMsg(rexxport)) {
  685.                 if (rxmessage->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
  686.                         FreeRexxCommand(rxmessage);
  687.                         finished = TRUE;
  688.                         CurrentPro->Quiet = FALSE;
  689.                         if (CurrentPro->CurrentLayout)
  690.                                 FreeInput(CurrentPro->CurrentLayout->Window);
  691.                 }
  692.                 else HandleRexxCommand(rxmessage);
  693.         }
  694.         return finished;
  695. }
  696.  
  697.