/* * MenuAlloc.c - Copyright © 1990 by S.R. & P.C. * * Created: 16 Jun 1990 * Modified: 20 Nov 1990 21:18:16 * * Make>> make */ #include "Menu.h" #include "Tokens.h" #define NO_MENUS 4 #define MEM_BLOCK_SIZE 1024 struct MemBlock { struct MinNode mb_MinNode; char mb_MemBlock[MEM_BLOCK_SIZE]; }; /***** global functions *****/ void AddMenu(char *); void AddSubMenu(char *); void AddEntry(char *, char *, char*, char*, char, char, long, short); void EndSubMenu(void); void CleanUp(void); void FreeMenus(void); void InitMenuAlloc(void); extern void Bye(short); /***** global variables *****/ extern struct Menu Menu1; extern UBYTE menu_pen; extern char *ReqTitle; /***** local variables *****/ static struct Menu *CurrentMenu; static struct MenuItem *CurrentSubMenu, **CurrentItem; static struct MinList MemList; static size_t Avail; void InitMenuAlloc(void) { MemList.mlh_Head = (struct MinNode *)&MemList.mlh_Tail; MemList.mlh_TailPred = (struct MinNode *)&MemList; } /* Memory allocation functions */ static void *Malloc(size_t size); #pragma regcall(Malloc(d0)) static void *Malloc(size_t size) { struct MemBlock *mb; static char *mem; void *chunck; size += 3; /* make chuncks long word aligned */ size &= ~(3L); if (size > Avail) { if (size > MEM_BLOCK_SIZE) { SimpleRequest(ReqTitle, "Line too long"); Bye(NO_MENUS); } if (!(mb = AllocMem(sizeof(struct MemBlock), MEMF_PUBLIC|MEMF_CLEAR))) Bye(NO_MENUS); AddTail((struct List *)&MemList, (struct Node *)mb); mem = mb->mb_MemBlock; Avail = MEM_BLOCK_SIZE; } chunck = mem; mem += size; Avail -= size; return chunck; } /* clean up widths and other info now that menu is all built */ void CleanUp(void) { UWORD maxw, smaxw, txtw, top, stop, left; struct Menu *mptr; struct MenuItem *iptr, *sptr; left = Menu1.Width; for( mptr = Menu1.NextMenu ; mptr ; mptr=mptr->NextMenu ) { mptr->LeftEdge = left; maxw = mptr->Width = (strlen(mptr->MenuName)+2) * 8; left += maxw; top = 0; /* determine max width */ for( iptr = mptr->FirstItem ; iptr ; iptr=iptr->NextItem ) { iptr->TopEdge = top; top += iptr->Height; txtw = IntuiTextLength((struct IntuiText *)iptr->ItemFill)+2; if( iptr->Flags & COMMSEQ ) txtw += 48; if( txtw > maxw ) maxw = txtw; } for( iptr = mptr->FirstItem ; iptr ; iptr=iptr->NextItem ) { iptr->Width = maxw; stop = smaxw = 0; for( sptr=iptr->SubItem ; sptr ; sptr=sptr->NextItem ) { sptr->LeftEdge = maxw; sptr->TopEdge = stop; stop += sptr->Height; txtw = IntuiTextLength((struct IntuiText *)sptr->ItemFill)+2; if( sptr->Flags & COMMSEQ ) txtw += 48; if( txtw > smaxw ) smaxw = txtw; } for( sptr=iptr->SubItem ; sptr ; sptr=sptr->NextItem ) sptr->Width = smaxw; } } } /***** make (and Mallocate) a copy of the passed string *****/ static char *MallocStr(char *str) { char *newstr; newstr = Malloc(strlen(str)+1); strcpy(newstr, str); return newstr; } /* allocate and initialize a new MenuItem */ struct Extended_MenuItem *AllocItem(char *itemstr) { struct IntuiText *IT; struct Extended_MenuItem *emi; emi = Malloc(sizeof(struct Extended_MenuItem)); IT = Malloc(sizeof(struct IntuiText)); emi->emi_MenuItem.Height = 10; emi->emi_MenuItem.Flags = ITEMTEXT+HIGHCOMP+ITEMENABLED; IT->FrontPen = menu_pen; IT->LeftEdge = IT->TopEdge = 1; IT->DrawMode = JAM1; IT->IText = (UBYTE *)MallocStr(itemstr); emi->emi_MenuItem.ItemFill = (APTR)IT; return emi; } /* allocate and initialize a new Menu */ void AddMenu(char *str) { struct Menu *Menu; Menu = Malloc(sizeof(struct Menu)); Menu->MenuName = MallocStr(str); Menu->Flags = MENUENABLED; CurrentMenu->NextMenu = Menu; CurrentMenu = Menu; CurrentItem = &Menu->FirstItem; } void AddSubMenu(char *substr) { *CurrentItem = (struct MenuItem *)AllocItem(substr); CurrentSubMenu = *CurrentItem; CurrentItem = &CurrentSubMenu->SubItem; } void EndSubMenu(void) { CurrentItem = &CurrentSubMenu->NextItem; } void AddEntry( char *item, char *cmd, char *args, char *win, char shortcut, char mode, long stk, short pri ) { struct Extended_MenuItem *emi; emi = AllocItem(item); emi->emi_Mode = mode; emi->emi_Cmd = MallocStr(cmd); if (args) emi->emi_Args = MallocStr(args); if (shortcut) { emi->emi_MenuItem.Flags |= COMMSEQ; emi->emi_MenuItem.Command = shortcut; } if (win) emi->emi_Window = MallocStr(win); emi->emi_Pri = pri; emi->emi_Stack = stk; *CurrentItem = (struct MenuItem *)emi; CurrentItem = &emi->emi_MenuItem.NextItem; } /* free up all space taken up by our menus */ void FreeMenus( void ) { struct MemBlock *mb; while( mb = (struct MemBlock *)RemTail((struct List *)&MemList) ) FreeMem(mb, sizeof(struct MemBlock)); CurrentMenu = &Menu1; Menu1.NextMenu = NULL; Avail = 0; }