/* Copyright ) Darin Johnson, 1989 */ #include #include #include #include #include #include #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)); } }