home *** CD-ROM | disk | FTP | other *** search
- /* Copyright ) Darin Johnson, 1989 */
-
- #include <exec/memory.h>
- #include <graphics/text.h>
- #include <graphics/gfxbase.h>
- #include <intuition/intuition.h>
- #include <clib/macros.h>
- #include <functions.h>
- #include "MyMenu.h"
-
- BYTE *copystr();
-
- unsigned long mnum, inum, snum, menu_num;
- struct ext_MenuItem *tail_list;
- UWORD font_width, font_height;
- UBYTE menu_pen; /* pen number for newly created items */
-
- extern struct GfxBase *GfxBase;
-
- struct Menu *mptr;
- struct MenuItem *iptr, *sptr;
-
- /* clean things up and initialize */
- start_menu() {
- MM->my_menu = NULL;
- menu_pen = 0; /* default */
- MM->item_list = tail_list = NULL;
- font_width = GfxBase->DefaultFont->tf_XSize;
- font_height = GfxBase->DefaultFont->tf_YSize;
- }
-
- /* clean up widths and other info now that menu is all built */
- end_menu() {
- UWORD maxw, smaxw, txtw, top, stop, left;
-
- ULONG ilock;
- if (MM->prev_menu) {
- ilock = LockIBase(0L);
- left = MM->prev_menu->LeftEdge + MM->prev_menu->Width + SEPARATE;
- UnlockIBase(ilock);
- }
- for (mptr = MM->my_menu; mptr; mptr=mptr->NextMenu) {
- mptr->LeftEdge = left;
- maxw = mptr->Width = (strlen(mptr->MenuName)+1) * font_width;
- maxw += SEPARATE;
- left += maxw;
- top = 0;
- /* determine max width */
- for (iptr = mptr->FirstItem; iptr; iptr=iptr->NextItem) {
- iptr->TopEdge = top;
- top += iptr->Height;
- txtw = IntuiTextLength(iptr->ItemFill);
- if (iptr->Flags & COMMSEQ)
- txtw += COMMWIDTH+font_width+4;
- if (txtw > maxw)
- maxw = txtw;
- }
- for (iptr = mptr->FirstItem; iptr; iptr=iptr->NextItem) {
- iptr->Width = maxw;
- stop = smaxw = 0;
- for (sptr=iptr->SubItem; sptr; sptr=sptr->NextItem) {
- sptr->LeftEdge = maxw;
- sptr->TopEdge = stop;
- stop += sptr->Height;
- txtw = IntuiTextLength(sptr->ItemFill);
- if (sptr->Flags & COMMSEQ)
- txtw += COMMWIDTH+font_width+4;
- if (txtw > smaxw)
- smaxw = txtw;
- }
- for (sptr=iptr->SubItem; sptr; sptr=sptr->NextItem)
- sptr->Width = smaxw;
- }
- }
- }
-
- /* allocate and initialize a new menu */
- struct Menu *new_menu(menustr)
- char *menustr;
- {
- struct Menu *menu;
- menu = (struct Menu *)
- AllocMem(sizeof(struct Menu), MEMF_PUBLIC|MEMF_CLEAR);
- menu->MenuName = copystr(menustr);
- menu->Flags = MENUENABLED;
- menu->NextMenu = NULL;
- menu->FirstItem = NULL;
- menu->TopEdge = menu->Height = 0;
- return menu;
- }
-
- /* Find a menu. If not found, create a new one */
- struct Menu *get_menu(menustr)
- char *menustr;
- {
- struct Menu *menu, *prev;
- mnum = menu_num + 1;
- if (MM->my_menu == NULL) /* our menu strip */
- menu = MM->my_menu = new_menu(menustr);
- else {
- for (menu=MM->my_menu; menu; menu=menu->NextMenu) {
- if (!strcmp(menustr, (char *)menu->MenuName))
- break; /* already here */
- prev = menu;
- mnum++;
- }
- if (menu == NULL)
- menu = prev->NextMenu = new_menu(menustr);
- }
- return menu;
- }
-
- /* create and initialize a new menu item */
- struct MenuItem *new_item(itemstr)
- char *itemstr;
- {
- struct MenuItem *item;
- struct IntuiText *it;
- /* notice that we allocate extra space */
- item = (struct MenuItem *)
- AllocMem(sizeof(struct ext_MenuItem), MEMF_PUBLIC|MEMF_CLEAR);
- it = (struct IntuiText *)
- AllocMem(sizeof(struct IntuiText), MEMF_PUBLIC|MEMF_CLEAR);
- item->NextItem = item->SubItem = NULL;
- item->SelectFill = NULL;
- item->NextSelect = 0;
- item->Height = font_height + 1;
- item->LeftEdge = item->TopEdge = item->MutualExclude = 0;
- item->Flags = ITEMTEXT+HIGHCOMP+ITEMENABLED;
- it->FrontPen = menu_pen;
- it->BackPen = AUTOBACKPEN;
- it->LeftEdge = it->TopEdge = 1;
- it->ITextFont = NULL;
- it->NextText = NULL;
- it->DrawMode = JAM2;
- it->IText = (UBYTE*)copystr(itemstr);
- item->ItemFill = (APTR)it;
- return item;
- }
-
- /* find a menu item, if not found, create a new one */
- struct MenuItem *get_item(menustr, itemstr)
- char *menustr, *itemstr;
- {
- struct Menu *menu;
- struct MenuItem *item, *prev;
- menu = get_menu(menustr);
- inum = 0;
- if (menu->FirstItem == NULL)
- item = menu->FirstItem = new_item(itemstr);
- else {
- for (item=menu->FirstItem; item; item=item->NextItem) {
- if (!strcmp(itemstr, ((struct IntuiText *)item->ItemFill)->IText))
- break; /* already here */
- prev = item;
- inum++;
- }
- if (item == NULL)
- item = prev->NextItem = new_item(itemstr);
- }
- return item;
- }
-
- #define EITEM ((struct ext_MenuItem *)item)
-
- /* create a new menu item (or sub item) */
- struct ext_MenuItem *add_menu(menustr, itemstr, substr, comm)
- char *menustr, *itemstr, *substr, comm;
- {
- struct MenuItem *item, *sub, *prev;
- if (!itemstr)
- return NULL; /* oops */
- item = get_item(menustr, itemstr); /* get (or create) the item */
- if (substr && *substr) {
- snum = 0;
- if (item->SubItem == NULL)
- sub = item->SubItem = new_item(substr); /* get the sub-item */
- else {
- for (sub=item->SubItem; sub; sub=sub->NextItem) {
- if (!strcmp(substr, (char *)sub->ItemFill))
- break; /* duplicate */
- prev = sub;
- snum++;
- }
- if (sub == NULL)
- sub = prev->NextItem = new_item(substr);
- }
- item = sub;
- } else
- snum = NOSUB;
- if (comm) {
- item->Command = comm;
- item->Flags |= COMMSEQ;
- }
- /* fill in our private fields */
- EITEM->id = SHIFTMENU(mnum)|SHIFTITEM(inum)|SHIFTSUB(snum);
- EITEM->cmd = EITEM->args = NULL;
- EITEM->type = NULL;
- /* stick onto item_list */
- EITEM->next_item = NULL;
- if (MM->item_list==NULL)
- MM->item_list = EITEM;
- else
- tail_list->next_item = EITEM;
- tail_list = EITEM;
- return EITEM;
- }
-
- /* free up memory used by a menu item */
- free_item(item)
- struct ext_MenuItem *item;
- {
- struct IntuiText *it;
- it = (struct IntuiText *)item->MenuItem.ItemFill;
- FreeMem(it->IText, strlen(it->IText)+1);
- FreeMem(it, sizeof(struct IntuiText));
- if (item->cmd)
- FreeMem(item->cmd, strlen(item->cmd)+1);
- if (item->args)
- FreeMem(item->args, strlen(item->args)+1);
- FreeMem(item, sizeof(struct ext_MenuItem));
- }
-
- /* free up all space taken up by our menus */
- free_menus() {
- struct Menu *mtmp;
- struct MenuItem *itmp;
-
- mptr = MM->my_menu;
- MM->my_menu = NULL;
- while (mptr) {
- iptr = mptr->FirstItem;
- while (iptr) {
- sptr = iptr->SubItem;
- while (sptr) {
- itmp = sptr;
- sptr = sptr->NextItem;
- free_item(itmp);
- }
- itmp = iptr;
- iptr = iptr->NextItem;
- free_item(itmp);
- }
- mtmp = mptr;
- mptr = mptr->NextMenu;
- FreeMem(mtmp->MenuName, strlen(mtmp->MenuName)+1);
- FreeMem(mtmp, sizeof(struct Menu));
- }
- }
-