/*- WINDOWS.CC -------------------------------------------------------------*
 Doom Editor (Registered Version Only) Ver 0.1

 Code for generating windows (C++)

 Any inquiries to Colin Reed or Dylan Cuthbert via
 DYL@CIX.COMPULINK.CO.UK
*---------------------------------------------------------------------------*/
#define _WINDOWS_

#include "sfc.h"

//----------------------------------------------
// prototypes

void Closedown_Windows();

//----------------------------------------------
// some data constants used by the print stream

WT_CONTROL WT_LEFT = {GR_ALIGN_LEFT};
WT_CONTROL WT_CENTRE = {GR_ALIGN_CENTER};
WT_CONTROL WT_RIGHT = {GR_ALIGN_RIGHT};

WT_COLOUR WT_BLACK = {BLACK};
WT_COLOUR WT_BLUE = {BLUE};
WT_COLOUR WT_GREEN = {GREEN};
WT_COLOUR WT_CYAN = {CYAN};
WT_COLOUR WT_RED = {RED};
WT_COLOUR WT_MAGENTA = {MAGENTA};
WT_COLOUR WT_BROWN = {BROWN};
WT_COLOUR WT_LIGHTGRAY = {LIGHTGRAY};
WT_COLOUR WT_DARKGRAY = {DARKGRAY};
WT_COLOUR WT_LIGHTBLUE = {LIGHTBLUE};
WT_COLOUR WT_LIGHTGREEN = {LIGHTGREEN};
WT_COLOUR WT_LIGHTCYAN = {LIGHTCYAN};
WT_COLOUR WT_LIGHTRED = {LIGHTRED};
WT_COLOUR WT_LIGHTMAGENTA = {LIGHTMAGENTA};
WT_COLOUR WT_YELLOW = {YELLOW};
WT_COLOUR WT_WHITE = {WHITE};


MouseEvent event;												// GUI variables
unsigned long event_id;

GrTextOption *normalfont;
GrTextOption *normalfont_bold;
GrTextOption *normalfont_ital;
GrTextOption *nicefont;
GrTextOption *nicefont_bold;
GrTextOption *nicefont_ital;

int Windows_Initialised=0;

/*---------------------------------------------------------------------------*/
// Program error


void ProgError( char *errstr, ...)
{
	va_list args;

	va_start( args, errstr);

	Closedown_Windows();
	printf( "\nProgram Error: *** ");
	vprintf( errstr, args);
	printf( " ***\n");
	va_end( args);
	exit( 5);
}

/*---------------------------------------------------------------------------*/
// Initialise the graphics server/mouse and other structures

void Initialise_Windows()
	{

	unsigned char palette[16*3] =
		{
		0, 0, 0,
		0, 0, 192,
		0, 192, 0,
		0, 192, 192,
		192, 0, 0,
		192, 0, 192,
		192,192,0,
		192,192,192,

		64, 64, 64,
		64, 64, 255,
		64, 255, 64,
		64, 255, 255,
		255, 64, 64,
		255, 64, 255,
		255,255,64,
		255,255,255

		};

	struct LOADFONTS {GrTextOption **t; char *name; int x,y;} fonts[] =
		{
		&normalfont_ital,"cour*ital",  14, 14,
		&normalfont_bold,"cour*bold",  14, 14,
		&nicefont,       "helve",      16, 16,
		&nicefont_ital,  "helve*ital", 16, 16,
		&nicefont_bold,  "helve*bold", 16, 16,
		NULL,NULL
		};
	int n;

// Set up the graphics screen
	GrSetMode(GR_width_height_color_graphics,640,480,16);

// Now set up the fonts

	if (!(normalfont = GrFindBestFont(8,14,0,"cour",NULL)))
		ProgError("Need LIBGRX's series of courier fonts");

	for (n=0;fonts[n].name;n++)
		if (!(*fonts[n].t = GrFindBestFont(fonts[n].x,fonts[n].y,0,fonts[n].name,NULL)))
			*fonts[n].t = normalfont;

	if (!MouseDetect()) ProgError("No mouse detected!\n");

	MouseEventMode(0);
	MouseSetColors(WHITE,0);

// Now to set up the color palette

	for (n=0*16;n<1*16;n++)
		GrSetColor(n,palette[n*3],palette[n*3+1],palette[n*3+2]);

	Windows_Initialised = 1;
	}

/*---------------------------------------------------------------------------*/
void Closedown_Windows()
	{
	MouseUnInit();
	GrSetMode(GR_default_text);
	}
/*---------------------------------------------------------------------------*/
void Update_Mouse()
	{
	event_id++;
	MouseGetEvent(M_EVENT,&event);
	}

void Update_Mouse_NoWait()
	{
	event_id++;
	MouseGetEvent(M_EVENT|M_POLL,&event);
	}

/*---------------------------------------------------------------------------*/
// Operators and their functions:
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
Window& Window::operator << (WT_COLOUR a)
	{
	DrawColor = a.colour;
	return *this;
	};
/*---------------------------------------------------------------------------*/
Window& Window::operator << (char *str)
	{
	int n;
	for (n=0;n<strlen(str);n++)
		(*this)<<str[n];

	return *this;
	}

/*---------------------------------------------------------------------------*/
Window& Window::operator << (int num)
	{
	static char temp[50];

	sprintf(temp,"%d",num);

	return (*this)<<temp;
	}

/*---------------------------------------------------------------------------*/
Window& Window::operator << (unsigned int num)
	{
	static char temp[50];
	int n;

	sprintf(temp,"%u",num);
	(*this)<<temp;

	return *this;
	}

/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void Window::outtext(char *s)
	{
	Set();
	Font.txo_xalign = textxalign;
	Font.txo_yalign = textyalign;
	Font.txo_fgcolor.v = DrawColor;
	Font.txo_bgcolor.v = DrawBGColor;
	GrDrawString(s,strlen(s),textx+tabx,texty,&Font);
	Unset();
	}
/*---------------------------------------------------------------------------*/

Window& Window::operator << (char c)
	{
	if (c != '\n' && c != '\t')
		{
		textline[tx++] = c;
		textline[tx] = '\0';
		}

	if (c == '\t')
		{
		outtext(textline);
		tx = 0;
		textline[0] = '\0';
		tabx += 8*textwidth("W");
		}

	if (c == '\n' ||
		(textwidth(textline)+textx+tabx>Drawable->gc_xmax && textxalign == GR_ALIGN_LEFT) ||
		((textx+tabx)-textwidth(textline)<0 && textxalign == GR_ALIGN_RIGHT) ||
		(((textx+tabx)-(textwidth(textline)/2)<0 || (textx+tabx)-(textwidth(textline)/2)>Drawable->gc_xmax) && textxalign == GR_ALIGN_CENTER)
			)
		{
		if (c != '\n') textline[tx-1] = '\0';
		outtext(textline);
		tx = 1;
		if (c == '\n') tx = 0;
		else textline[0] = c;
		textline[tx] = '\0';
		texty += textheight();
		tabx = 0;
		}

	return *this;
	}
/*---------------------------------------------------------------------------*/
void Window::Set()
	{
	GrSaveContext(&store);
	GrSetContext(Drawable);
	}

/*---------------------------------------------------------------------------*/
void Window::Set(GrContext &d)
	{
	GrSaveContext(&store);
	GrSetContext(&d);
	}

/*---------------------------------------------------------------------------*/
void Window::Direct()
	{
	if (!MAPSDIRECT)
		{
		flush();
		GrDestroyContext(grc);
		GrDestroyContext(Drawable);
		Drawable = GrCreateSubContext(minx,miny,maxx,maxy,scr,NULL);
		MAPSDIRECT = 1;
		}
	}
/*---------------------------------------------------------------------------*/
void Window::Indirect()
	{
	if (MAPSDIRECT)
		{
		grc = GrCreateContext(scr->gc_xmax+1,scr->gc_ymax+1,NULL,NULL);
		GrBitBlt(grc,0,0,scr,0,0,scr->gc_xmax,scr->gc_ymax,GrWRITE);
		GrDestroyContext(Drawable);
		Drawable = GrCreateSubContext(minx,miny,maxx,maxy,grc,NULL);
		MAPSDIRECT = 0;
		}
	}


/*---------------------------------------------------------------------------*/
void Window::gtag(char *gname,int x,int y, int sx, int sy, int mode, int type)
	{
//	Set();
//	DrawGTag(gname,x,y,sx,sy,mode,type);
//	Unset();
	}

/*---------------------------------------------------------------------------*/
void Window::thickline(int x,int y,int x1,int y1)
	{
	GrLineOption lo;

	Set();

// Initialise the custom line structure

	lo.lno_color = DrawColor|WriteMode;
	lo.lno_width = 3;
	lo.lno_pattlen = 0;
	lo.lno_dashpat = NULL;

// draw it

	GrCustomLine(x,y,x1,y1,&lo);

	Unset();
	}

/*---------------------------------------------------------------------------*/
void Window::line(int x,int y,int x1,int y1)
	{
	GrLineOption lo;
	unsigned char patt[]={1,1,0,0};

	Set();

	switch(LineStyle)
		{
		case DOTTED_LINE:
			lo.lno_color = DrawColor|WriteMode;
			lo.lno_width = 1;
			lo.lno_pattlen = 4;
			lo.lno_dashpat = patt;
			GrCustomLine(x,y,x1,y1,&lo);
			break;
		default:
			if (y==y1) { GrHLine(x,x1,y,DrawColor|WriteMode); break;}
			if (x==x1) { GrVLine(x,y,y1,DrawColor|WriteMode); break;}
			GrLine(x,y,x1,y1,DrawColor|WriteMode);
			break;
		}

	Unset();
	}

/*---------------------------------------------------------------------------*/
void Window::setclip(int x,int y,int x1,int y1)
	{
	Set();

	GrSetClipBox(x,y,x1,y1);

	GrSaveContext(Drawable);		// save the changes
	Unset();
	}

/*---------------------------------------------------------------------------*/
void Window::getclip(int *x,int *y,int *x1,int *y1)
	{
	Set();

	GrGetClipBox(x,y,x1,y1);

	Unset();
	}

/*---------------------------------------------------------------------------*/
Window::Window(int x,int y,int x1,int y1,int bg, char *title, int flags)
	{
	int rx=x,ry=y,rx1=x1,ry1=y1,b=0,n;
	GrContext oldgc;
	GrFBoxColors bdrcols = {DARKGRAY,WHITE,DARKGRAY,BLACK,LIGHTGRAY};

	memset(this,sizeof(struct Window),0);

	if (!Windows_Initialised) Initialise_Windows();

	GrSaveContext(&oldgc);

//-----------------------
// make space for borders

	if (flags&W_MOTIFBORDER) b = MOTIFBORDERSIZE;
	if (flags&W_SIMPLEBORDER) b = SIMPLEBORDERSIZE;

	if (flags&W_INCLUDEBORDER)
		{ x += b; y += b; x1 -= b; y1 -= b;}
	else
		{ rx -= b; ry -= b; rx1 += b; ry1 += b; }

//---------------------
// make space for title

	if (title)
		{
		if (flags&W_INCLUDETITLE) y += GrCharHeight('W',nicefont)+4+3;
		else ry -= GrCharHeight('W',nicefont)+4+3;
		}

	if (rx<0)
		{
		x+= -rx;
		x1+= -rx;
		rx1+= -rx;
		rx = 0;
		}

	if (ry<0)
		{
		y+= -ry;
		y1+= -ry;
		ry1+= -ry;
		ry = 0;
		}

	minx = x-rx; miny = y-ry; maxx = (x1-rx); maxy = (y1-ry);

//-------------------
// Create the buffers

	scr = GrCreateSubContext(rx,ry,rx1,ry1,NULL,NULL);
	grc = GrCreateContext(rx1-rx+1,ry1-ry+1,NULL,NULL);
	Drawable = GrCreateSubContext(minx,miny,maxx,maxy,grc,NULL);

	GrBitBlt(grc,0,0,NULL,rx,ry,rx1,ry1,GrWRITE);

//--------------------------------
// Store the back buffer if needed

	if (flags&W_BACKINGSTORE)
		{
		backstore = GrCreateContext(rx1-rx+1,ry1-ry+1,NULL,NULL);
		GrBitBlt(backstore,0,0,NULL,rx,ry,rx1,ry1,GrWRITE);
		}
	else backstore = NULL;

//-----------------------------
// set the default variables up

	DrawColor = WHITE;
	DrawBGColor = bg;
	WriteMode = GrWRITE;
	LineStyle = SOLID_LINE;
	gadgetlist = NULL; currentgadget = NULL;
	textxalign = GR_ALIGN_LEFT;
	textyalign = GR_ALIGN_TOP;

	input.inputflags = 0;
	input.lasttime = 0;
	input.searchstring = NULL;

	memcpy(&Font,normalfont,sizeof(GrTextOption));
	textline = new char[512];
	resettext();

//-----------------
// Draw the borders

	GrSetContext(grc);

	if (flags&W_MOTIFBORDER)
		{
		GrFramedBox(b-1,b-1,maxx+1,maxy+1,MOTIFBORDERSIZE-2,&bdrcols);
		GrBox(b-1,b-1,maxx+1,maxy+1,WHITE);
		GrBox(b-(MOTIFBORDERSIZE-1),b-(MOTIFBORDERSIZE-1),maxx+(MOTIFBORDERSIZE-1),maxy+(MOTIFBORDERSIZE-1),BLACK);
		}

	if (flags&W_SIMPLEBORDER)
		{
		GrBox(b-1,b-1,maxx+1,maxy+1,BLACK);
		for(n=2;n<SIMPLEBORDERSIZE;n++)
			GrBox(b-n,b-n,maxx+n,maxy+n,WHITE);
		GrBox(b-SIMPLEBORDERSIZE,b-SIMPLEBORDERSIZE,maxx+SIMPLEBORDERSIZE,maxy+SIMPLEBORDERSIZE,BLACK);
		}

//--------------------------
// Set the title if one

	if (title)
		{
		nicefont->txo_xalign = GR_ALIGN_CENTER;
		nicefont->txo_yalign = GR_ALIGN_TOP;
		nicefont->txo_bgcolor.v = BLACK|GrXOR;

		nicefont->txo_fgcolor.v = BLACK;
		GrDrawString(title,strlen(title),minx+(maxx-minx+1)/2+1,b+3,nicefont);

		nicefont->txo_fgcolor.v = LIGHTGRAY;
		GrDrawString(title,strlen(title),minx+(maxx-minx+1)/2,b+2,nicefont);

		GrHLine(minx,maxx,miny-1,BLACK);
		GrHLine(minx,maxx,miny-2,WHITE);
		GrHLine(minx,maxx,miny-3,BLACK);
		}
	
//--------------------------
// Clear the window and exit

	GrFilledBox(minx,miny,maxx,maxy,bg|GrWRITE);

	GrSetContext(&oldgc);

//--------------------------
// Maps direct to the screen? NO call Direct() after opening the window.

	MAPSDIRECT = 0;

	}


// Window destructor:

Window::~Window(void)
	{

// delete the output buffer
	delete textline;

// delete any gadgets that were created
	while (gadgetlist) delete gadgetlist;

// if not directly mapped to screen and not back stored
// copy the buffered image to the screen.

	if (!(MAPSDIRECT || backstore)) GrBitBlt(scr,0,0,grc,0,0,scr->gc_xmax,scr->gc_ymax,GrWRITE);

// if backing store exists, restore that to the screen

	if (backstore)
		{
		GrBitBlt(scr,0,0,backstore,0,0,scr->gc_xmax,scr->gc_ymax,GrWRITE);
		GrDestroyContext(backstore);
		}

// If buffer exists, delete it
		
	if (!MAPSDIRECT) GrDestroyContext(grc);

	GrDestroyContext(scr);
	}

//--------------------------------------------------
int Window::mouse()
	{
	Gadget *g;
	int n;

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// if the time signature is the same as the old one then don't process
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	if (input.id == event_id) return 0;

	input.flags = event.flags;
	input.x = event.x-scr->gc_xoffset-minx;
	input.y = event.y-scr->gc_yoffset-miny;
	input.buttons = event.buttons;
	input.key = event.key;
	input.kbstat = event.kbstat;
	input.time = event.time;
	input.gflags = 0;
	input.id = event_id;

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// If the mouse hasn't moved put the old values of x and y in place.
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	if (!(input.flags&M_MOTION))
		{
		input.x = omx; input.y = omy;
		}
	else
		{
		omx = input.x; omy = input.y;
		}

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// If the mouse is out of range of the window:
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	if (input.x < 0 || input.x > maxx ||
		input.y < 0 || input.y > maxy)
		{
		input.flags &= ~(M_MOTION|M_BUTTON_CHANGE);
		input.buttons &= ~(M_LEFT|M_RIGHT|M_MIDDLE);

		}

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Deal with the event-handling of the gadgets
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	while(1)
		{
		int highlighted = -1,selected = -1;

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Deal with normal keypresses and toggling of gadgets:
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

		if (!(input.inputflags&(IF_SLIDING|IF_STRING)))
			{
			if ((input.flags&M_KEYPRESS) && !(input.inputflags&(IF_SLIDING)))
				{
				switch(input.key)
					{
					Gadget *tmp;
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// If 'TAB' pressed then cycle highlighted gadget to next gadget
// If 'SPACE' pressed then select the current gadget
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
					case KB_SHIFTTAB:
						if (gadgetlist)
							{
							for (tmp=gadgetlist;tmp;tmp=tmp->next)
								if (tmp->flags&G_HIGHLIGHTABLE)
									{
									highlighted = tmp->id;
									break;
									}
							for (tmp = (currentgadget)?currentgadget->next:currentgadget; tmp; tmp=tmp->next)
								if (tmp->flags&G_HIGHLIGHTABLE)
									{
									highlighted = tmp->id;
									break;
									}
							event.flags&=~M_KEYPRESS;
							}
						break;

					case '	':
						if (gadgetlist)
							{
							for (tmp=gadgetlist;tmp;tmp=tmp->next)
								if (tmp->flags&G_HIGHLIGHTABLE) highlighted = tmp->id;
							for (tmp = (currentgadget)?currentgadget->prev:currentgadget; tmp ; tmp = tmp->prev)
								if (tmp->flags&G_HIGHLIGHTABLE)
									{
									highlighted = tmp->id;
									break;
									}
							event.flags&=~M_KEYPRESS;
							}
						break;

					case ' ':
						if (currentgadget && gadgetlist)
							{
							selected = currentgadget->id;
							event.flags&=~M_KEYPRESS;
							}
						break;
					default:

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// If current gadget is a G_LIST type then search list for keys pressed
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

						if (currentgadget)
							{
							if ((currentgadget->flags&G_LIST)&&!(input.kbstat&KB_ALT))
								{
								event.flags&=~M_KEYPRESS;
								switch(input.key)
									{
									case KB_PAGEUP:
										currentgadget->PageUp();
										highlighted = currentgadget->id;
										break;
									case KB_PAGEDOWN:
										currentgadget->PageDown();
										highlighted = currentgadget->id;
										break;
									case KB_UP:
										currentgadget->Up();
										highlighted = currentgadget->id;
										break;
									case KB_DOWN:
										currentgadget->Down();
										highlighted = currentgadget->id;
										break;
									default:
										if (!isalnum(input.key)) break;
										if (!input.searchstring)
											{
											input.searchstring = (char *)malloc(2);
											input.searchstring[0] = input.key;
											input.searchstring[1] = 0;
											}
										else
											{
											if (input.time-input.lasttime < 5)
												{
												input.searchstring = (char *)realloc(input.searchstring, strlen(input.searchstring)+2);
												input.searchstring[strlen(input.searchstring)+1] = 0;
												input.searchstring[strlen(input.searchstring)] = input.key;
												}
											else
												{
												input.searchstring[0] = input.key;
												input.searchstring[1] = 0;
												}
											}
										if ((n = currentgadget->Search(input.searchstring,GS_CURRENTITEM))!=-1)
											{
											currentgadget->SetSelectedItem(n);
											highlighted = currentgadget->id;
											}
										else
											{
											input.searchstring[0] = input.key;
											input.searchstring[1] = 0;
											if ((n = currentgadget->Search(input.searchstring,GS_CURRENTITEM))!=-1)
												{
												highlighted = currentgadget->id;
												currentgadget->SetSelectedItem(n);
												}
											}
										input.lasttime = input.time;
										break;
									}
								}
							}
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Check for hot-keys (eg. Alt-'c')
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

						for (g = gadgetlist; g; g = g->next)
							{
							if (toupper(input.key) == toupper(g->hotkey) && ((input.kbstat & KB_ALT) || !isalnum(g->hotkey)))
								{
								g->Select();
								event.flags&=~M_KEYPRESS;
								break;
								}
							}
						break;
					}
				}

			if ((input.flags & (M_MOTION|M_BUTTON_DOWN)) || highlighted!=-1 || selected!=-1)
				{
				for (g = gadgetlist; g; g = g->next)
					{
					if (( ((g->Onit(omx,omy) && highlighted==-1 && selected==-1) || highlighted==g->id) && ((g != currentgadget) || (input.flags&M_BUTTON_DOWN))) || selected==g->id || highlighted==g->id)
						{
						Highlight(g->id);
						input.gflags |= GF_HIGHLIGHT;
						input.gadget = g->id;

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Left mouse button pressed?
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
						if (((input.flags&M_BUTTON_DOWN) && (input.buttons&M_LEFT)) || selected == g->id)
							{
							input.buttons &= ~M_LEFT;
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Ok, mouse has clicked on a normal gadget so select it
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
							g->Select(selected);
							break;
							}
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// If mouse button not pressed
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
						else
							{
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// if list or string gadget then DON'T send HIGHLIGHT flag
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
							if (g->flags&(G_STRING)) input.gflags &= ~GF_HIGHLIGHT;
							if (g->flags&(G_LIST)) input.slider = g->selecteditem;
							}
						}
					else if ((g->flags&G_OVERONLY) && !g->Onit(omx,omy))
						{
						if (g->flags&G_HIGHLIGHTED)
							{
							g->Unhighlight();
							if (g == currentgadget) currentgadget = NULL;
							}
						}
					}
				}
			else
				{
				if (currentgadget)
					if ((event.flags&M_MOTION) && (currentgadget->flags&G_OVERONLY))
						{
						if (currentgadget->flags&G_HIGHLIGHTED)
							{
							currentgadget->Unhighlight();
							currentgadget = NULL;
							}
						}
				}
			break;
			}


//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Check for string gadgets
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

		if ((input.inputflags&IF_STRING) && ((input.flags&(M_KEYPRESS)) || (event.flags&M_BUTTON_DOWN)))
			{
			if (event.flags&M_KEYPRESS)
				{
				switch(event.key)
					{
					case 8:
						currentgadget->Del();
						break;
					case KB_LEFT:
						currentgadget->Left();
						break;
					case KB_RIGHT:
						currentgadget->Right();
						break;
					case KB_HOME:
						currentgadget->Home();
						break;
					case KB_END:
						currentgadget->End();
						break;
					case 13:
						input.gflags|=GF_SELECTED;
						input.gadget=currentgadget->id;
						input.slider=(int)currentgadget->text;
						input.inputflags &= ~IF_STRING;
						g = currentgadget;
						currentgadget = NULL;
						g->Unhighlight();
						break;
					default:
						if (currentgadget->flags&G_NUMBER)
							{
							if (!isdigit(event.key) || (event.key == '-' && strlen(currentgadget->GetString())==0)) break;
							}
						if (isprint(event.key))
							currentgadget->Ins(event.key);
						break;
					}
				if (currentgadget) currentgadget->Draw();
				}
			if ((event.flags & M_BUTTON_DOWN) && (event.buttons & M_LEFT))
				{
				input.inputflags &= ~IF_STRING;
				g = currentgadget;
				currentgadget = NULL;
				g->Unhighlight();
				}
			break;
			}

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// Check for sliding gadgets
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

		if ((input.inputflags&IF_SLIDING) && ((input.flags&M_MOTION) || (event.flags&M_BUTTON_UP)))		// Sliding gadget?
			{
			if (input.flags & M_MOTION)
				{
				currentgadget->sliderpos = omy-currentgadget->gy-5;
				if (currentgadget->sliderpos<0) currentgadget->sliderpos = 0;
				if (currentgadget->sliderpos+SLIDER_HEIGHT>currentgadget->gy1-currentgadget->gy-10)
					currentgadget->sliderpos = currentgadget->gy1-currentgadget->gy-10-7;
				currentgadget->DrawSlider();
				}

//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// check for button release
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
			if ((event.flags&M_BUTTON_UP) && !(event.buttons&M_LEFT))
				{
				currentgadget->flags &= ~G_HIGHLIGHTED;
				input.inputflags &= ~IF_SLIDING;
				input.gflags |= GF_SELECTED;
				currentgadget->DrawSlider();
				}
			else input.gflags |= GF_HIGHLIGHT;
			input.gadget = currentgadget->id;
			input.slider = currentgadget->GetSlider(65535);
			break;
			}

		break;
		}

	return input.flags|input.gflags;
	}


//------------------------------------------------------------
// Clear the window
void Window::cls()
	{
	Gadget *g;

	Set();
	GrClearContext(DrawBGColor|GrWRITE);
	Unset();

	for (g = gadgetlist; g; g=g->next)
		{
		g->Draw();
		}

// Clear the text variables
	tx = 0; texty = 0; textx = 0;
	tabx = 0;
	textline[0] = '\0';
	}

//------------------------------------------------------------
// Printf routine

int Window::printf(char *s,...)
	{
	char t[2048];
	va_list args;
	va_start(args,s);

	vsprintf(t,s,args);

	(*this) << t;

//	tx = 0;
//	textline[0] = '\0';

	va_end(args);
	}

//------------------------------------------------------------
// Printf routine

int Window::vprintf(char *s,...)
	{
	char t[2048];
	va_list args;
	va_start(args,s);

	vsprintf(t,s,*((va_list **)va_arg(args,va_list *)));

	(*this) << t;

	va_end(args);

//	tx = 0;
//	textline[0] = '\0';

	}


//------------------------------------------------------------
void Window::Select(int n)
	{
	Gadget *g;

	for (g = gadgetlist; g ; g = g->next)
		if (g->id == n)
			{
			g->Select();
			}
	}
//------------------------------------------------------------
void Window::Highlight(int n)
	{
	Gadget *g;

	for (g = gadgetlist; g ; g = g->next)
		if (g->id == n)
			{
			if (currentgadget != g)
				{
				if (currentgadget) currentgadget->Unhighlight();
				g->Highlight();
				}
			currentgadget = g;
			}
	}
//------------------------------------------------------------
void Window::Select(int n,int i)
	{
	Gadget *g;

	for (g = gadgetlist; g ; g = g->next)
		if (g->id == n)
			g->Select(i);
	}
//------------------------------------------------------------
Gadget *Window::Find(int n)
	{
	Gadget *g;

	for (g = gadgetlist; g ; g = g->next)
		if (g->id == n) return g;

	return NULL;
	}
//------------------------------------------------------------
void Window::Delete(int n)
	{
	Gadget *g;

	for (g = gadgetlist; g ; g = g->next)
		if (g->id == n) { delete g; break; }
	}

//------------------------------------------------------------
void Window::DeleteAll()
	{
	Gadget *g;

	while (gadgetlist) delete gadgetlist;
	}

//-------------------------------------------------
char *Window::GetItem(int n,int i)
	{
	Gadget *g;
	char *s;

	if (g = Find(n))
		return g->GetItem(i);
	return NULL;
	}

//-------------------------------------------------
void Window::SetList(int n,char *s)
	{
	Gadget *g;
	if (g = Find(n))	g->SetList(s);
	}


//-------------------------------------------------
char *Window::GetSelectedItem(int n)
	{
	if (Find(n)) return Find(n)->GetSelectedItemName();
	else return NULL;
	}

//-------------------------------------------------
int Window::GetSelectedItemNum(int n)
	{
	if (Find(n)) return Find(n)->GetSelectedItem();
	else return -1;
	}


//-------------------------------------------------
void Window::SetTopItem(int n,int i)
	{
	if (Find(n))
		{
		Find(n)->SetTopItem(i);
		Find(n)->Draw();
		}
	}

//-------------------------------------------------
void Window::SetString(int n,char *s)
	{
	if (Find(n)) Find(n)->SetString(s);
	}
//-------------------------------------------------
char *Window::GetString(int n)
	{
	if (Find(n)) return Find(n)->GetString();
	return NULL;
	}
//-------------------------------------------------
void Window::SetSelectedItem(int n, int i)
	{
	if (Find(n)) Find(n)->SetSelectedItem(i);
	}

//-------------------------------------------------
int Window::SearchList(int n, int i, char *s)
	{
	if (Find(n)) return Find(n)->Search(s,i);
	else return -1;
	}

