home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d476
/
browser
/
menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-17
|
8KB
|
344 lines
/* easy menus: Copyright 1987 Peter da Silva, all rights reserved.
*
* Permission is granted to use this in any application, so long as
* this notice is retained in the source. Permission is granted to
* modify the code as you like, so long as this notice (between the
* first line beginning "easy menus" and the end of this paragraph,
* inclusive) is retained intact.
*
* Usage:
*
* #include "menu.h"
*
* struct MenuPtr menudata;
* struct MenuPtr *menuptr = &menudata;
*
* init_menus(menuptr); / * Just zero menu pointer out * /
*
* for(each menu item) {
* add_menu(menuptr, menu, item, subitem, flags);
* }
*
* Flags:
* SUBITEM_NOCHECK -- subitem does not require a checkmark.
* SUBITEM_SELECTOR -- subitem is a 1 of n selector, use mutual-exclude.
* SUBITEM_TOGGLE -- subitem is a toggled flag.
* SUBITEM_SELECTED -- defaults to checked.
*
*
* SetMenuStrip(yourwindow, menuptr->MenuBar);
*
* ...
*
* ClearMenuStrip(yourwindow);
*
* trash_menus(menuptr);
*
* Notes:
*
* if you don't want any subitems, use zero for the subitem value.
*
* subitem is always initialised as a CHECKIT item with all the other
* subitems mutually excluded.
*
* it is intended that the menu be set up with all action items in
* the first level of the menu, and all toggles in the second level...
* this is a piece of blatant authoritarianism on my part. I've seen
* too many menus with no rhyme or reason. Look at AmigaTerm (the term
* program that comes with the Amiga modem) some time. Baud rate has
* an item all by itself, but word size is hidden off in a menu with
* things like bell sound.
*
* the appearance of the menus produced by this is (in my humble
* opinion) good. I took some care making text centered in menu boxes,
* for example.
*/
#include <exec/memory.h>
#include <intuition/intuition.h>
#include "menu.h"
#include "fonts.h"
/* Forward prototypes */
static void nudge(struct MenuItem *item, int delta);
static struct Menu *
new_menu(struct MenuPtr *menuptr, char *name);
static struct MenuItem *
new_item(struct MenuPtr *menuptr,
struct Menu *menu, UBYTE *name);
static struct MenuItem *
new_subitem(struct MenuPtr *menuptr,
struct MenuItem *item, UBYTE *name, long flags);
/*
struct MenuPtr {
struct Menu *MenuBar;
struct Remember *MenuMemory;
};
*/
char *AllocRemember();
static struct Menu *new_menu();
static struct MenuItem *new_item(), *new_subitem();
#define TOMENUNUM(i,j,k) (SHIFTMENU(i)|SHIFTITEM(j)|SHIFTSUB(k))
#define TextLen(s) (strlen(s)*FONTWIDTH)
void trash_menus(struct MenuPtr *menuptr)
{
FreeRemember(&menuptr->MenuMemory, 1);
menuptr->MenuMemory = 0;
menuptr->MenuBar = 0;
}
void init_menus(struct MenuPtr *menuptr)
{
menuptr->MenuMemory = 0;
menuptr->MenuBar = 0;
}
int add_menu(
struct MenuPtr *menuptr,
char *menuname,
char *itemname,
char *subitemname,
long flags)
{
int i, j, k;
struct Menu *menu;
struct MenuItem *item;
struct MenuItem *subitem;
if(menuptr->MenuBar) {
for(i = 0, menu = menuptr->MenuBar;
menu;
menu = menu->NextMenu, i++
)
if(strcmp(menuname, menu->MenuName)==0)
break;
if(!menu)
menu = new_menu(menuptr, menuname);
if(!menu)
return MENUNULL;
} else {
i = 0;
menu = new_menu(menuptr, menuname);
if(!menu)
return MENUNULL;
}
for(j = 0, item = menu->FirstItem;
item;
item = item->NextItem, j++
) {
struct IntuiText *text;
text = (struct IntuiText *)item->ItemFill;
if(strcmp(itemname, text->IText) == 0)
break;
}
if(subitemname) {
if(!item)
item = new_item(menuptr, menu, (UBYTE *)itemname);
if(!item)
return MENUNULL;
for(k = 0, subitem = item->SubItem;
subitem;
subitem = subitem->NextItem, k++
) {
struct IntuiText *text;
text = (struct IntuiText *)subitem->ItemFill;
if(strcmp(subitemname, text->IText) == 0)
break;
}
if(!subitem)
subitem = new_subitem(menuptr, item, (UBYTE *)subitemname, flags);
if(!subitem)
return MENUNULL;
return TOMENUNUM(i, j, k);
} else {
if(!item)
item = new_item(menuptr, menu, (UBYTE *)itemname);
if(!item)
return MENUNULL;
return TOMENUNUM(i, j, NOSUB);
}
}
static struct Menu *
new_menu(struct MenuPtr *menuptr, char *name)
{
struct Menu *menu;
menu = (struct Menu *)AllocRemember(
&menuptr->MenuMemory,
sizeof(struct Menu),
MEMF_PUBLIC);
if(!menu)
return 0;
menu->NextMenu = NULL;
menu->LeftEdge = 0;
menu->TopEdge = 0;
menu->Width = TextLen(name)+FONTWIDTH;
menu->Height = 0;
menu->Flags = MENUENABLED;
menu->MenuName = name;
menu->FirstItem = 0;
if(menuptr->MenuBar) {
struct Menu *ptr, *prev;
for(ptr = menuptr->MenuBar; ptr; ptr=ptr->NextMenu) {
menu->LeftEdge += ptr->Width;
prev = ptr;
}
prev->NextMenu = menu;
} else {
menuptr->MenuBar = menu;
}
return menu;
}
static struct MenuItem *
new_item(struct MenuPtr *menuptr, struct Menu *menu, UBYTE *name)
{
struct MenuItem *item;
struct IntuiText *text;
item = (struct MenuItem *)AllocRemember(
&menuptr->MenuMemory,
sizeof(struct MenuItem),
MEMF_PUBLIC);
if(!item)
return 0;
text = (struct IntuiText *)AllocRemember(
&menuptr->MenuMemory,
sizeof(struct IntuiText),
MEMF_PUBLIC);
if(!text)
return 0;
text->FrontPen = AUTOFRONTPEN;
text->BackPen = AUTOBACKPEN;
text->DrawMode = JAM2;
text->LeftEdge = 1;
text->TopEdge = 1;
text->ITextFont = NULL;
text->IText = name;
text->NextText = NULL;
item->NextItem = NULL;
item->LeftEdge = 0;
item->TopEdge = 0;
item->Width = IntuiTextLength(text)+2;
if(item->Width <= menu->Width)
item->Width = menu->Width+1;
item->Height = FONTHEIGHT+1;
item->Flags = ITEMTEXT|HIGHCOMP|ITEMENABLED;
item->MutualExclude = 0;
item->ItemFill = (APTR)text;
item->SelectFill = NULL;
item->Command = 0;
item->SubItem = NULL;
item->NextSelect = NULL;
if(menu->FirstItem) {
struct MenuItem *ptr, *prev;
for(ptr = menu->FirstItem; ptr; ptr=ptr->NextItem) {
if(item->Width > ptr->Width) {
if(ptr->SubItem)
nudge(ptr->SubItem, item->Width-ptr->Width);
ptr->Width = item->Width;
} else if(ptr->Width>item->Width)
item->Width = ptr->Width;
prev = ptr;
}
item->TopEdge = prev->TopEdge + prev->Height;
prev->NextItem = item;
} else {
menu->FirstItem = item;
}
return item;
}
static void nudge(struct MenuItem *item, int delta)
{
while(item) {
item->LeftEdge += delta;
item = item->NextItem;
}
}
static struct MenuItem *
new_subitem(
struct MenuPtr *menuptr,
struct MenuItem *item,
UBYTE *name,
long flags)
{
struct MenuItem *subitem;
struct IntuiText *text;
subitem = (struct MenuItem *)AllocRemember(
&menuptr->MenuMemory,
sizeof(struct MenuItem),
MEMF_PUBLIC);
if(!subitem)
return 0;
text = (struct IntuiText *)AllocRemember(
&menuptr->MenuMemory,
sizeof(struct IntuiText),
MEMF_PUBLIC);
if(!text)
return 0;
text->FrontPen = AUTOFRONTPEN;
text->BackPen = AUTOBACKPEN;
text->DrawMode = JAM2;
text->LeftEdge = 1;
if(flags != SUBITEM_NOCHECK) text->LeftEdge += CHECKWIDTH;
text->TopEdge = 1;
text->ITextFont = NULL;
text->IText = name;
text->NextText = NULL;
subitem->NextItem = NULL;
subitem->LeftEdge = item->Width;
subitem->TopEdge = 0;
subitem->Width = IntuiTextLength(text)+2;
if(flags != SUBITEM_NOCHECK) subitem->Width += CHECKWIDTH;
subitem->Height = FONTHEIGHT+1;
subitem->Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP;
subitem->MutualExclude = 0;
if(flags != SUBITEM_NOCHECK) {
subitem->Flags |= CHECKIT;
if(flags & SUBITEM_TOGGLE) subitem->Flags |= MENUTOGGLE;
if(flags & SUBITEM_SELECTED) subitem->Flags |= CHECKED;
}
subitem->ItemFill = (APTR)text;
subitem->SelectFill = NULL;
subitem->Command = 0;
subitem->SubItem = NULL;
subitem->NextSelect = NULL;
if(item->SubItem) {
struct MenuItem *ptr, *prev;
int i;
for(i=0, ptr = item->SubItem; ptr; i++, ptr=ptr->NextItem) {
if(subitem->Width > ptr->Width)
ptr->Width = subitem->Width;
else if(ptr->Width>subitem->Width)
subitem->Width = ptr->Width;
prev = ptr;
}
subitem->TopEdge = prev->TopEdge + prev->Height;
if(flags & SUBITEM_SELECTOR)
subitem->MutualExclude = ~(1<<i);
prev->NextItem = subitem;
} else {
item->SubItem = subitem;
if(flags & SUBITEM_SELECTOR)
subitem->MutualExclude = ~1;
}
return subitem;
}