2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
5 Open a drawer or launch a program.
9 #include <aros/debug.h>
11 #include <exec/types.h>
12 #include <exec/ports.h>
13 #include <utility/tagitem.h>
14 #include <intuition/intuition.h>
15 #include <workbench/workbench.h>
16 #include <proto/utility.h>
17 #include <proto/dos.h>
21 #include "workbench_intern.h"
23 #include "support_messages.h"
25 #include "handler_support.h"
26 #include "uae_integration.h"
28 /*** Prototypes *************************************************************/
29 static BOOL CLI_LaunchProgram(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
30 static STRPTR CLI_BuildCommandLine(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
31 static BOOL WB_LaunchProgram(BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
32 static BOOL WB_BuildArguments(struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
33 static BOOL HandleDrawer(STRPTR name, struct WorkbenchBase *WorkbenchBase);
34 static BOOL HandleTool(STRPTR name, LONG isDefaultIcon, struct DiskObject *icon, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
35 static BOOL HandleProject(STRPTR name, LONG isDefaultIcon, struct DiskObject *icon, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
37 /*****************************************************************************
41 #include <proto/workbench.h>
43 AROS_LH2(BOOL, OpenWorkbenchObjectA,
46 AROS_LHA(STRPTR, name, A0),
47 AROS_LHA(struct TagItem *, tags, A1),
50 struct WorkbenchBase *, WorkbenchBase, 16, Workbench)
68 ******************************************************************************/
73 LONG isDefaultIcon = 42;
75 struct DiskObject *icon = GetIconTags
78 ICONGETA_FailIfUnavailable, FALSE,
79 ICONGETA_IsDefaultIcon, (IPTR) &isDefaultIcon,
83 ASSERT_VALID_PTR(name);
84 ASSERT_VALID_PTR_OR_NULL(tags);
86 D(bug("[WBLIB] OpenWorkbenchObjectA: name = %s\n", name));
87 D(bug("[WBLIB] OpenWorkbenchObjectA: isDefaultIcon = %ld\n", isDefaultIcon));
89 if( j_uae_running() && is_68k(name, WorkbenchBase) )
92 D(bug("[WBLIB] OpenWorkbenchObjectA: forward %s to uae\n", name));
94 forward_to_uae(tags, name, WorkbenchBase);
101 switch (icon->do_Type)
106 success = HandleDrawer(name, WorkbenchBase);
110 success = HandleTool(name, isDefaultIcon, icon, tags, WorkbenchBase);
114 success = HandleProject(name, isDefaultIcon, icon, tags, WorkbenchBase);
118 FreeDiskObject(icon);
123 Getting (a possibly default) icon for the path failed, and
124 therefore there is no such file. We need to search the default
125 search path for an executable of that name and launch it. This
126 only makes sense if the name is *not* an (absolute or relative)
127 path: that is, it must not contain any ':' or '/'.
130 if (strpbrk(name, "/:") == NULL)
132 struct CommandLineInterface *cli = Cli();
135 BPTR *paths; /* Path list */
138 /* Iterate over all paths in the path list */
141 paths = (BPTR *) BADDR(cli->cli_CommandDir);
142 running == TRUE && paths != NULL;
143 paths = (BPTR *) BADDR(paths[0]) /* next path */
146 BPTR cd = CurrentDir(paths[1]);
147 BPTR lock = Lock(name, SHARED_LOCK);
151 success = OpenWorkbenchObjectA(name, tags);
164 D(bug("[WBLIB] OpenWorkbenchObjectA: success = %d\n", success));
169 } /* OpenWorkbenchObjectA() */
171 /****************************************************************************/
173 static STRPTR CLI_BuildCommandLine
175 CONST_STRPTR command, struct TagItem *tags,
176 struct WorkbenchBase *WorkbenchBase
179 struct TagItem *tstate = tags;
180 struct TagItem *tag = NULL;
181 BPTR lastLock = BNULL;
182 STRPTR buffer = NULL;
183 ULONG length = strlen(command) + 3 /* NULL + 2 '"' */;
185 /*-- Calculate length of resulting string ------------------------------*/
186 while ((tag = NextTagItem(&tstate)) != NULL)
190 case WBOPENA_ArgLock:
191 lastLock = (BPTR) tag->ti_Data;
194 case WBOPENA_ArgName:
195 if (lastLock != BNULL)
197 BPTR cd = CurrentDir(lastLock);
198 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
201 STRPTR path = AllocateNameFromLock(lock);
204 length += 3 /* space + 2 '"' */ + strlen(path);
217 /*-- Allocate space for command line string ----------------------------*/
218 buffer = AllocVec(length, MEMF_ANY);
224 /*-- Build command line --------------------------------------------*/
225 strcat(buffer, "\"");
226 strcat(buffer, command);
227 strcat(buffer, "\"");
229 tstate = tags; lastLock = BNULL;
230 while ((tag = NextTagItem(&tstate)) != NULL )
234 case WBOPENA_ArgLock:
235 lastLock = (BPTR) tag->ti_Data;
238 case WBOPENA_ArgName:
239 if (lastLock != BNULL)
241 BPTR cd = CurrentDir(lastLock);
242 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
245 STRPTR path = AllocateNameFromLock(lock);
248 strcat(buffer, " \"");
249 strcat(buffer, path);
250 strcat(buffer, "\"");
265 SetIoErr(ERROR_NO_FREE_STORE);
271 /****************************************************************************/
273 static BOOL CLI_LaunchProgram
275 CONST_STRPTR command, struct TagItem *tags,
276 struct WorkbenchBase *WorkbenchBase
280 STRPTR commandline = NULL;
281 IPTR stacksize = WorkbenchBase->wb_DefaultStackSize;
283 struct TagItem *foundTag = NULL;
285 input = Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE);
286 if (input == BNULL) goto error;
288 commandline = CLI_BuildCommandLine(command, tags, WorkbenchBase);
289 if (commandline == NULL) goto error;
293 foundTag = FindTagItem(NP_StackSize, tags);
294 if (foundTag != NULL)
296 stacksize = foundTag->ti_Data;
299 foundTag = FindTagItem(NP_Priority, tags);
300 if (foundTag != NULL)
302 priority = foundTag->ti_Data;
309 Launch the program. Note that there is no advantage of doing this
310 in the handler, since we need to wait for the return value anyway
311 (and thus we cannot cut down the blocking time by returning before
312 the program is loaded from disk).
319 SYS_Input, (IPTR) input,
320 SYS_Output, (IPTR) NULL,
321 SYS_Error, (IPTR) NULL,
322 NP_StackSize, stacksize,
323 NP_Priority, priority,
330 FreeVec(commandline);
335 if (input != BNULL) Close(input);
336 if (commandline != NULL) FreeVec(commandline);
341 /****************************************************************************/
343 static BOOL WB_BuildArguments
345 struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags,
346 struct WorkbenchBase *WorkbenchBase
349 struct TagItem *tstate = tags,
351 BPTR lastLock = BNULL;
352 struct WBArg *args = NULL;
354 /*-- Calculate the number of arguments ---------------------------------*/
355 startup->sm_NumArgs = 1;
356 while ((tag = NextTagItem(&tstate)) != NULL)
360 case WBOPENA_ArgLock:
361 lastLock = (BPTR) tag->ti_Data;
364 case WBOPENA_ArgName:
366 Filter out args where both lock AND name are NULL, since
367 they are completely worthless to the application.
369 if (lastLock != BNULL || (STRPTR) tag->ti_Data != NULL)
371 startup->sm_NumArgs++;
377 /*-- Allocate memory for the arguments ---------------------------------*/
378 args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
383 startup->sm_ArgList = args;
385 /*-- Build the argument list ---------------------------------------*/
388 (args[i].wa_Lock = DupLock(lock)) == BNULL
389 || (args[i].wa_Name = StrDup(name)) == NULL
396 tstate = tags; lastLock = BNULL;
397 while ((tag = NextTagItem(&tstate)) != NULL)
401 case WBOPENA_ArgLock:
402 lastLock = (BPTR) tag->ti_Data;
405 case WBOPENA_ArgName:
407 Filter out args where both lock AND name are NULL,
408 since they are completely worthless to the application.
410 if (lastLock != BNULL || (STRPTR) tag->ti_Data != NULL)
412 STRPTR name = (STRPTR) tag->ti_Data;
414 /* Duplicate the lock */
415 if (lastLock != BNULL)
417 args[i].wa_Lock = DupLock(lastLock);
419 if (args[i].wa_Lock == BNULL)
421 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate lock!\n"));
428 args[i].wa_Lock = BNULL;
431 /* Duplicate the name */
434 args[i].wa_Name = StrDup(name);
436 if (args[i].wa_Name == NULL)
438 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate string!\n"));
445 args[i].wa_Name = NULL;
458 D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
462 D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
463 /* Free allocated resources */
468 for (i = 0; i < startup->sm_NumArgs; i++)
470 if (args[i].wa_Lock != BNULL) UnLock(args[i].wa_Lock);
471 if (args[i].wa_Name != NULL) FreeVec(args[i].wa_Name);
474 FreeMem(args, sizeof(struct WBArg) * startup->sm_NumArgs);
477 startup->sm_NumArgs = 0;
478 startup->sm_ArgList = NULL;
483 /****************************************************************************/
485 static BOOL WB_LaunchProgram
487 BPTR lock, CONST_STRPTR name, struct TagItem *tags,
488 struct WorkbenchBase *WorkbenchBase
491 struct WBStartup *startup = NULL;
492 struct WBCommandMessage *message = NULL;
493 struct TagItem *stackTag = NULL;
494 struct TagItem *prioTag = NULL;
496 /*-- Allocate memory for messages --------------------------------------*/
497 startup = CreateWBS();
500 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
501 SetIoErr(ERROR_NO_FREE_STORE);
505 message = CreateWBCM(WBCM_TYPE_LAUNCH);
508 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
509 SetIoErr(ERROR_NO_FREE_STORE);
515 stackTag = FindTagItem(NP_StackSize, tags);
516 prioTag = FindTagItem(NP_Priority, tags);
518 if (stackTag || prioTag)
520 message->wbcm_Tags = AllocateTagItems(3);
522 message->wbcm_Tags[0].ti_Tag = stackTag ? stackTag->ti_Tag : TAG_IGNORE;
523 message->wbcm_Tags[0].ti_Data = stackTag->ti_Data;
525 message->wbcm_Tags[1].ti_Tag = prioTag ? prioTag->ti_Tag : TAG_IGNORE;
526 message->wbcm_Tags[1].ti_Data = prioTag->ti_Data;
528 message->wbcm_Tags[2].ti_Tag = TAG_DONE;
532 /*-- Build the arguments array -----------------------------------------*/
533 if (!WB_BuildArguments(startup, lock, name, tags, WorkbenchBase))
535 D(bug("[WBLIB] WB_LaunchProgram: Failed to build arguments\n"));
539 /*-- Send message to handler -------------------------------------------*/
540 /* NOTE: The handler will deallocate all resources of this message! */
541 message->wbcm_Data.Launch.Startup = startup;
543 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) message);
545 D(bug("[WBLIB] WB_LaunchProgram: Success\n"));
550 if (startup != NULL) DestroyWBS(startup);
551 if (message != NULL) DestroyWBCM(message);
553 D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));
558 /****************************************************************************/
560 static BOOL HandleDrawer(STRPTR name, struct WorkbenchBase *WorkbenchBase)
563 Since it's a directory or volume, tell the Workbench
564 Application to open the corresponding drawer.
567 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a DISK, DRAWER or GARBAGE\n"));
569 BOOL success = FALSE;
570 struct WBCommandMessage *wbcm = NULL;
571 struct WBHandlerMessage *wbhm = NULL;
572 CONST_STRPTR namecopy = NULL;
576 (wbcm = CreateWBCM(WBCM_TYPE_RELAY)) != NULL
577 && (wbhm = CreateWBHM(WBHM_TYPE_OPEN)) != NULL
578 && (namecopy = StrDup(name)) != NULL
582 wbhm->wbhm_Data.Open.Name = namecopy;
583 wbcm->wbcm_Data.Relay.Message = wbhm;
585 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) wbcm);
590 FreeVec((STRPTR)namecopy);
597 /****************************************************************************/
599 static BOOL HandleTool
601 STRPTR name, LONG isDefaultIcon, struct DiskObject *icon,
602 struct TagItem *tags, struct WorkbenchBase *WorkbenchBase
606 It's an executable. Before I launch it, I must check
607 whether it is a Workbench program or a CLI program.
610 BOOL success = FALSE;
612 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a TOOL\n"));
617 && FindToolType(icon->do_ToolTypes, "CLI") == NULL
620 /* It's a Workbench program */
621 BPTR lock = Lock(name, ACCESS_READ);
623 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a WB program\n"));
627 BPTR parent = ParentDir(lock);
631 IPTR stacksize = icon->do_StackSize;
633 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
634 stacksize = WorkbenchBase->wb_DefaultStackSize;
636 /* check for TOOLPRI */
638 STRPTR prio_tt = FindToolType(icon->do_ToolTypes, "TOOLPRI");
641 StrToLong(prio_tt, &priority);
648 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize, priority));
650 struct TagItem wbp_Tags[] =
652 { NP_StackSize, stacksize },
653 { NP_Priority, priority },
654 { TAG_MORE, (IPTR)tags },
659 wbp_Tags[2].ti_Tag = TAG_IGNORE;
661 success = WB_LaunchProgram
663 parent, FilePart(name), wbp_Tags, WorkbenchBase
669 Fallback to launching it as a CLI program.
670 Most likely it will also fail, but we
673 success = CLI_LaunchProgram(name, wbp_Tags, WorkbenchBase);
684 /* It's a CLI program */
686 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
688 success = CLI_LaunchProgram(name, tags, WorkbenchBase);
694 /****************************************************************************/
696 static BOOL HandleProject
698 STRPTR name, LONG isDefaultIcon, struct DiskObject *icon,
699 struct TagItem *tags, struct WorkbenchBase *WorkbenchBase
702 /* It's a project; try to launch it via its default tool. */
704 BOOL success = FALSE;
706 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a PROJECT\n"));
707 D(bug("[WBLIB] OpenWorkbenchObjectA: default tool: %s\n", icon->do_DefaultTool));
711 icon->do_DefaultTool != NULL
712 && strlen(icon->do_DefaultTool) > 0
715 BPTR lock = BNULL, parent = BNULL;
717 lock = Lock(name, ACCESS_READ);
719 parent = ParentDir(lock);
722 * A project icon (without a project file) is actually enough for
723 * original Workbench (ie to launch the supplied tool)
727 if ((iconname = AllocVec(strlen(name) + 5, MEMF_ANY)) == NULL)
730 strcat(iconname, name);
731 strcat(iconname, ".info");
732 if ((lock = Lock(iconname, ACCESS_READ)) != BNULL)
733 parent = ParentDir(lock);
738 IPTR stacksize = icon->do_StackSize;
740 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
741 stacksize = WorkbenchBase->wb_DefaultStackSize;
743 /* check for TOOLPRI */
745 STRPTR prio_tt = FindToolType(icon->do_ToolTypes, "TOOLPRI");
748 StrToLong(prio_tt, &priority);
755 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize, priority));
757 struct TagItem deftool_tags[] =
759 { NP_StackSize , stacksize },
760 { NP_Priority , priority },
761 { WBOPENA_ArgLock , (IPTR) parent },
762 { WBOPENA_ArgName , (IPTR) FilePart(name) },
763 { TAG_MORE , (IPTR) tags },
768 deftool_tags[4].ti_Tag = TAG_IGNORE;
770 if (FindToolType(icon->do_ToolTypes, "CLI") == NULL)
772 BPTR deftool_lock = BNULL, deftool_parent = BNULL, old_parent = BNULL;
775 /* try current dir / absolute path first */
776 deftool_lock = Lock(icon->do_DefaultTool, ACCESS_READ);
777 if (deftool_lock != BNULL)
778 deftool_parent = ParentDir(deftool_lock);
780 if (deftool_parent != BNULL)
783 success = WB_LaunchProgram
785 deftool_parent, FilePart(icon->do_DefaultTool), deftool_tags, WorkbenchBase
788 UnLock(deftool_parent);
789 UnLock(deftool_lock);
791 if (!found && strpbrk(icon->do_DefaultTool, "/:") == NULL) /* relative path */
793 struct CommandLineInterface *cli = Cli();
796 BPTR *paths; /* Path list */
799 /* Iterate over all paths in the path list */
802 paths = (BPTR *) BADDR(cli->cli_CommandDir);
803 running == TRUE && paths != NULL;
804 paths = (BPTR *) BADDR(paths[0]) /* next path */
807 old_parent = CurrentDir(paths[1]);
808 deftool_parent = DupLock(paths[1]);
809 deftool_lock = Lock(icon->do_DefaultTool, SHARED_LOCK);
811 if (deftool_lock != BNULL)
813 success = WB_LaunchProgram
815 deftool_parent, icon->do_DefaultTool, deftool_tags, WorkbenchBase
820 UnLock(deftool_lock);
821 UnLock(deftool_parent);
823 CurrentDir(old_parent);
830 success = CLI_LaunchProgram
832 icon->do_DefaultTool, tags, WorkbenchBase
840 D(bug("[WBLIB] OpenWorkbenchObjectA: Couldn't get parent dir!\n"));
845 // FIXME: open ExecuteCommand?