Instead of "eax" and "edx" in asm constraints use "a" and "d"
[tangerine.git] / rom / workbench / openworkbenchobjecta.c
blob744f48a052bbc03bbbfe2e0281660d4139740c91
1 /*
2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
3 $Id$
5 Open a drawer or launch a program.
6 */
7 #define DEBUG 1
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>
18 #include <string.h>
20 #include "workbench_intern.h"
21 #include "support.h"
22 #include "support_messages.h"
23 #include "handler.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 /*****************************************************************************
40 NAME */
42 #include <proto/workbench.h>
44 AROS_LH2(BOOL, OpenWorkbenchObjectA,
46 /* SYNOPSIS */
47 AROS_LHA(STRPTR, name, A0),
48 AROS_LHA(struct TagItem *, tags, A1),
50 /* LOCATION */
51 struct WorkbenchBase *, WorkbenchBase, 16, Workbench)
53 /* FUNCTION
55 INPUTS
57 RESULT
59 NOTES
61 EXAMPLE
63 BUGS
65 SEE ALSO
67 INTERNALS
69 ******************************************************************************/
71 AROS_LIBFUNC_INIT
72 AROS_LIBBASE_EXT_DECL(struct WorkbenchBase *, WorkbenchBase)
74 BOOL success = FALSE;
75 LONG isDefaultIcon = 42;
77 struct DiskObject *icon = GetIconTags
79 name,
80 ICONGETA_FailIfUnavailable, FALSE,
81 ICONGETA_IsDefaultIcon, (IPTR) &isDefaultIcon,
82 TAG_DONE
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));
91 if (icon != NULL)
93 switch (icon->do_Type)
95 case WBDISK:
96 case WBDRAWER:
97 case WBGARBAGE:
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);
123 else
125 FreeVec((STRPTR)namecopy);
126 DestroyWBHM(wbhm);
127 DestroyWBCM(wbcm);
131 break;
133 case WBTOOL:
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"));
143 !isDefaultIcon
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"));
152 if (lock != NULL)
154 BPTR parent = ParentDir(lock);
156 if (parent != NULL)
158 success = WB_LaunchProgram
160 parent, FilePart(name), tags
163 if (!success)
166 Fallback to launching it as a CLI program.
167 Most likely it will also fail, but we
168 might get lucky.
170 success = CLI_LaunchProgram(name, tags);
173 UnLock(parent);
176 UnLock(lock);
179 else
181 /* It's a CLI program */
183 D(bug("OpenWorkbenchObject: it's a CLI program\n"));
185 success = CLI_LaunchProgram(name, tags);
187 break;
189 case WBPROJECT:
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);
204 if (lock != NULL)
206 BPTR parent = ParentDir(lock);
208 if (parent != NULL)
210 success = OpenWorkbenchObject
212 icon->do_DefaultTool,
213 WBOPENA_ArgLock, (IPTR) parent,
214 WBOPENA_ArgName, (IPTR) FilePart(name),
215 TAG_DONE
218 UnLock(parent);
221 UnLock(lock);
225 if (!success)
227 // FIXME: open execute command?
229 break;
232 FreeDiskObject(icon);
234 else
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();
247 if (cli != NULL)
249 BPTR *paths; /* Path list */
250 BOOL running = TRUE;
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);
263 if (lock != NULL)
265 success = OpenWorkbenchObjectA(name, tags);
266 running = FALSE;
268 UnLock(lock);
271 CurrentDir(cd);
277 D(bug("OpenWorkbenchObject: success = %d\n", success));
279 return success;
281 AROS_LIBFUNC_EXIT
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)
299 switch (tag->ti_Tag)
301 case WBOPENA_ArgLock:
302 lastLock = (BPTR) tag->ti_Data;
303 break;
305 case WBOPENA_ArgName:
306 if (lastLock != NULL)
308 BPTR cd = CurrentDir(lastLock);
309 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
310 if (lock != NULL)
312 STRPTR path = AllocateNameFromLock(lock);
313 if (path != NULL)
315 length += 3 /* space + 2 '"' */ + strlen(path);
316 FreeVec(path);
319 UnLock(lock);
322 CurrentDir(cd);
324 break;
328 /*-- Allocate space for command line string ----------------------------*/
329 buffer = AllocVec(length, MEMF_ANY);
331 if (buffer != NULL)
333 buffer[0] = '\0';
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 )
343 switch (tag->ti_Tag)
345 case WBOPENA_ArgLock:
346 lastLock = (BPTR) tag->ti_Data;
347 break;
349 case WBOPENA_ArgName:
350 if (lastLock != NULL)
352 BPTR cd = CurrentDir(lastLock);
353 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
354 if (lock != NULL)
356 STRPTR path = AllocateNameFromLock(lock);
357 if (path != NULL)
359 strcat(buffer, " \"");
360 strcat(buffer, path);
361 strcat(buffer, "\"");
362 FreeVec(path);
365 UnLock(lock);
368 CurrentDir(cd);
370 break;
374 else
376 SetIoErr(ERROR_NO_FREE_STORE);
379 return buffer;
382 BOOL __CLI_LaunchProgram
384 CONST_STRPTR command, struct TagItem *tags,
385 struct WorkbenchBase *WorkbenchBase
388 BPTR input = NULL;
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).
406 SystemTags
408 commandline,
409 SYS_Asynch, TRUE,
410 SYS_Input, (IPTR) input,
411 SYS_Output, (IPTR) NULL,
412 SYS_Error, (IPTR) NULL,
413 NP_StackSize, WorkbenchBase->wb_DefaultStackSize,
414 TAG_DONE
415 ) == -1
418 goto error;
420 FreeVec(commandline);
422 return TRUE;
424 error:
425 if (input != NULL) Close(input);
426 if (commandline != NULL) FreeVec(commandline);
428 return FALSE;
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,
438 *tag = NULL;
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)
446 switch (tag->ti_Tag)
448 case WBOPENA_ArgLock:
449 lastLock = (BPTR) tag->ti_Data;
450 break;
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++;
461 break;
465 /*-- Allocate memory for the arguments ---------------------------------*/
466 args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
467 if (args != NULL)
469 LONG i = 0;
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
480 goto error;
482 i++;
484 tstate = tags; lastLock = NULL;
485 while ((tag = NextTagItem(&tstate)) != NULL)
487 switch (tag->ti_Tag)
489 case WBOPENA_ArgLock:
490 lastLock = (BPTR) tag->ti_Data;
491 break;
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"));
510 goto error;
511 break;
514 else
516 args[i].wa_Lock = NULL;
519 /* Duplicate the name */
520 if (name != NULL)
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"));
527 goto error;
528 break;
531 else
533 args[i].wa_Name = NULL;
536 i++;
538 break;
542 return TRUE;
544 else
546 D(bug("workbench.library: WB_BuildArguments: Failed to allocate memory for argument array\n"));
549 error:
550 D(bug("workbench.library: WB_BuildArguments: Freeing resources after error...\n"));
551 /* Free allocated resources */
552 if (args != NULL)
554 int i;
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;
568 return FALSE;
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();
582 if (startup == NULL)
584 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for startup message\n"));
585 SetIoErr(ERROR_NO_FREE_STORE);
586 goto error;
589 message = CreateWBCM(WBCM_TYPE_LAUNCH);
590 if (message == NULL)
592 D(bug("workbench.library: WB_LaunchProgram: Failed to allocate memory for launch message\n"));
593 SetIoErr(ERROR_NO_FREE_STORE);
594 goto error;
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"));
601 goto error;
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"));
612 return TRUE;
614 error:
615 if (startup != NULL) DestroyWBS(startup);
616 if (message != NULL) DestroyWBCM(message);
618 D(bug("workbench.library: WB_LaunchProgram: Failure\n"));
620 return FALSE;