2 Copyright © 1995-2007, 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 ******************************************************************************/
74 LONG isDefaultIcon
= 42;
76 struct DiskObject
*icon
= GetIconTags
79 ICONGETA_FailIfUnavailable
, FALSE
,
80 ICONGETA_IsDefaultIcon
, (IPTR
) &isDefaultIcon
,
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
));
92 switch (icon
->do_Type
)
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
);
124 FreeVec((STRPTR
)namecopy
);
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"));
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"));
153 BPTR parent
= ParentDir(lock
);
157 success
= WB_LaunchProgram
159 parent
, FilePart(name
), tags
165 Fallback to launching it as a CLI program.
166 Most likely it will also fail, but we
169 success
= CLI_LaunchProgram(name
, tags
);
180 /* It's a CLI program */
182 D(bug("OpenWorkbenchObject: it's a CLI program\n"));
184 success
= CLI_LaunchProgram(name
, tags
);
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
);
223 success
= WB_LaunchProgram
225 parent2
, FilePart(icon
->do_DefaultTool
), tags
233 success
= CLI_LaunchProgram
235 icon
->do_DefaultTool
, tags
246 // FIXME: open execute command?
251 FreeDiskObject(icon
);
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();
268 BPTR
*paths
; /* Path list */
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
);
284 success
= OpenWorkbenchObjectA(name
, tags
);
296 D(bug("OpenWorkbenchObject: success = %d\n", success
));
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
)
320 case WBOPENA_ArgLock
:
321 lastLock
= (BPTR
) tag
->ti_Data
;
324 case WBOPENA_ArgName
:
325 if (lastLock
!= NULL
)
327 BPTR cd
= CurrentDir(lastLock
);
328 BPTR lock
= Lock((STRPTR
) tag
->ti_Data
, ACCESS_READ
);
331 STRPTR path
= AllocateNameFromLock(lock
);
334 length
+= 3 /* space + 2 '"' */ + strlen(path
);
347 /*-- Allocate space for command line string ----------------------------*/
348 buffer
= AllocVec(length
, MEMF_ANY
);
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
)
364 case WBOPENA_ArgLock
:
365 lastLock
= (BPTR
) tag
->ti_Data
;
368 case WBOPENA_ArgName
:
369 if (lastLock
!= NULL
)
371 BPTR cd
= CurrentDir(lastLock
);
372 BPTR lock
= Lock((STRPTR
) tag
->ti_Data
, ACCESS_READ
);
375 STRPTR path
= AllocateNameFromLock(lock
);
378 strcat(buffer
, " \"");
379 strcat(buffer
, path
);
380 strcat(buffer
, "\"");
395 SetIoErr(ERROR_NO_FREE_STORE
);
401 BOOL __CLI_LaunchProgram
403 CONST_STRPTR command
, struct TagItem
*tags
,
404 struct WorkbenchBase
*WorkbenchBase
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).
429 SYS_Input
, (IPTR
) input
,
430 SYS_Output
, (IPTR
) NULL
,
431 SYS_Error
, (IPTR
) NULL
,
432 NP_StackSize
, WorkbenchBase
->wb_DefaultStackSize
,
439 FreeVec(commandline
);
444 if (input
!= NULL
) Close(input
);
445 if (commandline
!= NULL
) FreeVec(commandline
);
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
,
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
)
467 case WBOPENA_ArgLock
:
468 lastLock
= (BPTR
) tag
->ti_Data
;
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
++;
484 /*-- Allocate memory for the arguments ---------------------------------*/
485 args
= AllocMem(sizeof(struct WBArg
) * startup
->sm_NumArgs
, MEMF_ANY
| MEMF_CLEAR
);
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
503 tstate
= tags
; lastLock
= NULL
;
504 while ((tag
= NextTagItem(&tstate
)) != NULL
)
508 case WBOPENA_ArgLock
:
509 lastLock
= (BPTR
) tag
->ti_Data
;
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"));
535 args
[i
].wa_Lock
= NULL
;
538 /* Duplicate the name */
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"));
552 args
[i
].wa_Name
= NULL
;
565 D(bug("workbench.library: WB_BuildArguments: Failed to allocate memory for argument array\n"));
569 D(bug("workbench.library: WB_BuildArguments: Freeing resources after error...\n"));
570 /* Free allocated resources */
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
;
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();
603 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for startup message\n"));
604 SetIoErr(ERROR_NO_FREE_STORE
);
608 message
= CreateWBCM(WBCM_TYPE_LAUNCH
);
611 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for launch message\n"));
612 SetIoErr(ERROR_NO_FREE_STORE
);
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"));
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"));
634 if (startup
!= NULL
) DestroyWBS(startup
);
635 if (message
!= NULL
) DestroyWBCM(message
);
637 D(bug("workbench.library: WB_LaunchProgram: Failure\n"));