2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
5 Open a drawer or launch a program.
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>
20 #include "workbench_intern.h"
22 #include "support_messages.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 /*****************************************************************************
42 #include <proto/workbench.h>
44 AROS_LH2(BOOL
, OpenWorkbenchObjectA
,
47 AROS_LHA(STRPTR
, name
, A0
),
48 AROS_LHA(struct TagItem
*, tags
, A1
),
51 struct WorkbenchBase
*, WorkbenchBase
, 16, Workbench
)
69 ******************************************************************************/
72 AROS_LIBBASE_EXT_DECL(struct WorkbenchBase
*, WorkbenchBase
)
75 LONG isDefaultIcon
= 42;
77 struct DiskObject
*icon
= GetIconTags
80 ICONGETA_FailIfUnavailable
, FALSE
,
81 ICONGETA_IsDefaultIcon
, (IPTR
) &isDefaultIcon
,
85 ASSERT_VALID_PTR(name
);
86 ASSERT_VALID_PTR_OR_NULL(tags
);
88 D(bug("OpenWorkbenchObject: name = %s\n", name
));
89 D(bug("OpenWorkbenchObject: isDefaultIcon = %ld\n", isDefaultIcon
));
93 switch (icon
->do_Type
)
99 Since it's a directory or volume, tell the Workbench
100 Application to open the corresponding drawer.
103 D(bug("OpenWorkbenchObject: it's a DISK, DRAWER or GARGABE\n"));
106 struct WBCommandMessage
*wbcm
= NULL
;
107 struct WBHandlerMessage
*wbhm
= NULL
;
108 CONST_STRPTR namecopy
= NULL
;
112 (wbcm
= CreateWBCM(WBCM_TYPE_RELAY
)) != NULL
113 && (wbhm
= CreateWBHM(WBHM_TYPE_OPEN
)) != NULL
114 && (namecopy
= StrDup(name
)) != NULL
118 wbhm
->wbhm_Data
.Open
.Name
= namecopy
;
119 wbcm
->wbcm_Data
.Relay
.Message
= wbhm
;
121 PutMsg(&(WorkbenchBase
->wb_HandlerPort
), (struct Message
*) wbcm
);
125 FreeVec((STRPTR
)namecopy
);
135 It's an executable. Before I launch it, I must check
136 whether it is a Workbench program or a CLI program.
139 D(bug("OpenWorkbenchObject: it's a TOOL\n"));
144 && FindToolType(icon
->do_ToolTypes
, "CLI") == NULL
147 /* It's a Workbench program */
148 BPTR lock
= Lock(name
, ACCESS_READ
);
150 D(bug("OpenWorkbenchObject: it's a WB program\n"));
154 BPTR parent
= ParentDir(lock
);
158 success
= WB_LaunchProgram
160 parent
, FilePart(name
), tags
166 Fallback to launching it as a CLI program.
167 Most likely it will also fail, but we
170 success
= CLI_LaunchProgram(name
, tags
);
181 /* It's a CLI program */
183 D(bug("OpenWorkbenchObject: it's a CLI program\n"));
185 success
= CLI_LaunchProgram(name
, tags
);
190 /* It's a project; try to launch it via it's default tool. */
192 D(bug("OpenWorkbenchObject: it's a PROJECT\n"));
193 D(bug("OpenWorkbenchObject: default tool: %s\n", icon
->do_DefaultTool
));
197 icon
->do_DefaultTool
!= NULL
198 && strlen(icon
->do_DefaultTool
) > 0
201 BPTR lock
= Lock(name
, ACCESS_READ
);
206 BPTR parent
= ParentDir(lock
);
210 success
= OpenWorkbenchObject
212 icon
->do_DefaultTool
,
213 WBOPENA_ArgLock
, (IPTR
) parent
,
214 WBOPENA_ArgName
, (IPTR
) FilePart(name
),
227 // FIXME: open execute command?
232 FreeDiskObject(icon
);
237 Getting (a possibly default) icon for the path failed, and
238 therefore there is no such file. We need to search the default
239 search path for an executable of that name and launch it. This
240 only makes sense if the name is *not* an (absolute or relative)
241 path: that is, it must not contain any ':' or '/'.
244 if (strpbrk(name
, "/:") == NULL
)
246 struct CommandLineInterface
*cli
= Cli();
249 BPTR
*paths
; /* Path list */
252 /* Iterate over all paths in the path list */
255 paths
= (BPTR
*) BADDR(cli
->cli_CommandDir
);
256 running
== TRUE
&& paths
!= NULL
;
257 paths
= (BPTR
*) BADDR(paths
[0]) /* next path */
260 BPTR cd
= CurrentDir(paths
[1]);
261 BPTR lock
= Lock(name
, SHARED_LOCK
);
265 success
= OpenWorkbenchObjectA(name
, tags
);
277 D(bug("OpenWorkbenchObject: success = %d\n", success
));
282 } /* OpenWorkbenchObjectA() */
284 STRPTR __CLI_BuildCommandLine
286 CONST_STRPTR command
, struct TagItem
*tags
,
287 struct WorkbenchBase
*WorkbenchBase
290 struct TagItem
*tstate
= tags
;
291 struct TagItem
*tag
= NULL
;
292 BPTR lastLock
= NULL
;
293 STRPTR buffer
= NULL
;
294 ULONG length
= strlen(command
) + 3 /* NULL + 2 '"' */;
296 /*-- Calculate length of resulting string ------------------------------*/
297 while ((tag
= NextTagItem(&tstate
)) != NULL
)
301 case WBOPENA_ArgLock
:
302 lastLock
= (BPTR
) tag
->ti_Data
;
305 case WBOPENA_ArgName
:
306 if (lastLock
!= NULL
)
308 BPTR cd
= CurrentDir(lastLock
);
309 BPTR lock
= Lock((STRPTR
) tag
->ti_Data
, ACCESS_READ
);
312 STRPTR path
= AllocateNameFromLock(lock
);
315 length
+= 3 /* space + 2 '"' */ + strlen(path
);
328 /*-- Allocate space for command line string ----------------------------*/
329 buffer
= AllocVec(length
, MEMF_ANY
);
335 /*-- Build command line --------------------------------------------*/
336 strcat(buffer
, "\"");
337 strcat(buffer
, command
);
338 strcat(buffer
, "\"");
340 tstate
= tags
; lastLock
= NULL
;
341 while ((tag
= NextTagItem(&tstate
)) != NULL
)
345 case WBOPENA_ArgLock
:
346 lastLock
= (BPTR
) tag
->ti_Data
;
349 case WBOPENA_ArgName
:
350 if (lastLock
!= NULL
)
352 BPTR cd
= CurrentDir(lastLock
);
353 BPTR lock
= Lock((STRPTR
) tag
->ti_Data
, ACCESS_READ
);
356 STRPTR path
= AllocateNameFromLock(lock
);
359 strcat(buffer
, " \"");
360 strcat(buffer
, path
);
361 strcat(buffer
, "\"");
376 SetIoErr(ERROR_NO_FREE_STORE
);
382 BOOL __CLI_LaunchProgram
384 CONST_STRPTR command
, struct TagItem
*tags
,
385 struct WorkbenchBase
*WorkbenchBase
389 STRPTR commandline
= NULL
;
391 input
= Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE
);
392 if (input
== NULL
) goto error
;
394 commandline
= CLI_BuildCommandLine(command
, tags
);
395 if (commandline
== NULL
) goto error
;
400 Launch the program. Note that there is no advantage of doing this
401 in the handler, since we need to wait for the return value anyway
402 (and thus we cannot cut down the blocking time by returning before
403 the program is loaded from disk).
410 SYS_Input
, (IPTR
) input
,
411 SYS_Output
, (IPTR
) NULL
,
412 SYS_Error
, (IPTR
) NULL
,
413 NP_StackSize
, WorkbenchBase
->wb_DefaultStackSize
,
420 FreeVec(commandline
);
425 if (input
!= NULL
) Close(input
);
426 if (commandline
!= NULL
) FreeVec(commandline
);
431 BOOL __WB_BuildArguments
433 struct WBStartup
*startup
, BPTR lock
, CONST_STRPTR name
, struct TagItem
*tags
,
434 struct WorkbenchBase
*WorkbenchBase
437 struct TagItem
*tstate
= tags
,
439 BPTR lastLock
= NULL
;
440 struct WBArg
*args
= NULL
;
442 /*-- Calculate the number of arguments ---------------------------------*/
443 startup
->sm_NumArgs
= 1;
444 while ((tag
= NextTagItem(&tstate
)) != NULL
)
448 case WBOPENA_ArgLock
:
449 lastLock
= (BPTR
) tag
->ti_Data
;
452 case WBOPENA_ArgName
:
454 Filter out args where both lock AND name are NULL, since
455 they are completely worthless to the application.
457 if (lastLock
!= NULL
|| (STRPTR
) tag
->ti_Data
!= NULL
)
459 startup
->sm_NumArgs
++;
465 /*-- Allocate memory for the arguments ---------------------------------*/
466 args
= AllocMem(sizeof(struct WBArg
) * startup
->sm_NumArgs
, MEMF_ANY
| MEMF_CLEAR
);
471 startup
->sm_ArgList
= args
;
473 /*-- Build the argument list ---------------------------------------*/
476 (args
[i
].wa_Lock
= DupLock(lock
)) == NULL
477 || (args
[i
].wa_Name
= StrDup(name
)) == NULL
484 tstate
= tags
; lastLock
= NULL
;
485 while ((tag
= NextTagItem(&tstate
)) != NULL
)
489 case WBOPENA_ArgLock
:
490 lastLock
= (BPTR
) tag
->ti_Data
;
493 case WBOPENA_ArgName
:
495 Filter out args where both lock AND name are NULL,
496 since they are completely worthless to the application.
498 if (lastLock
!= NULL
|| (STRPTR
) tag
->ti_Data
!= NULL
)
500 STRPTR name
= (STRPTR
) tag
->ti_Data
;
502 /* Duplicate the lock */
503 if (lastLock
!= NULL
)
505 args
[i
].wa_Lock
= DupLock(lastLock
);
507 if (args
[i
].wa_Lock
== NULL
)
509 D(bug("workbench.library: WB_BuildArguments: Failed to duplicate lock!\n"));
516 args
[i
].wa_Lock
= NULL
;
519 /* Duplicate the name */
522 args
[i
].wa_Name
= StrDup(name
);
524 if (args
[i
].wa_Name
== NULL
)
526 D(bug("workbench.library: WB_BuildArguments: Failed to duplicate string!\n"));
533 args
[i
].wa_Name
= NULL
;
546 D(bug("workbench.library: WB_BuildArguments: Failed to allocate memory for argument array\n"));
550 D(bug("workbench.library: WB_BuildArguments: Freeing resources after error...\n"));
551 /* Free allocated resources */
556 for (i
= 0; i
< startup
->sm_NumArgs
; i
++)
558 if (args
[i
].wa_Lock
!= NULL
) UnLock(args
[i
].wa_Lock
);
559 if (args
[i
].wa_Name
!= NULL
) FreeVec(args
[i
].wa_Name
);
562 FreeMem(args
, sizeof(struct WBArg
) * startup
->sm_NumArgs
);
565 startup
->sm_NumArgs
= 0;
566 startup
->sm_ArgList
= NULL
;
571 BOOL __WB_LaunchProgram
573 BPTR lock
, CONST_STRPTR name
, struct TagItem
*tags
,
574 struct WorkbenchBase
*WorkbenchBase
577 struct WBStartup
*startup
= NULL
;
578 struct WBCommandMessage
*message
= NULL
;
580 /*-- Allocate memory for messages --------------------------------------*/
581 startup
= CreateWBS();
584 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for startup message\n"));
585 SetIoErr(ERROR_NO_FREE_STORE
);
589 message
= CreateWBCM(WBCM_TYPE_LAUNCH
);
592 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for launch message\n"));
593 SetIoErr(ERROR_NO_FREE_STORE
);
597 /*-- Build the arguments array -----------------------------------------*/
598 if (!WB_BuildArguments(startup
, lock
, name
, tags
))
600 D(bug("workbench.library: WB_LaunchProgram: Failed to build arguments\n"));
604 /*-- Send message to handler -------------------------------------------*/
605 /* NOTE: The handler will deallocate all resources of this message! */
606 message
->wbcm_Data
.Launch
.Startup
= startup
;
608 PutMsg(&(WorkbenchBase
->wb_HandlerPort
), (struct Message
*) message
);
610 D(bug("workbench.library: WB_LaunchProgram: Success\n"));
615 if (startup
!= NULL
) DestroyWBS(startup
);
616 if (message
!= NULL
) DestroyWBCM(message
);
618 D(bug("workbench.library: WB_LaunchProgram: Failure\n"));