Some compiler warnings removed.
[cake.git] / workbench / classes / datatypes / amigaguide / process.c
blobd2a71ce57c69b2e24763887eaa1809814022eab7
1 /*
2 ** $PROJECT: amigaguide.datatype
3 **
4 ** $VER: process.c 50.1 (14.06.03)
5 **
6 ** $AUTHOR: Stefan Ruppert <stefan@ruppert-it.de>
7 **
8 */
10 /* ------------------------------- includes ------------------------------- */
12 #include "classbase.h"
14 #include <dos/dostags.h>
16 /* ---------------------------- arexx autodoc ----------------------------- */
18 /****** amigaguide.datatype/--arexx-- ****************************************
20 NAME
21 ARexx interface -- amigaguide.datatype ARexx commands
23 FUNCTION
24 The amigaguide.datatype provides an own ARexx port for each object.
25 It's name is the port name passed via DTA_ARexxPortName plus a
26 suffix of '.1' or if this port exists '.2' and so on. If no
27 DTA_ARexxPortName is passed "AMIGAGUIDE" is used. For example if you
28 start MultiView with an amigaguide object, MultiView passes
29 "MULTIVIEW.1" for DTA_ARexxPortName to the amigaguide object. The
30 amigaguide.datatype tries to open a port named "MULTIVIEW.1.1".
32 AREXX COMMANDS
34 BEEP -- DisplayBeep().
36 CLOSE -- Close the current database.
38 CONTENTS -- Go to the contents node in the database. Same as pressing
39 the "Contents" button.
41 GETNODECOUNT -- Returns the number of nodes in the database using the
42 RESULT variable.
44 HELP -- Go to the help node in the database. Same as pressing the
45 "Help" button.
47 INDEX -- Go to the index node in the database. Same as pressing the
48 "Index" button.
50 LINK <node name> -- Go to the named node.
52 NEXT -- Go to the next physical node in the database. Same as pressing
53 the "Browse >" button.
55 PREVIOUS -- Go to the previous physical node in the database. Same as
56 pressing the "Browse <" button. New for V40.
58 PRINT -- Print the current node. Doesn't return until complete.
60 QUIT -- Close the current database.
62 RETRACE -- Go to the previous viewed node in the database. Same as
63 pressing the "Retrace" button.
65 RX <script> -- Launch the specified ARexx script.
67 SEE ALSO
69 ******************************************************************************
73 /* -------------------------- AG privat message --------------------------- */
75 struct AmigaGuideDTMsg
77 struct Message agm_Msg;
78 ULONG agm_Type;
80 union
82 struct
84 ULONG Trigger;
85 APTR Data;
86 } Trigger;
87 struct
89 BOOL Initial;
90 } Layout;
91 } agm_Data;
93 struct GadgetInfo agm_GInfo;
96 /* --------------------------- static functions --------------------------- */
98 static
99 void DoRexxTrigger(Class *cl, Object *obj, ULONG function, APTR trigger_data)
101 INSTDATA;
103 if(data->ag_Window != NULL)
105 struct dtTrigger dtt;
107 dtt.MethodID = DTM_TRIGGER;
108 dtt.dtt_GInfo = NULL;
109 dtt.dtt_Function = function;
110 dtt.dtt_Data = trigger_data;
112 DoDTMethodA(obj, data->ag_Window, NULL, (Msg) &dtt);
116 static
117 ULONG agdtm_rexxcmd(Class *cl, Object *obj, struct RexxMsg *msg)
119 CLASSBASE;
120 INSTDATA;
121 STRPTR cmd;
123 DB(("command received : %s\n",msg->rm_Args[0]));
125 cmd = CopyString(cl, obj, (STRPTR)msg->rm_Args[0]);
126 if(cmd != NULL)
128 STRPTR ptr = cmd;
129 STRPTR cmdend;
130 UBYTE chr ;
131 while(*ptr != '\0' && *ptr != ' ' && *ptr != '\t')
132 ++ptr;
133 cmdend = ptr;
134 chr = *ptr;
135 if(*ptr != '\0')
136 *ptr = '\0';
138 if(!Stricmp(cmd, "PRINT"))
140 /* TODO implement printing ARexx command. */
141 } else if(!Stricmp(cmd, "QUIT") || !Stricmp(cmd, "CLOSE"))
143 Signal(data->ag_Creator, SIGBREAKF_CTRL_C);
144 } else if(!Stricmp(cmd, "RETRACE"))
146 DoRexxTrigger(cl, obj, STM_RETRACE, NULL);
147 } else if(!Stricmp(cmd, "PREVIOUS"))
149 DoRexxTrigger(cl, obj, STM_BROWSE_PREV, NULL);
150 } else if(!Stricmp(cmd, "NEXT"))
152 DoRexxTrigger(cl, obj, STM_BROWSE_NEXT, NULL);
153 } else if(!Stricmp(cmd, "INDEX"))
155 DoRexxTrigger(cl, obj, STM_INDEX, NULL);
156 } else if(!Stricmp(cmd, "CONTENTS"))
158 DoRexxTrigger(cl, obj, STM_CONTENTS, NULL);
159 } else if(!Stricmp(cmd, "HELP"))
161 DoRexxTrigger(cl, obj, STM_HELP, NULL);
162 } else if(!Stricmp(cmd, "LINK") ||
163 !Stricmp(cmd, "RXS") || !Stricmp(cmd, "RX"))
165 *cmdend = chr;
166 DoRexxTrigger(cl, obj, STM_COMMAND | STMD_STRPTR, cmd);
167 } else if(!Stricmp(cmd, "GETNODECOUNT"))
169 UBYTE numbuf[32];
170 mysprintf(cb, numbuf, sizeof(numbuf), "%ld", data->ag_File->agf_NodeCount);
171 msg->rm_Result2 = (ULONG) CreateArgstring(numbuf,strlen(numbuf));
172 } else if(!Stricmp(cmd, "BEEP"))
174 DisplayBeep(NULL);
177 FreeAGVec(cl, obj, cmd);
180 return 0;
183 struct ProcMessage
185 struct Message pm_Message;
186 struct ClassBase *pm_ClassBase;
187 Class *pm_Class;
188 Object *pm_Object;
189 struct Task *pm_Parent;
192 #ifdef __AROS__
193 AROS_UFH3S(void, asyncmethodfunc,
194 AROS_UFHA(STRPTR, argptr_unused, A0),
195 AROS_UFHA(ULONG, argsize_unused, D0),
196 AROS_UFHA(struct ExecBase *, SysBase, A6))
198 AROS_USERFUNC_INIT
199 #else
200 #undef SysBase
201 static
202 RegCall GetA4 void asyncmethodfunc(void)
204 struct Library *SysBase = *((struct Library **) 4L);
205 #endif
206 struct Process *proc = (struct Process *) FindTask(NULL);
207 struct ClassBase *cb = NULL;
208 struct ProcMessage *pmsg;
209 struct AmigaGuideData *data;
210 struct MsgPort *port,*rexxport;
211 Class *cl = NULL;
212 Object *obj = NULL;
213 ULONG procmask, rexxmask;
214 ULONG rcvd;
217 WaitPort(&proc->pr_MsgPort);
218 pmsg = (struct ProcMessage *) GetMsg(&proc->pr_MsgPort);
219 cb = pmsg->pm_ClassBase;
220 cl = pmsg->pm_Class;
221 obj = pmsg->pm_Object;
222 data = INST_DATA(cl, obj);
223 data->ag_Process = proc;
224 data->ag_ProcPort = port = CreateMsgPort();
225 data->ag_RexxPort = rexxport = CreateMsgPort();
226 if(rexxport != NULL)
228 LONG i=0;
229 Forbid();
232 mysprintf(cb, data->ag_RexxName, sizeof(data->ag_RexxName),
233 "%s.%ld", data->ag_ARexxPortName, ++i);
234 } while(FindPort(data->ag_RexxName) != NULL);
236 rexxport->mp_Node.ln_Name = data->ag_RexxName;
237 AddPort(rexxport);
238 Permit();
239 DB(("arexx port is %s\n", data->ag_RexxName));
242 Signal(pmsg->pm_Parent, SIGBREAKF_CTRL_F);
244 if(port != NULL)
246 procmask = (1<<port->mp_SigBit);
247 if(rexxport != NULL)
248 rexxmask = (1<<rexxport->mp_SigBit);
251 rcvd = Wait(SIGBREAKF_CTRL_F | procmask | rexxmask);
252 if(rcvd & SIGBREAKF_CTRL_F)
253 break;
255 if(rcvd & procmask)
257 struct AmigaGuideDTMsg *msg;
259 while((msg = (struct AmigaGuideDTMsg *) GetMsg(port)) != NULL)
261 switch(msg->agm_Type)
263 case AGMT_TRIGGER:
264 DoTrigger(cl, obj,
265 &msg->agm_GInfo, msg->agm_Data.Trigger.Trigger,
266 msg->agm_Data.Trigger.Data);
267 break;
268 case AGMT_LAYOUT:
270 struct DTSpecialInfo *si = (struct DTSpecialInfo *) CAST_GAD(obj)->SpecialInfo;
271 INSTDATA;
272 struct gpLayout layout;
274 layout.MethodID = DTM_ASYNCLAYOUT;
275 layout.gpl_GInfo = &msg->agm_GInfo;
276 layout.gpl_Initial = msg->agm_Data.Layout.Initial;
278 ObtainSemaphore(&si->si_Lock);
282 si->si_Flags &= ~DTSIF_NEWSIZE;
283 DoMethodA(obj, (Msg) &layout);
284 } while(si->si_Flags & DTSIF_NEWSIZE);
285 si->si_Flags &= ~DTSIF_LAYOUT;
287 if(data->ag_Flags.GotoLine)
289 /* set possible new vertical top position. */
290 SetAttrs(obj, DTA_TopVert, data->ag_ActualObject->ago_TopVert, TAG_DONE);
291 /* and also tell others... */
292 NotifyAttrs(obj, &msg->agm_GInfo, 0,
293 GA_ID, CAST_GAD(obj)->GadgetID,
294 DTA_TopVert, data->ag_ActualObject->ago_TopVert,
295 TAG_DONE);
296 data->ag_Flags.GotoLine = FALSE;
298 ReleaseSemaphore(&si->si_Lock);
300 break;
302 FreeAGMem(cl, obj, msg, sizeof(struct AmigaGuideDTMsg));
306 if(rcvd & rexxmask)
308 struct RexxMsg *rxmsg;
310 while((rxmsg = (struct RexxMsg *) GetMsg(rexxport)) != NULL)
312 if(rxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
314 DB(("command returned : %s\n",rxmsg->rm_Args[0]));
315 if(rxmsg->rm_Stdout != NULL)
316 Close(rxmsg->rm_Stdout);
318 /* delete commandstring */
319 DeleteArgstring((STRPTR)rxmsg->rm_Args[0]);
321 DeleteRexxMsg(rxmsg);
323 --data->ag_RexxOutstanding;
324 } else
326 struct DTSpecialInfo *si = CAST_GAD(obj)->SpecialInfo;
328 ObtainSemaphore(&si->si_Lock);
329 agdtm_rexxcmd(cl, obj, rxmsg);
330 ReleaseSemaphore(&si->si_Lock);
332 ReplyMsg((struct Message *) rxmsg);
336 } while(TRUE);
339 Forbid();
340 data->ag_RexxPort = NULL;
341 if(rexxport != NULL)
343 RemPort(rexxport);
345 while(data->ag_RexxOutstanding > 0)
347 struct RexxMsg *rxmsg;
349 WaitPort(rexxport);
350 while((rxmsg = (struct RexxMsg *) GetMsg(rexxport)) != NULL)
352 if(rxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
354 if(rxmsg->rm_Stdout != NULL)
355 Close(rxmsg->rm_Stdout);
357 /* delete commandstring */
358 DeleteArgstring((STRPTR)rxmsg->rm_Args[0]);
360 DeleteRexxMsg(rxmsg);
362 --data->ag_RexxOutstanding;
363 } else
365 ReplyMsg((struct Message *) rxmsg);
369 DeleteMsgPort(rexxport);
371 data->ag_ProcPort = NULL;
372 if(data->ag_Parent != NULL)
373 Signal(data->ag_Parent, SIGBREAKF_CTRL_F);
374 Permit();
375 DeleteMsgPort(port);
377 return;
379 #ifdef __AROS__
380 AROS_USERFUNC_EXIT
381 #endif
383 #ifndef __AROS__
384 #define SysBase ((struct ExecBase *)cb->cb_SysBase)
385 #endif
387 /* --------------------------- public functions --------------------------- */
389 BOOL SendAGTrigger(Class *cl, Object *obj, struct dtTrigger *dtt)
391 INSTDATA;
392 struct AmigaGuideDTMsg *msg;
394 msg = AllocAGMem(cl, obj, sizeof(struct AmigaGuideDTMsg));
395 if(msg != NULL)
397 msg->agm_Msg.mn_Node.ln_Type = NT_MESSAGE;
398 msg->agm_Type = AGMT_TRIGGER;
399 msg->agm_Data.Trigger.Trigger = dtt->dtt_Function;
400 msg->agm_Data.Trigger.Data = dtt->dtt_Data;
401 msg->agm_GInfo = *dtt->dtt_GInfo;
402 PutMsg(data->ag_ProcPort, &msg->agm_Msg);
405 return (msg != NULL) ? TRUE : FALSE;
408 BOOL SendAGLayout(Class *cl, Object *obj, struct gpLayout *gpl)
410 INSTDATA;
411 struct AmigaGuideDTMsg *msg;
413 msg = AllocAGMem(cl, obj, sizeof(struct AmigaGuideDTMsg));
414 if(msg != NULL)
416 msg->agm_Msg.mn_Node.ln_Type = NT_MESSAGE;
417 msg->agm_Type = AGMT_LAYOUT;
418 msg->agm_GInfo = *gpl->gpl_GInfo;
419 msg->agm_Data.Layout.Initial = gpl->gpl_Initial;
420 PutMsg(data->ag_ProcPort, &msg->agm_Msg);
423 return (msg != NULL) ? TRUE : FALSE;
427 struct Process *CreateAGProcess(Class *cl, Object *obj)
429 CLASSBASE;
430 struct ProcMessage msg;
431 #ifndef __AROS__
432 struct EmulLibEntry GATE_ProcFunc = {TRAP_LIB, 0, (void (*)(void)) asyncmethodfunc};
433 #endif
434 struct Process *proc;
436 msg.pm_Message.mn_Node.ln_Type = NT_MESSAGE;
437 msg.pm_ClassBase = cb;
438 msg.pm_Class = cl;
439 msg.pm_Object = obj;
440 msg.pm_Parent = FindTask(NULL);
442 #ifdef __AROS__
443 if((proc = CreateNewProcTags(NP_Entry, (IPTR)AROS_ASMSYMNAME(asyncmethodfunc),
444 NP_StackSize, 2*8192,
445 NP_Name, (ULONG) "AmigaGuide process",
446 TAG_DONE)) != NULL)
447 #else
448 if((proc = CreateNewProcTags(NP_Entry, (ULONG) &GATE_ProcFunc,
449 NP_StackSize, 2*8192,
450 NP_Name, (ULONG) "AmigaGuide process",
451 TAG_DONE)) != NULL)
452 #endif
454 PutMsg(&proc->pr_MsgPort, &msg.pm_Message);
455 Wait(SIGBREAKF_CTRL_F);
458 return proc;
461 void DeleteAGProcess(Class *cl, Object *obj)
463 INSTDATA;
465 if(data->ag_Process != NULL)
467 data->ag_Parent = FindTask(NULL);
468 /* simple handshaking using CTRL-F signal between AG and current process */
469 Signal(&data->ag_Process->pr_Task, SIGBREAKF_CTRL_F);
470 Wait(SIGBREAKF_CTRL_F);