64-bit fix. Changed the user-supplied IDs used with
[AROS.git] / workbench / libs / workbench / handler.c
blob68893c14c2c8ea9a809ec62af55c65d0c5157bec
1 /*
2 Copyright © 1995-2010, 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 SetConsoleTask(NULL);
80 /*-- Initialization ----------------------------------------------------*/
81 if (!Initialize()) return 20; // FIXME: report error to user somehow. displaybeep? alert?
83 /*-- Event loop --------------------------------------------------------*/
84 D(bug("[WBLIB] WorkbenchHandler: entering event loop\n"));
86 while (running)
88 ULONG signals = Wait(hc->hc_Signals);
90 D(bug("[WBLIB] WorkbenchHandler: Got message(s)...\n"));
92 /*== Messages from the library =====================================*/
93 if (signals & hc->hc_CommandSignal)
95 struct WBCommandMessage *message;
97 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at command port\n"));
99 while ((message = WBCM(GetMsg(hc->hc_CommandPort))) != NULL)
101 /* Handle the message */
102 switch (message->wbcm_Type)
104 case WBCM_TYPE_LAUNCH:
105 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Launch message\n"));
106 HandleLaunch(message);
107 break;
109 case WBCM_TYPE_RELAY:
110 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Relay message\n"));
111 HandleRelay(message);
112 break;
115 /* Deallocate the message */
116 DestroyWBCM(message);
120 /*== Message replies from started WB programs ======================*/
121 if (signals & hc->hc_StartupReplySignal)
123 struct WBStartup *message;
125 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at startup reply port\n"));
127 while ((message = WBS(GetMsg(hc->hc_StartupReplyPort))) != NULL)
129 if (message->sm_Message.mn_Node.ln_Type == NT_REPLYMSG)
131 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBStartup message and arguments\n"));
132 DestroyWBS(message);
134 else
137 Eh, we should only get replies here. Just reply the
138 message and hope the sender will fail gracefully.
140 ReplyMsg((struct Message *) message);
145 /*== Message replies from the workbench application ================*/
146 if (signals & hc->hc_RelayReplySignal)
148 struct WBHandlerMessage *message;
150 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at relay reply port\n"));
152 while ((message = WBHM(GetMsg(hc->hc_RelayReplyPort))) != NULL)
154 if (message->wbhm_Message.mn_Node.ln_Type == NT_REPLYMSG)
156 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBHandlerMessage\n"));
157 if (message->wbhm_Type == WBHM_TYPE_HIDE)
159 struct IntWBHandlerMessage *iwbhm = (struct IntWBHandlerMessage *)message;
161 D(bug("[WBLIB] WorkbenchHandler: Replying IntuiMessage because Type = "
162 "WBHM_TYPE_HIDE\n"));
163 ReplyMsg((struct Message *)iwbhm->iwbhm_Data.Hide.imsg);
165 DestroyWBHM(message);
167 else
169 /* FIXME: comment ;-) */
170 ReplyMsg((struct Message *) message);
176 /*== Messages from Intuition =======================================*/
177 if (signals & hc->hc_IntuitionSignal)
179 struct IntuiMessage *message;
181 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at intuition port\n"));
183 while ((message = (struct IntuiMessage *) GetMsg(hc->hc_IntuitionPort)))
185 HandleIntuition(message); /* takes care of replying */
190 //FIXME: shutdown not properly implemented
192 Deinitialize();
194 return 0;
196 AROS_USERFUNC_EXIT
200 static BOOL __Initialize_WB
202 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
205 /* Create message ports ------------------------------------------------*/
208 (hc->hc_StartupReplyPort = CreateMsgPort()) != NULL
209 && (hc->hc_RelayReplyPort = CreateMsgPort()) != NULL
210 && (hc->hc_IntuitionPort = CreateMsgPort()) != NULL
213 /* Store command port ----------------------------------------------*/
214 hc->hc_CommandPort = &(WorkbenchBase->wb_HandlerPort);
216 /* Calculate and store signal flags --------------------------------*/
217 hc->hc_CommandSignal = 1UL << hc->hc_CommandPort->mp_SigBit;
218 hc->hc_StartupReplySignal = 1UL << hc->hc_StartupReplyPort->mp_SigBit;
219 hc->hc_RelayReplySignal = 1UL << hc->hc_RelayReplyPort->mp_SigBit;
220 hc->hc_IntuitionSignal = 1UL << hc->hc_IntuitionPort->mp_SigBit;
222 hc->hc_Signals = hc->hc_CommandSignal
223 | hc->hc_StartupReplySignal
224 | hc->hc_RelayReplySignal
225 | hc->hc_IntuitionSignal;
227 /* We're now ready to accept messages ------------------------------*/
228 WorkbenchBase->wb_HandlerPort.mp_SigTask = FindTask(NULL);
229 WorkbenchBase->wb_HandlerPort.mp_Flags = PA_SIGNAL;
231 /* Make sure to process messages that arrived before we were ready -*/
232 Signal(FindTask(NULL), SIGBREAKF_CTRL_F);
234 /* Register ourselves with Intuition -------------------------------*/
235 AlohaWorkbench(hc->hc_IntuitionPort);
237 return TRUE;
239 else
241 Deinitialize();
243 return FALSE;
247 static VOID __Deinitialize_WB
249 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
252 /* Unregister ourselves with Intuition ---------------------------------*/
253 AlohaWorkbench(NULL);
255 /* We no longer accept messages ----------------------------------------*/
256 WorkbenchBase->wb_HandlerPort.mp_Flags = PA_IGNORE;
257 WorkbenchBase->wb_HandlerPort.mp_SigTask = NULL;
259 /* Deallocate message ports --------------------------------------------*/
260 // FIXME: should we get & deallocate all queued messages?
261 if (hc->hc_IntuitionPort != NULL) DeleteMsgPort(hc->hc_IntuitionPort);
262 if (hc->hc_RelayReplyPort != NULL) DeleteMsgPort(hc->hc_RelayReplyPort);
263 if (hc->hc_StartupReplyPort != NULL) DeleteMsgPort(hc->hc_StartupReplyPort);
266 static VOID __HandleLaunch_WB
268 struct WBCommandMessage *message,
269 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
272 struct WBStartup *startup = message->wbcm_Data.Launch.Startup;
273 struct TagItem *msgTags = (struct TagItem *)message->wbcm_Tags;
274 struct TagItem *foundTag = NULL;
276 STRPTR name = startup->sm_ArgList[0].wa_Name;
277 BPTR lock = startup->sm_ArgList[0].wa_Lock;
278 BPTR home;
279 BPTR cd;
280 IPTR stacksize = WorkbenchBase->wb_DefaultStackSize;
281 LONG priority = 0;
282 struct Process *process;
284 D(bug("[WBLIB] __HandleLaunch_WB('%s')\n", name));
286 if (msgTags)
288 foundTag = FindTagItem(NP_StackSize, msgTags);
289 if (foundTag != NULL)
291 stacksize = foundTag->ti_Data;
294 foundTag = FindTagItem(NP_Priority, msgTags);
295 if (foundTag != NULL)
297 priority = foundTag->ti_Data;
300 FreeTagItems(msgTags);
303 /* Change directory to where the program resides */
304 cd = CurrentDir(startup->sm_ArgList[0].wa_Lock);
306 /* Load the program from disk */
307 if (startup->sm_Segment == BNULL)
308 startup->sm_Segment = LoadSeg(name);
309 if (startup->sm_Segment == BNULL) goto error;
311 /* Duplicate lock for NP_HomeDir */
312 home = DupLock(lock);
313 if (home == BNULL) goto error;
315 const struct TagItem tags[]=
317 {NP_Seglist, (IPTR)startup->sm_Segment },
318 {NP_Name, (IPTR)name },
319 {NP_HomeDir, (IPTR)home },
320 {NP_StackSize, stacksize },
321 {NP_Priority, priority },
322 {NP_Input, (IPTR)BNULL },
323 {NP_Output, (IPTR)BNULL },
324 {NP_CurrentDir, (IPTR)BNULL },
325 {TAG_DONE, 0 }
328 D(bug("[WBLIB] __HandleLaunch_WB: Starting '%s' with %d stack\n", tags[1].ti_Data, tags[3].ti_Data));
330 /* Launch the program */
331 process = CreateNewProc(tags);
333 if (process != NULL)
335 D(bug("[WBLIB] __HandleLaunch_WB: Process created successfully @ %p\n", process));
337 /* Setup startup message */
338 startup->sm_Process = &process->pr_MsgPort;
339 startup->sm_Message.mn_ReplyPort = hc->hc_StartupReplyPort;
341 /* Send startup message to program */
342 PutMsg(startup->sm_Process, (struct Message *) startup);
345 goto done;
347 error:
348 //FIXME: report error somehow?
349 D(bug("[WBLIB] __HandleLaunch_WB: Failed to launch program. Deallocating resources.\n"));
350 if (startup->sm_Segment != BNULL) UnLoadSeg(startup->sm_Segment);
351 DestroyWBS(startup);
353 done:
354 /* Restore current directory */
355 CurrentDir(cd);
358 static VOID __HandleRelay_WB
360 struct WBCommandMessage *message,
361 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
364 struct WBHandlerMessage *relaymsg = message->wbcm_Data.Relay.Message;
366 D(bug("[WBLIB] __HandleRelay_WB: Relaying message to workbench application\n"));
367 D(bug("[WBLIB] __HandleRelay_WB: destination port %p\n", WorkbenchBase->wb_WorkbenchPort));
368 relaymsg->wbhm_Message.mn_ReplyPort = hc->hc_RelayReplyPort;
369 PutMsg(WorkbenchBase->wb_WorkbenchPort, (struct Message *) relaymsg);
372 static void __HandleIntuition_WB
374 struct IntuiMessage *message,
375 struct HandlerContext *hc, struct WorkbenchBase *WorkbenchBase
378 struct IntWBHandlerMessage *iwbhm;
380 if (message->Class == IDCMP_WBENCHMESSAGE)
382 switch (message->Code)
384 case WBENCHOPEN:
385 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHOPEN\n"));
386 iwbhm = CreateIWBHM(WBHM_TYPE_SHOW, hc->hc_RelayReplyPort);
387 break;
388 case WBENCHCLOSE:
389 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHCLOSE\n"));
390 iwbhm = CreateIWBHM(WBHM_TYPE_HIDE, hc->hc_RelayReplyPort);
391 iwbhm->iwbhm_Data.Hide.imsg = message;
392 break;
393 default:
394 iwbhm = NULL;
395 break;
398 if ((iwbhm != NULL) && (WorkbenchBase->wb_WorkbenchPort != NULL))
400 D(bug("[WBLIB] __HandleIntuition_WB: Forwarding message to Workbench port @ %p\n", WorkbenchBase->wb_WorkbenchPort));
401 PutMsg(WorkbenchBase->wb_WorkbenchPort, (struct Message *)iwbhm);
403 /* Don't reply immediately if we're asked to close the WB,
404 we'll do it when handling replied message, so that the WB
405 will have a chance to close its windows. */
406 if (message->Code == WBENCHCLOSE)
407 return;
411 ReplyMsg((struct Message *) message);