#include "all.h"
#include "color.h"
#include "edt.h"

#ifdef __TURBOC__
#define DASHCHAR 249
#include "bios.h"
#include "conio.h"
#include "dir.h"
#else
#define DASHCHAR '.'
#include "vaxconio.h"
#endif

#define true (!false)
#define false 0
#define BEGINDEF extern
/* #include "begin.h" */
#define BCOLOR BLUE
#define FCOLOR MAGENTA
#define HBCOLOR h_bcolor
#define HVCOLOR h_fcolor
#define VCOLOR WHITE

int h_bcolor;
int h_fcolor;
int getsize(void);
char *tabtospace(char *s);
int printdash(int i);
char *gledir(char *s);
int scr_menuval(void);
int scr_menubg(void);
int scr_menuhi(void);
int scr_grey(void);
int gle_redraw(void);
int text_showerror(void);
int text_save(void);
char *strfile(char *s);

int vdelete(int i);
int vinsert(int y, char *s);
int m_ifsend(char *s);
int m_sendline(void);
int minit_extras(void);
int minit_extras(void);
int initmenu(void);
int mystrlen(char *s);
int pick_file(char *d, char *w);
int ncpy(char *d, char *s, int n);
int setvstr(char **d, char *s);
int text_inkey(void);

struct menu_struct { int x; int y; char *title; int width; int typ; int typ2;
	char *val; char *help; };
typedef struct menu_struct menutype;
struct pmenu_struct {int ci; menutype *menu; };
typedef struct pmenu_struct pmenutype;
pmenutype pmenu[17];
int setmenu(menutype *m,int x, int y, int typ, int typ2, int width, char *title
	, char *val, char *help);
int do_menu(pmenutype *p);
int token_space(void);
int extractmenu(void);
int add_unrecognized(char *s);
int fillinmenu(int nbegin);
int nunrec;

#define  PTXT 0
enum {MEND,MTEXT,MFILE,MTOGON,MTOGOFF,MSUB,MRETURN,MNULL};
enum {SNORM,SROL,SNEXTS,SNEXT,SSTR,STOG,SS,SSIZE,SNOBOX,SAMOVE,SSOFF,SSNULL};
int refresh_menu(struct menu_struct *m);
int menu_hilight(struct menu_struct *m);
int menu_norm(struct menu_struct *m);

/* menu's
	topmenu
		title,xtitle,ytitle min max dist on off, ticks dticks
		(2) let d = exp
		Data files
		Dn marker ,color, lwidth, lstyle, err,
	xnamesmenu
	ynamesmenu
	fillmenu
	barmenu
	axismenu's
*/
read_default(char *result, char *ques, char *dflt)
{
	char s[200];
	int r;
	strcpy(s,ques); strcat(s," ["); strcat(s,dflt); strcat(s,"] ");
/*	r = read_input(result,s);*/
	if (strlen(result)==0) strcpy(result,dflt);
	return r;
}
extern int changed;
addline(char *s)
{
	changed = true;
}
char *mark_names[] = {
	"dot", "square", "fcircle", "club", "diamond", "triangle", "snake"
	,"otimes", "odot", ""};

int init_menucolor(void);
int m_gstart,m_gend;
/*

	Getkey/command
		arrowkeys normal
		left and right arrow if editing
		delete
		insert normal character
		enter, change to new menu
		escape exit.
		F1, help key
*/
char mbuff[255];

extern int iserr;
int hcx,cx,hcy;	/* HIlighted current x,y */
do_menu(pmenutype *ppmenu)
{
	menutype *cm,*cmi,*si=NULL,*mi;
	int citem,emode=false;
	int c;
	cm = ppmenu->menu;
	citem = ppmenu->ci;
	cmi = cm+citem;
	refresh_menu(cm);
	menu_hilight(cmi);
	for (;;) {
	 c = text_inkey();
	 if (iserr) {fner_clear(); window(1,1,80,24);}
	 switch (c) {
	   case eescape: /* ESCAPE */
	   case equit: /* control c */
		return true;
	   case eleft: /* left */
		if (emode) {
			if (cx>0) cx--;
			gotoxy(hcx+cx,hcy);
		} else {
			for (si=NULL,mi=cm;mi->typ!=0;mi++) {
				if (mi->y==cmi->y && mi->x < cmi->x)
				if (si!=NULL) {
					if (mi->x > si->x)
						si = mi;
				} else si = mi;
			}
		}
		break;
	   case eright: /* right */
		if (emode) {
			if (cx < strlen(cmi->val)) cx++;
			gotoxy(hcx+cx,hcy);
		} else {
			for (si=NULL,mi=cm;mi->typ!=0;mi++) {
				if (mi->y==cmi->y && mi->x > cmi->x)
				if (si!=NULL) {
					if (mi->x < si->x)
						si = mi;
				} else si = mi;

			}
		}
		break;
	   case eup: /* arrow up */
		emode = false;
		for (si=NULL,mi=cm;mi->typ!=0;mi++) {
			if (mi->typ<MNULL) {
			 if (si!=NULL) if (mi->y==si->y)
			   if (abs(mi->x - cmi->x) <  abs(si->x - cmi->x))
				si = mi;
			 if (mi->y < cmi->y) if (si!=NULL) {
			   if (mi->y > si->y) si = mi;
			 } else	  si = mi;
			}
		}
		break;
	   case edown: /* arrow down */
		emode = false;
		for (si=NULL,mi=cm;mi->typ!=0;mi++) {
			if (mi->typ<MNULL) {
			 if (si!=NULL) if (mi->y==si->y)
			   if (abs(mi->x - cmi->x) <  abs(si->x - cmi->x))
				si = mi;
			 if (mi->y > cmi->y) if (si!=NULL) {
			   if (mi->y < si->y) si = mi;
			 } else  si = mi;
			}
		}
		break;
	  case ehelp: /* f1 help */
		do_help(cmi->help);
		refresh_menu(cm);
		menu_hilight(cmi);
		break;
	  case ereturn: /* carriage return */
		if (emode==true && cmi->typ==MFILE) {
			emode = false;
			break;
		}
		emode = false;
doreturn:;
		switch (cmi->typ) {
		  case MTEXT:
/*			if (emode) emode = false; else emode = true; */
			break;
		  case MTOGON:
			cmi->typ = MTOGOFF;
			menu_hilight(cmi);
			break;
		  case MTOGOFF:
			cmi->typ = MTOGON;
			menu_hilight(cmi);
			break;
		  case MRETURN:
			goto exit_menu;
		  case MFILE:
			if (mystrlen(cmi->val)==0) cmi->val = calloc(20,1);
			pick_file(cmi->val,"*.dat");
			refresh_menu(cm);
			menu_hilight(cmi);
			break;
		  case MSUB: /* SUB MENU */
			if (cmi->typ2>99) do_menu(&pmenu[cmi->typ2 - 100]);
			refresh_menu(cm);
			menu_hilight(cmi);
		}

		for (si=NULL,mi=cm;mi->typ!=0;mi++) {
			if (mi->y==cmi->y && mi->x > cmi->x)
			if (si!=NULL) {
				if (mi->x < si->x)
					si = mi;
			} else si = mi;
		}

		break;
	  case edelete: /* delete */
		emode = true;
		if (cmi->val==NULL) break;
		if (strlen(cmi->val)==0) break;
		if (cx<1) break;
		ncpy(mbuff,cmi->val,cx-1);
		strcat(mbuff,cmi->val + cx);
		setvstr(&cmi->val,mbuff);
		cx--;
		gotoxy(hcx+cx,hcy);
		cputs(cmi->val + cx);
		putch(DASHCHAR);
		gotoxy(hcx+cx,hcy);
		break;
	  case edrawit:
		break;
	  case eshowerror:
		break;
	  case esave: /* save file */
		break;
	  default: /* normal key */
		if (c<26  && c!=9) {fner("Key has no affect"); break;}
		if (c>200)  fner("Unimplemented command");
		else {
/* 	if (cmi->typ!=MTEXT  && cmi->typ!=MFILE) goto doreturn; */
			emode = true;
			if (cmi->val==NULL) setvstr(&cmi->val,"");
			ncpy(mbuff,cmi->val,cx);
			mbuff[cx] = c; mbuff[cx+1] = 0;
			strcat(mbuff,cmi->val + cx);
			setvstr(&cmi->val,mbuff);
			gotoxy(hcx+cx,hcy);
			cputs(cmi->val + cx);
			cx++;
			gotoxy(hcx+cx,hcy);
		}
		break;
	 }
	 if (si!=NULL) {
		menu_norm(cmi);
		cmi = si;
		menu_hilight(cmi);
		si = NULL;
	 }
	}
exit_menu:;
	/* save current point */
	{ int i;
		for (i=0,mi=cm;mi->typ!=0;mi++,i++) {
		  if (mi==cmi) ppmenu->ci = i;
		}
	}
	return false; /* normal exit */
}
setvstr(char **d, char *s)
{
	if ((*d) != 0) myfree(*d);
	*d = sdup(s);
}
int mystrlen(char *s)
{
	if (s==NULL) return 0;
	else return strlen(s);
}
menu_hilight(struct menu_struct *mm)
{
	int i,j;
	struct menu_struct *m=mm;
	scr_menuhi();
	hcx = m->x + mystrlen(m->title);
	hcy = m->y;
	gotoxy(hcx,hcy);
	if (m->typ==MTOGON || m->typ==MTOGOFF) {
		if (m->val==NULL) m->val = malloc(4);
		if (m->typ==MTOGON) strcpy(m->val,"ON ");
		if (m->typ==MTOGOFF) strcpy(m->val,"OFF");
	}
	if (m->val==NULL) setvstr(&m->val,"");
	cputs(m->val);
	j = m->width - mystrlen(m->val);
	printdash(j);
	cx = mystrlen(m->val);
	gotoxy(hcx+cx,hcy);
}
printdash(int j)
{
	int i;
	for (i=0;i<j;i++) mbuff[i] = DASHCHAR;
	mbuff[j] = 0;
	if (j>0) cputs(mbuff);
}
menu_norm(struct menu_struct *mm)
{
	int i,j;
	struct menu_struct *m=mm;
	gotoxy(m->x + mystrlen(m->title),m->y);
	if (m->typ==MTOGON  || m->typ==MTOGOFF) {
		if (m->val==NULL) m->val = malloc(4);
		if (m->typ==MTOGON) strcpy(m->val,"ON ");
		if (m->typ==MTOGOFF) strcpy(m->val,"OFF");
	}
	if (m->val != NULL) {
		scr_menuval();
		if (m->width>0) cputs(m->val);
		scr_menubg();
	}
	j = m->width - mystrlen(m->val);
	printdash(j);
}
refresh_menu(struct menu_struct *mm)
{
	int i;
	struct menu_struct *m=mm;
	window(1,1,80,24);
	scr_menubg();
	clrscr();
	for (;m->typ!=0;m++) {
		if (m->title != NULL) if (strlen(m->title)>0) {
			gotoxy(m->x,m->y);
			cputs(m->title);
		}
		menu_norm(m);
	}
}
do_help(char *k1, char *k2)
{
	FILE *hfile;
	int i,yy;
	char hbuff[90];
	char *hfilename="manip.hlp";
	char fk1[20],fk2[20],*os,*si;
	scr_menuval();
	clrscr();
	if (strcmp(k2," ")==0) k2 = "";
	gotoxy(1,1); wprintf("Manip help on topic {%s},  sub topic {%s}",k1,k2);
	scr_menubg();
	hfile = fopen(gledir(hfilename),"rt");
	if (hfile==NULL) wprintf("Unable to open {%s} \n",gledir(hfilename));
	for (;!feof(hfile);) {
		if (fgets(hbuff,90,hfile)!=NULL) {
			if (hbuff[0]=='3') {
				strtok(hbuff," \n");
				strcpy(fk1,strtok(NULL," \n"));
				if (strcmp(fk1,k1)==0 && strlen(k2)==0)
					goto help_type;
			}
			if (hbuff[0]=='4') {
				strtok(hbuff," \n");
				strcpy(fk2,strtok(NULL," \n"));
				if (strlen(k2)>0)
				if (strcmp(fk1,k1)==0 &&
					strcmp(fk2,k2)==0) goto help_type;
			}
		}
	}
	fclose(hfile);
	scr_menuval();
	gotoxy(1,9);
	wprintf("help text not found sorry ??? \n");
	text_inkey();
	return;
help_type:;
	yy = 3;
	for (;!feof(hfile);) {
		if (fgets(hbuff,90,hfile)!=NULL) {
			if (isdigit(hbuff[0])) {
				goto end_help;
			}
			gotoxy(1,yy++); cputs(tabtospace(hbuff));
		}
		if (yy==22) {
			scr_menuval();
			gotoxy(2,24); wprintf("Press any key for next screen of help");
			text_inkey();  clrscr();
			gotoxy(1,1); wprintf("Graph help on topic {%s},  sub topic {%s}",k1,k2);
			scr_menubg();  yy = 3;
		}
	}
end_help:;
	scr_menuval();
	gotoxy(1,yy+1); wprintf("Press any key to continue");
	text_inkey();
	fclose(hfile);
}
add_unrecognized(char *s)
{
	if (nunrec>6) return;
}
int vunquote(char **s);
vunquote(char **ss)
{
	char *s = *ss;
	if (*s=='\"') {
		s[strlen(s)-1] = 0;
		*ss = sdup(s+1);
		myfree(s);
	}
}

int initmenudone;
menutype *m_pnt[20];
menutype *m_end[20];
char *m_val[20];
char m_tog[50];
initmenu()
{
	menutype *mi;
	char *s,kw1[80],kw2[80];
	int i,j,nt=0,k,z,ct,used;
	static int nv;

	if (!initmenudone) {
	  initmenudone = true;
	  for (z=0;z<=10;z++) {
	    for (mi=pmenu[z].menu; mi->typ!=0; mi++) {
		if (mi->typ==MTOGON || mi->typ==MTOGOFF) {
			m_tog[nt++] = mi->typ;
		}
		if (mi->val!=NULL) {
			m_val[nv] = sdup(mi->val);
			mi->val = sdup(mi->val);
			m_pnt[nv++] = mi;
		}
	    }
	  }
	} else {
	  for (z=0;z<=10;z++) {
	    for (mi=pmenu[z].menu; mi->typ!=0; mi++) {
		if (mi->typ==MTOGON || mi->typ==MTOGOFF) {
			mi->typ = m_tog[nt++];
		} else {
			if (mi->val!=0) {
				myfree(mi->val);
			}
			mi->val = 0;
		}
	    }
	  }
	  for (z=0;z<nv;z++) {
		mi = m_pnt[z];
		mi->val = sdup(m_val[z]);
	  }
	}
}

char msend[200];
#define mss msend+strlen(msend)
char cs[80]="xyz";
int gstartend;
/* char msend[200]; */
m_sendline()
{
	msend[0] = 0;
	strcpy(cs,"xyz");
}
m_ifsend(char *s)
{
	if (strcmp(s,cs)!=0) {
	  m_sendline();
	  sprintf(msend,"\t%s ",s);
	  strcpy(cs,s);
	}
}
int g_get_usersize(double *x, double *y);
setmenu(menutype *m,int x, int y, int typ, int typ2, int width, char *title
, char *val, char *help)
{
	m->x = x; m->y = y; m->typ = typ; m->typ2 = typ2; m->width = width;
	m->title = sdup(title);
	if (val!=0) m->val = sdup(val);
	m->help = sdup(help);
}
init_menucolor()
{
		h_bcolor = WHITE; h_fcolor = BLACK;
}
int pick_file(char *result, char *wld)
{
	pmenutype ask;
	char wild[80];
	char buff2[80];
	char *f[80];
	char *swap;
	menutype *m,*mi,*mwild;
	struct ffblk ffblk;
	int done,i,x,y,nf,rval,adddir=false;

	strcpy(wild,wld);
	ask.ci = 0;
pick_again:;
	x=0; y=0; nf=0;
	init_menucolor();
	done = findfirst(wild,&ffblk,0);
	for (nf=0;nf<70 && !done;nf++) {
		f[nf] = sdup(ffblk.ff_name);
		done = findnext(&ffblk);
	}
sortagain:;
	swap = NULL;
	for (i=0;i<(nf-1);i++) {
		if (strcmp(f[i],f[i+1])>0) {
			swap = f[i]; f[i] = f[i+1]; f[i+1] = swap;
		}
	}
	if (swap != NULL) goto sortagain;

	m = calloc(3+nf,sizeof(*m));
	ask.menu = m;
	ask.ci = 0;
	if (nf==0) ask.ci = 1;
	if (m==0) wprintf("memory allocation error");
	for (mi=m,i=0;i<nf;i++,mi++) {
		setmenu(mi,x*20+1,y+5,MRETURN,0,18,"",f[i],"");
		x++;
		if (x==4) {x=0; y++; }
	}
	setmenu(mi,5,1,MNULL,0,0,"Use arrow keys to select file then press return","","");
	mi++;
	setmenu(mi,5,3,MRETURN,0,30,"Disk/Dir Specification ",wild,"");
	mwild = mi;
	mi++; mi->typ = 0;
	rval = do_menu(&ask);
	strcpy(result,((ask.menu)[ask.ci]).val);
	for (i=0;i<nf;i++) myfree(f[i]);
	myfree(m);

	if (strcmp(wild,mwild->val)!=0) {
		strcpy(wild,mwild->val);
		if (strstr(wild,"*")==NULL) {
			if (wild[strlen(wild)-1] == '\\')
				strcat(wild,"*.gle");
			else
				strcat(wild,"\\*.gle");
		}
		adddir = true;
		goto pick_again;
	}

	if (adddir) {
		*(strfile(wild)) = 0;
#ifdef __TURBOC__
		if (strstr(wild,":")!=NULL) {
			setdisk(toupper(*wild)-'A');
		}
		strcpy(buff2,wild+2); strcpy(wild,buff2);
#endif
		if (chdir(wild)!=0) ; /* {perror("Cannot change dir"); delay(3000);}*/
	}

/*	if (adddir) {
		*(strfile(wild)+1) = 0;
		strcpy(result,wild);
		strcat(result,((ask.menu)[ask.ci]).val);
	}
*/
	return rval;
}
char *strfile(char *s)
{
	char *e;
	e = s;
	for (;*s!=0;s++) {
		if (*s==']'  ||  *s=='\\' || *s=='/' || *s==':') e = s;
	}
	return e;
}
char *tabtospace(char *s)
{
	static char buf[255];
	char *o = &buf[0];
	int p=0,k,df;
	for (;*s!=0;s++) {
		if (*s==9) {
			df = (p/8)*8+8-p;
			for (k=1;k<=df;k++) {
				*o++ = ' ';
				p++;
			}
		} else {
			*o++ = *s;
			p++;
		}
	}
	*o = 0;
	return &buf[0];
}
