/* Copyright ) Darin Johnson, 1989 */ /* */ /* Permission is granted to use */ /* this program and to freely copy */ /* it and/or source code as long */ /* as these notices remain. */ /* No charges for these copies may */ /* be made, except for handling */ /* and distribution fees. */ /* This program puts customized menus into the WorkBench menubar. */ /* The program is split up into two parts, MyMenu and MyMenu-Handler. */ /* This section is MyMenu and it initializes and starts up a process */ /* to run MyMenu-Handler, and then terminates. MyMenu also terminates */ /* and cleans up after the suprocess. MyMenu will parse the users */ /* menus, initialize data to be passed to MyMenu-Handler, and start */ /* up MyMenu-Handler. MyMenu-Handler does very little memory */ /* allocation in order to save space, so MyMenu does allocation and */ /* freeing for it. */ #include #include #include #include #include #include #include #include #include #include "mymenu.h" static char *copyright = "Copyright ) Darin Johnson, 1989"; /* actually, I don't know if it will work under Lattice */ #ifdef AZTEC_C #define strcmp _BUILTIN_strcmp #define strcpy _BUILTIN_strcpy #define strlen _BUILTIN_strlen #endif struct IntuitionBase *IntuitionBase = NULL; struct GfxBase *GfxBase = NULL; extern int menu_num; /* this is the data structure that we use to pass data to MyMenu-Handler */ struct MMData *MM; char do_quit; int i; /* make (and allocate) a copy of the passed string */ char *copystr(str) char *str; { char *newstr; newstr = AllocMem(strlen(str)+1, MEMF_PUBLIC); strcpy(newstr, str); return newstr; } /* strcmp, ignoring case */ #define UPPER(c) (islower(c)?toupper(c):(c)) int stricmp(s, t) char *s, *t; { for ( ; UPPER(*s) == UPPER(*t); s++, t++) if (*s== NULL) return 0; return UPPER(*s) - UPPER(*t); } /* Find the workbench window - I'm sure there's a better way... */ struct Window *find_workbench() { struct Screen *scr; struct Window *win; ULONG ilock; ilock = LockIBase(0L); /* just so's things don't change on us */ for (scr = IntuitionBase->FirstScreen; /* find WB Screen */ scr && strcmp(scr->DefaultTitle, "Workbench Screen"); scr=scr->NextScreen); if (!scr) { UnlockIBase(ilock); printf("That's odd... I can't find the workbench screen...\n"); _abort(2000); } for (win=scr->FirstWindow; win; win = win->NextWindow) if (win->Flags & WBENCHWINDOW) break; UnlockIBase(ilock); return win; } /* open a library */ APTR *open_lib(name, rev) char *name; long rev; { APTR *lib; if ((lib = (APTR*)OpenLibrary(name, rev)) == NULL) { printf("Can't open %s (rev=%d\n", name, rev); _abort(1000); } return lib; } /* make a copy of our CLI path. We also convert BCPL stuff. */ copy_path() { register struct Path *oldpath, *newpath, *tmppath; struct CommandLineInterface *cli; struct Process *pr; pr = (struct Process *)FindTask(NULL); cli = (struct CommandLineInterface *)BADDR(pr->pr_CLI); newpath = MM->CLI_path = NULL; for (oldpath = (struct Path *)BADDR(cli->cli_CommandDir); oldpath; oldpath = (struct Path *) BADDR(oldpath->path_Next)) { tmppath = (struct Path *)AllocMem(sizeof(struct Path), MEMF_PUBLIC); if (!MM->CLI_path) { MM->CLI_path = tmppath; } else { newpath->path_Next = tmppath; /* we don't convert to BCPL */ } newpath = tmppath; tmppath->path_Next = NULL; tmppath->path_Lock = DupLock(oldpath->path_Lock); } } /* free up the space used by the copy of the CLI path */ free_path() { register struct Path *tmp, *path; /* clean out copy of path */ path = MM->CLI_path; MM->CLI_path = NULL; while (path) { tmp = path; path = path->path_Next; UnLock(tmp->path_Lock); FreeMem(tmp, sizeof(struct Path)); } } /* Initialize and load up the handler process, or update the menus */ /* for an existing handler. */ add_handler() { ULONG ilock; if (MM) { /* remove old menus and update */ printf("Updating menus -- "); fflush(stdout); /* coordinate with handler */ MM->parent_task = FindTask(NULL); MM->parent_sig = AllocSignal(-1L); Signal(MM->handler_task, SIGBREAKF_CTRL_D); Wait(1 << MM->parent_sig); /* clean old stuff up */ free_menus(); ilock = LockIBase(0L); menu_num = 0; for (MM->prev_menu = MM->WBWindow->MenuStrip; MM->prev_menu->NextMenu; MM->prev_menu=MM->prev_menu->NextMenu) menu_num++; UnlockIBase(ilock); /* get new menus */ if (!parse_menus()) { do_quit = TRUE; return; } /* let handler know it can continue */ Signal(MM->handler_task, SIGBREAKF_CTRL_D); printf("ok\n"); return; } /* create a new handler */ printf("Installing MyMenu -- "); fflush(stdout); /* get area to pass data in */ MM = (struct MMData *)AllocMem(sizeof(struct MMData), MEMF_PUBLIC|MEMF_CLEAR); MM->WBWindow = find_workbench(); if (MM->WBWindow==NULL) { printf("Can't find Workbench...\n"); do_quit = TRUE; return; } /* we need to find out what menu number ours start at */ ilock = LockIBase(0L); menu_num = 0; for (MM->prev_menu = MM->WBWindow->MenuStrip; MM->prev_menu->NextMenu; MM->prev_menu=MM->prev_menu->NextMenu) menu_num++; UnlockIBase(ilock); /* read in user's menus */ if (!parse_menus()) { do_quit = TRUE; return; } MM->port.mp_Flags = PA_IGNORE; /* we'll get msg's from do_wbrun */ MM->port.mp_Node.ln_Pri = 0; MM->port.mp_Node.ln_Type = NT_MSGPORT; MM->port.mp_Node.ln_Name = copystr(MYMENU_NAME); NewList(&MM->port.mp_MsgList); /* load in handler */ MM->segment = LoadSeg("l:MyMenu-Handler"); if (!MM->segment) MM->segment = LoadSeg("MyMenu-Handler"); if (!MM->segment) { printf("Can't find L:MyMenu-Handler\n"); do_quit = TRUE; return; } /* add to port list so that handler can find it */ AddPort(&MM->port); MM->parent_task = FindTask(NULL); MM->parent_sig = AllocSignal(-1L); copy_path(); CreateProc(MYMENU_NAME, 0, MM->segment, STACK); /* handshake so that we know it got started ok */ Wait(1 << MM->parent_sig); FreeSignal(MM->parent_sig); if (MM->error_code) { printf("Handler error (%d)\n", MM->error_code); do_quit = TRUE; } else { printf("ok - %s\n", VERSION); } } /* shutdown and clean up after handler */ remove_handler() { if (!MM) return; printf("removing -- "); fflush(stdout); if (MM->segment != NULL) { MM->parent_task = FindTask(NULL); MM->parent_sig = AllocSignal(-1L); Signal(MM->handler_task, SIGBREAKF_CTRL_C); /* wait until handler cleans up */ /* (don't advertise that we catch ^C - for emergency use only) */ Wait(1 << MM->parent_sig); FreeSignal(MM->parent_sig); if (MM->error_code != ERR_OK) { /* we can get an error if there are outstanding WB processes */ printf("Leaving handler in place...\n"); return; } RemPort(&MM->port); UnLoadSeg(MM->segment); } /* this is done here, not in handler... */ free_path(); free_menus(); if (MM->port.mp_Node.ln_Name) FreeMem(MM->port.mp_Node.ln_Name, strlen(MM->port.mp_Node.ln_Name)+1); FreeMem(MM, sizeof(struct MMData)); printf("done\n"); } /* Close up libraries and exit. Having a routine named _abort() is */ /* handy for use with SDB, otherwise, I would have a better name. */ _abort(st) int st; { if (IntuitionBase) CloseLibrary(IntuitionBase); if (GfxBase) CloseLibrary(GfxBase); exit(st); } main(argc, argv) int argc; char *argv[]; { IntuitionBase = (struct IntuitionBase *)open_lib("intuition.library", 0L); GfxBase = (struct GfxBase *)open_lib("graphics.library", 0L); do_quit=FALSE; for (i=1; i