/*EdQuake v0.50 source code
  (c) Copyright 1996 Scott Mitting
  email:smitting@netusa1.net
  ----------------------------------
  INPUT.C  -  Keyboard/mouse input routines /w windows

  __variables:
  <no global variables>
  __functions:
  button_t button(int x0, int y0, int x1, int y1, char *text)
				-- creates a button and returns a pointer
  button_t clearbutton(int x0, int y0, int x1, int y1)
				-- creates a button without drawing it
  int getkey()			-- stable getkey function with extended
  char *getstr(int x, int y)    -- gets string without button support
  int hitbutton(int x, int y, button_t b)
				-- using a button pointer finds out if
				   a button is currently being hit
  button_t inputbox(int x0, int y0, int x1, int y1, char *title)
				-- creates a windows with a close button
  void scrollbar(int x, int y0, int y1, int cur, int max)
				-- updates/creates a scrollbar
  button_t scrollbutton(int x, int y, char *text)
				-- prefab buttons for up and down
  int selectentry()		-- selects an entry from a list
  char *wgetstr(char * def, int x, int y, button_t ok, button_t cancel, button_t xbutton)
				-- gets a string from the keyboard with
				   button support
  char *wgetstringbox(char *menubar, char *text, char *def)
				-- high-level function for getting
				   a string.  draws an input box
				   with buttons and checks on buttons
  ----------------------------------
  the entire source code is under renovation to make it easier
  to understand.  happy coding.
*/

/* don't use too many low-level functions as they change rapidly
   with absolutely no thought of other programmers.  High-level
   functions are more stable */

#include <alloc.h>
#include <string.h>
#include "input.h"
#include "svgacc.h"
#include "pak.h"
#include "grfx.h"

int list[200];
int numlist;

button_t clearbutton(int x0, int y0, int x1, int y1)
{
      button_t ret;
      ret.x0 = x0;
      ret.x1 = x1;
      ret.y0 = y0;
      ret.y1 = y1;
      return ret;
}

button_t button(int x0, int y0, int x1, int y1, char *text)
{
      button_t ret;
      mousehide();
  drwfillbox(SET,LTGRAY, x0,y0,x1,y1);
   drwstring(SET,BLACK,LTGRAY,text,x0 + 2,y0 + 1);
      drwbox(SET,WHITE,x0    ,y0    ,x1 ,y1);
      drwbox(SET,DKGRAY, x0 + 1,y0 + 1,x1 ,y1);
      ret.x0 = x0;
      ret.x1 = x1;
      ret.y0 = y0;
      ret.y1 = y1;
      mouseshow();
      return ret;
}

button_t inputbox(int x0, int y0, int x1, int y1, char *title)
{
      mousehide();
      drwbox(SET, DKGRAY,x0    ,y0    ,x1    ,y1    );
      drwbox(SET, LTGRAY,x0 + 1,y0 + 1,x1 - 1,y1 - 1);
      drwbox(SET,  WHITE,x0 + 2,y0 + 2,x1 - 2,y1 - 2);

      drwbox(SET, DKGRAY,x0 + 5,y0 + 19,x1 - 5,y1 - 5);
      drwbox(SET, LTGRAY,x0 + 4,y0 + 18,x1 - 4,y1 - 4);
      drwbox(SET,  WHITE,x0 + 3,y0 + 17,x1 - 3,y1 - 3);
  drwfillbox(SET, LTGRAY,x0 + 6,y0 + 20,x1 - 6,y1 - 6);

  drwfillbox(SET, BLUE,x0 + 3,y0 +  3,x1 - 3, y0 + 16);
   drwstring(SET, WHITE, BLUE,title,x0 + 27,y0 + 3);
      return button(x1 - 13, y0 + 1, x1 -3 , y0+16, "x");
}

int hitbutton(int x, int y, button_t b)
{
   if (b.x0 > x) return 0;
   if (b.y0 > y) return 0;
   if (b.x1 < x) return 0;
   if (b.y1 < y) return 0;
   return 1;
}

int getkey()
{
   int k;
   k = getch();
   if (!k) k = getch() + 1000;
   return k;
}

char *getstr(int x, int y)
{
	char *data;
	int length, ext;
	char c;

	data = malloc(128);
	sprintf(data,"_");
	length = 0;
	ext = 0;
	c = '\0';

	while(!ext) {
	    drwstring(SET,WHITE,BLACK,data,x,y);
	    c = (char)getch();
	    if(c>=' ' && c<='~') {
		data[length] = c;
		data[length+1] = '_';
		data[length+2] = '\0';
		length++;
	    }
	    else
		if (c==8 && length>0) {
		    drwstring(SET,WHITE,BLACK,"   ",x+length*8,y);
		    length--;
		    data[length] = '_';
		    data[length+1] = '\0';
		}
		else
		    if (c==13)
			ext = 1;
	}
	if (length==0) {
	    free(data);
	    return 0;
	}

	data[length] = '\0';
	return data;
}

char *wgetstr(char * def, int x, int y, button_t ok, button_t cancel, button_t xbutton)
{
	char *data;
	int length, ext;
	int mx, my, mbuts;
	char c;

	data = malloc(128);
	length = strlen(def);
	memset(data,0,128);
	movmem(def, data,length);
	length = 0;
	while (data[length] != 0) length++;
	data[length] = '_';
	ext = 0;
	c = '\0';

	while(!ext) {
	    drwstring(SET,LTGRAY,BLACK,data,x,y);
	    while (!kbhit())
	    {
	       mousestatus(&mx,&my,&mbuts);
	       if (mbuts & 1)//check for buttons
	       {
		  if (hitbutton(mx,my,ok))
		  {	data[length] = '\0';
			return data;}
		  if (hitbutton(mx,my,cancel))
		  {     free(data);
			return 0;}
		  if (hitbutton(mx,my,xbutton))
		  {     free(data);
			return 0;}
	       }
	    }
	    c = (char)getch();
	    if(c>=' ' && c<='~') {
		data[length] = c;
		data[length+1] = '_';
		data[length+2] = '\0';
		length++;
	    }
	    else
		if (c==8 && length>0) {
		    drwstring(SET,WHITE,BLACK,"   ",x+length*8,y);
		    length--;
		    data[length] = '_';
		    data[length+1] = '\0';
		}
		else
		    if (c==13)
			ext = 1;
		else
		    if (c==27)
		    {ext = 1; length=0;}
	}
	if (length==0) {
	    free(data);
	    return 0;
	}

	data[length] = '\0';
	return data;
}

int query(char *info)
{
   int k = 0;
   int mx, my, mbuts;
   button_t ok, cancel, xbutton;
   mousehide();
   xbutton = inputbox(200,200,420,275,"Query");
   ok = button(220,250,290,265,"   Ok");
   cancel = button(330,250,400,265," Cancel");
   drwstring(SET,BLACK,LTGRAY,info,210,230);
   mouseshow();
   while (k != 27)
   {
	    while (!kbhit() && !mbuts)
	    {
	       mousestatus(&mx,&my,&mbuts);
	       if (mbuts)
	       {
		  if (hitbutton(mx,my,ok)) return 1;
		  if (hitbutton(mx,my,cancel)) return 0;
		  if (hitbutton(mx,my,xbutton)) return 0;
	       }
	    }
	    if (!mbuts) k = getkey();
	    mbuts = 0;
     if (k == a_ENTER) return 1;
   }
   return 0;
}


int selectentry(int e)
{
   int k;
   int curE = 1, showE = e;
   int mx, my, mbuts;
   button_t up, down, xbutton;
   mousehide();
   xbutton = inputbox(0,20,320,312,"Select PAK Entry");
   up = scrollbutton(302,280,"");
   down = scrollbutton(302,294,"");
   mouseshow();
   while (k != 27)
   {
     showmenu(showE, curE);
     scrollbar(302,40,278,showE+curE,pak.tablelen);
	    while (!kbhit() && !mbuts)
	    {
	       mousestatus(&mx,&my,&mbuts);
	       if (mbuts & 1)//scroll
	       {
		  if (hitbutton(mx,my,up)) showE-=1;
		  if (hitbutton(mx,my,down)) showE+=1;
		  if (hitbutton(mx,my,xbutton)) return -1;
		  //select
		  if (mx < 300 && my < 300 && my > 40)
		     curE =  ((my - 40) / 14)+1;
	       }
	       if (mbuts & 2)//scroll fast
	       {
		  if (hitbutton(mx,my,up)) showE-=3;
		  if (hitbutton(mx,my,down)) showE+=3;
		  if (mx < 300 && my < 300 && my > 40) return showE+curE;
	       }

	    }
	    if (!mbuts) k = getkey();
	    mbuts = 0;

     if (k == a_DOWN) curE++;
     if (k == a_UP)   curE--;
     if (k == a_PGDN) showE+=15;
     if (k == a_PGUP) showE-=15;
     if (k == a_HOME) curE=1;
     if (k == a_END)  curE=19;
     if (k == a_ENTER) return showE+curE;
     if (k == a_ESC)   return -1;
     if (curE > 19) {showE++;curE=19;}
     if (curE < 1)  {showE--;curE=1;}
     if (showE < 0) {showE = 0; curE = 1;}
     if (showE + 19 > pak.tablelen) {showE = pak.tablelen - 19; curE=19;}
   }
   return -1;
}

void scrollbar(int x, int y0, int y1, int cur, int max)
{
   int yloc = 0;
   yloc = y0+((y1-15)-y0)*((float)cur/max);
   drwbox(SET,BLACK,x,y0,x+11,y1);
   drwfillbox(SET,DKGRAY,x+1,y0+1,x+10,y1-1);
   drwbox(SET, WHITE,x + 1,yloc+1,x + 10 ,yloc+15);
   drwbox(SET, BLACK, x + 2,yloc+2,x + 10 ,yloc+15);
   drwfillbox(SET, LTGRAY, x+2,yloc+2,x+9,yloc+14);
}

button_t scrollbutton(int x, int y, char *text)
{
      button_t ret;
      drwfillbox(SET,LTGRAY,x,y,x+11,y+12);
      drwstring(SET,BLACK,LTGRAY,text,x+2,y);
      drwline(SET,BLACK,x+11,y,x+11,y+12);
      drwline(SET,BLACK,x,y+12,x+11,y+12);
      drwline(SET,WHITE,x,y,x+11,y);
      drwline(SET,WHITE,x,y,x,y+12);
      ret.x0 = x;
      ret.x1 = x+11;
      ret.y0 = y;
      ret.y1 = y+12;
      return ret;
}

char *wgetstringbox(char *menubar, char *text, char *def)
{
   button_t ok;
   button_t cancel;
   button_t xbutton;
   xbutton = inputbox(100,150,430,225,menubar);
//   drwstring(SET, BLACK,LTGRAY,pakentry.name,110,170);
   drwstring(SET, BLACK,LTGRAY,text,110,185);
   drwfillbox(SET,BLACK,110,200,350,214);
   ok = button(356,183,420,197,"   ok");
   cancel = button(356,203,420,217," cancel");
   return wgetstr(def,113,200, ok, cancel, xbutton);
}

void showmenulist(int showE, int curE)
{
   int t,qt;
   char buf[80];
   qt = 40;
   mousehide();
   for (t = 1; t < 20; t++)
   {
     getentry(list[t + showE]);
     if (t != curE)
     {
	drwfillbox(SET, BLACK,6,qt,300,qt+14);
	sprintf(buf, "%s",       pakentry.name);
	drwstring(SET, WHITE,BLACK,buf,11,qt);
     }
     else
     {
	drwfillbox(SET,RED,6,qt,300,qt+14);
	sprintf(buf, "%s",       pakentry.name);
	drwstring(SET, YELLOW,RED,buf,11,qt);
     }
     qt+=14;
   }
   mouseshow();
}


int selectentrykeyword(int e, char *keyword)
{
   int k;
   int curE = 1, showE = e;
   int mx, my, mbuts;
   int curt = 0;
   button_t up, down, xbutton;
   mousehide();
   numlist = 0;
   xbutton = inputbox(0,20,320,312,"Select PAK Entry");
   up = scrollbutton(302,280,"");
   down = scrollbutton(302,294,"");
   //get entries;
   for (curt = 0; curt < pak.tablelen; curt++)
   {
      getentry(curt);
      if (strstr(pakentry.name,keyword))
	list[numlist++] = curt;
   }
   numlist--;
   mouseshow();
   while (k != 27)
   {
     showmenulist(showE, curE);
     scrollbar(302,40,278,showE+curE,numlist);
	    while (!kbhit() && !mbuts)
	    {
	       mousestatus(&mx,&my,&mbuts);
	       if (mbuts & 1)//scroll
	       {
		  if (hitbutton(mx,my,up)) showE-=1;
		  if (hitbutton(mx,my,down)) showE+=1;
		  if (hitbutton(mx,my,xbutton)) return -1;
		  //select
		  if (mx < 300 && my < 300 && my > 40)
		     curE =  ((my - 40) / 14)+1;
	       }
	       if (mbuts & 2)//scroll fast
	       {
		  if (hitbutton(mx,my,up)) showE-=3;
		  if (hitbutton(mx,my,down)) showE+=3;
		  if (mx < 300 && my < 300 && my > 40) return list[showE+curE];
	       }

	    }
	    if (!mbuts) k = getkey();
	    mbuts = 0;

     if (k == a_DOWN) curE++;
     if (k == a_UP)   curE--;
     if (k == a_PGDN) showE+=15;
     if (k == a_PGUP) showE-=15;
     if (k == a_HOME) curE=1;
     if (k == a_END)  curE=19;
     if (k == a_ENTER) return list[curE+showE];
     if (k == a_ESC)   return -1;
     if (curE > 19) {showE++;curE=19;}
     if (curE < 1)  {showE--;curE=1;}
     if (showE < 0) {showE = 0; curE = 1;}
     if (numlist > 19)
       if (showE + 19 > numlist) {showE = numlist - 19; curE=19;}
   }
   return -1;
}

int wgetintbox(char *menubar, char *text, int def)
{
   button_t ok, cancel, xbutton;
   char *buf, *data, c;
   int length, ext, mx, my, mbuts;
   xbutton = inputbox(100,150,430,225,menubar);
   drwstring(SET, BLACK,LTGRAY,text,110,185);
   drwfillbox(SET,BLACK,110,200,350,214);
   ok = button(356,183,420,197,"   ok");
   cancel = button(356,203,420,217," cancel");
   sprintf(buf,"%i",def);
   data = malloc(128);
   memset(data,0,128);
   length = strlen(buf);
   memmove(data,buf,length);
   length = 0;
   while (data[length] != 0) length++;
   data[length] = '_';
   ext = 0;
   c = '\0';
   while(!ext)
   {
       drwstring(SET,LTGRAY,BLACK,data,113,200);
       while (!kbhit())
       {
	  mousestatus(&mx,&my,&mbuts);
	  if (mbuts & 1)//check for buttons
	  {
	     if (hitbutton(mx,my,ok)) ext = 1;
	     if (hitbutton(mx,my,cancel)) length = -1;
	     if (hitbutton(mx,my,xbutton)) length = -1;
	  }
       }
       c = getch();
       if(c >= ' ' && c <= '~')
       {
	  data[length] = c;
	  data[length+1] = '_';
	  data[length+2] = '\0';
	  length++;
       }
       if (c == 8 && length > 0)
       {
	  drwstring(SET,WHITE,BLACK,"   ",113+length*8,200);
	  length--;
	  data[length] = '_';
	  data[length+1] = '\0';
       }
       if (c == 13) ext = 1;
       if (c == 27) length = -1;
       if (length > 100) length = 100;
       if (length == -1) ext = 1;
   }
   if (length > 0) def = atoi(data);
   free(data);
   return def;
}

