home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Resources
/
System
/
BoingBag1
/
Contributions
/
Workbench
/
RexxArpLib3p6
/
src
/
sreq
/
simpmenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-17
|
15KB
|
652 lines
/** simpmenu.c
*
* Simple Menu routines.
*
**/
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <functions.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <simpmenu.h>
#include <simpreq.h>
static struct MenuItem *SItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy );
static struct MenuItem *SSItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy );
static struct Menu *LastMenu( struct Menu *menu );
static struct MenuItem *LastItem( struct MenuItem *item );
static void FixupItemLength( struct MenuItem *item, int leftedge );
static void FixupSubItemPos( struct MenuItem *item );
static struct MenuItem *MakeMenuItem( WORD x, WORD y, UBYTE *s, BYTE c, long excl );
static struct MenuItem *FreeItem( struct MenuItem *item );
#define MENUSIZE ((long) sizeof(struct Menu))
#define ITEMSIZE ((long) sizeof(struct XMenuItem))
#define COMMANDSIZE 45
#define LINESPACING 10
#define VSLOP 1
#define CHARWIDTH 8
#define MENUOFFSET 5
#define MENUSPACING 10
#define SUBMENUINDENT 10
/**
*
*
* SMenu(1.0) ARP Programmers Manual SMenu(1.0)
*
*
* NAME
* SMenu -- Allocate and initialize a new Menu structure.
*
* SYNOPSIS
* struct Menu *menu = SMenu(menutree, menuname);
*
* FUNCTION
* This function is used to create and initialize a new Menu structure.
* and link it to a previously created menu tree.
*
* INPUTS
* struct Menu *menutree Pointer to a menu tree to be extended
* or NULL to create a first Menu structure.
* char *menuname Name for new menu to be added
*
* RESULT
* Pointer to the newly created Menu structure, NULL on failure.
*
* ADDITIONAL CONSIDERATIONS
* This routine assumes the necessary libraries to be open.
* Typically, this routine is called the first time with a NULL
* first argument. This will create the first Menu structure.
* Subsequent calls to any of the simple menu functions should all
* use that first pointer as a first argument, and the menu will
* be built in sequence.
*
* BUGS
* None reported sofar.
*
* AUTHOR
* W.G.J. Langeveld (WGL)
*
**/
struct Menu *SMenu( struct Menu *menu, UBYTE *s)
{
struct Menu *m, *lm = NULL;
int l = 0;
ULONG *foo;
ULONG bar;
lm = LastMenu(menu);
l = MENUOFFSET;
if (lm)
l = strlen(lm->MenuName) * CHARWIDTH + lm->LeftEdge + MENUSPACING;
m = AllocMem(MENUSIZE, MEMF_CLEAR);
if (m == NULL)
goto cleanup;
m->LeftEdge = l;
m->Width = strlen(s) * CHARWIDTH + MENUSPACING;
m->Flags = MENUENABLED;
bar = strlen( s ) + 5;
foo = (ULONG *) AllocMem( bar, MEMF_CLEAR );
*foo++ = bar;
// m->MenuName = (BYTE *) malloc(strlen(s) + 1);
m->MenuName = (BYTE *) foo;
if (m->MenuName)
strcpy(m->MenuName, s);
else
goto cleanup;
if (lm)
lm->NextMenu = m;
return(m);
cleanup:
if (m)
FreeSMenu(m);
return(NULL);
}
/**
*
*
* SItem(1.0) ARP Programmers Manual SItem(1.0)
*
*
* NAME
* SItem -- Allocate and initialize a new MenuItem structure.
*
* SYNOPSIS
* struct MenuItem *item = SItem(menutree, itemname, command, exclude);
*
* FUNCTION
* This function is used to create and initialize a new MenuItem structure
* and link it to a menutree.
*
* INPUTS
* struct Menu *menutree Pointer to a menu tree to be extended
* char *itemname Name of new item to be added
* int command Character to be used in Right-Amiga combination.
* long exclude Mutual Exclude mask (see Intuition manual);
* 0L means no check marks, -1L means check mark
* but no mutual exclusion.
*
* RESULT
* Pointer to the newly created item, NULL on failure.
*
* ADDITIONAL CONSIDERATIONS
* This routine assumes the necessary libraries to be open.
* When called, this routine will automatically create the item as a
* new line in the menu below the previous item. See SItemB().
*
* BUGS
* None reported sofar.
*
* AUTHOR
* W.G.J. Langeveld (WGL)
*
*
**/
struct MenuItem *SItem( struct Menu *menu, UBYTE *s, BYTE c, long excl )
{
return(SItemY(menu, s, c, excl, LINESPACING));
}
/**
*
*
* SItemB(1.0) ARP Programmers Manual SItemB(1.0)
*
*
* NAME
* SItemB -- Allocate and initialize a new MenuItem structure.
*
* SYNOPSIS
* struct MenuItem *item = SItemB(menutree,itemname,command,exclude);
*
* FUNCTION
* This function is used to create and initialize a new MenuItem structure
* and link it to a menutree.
*
* INPUTS
* struct Menu *menutree Pointer to a menu tree to be extended
* char *itemname Name of new item to be added
* BYTE command Character to be used in Right-Amiga combination.
* long exclude Mutual Exclude mask (see Intuition manual);
* 0L means no check marks, -1L means check mark
* but no mutual exclusion.
*
* RESULT
* Pointer to the newly created item, NULL on failure.
*
* ADDITIONAL CONSIDERATIONS
* This routine assumes the necessary libraries to be open.
* When called, this routine will automatically create the item on the
* same line in the menu to the right of the previous item. See SItem().
*
* BUGS
* None reported sofar.
*
* AUTHOR
* W.G.J. Langeveld (WGL)
*
*
**/
struct MenuItem *SItemB( struct Menu *menu, UBYTE *s, BYTE c, long excl )
{
return(SItemY(menu, s, c, excl, 0));
}
/**
*
*
* SSItem(1.0) ARP Programmers Manual SSItem(1.0)
*
*
* NAME
* SSItem -- Allocate and initialize a new MenuItem structure.
*
* SYNOPSIS
* struct MenuItem *item = SSItem(menutree,itemname,command,exclude);
*
* FUNCTION
* This function is used to create and initialize a new MenuItem structure
* and link it to a menutree.
*
* INPUTS
* struct Menu *menutree Pointer to a menu tree to be extended
* UBYTE *itemname Name of new subitem to be added
* BYTE command Character to be used in Right-Amiga combination.
* long exclude Mutual Exclude mask (see Intuition manual);
* 0L means no check marks, -1L means check mark
* but no mutual exclusion.
*
* RESULT
* Pointer to the newly created subitem, NULL on failure.
*
* ADDITIONAL CONSIDERATIONS
* This routine assumes the necessary libraries to be open.
* When called, this routine will automatically create the subitem as a
* new line in the submenu below the previous subitem.
* See SSItemB().
*
* BUGS
* None reported sofar.
*
* AUTHOR
* W.G.J. Langeveld (WGL)
*
*
**/
struct MenuItem *SSItem( struct Menu *menu, UBYTE *s, BYTE c, long excl )
{
return(SSItemY(menu, s, c, excl, LINESPACING));
}
/**
*
*
* SSItemB(1.0) ARP Programmers Manual SSItemB(1.0)
*
*
* NAME
* SSItemB -- Allocate and initialize a new MenuItem structure.
*
* SYNOPSIS
* struct MenuItem *item=SSItemB(menutree,itemname,command,exclude);
*
* FUNCTION
* This function is used to create and initialize a new MenuItem structure
* and link it to a menutree.
*
* INPUTS
* struct Menu *menutree Pointer to a menu tree to be extended
* char *itemname Name of new subitem to be added
* BYTE command Character to be used in Right-Amiga combination.
* long exclude Mutual Exclude mask (see Intuition manual);
* 0L means no check marks, -1L means check mark
* but no mutual exclusion.
*
* RESULT
* Pointer to the newly created subitem, NULL on failure.
*
* ADDITIONAL CONSIDERATIONS
* This routine assumes the necessary libraries to be open.
* When called, this routine will automatically create the subitem on the
* same line in the submenu to the right of the previous subitem.
* See SSItem().
*
* BUGS
* None reported sofar.
*
* AUTHOR
* W.G.J. Langeveld (WGL)
*
*
**/
struct MenuItem *SSItemB( struct Menu *menu, UBYTE *s, BYTE c, long excl )
{
return(SSItemY(menu, s, c, excl, 0));
}
/**
*
*
* FreeSMenu(1.0) ARP Programmers Manual FreeSMenu(1.0)
*
*
* NAME
* FreeSMenu -- Allocate and initialize a new MenuItem structure.
*
* SYNOPSIS
* struct Menu *menu = FreeSMenu(menutree);
*
* FUNCTION
* This function is used to free all resources allocated for a particular
* menutree.
*
* INPUTS
* struct Menu *menutree Pointer to a menu tree to be freed
*
* RESULT
* Guaranteed NULL.
*
* ADDITIONAL CONSIDERATIONS
* This routine assumes the necessary libraries to be open.
* This routine uses recursion.
*
* BUGS
* None reported sofar.
*
* AUTHOR
* W.G.J. Langeveld (WGL)
*
*
**/
struct Menu *FreeSMenu( struct Menu *menu )
{
ULONG *foo;
if (menu == NULL)
return(NULL);
FreeSMenu(menu->NextMenu);
if (menu->FirstItem)
menu->FirstItem = FreeItem(menu->FirstItem);
foo = (ULONG *) menu->MenuName;
foo--;
FreeMem( foo, *foo );
// free(menu->MenuName);
FreeMem(menu, MENUSIZE);
return(NULL);
}
/**
*
* Adjust the menu items and subitems.
*
**/
void AdjustItems( struct Menu *menu )
{
struct MenuItem *item;
while (menu)
{
item = menu->FirstItem;
FixupItemLength(item, menu->LeftEdge);
while (item)
{
if (item->SubItem)
FixupItemLength(item->SubItem,
menu->LeftEdge + item->LeftEdge + item->Width - SUBMENUINDENT);
item = item->NextItem;
}
menu = menu->NextMenu;
}
return;
}
/**
*
* Internal routines
* ======== ========
*
**/
/**
*
* Internal routine: creates a new menu item with a certain line spacing.
*
**/
static struct MenuItem *SItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy )
{
struct Menu *lm = NULL;
struct MenuItem *i, *li = NULL;
int itemy = 0, itemx = 0;
lm = LastMenu(menu);
if (lm == NULL)
return(NULL);
li = LastItem(lm->FirstItem);
if (li)
{
if (!dy)
itemx = li->LeftEdge + li->Width;
itemy = li->TopEdge + dy;
}
i = MakeMenuItem(itemx, itemy, s, c, excl);
if (li)
li->NextItem = i;
else
lm->FirstItem = i;
return(i);
cleanup:
if (i)
FreeItem(i);
return(NULL);
}
/**
*
* Internal routine: creates a new subitem with a certain line spacing.
*
**/
static struct MenuItem *SSItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy )
{
struct Menu *lm = NULL;
struct MenuItem *i, *li = NULL, *lsi = NULL;
int sitemy = 0, sitemx = 0;
lm = LastMenu(menu);
if (lm == NULL)
return(NULL);
li = LastItem(lm->FirstItem);
if (li == NULL)
return(NULL);
sitemx = li->LeftEdge + li->Width - SUBMENUINDENT;
lsi = LastItem(li->SubItem);
if (lsi)
{
if (!dy)
sitemx = lsi->LeftEdge + lsi->Width;
sitemy = lsi->TopEdge + dy;
}
i = MakeMenuItem(sitemx, sitemy, s, c, excl);
if (lsi)
lsi->NextItem = i;
else
li->SubItem = i;
return(i);
cleanup:
if (i)
FreeItem(i);
return(NULL);
}
/**
*
* Internal routine: returns the last non-NULL menu pointer in a list of menus.
*
**/
static struct Menu *LastMenu( struct Menu *menu )
{
struct Menu *lm = menu;
while (menu)
{
menu = lm->NextMenu;
if (menu)
lm = menu;
}
return(lm);
}
/**
*
* Internal routine: returns the last non-NULL item in a list of items.
*
**/
static struct MenuItem *LastItem( struct MenuItem *item )
{
struct MenuItem *li = item;
while (item)
{
item = item->NextItem;
if (item)
li = item;
}
return(li);
}
/**
*
* Internal routine: computes the longest menu item and makes all others
* have the same length hitbox.
*
**/
static void FixupItemLength( struct MenuItem *item, int leftedge )
{
int l = 0, m = 0, commset = 0, le = 0;
struct MenuItem *fi = item;
while (item)
{
m = strlen( ((struct IntuiText *) item->ItemFill)->IText ) * CHARWIDTH;
if (item->Command)
{
commset = 1;
if (item->Command == -1)
m -= COMMANDSIZE;
}
if (m > l)
l = m;
item = item->NextItem;
}
if (commset)
l += COMMANDSIZE;
else
l += CHARWIDTH;
/*
* Fix up menus that fall off the edge
*/
if (l + leftedge > 630)
le = 630 - l - leftedge;
item = fi;
while (item)
{
item->Width = l;
item->LeftEdge += le;
if (item->SubItem)
FixupSubItemPos(item);
item = item->NextItem;
}
return;
}
/**
*
* Internal routine: Goes through a list of items and aligns all subitem
* hitboxes with the right edge.
*
**/
static void FixupSubItemPos( struct MenuItem *item )
{
int l = 0, m = 0;
struct MenuItem *i = NULL;
if (item == NULL)
return;
if (i = item->SubItem)
m = 5000;
while (i)
{
if (i->LeftEdge < m)
m = i->LeftEdge;
i = i->NextItem;
}
l = item->LeftEdge + item->Width - SUBMENUINDENT - m;
i = item->SubItem;
while (i)
{
i->LeftEdge += l;
i = i->NextItem;
}
return;
}
/**
*
* Internal routine: Allocate a MenuItem plus room for a UserData pointer
* and initialize it.
*
**/
static struct MenuItem *MakeMenuItem( WORD x, WORD y, UBYTE *s, BYTE c, long excl )
{
struct MenuItem *i = NULL;
struct IntuiText *MakeSIText();
i = AllocMem(ITEMSIZE, MEMF_CLEAR);
if (i == NULL)
return(NULL);
i->Flags = ITEMTEXT + ITEMENABLED + HIGHCOMP;
if (c && (c != -1))
i->Flags |= COMMSEQ;
if (excl)
i->Flags |= CHECKIT;
if (excl == -1L)
i->Flags |= MENUTOGGLE;
i->LeftEdge = x;
i->TopEdge = y;
i->Height = LINESPACING;
i->Width = strlen(s) * CHARWIDTH;
if (c && (c != -1))
i->Width += COMMANDSIZE;
if (excl && excl != -1L)
i->MutualExclude = excl;
i->Command = c;
i->ItemFill = (APTR) MakeSIText(0, 1, (int) JAM1, 0, VSLOP, s);
return(i);
}
/**
*
* Internal routine: free all resources associated with an item list.
*
**/
static struct MenuItem *FreeItem( struct MenuItem *item )
{
if (item == NULL)
return(NULL);
FreeItem(item->NextItem);
if (item->SubItem)
item->SubItem = FreeItem(item->SubItem);
FreeSIText(item->ItemFill);
FreeMem(item, ITEMSIZE);
return(NULL);
}