home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff225.lzh / MyMenu / MyMenu.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  9KB  |  315 lines

  1. /* Copyright ) Darin Johnson, 1989 */
  2. /*                                 */
  3. /* Permission is granted to use    */
  4. /* this program and to freely copy */
  5. /* it and/or source code as long   */
  6. /* as these notices remain.        */
  7. /* No charges for these copies may */
  8. /* be made, except for handling    */
  9. /* and distribution fees.          */
  10.  
  11. /* This program puts customized menus into the WorkBench menubar.      */
  12. /* The program is split up into two parts, MyMenu and MyMenu-Handler.  */
  13. /* This section is MyMenu and it initializes and starts up a process   */
  14. /* to run MyMenu-Handler, and then terminates.  MyMenu also terminates */
  15. /* and cleans up after the suprocess.  MyMenu will parse the users     */
  16. /* menus, initialize data to be passed to MyMenu-Handler, and start    */
  17. /* up MyMenu-Handler.  MyMenu-Handler does very little memory          */
  18. /* allocation in order to save space, so MyMenu does allocation and    */
  19. /* freeing for it.                                                     */
  20.  
  21. #include <exec/types.h>
  22. #include <exec/memory.h>
  23. #include <graphics/gfxbase.h>
  24. #include <intuition/intuitionbase.h>
  25. #include <libraries/dos.h>
  26. #include <libraries/dosextens.h>
  27. #include <functions.h>
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include "mymenu.h"
  31.  
  32. static char *copyright = "Copyright ) Darin Johnson, 1989";
  33.  
  34. /* actually, I don't know if it will work under Lattice */
  35. #ifdef AZTEC_C
  36. #define strcmp _BUILTIN_strcmp
  37. #define strcpy _BUILTIN_strcpy
  38. #define strlen _BUILTIN_strlen
  39. #endif
  40.  
  41. struct IntuitionBase *IntuitionBase = NULL;
  42. struct GfxBase *GfxBase = NULL;
  43.  
  44. extern int menu_num;
  45.  
  46. /* this is the data structure that we use to pass data to MyMenu-Handler */
  47. struct MMData *MM;
  48.  
  49. char do_quit;
  50. int i;
  51.  
  52. /* make (and allocate) a copy of the passed string */
  53. char *copystr(str)
  54. char *str;
  55. {
  56.   char *newstr;
  57.   newstr = AllocMem(strlen(str)+1, MEMF_PUBLIC);
  58.   strcpy(newstr, str);
  59.   return newstr;
  60. }
  61.  
  62. /* strcmp, ignoring case */
  63. #define UPPER(c) (islower(c)?toupper(c):(c))
  64. int stricmp(s, t)
  65.   char *s, *t;
  66. {
  67.   for ( ; UPPER(*s) == UPPER(*t); s++, t++)
  68.     if (*s== NULL)
  69.       return 0;
  70.   return UPPER(*s) - UPPER(*t);
  71. }
  72.  
  73. /* Find the workbench window - I'm sure there's a better way... */
  74. struct Window *find_workbench() {
  75.   struct Screen *scr;
  76.   struct Window *win;
  77.   ULONG ilock;
  78.   ilock = LockIBase(0L);    /* just so's things don't change on us */
  79.   for (scr = IntuitionBase->FirstScreen;    /* find WB Screen */
  80.        scr && strcmp(scr->DefaultTitle, "Workbench Screen");
  81.        scr=scr->NextScreen);
  82.   if (!scr) {
  83.     UnlockIBase(ilock);
  84.     printf("That's odd...  I can't find the workbench screen...\n");
  85.     _abort(2000);
  86.   }
  87.   for (win=scr->FirstWindow; win; win = win->NextWindow)
  88.     if (win->Flags & WBENCHWINDOW) break;      
  89.   UnlockIBase(ilock);
  90.   return win;
  91. }
  92.  
  93. /* open a library */
  94. APTR *open_lib(name, rev)
  95. char *name;
  96. long rev;
  97. {
  98.   APTR *lib;
  99.   if ((lib = (APTR*)OpenLibrary(name, rev)) == NULL) {
  100.     printf("Can't open %s (rev=%d\n", name, rev);
  101.     _abort(1000);
  102.   }
  103.   return lib;
  104. }
  105.  
  106. /* make a copy of our CLI path.  We also convert BCPL stuff. */
  107. copy_path() {
  108.   register struct Path *oldpath, *newpath, *tmppath;
  109.   struct CommandLineInterface *cli;
  110.   struct Process *pr;
  111.   
  112.   pr = (struct Process *)FindTask(NULL);
  113.   cli = (struct CommandLineInterface *)BADDR(pr->pr_CLI);
  114.   newpath = MM->CLI_path = NULL;
  115.   for (oldpath = (struct Path *)BADDR(cli->cli_CommandDir); oldpath;
  116.               oldpath = (struct Path *) BADDR(oldpath->path_Next)) {
  117.     tmppath = (struct Path *)AllocMem(sizeof(struct Path), MEMF_PUBLIC);
  118.     if (!MM->CLI_path) {
  119.       MM->CLI_path = tmppath;
  120.     } else {
  121.       newpath->path_Next = tmppath;    /* we don't convert to BCPL */
  122.     }
  123.     newpath = tmppath;
  124.     tmppath->path_Next = NULL;
  125.     tmppath->path_Lock = DupLock(oldpath->path_Lock);
  126.   }
  127. }
  128.  
  129. /* free up the space used by the copy of the CLI path */
  130. free_path() {
  131.   register struct Path *tmp, *path;
  132.       /* clean out copy of path */
  133.   path = MM->CLI_path;
  134.   MM->CLI_path = NULL;
  135.   while (path) {
  136.     tmp = path;
  137.     path = path->path_Next;
  138.     UnLock(tmp->path_Lock);
  139.     FreeMem(tmp, sizeof(struct Path));
  140.   }
  141. }
  142.  
  143. /* Initialize and load up the handler process, or update the menus */
  144. /* for an existing handler.                                        */
  145. add_handler() {
  146.   ULONG ilock;
  147.  
  148.   if (MM) {
  149.       /* remove old menus and update */
  150.     printf("Updating menus -- ");
  151.     fflush(stdout);
  152.       /* coordinate with handler */
  153.     MM->parent_task = FindTask(NULL);
  154.     MM->parent_sig = AllocSignal(-1L);
  155.     Signal(MM->handler_task, SIGBREAKF_CTRL_D);
  156.     Wait(1 << MM->parent_sig);
  157.       /* clean old stuff up */
  158.     free_menus();
  159.     ilock = LockIBase(0L);
  160.     menu_num = 0;
  161.     for (MM->prev_menu = MM->WBWindow->MenuStrip;
  162.     MM->prev_menu->NextMenu;
  163.     MM->prev_menu=MM->prev_menu->NextMenu)
  164.       menu_num++;
  165.     UnlockIBase(ilock);
  166.  
  167.       /* get new menus */
  168.     if (!parse_menus()) {
  169.       do_quit = TRUE;
  170.       return;
  171.     }
  172.  
  173.       /* let handler know it can continue */
  174.     Signal(MM->handler_task, SIGBREAKF_CTRL_D);
  175.     printf("ok\n");
  176.     return;
  177.   }
  178.  
  179.     /* create a new handler */  
  180.   printf("Installing MyMenu -- ");
  181.   fflush(stdout);
  182.  
  183.     /* get area to pass data in */
  184.   MM = (struct MMData *)AllocMem(sizeof(struct MMData), MEMF_PUBLIC|MEMF_CLEAR);
  185.  
  186.   MM->WBWindow = find_workbench();
  187.   if (MM->WBWindow==NULL) {
  188.     printf("Can't find Workbench...\n");
  189.     do_quit = TRUE;
  190.     return;
  191.   }
  192.  
  193.     /* we need to find out what menu number ours start at */
  194.   ilock = LockIBase(0L);
  195.   menu_num = 0;
  196.   for (MM->prev_menu = MM->WBWindow->MenuStrip;
  197.     MM->prev_menu->NextMenu;
  198.     MM->prev_menu=MM->prev_menu->NextMenu)
  199.     menu_num++;
  200.   UnlockIBase(ilock);  
  201.  
  202.     /* read in user's menus */
  203.   if (!parse_menus()) {
  204.     do_quit = TRUE;
  205.     return;
  206.   }
  207.  
  208.   MM->port.mp_Flags = PA_IGNORE;    /* we'll get msg's from do_wbrun */
  209.   MM->port.mp_Node.ln_Pri = 0;
  210.   MM->port.mp_Node.ln_Type = NT_MSGPORT;
  211.   MM->port.mp_Node.ln_Name = copystr(MYMENU_NAME);
  212.   NewList(&MM->port.mp_MsgList);
  213.  
  214.     /* load in handler */
  215.   MM->segment = LoadSeg("l:MyMenu-Handler");
  216.   if (!MM->segment)
  217.     MM->segment = LoadSeg("MyMenu-Handler");
  218.   if (!MM->segment) {
  219.     printf("Can't find L:MyMenu-Handler\n");
  220.     do_quit = TRUE;
  221.     return;
  222.   }
  223.  
  224.     /* add to port list so that handler can find it */
  225.   AddPort(&MM->port);
  226.  
  227.   MM->parent_task = FindTask(NULL);
  228.   MM->parent_sig = AllocSignal(-1L);
  229.   copy_path();
  230.   CreateProc(MYMENU_NAME, 0, MM->segment, STACK);
  231.     /* handshake so that we know it got started ok */
  232.   Wait(1 << MM->parent_sig);
  233.   FreeSignal(MM->parent_sig);
  234.   if (MM->error_code) {
  235.     printf("Handler error (%d)\n", MM->error_code);
  236.     do_quit = TRUE;
  237.   } else {
  238.     printf("ok - %s\n", VERSION);
  239.   }
  240. }
  241.  
  242. /* shutdown and clean up after handler */
  243. remove_handler() {
  244.   if (!MM)
  245.     return;
  246.   printf("removing -- ");
  247.   fflush(stdout);
  248.   if (MM->segment != NULL) {
  249.     MM->parent_task = FindTask(NULL);
  250.     MM->parent_sig = AllocSignal(-1L);
  251.     Signal(MM->handler_task, SIGBREAKF_CTRL_C);
  252.  
  253.       /* wait until handler cleans up */
  254.       /* (don't advertise that we catch ^C - for emergency use only) */
  255.     Wait(1 << MM->parent_sig);
  256.     FreeSignal(MM->parent_sig);
  257.     if (MM->error_code != ERR_OK) {
  258.       /* we can get an error if there are outstanding WB processes */
  259.       printf("Leaving handler in place...\n");
  260.       return;
  261.     }
  262.     RemPort(&MM->port);
  263.     UnLoadSeg(MM->segment);
  264.   }
  265.     /* this is done here, not in handler... */
  266.   free_path();
  267.   free_menus();
  268.   if (MM->port.mp_Node.ln_Name)
  269.     FreeMem(MM->port.mp_Node.ln_Name, strlen(MM->port.mp_Node.ln_Name)+1);
  270.   FreeMem(MM, sizeof(struct MMData));
  271.   printf("done\n");
  272. }
  273.  
  274. /* Close up libraries and exit.  Having a routine named _abort() is */
  275. /* handy for use with SDB, otherwise, I would have a better name.   */
  276. _abort(st)
  277.   int st;
  278. {
  279.   if (IntuitionBase)
  280.     CloseLibrary(IntuitionBase);
  281.   if (GfxBase)
  282.     CloseLibrary(GfxBase);
  283.   exit(st);
  284. }
  285.  
  286. main(argc, argv)
  287.   int argc;
  288.   char *argv[];
  289. {
  290.   IntuitionBase = (struct IntuitionBase *)open_lib("intuition.library", 0L);
  291.   GfxBase = (struct GfxBase *)open_lib("graphics.library", 0L);
  292.   
  293.   do_quit=FALSE;
  294.   for (i=1; i<argc; i++) {
  295.     if (stricmp(argv[i], "QUIT")==0) {
  296.       do_quit=TRUE;
  297.       continue;
  298.     }
  299.       /* no other options yet */
  300.     printf("Usage: MyMenu [quit]\n");
  301.     _abort(10);
  302.   }
  303.  
  304.     /* find shared data (if it exists) */
  305.   MM = (struct MMData *)FindPort(MYMENU_NAME);
  306.  
  307.   if (do_quit == FALSE) {
  308.     add_handler();
  309.   };
  310.   if (do_quit==TRUE) {        /* note that this isn't an 'else' */
  311.       remove_handler();
  312.   }
  313.   _abort(0);
  314. }
  315.