home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 408.lha / MyMenu_v1.1 / sources / MyMenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  9.0 KB  |  346 lines

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