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("[WBLIB] OpenWorkbenchObjectA: name = %s\n", name
));
88 D(bug("[WBLIB] OpenWorkbenchObjectA: 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("[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
);
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("[WBLIB] OpenWorkbenchObjectA: 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("[WBLIB] OpenWorkbenchObjectA: it's a WB program\n"));
153 BPTR parent
= ParentDir(lock
);
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
},
172 wbp_Tags
[1].ti_Tag
= TAG_IGNORE
;
174 success
= WB_LaunchProgram
176 parent
, FilePart(name
), wbp_Tags
182 Fallback to launching it as a CLI program.
183 Most likely it will also fail, but we
186 success
= CLI_LaunchProgram(name
, wbp_Tags
);
197 /* It's a CLI program */
199 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
201 success
= CLI_LaunchProgram(name
, tags
);
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 tags
[] =
233 { NP_StackSize
, stacksize
},
234 { WBOPENA_ArgLock
, (IPTR
) parent
},
235 { WBOPENA_ArgName
, (IPTR
) FilePart(name
) },
236 { TAG_DONE
, (IPTR
)NULL
}
239 if (FindToolType(icon
->do_ToolTypes
, "CLI") == NULL
)
241 BPTR lock2
= (BPTR
)NULL
, parent2
= (BPTR
)NULL
;
243 lock2
= Lock(icon
->do_DefaultTool
, ACCESS_READ
);
244 if (lock2
!= (BPTR
)NULL
)
245 parent2
= ParentDir(lock2
);
248 success
= WB_LaunchProgram
250 parent2
, FilePart(icon
->do_DefaultTool
), tags
258 success
= CLI_LaunchProgram
260 icon
->do_DefaultTool
, tags
271 // FIXME: open execute command?
276 FreeDiskObject(icon
);
281 Getting (a possibly default) icon for the path failed, and
282 therefore there is no such file. We need to search the default
283 search path for an executable of that name and launch it. This
284 only makes sense if the name is *not* an (absolute or relative)
285 path: that is, it must not contain any ':' or '/'.
288 if (strpbrk(name
, "/:") == NULL
)
290 struct CommandLineInterface
*cli
= Cli();
293 BPTR
*paths
; /* Path list */
296 /* Iterate over all paths in the path list */
299 paths
= (BPTR
*) BADDR(cli
->cli_CommandDir
);
300 running
== TRUE
&& paths
!= NULL
;
301 paths
= (BPTR
*) BADDR(paths
[0]) /* next path */
304 BPTR cd
= CurrentDir(paths
[1]);
305 BPTR lock
= Lock(name
, SHARED_LOCK
);
309 success
= OpenWorkbenchObjectA(name
, tags
);
321 D(bug("[WBLIB] OpenWorkbenchObjectA: success = %d\n", success
));
326 } /* OpenWorkbenchObjectA() */
328 STRPTR __CLI_BuildCommandLine
330 CONST_STRPTR command
, struct TagItem
*tags
,
331 struct WorkbenchBase
*WorkbenchBase
334 const struct TagItem
*tstate
= tags
;
335 const struct TagItem
*tag
= NULL
;
336 BPTR lastLock
= NULL
;
337 STRPTR buffer
= NULL
;
338 ULONG length
= strlen(command
) + 3 /* NULL + 2 '"' */;
340 /*-- Calculate length of resulting string ------------------------------*/
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 length
+= 3 /* space + 2 '"' */ + strlen(path
);
372 /*-- Allocate space for command line string ----------------------------*/
373 buffer
= AllocVec(length
, MEMF_ANY
);
379 /*-- Build command line --------------------------------------------*/
380 strcat(buffer
, "\"");
381 strcat(buffer
, command
);
382 strcat(buffer
, "\"");
384 tstate
= tags
; lastLock
= NULL
;
385 while ((tag
= NextTagItem(&tstate
)) != NULL
)
389 case WBOPENA_ArgLock
:
390 lastLock
= (BPTR
) tag
->ti_Data
;
393 case WBOPENA_ArgName
:
394 if (lastLock
!= NULL
)
396 BPTR cd
= CurrentDir(lastLock
);
397 BPTR lock
= Lock((STRPTR
) tag
->ti_Data
, ACCESS_READ
);
400 STRPTR path
= AllocateNameFromLock(lock
);
403 strcat(buffer
, " \"");
404 strcat(buffer
, path
);
405 strcat(buffer
, "\"");
420 SetIoErr(ERROR_NO_FREE_STORE
);
426 BOOL __CLI_LaunchProgram
428 CONST_STRPTR command
, struct TagItem
*tags
,
429 struct WorkbenchBase
*WorkbenchBase
433 STRPTR commandline
= NULL
;
434 IPTR stacksize
= WorkbenchBase
->wb_DefaultStackSize
;
435 struct TagItem
*foundTag
= NULL
;
437 input
= Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE
);
438 if (input
== NULL
) goto error
;
440 commandline
= CLI_BuildCommandLine(command
, tags
);
441 if (commandline
== NULL
) goto error
;
443 if ((tags
) && ((foundTag
= FindTagItem(NP_StackSize
, tags
)) != NULL
))
444 stacksize
= foundTag
->ti_Data
;
449 Launch the program. Note that there is no advantage of doing this
450 in the handler, since we need to wait for the return value anyway
451 (and thus we cannot cut down the blocking time by returning before
452 the program is loaded from disk).
459 SYS_Input
, (IPTR
) input
,
460 SYS_Output
, (IPTR
) NULL
,
461 SYS_Error
, (IPTR
) NULL
,
462 NP_StackSize
, stacksize
,
469 FreeVec(commandline
);
474 if (input
!= NULL
) Close(input
);
475 if (commandline
!= NULL
) FreeVec(commandline
);
480 BOOL __WB_BuildArguments
482 struct WBStartup
*startup
, BPTR lock
, CONST_STRPTR name
, struct TagItem
*tags
,
483 struct WorkbenchBase
*WorkbenchBase
486 const struct TagItem
*tstate
= tags
,
488 BPTR lastLock
= NULL
;
489 struct WBArg
*args
= NULL
;
491 /*-- Calculate the number of arguments ---------------------------------*/
492 startup
->sm_NumArgs
= 1;
493 while ((tag
= NextTagItem(&tstate
)) != NULL
)
497 case WBOPENA_ArgLock
:
498 lastLock
= (BPTR
) tag
->ti_Data
;
501 case WBOPENA_ArgName
:
503 Filter out args where both lock AND name are NULL, since
504 they are completely worthless to the application.
506 if (lastLock
!= NULL
|| (STRPTR
) tag
->ti_Data
!= NULL
)
508 startup
->sm_NumArgs
++;
514 /*-- Allocate memory for the arguments ---------------------------------*/
515 args
= AllocMem(sizeof(struct WBArg
) * startup
->sm_NumArgs
, MEMF_ANY
| MEMF_CLEAR
);
520 startup
->sm_ArgList
= args
;
522 /*-- Build the argument list ---------------------------------------*/
525 (args
[i
].wa_Lock
= DupLock(lock
)) == NULL
526 || (args
[i
].wa_Name
= StrDup(name
)) == NULL
533 tstate
= tags
; lastLock
= NULL
;
534 while ((tag
= NextTagItem(&tstate
)) != NULL
)
538 case WBOPENA_ArgLock
:
539 lastLock
= (BPTR
) tag
->ti_Data
;
542 case WBOPENA_ArgName
:
544 Filter out args where both lock AND name are NULL,
545 since they are completely worthless to the application.
547 if (lastLock
!= NULL
|| (STRPTR
) tag
->ti_Data
!= NULL
)
549 STRPTR name
= (STRPTR
) tag
->ti_Data
;
551 /* Duplicate the lock */
552 if (lastLock
!= NULL
)
554 args
[i
].wa_Lock
= DupLock(lastLock
);
556 if (args
[i
].wa_Lock
== NULL
)
558 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate lock!\n"));
565 args
[i
].wa_Lock
= NULL
;
568 /* Duplicate the name */
571 args
[i
].wa_Name
= StrDup(name
);
573 if (args
[i
].wa_Name
== NULL
)
575 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate string!\n"));
582 args
[i
].wa_Name
= NULL
;
595 D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
599 D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
600 /* Free allocated resources */
605 for (i
= 0; i
< startup
->sm_NumArgs
; i
++)
607 if (args
[i
].wa_Lock
!= NULL
) UnLock(args
[i
].wa_Lock
);
608 if (args
[i
].wa_Name
!= NULL
) FreeVec(args
[i
].wa_Name
);
611 FreeMem(args
, sizeof(struct WBArg
) * startup
->sm_NumArgs
);
614 startup
->sm_NumArgs
= 0;
615 startup
->sm_ArgList
= NULL
;
620 BOOL __WB_LaunchProgram
622 BPTR lock
, CONST_STRPTR name
, struct TagItem
*tags
,
623 struct WorkbenchBase
*WorkbenchBase
626 struct WBStartup
*startup
= NULL
;
627 struct WBCommandMessage
*message
= NULL
;
628 struct TagItem
*foundTag
= NULL
;
630 /*-- Allocate memory for messages --------------------------------------*/
631 startup
= CreateWBS();
634 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
635 SetIoErr(ERROR_NO_FREE_STORE
);
639 message
= CreateWBCM(WBCM_TYPE_LAUNCH
);
642 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
643 SetIoErr(ERROR_NO_FREE_STORE
);
647 if ((tags
) && ((foundTag
= FindTagItem(NP_StackSize
, tags
)) != NULL
))
649 message
->wbcm_Tags
= AllocateTagItems(2);
650 message
->wbcm_Tags
[0].ti_Tag
= foundTag
->ti_Tag
;
651 message
->wbcm_Tags
[0].ti_Data
= foundTag
->ti_Data
;
652 message
->wbcm_Tags
[1].ti_Tag
= TAG_DONE
;
655 /*-- Build the arguments array -----------------------------------------*/
656 if (!WB_BuildArguments(startup
, lock
, name
, tags
))
658 D(bug("[WBLIB] WB_LaunchProgram: Failed to build arguments\n"));
662 /*-- Send message to handler -------------------------------------------*/
663 /* NOTE: The handler will deallocate all resources of this message! */
664 message
->wbcm_Data
.Launch
.Startup
= startup
;
666 PutMsg(&(WorkbenchBase
->wb_HandlerPort
), (struct Message
*) message
);
668 D(bug("[WBLIB] WB_LaunchProgram: Success\n"));
673 if (startup
!= NULL
) DestroyWBS(startup
);
674 if (message
!= NULL
) DestroyWBCM(message
);
676 D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));