Path: utzoo!attcan!uunet!nuchat!sugar!peter From: peter@sugar.uu.net (Peter da Silva) Newsgroups: comp.sys.amiga Subject: Re: S/W Installation methodology Summary: Here's a solution to the menu problem. Message-ID: <3219@sugar.uu.net> Date: 6 Jan 89 01:50:12 GMT References: <2071@van-bc.UUCP> Organization: Sugar Land Unix - Houston, TX Lines: 385 Here's a quick-and-dirty menu routine, taken from Browser. I use it like so: open_id = add_menu("Browser", "Open", 0, 0); close_id = add_menu("Browser", "Close", 0, 0); quit_id = add_menu("Browser", "Quit", 0, 0); You can't delete menu items, or do any number of related manipulations. But for simple jobs it's easy as 3.14159... echo x - menu.c sed 's/^X//' > menu.c << '//END' X/* easy menus: Copyright 1987 Peter da Silva, all rights reserved. X * X * Permission is granted to use this in any application, so long as X * this notice is retained in the source. Permission is granted to X * modify the code as you like, so long as this notice (between the X * first line beginning "easy menus" and the end of this paragraph, X * inclusive) is retained intact. X * X * Usage: X * X * #include "menu.h" X * X * struct MenuPtr menudata; X * struct MenuPtr *menuptr = &menudata; X * X * init_menus(menuptr); / * Just zero menu pointer out * / X * X * for(each menu item) { X * add_menu(menuptr, menu, item, subitem, flags); X * } X * X * Flags: X * SUBITEM_NOCHECK -- subitem does not require a checkmark. X * SUBITEM_SELECTOR -- subitem is a 1 of n selector, use mutual-exclude. X * SUBITEM_TOGGLE -- subitem is a toggled flag. X * SUBITEM_SELECTED -- defaults to checked. X * X * X * SetMenuStrip(yourwindow, menuptr->MenuBar); X * X * ... X * X * ClearMenuStrip(yourwindow); X * X * trash_menus(menuptr); X * X * Notes: X * X * if you don't want any subitems, use zero for the subitem value. X * X * subitem is always initialised as a CHECKIT item with all the other X * subitems mutually excluded. X * X * it is intended that the menu be set up with all action items in X * the first level of the menu, and all toggles in the second level... X * this is a piece of blatant authoritarianism on my part. I've seen X * too many menus with no rhyme or reason. Look at AmigaTerm (the term X * program that comes with the Amiga modem) some time. Baud rate has X * an item all by itself, but word size is hidden off in a menu with X * things like bell sound. X * X * the appearance of the menus produced by this is (in my humble X * opinion) good. I took some care making text centered in menu boxes, X * for example. X */ X#include X#include X#include "menu.h" X#include "fonts.h" X X/* Xstruct MenuPtr { X struct Menu *MenuBar; X struct Remember *MenuMemory; X}; X*/ X Xchar *AllocRemember(); X Xstatic struct Menu *new_menu(); Xstatic struct MenuItem *new_item(), *new_subitem(); X X#define TOMENUNUM(i,j,k) (SHIFTMENU(i)|SHIFTITEM(j)|SHIFTSUB(k)) X#define TextLen(s) (strlen(s)*FONTWIDTH) X Xtrash_menus(menuptr) Xstruct MenuPtr *menuptr; X{ X FreeRemember(&menuptr->MenuMemory, 1); X menuptr->MenuMemory = 0; X menuptr->MenuBar = 0; X} X Xinit_menus(menuptr) Xstruct MenuPtr *menuptr; X{ X menuptr->MenuMemory = 0; X menuptr->MenuBar = 0; X} X Xint add_menu(menuptr, menuname, itemname, subitemname, flags) Xstruct MenuPtr *menuptr; Xchar *menuname, *itemname, *subitemname; Xlong flags; X{ X int i, j, k; X struct Menu *menu; X struct MenuItem *item; X struct MenuItem *subitem; X X if(menuptr->MenuBar) { X for(i = 0, menu = menuptr->MenuBar; X menu; X menu = menu->NextMenu, i++ X ) X if(strcmp(menuname, menu->MenuName)==0) X break; X if(!menu) X menu = new_menu(menuptr, menuname); X if(!menu) X return MENUNULL; X } else { X i = 0; X menu = new_menu(menuptr, menuname); X if(!menu) X return MENUNULL; X } X for(j = 0, item = menu->FirstItem; X item; X item = item->NextItem, j++ X ) { X struct IntuiText *text; X text = (struct IntuiText *)item->ItemFill; X if(strcmp(itemname, text->IText) == 0) X break; X } X if(subitemname) { X if(!item) X item = new_item(menuptr, menu, itemname); X if(!item) X return MENUNULL; X for(k = 0, subitem = item->SubItem; X subitem; X subitem = subitem->NextItem, k++ X ) { X struct IntuiText *text; X text = (struct IntuiText *)subitem->ItemFill; X if(strcmp(subitemname, text->IText) == 0) X break; X } X if(!subitem) X subitem = new_subitem(menuptr, item, subitemname, flags); X if(!subitem) X return MENUNULL; X return TOMENUNUM(i, j, k); X } else { X if(!item) X item = new_item(menuptr, menu, itemname); X if(!item) X return MENUNULL; X return TOMENUNUM(i, j, NOSUB); X } X} X Xstatic struct Menu * Xnew_menu(menuptr, name) Xstruct MenuPtr *menuptr; Xchar *name; X{ X struct Menu *menu; X X menu = (struct Menu *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct Menu), X MEMF_PUBLIC); X if(!menu) X return 0; X menu->NextMenu = NULL; X menu->LeftEdge = 0; X menu->TopEdge = 0; X menu->Width = TextLen(name)+FONTWIDTH; X menu->Height = 0; X menu->Flags = MENUENABLED; X menu->MenuName = name; X menu->FirstItem = 0; X if(menuptr->MenuBar) { X struct Menu *ptr, *prev; X for(ptr = menuptr->MenuBar; ptr; ptr=ptr->NextMenu) { X menu->LeftEdge += ptr->Width; X prev = ptr; X } X prev->NextMenu = menu; X } else { X menuptr->MenuBar = menu; X } X X return menu; X} X Xstatic struct item * Xnew_item(menuptr, menu, name) Xstruct MenuPtr *menuptr; Xchar *name; Xstruct Menu *menu; X{ X struct MenuItem *item; X struct IntuiText *text; X X item = (struct MenuItem *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct MenuItem), X MEMF_PUBLIC); X if(!item) X return 0; X text = (struct IntuiText *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct IntuiText), X MEMF_PUBLIC); X if(!text) X return 0; X X text->FrontPen = AUTOFRONTPEN; X text->BackPen = AUTOBACKPEN; X text->DrawMode = JAM2; X text->LeftEdge = 1; X text->TopEdge = 1; X text->ITextFont = NULL; X text->IText = name; X text->NextText = NULL; X X item->NextItem = NULL; X item->LeftEdge = 0; X item->TopEdge = 0; X item->Width = IntuiTextLength(text)+2; X if(item->Width <= menu->Width) X item->Width = menu->Width+1; X item->Height = FONTHEIGHT+1; X item->Flags = ITEMTEXT|HIGHCOMP|ITEMENABLED; X item->MutualExclude = 0; X item->ItemFill = text; X item->SelectFill = NULL; X item->Command = 0; X item->SubItem = NULL; X item->NextSelect = NULL; X X if(menu->FirstItem) { X struct MenuItem *ptr, *prev; X for(ptr = menu->FirstItem; ptr; ptr=ptr->NextItem) { X if(item->Width > ptr->Width) { X if(ptr->SubItem) X nudge(ptr->SubItem, item->Width-ptr->Width); X ptr->Width = item->Width; X } else if(ptr->Width>item->Width) X item->Width = ptr->Width; X prev = ptr; X } X item->TopEdge = prev->TopEdge + prev->Height; X prev->NextItem = item; X } else { X menu->FirstItem = item; X } X X return item; X} X Xstatic nudge(item, delta) Xstruct MenuItem *item; Xint delta; X{ X while(item) { X item->LeftEdge += delta; X item = item->NextItem; X } X} X Xstatic struct item * Xnew_subitem(menuptr, item, name, flags) Xstruct MenuPtr *menuptr; Xchar *name; Xstruct MenuItem *item; Xlong flags; X{ X struct MenuItem *subitem; X struct IntuiText *text; X X subitem = (struct MenuItem *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct MenuItem), X MEMF_PUBLIC); X if(!subitem) X return 0; X text = (struct IntuiText *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct IntuiText), X MEMF_PUBLIC); X if(!text) X return 0; X X text->FrontPen = AUTOFRONTPEN; X text->BackPen = AUTOBACKPEN; X text->DrawMode = JAM2; X text->LeftEdge = CHECKWIDTH+1; X text->TopEdge = 1; X text->ITextFont = NULL; X text->IText = name; X text->NextText = NULL; X X subitem->NextItem = NULL; X subitem->LeftEdge = item->Width; X subitem->TopEdge = 0; X subitem->Width = IntuiTextLength(text)+2; X if(flags != SUBITEM_NOCHECK) subitem->Width += CHECKWIDTH; X subitem->Height = FONTHEIGHT+1; X subitem->Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP; X subitem->MutualExclude = 0; X if(flags != SUBITEM_NOCHECK) { X subitem->Flags |= CHECKIT; X if(flags & SUBITEM_TOGGLE) subitem->Flags |= MENUTOGGLE; X if(flags & SUBITEM_SELECTED) subitem->Flags |= CHECKED; X } X subitem->ItemFill = text; X subitem->SelectFill = NULL; X subitem->Command = 0; X subitem->SubItem = NULL; X subitem->NextSelect = NULL; X X if(item->SubItem) { X struct MenuItem *ptr, *prev; X int i; X for(i=0, ptr = item->SubItem; ptr; i++, ptr=ptr->NextItem) { X if(subitem->Width > ptr->Width) X ptr->Width = subitem->Width; X else if(ptr->Width>subitem->Width) X subitem->Width = ptr->Width; X prev = ptr; X } X subitem->TopEdge = prev->TopEdge + prev->Height; X if(flags & SUBITEM_SELECTOR) X subitem->MutualExclude = ~(1<NextItem = subitem; X } else { X item->SubItem = subitem; X if(flags & SUBITEM_SELECTOR) X subitem->MutualExclude = ~1; X } X X return subitem; X} //END echo x - fonts.h sed 's/^X//' > fonts.h << '//END' X#ifndef FONTS_H X#define FONTS_H X#ifndef GRAPHICS_GFXBASE_H X#include X#endif X#ifndef GRAPHICS_TEXT_H X#include X#endif X Xextern struct GfxBase *GfxBase; X X#define FONTWIDTH (GfxBase->DefaultFont->tf_XSize) X#define FONTHEIGHT (GfxBase->DefaultFont->tf_YSize) X#define FONTBASELINE (GfxBase->DefaultFont->tf_Baseline) X#endif //END echo x - menu.h sed 's/^X//' > menu.h << '//END' Xstruct MenuPtr { X struct Menu *MenuBar; X struct Remember *MenuMemory; X int next_id; X}; X X/* flags */ X#define SUBITEM_NOCHECK 0x0 /* subitem does not require a checkmark. */ X#define SUBITEM_SELECTOR 0x10 /* subitem is a 1 of n selector */ X#define SUBITEM_TOGGLE 0x20 /* subitem is a toggled flag. */ X#define SUBITEM_SELECTED 0x01 /* defaults to checked. */ //END -- Peter "Have you hugged your wolf today" da Silva `-_-' Hackercorp. ...texbell!sugar!peter, or peter@sugar.uu.net 'U`