2 Copyright © 1995-2014, 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"));
427 args
[i
].wa_Lock
= BNULL
;
430 /* Duplicate the name */
433 args
[i
].wa_Name
= StrDup(name
);
435 if (args
[i
].wa_Name
== NULL
)
437 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate string!\n"));
443 args
[i
].wa_Name
= NULL
;
456 D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
460 D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
461 /* Free allocated resources */
466 for (i
= 0; i
< startup
->sm_NumArgs
; i
++)
468 if (args
[i
].wa_Lock
!= BNULL
) UnLock(args
[i
].wa_Lock
);
469 if (args
[i
].wa_Name
!= NULL
) FreeVec(args
[i
].wa_Name
);
472 FreeMem(args
, sizeof(struct WBArg
) * startup
->sm_NumArgs
);
475 startup
->sm_NumArgs
= 0;
476 startup
->sm_ArgList
= NULL
;
481 /****************************************************************************/
483 static BOOL WB_LaunchProgram
485 BPTR lock
, CONST_STRPTR name
, struct TagItem
*tags
,
486 struct WorkbenchBase
*WorkbenchBase
489 struct WBStartup
*startup
= NULL
;
490 struct WBCommandMessage
*message
= NULL
;
491 struct TagItem
*stackTag
= NULL
;
492 struct TagItem
*prioTag
= NULL
;
494 /*-- Allocate memory for messages --------------------------------------*/
495 startup
= CreateWBS();
498 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
499 SetIoErr(ERROR_NO_FREE_STORE
);
503 message
= CreateWBCM(WBCM_TYPE_LAUNCH
);
506 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
507 SetIoErr(ERROR_NO_FREE_STORE
);
513 stackTag
= FindTagItem(NP_StackSize
, tags
);
514 prioTag
= FindTagItem(NP_Priority
, tags
);
516 if (stackTag
|| prioTag
)
518 message
->wbcm_Tags
= AllocateTagItems(3);
520 message
->wbcm_Tags
[0].ti_Tag
= stackTag
? stackTag
->ti_Tag
: TAG_IGNORE
;
521 message
->wbcm_Tags
[0].ti_Data
= stackTag
->ti_Data
;
523 message
->wbcm_Tags
[1].ti_Tag
= prioTag
? prioTag
->ti_Tag
: TAG_IGNORE
;
524 message
->wbcm_Tags
[1].ti_Data
= prioTag
->ti_Data
;
526 message
->wbcm_Tags
[2].ti_Tag
= TAG_DONE
;
530 /*-- Build the arguments array -----------------------------------------*/
531 if (!WB_BuildArguments(startup
, lock
, name
, tags
, WorkbenchBase
))
533 D(bug("[WBLIB] WB_LaunchProgram: Failed to build arguments\n"));
537 /*-- Send message to handler -------------------------------------------*/
538 /* NOTE: The handler will deallocate all resources of this message! */
539 message
->wbcm_Data
.Launch
.Startup
= startup
;
541 PutMsg(&(WorkbenchBase
->wb_HandlerPort
), (struct Message
*) message
);
543 D(bug("[WBLIB] WB_LaunchProgram: Success\n"));
548 if (startup
!= NULL
) DestroyWBS(startup
);
549 if (message
!= NULL
) DestroyWBCM(message
);
551 D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));
556 /****************************************************************************/
558 static BOOL
HandleDrawer(STRPTR name
, struct WorkbenchBase
*WorkbenchBase
)
561 Since it's a directory or volume, tell the Workbench
562 Application to open the corresponding drawer.
565 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a DISK, DRAWER or GARBAGE\n"));
567 BOOL success
= FALSE
;
568 struct WBCommandMessage
*wbcm
= NULL
;
569 struct WBHandlerMessage
*wbhm
= NULL
;
570 CONST_STRPTR namecopy
= NULL
;
574 (wbcm
= CreateWBCM(WBCM_TYPE_RELAY
)) != NULL
575 && (wbhm
= CreateWBHM(WBHM_TYPE_OPEN
)) != NULL
576 && (namecopy
= StrDup(name
)) != NULL
580 wbhm
->wbhm_Data
.Open
.Name
= namecopy
;
581 wbcm
->wbcm_Data
.Relay
.Message
= wbhm
;
583 PutMsg(&(WorkbenchBase
->wb_HandlerPort
), (struct Message
*) wbcm
);
588 FreeVec((STRPTR
)namecopy
);
595 /****************************************************************************/
597 static BOOL HandleTool
599 STRPTR name
, LONG isDefaultIcon
, struct DiskObject
*icon
,
600 struct TagItem
*tags
, struct WorkbenchBase
*WorkbenchBase
604 It's an executable. Before I launch it, I must check
605 whether it is a Workbench program or a CLI program.
608 BOOL success
= FALSE
;
610 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a TOOL\n"));
615 && FindToolType(icon
->do_ToolTypes
, "CLI") == NULL
618 /* It's a Workbench program */
619 BPTR lock
= Lock(name
, ACCESS_READ
);
621 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a WB program\n"));
625 BPTR parent
= ParentDir(lock
);
629 IPTR stacksize
= icon
->do_StackSize
;
631 if (stacksize
< WorkbenchBase
->wb_DefaultStackSize
)
632 stacksize
= WorkbenchBase
->wb_DefaultStackSize
;
634 /* check for TOOLPRI */
636 STRPTR prio_tt
= FindToolType(icon
->do_ToolTypes
, "TOOLPRI");
639 StrToLong(prio_tt
, &priority
);
646 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize
, priority
));
648 struct TagItem wbp_Tags
[] =
650 { NP_StackSize
, stacksize
},
651 { NP_Priority
, priority
},
652 { TAG_MORE
, (IPTR
)tags
},
657 wbp_Tags
[2].ti_Tag
= TAG_IGNORE
;
659 success
= WB_LaunchProgram
661 parent
, FilePart(name
), wbp_Tags
, WorkbenchBase
667 Fallback to launching it as a CLI program.
668 Most likely it will also fail, but we
671 success
= CLI_LaunchProgram(name
, wbp_Tags
, WorkbenchBase
);
682 /* It's a CLI program */
684 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
686 success
= CLI_LaunchProgram(name
, tags
, WorkbenchBase
);
692 /****************************************************************************/
694 static BOOL HandleProject
696 STRPTR name
, LONG isDefaultIcon
, struct DiskObject
*icon
,
697 struct TagItem
*tags
, struct WorkbenchBase
*WorkbenchBase
700 /* It's a project; try to launch it via its default tool. */
702 BOOL success
= FALSE
;
704 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a PROJECT\n"));
705 D(bug("[WBLIB] OpenWorkbenchObjectA: default tool: %s\n", icon
->do_DefaultTool
));
709 icon
->do_DefaultTool
!= NULL
710 && strlen(icon
->do_DefaultTool
) > 0
713 BPTR lock
= BNULL
, parent
= BNULL
;
715 lock
= Lock(name
, ACCESS_READ
);
717 parent
= ParentDir(lock
);
720 * A project icon (without a project file) is actually enough for
721 * original Workbench (i.e. to launch the supplied tool)
725 if ((iconname
= AllocVec(strlen(name
) + 6, MEMF_ANY
)) == NULL
)
728 strcat(iconname
, name
);
729 strcat(iconname
, ".info");
730 if ((lock
= Lock(iconname
, ACCESS_READ
)) != BNULL
)
731 parent
= ParentDir(lock
);
736 IPTR stacksize
= icon
->do_StackSize
;
738 if (stacksize
< WorkbenchBase
->wb_DefaultStackSize
)
739 stacksize
= WorkbenchBase
->wb_DefaultStackSize
;
741 /* check for TOOLPRI */
743 STRPTR prio_tt
= FindToolType(icon
->do_ToolTypes
, "TOOLPRI");
746 StrToLong(prio_tt
, &priority
);
753 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize
, priority
));
755 struct TagItem deftool_tags
[] =
757 { NP_StackSize
, stacksize
},
758 { NP_Priority
, priority
},
759 { WBOPENA_ArgLock
, (IPTR
) parent
},
760 { WBOPENA_ArgName
, (IPTR
) FilePart(name
) },
761 { TAG_MORE
, (IPTR
) tags
},
766 deftool_tags
[4].ti_Tag
= TAG_IGNORE
;
768 if (FindToolType(icon
->do_ToolTypes
, "CLI") == NULL
)
770 BPTR deftool_lock
= BNULL
, deftool_parent
= BNULL
, old_parent
= BNULL
;
773 /* try current dir / absolute path first */
774 deftool_lock
= Lock(icon
->do_DefaultTool
, ACCESS_READ
);
775 if (deftool_lock
!= BNULL
)
776 deftool_parent
= ParentDir(deftool_lock
);
778 if (deftool_parent
!= BNULL
)
781 success
= WB_LaunchProgram
783 deftool_parent
, FilePart(icon
->do_DefaultTool
), deftool_tags
, WorkbenchBase
786 UnLock(deftool_parent
);
787 UnLock(deftool_lock
);
789 if (!found
&& strpbrk(icon
->do_DefaultTool
, "/:") == NULL
) /* relative path */
791 struct CommandLineInterface
*cli
= Cli();
794 BPTR
*paths
; /* Path list */
797 /* Iterate over all paths in the path list */
800 paths
= (BPTR
*) BADDR(cli
->cli_CommandDir
);
801 running
== TRUE
&& paths
!= NULL
;
802 paths
= (BPTR
*) BADDR(paths
[0]) /* next path */
805 old_parent
= CurrentDir(paths
[1]);
806 deftool_parent
= DupLock(paths
[1]);
807 deftool_lock
= Lock(icon
->do_DefaultTool
, SHARED_LOCK
);
809 if (deftool_lock
!= BNULL
)
811 success
= WB_LaunchProgram
813 deftool_parent
, icon
->do_DefaultTool
, deftool_tags
, WorkbenchBase
818 UnLock(deftool_lock
);
819 UnLock(deftool_parent
);
821 CurrentDir(old_parent
);
828 success
= CLI_LaunchProgram
830 icon
->do_DefaultTool
, tags
, WorkbenchBase
838 D(bug("[WBLIB] OpenWorkbenchObjectA: Couldn't get parent dir!\n"));
843 // FIXME: open ExecuteCommand?