Updates to includes for scsi & usbhardware.
[cake.git] / rom / workbench / openworkbenchobjecta.c
blobf5051d85abd2b824a00477f1fd3aa0d501926b27
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("[WBLIB] OpenWorkbenchObjectA: name = %s\n", name));
88 D(bug("[WBLIB] OpenWorkbenchObjectA: 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("[WBLIB] OpenWorkbenchObjectA: 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("[WBLIB] OpenWorkbenchObjectA: 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("[WBLIB] OpenWorkbenchObjectA: it's a WB program\n"));
151 if (lock != NULL)
153 BPTR parent = ParentDir(lock);
155 if (parent != NULL)
157 IPTR stacksize = icon->do_StackSize;
159 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
160 stacksize = WorkbenchBase->wb_DefaultStackSize;
162 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes\n", stacksize));
164 struct TagItem wbp_Tags[] =
166 { NP_StackSize, stacksize },
167 { TAG_MORE, (IPTR)tags },
168 { TAG_DONE, 0 }
171 if (tags == NULL)
172 wbp_Tags[1].ti_Tag = TAG_IGNORE;
174 success = WB_LaunchProgram
176 parent, FilePart(name), wbp_Tags
179 if (!success)
182 Fallback to launching it as a CLI program.
183 Most likely it will also fail, but we
184 might get lucky.
186 success = CLI_LaunchProgram(name, wbp_Tags);
189 UnLock(parent);
192 UnLock(lock);
195 else
197 /* It's a CLI program */
199 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
201 success = CLI_LaunchProgram(name, tags);
203 break;
205 case WBPROJECT:
206 /* It's a project; try to launch it via its default tool. */
208 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a PROJECT\n"));
209 D(bug("[WBLIB] OpenWorkbenchObjectA: default tool: %s\n", icon->do_DefaultTool));
213 icon->do_DefaultTool != NULL
214 && strlen(icon->do_DefaultTool) > 0
217 BPTR lock = (BPTR)NULL, parent = (BPTR)NULL;
219 lock = Lock(name, ACCESS_READ);
220 if (lock != (BPTR)NULL)
221 parent = ParentDir(lock);
222 if (parent != (BPTR)NULL)
224 IPTR stacksize = icon->do_StackSize;
226 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
227 stacksize = WorkbenchBase->wb_DefaultStackSize;
229 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes\n", stacksize));
231 struct TagItem tags2[] =
233 { NP_StackSize , stacksize },
234 { WBOPENA_ArgLock , (IPTR) parent },
235 { WBOPENA_ArgName , (IPTR) FilePart(name) },
236 { TAG_MORE , (IPTR) tags },
237 { TAG_DONE , 0 }
240 if (tags == NULL)
241 tags2[3].ti_Tag = TAG_IGNORE;
243 if (FindToolType(icon->do_ToolTypes, "CLI") == NULL)
245 BPTR lock2 = (BPTR)NULL, parent2 = (BPTR)NULL;
247 lock2 = Lock(icon->do_DefaultTool, ACCESS_READ);
248 if (lock2 != (BPTR)NULL)
249 parent2 = ParentDir(lock2);
250 if (parent2 != NULL)
252 success = WB_LaunchProgram
254 parent2, FilePart(icon->do_DefaultTool), tags2
257 UnLock(parent2);
258 UnLock(lock2);
260 else
262 success = CLI_LaunchProgram
264 icon->do_DefaultTool, tags
268 UnLock(parent);
269 UnLock(lock);
273 if (!success)
275 // FIXME: open execute command?
277 break;
280 FreeDiskObject(icon);
282 else
285 Getting (a possibly default) icon for the path failed, and
286 therefore there is no such file. We need to search the default
287 search path for an executable of that name and launch it. This
288 only makes sense if the name is *not* an (absolute or relative)
289 path: that is, it must not contain any ':' or '/'.
292 if (strpbrk(name, "/:") == NULL)
294 struct CommandLineInterface *cli = Cli();
295 if (cli != NULL)
297 BPTR *paths; /* Path list */
298 BOOL running = TRUE;
300 /* Iterate over all paths in the path list */
303 paths = (BPTR *) BADDR(cli->cli_CommandDir);
304 running == TRUE && paths != NULL;
305 paths = (BPTR *) BADDR(paths[0]) /* next path */
308 BPTR cd = CurrentDir(paths[1]);
309 BPTR lock = Lock(name, SHARED_LOCK);
311 if (lock != NULL)
313 success = OpenWorkbenchObjectA(name, tags);
314 running = FALSE;
316 UnLock(lock);
319 CurrentDir(cd);
325 D(bug("[WBLIB] OpenWorkbenchObjectA: success = %d\n", success));
327 return success;
329 AROS_LIBFUNC_EXIT
330 } /* OpenWorkbenchObjectA() */
332 STRPTR __CLI_BuildCommandLine
334 CONST_STRPTR command, struct TagItem *tags,
335 struct WorkbenchBase *WorkbenchBase
338 const struct TagItem *tstate = tags;
339 const struct TagItem *tag = NULL;
340 BPTR lastLock = NULL;
341 STRPTR buffer = NULL;
342 ULONG length = strlen(command) + 3 /* NULL + 2 '"' */;
344 /*-- Calculate length of resulting string ------------------------------*/
345 while ((tag = NextTagItem(&tstate)) != NULL)
347 switch (tag->ti_Tag)
349 case WBOPENA_ArgLock:
350 lastLock = (BPTR) tag->ti_Data;
351 break;
353 case WBOPENA_ArgName:
354 if (lastLock != NULL)
356 BPTR cd = CurrentDir(lastLock);
357 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
358 if (lock != NULL)
360 STRPTR path = AllocateNameFromLock(lock);
361 if (path != NULL)
363 length += 3 /* space + 2 '"' */ + strlen(path);
364 FreeVec(path);
367 UnLock(lock);
370 CurrentDir(cd);
372 break;
376 /*-- Allocate space for command line string ----------------------------*/
377 buffer = AllocVec(length, MEMF_ANY);
379 if (buffer != NULL)
381 buffer[0] = '\0';
383 /*-- Build command line --------------------------------------------*/
384 strcat(buffer, "\"");
385 strcat(buffer, command);
386 strcat(buffer, "\"");
388 tstate = tags; lastLock = NULL;
389 while ((tag = NextTagItem(&tstate)) != NULL )
391 switch (tag->ti_Tag)
393 case WBOPENA_ArgLock:
394 lastLock = (BPTR) tag->ti_Data;
395 break;
397 case WBOPENA_ArgName:
398 if (lastLock != NULL)
400 BPTR cd = CurrentDir(lastLock);
401 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
402 if (lock != NULL)
404 STRPTR path = AllocateNameFromLock(lock);
405 if (path != NULL)
407 strcat(buffer, " \"");
408 strcat(buffer, path);
409 strcat(buffer, "\"");
410 FreeVec(path);
413 UnLock(lock);
416 CurrentDir(cd);
418 break;
422 else
424 SetIoErr(ERROR_NO_FREE_STORE);
427 return buffer;
430 BOOL __CLI_LaunchProgram
432 CONST_STRPTR command, struct TagItem *tags,
433 struct WorkbenchBase *WorkbenchBase
436 BPTR input = NULL;
437 STRPTR commandline = NULL;
438 IPTR stacksize = WorkbenchBase->wb_DefaultStackSize;
439 struct TagItem *foundTag = NULL;
441 input = Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE);
442 if (input == NULL) goto error;
444 commandline = CLI_BuildCommandLine(command, tags);
445 if (commandline == NULL) goto error;
447 if ((tags) && ((foundTag = FindTagItem(NP_StackSize, tags)) != NULL))
448 stacksize = foundTag->ti_Data;
453 Launch the program. Note that there is no advantage of doing this
454 in the handler, since we need to wait for the return value anyway
455 (and thus we cannot cut down the blocking time by returning before
456 the program is loaded from disk).
459 SystemTags
461 commandline,
462 SYS_Asynch, TRUE,
463 SYS_Input, (IPTR) input,
464 SYS_Output, (IPTR) NULL,
465 SYS_Error, (IPTR) NULL,
466 NP_StackSize, stacksize,
467 TAG_DONE
468 ) == -1
471 goto error;
473 FreeVec(commandline);
475 return TRUE;
477 error:
478 if (input != NULL) Close(input);
479 if (commandline != NULL) FreeVec(commandline);
481 return FALSE;
484 BOOL __WB_BuildArguments
486 struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags,
487 struct WorkbenchBase *WorkbenchBase
490 const struct TagItem *tstate = tags,
491 *tag = NULL;
492 BPTR lastLock = NULL;
493 struct WBArg *args = NULL;
495 /*-- Calculate the number of arguments ---------------------------------*/
496 startup->sm_NumArgs = 1;
497 while ((tag = NextTagItem(&tstate)) != NULL)
499 switch (tag->ti_Tag)
501 case WBOPENA_ArgLock:
502 lastLock = (BPTR) tag->ti_Data;
503 break;
505 case WBOPENA_ArgName:
507 Filter out args where both lock AND name are NULL, since
508 they are completely worthless to the application.
510 if (lastLock != NULL || (STRPTR) tag->ti_Data != NULL)
512 startup->sm_NumArgs++;
514 break;
518 /*-- Allocate memory for the arguments ---------------------------------*/
519 args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
520 if (args != NULL)
522 LONG i = 0;
524 startup->sm_ArgList = args;
526 /*-- Build the argument list ---------------------------------------*/
529 (args[i].wa_Lock = DupLock(lock)) == NULL
530 || (args[i].wa_Name = StrDup(name)) == NULL
533 goto error;
535 i++;
537 tstate = tags; lastLock = NULL;
538 while ((tag = NextTagItem(&tstate)) != NULL)
540 switch (tag->ti_Tag)
542 case WBOPENA_ArgLock:
543 lastLock = (BPTR) tag->ti_Data;
544 break;
546 case WBOPENA_ArgName:
548 Filter out args where both lock AND name are NULL,
549 since they are completely worthless to the application.
551 if (lastLock != NULL || (STRPTR) tag->ti_Data != NULL)
553 STRPTR name = (STRPTR) tag->ti_Data;
555 /* Duplicate the lock */
556 if (lastLock != NULL)
558 args[i].wa_Lock = DupLock(lastLock);
560 if (args[i].wa_Lock == NULL)
562 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate lock!\n"));
563 goto error;
564 break;
567 else
569 args[i].wa_Lock = NULL;
572 /* Duplicate the name */
573 if (name != NULL)
575 args[i].wa_Name = StrDup(name);
577 if (args[i].wa_Name == NULL)
579 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate string!\n"));
580 goto error;
581 break;
584 else
586 args[i].wa_Name = NULL;
589 i++;
591 break;
595 return TRUE;
597 else
599 D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
602 error:
603 D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
604 /* Free allocated resources */
605 if (args != NULL)
607 int i;
609 for (i = 0; i < startup->sm_NumArgs; i++)
611 if (args[i].wa_Lock != NULL) UnLock(args[i].wa_Lock);
612 if (args[i].wa_Name != NULL) FreeVec(args[i].wa_Name);
615 FreeMem(args, sizeof(struct WBArg) * startup->sm_NumArgs);
618 startup->sm_NumArgs = 0;
619 startup->sm_ArgList = NULL;
621 return FALSE;
624 BOOL __WB_LaunchProgram
626 BPTR lock, CONST_STRPTR name, struct TagItem *tags,
627 struct WorkbenchBase *WorkbenchBase
630 struct WBStartup *startup = NULL;
631 struct WBCommandMessage *message = NULL;
632 struct TagItem *foundTag = NULL;
634 /*-- Allocate memory for messages --------------------------------------*/
635 startup = CreateWBS();
636 if (startup == NULL)
638 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
639 SetIoErr(ERROR_NO_FREE_STORE);
640 goto error;
643 message = CreateWBCM(WBCM_TYPE_LAUNCH);
644 if (message == NULL)
646 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
647 SetIoErr(ERROR_NO_FREE_STORE);
648 goto error;
651 if ((tags) && ((foundTag = FindTagItem(NP_StackSize, tags)) != NULL))
653 message->wbcm_Tags = AllocateTagItems(2);
654 message->wbcm_Tags[0].ti_Tag = foundTag->ti_Tag;
655 message->wbcm_Tags[0].ti_Data = foundTag->ti_Data;
656 message->wbcm_Tags[1].ti_Tag = TAG_DONE;
659 /*-- Build the arguments array -----------------------------------------*/
660 if (!WB_BuildArguments(startup, lock, name, tags))
662 D(bug("[WBLIB] WB_LaunchProgram: Failed to build arguments\n"));
663 goto error;
666 /*-- Send message to handler -------------------------------------------*/
667 /* NOTE: The handler will deallocate all resources of this message! */
668 message->wbcm_Data.Launch.Startup = startup;
670 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) message);
672 D(bug("[WBLIB] WB_LaunchProgram: Success\n"));
674 return TRUE;
676 error:
677 if (startup != NULL) DestroyWBS(startup);
678 if (message != NULL) DestroyWBCM(message);
680 D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));
682 return FALSE;