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

  1. /* Copyright (c) Darin Johnson, 1989 */
  2.  
  3. /* Menu.c               */
  4. /* Modified by John Baker, 1990       */
  5.  
  6. /* Modifications under 1.01:
  7.     the sizing of the drop-down menus is more appropriate
  8. */
  9.  
  10. #include <exec/memory.h>
  11. #include <graphics/text.h>
  12. #include <graphics/gfxbase.h>
  13. #include <intuition/intuition.h>
  14. #include <functions.h>
  15. #include "MyMenu.h"
  16.  
  17. BYTE *copystr();
  18.  
  19. unsigned long mnum, inum, snum, menu_num;
  20. struct ext_MenuItem *tail_list;
  21. UWORD font_width, font_height;
  22. UBYTE menu_pen;        /* pen number for newly created items */
  23.  
  24. extern struct GfxBase *GfxBase;
  25.  
  26. struct Menu *mptr;
  27. struct MenuItem *iptr, *sptr;
  28.  
  29. /* clean things up and initialize */
  30. start_menu() {
  31.   MM->my_menu = NULL;
  32.   menu_pen = 0;    /* default */
  33.   MM->item_list = tail_list = NULL;
  34.   font_width = GfxBase->DefaultFont->tf_XSize;
  35.   font_height = GfxBase->DefaultFont->tf_YSize;
  36. }
  37.  
  38. /* clean up widths and other info now that menu is all built */
  39. end_menu() {
  40.   UWORD maxw, smaxw, txtw, top, stop, left;
  41.   
  42.   ULONG ilock;
  43.   if (MM->prev_menu) {
  44.     ilock = LockIBase(0L);
  45.     left = MM->prev_menu->LeftEdge + MM->prev_menu->Width + SEPARATE;
  46.     UnlockIBase(ilock);
  47.   }
  48.   for (mptr = MM->my_menu; mptr; mptr=mptr->NextMenu) {
  49.     mptr->LeftEdge = left;
  50.     maxw = mptr->Width = (strlen(mptr->MenuName)+1) * font_width;
  51.  
  52. /*
  53.     maxw += SEPARATE;
  54. */
  55.  
  56.     left += (maxw + SEPARATE);  /* added SEPARATE here instead */
  57.     top = 0;
  58.       /* determine max width */
  59.     for (iptr = mptr->FirstItem; iptr; iptr=iptr->NextItem) {
  60.       iptr->TopEdge = top;
  61.       top += iptr->Height;
  62.       txtw = IntuiTextLength((struct IntuiText *)iptr->ItemFill) + 2;
  63.       if (iptr->Flags & COMMSEQ)
  64.         txtw += COMMWIDTH+font_width+2;
  65.       if (txtw > maxw)
  66.         maxw = txtw;
  67.     }
  68.     for (iptr = mptr->FirstItem; iptr; iptr=iptr->NextItem) {
  69.       iptr->Width = maxw;
  70.       stop = smaxw = 0;
  71.       for (sptr=iptr->SubItem; sptr; sptr=sptr->NextItem) {
  72.         sptr->LeftEdge = maxw;
  73.         sptr->TopEdge = stop;
  74.         stop += sptr->Height;
  75.         txtw = IntuiTextLength((struct IntuiText *)sptr->ItemFill) + 2;
  76.         if (sptr->Flags & COMMSEQ)
  77.           txtw += COMMWIDTH+font_width+2;
  78.         if (txtw > smaxw)
  79.           smaxw = txtw;
  80.       }
  81.       for (sptr=iptr->SubItem; sptr; sptr=sptr->NextItem)
  82.         sptr->Width = smaxw;
  83.     }
  84.   }
  85. }
  86.  
  87. /* allocate and initialize a new menu */
  88. struct Menu *new_menu(menustr)
  89.   char *menustr;
  90. {
  91.   struct Menu *menu;
  92.   menu = (struct Menu *)
  93.     AllocMem(sizeof(struct Menu), MEMF_PUBLIC|MEMF_CLEAR);
  94.   menu->MenuName = copystr(menustr);
  95.   menu->Flags = MENUENABLED;
  96.   menu->NextMenu = NULL;
  97.   menu->FirstItem = NULL;
  98.   menu->TopEdge = menu->Height = 0;
  99.   return menu;
  100. }
  101.  
  102. /* Find a menu.  If not found, create a new one */
  103. struct Menu *get_menu(menustr)
  104.   char *menustr;
  105. {
  106.   struct Menu *menu, *prev;
  107.   mnum = menu_num + 1;
  108.   if (MM->my_menu == NULL)        /* our menu strip */
  109.     menu = MM->my_menu = new_menu(menustr);
  110.   else {
  111.     for (menu=MM->my_menu; menu; menu=menu->NextMenu) {
  112.       if (!strcmp(menustr, (char *)menu->MenuName))
  113.         break;    /* already here */
  114.       prev = menu;
  115.       mnum++;
  116.     }
  117.     if (menu == NULL)
  118.       menu = prev->NextMenu = new_menu(menustr);
  119.   }
  120.   return menu;
  121. }
  122.  
  123. /* create and initialize a new menu item */
  124. struct MenuItem *new_item(itemstr)
  125.   char *itemstr;
  126. {
  127.   struct MenuItem *item;
  128.   struct IntuiText *it;
  129.     /* notice that we allocate extra space */
  130.   item = (struct MenuItem *)
  131.     AllocMem(sizeof(struct ext_MenuItem), MEMF_PUBLIC|MEMF_CLEAR);
  132.   it = (struct IntuiText *)
  133.     AllocMem(sizeof(struct IntuiText), MEMF_PUBLIC|MEMF_CLEAR);
  134.   item->NextItem = item->SubItem = NULL;
  135.   item->SelectFill = NULL;
  136.   item->NextSelect = 0;
  137.   item->Height = font_height + 1;
  138.   item->LeftEdge = item->TopEdge = item->MutualExclude = 0;
  139.   item->Flags = ITEMTEXT+HIGHCOMP+ITEMENABLED;
  140.   it->FrontPen = menu_pen;
  141.   it->BackPen = AUTOBACKPEN;
  142.   it->LeftEdge = it->TopEdge = 1;
  143.   it->ITextFont = NULL;
  144.   it->NextText = NULL;
  145.   it->DrawMode = JAM2;
  146.   it->IText = (UBYTE*)copystr(itemstr);
  147.   item->ItemFill = (APTR)it;
  148.   return item;
  149. }
  150.  
  151. /* find a menu item, if not found, create a new one */
  152. struct MenuItem *get_item(menustr, itemstr)
  153.   char *menustr, *itemstr;
  154. {
  155.   struct Menu *menu;
  156.   struct MenuItem *item, *prev;
  157.   menu = get_menu(menustr);
  158.   inum = 0;
  159.   if (menu->FirstItem == NULL)
  160.     item = menu->FirstItem = new_item(itemstr);
  161.   else {
  162.     for (item=menu->FirstItem; item; item=item->NextItem) {
  163.       if (!strcmp(itemstr, ((struct IntuiText *)item->ItemFill)->IText))
  164.         break;    /* already here */
  165.       prev = item;
  166.       inum++;
  167.     }
  168.     if (item == NULL)
  169.       item = prev->NextItem = new_item(itemstr);
  170.   }
  171.   return item;
  172. }
  173.  
  174. #define EITEM ((struct ext_MenuItem *)item)
  175.  
  176. /* create a new menu item (or sub item) */
  177. struct ext_MenuItem *add_menu(menustr, itemstr, substr, comm)
  178.   char *menustr, *itemstr, *substr, comm;
  179. {
  180.   struct MenuItem *item, *sub, *prev;
  181.   if (!itemstr)
  182.     return NULL;    /* oops */
  183.   item = get_item(menustr, itemstr);    /* get (or create) the item */
  184.   if (substr && *substr) {
  185.     snum = 0;
  186.     if (item->SubItem == NULL)
  187.       sub = item->SubItem = new_item(substr);    /* get the sub-item */
  188.     else {
  189.       for (sub=item->SubItem; sub; sub=sub->NextItem) {
  190.         if (!strcmp(substr, (char *)sub->ItemFill))
  191.           break;    /* duplicate */
  192.         prev = sub;
  193.     snum++;
  194.       }
  195.       if (sub == NULL)
  196.         sub = prev->NextItem = new_item(substr);
  197.     }
  198.     item = sub;
  199.   } else
  200.     snum = NOSUB;
  201.   if (comm) {
  202.     item->Command = comm;
  203.     item->Flags |= COMMSEQ;
  204.   }
  205.     /* fill in our private fields */
  206.   EITEM->id = SHIFTMENU(mnum)|SHIFTITEM(inum)|SHIFTSUB(snum);
  207.   EITEM->cmd = EITEM->args = NULL;
  208.   EITEM->type = NULL;
  209.     /* stick onto item_list */
  210.   EITEM->next_item = NULL;
  211.   if (MM->item_list==NULL)
  212.     MM->item_list = EITEM;
  213.   else
  214.     tail_list->next_item = EITEM;
  215.   tail_list = EITEM;
  216.   return EITEM;
  217. }
  218.  
  219. /* free up memory used by a menu item */
  220. free_item(item)
  221.   struct ext_MenuItem *item;
  222. {
  223.   struct IntuiText *it;
  224.   it = (struct IntuiText *)item->MenuItem.ItemFill;
  225.   FreeMem(it->IText, strlen(it->IText)+1);
  226.   FreeMem(it, sizeof(struct IntuiText));
  227.   if (item->cmd)
  228.     FreeMem(item->cmd, strlen(item->cmd)+1);
  229.   if (item->args)
  230.     FreeMem(item->args, strlen(item->args)+1);
  231.   FreeMem(item, sizeof(struct ext_MenuItem));
  232. }
  233.  
  234. /* free up all space taken up by our menus */
  235. free_menus() {
  236.   struct Menu *mtmp;
  237.   struct MenuItem *itmp;
  238.  
  239.   mptr = MM->my_menu;
  240.   MM->my_menu = NULL;
  241.   while (mptr) {
  242.     iptr = mptr->FirstItem;
  243.     while (iptr) {
  244.       sptr = iptr->SubItem;
  245.       while (sptr) {
  246.         itmp = sptr;
  247.     sptr = sptr->NextItem;
  248.     free_item(itmp);
  249.       }
  250.       itmp = iptr;
  251.       iptr = iptr->NextItem;
  252.       free_item(itmp);
  253.     }
  254.     mtmp = mptr;
  255.     mptr = mptr->NextMenu;
  256.     FreeMem(mtmp->MenuName, strlen(mtmp->MenuName)+1);
  257.     FreeMem(mtmp, sizeof(struct Menu));
  258.   }
  259. }
  260.