Make sure Locale dirs exsit before copying icons to them.
[cake.git] / rom / workbench / openworkbenchobjecta.c
blob808716e60d2d6e5b594e63f0aef1bbd9c5b80c89
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Open a drawer or launch a program.
6 */
7 #define DEBUG 0
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
73 BOOL success = FALSE;
74 LONG isDefaultIcon = 42;
76 struct DiskObject *icon = GetIconTags
78 name,
79 ICONGETA_FailIfUnavailable, FALSE,
80 ICONGETA_IsDefaultIcon, (IPTR) &isDefaultIcon,
81 TAG_DONE
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));
90 if (icon != NULL)
92 switch (icon->do_Type)
94 case WBDISK:
95 case WBDRAWER:
96 case WBGARBAGE:
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);
122 else
124 FreeVec((STRPTR)namecopy);
125 DestroyWBHM(wbhm);
126 DestroyWBCM(wbcm);
130 break;
132 case WBTOOL:
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"));
142 !isDefaultIcon
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"));
151 if (lock != NULL)
153 BPTR parent = ParentDir(lock);
155 if (parent != NULL)
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 },
167 { TAG_MORE, (IPTR)tags },
168 { TAG_DONE, 0 }
171 if (tags == NULL)
172 wbp_Tags[1].ti_Tag = TAG_IGNORE;
174 success = WB_LaunchProgram
176 parent, FilePart(name), wbp_Tags
179 if (!success)
182 Fallback to launching it as a CLI program.
183 Most likely it will also fail, but we
184 might get lucky.
186 success = CLI_LaunchProgram(name, wbp_Tags);
189 UnLock(parent);
192 UnLock(lock);
195 else
197 /* It's a CLI program */
199 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
201 success = CLI_LaunchProgram(name, tags);
203 break;
205 case WBPROJECT:
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);
246 if (parent2 != NULL)
248 success = WB_LaunchProgram
250 parent2, FilePart(icon->do_DefaultTool), tags
253 UnLock(parent2);
254 UnLock(lock2);
256 else
258 success = CLI_LaunchProgram
260 icon->do_DefaultTool, tags
264 UnLock(parent);
265 UnLock(lock);
269 if (!success)
271 // FIXME: open execute command?
273 break;
276 FreeDiskObject(icon);
278 else
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();
291 if (cli != NULL)
293 BPTR *paths; /* Path list */
294 BOOL running = TRUE;
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);
307 if (lock != NULL)
309 success = OpenWorkbenchObjectA(name, tags);
310 running = FALSE;
312 UnLock(lock);
315 CurrentDir(cd);
321 D(bug("[WBLIB] OpenWorkbenchObjectA: success = %d\n", success));
323 return success;
325 AROS_LIBFUNC_EXIT
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)
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 length += 3 /* space + 2 '"' */ + strlen(path);
360 FreeVec(path);
363 UnLock(lock);
366 CurrentDir(cd);
368 break;
372 /*-- Allocate space for command line string ----------------------------*/
373 buffer = AllocVec(length, MEMF_ANY);
375 if (buffer != NULL)
377 buffer[0] = '\0';
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 )
387 switch (tag->ti_Tag)
389 case WBOPENA_ArgLock:
390 lastLock = (BPTR) tag->ti_Data;
391 break;
393 case WBOPENA_ArgName:
394 if (lastLock != NULL)
396 BPTR cd = CurrentDir(lastLock);
397 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
398 if (lock != NULL)
400 STRPTR path = AllocateNameFromLock(lock);
401 if (path != NULL)
403 strcat(buffer, " \"");
404 strcat(buffer, path);
405 strcat(buffer, "\"");
406 FreeVec(path);
409 UnLock(lock);
412 CurrentDir(cd);
414 break;
418 else
420 SetIoErr(ERROR_NO_FREE_STORE);
423 return buffer;
426 BOOL __CLI_LaunchProgram
428 CONST_STRPTR command, struct TagItem *tags,
429 struct WorkbenchBase *WorkbenchBase
432 BPTR input = NULL;
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).
455 SystemTags
457 commandline,
458 SYS_Asynch, TRUE,
459 SYS_Input, (IPTR) input,
460 SYS_Output, (IPTR) NULL,
461 SYS_Error, (IPTR) NULL,
462 NP_StackSize, stacksize,
463 TAG_DONE
464 ) == -1
467 goto error;
469 FreeVec(commandline);
471 return TRUE;
473 error:
474 if (input != NULL) Close(input);
475 if (commandline != NULL) FreeVec(commandline);
477 return FALSE;
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,
487 *tag = NULL;
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)
495 switch (tag->ti_Tag)
497 case WBOPENA_ArgLock:
498 lastLock = (BPTR) tag->ti_Data;
499 break;
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++;
510 break;
514 /*-- Allocate memory for the arguments ---------------------------------*/
515 args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
516 if (args != NULL)
518 LONG i = 0;
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
529 goto error;
531 i++;
533 tstate = tags; lastLock = NULL;
534 while ((tag = NextTagItem(&tstate)) != NULL)
536 switch (tag->ti_Tag)
538 case WBOPENA_ArgLock:
539 lastLock = (BPTR) tag->ti_Data;
540 break;
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"));
559 goto error;
560 break;
563 else
565 args[i].wa_Lock = NULL;
568 /* Duplicate the name */
569 if (name != NULL)
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"));
576 goto error;
577 break;
580 else
582 args[i].wa_Name = NULL;
585 i++;
587 break;
591 return TRUE;
593 else
595 D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
598 error:
599 D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
600 /* Free allocated resources */
601 if (args != NULL)
603 int i;
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;
617 return FALSE;
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();
632 if (startup == NULL)
634 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
635 SetIoErr(ERROR_NO_FREE_STORE);
636 goto error;
639 message = CreateWBCM(WBCM_TYPE_LAUNCH);
640 if (message == NULL)
642 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
643 SetIoErr(ERROR_NO_FREE_STORE);
644 goto error;
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"));
659 goto error;
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"));
670 return TRUE;
672 error:
673 if (startup != NULL) DestroyWBS(startup);
674 if (message != NULL) DestroyWBCM(message);
676 D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));
678 return FALSE;