Fixed warnings.
[cake.git] / rom / workbench / handler.c
blob563284a1ca1aee76997f543a658a493a7429affc
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 The Workbench Handler process and associated functions.
6 */
8 #define DEBUG 0
9 #include <aros/debug.h>
11 #include <exec/ports.h>
12 #include <utility/hooks.h>
13 #include <dos/dosextens.h>
15 #include <proto/alib.h>
16 #include <proto/intuition.h>
17 #include <proto/workbench.h>
18 #include <proto/utility.h>
19 #include <proto/exec.h>
20 #include <proto/dos.h>
22 #include <workbench/workbench.h>
23 #include <workbench/startup.h>
25 #include "workbench_intern.h"
26 #include "support.h"
27 #include "support_messages.h"
28 #include "handler.h"
29 #include "handler_support.h"
31 struct HandlerContext
33 /* Ports and signals ---------------------------------------------------*/
34 struct MsgPort *hc_CommandPort; /* Command messages from the library */
35 ULONG hc_CommandSignal; /* Signal bit field for the above */
36 struct MsgPort *hc_StartupReplyPort; /* Replies to startup messages */
37 ULONG hc_StartupReplySignal; /* Signal bit field for the above */
38 struct MsgPort *hc_RelayReplyPort; /* Replies to messages sent to the workbench application */
39 ULONG hc_RelayReplySignal; /* Signal bit field for the above */
40 struct MsgPort *hc_IntuitionPort; /* Messages from Intuition */
41 ULONG hc_IntuitionSignal; /* Signal bit field for the above */
43 ULONG hc_Signals; /* Mask from all signals above */
47 /*** Prototypes *************************************************************/
48 static BOOL __Initialize_WB(struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
49 static VOID __Deinitialize_WB(struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
51 static VOID __HandleLaunch_WB(struct WBCommandMessage *message, struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
52 static VOID __HandleRelay_WB(struct WBCommandMessage *message, struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
53 static VOID __HandleIntuition_WB(struct IntuiMessage *message, struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
55 /*** Macros *****************************************************************/
56 #define Initialize() (__Initialize_WB(hc, WorkbenchBase))
57 #define Deinitialize() (__Deinitialize_WB(hc, WorkbenchBase))
59 #define HandleLaunch(message) (__HandleLaunch_WB((message), hc, WorkbenchBase))
60 #define HandleRelay(message) (__HandleRelay_WB((message), hc, WorkbenchBase))
61 #define HandleIntuition(message) (__HandleIntuition_WB((message), hc, WorkbenchBase))
63 /*** Entry point ************************************************************/
64 AROS_UFH3
66 LONG, WorkbenchHandler,
67 AROS_UFHA(STRPTR, args, A0),
68 AROS_UFHA(ULONG, argsLength, D0),
69 AROS_UFHA(struct ExecBase *, SysBase, A6)
72 AROS_USERFUNC_INIT
74 struct WorkbenchBase *WorkbenchBase = FindTask(NULL)->tc_UserData;
75 struct HandlerContext context = { 0 };
76 struct HandlerContext *hc = &context;
77 BOOL running = TRUE;
79 /*-- Initialization ----------------------------------------------------*/
80 if (!Initialize()) return 20; // FIXME: report error to user somehow. displaybeep? alert?
82 /*-- Event loop --------------------------------------------------------*/
83 D(bug("[WBLIB] WorkbenchHandler: entering event loop\n"));
85 while (running)
87 ULONG signals = Wait(hc->hc_Signals);
89 D(bug("[WBLIB] WorkbenchHandler: Got message(s)...\n"));
91 /*== Messages from the library =====================================*/
92 if (signals & hc->hc_CommandSignal)
94 struct WBCommandMessage *message;
96 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at command port\n"));
98 while ((message = WBCM(GetMsg(hc->hc_CommandPort))) != NULL)
100 /* Handle the message */
101 switch (message->wbcm_Type)
103 case WBCM_TYPE_LAUNCH:
104 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Launch message\n"));
105 HandleLaunch(message);
106 break;
108 case WBCM_TYPE_RELAY:
109 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Relay message\n"));
110 HandleRelay(message);
111 break;
114 /* Deallocate the message */
115 DestroyWBCM(message);
119 /*== Message replies from started WB programs ======================*/
120 if (signals & hc->hc_StartupReplySignal)
122 struct WBStartup *message;
124 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at startup reply port\n"));
126 while ((message = WBS(GetMsg(hc->hc_StartupReplyPort))) != NULL)
128 if (message->sm_Message.mn_Node.ln_Type == NT_REPLYMSG)
130 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBStartup message and arguments\n"));
131 DestroyWBS(message);
133 else
136 Eh, we should only get replies here. Just reply the
137 message and hope the sender will fail gracefully.
139 ReplyMsg((struct Message *) message);
144 /*== Message replies from the workbench application ================*/
145 if (signals & hc->hc_RelayReplySignal)
147 struct WBHandlerMessage *message;
149 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at relay reply port\n"));
151 while ((message = WBHM(GetMsg(hc->hc_RelayReplyPort))) != NULL)
153 if (message->wbhm_Message.mn_Node.ln_Type == NT_REPLYMSG)
155 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBHandlerMessage\n"));
156 if (message->wbhm_Type == WBHM_TYPE_HIDE)
158 struct IntWBHandlerMessage *iwbhm = (struct IntWBHandlerMessage *)message;
160 D(bug("[WBLIB] WorkbenchHandler: Replying IntuiMessage because Type = "
161 "WBHM_TYPE_HIDE\n"));
162 ReplyMsg((struct Message *)iwbhm->iwbhm_Data.Hide.imsg);
164 DestroyWBHM(message);
166 else
168 /* FIXME: comment ;-) */
169 ReplyMsg((struct Message *) message);
175 /*== Messages from Intuition =======================================*/
176 if (signals & hc->hc_IntuitionSignal)
178 struct IntuiMessage *message;
180 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at intuition port\n"));
182 while ((message = (struct IntuiMessage *) GetMsg(hc->hc_IntuitionPort)))
184 HandleIntuition(message); /* takes care of replying */
189 //FIXME: shutdown not properly implemented
191 Deinitialize();
193 return 0;
195 AROS_USERFUNC_EXIT
199 static BOOL __Initialize_WB
201 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
204 /* Create message ports ------------------------------------------------*/
207 (hc->hc_StartupReplyPort = CreateMsgPort()) != NULL
208 && (hc->hc_RelayReplyPort = CreateMsgPort()) != NULL
209 && (hc->hc_IntuitionPort = CreateMsgPort()) != NULL
212 /* Store command port ----------------------------------------------*/
213 hc->hc_CommandPort = &(WorkbenchBase->wb_HandlerPort);
215 /* Calculate and store signal flags --------------------------------*/
216 hc->hc_CommandSignal = 1UL << hc->hc_CommandPort->mp_SigBit;
217 hc->hc_StartupReplySignal = 1UL << hc->hc_StartupReplyPort->mp_SigBit;
218 hc->hc_RelayReplySignal = 1UL << hc->hc_RelayReplyPort->mp_SigBit;
219 hc->hc_IntuitionSignal = 1UL << hc->hc_IntuitionPort->mp_SigBit;
221 hc->hc_Signals = hc->hc_CommandSignal
222 | hc->hc_StartupReplySignal
223 | hc->hc_RelayReplySignal
224 | hc->hc_IntuitionSignal;
226 /* We're now ready to accept messages ------------------------------*/
227 WorkbenchBase->wb_HandlerPort.mp_SigTask = FindTask(NULL);
228 WorkbenchBase->wb_HandlerPort.mp_Flags = PA_SIGNAL;
230 /* Make sure to process messages that arrived before we were ready -*/
231 Signal(FindTask(NULL), SIGBREAKF_CTRL_F);
233 /* Register ourselves with Intuition -------------------------------*/
234 AlohaWorkbench(hc->hc_IntuitionPort);
236 return TRUE;
238 else
240 Deinitialize();
242 return FALSE;
246 static VOID __Deinitialize_WB
248 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
251 /* Unregister ourselves with Intuition ---------------------------------*/
252 AlohaWorkbench(NULL);
254 /* We no longer accept messages ----------------------------------------*/
255 WorkbenchBase->wb_HandlerPort.mp_Flags = PA_IGNORE;
256 WorkbenchBase->wb_HandlerPort.mp_SigTask = NULL;
258 /* Deallocate message ports --------------------------------------------*/
259 // FIXME: should we get & deallocate all queued messages?
260 if (hc->hc_IntuitionPort != NULL) DeleteMsgPort(hc->hc_IntuitionPort);
261 if (hc->hc_RelayReplyPort != NULL) DeleteMsgPort(hc->hc_RelayReplyPort);
262 if (hc->hc_StartupReplyPort != NULL) DeleteMsgPort(hc->hc_StartupReplyPort);
265 static VOID __HandleLaunch_WB
267 struct WBCommandMessage *message,
268 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
271 struct WBStartup *startup = message->wbcm_Data.Launch.Startup;
272 struct TagItem *msgTags = (struct TagItem *)message->wbcm_Tags;
273 struct TagItem *foundTag = NULL;
275 STRPTR name = startup->sm_ArgList[0].wa_Name;
276 BPTR lock = startup->sm_ArgList[0].wa_Lock;
277 BPTR home;
278 BPTR cd;
279 IPTR stacksize = WorkbenchBase->wb_DefaultStackSize;
280 struct Process *process;
282 D(bug("[WBLIB] __HandleLaunch_WB('%s')\n", name));
284 if (msgTags)
286 if ((foundTag = FindTagItem(NP_StackSize, msgTags)) != NULL)
287 stacksize = foundTag->ti_Data;
288 FreeTagItems(msgTags);
291 /* Change directory to where the program resides */
292 cd = CurrentDir(startup->sm_ArgList[0].wa_Lock);
294 /* Load the program from disk */
295 startup->sm_Segment = LoadSeg(name);
296 if (startup->sm_Segment == NULL) goto error;
298 /* Duplicate lock for NP_HomeDir */
299 home = DupLock(lock);
300 if (home == NULL) goto error;
302 const struct TagItem tags[]=
304 {NP_Seglist, (IPTR)startup->sm_Segment },
305 {NP_Name, (IPTR)name },
306 {NP_HomeDir, (IPTR)home },
307 {NP_StackSize, stacksize },
308 {TAG_DONE, 0 }
311 D(bug("[WBLIB] __HandleLaunch_WB: Starting '%s' with %d stack\n", tags[1].ti_Data, tags[3].ti_Data));
313 /* Launch the program */
314 process = CreateNewProc(tags);
316 if (process != NULL)
318 D(bug("[WBLIB] __HandleLaunch_WB: Process created successfully @ %p\n", process));
320 /* Setup startup message */
321 startup->sm_Process = &process->pr_MsgPort;
322 startup->sm_Message.mn_ReplyPort = hc->hc_StartupReplyPort;
324 /* Send startup message to program */
325 PutMsg(startup->sm_Process, (struct Message *) startup);
328 goto done;
330 error:
331 //FIXME: report error somehow?
332 D(bug("[WBLIB] __HandleLaunch_WB: Failed to launch program. Deallocating resources.\n"));
333 if (startup->sm_Segment != NULL) UnLoadSeg(startup->sm_Segment);
334 DestroyWBS(startup);
336 done:
337 /* Restore current directory */
338 CurrentDir(cd);
341 static VOID __HandleRelay_WB
343 struct WBCommandMessage *message,
344 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
347 struct WBHandlerMessage *relaymsg = message->wbcm_Data.Relay.Message;
349 D(bug("[WBLIB] __HandleRelay_WB: Relaying message to workbench application\n"));
350 D(bug("[WBLIB] __HandleRelay_WB: destination port %p\n", WorkbenchBase->wb_WorkbenchPort));
351 relaymsg->wbhm_Message.mn_ReplyPort = hc->hc_RelayReplyPort;
352 PutMsg(WorkbenchBase->wb_WorkbenchPort, (struct Message *) relaymsg);
355 static void __HandleIntuition_WB
357 struct IntuiMessage *message,
358 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
361 struct IntWBHandlerMessage *iwbhm;
363 if (message->Class == IDCMP_WBENCHMESSAGE)
365 switch (message->Code)
367 case WBENCHOPEN:
368 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHOPEN\n"));
369 iwbhm = CreateIWBHM(WBHM_TYPE_SHOW, hc->hc_RelayReplyPort);
370 break;
371 case WBENCHCLOSE:
372 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHCLOSE\n"));
373 iwbhm = CreateIWBHM(WBHM_TYPE_HIDE, hc->hc_RelayReplyPort);
374 iwbhm->iwbhm_Data.Hide.imsg = message;
375 break;
376 default:
377 iwbhm = NULL;
378 break;
381 if ((iwbhm != NULL) && (WorkbenchBase->wb_WorkbenchPort != NULL))
383 D(bug("[WBLIB] __HandleIntuition_WB: Forwarding message to Workbench port @ %p\n", WorkbenchBase->wb_WorkbenchPort));
384 PutMsg(WorkbenchBase->wb_WorkbenchPort, (struct Message *)iwbhm);
386 /* Don't reply immediately if we're asked to close the WB,
387 we'll do it when handling replied message, so that the WB
388 will have a chance to close its windows. */
389 if (message->Code == WBENCHCLOSE)
390 return;
394 ReplyMsg((struct Message *) message);