/* menus.c */
#include "aib.h"
#include "extern.h"

/* defines */
#define NORM 0
#define MX   1
#define TOG  2

/* prototypes */

void old_menu(void);
struct title_box *grabtitle(struct title_box *);
struct item_box *grabitem(struct item_box *);
struct sub_box *grabsub(struct sub_box *);
void free_allmenu(struct title_box *);
void generate(void);
LONG GetMX_it(struct item_box *);
LONG GetMX_sub(struct sub_box *);
void freeall_subs(struct sub_box *);
void freeall_items(struct item_box *);
void menu_opts(struct Gadget *, UWORD);
struct title_box *new_title(struct title_box*);
struct item_box *new_item(struct item_box*);
struct sub_box *new_sub(struct sub_box*);
void add_title(char [256]);
void add_item(char [256]);
void add_sub(char [256]);
void change_title(UWORD,char *);
void change_item(UWORD,char *);
void change_sub(UWORD,char*);
struct title_box *locate_title(UWORD);
struct item_box  *locate_item(UWORD);
struct sub_box   *locate_sub (UWORD);
void rem_title(struct title_box*);
void rem_item(struct item_box*);
void rem_sub(struct sub_box*);
void swapit (void);
void swapit_it(void);
void swapit_sub(void);
void prepare_title(void);
void prepare_item(void);
void prepare_sub(void);
void disable_all(void);

/* globals needed */
struct List it_list,sub_list;
char new_t[256],new_i[256],new_s[256];
struct title_box *curr_t = NULL;
struct item_box *curr_i = NULL;
struct sub_box *curr_s = NULL;
int ord_title = -1;
int ord_item = -1;
int ord_sub = -1;
struct title_box *swap_tit = NULL;
struct item_box  *swap_it  = NULL;
struct sub_box   *swap_sub = NULL;
BOOL fchecked = FALSE;
int curr_box =0;
int num_entries = 0;

/************************** menu gads ***********************************/
void menu_opts (struct Gadget *gad, UWORD code)
{
	switch (gad->GadgetID) {

  case MM_titl:
	if (!topt) break;
	ord_title=code;
	curr_t=locate_title(code);

	if (swap_tit) swapit();

	/* activate legal buttons */
	prepare_title();

	break;
	
  case MM_item:
	if (!curr_t->items) break;
	ord_item=code;
	curr_i=locate_item(code);

	if (swap_it) swapit_it();

	/* activate legal buttons */
	prepare_item();

	break;

  case MM_subs:
	if (!curr_i->submenu) break;
	ord_sub=code;
	curr_s=locate_sub(code);

	if (swap_sub) swapit_sub();

	/* activate legal buttons */
	prepare_sub();

	break;

  case MM_tstring:
	strcpy(new_t,((struct StringInfo *)gad->SpecialInfo)->Buffer);
	if (ord_title >= 0) change_title(ord_title,new_t);
	else break;
	GT_SetGadgetAttrs(tl,window,NULL,
		GTLV_Labels,&tit_list,
		GA_Disabled,FALSE,
		GTLV_Selected,curr_t->index,
		TAG_DONE);
	GT_SetGadgetAttrs(select,window,NULL,
		GTTX_Text,"T",
		TAG_DONE);
	GT_SetGadgetAttrs(stype,window,NULL,
		GTTX_Text,curr_t->title,
		TAG_DONE);
	break;
	 
  case MM_istring:
	strcpy(new_i,((struct StringInfo *)gad->SpecialInfo)->Buffer);
	if (ord_item >= 0) change_item(ord_item,new_i);
	else break;
	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,&it_list,
		GTLV_Selected,curr_i->index,
		TAG_DONE);
	GT_SetGadgetAttrs(select,window,NULL,
		GTTX_Text,"I",
		TAG_DONE);
	GT_SetGadgetAttrs(stype,window,NULL,
		GTTX_Text,curr_i->item,
		TAG_DONE);
	break;

  case MM_sstring:
	strcpy(new_s,((struct StringInfo *)gad->SpecialInfo)->Buffer);
	if (ord_sub >= 0) change_sub(ord_sub,new_s);
	else break;
	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,&sub_list,
		GTLV_Selected,curr_s->index,
		TAG_DONE);
	GT_SetGadgetAttrs(select,window,NULL,
		GTTX_Text,"S",
		TAG_DONE);
	GT_SetGadgetAttrs(stype,window,NULL,
		GTTX_Text,curr_s->submenu,
		TAG_DONE);
	break;


  case MM_ts:

	if (ord_title <1) break;
	/* is this the first time? */
	if (!swap_tit) {
		swap_tit = curr_t;
                NewList(&it_list);
		disable_all();
		GT_SetGadgetAttrs(ts,window,NULL,	
			GA_Disabled,FALSE,
			TAG_DONE);
		}
 	
	else {  /* undo swap */
		swap_tit =NULL;
		prepare_title();
 	     }
	break;

  case MM_ta:
	num_entries++;
        curr_t = new_title(curr_t);

	GT_SetGadgetAttrs(tl,window,NULL,
		GTLV_Labels,-1,
		GA_Disabled,FALSE,
		TAG_DONE);
	
	add_title(curr_t->title);

	GT_SetGadgetAttrs(tl,window,NULL,
		GTLV_Labels,&tit_list,
		GTLV_Selected,curr_t->index,
		GA_Disabled,FALSE,
		TAG_DONE);

	ord_title=curr_t->index;
	prepare_title();
	/* update items display... */
	break;

  case MM_td:
	num_entries--;
	if (ord_title <0) break;
 	curr_box=0;
	rem_title(curr_t);
	disable_all();
	GT_SetGadgetAttrs(select,window,NULL,
		GTTX_Text,"",
		TAG_DONE);
	GT_SetGadgetAttrs(stype,window,NULL,
		GTTX_Text,"",
		TAG_DONE);
	GT_SetGadgetAttrs(tstring,window,NULL,
		GTST_String,"",
		TAG_DONE);
	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,0,
		TAG_DONE);	
	GT_SetGadgetAttrs(tl,window,NULL,
		GTLV_Labels,&tit_list,
		TAG_DONE);
	GT_SetGadgetAttrs(ta,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
	ord_title=-1;  
	break;

case MM_ia:
	num_entries++;
	if (ord_title <0) break;
        curr_i=new_item(curr_i);

	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,-1,
		GA_Disabled,FALSE,
		TAG_DONE);
	
	add_item(curr_i->item);

	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,&it_list,
		GTLV_Selected,curr_i->index,
		GA_Disabled,FALSE,
		TAG_DONE);

	ord_item=curr_i->index;
	prepare_item();
	break;

case MM_id:
	num_entries--;
	if (ord_item <0) break;
	curr_box=0;
	rem_item(curr_i);
	disable_all();
	GT_SetGadgetAttrs(select,window,NULL,
		GTTX_Text,"",
		TAG_DONE);
	GT_SetGadgetAttrs(stype,window,NULL,
		GTTX_Text,"",
		TAG_DONE);
	GT_SetGadgetAttrs(istring,window,NULL,
		GTST_String,"",
		GA_Disabled,TRUE,
		TAG_DONE);
	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,0,
		TAG_DONE);
	GT_SetGadgetAttrs(ta,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);	
	GT_SetGadgetAttrs(ia,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);	
	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,&it_list,
		TAG_DONE);
	ord_item=-1;  
	break;

case MM_is:

	if (ord_item <1) break;
	/* is this the first time? */
	if (!swap_it) {
		swap_it = curr_i;
		disable_all();
		GT_SetGadgetAttrs(is,window,NULL,	
			GA_Disabled,FALSE,
			TAG_DONE);
		}
 	
	else {  /* undo swap */
		swap_it =NULL;
		prepare_item();
 	     }
	break;

case MM_sa:
	num_entries++;
	if (ord_item <0) break;
        curr_s=new_sub(curr_s);

	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,-1,
		GA_Disabled,FALSE,
		TAG_DONE);
	
	add_sub(curr_s->submenu);

	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,&sub_list,
		GTLV_Selected,curr_s->index,
		GA_Disabled,FALSE,
		TAG_DONE);

	ord_sub=curr_s->index;
	prepare_sub();
	break;

case MM_sd:
	num_entries--;
	if (ord_sub <0) break;
	curr_box=0;
	rem_sub(curr_s);
	disable_all();
	GT_SetGadgetAttrs(select,window,NULL,
		GTTX_Text,"",
		TAG_DONE);
	GT_SetGadgetAttrs(stype,window,NULL,
		GTTX_Text,"",
		TAG_DONE);
	GT_SetGadgetAttrs(ta,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);	
	GT_SetGadgetAttrs(ia,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
	GT_SetGadgetAttrs(sa,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,&sub_list,
		TAG_DONE);
	
	ord_sub=-1;  
	break;

case MM_ss:

	if (ord_sub <1) break;
	/* is this the first time? */
	if (!swap_sub) {
		swap_sub = curr_s;
		disable_all();
		GT_SetGadgetAttrs(ss,window,NULL,	
			GA_Disabled,FALSE,
			TAG_DONE);
		}
 	
	else {  /* undo swap */
		swap_sub =NULL;
		prepare_sub();
 	     }
	break;


case MM_fche:
	fchecked=(fchecked)?FALSE:TRUE;
	GT_SetGadgetAttrs(nfont,window,NULL,
		GA_Disabled,(fchecked)?FALSE:TRUE,
		TAG_DONE);
	if (fchecked) menuta = &menucta;
	else menuta = screen->Font;
	break;

	/***** title, item, and sub choices... ******/

case MM_dis:
 	if (curr_box==1) curr_t->disabled=(curr_t->disabled)?FALSE:TRUE;
	else if (curr_box==2) curr_i->disabled=(curr_i->disabled)?FALSE:TRUE;
	else if (curr_box==3) curr_s->disabled=(curr_s->disabled)?FALSE:TRUE;
 	break;
	
	/***** item , and sub choices... ******/
	
case MM_bar:
	if (curr_box==2) curr_i->menubar=(curr_i->menubar)?FALSE:TRUE;
	else if (curr_box==3) curr_s->menubar=(curr_s->menubar)?FALSE:TRUE;
 	break;

case MM_chec:
	if (curr_box==2) curr_i->checked=(curr_i->checked)?FALSE:TRUE;
	else if (curr_box==3) curr_s->checked=(curr_s->checked)?FALSE:TRUE;
 	break;

case MM_tog:
	if (curr_box==2)  curr_i->type=code;
	else if (curr_box==3)  curr_s->type=code;
	if (code == 2)
	GT_SetGadgetAttrs(chec,window,NULL,
		GA_Disabled,TRUE,
		TAG_DONE);
	else 
	GT_SetGadgetAttrs(chec,window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
 	break;

case MM_func:
        if (curr_box==2) strcpy(curr_i->function,
		((struct StringInfo *)gad->SpecialInfo)->Buffer );
	else if (curr_box==3) strcpy(curr_s->function,
		((struct StringInfo *)gad->SpecialInfo)->Buffer );
 	break;

case MM_key:
        if (curr_box==2) strcpy(curr_i->hotkey,
		((struct StringInfo *)gad->SpecialInfo)->Buffer );
	else if (curr_box==3) strcpy(curr_s->hotkey,
		((struct StringInfo *)gad->SpecialInfo)->Buffer );
 	break;

default:
	gad_opts(gad,code);
	break;
	}

}


/****** handle MX *********************************************************/

LONG GetMX_it(struct item_box *temp)
{
 LONG flag = 0;
 LONG count = 1;

 while (temp)
	{
	 if (temp->type != 2) flag = flag | count;
	 count=count*2;
	 temp=temp->next;
	}
 
 return(flag); 

}

LONG GetMX_sub (struct sub_box *temp)
{
 LONG flag = 0;
 LONG count = 1;

 while (temp)
	{
	 if (temp->type != 2) flag = flag | count;
	 count=count*2;
	 temp=temp->next;
	}
 
 return(flag); 

}


/* generate menu! ********************************************************/

void generate(void)
{
 UWORD mxi,mxs,x, flags;
 LONG ic,sc,sfl,ifl;

 struct title_box *tempt=topt;
 struct item_box *tempi= NULL;
 struct sub_box *temps = NULL;

 x=0;

 if (their_menu) free(their_menu);
 their_menu = NULL;
 
 if (topt) {
 their_menu = (struct NewMenu *)calloc(num_entries+1,sizeof(struct NewMenu));

 while (tempt)
	{
 	 (their_menu +x)->nm_Type = (UBYTE) NM_TITLE;
 	 (their_menu +x)->nm_Label=tempt->title;
 	 (their_menu +x)->nm_CommKey=0;
 	 (their_menu +x)->nm_Flags=0;
 	 (their_menu +x)->nm_MutualExclude = 0;
 	 (their_menu +x)->nm_UserData = 0;
	 x++;

	 /* handle items */
	 if (tempt->items) 
		{
		 tempi = tempt->items;
		 mxi=0;
		 ic=1;
		 ifl = GetMX_it(tempt->items);
		 while(tempi)
		   {
			flags=0;
 			(their_menu +x)->nm_Type = NM_ITEM;
			(their_menu +x)->nm_Label=(tempi->menubar)?
					 NM_BARLABEL:tempi->item;
		        
			if (!(tempi->submenu) && strlen(tempi->hotkey)>0)
 			(their_menu +x)->nm_CommKey=tempi->hotkey;

			else (their_menu + x)->nm_CommKey = 0;
					
			  (their_menu +x)->nm_MutualExclude =0;
			if (tempi->disabled) flags = NM_ITEMDISABLED;
			if (tempi->type == 2) {
				if (!mxi) flags = flags | CHECKED;
				mxi=1; 
				flags = flags | CHECKIT; 
 			        (their_menu +x)->nm_MutualExclude = 
					(tempi->type==2)?~(ic|ifl):0;
				}
			else if (tempi->type == 1) {
				flags = flags | MENUTOGGLE | CHECKIT;
				if (tempi->checked) flags = flags | CHECKED;
				}
			(their_menu +x)->nm_Flags=flags;

 			(their_menu +x)->nm_UserData = (strlen(tempi->function)>0)
				?tempi->function:0;
			x++;
			ic = ic * 2;
		    /* handle submenus */
		    if (tempi->submenu && !tempi->type && !tempi->menubar)
			{
			 temps = tempi->submenu;
			 mxs=0;
			 sc=1;
			 sfl = GetMX_sub(tempi->submenu);
			 while(temps)
			    {
				 flags = 0;
				 (their_menu +x)->nm_Type = NM_SUB;
				 (their_menu +x)->nm_Label=(temps->menubar)?
						NM_BARLABEL:temps->submenu;

				 if (strlen(temps->hotkey)>0)
 				 (their_menu +x)->nm_CommKey=temps->hotkey;

				 else (their_menu + x)->nm_CommKey = 0;
					
				   (their_menu +x)->nm_MutualExclude =0;
				if (temps->disabled) flags = NM_ITEMDISABLED;
				if (temps->type == 2) {
					if (!mxs) flags = flags | CHECKED;
					mxs=1; 
					flags = flags | CHECKIT; 
 				        (their_menu +x)->nm_MutualExclude = 
						(temps->type==2)?~(sc|sfl):0;
					}
				else if (temps->type == 1) {
					flags = flags | MENUTOGGLE;
					if (temps->checked) flags = flags | CHECKED;
					}
				 (their_menu +x)->nm_Flags=flags;

				 (their_menu +x)->nm_UserData = (strlen(temps->function)>0)?
					temps->function:0;
				 x++;
				 sc = sc * 2;
			      temps = temps->next;
			    }
			 }			      
		    tempi=tempi->next;
		   }
	        }
	
	 tempt = tempt->next;
	}

 (their_menu +x)->nm_Type = NM_END;
 (their_menu +x)->nm_Label=0;
 (their_menu +x)->nm_CommKey=0;
 (their_menu +x)->nm_Flags=0;
 (their_menu +x)->nm_MutualExclude = 0;
 (their_menu +x)->nm_UserData = 0;

 }
}

/* disable all ***********************************************************/

void disable_all(void)
{
 struct Gadget *gads[20];
 int x;


  /* disabled */
 gads[0]=sstring; gads[1]=sa; gads[2]=ss; gads[3]=sd;
 gads[5]=istring; gads[6]=is; gads[7]=id; gads[8]=bar; gads[9]=chec; 
 gads[10]=tog; gads[11]=func;  gads[12]=tstring; gads[13]=ta; gads[14]=ts; 
 gads[15]=td;  gads[16]=ia; gads[17]=dis; gads[18]=dis; gads[19]=key;

 for (x=0;x<20;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,TRUE,
		TAG_DONE);

 
}

/************************* prepare title *********************************/

void prepare_title(void)
{
 struct Gadget *gads[13];
 struct item_box *temp= curr_t->items; 
 int x;

 /* disabled */
 gads[0]=sstring; gads[1]=sa; gads[2]=ss; gads[3]=sd; gads[4]=sl;
 gads[5]=istring; gads[6]=is; gads[7]=id;
 gads[8]=bar; gads[9]=chec; gads[10]=tog; gads[11]=func; gads[12]=key;
 
 for (x=0;x<13;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,TRUE,
		TAG_DONE);

 /* abled */
 gads[0]=tstring; gads[1]=ta; gads[2]=ts; gads[3]=td; gads[4]=il; 
 gads[5]=ia; gads[6]=dis;

for (x=0;x<7;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
	
 curr_box=1;
 ord_item=-1;
 ord_sub =-1;

 /* enter visual response */
 GT_SetGadgetAttrs(select,window,NULL,
	GTTX_Text,"T",
	TAG_DONE);
 GT_SetGadgetAttrs(stype,window,NULL,
	GTTX_Text,curr_t->title,
	TAG_DONE);

 GT_SetGadgetAttrs(dis,window,NULL,
	GTCB_Checked,curr_t->disabled,
 	TAG_DONE);

 /* update item & sub boxes... */
 curr_i=curr_t->items;

 NewList(&sub_list);
 NewList(&it_list);
 while (temp) { add_item(temp->item);
		temp=temp->next; }

	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,&it_list,
		TAG_DONE);
	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,0,
		TAG_DONE);
}

/************************ prepare item ************************************/

void prepare_item(void)
{
 struct Gadget *gads[13];
 struct sub_box *temp = curr_i->submenu;
 int x;

 /* disabled */
 gads[0]=sstring; gads[1]=ss; gads[2]=sd; gads[3]=sl;
 gads[4]=tstring; gads[5]=ts; gads[6]=td; 
 
 
 for (x=0;x<7;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,TRUE,
		TAG_DONE);

 /* abled */
 gads[0]=istring; gads[1]=ia; gads[2]=is; gads[3]=id; gads[4]=il; 
 gads[5]=sa; gads[6]=dis; gads[7]=chec; gads[8]=tog; gads[9]=func;
 gads[10]=bar; gads[11]=ta; gads[12]=key;

for (x=0;x<13;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
	
 curr_box=2;
 ord_sub = -1;

 /* enter visual response */
 GT_SetGadgetAttrs(select,window,NULL,
	GTTX_Text,"I",
	TAG_DONE);
 GT_SetGadgetAttrs(stype,window,NULL,
	GTTX_Text,curr_i->item,
	TAG_DONE);
 GT_SetGadgetAttrs(dis,window,NULL,
	GTCB_Checked,curr_i->disabled,
	TAG_DONE);
 GT_SetGadgetAttrs(bar,window,NULL,
	GTCB_Checked,curr_i->menubar,
	TAG_DONE);
 GT_SetGadgetAttrs(chec,window,NULL,
	GTCB_Checked,curr_i->checked,
	TAG_DONE);
 GT_SetGadgetAttrs(tog,window,NULL,
	GTCY_Active,curr_i->type,
	TAG_DONE);
 GT_SetGadgetAttrs(func,window,NULL,
	GTST_String,curr_i->function,
	TAG_DONE);
 GT_SetGadgetAttrs(key,window,NULL,
	GTST_String,curr_i->hotkey,
	TAG_DONE);

  /* handle MX disabling of checked */
if (curr_i->type == 2)
     GT_SetGadgetAttrs(chec,window,NULL,
	GA_Disabled,TRUE,
	TAG_DONE);

 /* update sub box... */
 NewList(&sub_list);
  while (temp) { add_sub(temp->submenu);
		temp=temp->next; }

	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,&sub_list,
		TAG_DONE);
}

/*************************** prepare sub *********************************/

void prepare_sub(void)
{
 struct Gadget *gads[13];
 int x;

 /* disabled */
 gads[0]=istring; gads[1]=is; gads[2]=id; gads[3]=il;
 gads[4]=tstring; gads[5]=ts; gads[6]=td; 
 
 
 for (x=0;x<7;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,TRUE,
		TAG_DONE);

 /* abled */
 gads[0]=sstring; gads[1]=sa; gads[2]=ss; gads[3]=dis; gads[4]=chec; 
 gads[5]=tog; gads[6]=func; gads[7 ]=bar; gads[8 ]=ta; gads[9]=sd;
 gads[10]=ia; gads[11]=key;

for (x=0;x<12;x++)
	GT_SetGadgetAttrs(gads[x],window,NULL,
		GA_Disabled,FALSE,
		TAG_DONE);
	
 curr_box=3;

 /* enter visual response */
 GT_SetGadgetAttrs(select,window,NULL,
	GTTX_Text,"S",
	TAG_DONE);
 GT_SetGadgetAttrs(stype,window,NULL,
	GTTX_Text,curr_s->submenu,
	TAG_DONE);
 GT_SetGadgetAttrs(dis,window,NULL,
	GTCB_Checked,curr_s->disabled,
	TAG_DONE);
 GT_SetGadgetAttrs(bar,window,NULL,
	GTCB_Checked,curr_s->menubar,
	TAG_DONE);
 GT_SetGadgetAttrs(chec,window,NULL,
	GTCB_Checked,curr_s->checked,
	TAG_DONE);
 GT_SetGadgetAttrs(tog,window,NULL,
	GTCY_Active,curr_s->type,
	TAG_DONE);
 GT_SetGadgetAttrs(func,window,NULL,
	GTST_String,curr_s->function,
	TAG_DONE);
 GT_SetGadgetAttrs(key,window,NULL,
	GTST_String,curr_s->hotkey,
	TAG_DONE);

/* handle MX disabling of Checked */
if (curr_s->type == 2)
     GT_SetGadgetAttrs(chec,window,NULL,
	GA_Disabled,TRUE,
	TAG_DONE);

}


/****************************** swap_sub *************************************/

void swapit_sub (void)
{
 struct sub_box *temp;
 struct Node *node1,*node2;
 int ord;

  if ( !(temp=(struct sub_box *)calloc(sizeof(struct sub_box),1) ))
	abort_me("Out of memory");
 
 if (swap_sub != curr_s)
{

 /* find nodes */
 node1 = node2 = sub_list.lh_Head;
 for (ord=0;ord < curr_s->index;ord++)
	node1 = node1->ln_Succ;
 for (ord=0;ord < swap_sub->index;ord++)
	node2 = node2->ln_Succ;

 /* swap items's data */
 temp->disabled = curr_s->disabled;
 strcpy(temp->submenu,curr_s->submenu);
 temp->menubar = curr_s->menubar;
 temp->type = curr_s->type;
 strcpy(temp->function,curr_s->function);
 temp->checked = curr_s->checked;
 strcpy(temp->hotkey,curr_s->hotkey);

 curr_s->disabled = swap_sub->disabled;
 strcpy(curr_s->submenu,swap_sub->submenu);
 curr_s->menubar = swap_sub->menubar;
 curr_s->type = swap_sub->type;
 curr_s->checked = swap_sub->checked;
 strcpy(curr_s->function,swap_sub->function); 
 strcpy(curr_s->hotkey,swap_sub->hotkey);

 swap_sub->disabled = temp->disabled;
 strcpy(swap_sub->submenu,temp->submenu);
 swap_sub->menubar = temp->menubar;
 swap_sub->type = temp->type;
 swap_sub->checked = temp->checked;
 strcpy(swap_sub->function,temp->function); 
 strcpy(swap_sub->hotkey,temp->hotkey);

 free(temp);

 /* fix nodes now */ 
 node2->ln_Name = swap_sub->submenu;
 node1->ln_Name = curr_s->submenu;

 }
 swap_sub = NULL;
 ord_item = curr_s->index;

	GT_SetGadgetAttrs(sl,window,NULL,
		GTLV_Labels,&sub_list,
		GTLV_Selected,curr_s->index,
		TAG_DONE);
	GT_SetGadgetAttrs(sstring,window,NULL,
		GTST_String,curr_s->submenu,
		TAG_DONE);
}

/************************* swapit_it ***************************************/

void swapit_it (void)
{
 struct item_box *temp;
 struct Node *node1,*node2;
 int ord;

  if ( !(temp=(struct item_box *)calloc(sizeof(struct item_box),1) ))
	abort_me("Out of memory");
 
 if (swap_it != curr_i)
{

 /* find nodes */
 node1 = node2 = it_list.lh_Head;
 for (ord=0;ord < curr_i->index;ord++)
	node1 = node1->ln_Succ;
 for (ord=0;ord < swap_it->index;ord++)
	node2 = node2->ln_Succ;

 /* swap items's data */
 temp->disabled = curr_i->disabled;
 temp->submenu = curr_i->submenu;
 strcpy(temp->item,curr_i->item);
 temp->menubar = curr_i->menubar;
 temp->type = curr_i->type;
 strcpy(temp->function,curr_i->function);
 temp->checked = curr_i->checked;
 strcpy(temp->hotkey,curr_i->hotkey);

 curr_i->submenu = swap_it->submenu;
 curr_i->disabled = swap_it->disabled;
 strcpy(curr_i->item,swap_it->item);
 curr_i->menubar = swap_it->menubar;
 curr_i->type = swap_it->type;
 curr_i->checked = swap_it->checked;
 strcpy(curr_i->function,swap_it->function); 
 strcpy(curr_i->hotkey, swap_it->hotkey);

 swap_it->submenu = temp->submenu;
 swap_it->disabled = temp->disabled;
 strcpy(swap_it->item,temp->item);
 swap_it->menubar = temp->menubar;
 swap_it->type = temp->type;
 swap_it->checked = temp->checked;
 strcpy(swap_it->function,temp->function); 
 strcpy(swap_it->hotkey,temp->hotkey);

 free(temp);

 /* fix nodes now */ 
 node2->ln_Name = swap_it->item;
 node1->ln_Name = curr_i->item;

 }
 swap_it = NULL;
 ord_item = curr_i->index;

	GT_SetGadgetAttrs(il,window,NULL,
		GTLV_Labels,&it_list,
		GTLV_Selected,curr_i->index,
		TAG_DONE);
	GT_SetGadgetAttrs(istring,window,NULL,
		GTST_String,curr_i->item,
		TAG_DONE);
}


/********************** swapit ********************************************/

void swapit (void)
{
 struct title_box *temp;
 struct Node *node1,*node2;
 int ord;

  if ( !(temp=(struct title_box *)calloc(sizeof(struct title_box),1) ))
	abort_me("Out of memory");
 
 if (swap_tit != curr_t)
{

 /* find nodes */
 node1 = node2 = tit_list.lh_Head;
 for (ord=0;ord < curr_t->index;ord++)
	node1 = node1->ln_Succ;
 for (ord=0;ord < swap_tit->index;ord++)
	node2 = node2->ln_Succ;

 /* swap title's data */
 temp->disabled = curr_t->disabled;
 temp->items = curr_t->items;
 strcpy(temp->title,curr_t->title);

 curr_t->items = swap_tit->items;
 curr_t->disabled = swap_tit->disabled;
 strcpy(curr_t->title,swap_tit->title);

 swap_tit->items = temp->items;
 swap_tit->disabled = temp->disabled;
 strcpy(swap_tit->title,temp->title);

 free(temp);

 /* fix nodes now */ 
 node2->ln_Name = swap_tit->title;
 node1->ln_Name = curr_t->title;

 }
 swap_tit = NULL;
 ord_title = curr_t->index;

	GT_SetGadgetAttrs(tl,window,NULL,
		GTLV_Labels,&tit_list,
		GTLV_Selected,curr_t->index,
		TAG_DONE);
	GT_SetGadgetAttrs(tstring,window,NULL,
		GTST_String,curr_t->title,
		TAG_DONE);
}


/************************************* remove item ********************/

void rem_item(struct item_box *curr)
{
 struct item_box *temp = curr;
 struct Node *node;
 int ord,x;

 x=temp->index;

 curr_i = curr_t->items;

 /* remove link */
 if (temp->prev ) temp->prev->next = temp->next;
	else if (temp->next) curr_t->items = curr_i = temp->next;
	else curr_t->items = curr_i = NULL;

 if (temp->next ) temp->next->prev = temp->prev;
 

 /* update indices */
 temp=temp->next;
 while(temp) { temp->index--;temp=temp->next;}
 
 /* free node */
 node = it_list.lh_Head;
 for (ord=0;ord < x;ord++)
	node=node->ln_Succ;

 Remove(node);
 /*free(node);*/

 /* free its sub_menus*/
 if (curr->submenu) freeall_subs(curr->submenu);
 free(curr);
}

/********************************* remove sub *****************************/

void rem_sub(struct sub_box *curr)
{
 struct sub_box *temp = curr;
 struct Node *node;
 int ord,x;

 x=temp->index;

 curr_s = curr_i->submenu;

 /* remove link */
 if (temp->prev ) temp->prev->next = temp->next;
	else if (temp->next) curr_i->submenu = curr_s = temp->next;
	else curr_i->submenu = curr_s = NULL;

 if (temp->next ) temp->next->prev = temp->prev;
 

 /* update indices */
 temp=temp->next;
 while(temp) { temp->index--;temp=temp->next;}
 
 /* free node */
 node = sub_list.lh_Head;
 for (ord=0;ord < x;ord++)
	node=node->ln_Succ;

 Remove(node);
 /*free(node);*/

 free(curr);
}


/********************************* freeall items ************************/

void freeall_items(struct item_box *curr)
{
  struct item_box *temp = curr;

   while (curr)
	{
	  temp=curr->next;
	  if (curr->submenu) freeall_subs (curr->submenu);
	  free(curr);
	  curr=temp;
	}
}

/******************************* freeall subs ***************************/

void freeall_subs(struct sub_box *curr)
{
  struct sub_box *temp = curr;

  while (curr)
	{
	  temp=curr->next;
	  free(curr);
	  curr=temp;
	}
}


/********************************** remove title ***************************/

void rem_title(struct title_box *curr)
{
 struct title_box *temp = curr;
 struct Node *node;
 int ord,x;

 x=temp->index;

 curr_t = topt;
 /* remove link */
 if (temp->prev ) temp->prev->next = temp->next;
	else if (temp->next) topt = curr_t = temp->next;
	else  topt=curr_t=NULL;

 if (temp->next ) temp->next->prev = temp->prev;
 

 /* update indices */
 temp=temp->next;
 while(temp) { temp->index--;temp=temp->next;}
 
 /* free item,sub menus */

 /* free node */
 node = tit_list.lh_Head;
 for (ord=0;ord < x;ord++)
	node=node->ln_Succ;

 Remove(node);
 /*free(node);*/

 /* free title */
 if (curr->items) freeall_items(curr->items);
 free(curr);
}


/******************************** locate sub ****************************/

struct sub_box *locate_sub(UWORD code)
{
  struct sub_box *temp = curr_i->submenu;

  while ((temp->index != code) && temp)
	temp=temp->next;

  return(temp);
}

/**************************** locate item ********************************/

struct item_box *locate_item(UWORD code)
{
  struct item_box *temp = curr_t->items;

  while ((temp->index != code) && temp)
	temp=temp->next;

  return(temp);
}

/*************************** locate title ********************************/

struct title_box *locate_title(UWORD code)
{
  struct title_box *temp = topt;

  while ((temp->index != code) && temp)
	temp=temp->next;

  return(temp);
}

/****************************** change sub *****************************/

void change_sub(UWORD code, char *nt)
{
 struct sub_box *temp=curr_i->submenu;

 while((temp->index != code) && temp)
	temp=temp->next;

 if (temp)
	{
	 strcpy(temp->submenu,nt);
	 curr_s = temp;
	}
}


/***************************** change item ****************************/

void change_item(UWORD code, char *nt)
{
 struct item_box *temp=curr_t->items;

 while((temp->index != code) && temp)
	temp=temp->next;

 if (temp)
	{
	  strcpy(temp->item,nt);
	  curr_i = temp;
	}
}

/***************************** change title ****************************/

void change_title(UWORD code, char *nt)
{
 struct title_box *temp=topt;

 while((temp->index != code) && temp)
	temp=temp->next;

 if (temp){
	   strcpy(temp->title,nt);
	   curr_t = temp;
	 }
}

/************************** add title ***********************************/

void add_title(char *nt)
{
 struct Node *node;

 node=(struct Node *)AllocRemember(&rmem,sizeof(struct Node), MEMF_CLEAR);
      if (!node)
          abort_me("couldn't allocate LISTVIEW list.");
 node->ln_Name = nt;
 AddTail(&tit_list,node);
 
}


/****************** add item *******************************************/

void add_item(char *nt)
{
 struct Node *node;

 node=(struct Node *)AllocRemember(&rmem,sizeof(struct Node), MEMF_CLEAR);
      if (!node)
          abort_me("couldn't allocate LISTVIEW list.");
 node->ln_Name = nt;
 AddTail(&it_list,node);
 
}


/********************** add sub *****************************************/

void add_sub(char *nt)
{
 struct Node *node;

 node=(struct Node *)AllocRemember(&rmem,sizeof(struct Node), MEMF_CLEAR);
      if (!node)
          abort_me("couldn't allocate LISTVIEW list.");
 node->ln_Name = nt;
 AddTail(&sub_list,node);
 
}

/************* new title ***********************************************/
struct title_box *new_title(struct title_box *curr)
{
  struct title_box *temp1, *temp2;


  if ( !(temp1=(struct title_box *)calloc(1,sizeof(struct title_box)) ))
	abort_me("Out of memory");
 
  strcpy(temp1->title,"<none>");
  temp1->disabled = FALSE;
 
  if (curr == NULL) 
	{
	curr = topt = temp1;
	curr->index = 0;
	curr->next = curr->prev = NULL;
	curr->items = NULL;

	}
  else {
	/* add new one at end */
	while (curr->next != NULL) curr = curr->next;

	temp2 = curr;
	curr = temp1;
	curr->index = temp2->index+1;
	curr->next = temp2->next;
	temp2->next = curr;
	curr->prev = temp2;
	curr->items = NULL;

	/* maintain proper indices */
/*	while(temp1->next)
	 	{
		 temp1=temp1->next;
		 temp1->index++;
		}*/
	}

return(curr);
}


/************* new item ************************************************/

struct item_box *new_item(struct item_box *curr)
{
  struct item_box *temp1, *temp2;

  if ( !(temp1=(struct item_box *)calloc(1,sizeof(struct item_box )) ))
	abort_me("Out of memory");


  strcpy(temp1->item,"<item>");
  temp1->disabled = FALSE;
  temp1->menubar = FALSE;
  temp1->checked = FALSE;
  temp1->type = NORM;
  strcpy(temp1->hotkey,"");
 

  if (curr_t->items == NULL) 
	{
	curr_t->items = temp1;
	strcpy(curr_t->items->function,"");
	curr_t->items->next = curr_t->items->prev = NULL;
	curr_t->items->submenu = NULL;
	curr_t->items->index = 0;
	return(curr_t->items);
	}
  else {
	/* add new one at end*/
	while (curr->next != NULL) curr = curr->next;	

	temp2 = curr;
	curr = temp1;
	curr->next = temp2->next;
	temp2->next = curr;
	curr->prev = temp2;
	curr->submenu = NULL;
	strcpy(curr->function,"");
	curr->index = temp2->index+1;

	/* maintain proper indices */
/*	while(temp1->next)
	 	{
		 temp1=temp1->next;
		 temp1->index++;
		}*/
	}

return(curr);
}

/************* new sub *************************************************/

struct sub_box *new_sub(struct sub_box *curr)
{
  struct sub_box *temp1, *temp2;

  if ( !(temp1=(struct sub_box *)calloc(1,sizeof(struct sub_box )) ))
	abort_me("Out of memory");

  strcpy(temp1->submenu,"<sub>");
  temp1->disabled = FALSE;
  temp1->menubar = FALSE;
  temp1->checked = FALSE;
  temp1->type = NORM;
  strcpy(temp1->hotkey,"");
  
  if (curr_i->submenu == NULL) 
	{
	curr_i->submenu = temp1;
	curr_i->submenu->next = curr_i->submenu->prev = NULL;
	strcpy(curr_i->submenu->function,"");
	curr_i->submenu->index = 0;
	return(curr_i->submenu);
	}
  else {
	/* add new one at end */
	while (curr->next) curr = curr->next;

	temp2 = curr;
	curr = temp1;
	curr->next = temp2->next;
	temp2->next = curr;
	curr->prev = temp2;
	strcpy(curr->function,"");
	curr->index = temp2->index+1;

	/* maintain proper indices */
	while(temp1->next)
	 	{
		 temp1=temp1->next;
		 temp1->index++;
		}
	}

return(curr);
}


/***************** clone current parameters *********************************/

void old_menu(void)
{
  struct title_box *temp= topt;
  struct title_box *newt = NULL;

  if (topt) {
	
  /* grab first one */
  if ( !(newtop=newt=(struct title_box *)calloc(1,sizeof(struct title_box)) ))
	abort_me("Out of memory");
   
/*  printf("%s\n",temp->title); */
  newt->disabled = temp->disabled;
  strcpy(newt->title,temp->title);
  newt->next = NULL;
  newt->prev = NULL; 
  newt->items = NULL;
  newt->index = temp->index;
  if (temp->items)  newt->items = grabitem(temp->items);

  temp = temp->next;
  
  while (temp) {
  newt->next =grabtitle(temp);
  newt->next->prev = newt;
  newt=newt->next;
  temp = temp->next;
   }
 } else newtop = NULL;
}

/********************** grabtitle *****************************************/

struct title_box *grabtitle(struct title_box *temp)
{
  struct title_box *newt = NULL;
  
  if ( !(newt=(struct title_box *)calloc(1,sizeof(struct title_box)) ))
	abort_me("Out of memory");
   
 newt->disabled = temp->disabled;
 strcpy(newt->title,temp->title);
 newt->next = NULL;
 newt->index = temp->index;
 
 newt->items = NULL;
 if (temp->items)  newt->items = grabitem(temp->items);

 return(newt);
}

/******************* grabitem ********************************************/

struct item_box *grabitem(struct item_box *tempi)
{
 struct item_box *newi = NULL;
 struct item_box *newi2 = NULL;

 /* get first one */
 if ( !(newi=newi2=(struct item_box *)calloc(1,sizeof(struct item_box)) ))
	abort_me("Out of memory");

 newi->disabled = tempi->disabled;
 strcpy(newi->item,tempi->item);
 newi->menubar = tempi->menubar;
 newi->type = tempi->type;
 newi->checked = tempi->checked;
 strcpy(newi->function,tempi->function); 
 strcpy(newi->hotkey, tempi->hotkey);
 newi->prev = newi->next = NULL;
 newi->index = tempi->index;

 newi->submenu = NULL;
 if (tempi->submenu) newi->submenu = grabsub(tempi->submenu); 
 
 tempi=tempi->next;

  while (tempi){
      if ( !(newi2->next=(struct item_box *)calloc(1,sizeof(struct item_box)) ))
	abort_me("Out of memory");    
            
      newi2->next->prev = newi2;
      newi2->next->next = NULL;
      newi2 = newi2->next;

        newi2->index = tempi->index;
        newi2->disabled = tempi->disabled;
 	strcpy(newi2->item,tempi->item);
	newi2->menubar = tempi->menubar;
 	newi2->type = tempi->type;
 	newi2->checked = tempi->checked;
 	strcpy(newi2->function,tempi->function); 
 	strcpy(newi2->hotkey, tempi->hotkey);
	if (tempi->submenu) newi2->submenu = grabsub(tempi->submenu); 
	tempi=tempi->next;
	}

 return(newi);
}

/******************** grabsub *********************************************/

struct sub_box *grabsub(struct sub_box *temps)
{
 struct sub_box *news,*news2;

 /* get first */
 if ( !(news=news2=(struct sub_box *)calloc(1,sizeof(struct sub_box )) ))
	abort_me("Out of memory");

 news->disabled = temps->disabled;
 strcpy(news->submenu,temps->submenu);
 news->menubar = temps->menubar;
 news->type = temps->type;
 strcpy(news->function,temps->function);
 news->checked = temps->checked;
 strcpy(news->hotkey,temps->hotkey);
 news->next=news->prev = NULL;
 news->index = temps->index;

 temps=temps->next;
 
 while(temps)
     {
      if ( !(news2->next=(struct sub_box *)calloc(1,sizeof(struct sub_box )) ))
	abort_me("Out of memory");

      news2->next->prev = news2;
      news2->next->next = NULL;
      news2=news2->next;

	 news2->index = temps->index;
	 news2->disabled = temps->disabled;
	 strcpy(news2->submenu,temps->submenu);
	 news2->menubar = temps->menubar;
	 news2->type = temps->type;
	 strcpy(news2->function,temps->function);
	 news2->checked = temps->checked;
	 strcpy(news2->hotkey,temps->hotkey);

       temps=temps->next;
	}

return(news);
}

/**************** free menu structure *************************************/

void free_allmenu (struct title_box *top)
{
 struct title_box *temp = top;
 struct title_box *temp2 = NULL;
 struct item_box  *tempi, *tempi2;
 struct sub_box   *temps, *temps2;

 while (temp)
 	{
	 temp2 = temp;
	  if (temp->items) {
		tempi = tempi2 = temp->items;
		while(tempi)
			{
			  if (tempi->submenu){
			  temps = temps2 = tempi->submenu;
			  while(temps)
				{
				  if (temps->next) temps=temps->next;
				  else temps=NULL;
				  free(temps2);
				  temps2 = temps;
				}}
			   if (tempi->next) tempi=tempi->next;
			   else tempi=NULL;
			   free(tempi2);
			   tempi2 = tempi;
			}}
	  if (temp->next) temp=temp->next;
	  else temp=NULL;
	  free(temp2);
	  temp2=temp;
	}
}


