home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
199.lha
/
GimmeLib
/
menustuff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-27
|
11KB
|
402 lines
/*
* FILE: menustuff.c
* Support routines for dealing with menus and menuitems.
*
* NOTE: these routines should only be used on a menustrip that is
* not attached to a window or guaranteed not to be actively used by
* Intuition (eg. by using the MENUVERIFY flag).
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt added to gimme.lib
*/
#define I_AM_MENUSTUFF
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/menustuff.h"
/* internal flags: must stay within defined GMI_RESERVED bits */
#define GMI_SUBITEM (1L << 30) /* process subitem, not item */
#define GMI_DO_TOP (1L << 29) /* modify top edge */
#define GMI_DO_ME (1L << 28) /* modify mutual exclude */
#define GMI_SNEAKY (1L << 27) /* sneaky -- don't modify too much */
#define GMI_ADJUST (GMI_FIXUP | GMI_SHUFFLE)
#define GMI_ADJUSTME (GMI_FIXUPME | GMI_SHUFFLEME)
ULONG addMenuItem( menu, item, positem, possub, numitem, myflags )
struct Menu *menu;
struct MenuItem *item;
SHORT positem, possub, numitem;
ULONG myflags;
{
register struct MenuItem *temp, **old;
struct MenuItem *save, *savelast;
SHORT pos, sub;
SHORT top, topedge;
if( !menu || !item || !numitem ) {
return( MENUNULL );
}
if( myflags & GMI_SUBITEM ) {
old = &((struct MenuItem *)menu)->SubItem;
} else {
old = &menu->FirstItem;
}
if( myflags & GMI_ADDSUBITEM ) {
if( !*old ) { /* if no items, can't put subitem */
return( MENUNULL );
}
} else {
/* find last item in list to be added and truncate list appropriately */
for( temp = item; temp->NextItem; temp = temp->NextItem ) {
if( --numitem == 0 ) {
temp->NextItem = NULL;
break;
}
} /* for */
savelast = temp; /* save pointer to last item to be added */
if( positem == 0 || !*old ) { /* add as first (sub)item */
savelast->NextItem = *old;
*old = item;
if( *old && (myflags & (GMI_ADJUST|GMI_ADJUSTME|GMI_APPEAREND)) ) {
pos = 0;
save = item;
myflags |= GMI_SNEAKY; /* careful handling */
goto calculate_adjustment_mi;
}
adjustMenuItems( item, savelast->NextItem, 0, 0, myflags );
return( SHIFTITEM(0) | SHIFTSUB(NOSUB) );
}
}
/* find the item preceding where to insert, and position# for new item */
pos = 1;
for( temp = *old; temp->NextItem; temp = temp->NextItem ) {
if( --positem == 0 ) {
break;
}
++pos;
} /* for */
if( myflags & GMI_ADDSUBITEM ) {
sub = ITEMNUM( addMenuItem(temp, item, possub, 0, numitem,
(myflags | GMI_SUBITEM) & ~GMI_ADDSUBITEM) );
} else {
savelast->NextItem = temp->NextItem;
save = temp; /* save ptr to item after which to add */
if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) {
calculate_adjustment_mi: {}
/* calculate top edge for new item */
topedge = 0;
for( temp = *old; temp; temp = temp->NextItem ) {
top = temp->TopEdge + temp->Height;
if( temp == save ) {
if( !(myflags & GMI_SNEAKY) ) {
save->NextItem = item;
if( top > topedge ) {
topedge = top;
}
}
if( !(myflags & GMI_APPEAREND) ) {
break; /* exit for loop */
}
temp = savelast; /* skip over what we added */
}
if( top > topedge ) {
topedge = top;
}
} /* for */
adjustMenuItems( item, savelast->NextItem, topedge, pos, myflags );
} else {
save->NextItem = item;
}
sub = NOSUB;
}
return( SHIFTITEM(pos) | SHIFTSUB(sub) );
} /* addMenuItem */
ULONG addMenu( menuptr, menu, posmenu, nummenu, myflags )
struct Menu **menuptr;
struct Menu *menu;
SHORT posmenu, nummenu;
ULONG myflags;
{
register struct Menu *temp, **old;
struct Menu *save, *savelast;
SHORT pos;
SHORT left, leftedge;
if( !nummenu || !menuptr || !menu ) {
return( MENUNULL );
}
old = menuptr;
/* find last menu in list to be added and truncate list appropriately */
for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) {
if( --nummenu == 0 ) {
temp->NextMenu = NULL;
break;
}
} /* for */
savelast = temp; /* save pointer to last menu to be added */
if( posmenu == 0 || !*old ) { /* add to front of menu strip */
savelast->NextMenu = *old;
*old = menu;
if( *old && (myflags & (GMI_ADJUST | GMI_APPEAREND)) ) {
pos = 0;
save = menu;
myflags |= GMI_SNEAKY; /* careful handling */
goto calculate_adjustment_m;
}
adjustMenuLefts( menu, savelast->NextMenu, 0, myflags );
return( SHIFTMENU(0) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) );
}
/* find the menu preceding where to insert, and position# for new menu */
pos = 1;
for( temp = *old; temp->NextMenu; temp = temp->NextMenu ) {
if( --posmenu == 0 ) {
break;
}
++pos;
} /* for */
savelast->NextMenu = temp->NextMenu;
save = temp; /* save ptr to menu after which to add */
if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) {
calculate_adjustment_m: {}
/* calculate left edge for new menu */
leftedge = 0;
for( temp = *old; temp; temp = temp->NextMenu ) {
left = temp->LeftEdge + temp->Width;
if( temp == save ) {
if( !(myflags & GMI_SNEAKY) ) {
save->NextMenu = menu;
if( left > leftedge ) {
leftedge = left;
}
}
if( !(myflags & GMI_APPEAREND) ) {
break; /* exit for loop */
}
temp = savelast; /* skip over what we added */
}
if( left > leftedge ) {
leftedge = left;
}
} /* for */
adjustMenuLefts( menu, savelast->NextMenu, leftedge, myflags );
} else {
save->NextMenu = menu;
}
return( SHIFTMENU(pos) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) );
} /* addMenu */
struct MenuItem *removeMenuItem( menu, item, positem, possub, numitem, myflags )
struct Menu *menu;
struct MenuItem *item;
SHORT positem, possub, numitem;
ULONG myflags;
{
register struct MenuItem *temp, **old;
struct MenuItem *save;
SHORT pos; /* position for mutual exclude */
if( !menu ) {
return( NULL );
}
if( myflags & GMI_SUBITEM ) {
old = &((struct MenuItem *)menu)->SubItem;
} else {
old = &menu->FirstItem;
}
if( !*old || !numitem ) { /* if no menu items */
return( NULL );
}
if( myflags & GMI_REMSUBITEM ) {
save = item; /* don't want to check item address yet */
item = NULL;
} else {
if( item ) {
positem = -1;
}
}
pos = 0;
temp = *old;
if( temp != item && positem != 0 && temp->NextItem ) {
/* find the "item" preceding where to remove */
for( ; temp->NextItem && --positem != 0; ) {
++pos;
if( temp->NextItem == item ) { /* found the item */
break;
}
temp = temp->NextItem; /* next in loop */
if( !temp->NextItem ) { /* no more to follow so stop */
break;
}
} /* for */
old = &temp->NextItem;
}
/* now old points to a MenuItem pointer to item to be removed */
if( item && *old != item ) { /* if its not the right item */
return( NULL );
}
if( myflags & GMI_REMSUBITEM ) {
item = removeMenuItem( temp, save, possub, 0, numitem,
(myflags | GMI_SUBITEM) & ~GMI_REMSUBITEM );
} else {
if( !item ) {
item = *old;
}
if( myflags & GMI_ADDRONLY ) {
return( item );
}
/* find last one to be removed */
for( temp = item; temp->NextItem; temp = temp->NextItem ) {
if( --numitem == 0 ) {
break;
}
} /* for */
*old = temp->NextItem;
temp->NextItem = NULL;
myflags &= ~(GMI_FIXUP | GMI_FIXUPME);
if( myflags & GMI_SHUFFLE ) {
myflags |= GMI_FIXUP;
}
if( myflags & GMI_SHUFFLEME ) {
myflags |= GMI_FIXUPME;
}
adjustMenuItems( *old, NULL, item->TopEdge, pos, myflags );
}
return( item );
} /* removeMenuItem */
struct Menu *removeMenu( menuptr, menu, posmenu, nummenu, myflags )
struct Menu **menuptr;
struct Menu *menu;
SHORT posmenu, nummenu;
ULONG myflags;
{
register struct Menu *temp, **old;
if( !nummenu || !menuptr || !*menuptr ) {
return( NULL );
}
old = menuptr;
if( menu ) {
posmenu = -1;
}
temp = *old;
if( temp != menu && posmenu != 0 && temp->NextMenu ) {
/* find the menu preceding where to remove */
for( ; temp->NextMenu && --posmenu != 0; ) {
if( temp->NextMenu == menu ) { /* found the menu */
break;
}
temp = temp->NextMenu; /* next in loop */
if( !temp->NextMenu ) { /* no more to follow so stop */
break;
}
} /* for */
old = &temp->NextMenu;
}
/* now old points to a Menu pointer to menu to be removed */
if( menu && *old != menu ) { /* if its not the right menu */
return( NULL );
}
if( !menu ) {
menu = *old;
}
if( myflags & GMI_ADDRONLY ) {
return( menu );
}
/* find last one to be removed */
for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) {
if( --nummenu == 0 ) {
break;
}
} /* for */
*old = temp->NextMenu;
temp->NextMenu = NULL;
adjustMenuLefts( *old, NULL, menu->LeftEdge, myflags );
return( menu );
} /* removeMenu */
short adjustMenuItems( item, stop, topedge, meposition, myflags )
struct MenuItem *item, *stop;
SHORT topedge, meposition;
register ULONG myflags;
{
register struct MenuItem *temp;
if( !(myflags & (GMI_ADJUST | GMI_ADJUSTME)) ) {
return( -1 );
}
if( myflags & GMI_FIXUP ) {
myflags |= GMI_DO_TOP;
}
if( myflags & GMI_FIXUPME ) {
myflags |= GMI_DO_ME;
}
for( temp = item; temp; temp = temp->NextItem ) {
if( temp == stop ) {
if( !(myflags & (GMI_SHUFFLE | GMI_SHUFFLEME)) ) {
break;
}
myflags &= ~(GMI_DO_TOP | GMI_DO_ME);
if( (myflags & GMI_SHUFFLE) && !(myflags & GMI_APPEAREND) ) {
myflags |= GMI_DO_TOP;
}
if( myflags & GMI_SHUFFLEME ) {
myflags |= GMI_DO_ME;
}
}
if( myflags & GMI_DO_TOP ) {
temp->TopEdge = topedge;
}
topedge += temp->Height;
if( myflags & GMI_DO_ME ) {
temp->MutualExclude = ~(1L << meposition);
}
++meposition;
} /* for */
return( 0 );
} /* adjustMenuItems */
short adjustMenuLefts( menu, stop, leftedge, myflags )
struct Menu *menu, *stop;
register SHORT leftedge;
ULONG myflags;
{
register struct Menu *temp;
if( !(myflags & (GMI_ADJUST)) ) {
return( -1 );
}
for( temp = menu; temp; temp = temp->NextMenu ) {
if( !(myflags & GMI_SHUFFLE) && temp == stop ) {
break;
}
temp->LeftEdge = leftedge;
leftedge += temp->Width;
} /* for */
return( 0 );
} /* adjustMenuLefts */