home *** CD-ROM | disk | FTP | other *** search
- /*
- AddItem
-
- This program was written to add easily some items to the workbench tool menu which can be used to
- cause an action.
-
- You can enter in the ToolTypes of AddItem's icon the
- ITEM TEXT
- COMMAND TEXT
- OUTPUT TEXT .
- Those entries must be separated by the comma, e.g.
- NoTurbo,C:CPU NOCACHE,NIL:
- where "NoTurbo" is the item-text (visible)
- "C:CPU NOCACHE" is the command line (same as in Shell)
- "NIL:" is the stream where the outputs of the
- command should be displayed .
- Please note:
- The command-text itself should be set in quotes when it contains commas, otherwise not. If the
- argument which is supplied for the command contains blanks (" "), the argument itself has to
- stand within double quotes, e.g. C:Type "%s" .
- Please note also:
- Blanks are not skipped! Do not use them at all in front of a CMD-text or Output-text, although
- the DOS will handle it correctly!
-
- ADDITEM=<,,> is the keyword for the tooltypes. Other keywords
- are ignored by "AddItem".
-
- # A D D E D F O R V E R S I O N 2 . 0 O F A D D I T E M
- #
- # For the now comming part you can thank Marc Berson.
- # It was his idea.
- #
- # If the output text is a number (e.g. 4096) the whole entries are interpreted as an argument to
- # force the command part NOT to execute as a single command, instead it is forced to a backgound
- # process.
- #
- # This new background process will get from AddItem a message which is likely the same as a
- # workbench message. Thus its seems for the application that it was started from Workbench and not
- # from CLI! The new keyword to do:
- #
- # ADDITEM=itemname,objectname,stacksize
- #
- # ADDITEM=DOpus,Work:Tools/Opus/DirectoryOpus,20480
- #
- # which means:
- #
- # DOpus - appearing string of the item (visible)
- # Work:Tools/Opus/DirectoryOpus - the full application name
- # 20480 - stacksize for the application
- #
- # Please note:
- # The full application name ╖must not╖ conatian double quotes, e.g.
- # ADDITEM=IntelliFont,"Worbench/System/IntelliFont",4096 - W R O N G !!!
- #
- # use instead: ADDITEM=IntelliFont,Worbench/System/IntelliFont,4096 even
- # when the full application name contains blanks
- #
- # ADDITEM=Replayer,Work:Tools/This Player,4096 - O K !!! where 'This Player' is the name of the
- # object module. Note also: Arguments '%s' for the application aren't allowed (yet).
- #
- # The default I currently use:
- #
- # DONOTWAIT
- # ADDITEM=NewShell,NewShell CON:///130/AmigaShell/AUTO/CLOSE,NIL:
- # ADDITEM=Turn Caches On,C:Cpu CACHE,NIL:
- # ADDITEM=Turn Caches Off,C:Cpu NOCACHE:,NIL:
- # ADDITEM=Lock <> On,C:Lock "%s" ON,NIL:
- # ADDITEM=Lock <> Off,C:Lock "%s" OFF,NIL:
- # ADDITEM=View <>,Run >NIL: <NIL: Work:Tools/Viewer "%s",NIL:
- # ADDITEM=PPaint,Work-II:DTP/PPaint/PPaint,4096
- #
- # The %s specifies the argument passed by workbench. This argument is the current volume, current
- # drawer and current file you have got selected via the mouse. Clearly spoken: It is (are) the
- # active icon(s)!
-
- # Version 2.2 of AddItems allows now to pass an argument to the background process.
-
- To quit AddItem and thus remove the items made by it in the tool menu you can send AddItem a
- CTRL-C (BREAK) signal, or easily, start AddItem again. When started a second time, AddItem(2)
- looks for a created port named as "AddItem's WBench AppPort", if this port is found it will
- signal the task who is the owner of this port a signal (CTRL-C) and thus remove the program
- AddItem(1).
-
- This program was written by Joerg van de Loo
- Hoevel 15
- 47559 Kranenburg
- Germany
-
- It was tested on:
- Amiga 1200, 68030 (EC) 40 MHz, 2MB CHIP, 8 MB FAST, OS3.0, AGA
- Amiga 4000, 68040 25 MHz, 2MB CHIP, 4 MB FAST, OS3.0, AGA
- Amiga 4000, 68040 25 MHz, 2MB CHIP, 16 MB FAST, OS3.0, Picasso96/CV3D
- Draco 68060 66 MHz, 4MB VRAM, 64 MB FAST, OS3.1, CyberGraphX/Altais
-
- !!! Enforcer proofed !!!
-
- Can be linked without "amiga.lib"!
-
- This source-code is Amiga-ROM« specific!
-
- It's placed in the public domain pool as public domain - thus everybody is able to modify this
- program.
-
- Because I don't ask for something, you can't ask for anything. Don't blame me when this material
- bombs your Amiga. All risk is at your own.
-
- */
-
- char VersionString[] = "$VER: AddItem 2.21 (13-Jun-01) Written by ONIX";
- char AIName[] = "AddItem";
- char PortName[] = "AddItem's WBench AppPort";
- char SyntaxTxt[] = "╗Used to add items into Workbench's Tools Menu.½\n" \
- "Use within desk-top 'Icon-Information' and enter for every item:\n" \
- " ADDITEM=<itemtext>,<doscommand>,<output-stream or stacksize>\n";
-
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/ports.h>
- #include <exec/libraries.h>
- #include <exec/memory.h>
- #include <dos/dosextens.h>
- #include <workbench/workbench.h>
- #include <workbench/icon.h>
- #include <workbench/startup.h>
- #include <intuition/intuition.h>
-
- #include <pragma/exec_lib.h>
- #include <pragma/dos_lib.h>
- #include <pragma/intuition_lib.h>
- #include <pragma/icon_lib.h>
- #include <pragma/wb_lib.h>
-
- /* Prototypes please - I don't like to crash my system... */
- #include <stdio.h>
- #include <linkerfunc.h>
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/icon_protos.h>
- #include <clib/wb_protos.h>
-
-
- /* -----------------------------------------------------------------------
- If compiled with Maxon's C++, we have to make the WBenchMsg available!
- */
- #if defined(__MAXON__) || defined (__STORM__)
-
- struct WBStartup *WBenchMsg = NULL; /* Variable */
- extern "C" void wbparse( struct WBStartup *); /* Prototype */
- extern "C" void wbmain( struct WBStartup *ws) /* This is called if we're running from WB */
- {
- WBenchMsg = ws; /* Remember message */
-
- #if defined(__MAXON__)
- wbparse( ws); /* Parse WBench arguments (argv[0....])*/
- #endif
- }
-
- #endif
- /* ----------------------------------------------------------------------- */
-
- extern struct ExecBase *SysBase;
- struct Process *ThisTask;
- struct IntuitionBase *IntuitionBase;
- struct Library *WorkbenchBase;
- struct Library *IconBase;
- struct MsgPort *MsgPort, *Port, *WBPort = NULL;
- extern struct WBStartup *WBenchMsg;
- struct DiskObject *PrgIcon;
- char **ToolTypes;
- UBYTE *ToolText, *ItemTxt, *CMDTxt, *OTxt;
- ULONG SignalSet, WBSignal, LaunchCnt = NULL, ILen, CMDLen, OLen;
- struct stuff *ArrayPtr;
- APTR DummyPtr, CurrItem;
- struct Remember **RememberKey = NULL, *ItemList = NULL, *NextItem = NULL;
- struct AppMenuItem *WBMadeItem;
- struct AppMessage *AMsg, *PMsg;
-
- struct EasyStruct Say =
- {
- sizeof( EasyStruct),
- NULL,
- AIName,
- NULL,
- " Ok "
- };
-
- struct stuff
- {
- APTR TextLinePtr;
- APTR ItemTextPtr;
- APTR CMDTextPtr;
- APTR OutputTextPtr;
- };
-
- struct PseudoMsg {
- struct WBStartup pm_Startup;
- BPTR pm_Lock;
- char *pm_Name;
- BPTR pm_ArgLock;
- char *pm_ArgName;
- char pm_Dir[256];
- char pm_FileName[108];
- char pm_ArgStrName[108];
- };
-
-
- /* Own made ItemList (Intuition Remember Variable -> Memory) holds the pointer to this list, which
- in fact is only a pointer to the added Item! */
-
- struct ilist
- { /* ------------------------ */
- struct AppMenuItem *ilistItem; /* | Intuition Remember Var | -------- */
- ULONG exter; /* Currently not used ------------------------ ---> | Memory | --------- */
- }; /* -------- ---> | AppItem | */
- /* --------- */
-
- /* ######################################## */
- struct localtable
- {
- void *bg;
- int size;
- BPTR o;
- char *bufptr;
- };
-
- void funny_code( register __a0 char *d, register __a1 char *d1, register __a2 char *d2, register __a3 volatile struct localtable *lt, register __d0 volatile char c, register __d1 int *d3, register __d2 int *d4)
- {
- #ifdef __MAXON__
- GetBaseReg();
- #else
- geta4();
- #endif
-
- if (lt->size < 78)
- {
- lt->bufptr[lt->size] = c;
- lt->bufptr[lt->size + 1] = 0;
- lt->size ++;
- }
- else
- {
- if (lt->bufptr[ lt->size - 1] != 0)
- Write( lt->o, lt->bufptr, lt->size );
- else
- Write( lt->o, lt->bufptr, lt->size - 1 );
- lt->bufptr[0] = c;
- lt->bufptr[1] = 0;
- lt->size = 1;
- }
-
- }
-
- #define FUNC (void (*)()) &funny_code /* Code will use: lea funny_code(a4),a2 */
-
- void printfNR( char *s, ...)
- {
- char buf[80], *a;
- struct localtable lt;
-
- lt.bg = 0; // Drop value that the register a4 currently holds!
- lt.size = 0; // No characters stored till now.
- lt.o = Output(); // Result is printed to <whatsoever>
- lt.bufptr = buf; // Address local buffer for characters
-
- if (lt.o)
- {
- (char *) a = (char *) &s; // Address format string on stack
- a += 4; // Address 1st additional argument
- RawDoFmt( s, a, FUNC, ((APTR) <) );
- if (lt.size)
- Write( lt.o, lt.bufptr, lt.size - 1 );
- }
- }
-
- static unsigned int strlenNR( register const unsigned char *str)
- {
- register unsigned int i = 0;
-
- while (*str++)
- i++;
- return i;
- }
-
- static void strncpyNR( register unsigned char *d, register const unsigned char *s, register unsigned int i)
- {
- while (i)
- {
- *d++ = *s++;
- i--;
- }
- *d = 0;
- }
-
- static void strcpyNR( register unsigned char *d, register const unsigned char *s)
- {
- while (*s)
- *d++ = *s++;
- *d = 0;
- }
-
- static unsigned int strcmpNR( register unsigned char *d, register const unsigned char *s)
- {
- while (*s)
- {
- if (*d++ != *s++)
- break;
- }
-
- if ( !*s && !*d)
- return FALSE;
- else
- return TRUE;
- }
-
- static unsigned int strncmpNR( register unsigned char *d, register const unsigned char *s, register unsigned int i)
- {
- while (i)
- {
- if (*d++ != *s++)
- break;
- i--;
- }
-
- return i;
- }
-
- static char *strchrNR( char *s, char c)
- {
- while (*s)
- {
- if (*s++ == c)
- break;
- }
-
- if (s[-1] == c)
- return s - 1;
- else
- return 0;
- }
-
- /* ######################################## */
- void CloseThem( void)
- {
- if (ItemList)
- {
- NextItem = (struct Remember *) ItemList; /* Intuition made list... */
-
- while (1)
- {
- CurrItem = NextItem -> Memory; /* Pointer to memory which holds
- the address of the created Item */
- RemoveAppMenuItem( ( (struct ilist *) CurrItem) -> ilistItem);
- NextItem = (struct Remember *) NextItem -> NextRemember;
- if ( !(NextItem) )
- break;
- }
-
- FreeRemember( &ItemList, TRUE);
- }
-
- if (RememberKey)
- FreeRemember( (struct Remember **) &RememberKey, TRUE);
-
- if (PrgIcon)
- FreeDiskObject( PrgIcon);
-
- if (MsgPort) /* Did we create a MessagePort ? */
- {
- Port = (struct MsgPort *) FindPort( PortName); /* Find public port */
- if ( Port == MsgPort) /* Public port and our private port the same ? */
- RemPort( MsgPort); /* If so, remove public port from list of ports */
- DeleteMsgPort( MsgPort); /* Free our private port */
- }
-
- if (IconBase)
- CloseLibrary( IconBase);
-
- if (WorkbenchBase)
- CloseLibrary( WorkbenchBase);
-
- if (IntuitionBase)
- CloseLibrary( (struct Library *) IntuitionBase);
- }
-
- /* ######################################## */
- void RemMessage( struct PseudoMsg *msg)
- {
- LaunchCnt --;
- UnLock( msg -> pm_Lock);
- UnLoadSeg( msg -> pm_Startup . sm_Segment);
-
- if (msg -> pm_ArgLock != -1)
- UnLock( msg->pm_ArgLock);
-
- FreeMem( msg, sizeof (PseudoMsg) );
-
- if ( !( LaunchCnt))
- {
- DeleteMsgPort( WBPort);
- WBPort = NULL;
- }
- }
-
- /* ######################################## */
- void tell( STRPTR Txt)
- {
- if (IntuitionBase)
- {
- Say.es_TextFormat = Txt;
- EasyRequestArgs( NULL, &Say, NULL, NULL);
- }
-
- printfNR("%s: %s\n", AIName, Txt);
- }
-
- /* ######################################## */
- void closeall( void)
- {
- struct Message *msg;
-
- if ( !(WBPort) ) /* No pseudo WBench port ? */
- {
- CloseThem();
- exit(0);
- }
- else
- {
- tell( "Cannot terminate yet completely - there\n"
- "are still some \"launched\" programs.\n"
- "Don't forget to terminate them later.");
-
- /* Free the stuff we don't need anymore */
- CloseThem();
- /* ... and wait for all processes we created and which are still running */
- while ( LaunchCnt)
- {
- WaitPort( WBPort);
- msg = (struct Message *) GetMsg( WBPort);
- if (msg)
- RemMessage( (struct PseudoMsg *) msg);
- }
-
- exit(0);
- }
- }
-
- /* ######################################## */
- void bailoutold( ULONG err, STRPTR errTxt)
- {
- printfNR("%s missed: %s\n", AIName, errTxt);
- ThisTask = (struct Process *) FindTask( NULL);
- ThisTask -> pr_Result2 = err;
- exit( err);
- }
-
- /* ######################################## */
- void bailout( ULONG err, STRPTR errTxt)
- {
- if (IntuitionBase)
- {
- Say.es_TextFormat = errTxt;
- EasyRequestArgs( NULL, &Say, NULL, NULL);
- }
-
- printfNR("%s missed: %s\n", AIName, errTxt);
- CloseThem();
- ThisTask = (struct Process *) FindTask( NULL);
- ThisTask -> pr_Result2 = err;
- exit( err);
- }
-
- /* ######################################## */
- void FreeCmdStuff(APTR memoryBlock, BPTR output)
- {
- if (memoryBlock)
- FreeMem( memoryBlock, 1024);
- if (output)
- Close( output);
- }
-
-
- /* ######################################## */
- char * GetStrName( struct stuff *array)
- {
- char *nm;
- ULONG len;
-
- nm = array -> CMDTextPtr;
- len = strlenNR( nm);
- len -= 1;
- nm = nm + len;
-
- while ( len)
- {
- if (nm[-1] == '/')
- break;
- if (nm[-1] == ':')
- break;
- len -= 1;
- nm --;
- }
-
- return nm;
- }
-
- /* ######################################## */
- void RHook( register __d0 char c, register __a3 UBYTE *buf)
- {
- *buf++ = c; /* move.b d0,(a3)+ */
- } /* rts */
-
- /* ######################################## */
- /* Format CMD-txt with argument,
- Lock "%s" On -> Lock "Workbench:" On */
-
- void FormatStr( struct stuff *stuff, APTR fmt, UBYTE *ResultStr)
- {
- RawDoFmt( stuff -> CMDTextPtr, fmt, (APTR) &RHook, ResultStr)
- }
-
-
- /* ######################################## */
- #ifndef MTYPE_APPMENUITEM
- #define MTYPE_APPMENUITEM AMTYPE_APPMENUITEM
- #endif
-
- void CallFunc( struct AppMessage *appmsg)
- {
- struct stuff *array; /* <- the things we remembered in the user-data field... */
- BPTR output = NULL, OldDir = NULL;
- UBYTE *memblock = NULL, *ExecuteStr;
- ULONG dummy;
- LONG numArgs;
- APTR **argLock, **argName;
- ULONG stackSize = NULL;
- BPTR lockSave = NULL;
- struct MsgPort *procPort = NULL;
- STRPTR procName;
-
- if (appmsg == NULL)
- return;
- if (appmsg -> am_Type != MTYPE_APPMENUITEM)
- return;
-
- /* Lets first check if the output-text is a value, if it is, treat argument (value) as
- indicator for a workbench start. */
-
-
- StrToLong( ((struct stuff *) appmsg -> am_UserData) -> OutputTextPtr, (LONG *) &stackSize);
- if (!stackSize)
- {
- /* Normal DOS-execute stuff. We need a buffer of 1KB... - for:
- -----------------------------
- | Volume's/directory's name | 256 bytes
- -----------------------------
- | Filename | 256 bytes
- -----------------------------
- | Merged command-string |
- | with those both strings | 512 bytes = string to execute!
- -----------------------------
- */
- if ( (memblock = (APTR) AllocMem( 1024, MEMF_CLEAR) ))
- {
- /* The argument submitted to us is merged with the command-string, this
- is the buffer for it, 512 Bytes - hopefully enought... */
- ExecuteStr = memblock + 512; /* Room (512 bytes) behind 512 bytes for name */
-
- array = (struct stuff *) appmsg -> am_UserData; /* Get array of pointer-table... */
-
- if ( (output = Open( array -> OutputTextPtr, MODE_NEWFILE) )); /* Open specified output */
- {
- numArgs = appmsg -> am_NumArgs;
- argLock = (APTR) &(appmsg -> am_ArgList -> wa_Lock);
- argName = (APTR) &(appmsg -> am_ArgList -> wa_Name);
-
- while (1)
- {
- OldDir = NULL; /* Indicates staying on home-lock - there were we
- started from */
-
- strcpyNR( memblock, "SYS:"); /* Default when nothing is picked... */
- memblock[4] = NULL; /* May remove - only for savety... */
-
- if (numArgs) /* Any argument ? */
- {
- if (argLock[0]) /* The volume/directory name */
- {
- /* Get volume's/directory's name, store it into first 256 bytes
- of buffer */
- NameFromLock( (BPTR) argLock[0], memblock, 255L);
- OldDir = CurrentDir( (BPTR) argLock[0]); /* Change also directory... */
- }
-
- dummy = strlenNR( memblock); /* Length of name */
- dummy -= 1; /* minus 1 so that memblock[dummy] points to the last
- valid char of string */
- if ( memblock[dummy] != ':' && memblock[dummy] != '/')
- {
- dummy += 1; /* Strlength plus 1 */
- memblock[dummy] = '/'; /* Add this char at end of string */
- }
- /* Copy the name of the file right at the end of the
- volume's/diretory's name... */
-
- if (argName[0]) /* Name of file set? */
- strncpyNR( &memblock[dummy + 1], (char *) argName[0], 255L);
-
- /* printfNR("Name of object: %s\n", memblock); <- can be used for debugging... */
- }
-
- dummy = (ULONG) memblock; /* dummy is used as fmt-array for RawDoFmt() ! */
-
- FormatStr( array, &dummy, ExecuteStr); /* Format CMD-text... */
-
- /* I do not test here if the command was executed because against
- the documentation Execute() does ever return BOOL-ok on my machine! */
- Execute( ExecuteStr, NULL, output); /* Execute command... */
- dummy = IoErr(); /* Was function Execute() succesful ? */
- if (dummy)
- tell("Cannot execute command or\n"
- "command returned an error!");
-
- if (OldDir)
- CurrentDir( OldDir); /* If we don't restore the original lock
- the DOS will refer to an invalid lock
- -- hello Guru! */
-
- /* Lets say you want to open a NewShell. In this case you don't need any args
- (%s). But it might be that some icons are picked while you choose NewShell
- from the menu. Because some icons are picked, numArg is taller NULL - this
- means as much icons are selected as many 'NewShells' are created. To avaiod
- this I check if the command string is as long as the string which is
- executed, if it is, there can't be (?!?!) an arg (%s) thus we can leave the
- routine here - only once executed.... */
-
- if ( (strlenNR( ExecuteStr) == strlenNR( array -> CMDTextPtr)) )
- break;
-
- argLock += 2; /* Pointer to next lock */
- argName += 2; /* Pointer to next name */
- numArgs -= 1; /* One less to work out */
- if (numArgs <= NULL)
- break; /* If zero or -1 break */
- }
-
- FreeCmdStuff( memblock, output);
- return /* Back */
- }
-
- tell("Error while opening output terminal respectively file");
- FreeCmdStuff( memblock, output);
- return;
- }
-
- tell("Cannot allocate buffer for application-command!");
- return;
- }
- else
- {
-
- /* ----------------- Up from here the stuff to emulate a workbench start ----------- */
-
- if ( (memblock = (APTR) AllocMem( sizeof( PseudoMsg), MEMF_CLEAR) ))
- {
- /* If the WBench Pseudo port doesn't exists, create it! */
- if ( !( WBPort) )
- WBPort = (struct MsgPort *) CreateMsgPort();
- if ( WBPort)
- {
- /* Get out of array the private pointer table for the item */
- array = (struct stuff *) appmsg -> am_UserData;
-
- /* Extract out of full filename (which includes the pathname) the object (PRG) name */
- procName = (STRPTR) GetStrName( array);
-
- /* Get length of drawer and path part of filename */
- dummy = strlenNR(procName);
- dummy = strlenNR( array -> CMDTextPtr) - dummy;
-
- /* Copy drawer and path part to private buffer (e.g. "SYS:SYSTEM/") */
- strncpyNR( ((struct PseudoMsg *) memblock) -> pm_Dir, array -> CMDTextPtr, dummy);
-
- /* Lock the drawer and path (directory) */
- lockSave = Lock( ((struct PseudoMsg *) memblock) -> pm_Dir, ACCESS_READ);
- if (lockSave)
- {
- /* Store lock into variable which can be reach via "wa_Lock" from the application */
- ((struct PseudoMsg *) memblock) -> pm_Lock = lockSave;
- /* Change also the directory */
- OldDir = CurrentDir( lockSave);
- }
-
- /* Copy PRG-name into private buffer which can the application reach via "wa_Name" */
- strcpyNR( &((struct PseudoMsg *) memblock) -> pm_FileName[0], procName );
- (APTR) ((struct PseudoMsg *) memblock) -> pm_Name = & ((struct PseudoMsg *) memblock) -> pm_FileName;
-
- /* Load the object file and store the "Segments" of it in the messsage - so that
- the application can examine it for its own use and we to unload the prg */
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Segment = LoadSeg( procName);
-
- /* Successfully loaded in? */
- if ( ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Segment)
- {
- Forbid();
- /* Create a process via function "CreateProc()".
- Remember returned MsgPort of this new created process. */
- procPort = (struct MsgPort *) CreateProc( procName, 0,
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Segment,
- stackSize);
- /* Process created? */
- if (procPort)
- {
- /* Setup message with new created process' MsgPort */
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Process = (struct MsgPort *) procPort;
-
- /* Setup Home directory (PROGDIR:) */
- (char *) ThisTask = (char *) procPort - sizeof( struct Task);
- ThisTask -> pr_HomeDir = lockSave;
-
- /* ReplyPort to send back the message is our MsgPort 'WBPort' */
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Message . mn_ReplyPort = WBPort;
-
- /* How tall is the message we will send to the new created process? */
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Message . mn_Length = sizeof( PseudoMsg);
-
- /* We pass one argument to the new process: The lock of its directory
- and the PRG-name itself */
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_NumArgs = 1;
- ((struct PseudoMsg *) memblock) -> pm_ArgLock = -1;
-
- /* Check if we should pass one, single argument to the application we're
- going to fire up */
- if (appmsg->am_NumArgs)
- {
- ((struct PseudoMsg *) memblock) -> pm_ArgLock = DupLock( appmsg -> am_ArgList[0] . wa_Lock);
- strcpyNR( & ((struct PseudoMsg *) memblock) -> pm_ArgStrName[0], appmsg -> am_ArgList[0] . wa_Name);
- ((struct PseudoMsg *) memblock) -> pm_ArgName = & ((struct PseudoMsg *) memblock) -> pm_ArgStrName[0];
- ((struct PseudoMsg *) memblock) -> pm_Startup . sm_NumArgs = 2;
- }
-
- /* sm_ArgList is setup with the address of pm_Lock (wa_Lock!) */
- (APTR) ((struct PseudoMsg *) memblock) -> pm_Startup . sm_ArgList = & ((struct PseudoMsg *) memblock) -> pm_Lock;
-
- /* Now, send the message to the process */
- PutMsg( procPort, (struct Message *) memblock);
-
- /* Increase counter or number of created processes */
- LaunchCnt ++;
-
- /* Restore our (AddItem's) PROG-DIR */
- if ( OldDir)
- CurrentDir( OldDir);
-
- Permit();
- return; /* Done */
-
- /* ------------- ERROR OCCURRED !!! --------------- */
- }
-
- Permit();
- tell("DOS-function CreateProc() failed -\n"
- "thus cannot create process!");
- UnLoadSeg( ((struct PseudoMsg *) memblock) -> pm_Startup . sm_Segment);
-
- }
-
- if ( OldDir)
- CurrentDir( OldDir);
- if (lockSave)
- UnLock( lockSave);
- if ( ! (((struct PseudoMsg *) memblock) -> pm_Startup . sm_Segment))
- tell("Cannot load the programm-code!");
- if ( !(LaunchCnt) && (WBPort) )
- DeleteMsgPort( WBPort);
-
- }
-
- if ( !(WBPort))
- tell("Cannot create \"ReplyPort\" for \"Pseudo WBench-message\"");
- if ( !(LaunchCnt))
- WBPort = NULL;
- }
-
- if ( !(memblock))
- tell("Cannot allocate memory for \"Pseudo WBench-message\"");
- else
- FreeMem( memblock, sizeof( PseudoMsg));
- }
- }
-
- /* #################### main ################## */
-
- ULONG main( ULONG argc, APTR **argv)
- {
- if (argc > 1)
- {
- if ( strcmpNR( (char *) argv[1], "?") == NULL )
- {
- printfNR("%s: %s", AIName, SyntaxTxt);
- return 5;
- }
- }
-
- if ( SysBase -> LibNode . lib_Version < 37 )
- bailoutold(122, "Wrong OS-Version! Need at least KS 2.04 .");
-
- IntuitionBase = (struct IntuitionBase *) OldOpenLibrary( "intuition.library");
-
- if ( !( WorkbenchBase = (struct Library *) OldOpenLibrary( "workbench.library") ))
- bailout( 122, "Cannot open \"workbench.library\" !");
-
- if ( !( IconBase = (struct Library *) OpenLibrary( "icon.library", 33) ))
- bailout( 122, "Cannot open \"icon.library\" !");
-
- if ( ((struct Process *) FindTask( NULL)) -> pr_StackSize < 3072 )
- bailout( 20, "Cannot run: Stacksize set too low!");
-
- /* If there is an existing port with the name "AddItem's WBench AppPort" signal the owner of
- this port his end, do it via a CTRL-C signal. */
- if ( (Port = (struct MsgPort *) FindPort( PortName) ))
- {
- Signal( Port->mp_SigTask, 0x1000); /* CTRL-BREAK */
- bailout( 5, "Removing existing AddItem program\n"
- "and terminating myself!");
- }
-
- if ( !( MsgPort = (struct MsgPort *) CreateMsgPort() ))
- bailout( 20, "Cannot create message port!");
-
- MsgPort->mp_Node.ln_Name = PortName;
- MsgPort->mp_Node.ln_Pri = 1;
- AddPort( MsgPort);
-
- /* Now we read the diskobject (icon-structure plus set strings) */
- if (WBenchMsg)
- {
- if (WBenchMsg -> sm_ArgList -> wa_Lock)
- CurrentDir(WBenchMsg -> sm_ArgList -> wa_Lock);
-
- if ( !(PrgIcon = (struct DiskObject *) GetDiskObject( WBenchMsg -> sm_ArgList -> wa_Name) ))
- bailout(205, "Cannot find program specific icon!");
- }
- else
- {
- /* We were called from CLI/Shell - so argv[0] contains our path and name,
- thus we can use it to load our own program-icon. */
- if ( !(PrgIcon = (struct DiskObject *) GetDiskObject( (UBYTE *) argv[0]) ))
- bailout(205, "Cannot find program specific icon!");
- }
-
- ToolTypes = PrgIcon -> do_ToolTypes;
-
- /* Is there a tooltype which matches with "ADDITEM" ? */
- if ( !(ToolText = (UBYTE *) FindToolType( (UBYTE **) ToolTypes, "ADDITEM") ))
- bailout( 20, "Not even one tool entry which\n"
- "matches with \"ADDITEM\" !");
-
- /* Now get all strings which are introduced by the text "ADDITEM" ! */
- while (1)
- {
- if ( strncmpNR( ToolTypes[0], "ADDITEM=", 8) == NULL )
- {
- ToolText = (UBYTE *) ToolTypes[0];
-
- ItemTxt = ToolText + 8; /* Pointer to char behind the "=" char */
-
- if ( !( CMDTxt = (UBYTE *) strchrNR( ItemTxt, ',') )) /* Search for a comma */
- bailout( 20, "Missing command part!");
-
- OTxt = NULL; /* Both are used also as flags... */
- CMDLen = NULL;
-
- CMDTxt ++; /* Skip comma */
-
- if ( CMDTxt[0] == '"') /* Command part within quotes? */
- {
- CMDTxt ++; /* Skip quote */
- CMDLen = -1L; /* Skip also unquote! */
-
- if ( !(OTxt = (UBYTE *) strchrNR( CMDTxt, '"') )) /* Find unquote... */
- bailout( 20, "Invalid number of double quotes\n"
- "set within command part!");
-
- if ( OTxt[1] != ',') /* The next char the comma ? */
- bailout( 20, "Missing output part!");
-
- OTxt = OTxt + 2; /* Skip unquote and comma */
- }
-
- ILen = CMDTxt - ItemTxt - 1;
-
- if ( !(OTxt) ) /* OTxt already set (when in quotes) ? */
- {
- if ( !(OTxt = (UBYTE *) strchrNR( CMDTxt, ',') )) /* Search for 2nd comma... */
- bailout( 20, "Missing command part!");
- OTxt ++; /* Skip comma */
- }
- else
- {
- ILen --; /* otherwise CMDTxt within quotes so correct ILen! */
- }
-
- CMDLen = CMDLen + ( OTxt - CMDTxt - 1);
- OLen = strlenNR( OTxt );
-
- /* Now we allocate an array where we can store the yet computed
- things; when we create ( see below) a MenuItem the user-data
- field of it points to this array. */
- ArrayPtr = (APTR) AllocRemember( (struct Remember **) &RememberKey, sizeof( stuff) +
- strlenNR(ToolText) + 1 +
- ILen + 1 +
- CMDLen + 1 +
- OLen + 1, MEMF_CLEAR);
- if ( !(ArrayPtr) )
- bailout( 103, "Error while allocating the Item-stuff!");
-
- /* Pointer to buffer for strings right behind pointer table! */
- DummyPtr = (UBYTE *) ArrayPtr + sizeof( stuff);
- /* TextLinePtr points to the buffer... */
- ArrayPtr ->TextLinePtr = DummyPtr;
- /* Copy string to buffer... */
- CopyMem( ItemTxt, DummyPtr, strlenNR( ItemTxt) );
-
- /* Buffer = Buffer + strlenNR(Buffer) + 1 */
- DummyPtr = (UBYTE *) DummyPtr + strlenNR( ToolText) + 1;
- /* ItemTextPtr = Buffer */
- ArrayPtr -> ItemTextPtr = DummyPtr;
- /* Copy string to Buffer */
- CopyMem( ItemTxt, DummyPtr, ILen );
-
- /* Pointer to next free pool of buffer */
- DummyPtr = (UBYTE *) DummyPtr + ILen + 1;
- /* CMDTextPtr = Buffer */
- ArrayPtr -> CMDTextPtr = DummyPtr;
- /* Copy string to Buffer */
- CopyMem( CMDTxt, DummyPtr, CMDLen );
-
- /* Pointer to next free pool of buffer */
- DummyPtr = (UBYTE *) DummyPtr + CMDLen + 1;
- /* OutputTextPtr = Buffer */
- ArrayPtr -> OutputTextPtr = DummyPtr;
- /* Copy string to buffer */
- CopyMem( OTxt, DummyPtr, OLen );
-
- /* Can be used for debugging....
- printfNR("Original: %s\n Item= %s, Cmd= %s, Out= %s\n",
- ArrayPtr -> TextLinePtr,
- ArrayPtr -> ItemTextPtr,
- ArrayPtr -> CMDTextPtr,
- ArrayPtr -> OutputTextPtr ); */
-
- /* Now we allocate an array where we can store the address of the created MenuItem made
- with function AddAppMenuItemA(); we need only 4 bytes but the minimum for allocation
- should ever be 8 */
-
- CurrItem = (APTR) AllocRemember( &ItemList, sizeof( ilist), MEMF_CLEAR);
- if ( !(CurrItem) )
- bailout( 103, "Cannot allocate linked list for Items!");
-
- /* Create a item in the tool-menu.... */
- WBMadeItem = (struct AppMenuItem *)
- AddAppMenuItemA( NULL, (ULONG) ArrayPtr, ArrayPtr -> ItemTextPtr, MsgPort, NULL);
- if (WBMadeItem == NULL)
- bailout( 20, "Workbench said: Cannot create Item...");
-
- /* Remember Item (created) in allocated array... */
- ((struct ilist *) CurrItem) -> ilistItem = WBMadeItem;
-
- ToolTypes ++; /* Next tool-entry */
- }
- else
- {
- ToolTypes ++; /* Wasn't "ADDITEM=" so point only to next tool-entry */
- }
-
- if (ToolTypes[0] == NULL)
- break; /* No next entry ? */
- }
-
- while (1)
- {
- if (WBPort) /* Workbench port set (to emulate WBStart?) */
- {
- WBSignal = WBPort->mp_SigBit; /* If so, get sigbit of WBPort */
- WBSignal = 1 << WBSignal; /* Convert it into mask */
- }
-
- SignalSet = MsgPort->mp_SigBit; /* Get Sigbit of msg-port */
- SignalSet = 1 << SignalSet; /* Convert it into mask */
- SignalSet |= 0x1000; /* Add also CTRL-C */
-
- if (WBPort) /* Emulate WBStart ? */
- SignalSet |= WBSignal; /* If so, wait also for the reply of messages */
-
- SignalSet = Wait( SignalSet); /* Wait for signals */
-
- if ( (SignalSet & 0x1000) == 0x1000) /* CTRL-C ? */
- {
- closeall();
- exit(0);
- }
-
- if (WBPort)
- {
- if ( (SignalSet & WBSignal) == WBSignal) /* A reply ? */
- {
- while ( WBPort && (PMsg = (APTR) GetMsg( WBPort)) )
- RemMessage( (struct PseudoMsg *) PMsg);
- }
- }
-
- if ( (SignalSet & (1 << MsgPort->mp_SigBit)) == (1 << MsgPort->mp_SigBit) )
- {
- /* Else a WBench-Item message */
- while ( (AMsg = (struct AppMessage *) GetMsg( MsgPort)) )
- {
- CallFunc( AMsg); /* Do something with that message... */
- ReplyMsg( (struct Message *) AMsg);
- }
- }
- }
- }
-