/*
 *	MenuAlloc.c - Copyright © 1990 by S.R. & P.C.
 *
 *	Created:	16 Jun 1990
 *	Modified:	05 Jul 1990
 *
 *	Make>> make
 */

/*
#define DO_ARP_COPIES
#include <exec/memory.h>
#include <libraries/arpbase.h>
#include <functions.h>
*/

#include "ParM.h"

#define STEP 10


/*****				 global functions					*****/

char *copystr(char *);
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);


/*****				 global variables					*****/

extern struct Menu Menu1;
extern UBYTE menu_pen;
extern struct TextAttr TOPAZ80;


/*****				 local variables					*****/

static struct Menu *CurrentMenu = &Menu1;
static struct MenuItem *CurrentSubMenu, **CurrentItem;


/* 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 + STEP;
	for( mptr = Menu1.NextMenu ; mptr ; mptr=mptr->NextMenu ) {
		mptr->LeftEdge = left;
		maxw = mptr->Width = (strlen(mptr->MenuName)+2) * 8;
		left += maxw + STEP;
		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 allocate) a copy of the passed string *****/

char *copystr( char *str )
{
	char *newstr;
	newstr = AllocMem(strlen(str)+1, MEMF_PUBLIC);
	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 = (struct Extended_MenuItem *)
		  AllocMem(sizeof(struct Extended_MenuItem), MEMF_PUBLIC|MEMF_CLEAR);
	IT = (struct IntuiText *)AllocMem(sizeof(struct IntuiText), MEMF_PUBLIC|MEMF_CLEAR);
	emi->emi_MenuItem.Height = 10;
	emi->emi_MenuItem.Flags = ITEMTEXT+HIGHCOMP+ITEMENABLED;
	IT->FrontPen = menu_pen;
	IT->LeftEdge = IT->TopEdge = 1;
	IT->ITextFont = &TOPAZ80;
	IT->DrawMode = JAM1;
	IT->IText = (UBYTE*)copystr(itemstr);
	emi->emi_MenuItem.ItemFill = (APTR)IT;
	return emi;
}


/* allocate and initialize a new Menu */

void AddMenu(char *str)
{
	struct Menu *Menu;

	Menu = (struct Menu *)AllocMem(sizeof(struct Menu), MEMF_PUBLIC|MEMF_CLEAR);
	Menu->MenuName = copystr(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 = copystr(cmd);
	if (args) emi->emi_Args = copystr(args);
	if (shortcut) {
		emi->emi_MenuItem.Flags |= COMMSEQ;
		emi->emi_MenuItem.Command = shortcut;
	}
	if (mode=='c') {
		emi->emi_Window = copystr(win);
		emi->emi_Pri = pri;
		if (stk < DEFAULT_STACK) stk = DEFAULT_STACK;
		emi->emi_Stack = stk;
	}
	*CurrentItem = (struct MenuItem *)emi;
	CurrentItem = &emi->emi_MenuItem.NextItem;
}


/* free up memory used by a menu item */

static void FreeItem( struct Extended_MenuItem *Item )
{
	struct IntuiText *IT;

	IT = (struct IntuiText *)Item->emi_MenuItem.ItemFill;
	if (IT->IText) FreeMem(IT->IText, strlen((char *)IT->IText)+1);
	if (IT) FreeMem(IT, sizeof(struct IntuiText));
	if (Item->emi_Cmd) FreeMem(Item->emi_Cmd, strlen(Item->emi_Cmd)+1);
	if (Item->emi_Args) FreeMem(Item->emi_Args, strlen(Item->emi_Args)+1);
	if (Item->emi_Window) FreeMem(Item->emi_Window, strlen(Item->emi_Window)+1);
	FreeMem(Item, sizeof(struct Extended_MenuItem));
}


/* free up all space taken up by our menus */

void FreeMenus( void )
{
	struct Menu *mptr, *mtmp;
	struct MenuItem *iptr, *sptr, *itmp;

	mptr = Menu1.NextMenu;
	while( mptr ) {
		iptr = mptr->FirstItem;
		while( iptr ) {
			sptr = iptr->SubItem;
			while( sptr ) {
				itmp = sptr;
				sptr = sptr->NextItem;
				FreeItem( (struct Extended_MenuItem *)itmp );
			}
			itmp = iptr;
			iptr = iptr->NextItem;
			FreeItem( (struct Extended_MenuItem *)itmp );
		}
		mtmp = mptr;
		mptr = mptr->NextMenu;
		if (mtmp->MenuName) FreeMem(mtmp->MenuName, strlen(mtmp->MenuName)+1);
		FreeMem( mtmp , sizeof(struct Menu) );
	}
	Menu1.NextMenu = NULL;
	CurrentMenu = &Menu1;
}

