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 / Menu.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  7KB  |  250 lines

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