r4493@vps: verhaegs | 2007-04-19 14:44:00 -0400
[AROS.git] / rom / workbench / handler.c
blobb62e1efddd4c5fe1c6562fecfc59192fe10a8905
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 The Workbench Handler process and associated functions.
6 */
8 #include <aros/debug.h>
10 #include <exec/ports.h>
11 #include <utility/hooks.h>
12 #include <dos/dosextens.h>
14 #include <proto/alib.h>
15 #include <proto/intuition.h>
16 #include <proto/workbench.h>
17 #include <proto/utility.h>
18 #include <proto/exec.h>
19 #include <proto/dos.h>
21 #include <workbench/workbench.h>
22 #include <workbench/startup.h>
24 #include "workbench_intern.h"
25 #include "support.h"
26 #include "support_messages.h"
27 #include "handler.h"
28 #include "handler_support.h"
30 struct HandlerContext
32 /* Ports and signals ---------------------------------------------------*/
33 struct MsgPort *hc_CommandPort; /* Command messages from the library */
34 ULONG hc_CommandSignal; /* Signal bit field for the above */
35 struct MsgPort *hc_StartupReplyPort; /* Replies to startup messages */
36 ULONG hc_StartupReplySignal; /* Signal bit field for the above */
37 struct MsgPort *hc_RelayReplyPort; /* Replies to messages sent to the workbench application */
38 ULONG hc_RelayReplySignal; /* Signal bit field for the above */
39 struct MsgPort *hc_IntuitionPort; /* Messages from Intuition */
40 ULONG hc_IntuitionSignal; /* Signal bit field for the above */
42 ULONG hc_Signals; /* Mask from all signals above */
46 /*** Prototypes *************************************************************/
47 static BOOL __Initialize_WB(struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
48 static VOID __Deinitialize_WB(struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
50 static VOID __HandleLaunch_WB(struct WBCommandMessage *message, struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
51 static VOID __HandleRelay_WB(struct WBCommandMessage *message, struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
52 static VOID __HandleIntuition_WB(struct IntuiMessage *message, struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase);
54 /*** Macros *****************************************************************/
55 #define Initialize() (__Initialize_WB(hc, WorkbenchBase))
56 #define Deinitialize() (__Deinitialize_WB(hc, WorkbenchBase))
58 #define HandleLaunch(message) (__HandleLaunch_WB((message), hc, WorkbenchBase))
59 #define HandleRelay(message) (__HandleRelay_WB((message), hc, WorkbenchBase))
60 #define HandleIntuition(message) (__HandleIntuition_WB((message), hc, WorkbenchBase))
62 /*** Entry point ************************************************************/
63 AROS_UFH3
65 LONG, WorkbenchHandler,
66 AROS_UFHA(STRPTR, args, A0),
67 AROS_UFHA(ULONG, argsLength, D0),
68 AROS_UFHA(struct ExecBase *, SysBase, A6)
71 AROS_USERFUNC_INIT
73 struct WorkbenchBase *WorkbenchBase = FindTask(NULL)->tc_UserData;
74 struct HandlerContext context = { 0 };
75 struct HandlerContext *hc = &context;
76 BOOL running = TRUE;
78 /*-- Initialization ----------------------------------------------------*/
79 if (!Initialize()) return 20; // FIXME: report error to user somehow. displaybeep? alert?
81 /*-- Event loop --------------------------------------------------------*/
82 D(bug("Workbench Handler: entering event loop\n"));
84 while (running)
86 ULONG signals = Wait(hc->hc_Signals);
88 D(bug("Workbench Handler: Got message(s)...\n"));
90 /*== Messages from the library =====================================*/
91 if (signals & hc->hc_CommandSignal)
93 struct WBCommandMessage *message;
95 D(bug("Workbench Handler: Got message(s) at command port\n"));
97 while ((message = WBCM(GetMsg(hc->hc_CommandPort))) != NULL)
99 /* Handle the message */
100 switch (message->wbcm_Type)
102 case WBCM_TYPE_LAUNCH:
103 D(bug("Workbench Handler: Got WBCM_Launch message\n"));
104 HandleLaunch(message);
105 break;
107 case WBCM_TYPE_RELAY:
108 D(bug("Workbench Handler: Got WBCM_Relay message\n"));
109 HandleRelay(message);
110 break;
113 /* Deallocate the message */
114 DestroyWBCM(message);
118 /*== Message replies from started WB programs ======================*/
119 if (signals & hc->hc_StartupReplySignal)
121 struct WBStartup *message;
123 D(bug("Workbench Handler: Got message(s) at startup reply port\n"));
125 while ((message = WBS(GetMsg(hc->hc_StartupReplyPort))) != NULL)
127 if (message->sm_Message.mn_Node.ln_Type == NT_REPLYMSG)
129 D(bug("Workbench Handler: Deallocating WBStartup message and arguments\n"));
130 DestroyWBS(message);
132 else
135 Eh, we should only get replies here. Just reply the
136 message and hope the sender will fail gracefully.
138 ReplyMsg((struct Message *) message);
143 /*== Message replies from the workbench application ================*/
144 if (signals & hc->hc_RelayReplySignal)
146 struct WBHandlerMessage *message;
148 D(bug("Workbench Handler: Got message(s) at relay reply port\n"));
150 while ((message = WBHM(GetMsg(hc->hc_RelayReplyPort))) != NULL)
152 if (message->wbhm_Message.mn_Node.ln_Type == NT_REPLYMSG)
154 D(bug("Workbench Handler: Deallocating WBHandlerMessage\n"));
155 if (message->wbhm_Type == WBHM_TYPE_HIDE)
157 struct IntWBHandlerMessage *iwbhm = (struct IntWBHandlerMessage *)message;
159 D(bug("Workbench Handler: Replying IntuiMessage because Type = "
160 "WBHM_TYPE_HIDE"));
161 ReplyMsg((struct Message *)iwbhm->iwbhm_Data.Hide.imsg);
163 DestroyWBHM(message);
165 else
167 /* FIXME: comment ;-) */
168 ReplyMsg((struct Message *) message);
174 /*== Messages from Intuition =======================================*/
175 if (signals & hc->hc_IntuitionSignal)
177 struct IntuiMessage *message;
179 D(bug("Workbench Handler: Got message(s) at intuition port\n"));
181 while ((message = (struct IntuiMessage *) GetMsg(hc->hc_IntuitionPort)))
183 HandleIntuition(message); /* takes care of replying */
188 //FIXME: shutdown not properly implemented
190 Deinitialize();
192 return 0;
194 AROS_USERFUNC_EXIT
198 static BOOL __Initialize_WB
200 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
203 /* Create message ports ------------------------------------------------*/
206 (hc->hc_StartupReplyPort = CreateMsgPort()) != NULL
207 && (hc->hc_RelayReplyPort = CreateMsgPort()) != NULL
208 && (hc->hc_IntuitionPort = CreateMsgPort()) != NULL
211 /* Store command port ----------------------------------------------*/
212 hc->hc_CommandPort = &(WorkbenchBase->wb_HandlerPort);
214 /* Calculate and store signal flags --------------------------------*/
215 hc->hc_CommandSignal = 1UL << hc->hc_CommandPort->mp_SigBit;
216 hc->hc_StartupReplySignal = 1UL << hc->hc_StartupReplyPort->mp_SigBit;
217 hc->hc_RelayReplySignal = 1UL << hc->hc_RelayReplyPort->mp_SigBit;
218 hc->hc_IntuitionSignal = 1UL << hc->hc_IntuitionPort->mp_SigBit;
220 hc->hc_Signals = hc->hc_CommandSignal
221 | hc->hc_StartupReplySignal
222 | hc->hc_RelayReplySignal
223 | hc->hc_IntuitionSignal;
225 /* We're now ready to accept messages ------------------------------*/
226 WorkbenchBase->wb_HandlerPort.mp_SigTask = FindTask(NULL);
227 WorkbenchBase->wb_HandlerPort.mp_Flags = PA_SIGNAL;
229 /* Make sure to process messages that arrived before we were ready -*/
230 Signal(FindTask(NULL), SIGBREAKF_CTRL_F);
232 /* Register ourselves with Intuition -------------------------------*/
233 AlohaWorkbench(hc->hc_IntuitionPort);
235 return TRUE;
237 else
239 Deinitialize();
241 return FALSE;
245 static VOID __Deinitialize_WB
247 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
250 /* Unregister ourselves with Intuition ---------------------------------*/
251 AlohaWorkbench(NULL);
253 /* We no longer accept messages ----------------------------------------*/
254 WorkbenchBase->wb_HandlerPort.mp_Flags = PA_IGNORE;
255 WorkbenchBase->wb_HandlerPort.mp_SigTask = NULL;
257 /* Deallocate message ports --------------------------------------------*/
258 // FIXME: should we get & deallocate all queued messages?
259 if (hc->hc_IntuitionPort != NULL) DeleteMsgPort(hc->hc_IntuitionPort);
260 if (hc->hc_RelayReplyPort != NULL) DeleteMsgPort(hc->hc_RelayReplyPort);
261 if (hc->hc_StartupReplyPort != NULL) DeleteMsgPort(hc->hc_StartupReplyPort);
264 static VOID __HandleLaunch_WB
266 struct WBCommandMessage *message,
267 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
270 struct WBStartup *startup = message->wbcm_Data.Launch.Startup;
271 STRPTR name = startup->sm_ArgList[0].wa_Name;
272 BPTR lock = startup->sm_ArgList[0].wa_Lock;
273 BPTR home;
274 BPTR cd;
275 struct Process *process;
277 D(bug("Workbench Handler: HandleLaunch: name = %s\n", name));
279 /* Change directory to where the program resides */
280 cd = CurrentDir(startup->sm_ArgList[0].wa_Lock);
282 /* Load the program from disk */
283 startup->sm_Segment = LoadSeg(name);
284 if (startup->sm_Segment == NULL) goto error;
286 /* Duplicate lock for NP_HomeDir */
287 home = DupLock(lock);
288 if (home == NULL) goto error;
290 /* Launch the program */
291 process = CreateNewProcTags
293 NP_Seglist, (IPTR) startup->sm_Segment,
294 NP_Name, (IPTR) name,
295 NP_HomeDir, (IPTR) home,
296 NP_StackSize, WorkbenchBase->wb_DefaultStackSize, /* FIXME: should be read from icon */
297 TAG_DONE
300 if (process != NULL)
302 D(bug("Workbench Handler: HandleLaunch: Process created successfully\n"));
304 /* Setup startup message */
305 startup->sm_Process = &process->pr_MsgPort;
306 startup->sm_Message.mn_ReplyPort = hc->hc_StartupReplyPort;
308 /* Send startup message to program */
309 PutMsg(startup->sm_Process, (struct Message *) startup);
312 goto done;
314 error:
315 //FIXME: report error somehow?
316 D(bug("Workbench Handler: HandleLaunch: Failed to launch program. Deallocating resources.\n"));
317 if (startup->sm_Segment != NULL) UnLoadSeg(startup->sm_Segment);
318 DestroyWBS(startup);
320 done:
321 /* Restore current directory */
322 CurrentDir(cd);
325 static VOID __HandleRelay_WB
327 struct WBCommandMessage *message,
328 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
331 struct WBHandlerMessage *relaymsg = message->wbcm_Data.Relay.Message;
333 D(bug("Workbench Handler: HandleRelay: Relaying message to workbench application\n"));
334 D(bug("Workbench Handler: HandleRelay: destination port %p\n", WorkbenchBase->wb_WorkbenchPort));
335 relaymsg->wbhm_Message.mn_ReplyPort = hc->hc_RelayReplyPort;
336 PutMsg(WorkbenchBase->wb_WorkbenchPort, (struct Message *) relaymsg);
339 static void __HandleIntuition_WB
341 struct IntuiMessage *message,
342 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
345 struct IntWBHandlerMessage *iwbhm;
347 if (message->Class == IDCMP_WBENCHMESSAGE)
349 switch (message->Code)
351 case WBENCHOPEN:
352 iwbhm = CreateIWBHM(WBHM_TYPE_SHOW, hc->hc_RelayReplyPort);
353 break;
354 case WBENCHCLOSE:
355 iwbhm = CreateIWBHM(WBHM_TYPE_HIDE, hc->hc_RelayReplyPort);
356 iwbhm->iwbhm_Data.Hide.imsg = message;
357 break;
358 default:
359 iwbhm = NULL;
360 break;
363 if ((iwbhm != NULL) && (WorkbenchBase->wb_WorkbenchPort != NULL))
365 PutMsg(WorkbenchBase->wb_WorkbenchPort, (struct Message *)iwbhm);
367 /* Don't reply immediately if we're asked to close the WB,
368 we'll do it when handling replied message, so that the WB
369 will have a chance to close its windows. */
370 if (message->Code == WBENCHCLOSE)
371 return;
375 ReplyMsg((struct Message *) message);