home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
530b.lha
/
AMenu_v1.3
/
Menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-03
|
10KB
|
322 lines
/*********************************************************************\
** ________________________________ **
** A n t h o n y |________ __ __ ________| **
** | |o_| |o_| | **
** T h y s s e n __| __ __ |__ **
** __| __| | | |__ |__ **
** `` Dragon Computing ! '' __| __| | | |__ |__ **
** |_____| |__| |_____| **
** **
\*********************************************************************/
/* Given individual menu entries (Menu,Item,SubItem,CommandChar),
** add them to the MPort as Extended Menu Items.
** Calculate positioning information required to complete the menus.
*/
#include "AMenu.h"
#include "AllocStr.h" /* string copy/allocate/deallocate macros */
#include <Graphics/GfxBase.h> /* so we can get the font width and height */
unsigned WBMenus, NextGap, MenuGap; /* Number WB menus, Menu Pos */
UBYTE Color[]={2,1}, TColor[]={2,3}; /* Colors :- Items and Title */
USHORT ItemStyle = HIGHCOMP; /* MenuItem Highlighting style */
UWORD FontWidth, FontHeight; /* size of font in use */
struct ExtMenuItem **EItemList; /* Last ExtMenuItem in EItemList */
struct Menu **MenuList, *CurrMenu;
struct MenuItem **OldItemList, **ItemList, *CurrSubMenu;
unsigned OldItemPos, ItemPos;
DB( int NumMenus; int NumItems; ) /* Debugging variables - memory checks */
/* NOTE: The TopEdge entry in the head element of a menu or sub-menu
** is used to store information about the column structure of that
** menu. The macros that follow, map this information in to, and out
** of this store.
*/
#define SHIFTCOLS(n) ((n)&255)
#define SHIFTPOS(n) (((n)&255)<<8)
#define NUMCOLS(n) ((n)&255)
#define NUMPOS(n) (((n)>>8)&255)
/* The LeftEdge entry in individual items (including the sub-menu head
** item) is used to hold the position number of that item in the final
** columned array of the menu.
*/
/*---------------------------------------------------------------*/
void
StartMenu()
/* Initialise the facts needed */
{
struct Menu *Menu;
ULONG Ilock;
M->AMenu = NULL;
MenuList = &M->AMenu;
M->EItemList = NULL;
EItemList = &M->EItemList;
FontWidth = GfxBase->DefaultFont->tf_XSize; /* font size */
FontHeight = GfxBase->DefaultFont->tf_YSize;
Ilock = LockIBase(0L);
Menu = M->WBWindow->MenuStrip; /* The First WB Menu */
MenuGap = Menu->NextMenu->LeftEdge -
(Menu->LeftEdge + Menu->Width); /* The Gap between WB Menus */
for( WBMenus=1; Menu->NextMenu; Menu=Menu->NextMenu) /* Count WB Menus */
WBMenus++;
NextGap = Menu->LeftEdge + Menu->Width; /* Start of Next Menu Gap */
UnlockIBase(Ilock);
DB( NumMenus = NumItems = 0; )
}
static void
PositionMenu(ItemList, SavedInfo, Top, Left)
struct MenuItem *ItemList;
unsigned SavedInfo, Top, Left;
/* Given an ItemList organise it into a number of Columns
** Offset by Top and Left (for SubMenus).
** Assumes that LeftEdge contains the Position Number for
** each Item in Item List.
*/
{
struct MenuItem *Start, *End; /* Position within ItemList */
unsigned NumColumns, ItemsPerColumn, Column;
NumColumns = NUMCOLS(SavedInfo);
ItemsPerColumn = NUMPOS(SavedInfo) / NumColumns + 1;
End = ItemList;
for(Column=0; Column<NumColumns; Column++ ) {
SHORT Width, ColWidth=0;
Start = End; /* first Item in column = End of last Column */
/* determine Columns Width and Extent */
while( End && (End->LeftEdge/ItemsPerColumn) == Column ) {
Width = End->Width;
if( End->Flags & COMMSEQ )
Width += COMMWIDTH + FontWidth + 4;
if( Width > ColWidth )
ColWidth = Width;
End = End->NextItem;
}
/* Position all the Items in Column */
while( Start != End ) {
/* if their a Sub-Menu within this menu - Position it*/
if( Start->SubItem )
PositionMenu( Start->SubItem, Start->TopEdge, 0, ColWidth );
/* position this Item */
Start->TopEdge = Top +
(Start->LeftEdge % ItemsPerColumn) * (FontHeight+2);
Start->LeftEdge = Left;
Start->Width = ColWidth;
Start = Start->NextItem;
}
Left = Left + ColWidth + 8; /* Gap between columns */
} /* For each Column */
}
BOOL
FinishMenu()
/* Cleanup New Menus - Postition, Size, etc. */
{
struct Menu *Menu;
BOOL ScreenOverflow;
DB( Printf("Added -- %ld Menus, %ld Items\n", NumMenus, NumItems); )
ScreenOverflow = ( NextGap > M->WBWindow->Width );
/* screen overflow on number of menus ? */
for (Menu = M->AMenu; Menu; Menu=Menu->NextMenu) {
PositionMenu( Menu->FirstItem, Menu->TopEdge, 0, 0 );
Menu->TopEdge = 0; /* explictly remove information saved */
}
return ScreenOverflow; /* if overflow - have parser WARN user */
}
/*---------------------------------------------------------------------*/
/* create and initialize a new menu item */
struct ExtMenuItem *
AddItem(ItemName, CommandChar)
char *ItemName, CommandChar;
{
register struct ExtMenuItem *EItem;
register struct MenuItem *Item;
register struct IntuiText *IText;
EItem = (struct ExtMenuItem *)
AllocMem(sizeof(struct ExtMenuItem), MEMF_PUBLIC|MEMF_CLEAR);
IText = (struct IntuiText *)
AllocMem(sizeof(struct IntuiText), MEMF_PUBLIC|MEMF_CLEAR);
Item = (struct MenuItem *)EItem; /* same object different type */
/* fill out the selection */
IText->FrontPen = Color[0];
IText->BackPen = Color[1];
IText->DrawMode = JAM2;
IText->IText = (UBYTE*)AllocStr(ItemName);
Item->Height = FontHeight;
Item->Width = IntuiTextLength(IText);
Item->Flags = ITEMTEXT | ITEMENABLED | ItemStyle;
Item->ItemFill = (APTR)IText;
if( CommandChar ) {
Item->Command = CommandChar;
Item->Flags |= COMMSEQ;
}
*EItemList = EItem; /* add to EItemList for Free'ing */
EItemList = &EItem->NextEItem;
*ItemList = Item; /* add to the current MenuItem chain */
ItemList = &Item->NextItem;
Item->LeftEdge = ItemPos++;
DB( NumItems++; )
return EItem;
}
void
AddTitle( TitleName )
char *TitleName;
/* create a Menu Item in the form of a Title
*/
{
struct ExtMenuItem *EItem = AddItem( TitleName, '\0' );
struct IntuiText *IText =
(struct IntuiText *)EItem->MenuItem.ItemFill;
IText->FrontPen = TColor[0];
IText->BackPen = TColor[1];
EItem->MenuItem.Flags = ITEMTEXT | ITEMENABLED | HIGHNONE;
}
void
AddSkip()
/* skip a position in the Menu Items (Leave a space)
*/
{
ItemPos++; /* adjust position number for latter items and menu size */
}
/*-------------------------------------------------------------*/
void
AddSubMenu(SubName, NumColumns)
char *SubName;
int NumColumns;
{
struct ExtMenuItem *EItem = AddItem(SubName, '\0');
struct MenuItem *Item = (struct MenuItem *)EItem;
Item->TopEdge = SHIFTCOLS(NumColumns); /* store information needed */
CurrSubMenu = Item;
OldItemList = ItemList; /* setup item list */
ItemList = &Item->SubItem;
OldItemPos = ItemPos;
ItemPos = 0;
}
void
EndSubMenu()
/* Cleanup and finalize a SubMenu */
{
CurrSubMenu->TopEdge |= SHIFTPOS(ItemPos-1); /* last position number */
ItemPos = OldItemPos; /* return to a normal Menu */
ItemList = OldItemList;
}
/*------------------------------------------------------------*/
void
AddMenu(MenuName, NumColumns)
char *MenuName;
int NumColumns;
/* Start a new menu attaching it to the AMenu list and storing
** Information about its characteristics
*/
{
struct Menu *Menu = (struct Menu *)
AllocMem(sizeof(struct Menu), MEMF_PUBLIC|MEMF_CLEAR);
Menu->MenuName = (UBYTE *)AllocStr(MenuName);
Menu->LeftEdge = NextGap + MenuGap; /* use menugap on creation */
Menu->Width = (strlen(MenuName)+1) * FontWidth;
Menu->Flags = MENUENABLED;
NextGap = Menu->LeftEdge + Menu->Width;
Menu->TopEdge = SHIFTCOLS(NumColumns);
CurrMenu = Menu;
*MenuList = Menu; /* add to menu list */
MenuList = &Menu->NextMenu;
ItemList = &Menu->FirstItem; /* initialize Item list */
ItemPos = 0;
DB( NumMenus++; );
}
void
EndMenu()
/* Finalize the Position Tally for this Menu */
{
CurrMenu->TopEdge |= SHIFTPOS(ItemPos-1); /* last position number */
}
/*------------------------------------------------------------*/
void
FreeMenus()
/* free up all space taken up by our menus */
{
struct Menu *Menu;
struct ExtMenuItem *EItem;
struct IntuiText *IText;
DB( NumMenus = NumItems = 0; )
while( EItem = M->EItemList ) { /* free all the ExtMenuItems */
M->EItemList = EItem->NextEItem;
if( EItem->Cmd ) FreeStr(EItem->Cmd);
if( EItem->Args ) FreeStr(EItem->Args);
if( EItem->Console ) FreeStr(EItem->Console);
if( EItem->Directory ) FreeStr(EItem->Directory);
IText = (struct IntuiText *)EItem->MenuItem.ItemFill;
FreeStr(IText->IText);
FreeMem(IText, sizeof(struct IntuiText));
FreeMem(EItem, sizeof(struct ExtMenuItem));
DB( NumItems++; )
}
while( Menu = M->AMenu ) { /* Free all the Menus */
M->AMenu = Menu->NextMenu;
FreeStr(Menu->MenuName);
FreeMem(Menu, sizeof(struct Menu));
DB( NumMenus++; )
}
DB( Printf("\nFreed -- %ld Menus, %ld Items\n", NumMenus, NumItems); )
}