Fixes to typos in comments etc.
[AROS.git] / workbench / libs / workbench / openworkbenchobjecta.c
blobfb56097a7f4f7fea5b7712155d63e5076b4ceb9a
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Open a drawer or launch a program.
6 */
8 #define DEBUG 0
9 #include <aros/debug.h>
11 #include <exec/types.h>
12 #include <exec/ports.h>
13 #include <utility/tagitem.h>
14 #include <intuition/intuition.h>
15 #include <workbench/workbench.h>
16 #include <proto/utility.h>
17 #include <proto/dos.h>
19 #include <string.h>
21 #include "workbench_intern.h"
22 #include "support.h"
23 #include "support_messages.h"
24 #include "handler.h"
25 #include "handler_support.h"
26 #include "uae_integration.h"
28 /*** Prototypes *************************************************************/
29 static BOOL CLI_LaunchProgram(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
30 static STRPTR CLI_BuildCommandLine(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
31 static BOOL WB_LaunchProgram(BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
32 static BOOL WB_BuildArguments(struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
33 static BOOL HandleDrawer(STRPTR name, struct WorkbenchBase *WorkbenchBase);
34 static BOOL HandleTool(STRPTR name, LONG isDefaultIcon, struct DiskObject *icon, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
35 static BOOL HandleProject(STRPTR name, LONG isDefaultIcon, struct DiskObject *icon, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
37 /*****************************************************************************
39 NAME */
41 #include <proto/workbench.h>
43 AROS_LH2(BOOL, OpenWorkbenchObjectA,
45 /* SYNOPSIS */
46 AROS_LHA(STRPTR, name, A0),
47 AROS_LHA(struct TagItem *, tags, A1),
49 /* LOCATION */
50 struct WorkbenchBase *, WorkbenchBase, 16, Workbench)
52 /* FUNCTION
54 INPUTS
56 RESULT
58 NOTES
60 EXAMPLE
62 BUGS
64 SEE ALSO
66 INTERNALS
68 ******************************************************************************/
70 AROS_LIBFUNC_INIT
72 BOOL success = FALSE;
73 LONG isDefaultIcon = 42;
75 struct DiskObject *icon = GetIconTags
77 name,
78 ICONGETA_FailIfUnavailable, FALSE,
79 ICONGETA_IsDefaultIcon, (IPTR) &isDefaultIcon,
80 TAG_DONE
83 ASSERT_VALID_PTR(name);
84 ASSERT_VALID_PTR_OR_NULL(tags);
86 D(bug("[WBLIB] OpenWorkbenchObjectA: name = %s\n", name));
87 D(bug("[WBLIB] OpenWorkbenchObjectA: isDefaultIcon = %ld\n", isDefaultIcon));
89 if( j_uae_running() && is_68k(name, WorkbenchBase) )
92 D(bug("[WBLIB] OpenWorkbenchObjectA: forward %s to uae\n", name));
94 forward_to_uae(tags, name, WorkbenchBase);
95 success = TRUE;
97 else
99 if (icon != NULL)
101 switch (icon->do_Type)
103 case WBDISK:
104 case WBDRAWER:
105 case WBGARBAGE:
106 success = HandleDrawer(name, WorkbenchBase);
107 break;
109 case WBTOOL:
110 success = HandleTool(name, isDefaultIcon, icon, tags, WorkbenchBase);
111 break;
113 case WBPROJECT:
114 success = HandleProject(name, isDefaultIcon, icon, tags, WorkbenchBase);
115 break;
118 FreeDiskObject(icon);
120 else
123 Getting (a possibly default) icon for the path failed, and
124 therefore there is no such file. We need to search the default
125 search path for an executable of that name and launch it. This
126 only makes sense if the name is *not* an (absolute or relative)
127 path: that is, it must not contain any ':' or '/'.
130 if (strpbrk(name, "/:") == NULL)
132 struct CommandLineInterface *cli = Cli();
133 if (cli != NULL)
135 BPTR *paths; /* Path list */
136 BOOL running = TRUE;
138 /* Iterate over all paths in the path list */
141 paths = (BPTR *) BADDR(cli->cli_CommandDir);
142 running == TRUE && paths != NULL;
143 paths = (BPTR *) BADDR(paths[0]) /* next path */
146 BPTR cd = CurrentDir(paths[1]);
147 BPTR lock = Lock(name, SHARED_LOCK);
149 if (lock != BNULL)
151 success = OpenWorkbenchObjectA(name, tags);
152 running = FALSE;
154 UnLock(lock);
157 CurrentDir(cd);
164 D(bug("[WBLIB] OpenWorkbenchObjectA: success = %d\n", success));
166 return success;
168 AROS_LIBFUNC_EXIT
169 } /* OpenWorkbenchObjectA() */
171 /****************************************************************************/
173 static STRPTR CLI_BuildCommandLine
175 CONST_STRPTR command, struct TagItem *tags,
176 struct WorkbenchBase *WorkbenchBase
179 struct TagItem *tstate = tags;
180 struct TagItem *tag = NULL;
181 BPTR lastLock = BNULL;
182 STRPTR buffer = NULL;
183 ULONG length = strlen(command) + 3 /* NULL + 2 '"' */;
185 /*-- Calculate length of resulting string ------------------------------*/
186 while ((tag = NextTagItem(&tstate)) != NULL)
188 switch (tag->ti_Tag)
190 case WBOPENA_ArgLock:
191 lastLock = (BPTR) tag->ti_Data;
192 break;
194 case WBOPENA_ArgName:
195 if (lastLock != BNULL)
197 BPTR cd = CurrentDir(lastLock);
198 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
199 if (lock != BNULL)
201 STRPTR path = AllocateNameFromLock(lock);
202 if (path != NULL)
204 length += 3 /* space + 2 '"' */ + strlen(path);
205 FreeVec(path);
208 UnLock(lock);
211 CurrentDir(cd);
213 break;
217 /*-- Allocate space for command line string ----------------------------*/
218 buffer = AllocVec(length, MEMF_ANY);
220 if (buffer != NULL)
222 buffer[0] = '\0';
224 /*-- Build command line --------------------------------------------*/
225 strcat(buffer, "\"");
226 strcat(buffer, command);
227 strcat(buffer, "\"");
229 tstate = tags; lastLock = BNULL;
230 while ((tag = NextTagItem(&tstate)) != NULL )
232 switch (tag->ti_Tag)
234 case WBOPENA_ArgLock:
235 lastLock = (BPTR) tag->ti_Data;
236 break;
238 case WBOPENA_ArgName:
239 if (lastLock != BNULL)
241 BPTR cd = CurrentDir(lastLock);
242 BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
243 if (lock != BNULL)
245 STRPTR path = AllocateNameFromLock(lock);
246 if (path != NULL)
248 strcat(buffer, " \"");
249 strcat(buffer, path);
250 strcat(buffer, "\"");
251 FreeVec(path);
254 UnLock(lock);
257 CurrentDir(cd);
259 break;
263 else
265 SetIoErr(ERROR_NO_FREE_STORE);
268 return buffer;
271 /****************************************************************************/
273 static BOOL CLI_LaunchProgram
275 CONST_STRPTR command, struct TagItem *tags,
276 struct WorkbenchBase *WorkbenchBase
279 BPTR input = BNULL;
280 STRPTR commandline = NULL;
281 IPTR stacksize = WorkbenchBase->wb_DefaultStackSize;
282 LONG priority = 0;
283 struct TagItem *foundTag = NULL;
285 input = Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE);
286 if (input == BNULL) goto error;
288 commandline = CLI_BuildCommandLine(command, tags, WorkbenchBase);
289 if (commandline == NULL) goto error;
291 if (tags)
293 foundTag = FindTagItem(NP_StackSize, tags);
294 if (foundTag != NULL)
296 stacksize = foundTag->ti_Data;
299 foundTag = FindTagItem(NP_Priority, tags);
300 if (foundTag != NULL)
302 priority = foundTag->ti_Data;
309 Launch the program. Note that there is no advantage of doing this
310 in the handler, since we need to wait for the return value anyway
311 (and thus we cannot cut down the blocking time by returning before
312 the program is loaded from disk).
315 SystemTags
317 commandline,
318 SYS_Asynch, TRUE,
319 SYS_Input, (IPTR) input,
320 SYS_Output, (IPTR) NULL,
321 SYS_Error, (IPTR) NULL,
322 NP_StackSize, stacksize,
323 NP_Priority, priority,
324 TAG_DONE
325 ) == -1
328 goto error;
330 FreeVec(commandline);
332 return TRUE;
334 error:
335 if (input != BNULL) Close(input);
336 if (commandline != NULL) FreeVec(commandline);
338 return FALSE;
341 /****************************************************************************/
343 static BOOL WB_BuildArguments
345 struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags,
346 struct WorkbenchBase *WorkbenchBase
349 struct TagItem *tstate = tags,
350 *tag = NULL;
351 BPTR lastLock = BNULL;
352 struct WBArg *args = NULL;
354 /*-- Calculate the number of arguments ---------------------------------*/
355 startup->sm_NumArgs = 1;
356 while ((tag = NextTagItem(&tstate)) != NULL)
358 switch (tag->ti_Tag)
360 case WBOPENA_ArgLock:
361 lastLock = (BPTR) tag->ti_Data;
362 break;
364 case WBOPENA_ArgName:
366 Filter out args where both lock AND name are NULL, since
367 they are completely worthless to the application.
369 if (lastLock != BNULL || (STRPTR) tag->ti_Data != NULL)
371 startup->sm_NumArgs++;
373 break;
377 /*-- Allocate memory for the arguments ---------------------------------*/
378 args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
379 if (args != NULL)
381 LONG i = 0;
383 startup->sm_ArgList = args;
385 /*-- Build the argument list ---------------------------------------*/
388 (args[i].wa_Lock = DupLock(lock)) == BNULL
389 || (args[i].wa_Name = StrDup(name)) == NULL
392 goto error;
394 i++;
396 tstate = tags; lastLock = BNULL;
397 while ((tag = NextTagItem(&tstate)) != NULL)
399 switch (tag->ti_Tag)
401 case WBOPENA_ArgLock:
402 lastLock = (BPTR) tag->ti_Data;
403 break;
405 case WBOPENA_ArgName:
407 Filter out args where both lock AND name are NULL,
408 since they are completely worthless to the application.
410 if (lastLock != BNULL || (STRPTR) tag->ti_Data != NULL)
412 STRPTR name = (STRPTR) tag->ti_Data;
414 /* Duplicate the lock */
415 if (lastLock != BNULL)
417 args[i].wa_Lock = DupLock(lastLock);
419 if (args[i].wa_Lock == BNULL)
421 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate lock!\n"));
422 goto error;
425 else
427 args[i].wa_Lock = BNULL;
430 /* Duplicate the name */
431 if (name != NULL)
433 args[i].wa_Name = StrDup(name);
435 if (args[i].wa_Name == NULL)
437 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate string!\n"));
438 goto error;
441 else
443 args[i].wa_Name = NULL;
446 i++;
448 break;
452 return TRUE;
454 else
456 D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
459 error:
460 D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
461 /* Free allocated resources */
462 if (args != NULL)
464 int i;
466 for (i = 0; i < startup->sm_NumArgs; i++)
468 if (args[i].wa_Lock != BNULL) UnLock(args[i].wa_Lock);
469 if (args[i].wa_Name != NULL) FreeVec(args[i].wa_Name);
472 FreeMem(args, sizeof(struct WBArg) * startup->sm_NumArgs);
475 startup->sm_NumArgs = 0;
476 startup->sm_ArgList = NULL;
478 return FALSE;
481 /****************************************************************************/
483 static BOOL WB_LaunchProgram
485 BPTR lock, CONST_STRPTR name, struct TagItem *tags,
486 struct WorkbenchBase *WorkbenchBase
489 struct WBStartup *startup = NULL;
490 struct WBCommandMessage *message = NULL;
491 struct TagItem *stackTag = NULL;
492 struct TagItem *prioTag = NULL;
494 /*-- Allocate memory for messages --------------------------------------*/
495 startup = CreateWBS();
496 if (startup == NULL)
498 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
499 SetIoErr(ERROR_NO_FREE_STORE);
500 goto error;
503 message = CreateWBCM(WBCM_TYPE_LAUNCH);
504 if (message == NULL)
506 D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
507 SetIoErr(ERROR_NO_FREE_STORE);
508 goto error;
511 if (tags)
513 stackTag = FindTagItem(NP_StackSize, tags);
514 prioTag = FindTagItem(NP_Priority, tags);
516 if (stackTag || prioTag)
518 message->wbcm_Tags = AllocateTagItems(3);
520 message->wbcm_Tags[0].ti_Tag = stackTag ? stackTag->ti_Tag : TAG_IGNORE;
521 message->wbcm_Tags[0].ti_Data = stackTag->ti_Data;
523 message->wbcm_Tags[1].ti_Tag = prioTag ? prioTag->ti_Tag : TAG_IGNORE;
524 message->wbcm_Tags[1].ti_Data = prioTag->ti_Data;
526 message->wbcm_Tags[2].ti_Tag = TAG_DONE;
530 /*-- Build the arguments array -----------------------------------------*/
531 if (!WB_BuildArguments(startup, lock, name, tags, WorkbenchBase))
533 D(bug("[WBLIB] WB_LaunchProgram: Failed to build arguments\n"));
534 goto error;
537 /*-- Send message to handler -------------------------------------------*/
538 /* NOTE: The handler will deallocate all resources of this message! */
539 message->wbcm_Data.Launch.Startup = startup;
541 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) message);
543 D(bug("[WBLIB] WB_LaunchProgram: Success\n"));
545 return TRUE;
547 error:
548 if (startup != NULL) DestroyWBS(startup);
549 if (message != NULL) DestroyWBCM(message);
551 D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));
553 return FALSE;
556 /****************************************************************************/
558 static BOOL HandleDrawer(STRPTR name, struct WorkbenchBase *WorkbenchBase)
561 Since it's a directory or volume, tell the Workbench
562 Application to open the corresponding drawer.
565 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a DISK, DRAWER or GARBAGE\n"));
567 BOOL success = FALSE;
568 struct WBCommandMessage *wbcm = NULL;
569 struct WBHandlerMessage *wbhm = NULL;
570 CONST_STRPTR namecopy = NULL;
574 (wbcm = CreateWBCM(WBCM_TYPE_RELAY)) != NULL
575 && (wbhm = CreateWBHM(WBHM_TYPE_OPEN)) != NULL
576 && (namecopy = StrDup(name)) != NULL
580 wbhm->wbhm_Data.Open.Name = namecopy;
581 wbcm->wbcm_Data.Relay.Message = wbhm;
583 PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) wbcm);
584 success = TRUE;
586 else
588 FreeVec((STRPTR)namecopy);
589 DestroyWBHM(wbhm);
590 DestroyWBCM(wbcm);
592 return success;
595 /****************************************************************************/
597 static BOOL HandleTool
599 STRPTR name, LONG isDefaultIcon, struct DiskObject *icon,
600 struct TagItem *tags, struct WorkbenchBase *WorkbenchBase
604 It's an executable. Before I launch it, I must check
605 whether it is a Workbench program or a CLI program.
608 BOOL success = FALSE;
610 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a TOOL\n"));
614 !isDefaultIcon
615 && FindToolType(icon->do_ToolTypes, "CLI") == NULL
618 /* It's a Workbench program */
619 BPTR lock = Lock(name, ACCESS_READ);
621 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a WB program\n"));
623 if (lock != BNULL)
625 BPTR parent = ParentDir(lock);
627 if (parent != BNULL)
629 IPTR stacksize = icon->do_StackSize;
631 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
632 stacksize = WorkbenchBase->wb_DefaultStackSize;
634 /* check for TOOLPRI */
635 LONG priority = 0;
636 STRPTR prio_tt = FindToolType(icon->do_ToolTypes, "TOOLPRI");
637 if (prio_tt)
639 StrToLong(prio_tt, &priority);
640 if (priority < -128)
641 priority = -128;
642 if (priority > 127)
643 priority = 127;
646 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize, priority));
648 struct TagItem wbp_Tags[] =
650 { NP_StackSize, stacksize },
651 { NP_Priority, priority },
652 { TAG_MORE, (IPTR)tags },
653 { TAG_DONE, 0 }
656 if (tags == NULL)
657 wbp_Tags[2].ti_Tag = TAG_IGNORE;
659 success = WB_LaunchProgram
661 parent, FilePart(name), wbp_Tags, WorkbenchBase
664 if (!success)
667 Fallback to launching it as a CLI program.
668 Most likely it will also fail, but we
669 might get lucky.
671 success = CLI_LaunchProgram(name, wbp_Tags, WorkbenchBase);
674 UnLock(parent);
677 UnLock(lock);
680 else
682 /* It's a CLI program */
684 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
686 success = CLI_LaunchProgram(name, tags, WorkbenchBase);
689 return success;
692 /****************************************************************************/
694 static BOOL HandleProject
696 STRPTR name, LONG isDefaultIcon, struct DiskObject *icon,
697 struct TagItem *tags, struct WorkbenchBase *WorkbenchBase
700 /* It's a project; try to launch it via its default tool. */
702 BOOL success = FALSE;
704 D(bug("[WBLIB] OpenWorkbenchObjectA: it's a PROJECT\n"));
705 D(bug("[WBLIB] OpenWorkbenchObjectA: default tool: %s\n", icon->do_DefaultTool));
709 icon->do_DefaultTool != NULL
710 && strlen(icon->do_DefaultTool) > 0
713 BPTR lock = BNULL, parent = BNULL;
715 lock = Lock(name, ACCESS_READ);
716 if (lock != BNULL)
717 parent = ParentDir(lock);
718 else
720 * A project icon (without a project file) is actually enough for
721 * original Workbench (i.e. to launch the supplied tool)
724 STRPTR iconname;
725 if ((iconname = AllocVec(strlen(name) + 6, MEMF_ANY)) == NULL)
726 return success;
727 iconname[0] = '\0';
728 strcat(iconname, name);
729 strcat(iconname, ".info");
730 if ((lock = Lock(iconname, ACCESS_READ)) != BNULL)
731 parent = ParentDir(lock);
732 FreeVec(iconname);
734 if (parent != BNULL)
736 IPTR stacksize = icon->do_StackSize;
738 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
739 stacksize = WorkbenchBase->wb_DefaultStackSize;
741 /* check for TOOLPRI */
742 LONG priority = 0;
743 STRPTR prio_tt = FindToolType(icon->do_ToolTypes, "TOOLPRI");
744 if (prio_tt)
746 StrToLong(prio_tt, &priority);
747 if (priority < -128)
748 priority = -128;
749 if (priority > 127)
750 priority = 127;
753 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize, priority));
755 struct TagItem deftool_tags[] =
757 { NP_StackSize , stacksize },
758 { NP_Priority , priority },
759 { WBOPENA_ArgLock , (IPTR) parent },
760 { WBOPENA_ArgName , (IPTR) FilePart(name) },
761 { TAG_MORE , (IPTR) tags },
762 { TAG_DONE , 0 }
765 if (tags == NULL)
766 deftool_tags[4].ti_Tag = TAG_IGNORE;
768 if (FindToolType(icon->do_ToolTypes, "CLI") == NULL)
770 BPTR deftool_lock = BNULL, deftool_parent = BNULL, old_parent = BNULL;
771 BOOL found = FALSE;
773 /* try current dir / absolute path first */
774 deftool_lock = Lock(icon->do_DefaultTool, ACCESS_READ);
775 if (deftool_lock != BNULL)
776 deftool_parent = ParentDir(deftool_lock);
778 if (deftool_parent != BNULL)
780 found = TRUE;
781 success = WB_LaunchProgram
783 deftool_parent, FilePart(icon->do_DefaultTool), deftool_tags, WorkbenchBase
786 UnLock(deftool_parent);
787 UnLock(deftool_lock);
789 if (!found && strpbrk(icon->do_DefaultTool, "/:") == NULL) /* relative path */
791 struct CommandLineInterface *cli = Cli();
792 if (cli != NULL)
794 BPTR *paths; /* Path list */
795 BOOL running = TRUE;
797 /* Iterate over all paths in the path list */
800 paths = (BPTR *) BADDR(cli->cli_CommandDir);
801 running == TRUE && paths != NULL;
802 paths = (BPTR *) BADDR(paths[0]) /* next path */
805 old_parent = CurrentDir(paths[1]);
806 deftool_parent = DupLock(paths[1]);
807 deftool_lock = Lock(icon->do_DefaultTool, SHARED_LOCK);
809 if (deftool_lock != BNULL)
811 success = WB_LaunchProgram
813 deftool_parent, icon->do_DefaultTool, deftool_tags, WorkbenchBase
816 running = FALSE;
818 UnLock(deftool_lock);
819 UnLock(deftool_parent);
821 CurrentDir(old_parent);
826 else
828 success = CLI_LaunchProgram
830 icon->do_DefaultTool, tags, WorkbenchBase
834 UnLock(parent);
835 UnLock(lock);
837 else
838 D(bug("[WBLIB] OpenWorkbenchObjectA: Couldn't get parent dir!\n"));
841 if (!success)
843 // FIXME: open ExecuteCommand?
846 return success;