home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / bazy / db3.4 / dbrexx.c < prev    next >
C/C++ Source or Header  |  1997-01-28  |  16KB  |  655 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 liner */
  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.  
  144. static void Rx_Add(RXInfo *ri)
  145. {
  146.     DB_ADD();
  147. }
  148.  
  149. static void Rx_Kill(RXInfo *ri)
  150. {
  151.     DB_KILL();
  152. }
  153.  
  154. static void Rx_FirstRecord(RXInfo *ri)
  155. {
  156.     UpdateRecord(CurrentPro);
  157.     if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
  158.     JumpList(CurrentPro, -CurrentPro->RecNum);
  159.     if (CurrentPro->Mode == MODE_NORMAL) {
  160.         UpdateWindow(CurrentPro);
  161.         UpdateDragBar(CurrentPro);
  162.     }
  163.     if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  164.  
  165.     stci_d(ri->buf, CurrentPro->RecNum+1);
  166.     ri->Result = ri->buf;
  167. }
  168.  
  169. static void Rx_NextRecord(RXInfo *ri)
  170. {
  171.     if (CurrentPro->RecNum < (CurrentPro->RecSum-1)) {
  172.         if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
  173.         JumpList(CurrentPro, 1);
  174.         if (CurrentPro->Mode == MODE_NORMAL) {
  175.             UpdateWindow(CurrentPro);
  176.             UpdateDragBar(CurrentPro);
  177.         }
  178.         if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  179.     }
  180.     else ri->RC = RC_WARN;
  181.     stci_d(ri->buf, CurrentPro->RecNum+1);
  182.     ri->Result = ri->buf;
  183. }
  184.  
  185. static void Rx_CurrentRecord(RXInfo *ri)
  186. {
  187.     int recnum;
  188.     if (*ri->arg) {
  189.         recnum = atoi(ri->arg)-1;
  190.         if (recnum >= 0 && recnum < CurrentPro->RecSum) {
  191.             if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
  192.             JumpList(CurrentPro, -CurrentPro->RecNum+recnum);
  193.             if (CurrentPro->Mode == MODE_NORMAL) {
  194.                 UpdateWindow(CurrentPro);
  195.                 UpdateDragBar(CurrentPro);
  196.             }
  197.             if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  198.         }
  199.         else ri->RC = RC_WARN;
  200.     }
  201.     stci_d(ri->buf, CurrentPro->RecNum+1);
  202.     ri->Result = ri->buf;
  203. }
  204.  
  205. static void Rx_RecordSum(RXInfo *ri)
  206. {
  207.     stci_d(ri->buf, CurrentPro->RecSum);
  208.     ri->Result = ri->buf;
  209. }
  210.  
  211. static void Rx_FindFirst(RXInfo *ri)
  212. {
  213.     if (!FindRecord(CurrentPro,0,1)) ri->RC = RC_WARN;
  214.     stci_d(ri->buf, CurrentPro->RecNum+1);
  215.     ri->Result = ri->buf;
  216. }
  217.  
  218. static void Rx_FindNext(RXInfo *ri)
  219. {
  220.     if (!FindRecord(CurrentPro,CurrentPro->RecNum+1,1)) ri->RC = RC_WARN;
  221.     stci_d(ri->buf, CurrentPro->RecNum+1);
  222.     ri->Result = ri->buf;
  223. }
  224.  
  225. static void Rx_Cut(RXInfo *ri)
  226. {
  227.     DB_CUT();
  228. }
  229.  
  230. static void Rx_Copy(RXInfo *ri)
  231. {
  232.     DB_COPY();
  233. }
  234.  
  235. static void Rx_Paste(RXInfo *ri)
  236. {
  237.     DB_PASTE();
  238. }
  239.  
  240. static void Rx_Merge(RXInfo *ri)
  241. {
  242.     UpdateRecord(CurrentPro);
  243.     PasteFromClipboard(CurrentPro, *CurrentPro->Recpp);
  244.     CurrentPro->Modified |= PROMODIFIED;
  245.     UpdateGadgets(CurrentPro);
  246. }
  247.  
  248. static void Rx_FirstField(RXInfo *ri)
  249. {
  250.     struct FldInfo *fi;
  251.     if (fi = GetFldInfo(CurrentPro, 0)) {
  252.         CurrentPro->CurrentFldOffset = 0;
  253.         ri->Result = fi->Name;
  254.     }
  255.     else ri->RC = RC_WARN;    /* No fields at all */
  256. }
  257.  
  258. static void Rx_NextField(RXInfo *ri)
  259. {
  260.     struct FldInfo *fi;
  261.     if (fi = GetFldInfo(CurrentPro, CurrentPro->CurrentFldOffset+1)) {
  262.         CurrentPro->CurrentFldOffset++;
  263.         ri->Result = fi->Name;
  264.     }
  265.     else ri->RC = RC_WARN;
  266. }
  267.  
  268. static void Rx_CurrentField(RXInfo *ri)
  269. {
  270.     int offset;
  271.     struct FldInfo *fi;
  272.  
  273.     if (*ri->arg) {
  274.         if ((offset = GetFldIndex(CurrentPro, ri->arg)) == -1) {
  275.             ri->RC = RC_WARN;
  276.             return;
  277.         }
  278.         CurrentPro->CurrentFldOffset = offset;
  279.     }
  280.     if (fi = GetFldInfo(CurrentPro, CurrentPro->CurrentFldOffset)) ri->Result = fi->Name;
  281.     else ri->RC = RC_WARN;    /* Should never happen */
  282. }
  283.  
  284.  
  285. static void Rx_GetField(RXInfo *ri)                            /* ri->arg is fieldname */
  286. {
  287.     UpdateRecord(CurrentPro);
  288.     if (*ri->arg) ri->Result = RXGetFld(CurrentPro, ri->arg);
  289.     else ri->Result = GetFld(*CurrentPro->Recpp, CurrentPro->CurrentFldOffset);
  290.     if (!ri->Result) ri->RC = RC_WARN;
  291. }
  292.  
  293.  
  294. static void Rx_PutField(RXInfo *ri)
  295. {
  296.     UpdateRecord(CurrentPro);
  297.     if (UpdateFld(*CurrentPro->Recpp, CurrentPro->CurrentFldOffset, ri->arg) &&
  298.      CurrentPro->Mode == MODE_NORMAL)
  299.         CurrentPro->Modified |= PROMODIFIED;
  300.     UpdateGadgets(CurrentPro);
  301. }
  302.  
  303. static void Rx_Mode(RXInfo *ri)
  304. {
  305.     if (*ri->arg) {
  306.         if (!Stricmp(ri->arg, "Normal")) SetProMode(CurrentPro, MODE_NORMAL);
  307.         else if (!Stricmp(ri->arg, "Find")) SetProMode(CurrentPro, MODE_FIND);
  308.         else if (!Stricmp(ri->arg, "Sort")) SetProMode(CurrentPro, MODE_SORT);
  309.         else ri->RC = RC_ERROR;
  310.     }
  311.  
  312.     switch (CurrentPro->Mode) {
  313.         case MODE_NORMAL:
  314.             ri->Result = "Normal";
  315.             break;
  316.         case MODE_FIND:
  317.             ri->Result = "Find";
  318.             break;
  319.         case MODE_SORT:
  320.             ri->Result = "Sort";
  321.             break;
  322.     }
  323. }
  324.  
  325. static void Rx_Save(RXInfo *ri)
  326. {
  327.     DB_SAVE();
  328. }
  329.  
  330. static void Rx_Sort(RXInfo *ri)
  331. {
  332.     DoSort(CurrentPro, -1);
  333. }
  334.  
  335. static void Rx_Quit(RXInfo *ri)
  336. {
  337.     ReplyRexxCommand(ri->rxmessage, RC_OK, 0);
  338.     ByeBye();
  339. }
  340.  
  341. static void Rx_UpdateGUI(RXInfo *ri)
  342. {
  343.     BOOL save = CurrentPro->Quiet;
  344.     CurrentPro->Quiet = FALSE;
  345.     SetProMode(CurrentPro, CurrentPro->Mode);
  346.     CurrentPro->Quiet = save;
  347. }
  348.  
  349. static void Rx_WindowToFront(RXInfo *ri)
  350. {
  351.     if (CurrentPro->CurrentLayout->Window)
  352.         WindowToFront(CurrentPro->CurrentLayout->Window);
  353.     else ri->RC = RC_WARN;
  354.  
  355. }
  356.  
  357. static void Rx_ScreenToFront(RXInfo *ri)
  358. {
  359.     ScreenToFront(Scr);
  360. }
  361.  
  362. static void Rx_ActivateWindow(RXInfo *ri)
  363. {
  364.     if (CurrentPro->CurrentLayout->Window)
  365.         ActivateWindow(CurrentPro->CurrentLayout->Window);
  366.     else ri->RC = RC_WARN;
  367. }
  368.  
  369. static void Rx_BlockInput(RXInfo *ri)
  370. {
  371.     BlockInput(CurrentPro->CurrentLayout->Window, TRUE);
  372.     UpdateRecord(CurrentPro);
  373.     CurrentPro->Quiet = TRUE;    /* Don't do any GUI stuff from now on */
  374. }
  375.  
  376. static void Rx_FreeInput(RXInfo *ri)
  377. {
  378.     FreeInput(CurrentPro->CurrentLayout->Window);
  379.     CurrentPro->Quiet = FALSE;        /* Release GUI now */
  380.     Rx_UpdateGUI(ri);
  381. }
  382.  
  383. static void Rx_Dial(RXInfo *ri)
  384. {
  385.     ri->RC = DoDial(ri->arg);
  386. }
  387.  
  388. static void Rx_DisplayBeep(RXInfo *ri)
  389. {
  390.     DisplayBeep(Scr);
  391. }
  392.  
  393. static void Rx_Okay1(RXInfo *ri)
  394. {
  395.     EasyRexxRequest(CurrentPro->CurrentLayout->Window, &ES_RexxOkay1, NULL, ri->arg);
  396. }
  397.  
  398. static void Rx_Okay2(RXInfo *ri)
  399. {
  400.     stci_d(ri->buf, EasyRexxRequest(CurrentPro->CurrentLayout->Window, &ES_RexxOkay2, NULL, ri->arg));
  401.     ri->Result = ri->buf;
  402. }
  403.  
  404. static void Rx_CurrentGadget(RXInfo *ri)
  405. {
  406.     int gadindex;
  407.     struct VisFldInfo *vf;
  408.  
  409.     NextGad = NULL;
  410.     if (*ri->arg) {
  411.         gadindex = atoi(ri->arg);
  412.         if (!gadindex--) {    /* string argument, not a number */
  413.             for(vf=CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next)
  414.                 if (!Stricmp(ri->arg, vf->Name)) break;
  415.         }
  416.         else for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf && gadindex > 0; vf = vf->Next, gadindex--);
  417.         if (vf) LastGad = vf->Gadget;
  418.     }
  419.     if (LastGad) {
  420.         for(gadindex=1, vf=CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next, gadindex++)
  421.             if (vf->Gadget == LastGad) break;
  422.  
  423.         stci_d(ri->buf, gadindex);
  424.         ri->Result = ri->buf;
  425.  
  426.     }
  427.     else ri->RC = RC_WARN;
  428. }
  429.  
  430. static void Rx_RetryInput(RXInfo *ri)
  431. {
  432.         NextGad = NULL;    /* Don't activate NextGad if tabcycling */
  433.         ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  434. }
  435.  
  436. static void Rx_CurrentView(RXInfo *ri)
  437. {
  438.     int viewindex;
  439.     struct Layout *lay = CurrentPro->FirstLayout;
  440.  
  441.     if (*ri->arg) {
  442.         viewindex = atoi(ri->arg);
  443.         if (!viewindex--) {    /* string argument, not a number */
  444.             for (; lay; lay = lay->NextLayout)
  445.                 if (!Stricmp(ri->arg, lay->Name)) break;
  446.         } else for (; lay && viewindex; lay = lay->NextLayout, viewindex--);
  447.         ChangeView(lay);
  448.     }
  449.     else for (viewindex=1; lay != CurrentPro->CurrentLayout; lay = lay->NextLayout, viewindex++);
  450.  
  451.     stci_d(ri->buf, viewindex);
  452.     ri->Result = ri->buf;
  453. }
  454.  
  455. static void Rx_UndoBuffer(RXInfo *ri)
  456. {
  457.     if (LastGad && LastGad->GadgetID == STRING_KIND)
  458.         ri->Result = ((struct StringInfo *)LastGad->SpecialInfo)->UndoBuffer;
  459.     else ri->RC = RC_WARN;
  460. }
  461.  
  462. static void Rx_GetPortName(RXInfo *ri)    /* Undocumented. The ARexx function Address() should do this job */
  463. {
  464.     ri->Result = MyRexxPortName;
  465. }
  466.  
  467.  
  468. /**********************************************************************/
  469. /*                      ARexx command dispatcher                      */
  470. /**********************************************************************/
  471.  
  472. typedef struct {
  473.     char *name;
  474.     void (*cmd)(RXInfo *);
  475. } Comm;
  476.  
  477. static Comm Commands[] = {
  478.     { "Add", Rx_Add },
  479.     { "Kill", Rx_Kill }, 
  480.     { "FirstRecord", Rx_FirstRecord, },
  481.     { "NextRecord", Rx_NextRecord },
  482.     { "CurrentRecord", Rx_CurrentRecord },
  483.     { "RecordSum", Rx_RecordSum },
  484.     { "FindFirst", Rx_FindFirst },
  485.     { "FindNext", Rx_FindNext },
  486.     { "Cut", Rx_Cut },
  487.     { "Copy", Rx_Copy },
  488.     { "Paste", Rx_Paste },
  489.     { "Merge", Rx_Merge },
  490.     { "FirstField", Rx_FirstField },
  491.     { "NextField", Rx_NextField },
  492.     { "CurrentField", Rx_CurrentField },
  493.     { "GetField", Rx_GetField },
  494.     { "PutField", Rx_PutField },
  495.     { "Mode", Rx_Mode },
  496.     { "Save", Rx_Save },
  497.     { "Sort", Rx_Sort },
  498.     { "Quit", Rx_Quit },
  499.     { "UpdateGUI", Rx_UpdateGUI },
  500.     { "WindowToFront", Rx_WindowToFront },
  501.     { "ScreenToFront", Rx_ScreenToFront },
  502.     { "ActivateWindow", Rx_ActivateWindow },
  503.     { "BlockInput", Rx_BlockInput },
  504.     { "FreeInput", Rx_FreeInput },
  505.     { "Dial", Rx_Dial },
  506.     { "DisplayBeep", Rx_DisplayBeep },
  507.     { "Okay1", Rx_Okay1 },
  508.     { "Okay2", Rx_Okay2 },
  509.     { "CurrentGadget", Rx_CurrentGadget },
  510.     { "UndoBuffer", Rx_UndoBuffer },
  511.     { "RetryInput", Rx_RetryInput },
  512.     { "CurrentView", Rx_CurrentView },
  513.     { "GetPortName", Rx_GetPortName },
  514.     { NULL, NULL }
  515. };
  516.  
  517.  
  518. void HandleRexxCommand(struct RexxMsg *rxmessage)
  519. {
  520.     int i, namelen;
  521.     char name[40];
  522.     char *cmdline = ARG0(rxmessage);
  523.     RXInfo ri;
  524.  
  525.     ri.rxmessage = rxmessage;    /* QUIT needs to answer itself */
  526.     ri.RC = RC_OK;
  527.     ri.Result = NULL;    
  528.  
  529.     /* Split cmdline into name and arg without affecting cmdline */
  530.     for (i=0; i<30 && cmdline[i] && cmdline[i] != ' '; i++)
  531.         name[i] = cmdline[i];
  532.     name[i] = '\0';
  533.     namelen = strlen(name);
  534.     ri.arg = NextWord(cmdline);
  535.  
  536.     /* Do the dispatch */
  537.     for (i=0; Commands[i].name; i++)    {
  538.         if (!Strnicmp(Commands[i].name, name, namelen)) {
  539.             Commands[i].cmd(&ri);    /* Run this command */
  540.             ReplyRexxCommand(rxmessage, ri.RC, ri.Result);
  541.             return;
  542.         }
  543.     }
  544.     ReplyRexxCommand(rxmessage,RC_ERROR,NULL);        /* Command not found */
  545. }
  546.  
  547.  
  548. void FreeRexxCommand(struct RexxMsg *rxmessage)
  549. {
  550.     struct Window *win = (CurrentPro->CurrentLayout) ?
  551.      CurrentPro->CurrentLayout->Window : NULL;
  552.  
  553.     if (rxmessage->rm_Result1) {
  554.         if (rxmessage->rm_Result2 == ERR10_001)     /* Program not found */
  555.             EasyLocRequest(win, &ES_RexxProgNotFound, NULL, ARG0(rxmessage));
  556.         else EasyLocRequest(win, &ES_RexxError, NULL, ARG0(rxmessage), rxmessage->rm_Result2);
  557.     }    
  558.     DeleteArgstring(rxmessage->rm_Args[0]);    /* The command name */
  559.  
  560.     /* In SendRexxCommand we cd to project's dir, cd back and unlock now */
  561.     UnLock(CurrentDir((BPTR)rxmessage->rm_Args[15]));
  562.     DeleteRexxMsg(rxmessage);
  563.     OutstandingRexxCommands--;
  564. }
  565.  
  566.  
  567. void CloseRexxPort(struct MsgPort *rexxport)
  568. {
  569.     struct RexxMsg *rxmessage;
  570.     
  571.     do {
  572.         while (rxmessage = (struct RexxMsg *)GetMsg(rexxport)) {
  573.              if (rxmessage->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  574.                 FreeRexxCommand(rxmessage);     /* A command finished */
  575.             else ReplyRexxCommand(rxmessage, ERR10_013, NULL); /* 'Host not found' */
  576.         }
  577.         if (OutstandingRexxCommands) WaitPort(rexxport);
  578.     } while (OutstandingRexxCommands);        /* Wait out all commands we've sent */
  579.  
  580.     DeletePort(rexxport);
  581. }
  582.  
  583.  
  584. BOOL SendRexxCommand(char *name)
  585. {
  586.     struct MsgPort *rexxport;    /* System's Rexx port */
  587.     struct RexxMsg *rxmessage;
  588.  
  589.     Forbid();
  590.     if (!(rexxport = FindPort(RXSDIR))) {
  591.         Permit();
  592.         return FALSE;
  593.     }
  594.     if (!(rxmessage = CreateRexxMsg(MyRexxPort,
  595.      NULL, MyRexxPort->mp_Node.ln_Name))) {
  596.         Permit();
  597.         return FALSE;
  598.     }
  599.  
  600.     if (!(rxmessage->rm_Args[0] = CreateArgstring(name, strlen(name)))) {
  601.         Permit();
  602.         return FALSE;
  603.     }
  604.     rxmessage->rm_Action = RXCOMM | RXFB_NOIO;        /* OR a stringcommand here */
  605.  
  606.     /* Change to the directory of the project */
  607.     /* We put the old lock in Args[15] for FreeRexxCommand() */
  608.     rxmessage->rm_Args[15] =
  609.      (STRPTR)CurrentDir(Lock(CurrentPro->Drawer,ACCESS_READ));
  610.     PutMsg(rexxport, (struct Message *)rxmessage);    /* Send it */
  611.     OutstandingRexxCommands++;                                /* For graceful cleanup */
  612.     Permit();
  613.     return TRUE;
  614. }
  615.  
  616.  
  617. BOOL SendRexxStrCommand(char *name)
  618. {
  619.     char *str;
  620.     BOOL success;
  621.     int bufsize = strlen(name)+3;
  622.  
  623.     if (!(str = AllocMem(bufsize, 0))) {
  624.         return FALSE;
  625.     }
  626.     sprintf(str,"\"%s\"", name);
  627.     
  628.     success = SendRexxCommand(str);
  629.     
  630.     FreeMem(str, bufsize);
  631.     return success;
  632. }
  633.  
  634.  
  635. BOOL HandleRexxMessage(struct MsgPort *rexxport)
  636. {
  637.     BOOL finished = FALSE;
  638.     struct RexxMsg *rxmessage;
  639.     /* returns TRUE when command is finished */
  640.  
  641.     /* Is this a reply? ie has a command finished? */
  642.     while (rxmessage = (struct RexxMsg *)GetMsg(rexxport)) {
  643.         if (rxmessage->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
  644.             FreeRexxCommand(rxmessage);
  645.             finished = TRUE;
  646.             CurrentPro->Quiet = FALSE;
  647.             if (CurrentPro->CurrentLayout)
  648.                 FreeInput(CurrentPro->CurrentLayout->Window);
  649.         }
  650.         else HandleRexxCommand(rxmessage);
  651.     }
  652.     return finished;
  653. }
  654.  
  655.