4 ** Copyright (C) 1994,95,96,97 by Bernardo Innocenti
6 ** ARexx interface handling routines
9 #include <exec/memory.h>
10 #include <rexx/rxslib.h>
11 #include <rexx/storage.h>
12 #include <rexx/errors.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
16 #include <proto/intuition.h>
17 #include <proto/utility.h>
18 #include <proto/rexxsyslib.h>
19 #include <proto/xmodule.h>
21 #include "XModulePriv.h"
29 const STRPTR Template;
30 LONG (*Func)(struct RexxMsg *, LONG *);
31 LONG Pad; /* Makes each entry 16 bytes long for faster array access */
35 /* Local function prototypes */
37 static LONG ExecRexxCmd (struct RexxMsg *msg, struct RexxCmd *cmd, const UBYTE *rexxargs);
39 static LONG RexxActivate (struct RexxMsg *msg, LONG *args);
40 static LONG RexxClear (struct RexxMsg *msg, LONG *args);
41 static LONG RexxClose (struct RexxMsg *msg, LONG *args);
42 static LONG RexxColumn (struct RexxMsg *msg, LONG *args);
43 static LONG RexxCopy (struct RexxMsg *msg, LONG *args);
44 static LONG RexxCursor (struct RexxMsg *msg, LONG *args);
45 static LONG RexxCut (struct RexxMsg *msg, LONG *args);
46 static LONG RexxDeactivate (struct RexxMsg *msg, LONG *args);
47 static LONG RexxErase (struct RexxMsg *msg, LONG *args);
48 static LONG RexxGotoBookmark (struct RexxMsg *msg, LONG *args);
49 static LONG RexxHelp (struct RexxMsg *msg, LONG *args);
50 static LONG RexxIconify (struct RexxMsg *msg, LONG *args);
51 static LONG RexxLine (struct RexxMsg *msg, LONG *args);
52 static LONG RexxLockGui (struct RexxMsg *msg, LONG *args);
53 static LONG RexxNew (struct RexxMsg *msg, LONG *args);
54 static LONG RexxOpen (struct RexxMsg *msg, LONG *args);
55 static LONG RexxOptimize (struct RexxMsg *msg, LONG *args);
56 static LONG RexxPaste (struct RexxMsg *msg, LONG *args);
57 static LONG RexxPrint (struct RexxMsg *msg, LONG *args);
58 static LONG RexxQuit (struct RexxMsg *msg, LONG *args);
59 static LONG RexxRequestFile (struct RexxMsg *msg, LONG *args);
60 static LONG RexxRequestResponse (struct RexxMsg *msg, LONG *args);
61 static LONG RexxRequestNotify (struct RexxMsg *msg, LONG *args);
62 static LONG RexxSave (struct RexxMsg *msg, LONG *args);
63 static LONG RexxSaveInstrument (struct RexxMsg *msg, LONG *args);
64 static LONG RexxScreenToBack (struct RexxMsg *msg, LONG *args);
65 static LONG RexxScreenToFront (struct RexxMsg *msg, LONG *args);
66 static LONG RexxSelectInstrument(struct RexxMsg *msg, LONG *args);
67 static LONG RexxSetBookmark (struct RexxMsg *msg, LONG *args);
68 static LONG RexxShowMessage (struct RexxMsg *msg, LONG *args);
69 static LONG RexxUnLockGui (struct RexxMsg *msg, LONG *args);
70 static LONG RexxVersion (struct RexxMsg *msg, LONG *args);
73 static struct Library *RexxSysBase = NULL;
75 XDEF struct MsgPort *PubPort = NULL;
76 XDEF ULONG PubPortSig = 0L;
77 XDEF UBYTE PubPortName[16]; /* ARexx host name */
80 static struct RexxCmd RexxCmds[] =
82 { "ACTIVATE", NULL, RexxActivate },
83 { "CLEAR", "FORCE/S", RexxClear },
84 { "CLOSE", "FORCE/S", RexxClose },
85 { "COLUMN", "/N/A", RexxColumn },
86 { "COPY", NULL, RexxCopy },
87 { "CURSOR", "UP/S,DOWN/S,LEFT/S,RIGHT/S", RexxCursor },
88 { "CUT", NULL, RexxCut },
89 { "DEACTIVATE", NULL, RexxDeactivate },
90 { "ERASE", "FORCE/S", RexxErase },
91 { "GOTOBOOKMARK", NULL, RexxGotoBookmark },
92 { "HELP", "COMMAND,PROMPT/S", RexxHelp },
93 { "ICONIFY", NULL, RexxIconify },
94 { "LINE", "/N/A", RexxLine },
95 { "LOCKGUI", NULL, RexxLockGui },
96 { "NEW", "PORTNAME/K", RexxNew },
97 { "OPEN", "FILENAME,FORCE/S", RexxOpen },
98 { "OPTIMIZE", NULL, RexxOptimize },
99 { "PASTE", NULL, RexxPaste },
100 { "PRINT", "PROMPT/S", RexxPrint },
101 { "QUIT", "FORCE/S", RexxQuit },
102 { "REQUESTFILE", "TITLE/K,PATH/K,FILE/K,PATTERN/K", RexxRequestFile },
103 { "REQUESTRESPONSE","TITLE/K,PROMPT/K", RexxRequestResponse },
104 { "REQUESTNOTIFY", "PROMPT/K", RexxRequestNotify },
105 { "SAVE", "NAME,FORMAT", RexxSave },
106 { "SAVEINSTRUMENT", "NAME", RexxSaveInstrument },
107 { "SCREENTOBACK", NULL, RexxScreenToBack },
108 { "SCREENTOFRONT", NULL, RexxScreenToFront },
109 { "SELECTINSTRUMENT","/N/A", RexxSelectInstrument },
110 { "SETBOOKMARK", NULL, RexxSetBookmark },
111 { "SHOWMESSAGE", "MSG/A", RexxShowMessage },
112 { "UNLOCKGUI", NULL, RexxUnLockGui },
113 { "VERSION", NULL, RexxVersion }
116 #define COMMAND_CNT (sizeof (RexxCmds) / sizeof (struct RexxCmd))
119 GLOBALCALL void HandleRexxMsg (void)
121 /* Arexx command handler */
124 LONG compare, high, low, mid, skip, cmdlen;
128 while (msg = (struct RexxMsg *) GetMsg (PubPort))
132 msg->rm_Result1 = RETURN_FAIL;
134 /* Find command name length */
138 while (*arg0 && (*arg0 != ' ') && (*arg0 != '\t')
139 && (*arg0 != '\n') && (cmdlen < 31))
141 cmd[cmdlen] = *arg0 & ~(1 << 5); /* Fast toupper() */
149 high = COMMAND_CNT - 1;
151 /* Perform an optimized binary serch to find the ARexx
152 * command in the ARexx commands array.
156 /* Search optimization. Skip first characters until they
158 * We must test low != high because otherwise this
159 * loop would go past the end of the string, as the
160 * two strings we compare are identical).
163 while ((RexxCmds[low].Cmd[skip] == RexxCmds[high].Cmd[skip])
164 && (RexxCmds[low].Cmd[skip] == cmd[skip]))
167 mid = (low + high) >> 1;
168 compare = strcmp (RexxCmds[mid].Cmd + skip, cmd + skip);
172 else if (compare < 0)
176 msg->rm_Result1 = ExecRexxCmd (msg, &RexxCmds[mid],
178 break; /* Exit from loop */
184 ReplyMsg ((struct Message *)msg);
190 static LONG ExecRexxCmd (struct RexxMsg *msg, struct RexxCmd *cmd, const UBYTE *rexxargs)
192 struct RDArgs *rdargs;
194 ULONG arglen = strlen (rexxargs) + 1; /* Space for newline */
196 LONG argarray[6] = { 0L }; /* Max 6 arguments allowed! */
198 ShowRequesters = FALSE;
201 rc = (cmd->Func)(msg, NULL); /* Call command directly */
202 else if (argbuf = AllocVec (arglen, MEMF_ANY))
204 /* Copy arguments to temporary buffer.
205 * ReadArgs() also requires a newline.
207 strcpy (argbuf, rexxargs);
208 argbuf[arglen-1] = '\n';
210 if (rdargs = AllocDosObject (DOS_RDARGS, NULL))
212 rdargs->RDA_Source.CS_Buffer = argbuf;
213 rdargs->RDA_Source.CS_Length = arglen;
214 rdargs->RDA_Flags |= RDAF_NOPROMPT;
216 if (ReadArgs ((volatile STRPTR)cmd->Template, argarray, rdargs))
218 /* Call Command server */
219 rc = (cmd->Func)(msg, argarray);
223 FreeDosObject (DOS_RDARGS, rdargs);
228 ShowRequesters = TRUE;
235 GLOBALCALL LONG CreateRexxPort (void)
237 /* Setup public port for ARexx host */
241 if (!PubPortName[0]) return RETURN_FAIL;
243 if (!(RexxSysBase = OpenLibrary (RXSNAME, 36L)))
246 if (!(PubPort = CreateMsgPort ())) return ERROR_NO_FREE_STORE;
248 PubPortSig = 1 << PubPort->mp_SigBit;
249 Signals |= PubPortSig;
252 while (FindPort (PubPortName))
253 SPrintf (PubPortName, "XMODULE.%ld", ++i);
255 PubPort->mp_Node.ln_Name = PubPortName;
256 PubPort->mp_Node.ln_Pri = 1;
264 GLOBALCALL void DeleteRexxPort (void)
269 KillMsgPort (PubPort); PubPort = NULL;
273 { CloseLibrary (RexxSysBase); RexxSysBase = NULL; }
276 /************************/
277 /* Rexx Command servers */
278 /************************/
280 static LONG RexxActivate (struct RexxMsg *msg, LONG *args)
285 static LONG RexxClear (struct RexxMsg *msg, LONG *args)
290 static LONG RexxClose (struct RexxMsg *msg, LONG *args)
295 static LONG RexxColumn (struct RexxMsg *msg, LONG *args)
300 static LONG RexxCopy (struct RexxMsg *msg, LONG *args)
305 static LONG RexxCursor (struct RexxMsg *msg, LONG *args)
310 static LONG RexxCut (struct RexxMsg *msg, LONG *args)
315 static LONG RexxDeactivate (struct RexxMsg *msg, LONG *args)
322 static LONG RexxErase (struct RexxMsg *msg, LONG *args)
329 static LONG RexxGotoBookmark (struct RexxMsg *msg, LONG *args)
336 static LONG RexxHelp (struct RexxMsg *msg, LONG *args)
343 static LONG RexxIconify (struct RexxMsg *msg, LONG *args)
351 static LONG RexxLine (struct RexxMsg *msg, LONG *args)
358 static LONG RexxLockGui (struct RexxMsg *msg, LONG *args)
367 static LONG RexxNew (struct RexxMsg *msg, LONG *args)
371 if (si = xmCreateSong (
372 SNGA_ReadyToUse, TRUE,
377 ReleaseSemaphore (&si->Lock);
386 static LONG RexxOpen (struct RexxMsg *msg, LONG *args)
394 if (si = xmLoadModule ((STRPTR)args[0],
396 XMSNG_AddToList, TRUE,
399 ReleaseSemaphore (&si->Lock);
403 UBYTE filename[PATHNAME_MAX];
407 if (FileRequest (FREQ_LOADMOD, filename))
409 if (si = xmLoadModule (filename,
411 XMSNG_AddToList, TRUE,
414 ReleaseSemaphore (&si->Lock);
425 static LONG RexxOptimize (struct RexxMsg *msg, LONG *args)
429 if (si = xmLockActiveSong (SM_EXCLUSIVE))
431 xmProcessSong (si, NULL,
432 XMSNG_Optimize, XMOF_DEFAULT,
437 ReleaseSemaphore (&si->Lock);
445 static LONG RexxPaste (struct RexxMsg *msg, LONG *args)
452 static LONG RexxPrint (struct RexxMsg *msg, LONG *args)
459 static LONG RexxQuit (struct RexxMsg *msg, LONG *args)
462 if (args[0]) GuiSwitches.AskExit = FALSE;
469 static LONG RexxRequestFile (struct RexxMsg *msg, LONG *args)
476 static LONG RexxRequestResponse (struct RexxMsg *msg, LONG *args)
478 return ShowRequestStr ((STRPTR)args[0], (STRPTR)args[1], NULL);
483 static LONG RexxRequestNotify (struct RexxMsg *msg, LONG *args)
485 ShowRequestStr ((STRPTR)args[0], NULL, NULL);
491 static LONG RexxSave (struct RexxMsg *msg, LONG *args)
495 if (si = xmLockActiveSong (SM_SHARED))
499 SNGA_Path, (STRPTR)args[0],
504 struct XMHook *saver;
506 /* Workaround for Pre-V39 ObtainSemaphoreShared() bug (see autodoc) */
508 /* Try to get the shared semaphore */
509 if (!AttemptSemaphoreShared (&XModuleBase->xm_BaseLock))
510 /* Check if we can get the exclusive version */
511 if (!AttemptSemaphore (&XModuleBase->xm_BaseLock))
512 /* Oh well, wait for the shared lock */
513 ObtainSemaphoreShared (&XModuleBase->xm_BaseLock);
515 if (saver = (struct XMHook *)FindName ((struct List *)&XModuleBase->xm_Loaders, (STRPTR)args[1]))
516 LastErr = xmSaveModuleA (si, si->Path, saver, NULL);
518 LastErr = ERROR_OBJECT_NOT_FOUND;
520 ReleaseSemaphore (&XModuleBase->xm_BaseLock);
523 LastErr = xmSaveModuleA (si, si->Path, NULL, NULL);
525 ReleaseSemaphore (&si->Lock);
533 static LONG RexxSaveInstrument (struct RexxMsg *msg, LONG *args)
537 if (si = xmLockActiveSong (SM_SHARED))
539 struct Instrument *instr;
541 if (instr = si->Instr[si->CurrentInst])
544 LastErr = SaveInstrument (instr, (STRPTR)args[0]);
546 LastErr = SaveInstrument (instr, instr->Name);
548 else LastErr = ERROR_OBJECT_NOT_FOUND;
550 ReleaseSemaphore (&si->Lock);
558 static LONG RexxSelectInstrument (struct RexxMsg *msg, LONG *args)
562 if (si = xmLockActiveSong (SM_SHARED))
564 if (*((ULONG *)args[0]) >= MAXINSTRUMENTS)
567 si->CurrentInst = *((ULONG *)args[0]);
569 ReleaseSemaphore (&si->Lock);
579 static LONG RexxScreenToBack (struct RexxMsg *msg, LONG *args)
581 if (Scr) ScreenToBack (Scr);
588 static LONG RexxScreenToFront (struct RexxMsg *msg, LONG *args)
593 if (ThisTask->pr_WindowPtr) ActivateWindow (ThisTask->pr_WindowPtr);
601 static LONG RexxSetBookmark (struct RexxMsg *msg, LONG *args)
608 static LONG RexxShowMessage (struct RexxMsg *msg, LONG *args)
610 ShowString ((STRPTR)args[0], NULL);
617 static LONG RexxUnLockGui (struct RexxMsg *msg, LONG *args)
625 static LONG RexxVersion (struct RexxMsg *msg, LONG *args)
629 SPrintf (RexxVer, "%ld.%ld", VERSION, REVISION);
631 // SetRexxVar ((struct Message *)msg, "RESULT", RexxVer, strlen (RexxVer));
632 msg->rm_Result2=(LONG)CreateArgstring (RexxVer, (LONG)strlen(RexxVer));