2 ** $PROJECT: amigaguide.datatype
4 ** $VER: process.c 50.1 (14.06.03)
6 ** $AUTHOR: Stefan Ruppert <stefan@ruppert-it.de>
10 /* ------------------------------- includes ------------------------------- */
12 #include "classbase.h"
14 #include <dos/dostags.h>
16 /* ---------------------------- arexx autodoc ----------------------------- */
18 /****** amigaguide.datatype/--arexx-- ****************************************
21 ARexx interface -- amigaguide.datatype ARexx commands
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".
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
44 HELP -- Go to the help node in the database. Same as pressing the
47 INDEX -- Go to the index node in the database. Same as pressing the
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.
69 ******************************************************************************
73 /* -------------------------- AG privat message --------------------------- */
75 struct AmigaGuideDTMsg
77 struct Message agm_Msg
;
93 struct GadgetInfo agm_GInfo
;
96 /* --------------------------- static functions --------------------------- */
99 void DoRexxTrigger(Class
*cl
, Object
*obj
, ULONG function
, APTR trigger_data
)
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
);
117 ULONG
agdtm_rexxcmd(Class
*cl
, Object
*obj
, struct RexxMsg
*msg
)
123 DB(("command received : %s\n",msg
->rm_Args
[0]));
125 cmd
= CopyString(cl
, obj
, (STRPTR
)msg
->rm_Args
[0]);
131 while(*ptr
!= '\0' && *ptr
!= ' ' && *ptr
!= '\t')
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"))
166 DoRexxTrigger(cl
, obj
, STM_COMMAND
| STMD_STRPTR
, cmd
);
167 } else if(!Stricmp(cmd
, "GETNODECOUNT"))
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"))
177 FreeAGVec(cl
, obj
, cmd
);
185 struct Message pm_Message
;
186 struct ClassBase
*pm_ClassBase
;
189 struct Task
*pm_Parent
;
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
))
202 RegCall GetA4
void asyncmethodfunc(void)
204 struct Library
*SysBase
= *((struct Library
**) 4L);
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
;
213 ULONG procmask
, rexxmask
;
217 WaitPort(&proc
->pr_MsgPort
);
218 pmsg
= (struct ProcMessage
*) GetMsg(&proc
->pr_MsgPort
);
219 cb
= pmsg
->pm_ClassBase
;
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();
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
;
239 DB(("arexx port is %s\n", data
->ag_RexxName
));
242 Signal(pmsg
->pm_Parent
, SIGBREAKF_CTRL_F
);
246 procmask
= (1<<port
->mp_SigBit
);
248 rexxmask
= (1<<rexxport
->mp_SigBit
);
251 rcvd
= Wait(SIGBREAKF_CTRL_F
| procmask
| rexxmask
);
252 if(rcvd
& SIGBREAKF_CTRL_F
)
257 struct AmigaGuideDTMsg
*msg
;
259 while((msg
= (struct AmigaGuideDTMsg
*) GetMsg(port
)) != NULL
)
261 switch(msg
->agm_Type
)
265 &msg
->agm_GInfo
, msg
->agm_Data
.Trigger
.Trigger
,
266 msg
->agm_Data
.Trigger
.Data
);
270 struct DTSpecialInfo
*si
= (struct DTSpecialInfo
*) CAST_GAD(obj
)->SpecialInfo
;
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
,
296 data
->ag_Flags
.GotoLine
= FALSE
;
298 ReleaseSemaphore(&si
->si_Lock
);
302 FreeAGMem(cl
, obj
, msg
, sizeof(struct AmigaGuideDTMsg
));
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
;
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
);
340 data
->ag_RexxPort
= NULL
;
345 while(data
->ag_RexxOutstanding
> 0)
347 struct RexxMsg
*rxmsg
;
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
;
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
);
384 #define SysBase ((struct ExecBase *)cb->cb_SysBase)
387 /* --------------------------- public functions --------------------------- */
389 BOOL
SendAGTrigger(Class
*cl
, Object
*obj
, struct dtTrigger
*dtt
)
392 struct AmigaGuideDTMsg
*msg
;
394 msg
= AllocAGMem(cl
, obj
, sizeof(struct AmigaGuideDTMsg
));
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
)
411 struct AmigaGuideDTMsg
*msg
;
413 msg
= AllocAGMem(cl
, obj
, sizeof(struct AmigaGuideDTMsg
));
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
)
430 struct ProcMessage msg
;
432 struct EmulLibEntry GATE_ProcFunc
= {TRAP_LIB
, 0, (void (*)(void)) asyncmethodfunc
};
434 struct Process
*proc
;
436 msg
.pm_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
437 msg
.pm_ClassBase
= cb
;
440 msg
.pm_Parent
= FindTask(NULL
);
443 if((proc
= CreateNewProcTags(NP_Entry
, (IPTR
)AROS_ASMSYMNAME(asyncmethodfunc
),
444 NP_StackSize
, 2*8192,
445 NP_Name
, (ULONG
) "AmigaGuide process",
448 if((proc
= CreateNewProcTags(NP_Entry
, (ULONG
) &GATE_ProcFunc
,
449 NP_StackSize
, 2*8192,
450 NP_Name
, (ULONG
) "AmigaGuide process",
454 PutMsg(&proc
->pr_MsgPort
, &msg
.pm_Message
);
455 Wait(SIGBREAKF_CTRL_F
);
461 void DeleteAGProcess(Class
*cl
, Object
*obj
)
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
);