/*

Directory Opus 4
Original GPL release version 4.12
Copyright 1993-2000 Jonathan Potter

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

All users of Directory Opus 4 (including versions distributed
under the GPL) are entitled to upgrade to the latest version of
Directory Opus version 5 at a reduced price. Please see
http://www.gpsoft.com.au for more information.

The release of Directory Opus 4 under the GPL in NO WAY affects
the existing commercial status of Directory Opus 5.

*/

#include "config.h"

static struct dopusgadgetbanks *currentbank,*selbank;

dogadgetconfig()
{
	ULONG class;
	USHORT code,gadgetid;
	struct ConfigUndo *undo;
	struct DOpusRemember *gadkey=NULL;
	struct dopusgadgetbanks *bank,*bank2;
	struct newdopusfunction *secondgad;
	struct Gadget *gad;
	struct Border *unselborder,*selborder;
	char buf[80];
	int a,b,x,y,mode=-1;

	if (!(gadgads=(struct Gadget *)LAllocRemember(&gadkey,sizeof(struct Gadget)*GADCOUNT,
		MEMF_CLEAR))) return(0);

	CreateGadgetBorders(&gadkey,
		80,10,
		&selborder,&unselborder,
		0,
		screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen);

	selgad=NULL; selbank=NULL; seligad=NULL;

	x=x_off+38; y=y_off+4;
	for (a=0;a<GADCOUNT;a++) {
		gadgads[a].NextGadget=(a<GADCOUNT-1)?&gadgads[a+1]:NULL;
		gadgads[a].LeftEdge=x;
		gadgads[a].TopEdge=y;
		gadgads[a].Width=80;
		gadgads[a].Height=10;
		gadgads[a].Flags=(selborder)?GFLG_GADGHIMAGE:GFLG_GADGHCOMP;
		gadgads[a].Activation=GACT_RELVERIFY;
		gadgads[a].GadgetType=GTYP_BOOLGADGET;
		gadgads[a].GadgetID=a+100;
		gadgads[a].GadgetRender=unselborder;
		gadgads[a].SelectRender=selborder;
		if ((x+=80)>=x_off+598) {
			x=x_off+38;
			if ((y+=10)==y_off+64) y+=14;
		}
	}

	paint_state=0;
	showconfigscreen(CFG_GADGET);
	ClearMenuStrip(Window);
	projectmenu.NextMenu=&gadrowsmenu;
	neatstuffitem.Flags&=~CHECKED;
	neatstuffmenu.LeftEdge=272;

	for (a=0;a<5;a++) {
		if (config->gadgetrows==rowtrans[a]) gadrowsitems[a].Flags|=CHECKED;
		else gadrowsitems[a].Flags&=~CHECKED;
	}
	FSSetMenuStrip(Window,&projectmenu);
	undo=makeundo(UNDO_GADGET);
	currentbank=firstbank;
	showgadgets(currentbank,1);
	nextbankrmb.x=maingad[0].LeftEdge;
	nextbankrmb.y=maingad[0].TopEdge;
	insertbankrmb.x=maingad[1].LeftEdge;
	insertbankrmb.y=maingad[1].TopEdge;
	fixrmbimage(&nextbankrmb,maingad,1,-1,-1);

	FOREVER {
		Wait(1<<Window->UserPort->mp_SigBit);
		while (IMsg=getintuimsg()) {
			class=IMsg->Class;
			code=IMsg->Code;
			x=IMsg->MouseX;
			y=IMsg->MouseY;
			if (class==IDCMP_GADGETUP || class==IDCMP_GADGETDOWN) {
				gad=(struct Gadget *)IMsg->IAddress;
				gadgetid=gad->GadgetID;
			}
			ReplyMsg((struct Message *)IMsg);
			switch (class) {
				case IDCMP_MENUPICK:
					if (code==MENUNULL) break;
					switch (MENUNUM(code)) {
						case 0:
							if (selgad) {
								if (selbank==currentbank) select_gadget(seligad,0);
								selbank=NULL; seligad=NULL; selgad=NULL;
							}
							if (mode>-1) {
								select_gadget(&maingad[mode],0);
								mode=-1;
							}
							dogadgetinfo(NULL);
							switch ((a=ITEMNUM(code))) {
								case 0:
								case 1:
									if (doload(CFG_GADGET,a)) {
										if (bank=firstbank) {
											while (bank->next) bank=bank->next;
											currentbank=bank;
											showgadgets(currentbank,1);
											if (a) dogadgetinfo(cfg_string[STR_NEW_GADGET_BANKS_APPENDED]);
											else dogadgetinfo(cfg_string[STR_DEFAULT_GADGET_BANKS_APPENDED]);
										}
									}
									break;
							}
							break;
						case 1:
							config->gadgetrows=rowtrans[ITEMNUM(code)];
							break;
						case 2:
							if (ITEMNUM(code)==0) {
								if (neatstuffitem.Flags&CHECKED) {
									if (!(paint_state=get_paint_colours(&paint_fg,&paint_bg,CFG_GADGET))) {
										ClearMenuStrip(Window);
										neatstuffitem.Flags&=~CHECKED;
										FSSetMenuStrip(Window,&projectmenu);
									}
								}
								else paint_state=0;
								showgadgets(currentbank,0);
							}
							break;
					}
					break;

				case IDCMP_MOUSEBUTTONS:
					if (code==MENUDOWN) {
						fixrmbimage(&nextbankrmb,maingad,0,x,y);
						if ((a=DoRMBGadget(&nextbankrmb,Window))==0) {
							if (currentbank) {
								if (mode==-1) dogadgetinfo(NULL);
								if (selgad && selbank==currentbank) select_gadget(seligad,0);
								bank2=currentbank;
								if (!(bank=lastbank(currentbank))) {
									bank=firstbank;
									while (bank && bank->next) bank=bank->next;
								}
								currentbank=bank;
								if (currentbank!=bank2) showgadgets(currentbank,1);
								if (selgad && selbank==currentbank) select_gadget(seligad,1);
							}
							else dogadgetinfo(cfg_string[STR_NO_GADGET_BANKS_CONFIGURED]);
						}
						else if (a==1) makenewbank(1);
						fixrmbimage(&nextbankrmb,maingad,1,-1,-1);
					}
					break;

				case IDCMP_GADGETUP:
					if (gadgetid<GAD_OKAY) {
						if (selgad) {
							if (gadgetid!=GAD_NEXTBANK) selgad=NULL;
							if (selbank==currentbank) select_gadget(seligad,0);
							if (gadgetid!=GAD_NEXTBANK) {
								selbank=NULL; seligad=NULL;
							}
						}
						if (mode==gadgetid) {
							mode=-1;
							dogadgetinfo(NULL);
							break;
						}
						if (gadgetid!=GAD_NEXTBANK && mode>-1) {
							select_gadget(&maingad[mode],0);
							mode=-1;
						}
						if (gadgetid!=GAD_NEWBANK && !firstbank) {
							dogadgetinfo(cfg_string[STR_NO_GADGET_BANKS_CONFIGURED]);
							if (gad->Activation&GACT_TOGGLESELECT) select_gadget(gad,0);
							break;
						}
					}
					else if (gadgetid>=100) {
						if (!firstbank) {
							dogadgetinfo(cfg_string[STR_NO_GADGET_BANKS_CONFIGURED]);
							break;
						}
						a=gadgetid-100;
						if (mode>-1) {
							if (mode==GAD_DELETEGADGET) {
								selgad=&(currentbank->gadgets[a]);
								clearmenu(selgad);
								selgad->fpen=1; selgad->bpen=0;
								freenewfunction(selgad);
								selgad=NULL;
								dogadgetinfo(cfg_string[STR_GADGET_DELETED]);
								showgadgetname(selgad,gad);
							}
							else if (!selgad) {
								selgad=&(currentbank->gadgets[a]);
								seligad=gad;
								selbank=currentbank;
								select_gadget(gad,1);
								if (mode==GAD_COPYGADGET)
									dogadgetinfo(cfg_string[STR_SELECT_GADGET_TO_COPY]);
								else if (mode==GAD_SWAPGADGET)
									dogadgetinfo(cfg_string[STR_SELECT_GADGET_TO_SWAP]);
							}
							else {
								secondgad=&(currentbank->gadgets[a]);
								if (selgad==secondgad) select_gadget(gad,0);
								else {
									if (mode==GAD_COPYGADGET) {
										freenewfunction(secondgad);
										CopyMem((char *)selgad,(char *)secondgad,sizeof(struct newdopusfunction));
										secondgad->name=getcopy(selgad->name,-1,NULL);
										secondgad->function=getcopy(selgad->function,-1,NULL);
									}
									else if (mode==GAD_SWAPGADGET)
										SwapMem((char *)selgad,(char *)secondgad,sizeof(struct dopusfunction));
									showgadgetname(secondgad,gad);
									if (selbank==currentbank) {
										select_gadget(seligad,0);
										showgadgetname(selgad,seligad);
									}
								}
								selgad=NULL; seligad=NULL; selbank=NULL;
								if (mode==GAD_COPYGADGET)
									dogadgetinfo(cfg_string[STR_SELECT_A_GADGET_TO_COPY]);
								else if (mode==GAD_SWAPGADGET)
									dogadgetinfo(cfg_string[STR_SELECT_FIRST_GADGET_TO_SWAP]);
							}
						}
						else {
							if (paint_state) {
								currentbank->gadgets[a].fpen=paint_fg;
								currentbank->gadgets[a].bpen=paint_bg;
								showgadgetname(&currentbank->gadgets[a],&gadgads[a]);
							}
							else {
								cleanconfigscreen();
								selgad=&(currentbank->gadgets[a]);
								doscreentitle(cfg_string[STR_GADGET_EDIT_SCREEN]);
								editfunction((struct dopusfunction *)selgad,CFG_GADGET,NULL);
								showconfigscreen(CFG_GADGET);
								fixrmbimage(&nextbankrmb,maingad,1,-1,-1);
								selgad=NULL;
								showgadgets(currentbank,1);
							}
						}
						break;
					}
					switch (gadgetid) {
						case GAD_NEXTBANK:
							bank2=currentbank;
							if (!(currentbank=currentbank->next)) currentbank=firstbank;
							if (currentbank!=bank2) showgadgets(currentbank,1);
							if (mode==-1) dogadgetinfo(NULL);
							break;
						case GAD_NEWBANK:
							makenewbank(0);
							break;
						case GAD_COPYBANK:
							dogadgetinfo(NULL);
							buf[0]=0;
							if (!getstring(cfg_string[STR_ENTER_BANK_TO_COPY],buf,5,SRF_LONGINT|SRF_CENTJUST))
								break;
							a=atoi(buf)-1;
							if (a<0) break;
							bank2=currentbank;
							bank=firstbank;
							for (b=0;b<a;b++) if (!(bank=bank->next)) break;
							if (bank) {
								showgadgets(bank,1);
								if (!(request(cfg_string[STR_BANK_ALREADY_EXISTS]))) {
									showgadgets(currentbank,1);
									break;
								}
								freegadgetbank(bank,0);
								currentbank=bank;
								dogadgetinfo(cfg_string[STR_GADGET_BANK_COPIED]);
							}
							else if (!makenewbank(0)) break;
							CopyMem((char *)bank2,(char *)currentbank,sizeof(struct newdopusfunction)*GADCOUNT);
							copygadgets(bank2,currentbank,NULL);
							showgadgets(currentbank,1);
							break;
						case GAD_SWAPBANK:
							dogadgetinfo(NULL);
							buf[0]=0;
							if (!getstring(cfg_string[STR_ENTER_BANK_TO_SWAP],buf,5,SRF_LONGINT|SRF_CENTJUST))
								break;
							a=atoi(buf)-1;
							if (a<0) break;
							bank=firstbank;
							for (b=0;b<a;b++) if (!(bank=bank->next)) break;
							if (!bank) {
								dogadgetinfo(cfg_string[STR_BANK_DOES_NOT_EXIST]);
								break;
							}
							if (bank==currentbank) break;
							SwapMem((char *)bank,(char *)currentbank,sizeof(struct newdopusfunction)*GADCOUNT);
							showgadgets(currentbank,1);
							dogadgetinfo(cfg_string[STR_BANKS_SWAPPED]);
							break;
						case GAD_DELETEBANK:
							dogadgetinfo(NULL);
							if (currentbank==firstbank && !currentbank->next) {
								if (!request(cfg_string[STR_ONLY_BANK_CONFIGURED])) break;
							}
							else if (!request(cfg_string[STR_REALLY_DELETE_BANK]))
								break;
							if (bank=lastbank(currentbank)) bank->next=currentbank->next;
							if (firstbank==currentbank) firstbank=currentbank->next;
							freegadgetbank(currentbank,1);
							if (bank && bank->next) currentbank=bank->next;
							else if (bank) currentbank=bank;
							else currentbank=firstbank;
							dogadgetinfo(cfg_string[STR_BANK_DELETED]);
							showgadgets(currentbank,1);
							break;
						case GAD_COPYGADGET:
							mode=GAD_COPYGADGET;
							dogadgetinfo(cfg_string[STR_SELECT_A_GADGET_TO_COPY]);
							break;
						case GAD_SWAPGADGET:
							mode=GAD_SWAPGADGET;
							dogadgetinfo(cfg_string[STR_SELECT_FIRST_GADGET_TO_SWAP]);
							break;
						case GAD_DELETEGADGET:
							mode=GAD_DELETEGADGET;
							dogadgetinfo(cfg_string[STR_SELECT_GADGET_TO_DELETE]);
							break;
						case GAD_CANCEL:
							doundo(undo,UNDO_GADGET);
						case GAD_OKAY:
							doundo(undo,0);
							RemoveGList(Window,gadgads,GADCOUNT);
							LFreeRemember(&gadkey); gadgads=NULL;
							ClearMenuStrip(Window); projectmenu.NextMenu=NULL;
							FSSetMenuStrip(Window,&projectmenu);
							paint_state=0;
							return((gadgetid==GAD_OKAY));
					}
			}
		}
	}
}

void showgadgets(bank,show)
struct dopusgadgetbanks *bank;
int show;
{
	int a;
	struct dopusgadgetbanks *bank2;
	char buf[60],*ptr;

	if (show) {
		for (a=0;a<GADCOUNT;a++) {
			if (bank) {
				showgadgetname(&bank->gadgets[a],&gadgads[a]);
				if (selgad==&bank->gadgets[a]) select_gadget(&gadgads[a],1);
			}
			else showgadgetname(NULL,&gadgads[a]);
		}
	}
	if (bank) {
		bank2=firstbank; a=0;
		while (bank2 && bank2!=bank) {
			++a;
			bank2=bank2->next;
		}
		lsprintf(buf,"%s %ld",cfg_string[STR_GADGET_BANK_NUMBER],a+1);
		if (paint_state) strcat(buf,cfg_string[STR_PAINT_STATE]);
		ptr=buf;
	}
	else ptr=cfg_string[STR_GADGET_SCREEN_NO_BANKS];
	doscreentitle(ptr);
}

void showgadgetname(gad,gadget)
struct newdopusfunction *gad;
struct Gadget *gadget;
{
	int a,x,y;

	x=gadget->LeftEdge;
	y=gadget->TopEdge;
	if (gad) SetAPen(rp,screen_pens[gad->bpen].pen);
	else SetAPen(rp,screen_pens[0].pen);
	RectFill(rp,x+2,y+1,x+77,y+8);
	if (gad) {
		SetAPen(rp,screen_pens[gad->fpen].pen);
		SetBPen(rp,screen_pens[gad->bpen].pen);
		if (gad->name && gad->name[0]) {
			Move(rp,x+((80-(((a=strlen(gad->name))>9?(a=9):a)*8))/2),y+7);
			Text(rp,gad->name,a);
		}
	}
	SetBPen(rp,screen_pens[0].pen);
}

makenewbank(insert)
int insert;
{
	struct dopusgadgetbanks *bank,*bank2;
	int a;

	if (!(bank=AllocMem(sizeof(struct dopusgadgetbanks),MEMF_CLEAR))) {
		dogadgetinfo(cfg_string[STR_NO_MEMORY_FOR_NEW_BANK]);
		return(0);
	}
	for (a=0;a<GADCOUNT;a++) {
		bank->gadgets[a].stack=4000; bank->gadgets[a].delay=2;
		if (paint_state) {
			bank->gadgets[a].fpen=paint_fg;
			bank->gadgets[a].bpen=paint_bg;
		}
		else bank->gadgets[a].fpen=1;
	}
	if (insert && firstbank) {
		if (currentbank==firstbank) {
			bank->next=firstbank;
			firstbank=bank;
		}
		else {
			bank2=firstbank;
			while (bank2->next) {
				if (bank2->next==currentbank) break;
				bank2=bank2->next;
			}
			if (bank2->next==currentbank) {
				bank2->next=bank;
				bank->next=currentbank;
			}
			else bank2->next=bank;
		}
	}
	else {
		if (!firstbank) firstbank=bank;
		else {
			bank2=firstbank;
			while (bank2->next) bank2=bank2->next;
			bank2->next=bank;
		}
	}
	currentbank=bank;
	showgadgets(currentbank,1);
	dogadgetinfo(cfg_string[STR_NEW_BANK_CREATED]);
	return(1);
}

struct dopusgadgetbanks *lastbank(bank)
struct dopusgadgetbanks *bank;
{
	struct dopusgadgetbanks *temp;

	temp=firstbank;
	while (temp && temp->next!=bank) temp=temp->next;
	return(temp);
}

void dogadgetinfo(str)
char *str;
{
	int tx,ex,len,x;

	x=(Window->Width-580)/2;

	Do3DBox(rp,
		x,y_off+144,
		580,10,
		screen_pens[config->gadgetbotcol].pen,screen_pens[config->gadgettopcol].pen);
	SetDrMd(rp,JAM2);

	tx=x;
	if (str) {
		SetAPen(rp,screen_pens[1].pen);
		tx+=(580-((len=strlen(str))*8))/2;
		UScoreText(rp,str,tx,y_off+151,-1);
		ex=rp->cp_x;
	}
	else ex=x;
	SetAPen(rp,screen_pens[0].pen);
	if (tx>x) RectFill(rp,x,y_off+145,tx-1,y_off+153);
	if (ex<x+579) RectFill(rp,ex,y_off+145,x+579,y_off+153);
}

static struct newdopusfunction *selmenu;
static int menuoffset;

domenuconfig()
{
	ULONG class;
	USHORT code,gadgetid;
	struct ConfigUndo *undo;
	struct Gadget *gad;
	struct DOpusRemember *menukey=NULL;
	struct newdopusfunction *secondmenu;
	int a,b,x,y,mode=-1,gid,mnum=-1,omnum;
	char buf[100];

	if (!(menugads=(struct Gadget *)LAllocRemember(&menukey,sizeof(struct Gadget)*
		(MENUCOUNT+5-(HIDDENLINES*5)),MEMF_CLEAR))) return(0);
	selgad=NULL; selbank=NULL;
	menuoffset=0;

	a=0; gid=100;
	for (x=0;x<5;x++,gid+=HIDDENLINES) {
		for (y=0;y<20-HIDDENLINES;y++,a++) {
			menugads[a].NextGadget=(a<MENUCOUNT+4-(HIDDENLINES*5))?&menugads[a+1]:NULL;
			menugads[a].LeftEdge=(x*120)+x_off+12;
			menugads[a].TopEdge=(y*8)+y_off+21;
			menugads[a].Width=112;
			menugads[a].Height=8;
			menugads[a].Flags=GADGHCOMP; menugads[a].Activation=RELVERIFY;
			menugads[a].GadgetType=BOOLGADGET;
			menugads[a].GadgetID=gid++;
		}
	}
	gid=200;
	for (x=0;x<5;x++,a++) {
		menugads[a].NextGadget=(x<4)?&menugads[a+1]:NULL;
		menugads[a].LeftEdge=(x*120)+x_off+12;
		menugads[a].TopEdge=y_off+8;
		menugads[a].Width=112;
		menugads[a].Height=8;
		menugads[a].Flags=GADGHCOMP; menugads[a].Activation=RELVERIFY;
		menugads[a].GadgetType=BOOLGADGET;
		menugads[a].GadgetID=gid++;
	}

	fix_slider(&menuslidergads[0]);
	AddGadgetBorders(&menukey,
		&menuslidergads[1],
		2,
		screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen);

	showconfigscreen(CFG_MENU);
	ClearMenuStrip(Window);
	projectmenu.NextMenu=&neatstuffmenu;
	neatstuffitem.Flags&=~CHECKED;
	neatstuffmenu.LeftEdge=140;
	FSSetMenuStrip(Window,&projectmenu);

	paint_state=0;
	undo=makeundo(UNDO_MENU);
	showmenus(7);

	FOREVER {
		Wait(1<<Window->UserPort->mp_SigBit);
		while (IMsg=getintuimsg()) {
			class=IMsg->Class; code=IMsg->Code;
			if (class==GADGETUP || class==GADGETDOWN) {
				gad=(struct Gadget *)IMsg->IAddress;
				gadgetid=gad->GadgetID;
			}
			ReplyMsg((struct Message *)IMsg);
			switch (class) {
				case IDCMP_MENUPICK:
					if (code==MENUNULL) break;
					switch (MENUNUM(code)) {
						case 0:
							if (selmenu) {
								selmenu=NULL;
								showmenus(5);
							}
							dogadgetinfo(NULL);
							if (mode>-1) {
								select_gadget(&maingad[mode],0);
								mode=-1;
							}
							switch ((a=ITEMNUM(code))) {
								case 0:
								case 1:
									if (doload(CFG_MENU,a)) {
										showmenus(5);
										if (a) dogadgetinfo(cfg_string[STR_NEW_MENUS_LOADED]);
										else dogadgetinfo(cfg_string[STR_DEFAULT_MENUS_LOADED]);
									}
									break;
							}
							break;
						case 1:
							if (ITEMNUM(code)==0) {
								if (neatstuffitem.Flags&CHECKED) {
									if (!(paint_state=get_paint_colours(&paint_fg,&paint_bg,CFG_MENU))) {
										ClearMenuStrip(Window);
										neatstuffitem.Flags&=~CHECKED;
										FSSetMenuStrip(Window,&projectmenu);
									}
								}
								else paint_state=0;
								do_menuscreen_title(STR_MENU_SCREEN);
							}
							break;
					}
					break;

				case IDCMP_GADGETUP:
					if (gadgetid<MENU_OKAY) {
						if (selmenu) {
							selmenu=NULL;
							showmenus(5);
						}
						dogadgetinfo(NULL);
						if (mode==gadgetid) {
							mode=-1;
							break;
						}
						if (mode>-1) {
							select_gadget(&maingad[mode],0);
							mode=-1;
						}
					}
					if (gadgetid>199) {
						if ((a=gadgetid-200)<0 || a>4) break;
						if (mode==MENU_DELETEMENU || mode==MENU_SORTMENU ||
							mode==MENU_COPYMENU || mode==MENU_SWAPMENU) {
							gadgetid=100+(a*20);
						}
						else {
							if (getstring(cfg_string[STR_ENTER_MENU_TITLE],config->menutit[a],14,SRF_CENTJUST))
								showmenus(4);
							break;
						}
					}
					if (gadgetid>99 && gadgetid<200) {
						a=(gadgetid-100)+menuoffset;
						omnum=mnum; mnum=a/20;
						if (mode>-1) {
							switch (mode) {
								case MENU_DELETEITEM:	
									clearmenu(&config->menu[a]);
									freenewfunction(&config->menu[a]);
									if (((a+1)%20)!=0) {
										x=((a+20)/20)*20-1;
										y=x-a;
										CopyMem((char *)&config->menu[a+1],&config->menu[a],y*sizeof(struct dopusfunction));
										clearmenu(&config->menu[x]);
										config->menu[x].function=NULL;
										config->menu[x].name=NULL;
									}
									showmenus(1);
									dogadgetinfo(cfg_string[STR_MENU_ITEM_DELETED]);
									break;
								case MENU_INSERTITEM:
									x=((a+20)/20)*20-1;
									freenewfunction(&config->menu[x]);
									for (b=x-1;b>=a;b--)
										CopyMem((char *)&config->menu[b],&config->menu[b+1],sizeof(struct dopusfunction));
									clearmenu(&config->menu[a]);
									config->menu[a].name=NULL;
									config->menu[a].function=NULL;
									showmenus(1);
									dogadgetinfo(cfg_string[STR_MENU_ITEM_INSERTED]);
									break;
								case MENU_DELETEMENU:
									lsprintf(buf,"%s\n%s",
										config->menutit[mnum],
										cfg_string[STR_REALLY_DELETE_THIS_MENU]);
									if (request(buf)) {
										b=(mnum*20)+20;
										for (a=mnum*20;a<b;a++) {
											clearmenu(&config->menu[a]);
											freenewfunction(&config->menu[a]);
										}
										config->menutit[mnum][0]=0;
										showmenus(5);
										dogadgetinfo(cfg_string[STR_MENU_DELETED]);
									}
									break;
								case MENU_SORTMENU:
									sortmenustrip(mnum);
									showmenus(5);
									dogadgetinfo(cfg_string[STR_MENU_SORTED]);
									break;
								default:
									if (!selmenu) {
										selmenu=&config->menu[a];
										HiliteGad(gad,rp);
										switch (mode) {
											case MENU_COPYMENU:
												dogadgetinfo(cfg_string[STR_SELECT_MENU_TO_COPY]);
												break;
											case MENU_SWAPMENU:
												dogadgetinfo(cfg_string[STR_SELECT_MENU_TO_SWAP]);
												break;
											case MENU_COPYITEM:
												dogadgetinfo(cfg_string[STR_SELECT_ITEM_TO_COPY]);
												break;
											case MENU_SWAPITEM:
												dogadgetinfo(cfg_string[STR_SELECT_ITEM_TO_SWAP]);
												break;
										}
									}
									else {
										secondmenu=&config->menu[a];
										if (selmenu==secondmenu) {
											HiliteGad(gad,rp);
											selmenu=NULL;
										}
										else {
											switch (mode) {
												case MENU_COPYITEM:
													freenewfunction(secondmenu);
													CopyMem((char *)selmenu,(char *)secondmenu,sizeof(struct newdopusfunction));
													secondmenu->function=getcopy(selmenu->function,-1,NULL);
													secondmenu->name=getcopy(selmenu->name,-1,NULL);
													break;
												case MENU_SWAPITEM:
													SwapMem((char *)selmenu,(char *)secondmenu,sizeof(struct newdopusfunction));
													break;
												case MENU_COPYMENU:
													if (omnum<0 || mnum==omnum) break;
													CopyMem((char *)&config->menu[omnum*20],(char *)&config->menu[mnum*20],
														sizeof(struct newdopusfunction)*20);
													b=(mnum*20)+20;
													for (a=mnum*20;a<b;a++) {
														config->menu[a].name=getcopy(config->menu[a].name,-1,NULL);
														config->menu[a].function=getcopy(config->menu[a].function,-1,NULL);
													}
													strcpy(config->menutit[mnum],config->menutit[omnum]);
													break;
												case MENU_SWAPMENU:
													if (omnum<0 || mnum==omnum) break;
													SwapMem((char *)&config->menu[omnum*20],(char *)&config->menu[mnum*20],
														sizeof(struct newdopusfunction)*20);
													SwapMem(config->menutit[mnum],config->menutit[omnum],16);
													break;
											}
											selmenu=NULL;
											showmenus(5);
										}
										doinitmenutext(mode);
									}
									break;
							}
						}
						else {
							if (paint_state) {
								config->menu[a].fpen=paint_fg;
								config->menu[a].bpen=paint_bg;
								showmenus(1);
							}
							else {
								cleanconfigscreen();
								selmenu=&config->menu[a];
								doscreentitle(cfg_string[STR_MENU_ITEM_EDIT_SCREEN]);
								editfunction((struct dopusfunction *)selmenu,CFG_MENU,NULL);
								showconfigscreen(CFG_MENU);
								FixSliderPot(Window,&menuslidergads[0],menuoffset,20,20-HIDDENLINES,2);
								selmenu=NULL;
								showmenus(7);
							}
						}
						break;
					}
					switch (gadgetid) {
						case MENU_CANCEL:
							doundo(undo,UNDO_MENU);
						case MENU_OKAY:
							doundo(undo,0);
							RemoveGList(Window,menugads,MENUCOUNT);
							LFreeRemember(&menukey); menugads=NULL;
							ClearMenuStrip(Window); projectmenu.NextMenu=NULL;
							FSSetMenuStrip(Window,&projectmenu);
							paint_state=0;
							return((gadgetid==MENU_OKAY));
					}
					if (gadgetid<MENU_OKAY) mode=doinitmenutext(gadgetid);
					break;

				case IDCMP_GADGETDOWN:
					switch (gadgetid) {
						case MENU_SLIDER:
							a=menuoffset;
							menuoffset=GetSliderPos(&menuslidergads[0],20,20-HIDDENLINES);
							if (a!=menuoffset) showmenus(1);
							FOREVER {
								Wait(1<<Window->UserPort->mp_SigBit);
								while (IMsg=getintuimsg()) {
									class=IMsg->Class;
									ReplyMsg((struct Message *)IMsg);
									if (class==IDCMP_GADGETUP) break;
									if (class==IDCMP_MOUSEMOVE) {
										a=menuoffset;
										menuoffset=GetSliderPos(&menuslidergads[0],20,20-HIDDENLINES);
										if (a!=menuoffset) showmenus(1);
									}
								}
								if (class==IDCMP_GADGETUP) break;
							}
							ShowSlider(Window,&menuslidergads[0]);
							break;
						case MENU_MOVEUP:
							menuoffset-=2;
							if (menuoffset<-1) {
								menuoffset=0;
								break;
							}
						case MENU_MOVEDOWN:
							++menuoffset;
							if (menuoffset>HIDDENLINES) {
								menuoffset=HIDDENLINES;
								break;
							}
							showmenus(1);
							FixSliderPot(Window,&menuslidergads[0],menuoffset,20,20-HIDDENLINES,2);
							Delay(5);
							FOREVER {
								while (IMsg=getintuimsg()) {
									class=IMsg->Class;
									ReplyMsg((struct Message *)IMsg);
									if (class==IDCMP_GADGETUP) break;
								}
								if (class==IDCMP_GADGETUP) break;
								if (gadgetid==MENU_MOVEUP) {
									--menuoffset;
									if (menuoffset<0) {
										menuoffset=0;
										break;
									}
								}
								else {
									++menuoffset;
									if (menuoffset>HIDDENLINES) {
										menuoffset=HIDDENLINES;
										break;
									}
								}
								FixSliderPot(Window,&menuslidergads[0],menuoffset,20,20-HIDDENLINES,2);
								showmenus(1);
							}
							break;
					}
					break;
			}
		}
	}
}

void showmenus(disp)
int disp;
{
	int a,b,x,y;

	a=0;
	SetDrMd(rp,JAM2);
	for (x=0;x<5;x++) {
		if (disp&1) {
			b=(x*20)+menuoffset;
			for (y=0;y<20-HIDDENLINES;y++,a++,b++)
				showmenuname(&config->menu[b],&menugads[a]);
		}
		if (disp&2) {
			do3dbox((x*120)+x_off+12,y_off+21,112,160-(HIDDENLINES*8));
		}
		if (disp&4) {
			showmenutext(config->menutit[x],(x*120)+x_off+12,y_off+8,0,1);
			do3dbox((x*120)+x_off+12,y_off+8,112,8);
		}
	}
}

void showmenuname(menu,gadget)
struct newdopusfunction *menu;
struct Gadget *gadget;
{
	int x,y;

	x=gadget->LeftEdge;
	y=gadget->TopEdge;
	if (menu) {
		showmenutext(menu->name,x,y,menu->fpen,menu->bpen);
		if (menu==selmenu) HiliteGad(gadget,rp);
	}
	else {
		SetAPen(rp,screen_pens[1].pen);
		RectFill(rp,x,y,x+111,y+7);
	}
}

void showmenutext(txt,x,y,fp,bp)
char *txt;
int x,y,fp,bp;
{
	int a;

	SetAPen(rp,screen_pens[fp].pen);
	SetBPen(rp,screen_pens[bp].pen);
	Move(rp,x,y+6);
	if (txt) {
		if ((a=strlen(txt))>0) {
			if (a>14) a=14;
			Text(rp,txt,a);
		}
	}
	else a=0;
	if (a<14) Text(rp,spacestring,14-a);
	SetBPen(rp,screen_pens[0].pen);
}

void clearmenu(menu)
struct newdopusfunction *menu;
{
	menu->which=0;
	menu->stack=4000;
	menu->key=0;
	menu->qual=0;
	menu->type=0;
	menu->pri=0;
	menu->delay=0;
	if (paint_state) {
		menu->fpen=paint_fg;
		menu->bpen=paint_bg;
	}
	else {
		menu->fpen=0;
		menu->bpen=1;
	}
}

doinitmenutext(id)
int id;
{
	int mode=-1;

	switch (id) {
		case MENU_COPYMENU:
			mode=MENU_COPYMENU;
			dogadgetinfo(cfg_string[STR_SELECT_ITEM_IN_MENU_TO_COPY]);
			break;
		case MENU_SWAPMENU:
			mode=MENU_SWAPMENU;
			dogadgetinfo(cfg_string[STR_SELECT_ITEM_IN_MENU_TO_SWAP]);
			break;
		case MENU_DELETEMENU:
			mode=MENU_DELETEMENU;
			dogadgetinfo(cfg_string[STR_SELECT_ITEM_IN_MENU_TO_DELETE]);
			break;
		case MENU_SORTMENU:
			mode=MENU_SORTMENU;
			dogadgetinfo(cfg_string[STR_SELECT_ITEM_IN_MENU_TO_SORT]);
			break;
		case MENU_INSERTITEM:
			mode=MENU_INSERTITEM;
			dogadgetinfo(cfg_string[STR_SELECT_ITEM_TO_INSERT_BEFORE]);
			break;
		case MENU_COPYITEM:
			mode=MENU_COPYITEM;
			dogadgetinfo(cfg_string[STR_SELECT_MENU_ITEM_TO_COPY]);
			break;
		case MENU_SWAPITEM:
			mode=MENU_SWAPITEM;
			dogadgetinfo(cfg_string[STR_SELECT_MENU_ITEM_TO_SWAP]);
			break;
		case MENU_DELETEITEM:
			mode=MENU_DELETEITEM;
			dogadgetinfo(cfg_string[STR_SELECT_MENU_ITEM_TO_DELETE]);
			break;
	}
	return(mode);
}

void sortmenustrip(m)
int m;
{
	int gap,i,j,k;
	char *ptr1,*ptr2,*zstr="\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f";

	m*=20;
	for (gap=10;gap>0;gap/=2)
		for (i=gap;i<20;i++)
			for (j=i-gap;j>=0;j-=gap) {
				k=j+gap;
				ptr1=(config->menu[j+m].name && config->menu[j+m].name[0])?config->menu[j+m].name:zstr;
				ptr2=(config->menu[k+m].name && config->menu[k+m].name[0])?config->menu[k+m].name:zstr;
				if (LStrCmpI(ptr1,ptr2)<=0) break;
				SwapMem((char *)&config->menu[j+m],(char *)&config->menu[k+m],
					sizeof(struct newdopusfunction));
			}
}

void do_menuscreen_title(title)
int title;
{
	if (!paint_state) doscreentitle(cfg_string[title]);
	else {
		char temp[80];

		StrCombine(temp,cfg_string[title],cfg_string[STR_PAINT_STATE],80);
		doscreentitle(temp);
	}
}
