Bus reset timeouts are now implemented with more coarse-grained sleeps
[tangerine.git] / rom / workbench / openworkbenchobjecta.c
blobb9569c2a8fd289178fa9fd9bada9e67ecee61870
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Open a drawer or launch a program.
6 */
7 #define DEBUG 0
8 #include <aros/debug.h>
10 #include <exec/types.h>
11 #include <exec/ports.h>
12 #include <utility/tagitem.h>
13 #include <intuition/intuition.h>
14 #include <workbench/workbench.h>
15 #include <proto/utility.h>
16 #include <proto/dos.h>
18 #include <string.h>
20 #include "workbench_intern.h"
21 #include "support.h"
22 #include "support_messages.h"
23 #include "handler.h"
24 #include "handler_support.h"
26 /*** Prototypes *************************************************************/
27 BOOL __CLI_LaunchProgram(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
28 STRPTR __CLI_BuildCommandLine(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
29 BOOL __WB_LaunchProgram(BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
30 BOOL __WB_BuildArguments(struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
32 /*** Macros *****************************************************************/
33 #define CLI_LaunchProgram(name, tags) (__CLI_LaunchProgram((name), (tags), WorkbenchBase))
34 #define CLI_BuildCommandLine(name, tags) (__CLI_BuildCommandLine((name), (tags), WorkbenchBase))
35 #define WB_LaunchProgram(lock, name, tags) (__WB_LaunchProgram((lock), (name), (tags), WorkbenchBase))
36 #define WB_BuildArguments(startup, lock, name, tags) (__WB_BuildArguments((startup), (lock), (name), (tags), WorkbenchBase))
38 /*****************************************************************************
40 NAME */
42 #include <proto/workbench.h>
44 AROS_LH2(BOOL, OpenWorkbenchObjectA,
46 /* SYNOPSIS */
47 AROS_LHA(STRPTR, name, A0),
48 AROS_LHA(struct TagItem *, tags, A1),
50 /* LOCATION */
51 struct WorkbenchBase *, WorkbenchBase, 16, Workbench)
53 /* FUNCTION
55 INPUTS
57 RESULT
59 NOTES
61 EXAMPLE
63 BUGS
65 SEE ALSO
67 INTERNALS
69 ******************************************************************************/
71 AROS_LIBFUNC_INIT
73 BOOL success = FALSE;
74 LONG isDefaultIcon = 42;
76 struct DiskObject *icon = GetIconTags
78 name,
79 ICONGETA_FailIfUnavailable, FALSE,
80 ICONGETA_IsDefaultIcon, (IPTR) &isDefaultIcon,
81 TAG_DONE
84 ASSERT_VALID_PTR(name);
85 ASSERT_VALID_PTR_OR_NULL(tags);
87 D(bug("OpenWorkbenchObject: name = %s\n", name));
88 D(bug("OpenWorkbenchObject: isDefaultIcon = %ld\n", isDefaultIcon));
90 if (icon != NULL)
92 switch (icon->do_Type)
94 case WBDISK:
95 case WBDRAWER:
96 case WBGARBAGE:
98 Since it's a directory or volume, tell the Workbench
99 Application to open the corresponding drawer.
102 D(bug("OpenWorkbenchObject: it's a DISK, DRAWER or GARBAGE\n"));
105 struct WBCommandMessage *wbcm = NULL;
106 struct WBHandlerMessage *wbhm = NULL;
107 CONST_STRPTR namecopy = NULL;
111 (wbcm = CreateWBCM(WBCM_TYPE_RELAY)) != NULL
112 && (wbhm = CreateWBHM(WBHM_TYPE_OPEN)) != NULL
113 && (namecopy = StrDup(name)) != NULL
117 wbhm->wbhm_Data.Open.Name = namecopy;
118 wbcm->wbcm_Data.Relay.Message = wbhm;
120 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) wbcm);
122 else
124 FreeVec((STRPTR)namecopy);
125 DestroyWBHM(wbhm);
126 DestroyWBCM(wbcm);
130 break;
132 case WBTOOL:
134 It's an executable. Before I launch it, I must check
135 whether it is a Workbench program or a CLI program.
138 D(bug("OpenWorkbenchObject: it's a TOOL\n"));
142 !isDefaultIcon
143 && FindToolType(icon->do_ToolTypes, "CLI") == NULL
146 /* It's a Workbench program */
147 BPTR lock = Lock(name, ACCESS_READ);
149 D(bug("OpenWorkbenchObject: it's a WB program\n"));
151 if (lock != NULL)
153 BPTR parent = ParentDir(lock);
155 if (parent != NULL)
157 success = WB_LaunchProgram
159 parent, FilePart(name), tags
162 if (!success)
165 Fallback to launching it as a CLI program.
166 Most likely it will also fail, but we
167 might get lucky.
169 success = CLI_LaunchProgram(name, tags);
172 UnLock(parent);
175 UnLock(lock);
178 else
180 /* It's a CLI program */
182 D(bug("OpenWorkbenchObject: it's a CLI program\n"));
184 success = CLI_LaunchProgram(name, tags);
186 break;
188 case WBPROJECT:
189 /* It's a project; try to launch it via its default tool. */
191 D(bug("OpenWorkbenchObject: it's a PROJECT\n"));
192 D(bug("OpenWorkbenchObject: default tool: %s\n", icon->do_DefaultTool));
196 icon->do_DefaultTool != NULL
197 && strlen(icon->do_DefaultTool) > 0
200 BPTR lock = (BPTR)NULL, parent = (BPTR)NULL;
202 lock = Lock(name, ACCESS_READ);
203 if (lock != (BPTR)NULL)
204 parent = ParentDir(lock);
205 if (parent != (BPTR)NULL)
207 struct TagItem tags[] =
209 {WBOPENA_ArgLock, (IPTR) parent},
210 {WBOPENA_ArgName, (IPTR) FilePart(name)},
211 {TAG_DONE, (IPTR)NULL}
214 if (FindToolType(icon->do_ToolTypes, "CLI") == NULL)
216 BPTR lock2 = (BPTR)NULL, parent2 = (BPTR)NULL;
218 lock2 = Lock(icon->do_DefaultTool, ACCESS_READ);
219 if (lock2 != (BPTR)NULL)
220 parent2 = ParentDir(lock2);
221 if (parent2 != NULL)
223 success = WB_LaunchProgram
225 parent2, FilePart(icon->do_DefaultTool), tags
228 UnLock(parent2);
229 UnLock(lock2);
231 else
233 success = CLI_LaunchProgram
235 icon->do_DefaultTool, tags
239 UnLock(parent);
240 UnLock(lock);
244 if (!success)
246 // FIXME: open execute command?
248 break;
251 FreeDiskObject(icon);
253 else
256 Getting (a possibly default) icon for the path failed, and
257 therefore there is no such file. We need to search the default
258 search path for an executable of that name and launch it. This
259 only makes sense if the name is *not* an (absolute or relative)
260 path: that is, it must not contain any ':' or '/'.
263 if (strpbrk(name, "/:") == NULL)
265 struct CommandLineInterface *cli = Cli();
266 if (cli != NULL)
268 BPTR *paths; /* Path list */
269 BOOL running = TRUE;
271 /* Iterate over all paths in the path list */
274 paths = (BPTR *) BADDR(cli->cli_CommandDir);
275 running == TRUE && paths != NULL;
276 paths = (BPTR *) BADDR(paths[0]) /* next path */
279 BPTR cd = CurrentDir(paths[1]);
280 BPTR lock = Lock(name, SHARED_LOCK);
282 if (lock != NULL)
284 success = OpenWorkbenchObjectA(name, tags);
285 running = FALSE;
287 UnLock(lock);
290 CurrentDir(cd);
296 D(bug("OpenWorkbenchObject: success = %d\n", success));
298 return success;
300 AROS_LIBFUNC_EXIT
301 } /* OpenWorkbenchObjectA() */
303 STRPTR __CLI_BuildCommandLine
305 CONST_STRPTR command, struct TagItem *tags,
306 struct WorkbenchBase *WorkbenchBase
309 const struct TagItem *tstate = tags;
310 const struct TagItem *tag = NULL;
311 BPTR lastLock = NULL;
312 STRPTR buffer = NULL;
313 ULONG length = strlen(command) + 3 /* NULL + 2 '"' */;
315 /*-- Calculate length of resulting string ------------------------------*/
316 while ((tag = NextTagItem(&tstate)) != NULL)
318 switch (tag->ti_Tag)
320 case WBOPENA_ArgLock:
321 lastLock = (BPTR) tag->ti_Data;
322 break;
324 case WBOPENA_ArgName:
325 if (lastLock != NULL)
327 BPTR cd = CurrentDir(lastLock);
328 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
329 if (lock != NULL)
331 STRPTR path = AllocateNameFromLock(lock);
332 if (path != NULL)
334 length += 3 /* space + 2 '"' */ + strlen(path);
335 FreeVec(path);
338 UnLock(lock);
341 CurrentDir(cd);
343 break;
347 /*-- Allocate space for command line string ----------------------------*/
348 buffer = AllocVec(length, MEMF_ANY);
350 if (buffer != NULL)
352 buffer[0] = '\0';
354 /*-- Build command line --------------------------------------------*/
355 strcat(buffer, "\"");
356 strcat(buffer, command);
357 strcat(buffer, "\"");
359 tstate = tags; lastLock = NULL;
360 while ((tag = NextTagItem(&tstate)) != NULL )
362 switch (tag->ti_Tag)
364 case WBOPENA_ArgLock:
365 lastLock = (BPTR) tag->ti_Data;
366 break;
368 case WBOPENA_ArgName:
369 if (lastLock != NULL)
371 BPTR cd = CurrentDir(lastLock);
372 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
373 if (lock != NULL)
375 STRPTR path = AllocateNameFromLock(lock);
376 if (path != NULL)
378 strcat(buffer, " \"");
379 strcat(buffer, path);
380 strcat(buffer, "\"");
381 FreeVec(path);
384 UnLock(lock);
387 CurrentDir(cd);
389 break;
393 else
395 SetIoErr(ERROR_NO_FREE_STORE);
398 return buffer;
401 BOOL __CLI_LaunchProgram
403 CONST_STRPTR command, struct TagItem *tags,
404 struct WorkbenchBase *WorkbenchBase
407 BPTR input = NULL;
408 STRPTR commandline = NULL;
410 input = Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE);
411 if (input == NULL) goto error;
413 commandline = CLI_BuildCommandLine(command, tags);
414 if (commandline == NULL) goto error;
419 Launch the program. Note that there is no advantage of doing this
420 in the handler, since we need to wait for the return value anyway
421 (and thus we cannot cut down the blocking time by returning before
422 the program is loaded from disk).
425 SystemTags
427 commandline,
428 SYS_Asynch, TRUE,
429 SYS_Input, (IPTR) input,
430 SYS_Output, (IPTR) NULL,
431 SYS_Error, (IPTR) NULL,
432 NP_StackSize, WorkbenchBase->wb_DefaultStackSize,
433 TAG_DONE
434 ) == -1
437 goto error;
439 FreeVec(commandline);
441 return TRUE;
443 error:
444 if (input != NULL) Close(input);
445 if (commandline != NULL) FreeVec(commandline);
447 return FALSE;
450 BOOL __WB_BuildArguments
452 struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags,
453 struct WorkbenchBase *WorkbenchBase
456 const struct TagItem *tstate = tags,
457 *tag = NULL;
458 BPTR lastLock = NULL;
459 struct WBArg *args = NULL;
461 /*-- Calculate the number of arguments ---------------------------------*/
462 startup->sm_NumArgs = 1;
463 while ((tag = NextTagItem(&tstate)) != NULL)
465 switch (tag->ti_Tag)
467 case WBOPENA_ArgLock:
468 lastLock = (BPTR) tag->ti_Data;
469 break;
471 case WBOPENA_ArgName:
473 Filter out args where both lock AND name are NULL, since
474 they are completely worthless to the application.
476 if (lastLock != NULL || (STRPTR) tag->ti_Data != NULL)
478 startup->sm_NumArgs++;
480 break;
484 /*-- Allocate memory for the arguments ---------------------------------*/
485 args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
486 if (args != NULL)
488 LONG i = 0;
490 startup->sm_ArgList = args;
492 /*-- Build the argument list ---------------------------------------*/
495 (args[i].wa_Lock = DupLock(lock)) == NULL
496 || (args[i].wa_Name = StrDup(name)) == NULL
499 goto error;
501 i++;
503 tstate = tags; lastLock = NULL;
504 while ((tag = NextTagItem(&tstate)) != NULL)
506 switch (tag->ti_Tag)
508 case WBOPENA_ArgLock:
509 lastLock = (BPTR) tag->ti_Data;
510 break;
512 case WBOPENA_ArgName:
514 Filter out args where both lock AND name are NULL,
515 since they are completely worthless to the application.
517 if (lastLock != NULL || (STRPTR) tag->ti_Data != NULL)
519 STRPTR name = (STRPTR) tag->ti_Data;
521 /* Duplicate the lock */
522 if (lastLock != NULL)
524 args[i].wa_Lock = DupLock(lastLock);
526 if (args[i].wa_Lock == NULL)
528 D(bug("workbench.library: WB_BuildArguments: Failed to duplicate lock!\n"));
529 goto error;
530 break;
533 else
535 args[i].wa_Lock = NULL;
538 /* Duplicate the name */
539 if (name != NULL)
541 args[i].wa_Name = StrDup(name);
543 if (args[i].wa_Name == NULL)
545 D(bug("workbench.library: WB_BuildArguments: Failed to duplicate string!\n"));
546 goto error;
547 break;
550 else
552 args[i].wa_Name = NULL;
555 i++;
557 break;
561 return TRUE;
563 else
565 D(bug("workbench.library: WB_BuildArguments: Failed to allocate memory for argument array\n"));
568 error:
569 D(bug("workbench.library: WB_BuildArguments: Freeing resources after error...\n"));
570 /* Free allocated resources */
571 if (args != NULL)
573 int i;
575 for (i = 0; i < startup->sm_NumArgs; i++)
577 if (args[i].wa_Lock != NULL) UnLock(args[i].wa_Lock);
578 if (args[i].wa_Name != NULL) FreeVec(args[i].wa_Name);
581 FreeMem(args, sizeof(struct WBArg) * startup->sm_NumArgs);
584 startup->sm_NumArgs = 0;
585 startup->sm_ArgList = NULL;
587 return FALSE;
590 BOOL __WB_LaunchProgram
592 BPTR lock, CONST_STRPTR name, struct TagItem *tags,
593 struct WorkbenchBase *WorkbenchBase
596 struct WBStartup *startup = NULL;
597 struct WBCommandMessage *message = NULL;
599 /*-- Allocate memory for messages --------------------------------------*/
600 startup = CreateWBS();
601 if (startup == NULL)
603 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for startup message\n"));
604 SetIoErr(ERROR_NO_FREE_STORE);
605 goto error;
608 message = CreateWBCM(WBCM_TYPE_LAUNCH);
609 if (message == NULL)
611 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for launch message\n"));
612 SetIoErr(ERROR_NO_FREE_STORE);
613 goto error;
616 /*-- Build the arguments array -----------------------------------------*/
617 if (!WB_BuildArguments(startup, lock, name, tags))
619 D(bug("workbench.library: WB_LaunchProgram: Failed to build arguments\n"));
620 goto error;
623 /*-- Send message to handler -------------------------------------------*/
624 /* NOTE: The handler will deallocate all resources of this message! */
625 message->wbcm_Data.Launch.Startup = startup;
627 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) message);
629 D(bug("workbench.library: WB_LaunchProgram: Success\n"));
631 return TRUE;
633 error:
634 if (startup != NULL) DestroyWBS(startup);
635 if (message != NULL) DestroyWBCM(message);
637 D(bug("workbench.library: WB_LaunchProgram: Failure\n"));
639 return FALSE;