/*- 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;
	}

