#include "all.h"
#include <errno.h>
#include <math.h>
#ifdef __TURBOC__
#define HLINECHAR 205
#include "bios.h"
#include "conio.h"
#else
#define ENOFILE 999
#define HLINECHAR '-'
#include "vaxconio.h"
#endif
#include "edt.h"
int vax_edt(char *s);
int delay(int i);
extern int gle_debug;
int gle_speed;
int gle_nspeed;
int trace_on;
#define true (!false)
#define false 0
#define dbg if (gle_debug>0)
long mem_total(void);
int pick_file(char *r, char *w);
typedef char (*TEXT)[];
int scr_blackwhite;
int scr_left(int i);
int scr_right(int i);
int scr_norm(void);
int scr_inv(void);
int scr_grey(void);
int text_search(void);
int text_deleol(void);
int text_undeleol(void);
int scr_savexy(void);
int scr_restorexy(void);
int scr_gets(char *s);
int text_showerror(void);
int text_findnext(void);
int text_changed(void);
int read_command(char *ans, char *ques);
int read_str(char *s);
int text_load(char *fname);
int text_free(void);
int do_help(char *s);
int int_edt(char *fname);
int vinsert(int y, char *s);
int vdelete(int y);
int menu(void);
int gle_redraw(void);
int scrinsert(int y);
int scrdeleteline(int y);
int text_save(void) ;
int text_eol(void);
int text_delright(void);
int text_delete(void);
int text_undelete(void);
int text_deleteline(void);
int text_left(void);
int text_right(void);
int text_up(void);
int text_down(void);
int text_return(void);
int text_refresh();
int text_putstr(char *s);
int text_setwindow();
int text_saveas(void);
int text_move(int x,int y);
int scr_tab(char *s, int x);
int scr_negtab(char *s, int x, int *fpos, int *scrx);
int fner(char *s);
int fner_clear(void);
int text_setwindow(void);
int text_refresh(void);
int text_main(void);
int text_inkey(void);
int text_scroll(void);
int text_scroll_up(void);
int text_scroll_down(void);
int text_select(void);
int text_cut(void);
int text_paste(void);
int restofline(int y,int x);
int normal_key(int c);
int lineset(int i,char *ss);
int lineinsert(int y, char *ss);
int textinsert(int y);
char *sline(int i);
char *line(int i);
int ncpy(char *d, char *s, int n);
/*------------ GLOBAL VARIABLES --------------*/
extern long gtotalmem;
int max_ngtxt;
extern int ngtxt;
extern char *(*gtxt)[];   /* gtxt is a pointer to an array of poiter to char */
char *(*ctxt)[];	/* cut buffer */
int ncut;
int iserr;
int w_top=0,w_bot=0,w_len,w_cl,w_cx;
#define MAXLINES (max_ngtxt-10)
extern int ngtxt;
int move_pos,onmove;
int ii;
char gbuff[255];
char gbuff2[255];
int selx,sely;
extern char input_file[];
int changed;
int scr_isblackwhite(void);
extern int netxt;	/* errors which occured */
extern char *(*etxt)[];
/*---------------------------------------------------------------------------*/
/* copy gtxt, ngtxt   to local paramters */
int tfx,tfy;
extern int gotfile;
int_edt(char *fname)
{
	int i,j;

	tfx = 1;
	tfy = 1;
	w_len = 20;
	scr_blackwhite = scr_isblackwhite();
	if (!gotfile) {
		{ char infile[80]; char wildcard[80];
		strcpy(wildcard,"*.gle");
		if (pick_file(infile,wildcard)) strcpy(infile,"test.gle");
		text_load(infile);
		}
	}
	gotfile=true;
	text_setwindow();
	text_refresh();
	text_main();
}
vinsert(int y,char *ss)
{
	int i;
	if (ngtxt>(max_ngtxt-50)) text_expand(2*(ngtxt+50));
	if (ngtxt>MAXLINES) {fner("too many lines in file "); return;}
	ngtxt++;
	for (i=ngtxt;i>y;i--)
		(*gtxt)[i] = (*gtxt)[i-1];
	(*gtxt)[y] = sdup(ss);
}
lineinsert(int y,char *ss)
{
	vinsert(y,ss);
	scrinsert(y);
}

vdelete(int y)
{
	int i;
	if (ngtxt==0) {fner("too few lines in file "); return;}
	ngtxt--;
	myfrees((*gtxt)[y],"vdelete");
	for (i=y;i<=ngtxt;i++)
		(*gtxt)[i] = (*gtxt)[i+1];
}
linedelete(int y)
{
	vdelete(y);
	scrdeleteline(y);
}
lineset(int i,char *ss)
{
	char *zzz;
	int same;
	char *d=(*gtxt)[i];
	char *s=ss;
	if (d==0) gle_abort("linset zero\n");
	for (;*d!=0 && *s!=0 && *d==*s ;s++,d++) ;
	same = s-ss;
	myfrees((*gtxt)[i],"Linset");
	zzz = sdup(ss);
	(*gtxt)[i] = zzz;
	restofline(i,same);
}
char *line(int i)
{
	static char xxx[2]="";
	static char eob[7]="[EOB]";
	if (i>ngtxt) {
		if (i==ngtxt+1) return &eob[0];
		else return &xxx[0];
	}
	return (*gtxt)[i];
}
text_free(void)
{
	int i;
	for (i=1;i<=ngtxt;i++) myfrees( (*gtxt)[i] ,"textfree");
	ngtxt = 0;
}
char *tabtospace(char *s);
char *sline(int i)
{
	char *s;
	s = tabtospace(line(i));
	if (strlen(s)>77) {s[77] = '>'; s[78] = 0;}
	return s;
}
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];
}
text_main()
{
	int c,doask;
	for (;;) {
	 doask = true;
	 c = text_inkey();
	 if (iserr) fner_clear();
	 switch (c) {
	   case eexitnow:
		doask = false;
	   case eescape:
	   case equit: /* control c */
		if (text_changed()) break;
		if (doask) {
		  fner("Exit from cgle ? (Y,N)  [y]");
		  c = text_inkey();
		  fner_clear();
		  if (tolower(c)=='n') break;
		  if (tolower(c)!='y' && c != ereturn) break;
		}
		window(1,1,80,25);
		scr_norm();
		clrscr();
		return;
	   case eedt: /* call edt editor */
		text_save();
		clrscr();
		fner("Entering VAX EDT");
		scr_refresh();
		vax_edt(input_file);
		text_free();
		text_load(input_file);
		text_setwindow();
		text_refresh();
		break;
	   case efast:
		gle_speed++;
		if (gle_speed>=gle_nspeed) gle_speed = 0;
		sprintf(gbuff,"Speed of display set to {%d}",gle_speed);
		fner(gbuff);
		break;
	   case eleft: /* left */
		text_left();
		break;
	   case eshell: /* shell, start a subprocess */
		window(1,1,80,25); scr_norm(); clrscr();
		printf("Type in EXIT to return to CGLE\n\n");
		system("");
		text_refresh();
		break;
	   case etrace: /* trace */
		fner("Trace is now ON (or off)");
		if (trace_on) trace_on = false; else trace_on = true;
		break;
	   case eright: /* right */
		text_right();
		break;
	   case eup: /* arrow up */
		text_up();
		break;
	   case edown: /* arrow down */
		text_down();
		break;
	   case epageup:
		tfy = tfy - 15;
		if (tfy<1) {fner("Backup past top of file"); tfy = 1;}
		text_move(tfx,tfy);
		break;
	   case epagedown:
		tfy = tfy + 15;
		if (tfy>ngtxt) {fner("Advance past end of file"); tfy = ngtxt;}
		text_move(tfx,tfy);
		break;
	   case edelright:
		changed = true;
		text_right();
		text_delete();
		break;
	   case edeleol:
		changed = true;
		text_deleol();
		break;
	   case eundeleol:
		changed = true;
		text_undeleol();
		break;
	   case edelline:
		changed = true;
		text_deleteline();
		break;
	  case edrawit:
		window(1,1,79,24);
		clrscr();
		gotoxy(1,1);
		scr_refresh();
		gle_redraw();
		if (netxt>0) text_showerror();
		text_refresh();
		break;
	  case eshowerror:
		text_showerror();
		text_refresh();
		break;
	  case eundelline:
		changed = true;
		text_undelete();
		break;
	  case eselect:
		text_select();
		break;
	  case ehelp: /* help */
		do_help2("gle");
		text_refresh();
		break;
	  case esaveas:
		text_saveas();
		text_refresh();
		break;
	  case esave: /* save file */
		text_save();
		changed = false;
		break;
	  case efindnext:
		text_findnext();
		break;
	  case esearch: /* search for string */
		text_search();
		break;
	  case egraphmenu: /* graph mode  */
		changed = true;
		menu();
		text_refresh();
		break;
	  case eload:
		{ char infile[80]; char wildcard[80];
		if (text_changed()) break;
		if (read_command(infile,"Name of file to load <return for menu> ")) break;
		strcpy(wildcard,infile);
		if (strlen(infile)==0) strcpy(wildcard,"*.gle");
		if (strchr(wildcard,'*')!=NULL)
			if (pick_file(infile,wildcard)) goto dontload;
		text_free();
		text_load(infile);
		}
		text_setwindow();
dontload:	text_refresh();
		break;
	  case ecut: /* control K , delete line, or block */
		changed = true;
		text_cut();
		break;
	  case ebol:
		text_move(1,tfy);
		break;
	  case eeol:
		text_move(strlen(line(tfy))+1,tfy);
		break;
	  case eendoffile:
		text_move(strlen(line(ngtxt))+1,ngtxt);
		break;
	  case etopoffile:
		text_move(1,1);
		break;
	  case epaste: /* control Y , Yank line back, or block */
		changed = true;
		text_paste();
		break;
	  case ereturn: /* carriage return */
		changed = true;
		text_return();
		break;
	  case edelete: /* delete */
		changed = true;
		text_delete();
		break;
	  default: /* normal key */
		changed = true;
		onmove = false;
		if (c<26  && c!=9) {fner("Key has no affect"); text_move(tfx,tfy); break;}
		if (c>200)  {fner("Unimplemented command"); text_move(tfx,tfy);}
		else normal_key(c);
		break;
	 }
	}
}
text_changed()
{
	int c;
	if (!changed) return false;
	for (;;) {
		fner("Save changes ? (Y,N)");
		c = text_inkey();
		fner_clear();
		if (c==eescape) return true;
		if (tolower(c)=='n') return false;
		if (tolower(c)=='y') {text_save(); return false;}
	}
}
int text_expand(int n);
text_expand(int n)
{
	char **a;
	max_ngtxt = n;
	a = myallocz((n+1)*sizeof(char *));
	if (gtxt!=NULL) {
		memcpy(a,gtxt,(ngtxt+1)*sizeof(char *));
		myfrees(gtxt,"textexpand");
	}
	gtxt = (char *(*)[]) a;
}
text_load(char *fname)
{
static char inbuff[200];
FILE *fptr;
char *s;
int i;
char emess[80];
	changed = false;
	strcpy(input_file,fname);
	s = strchr(input_file,'.');
	if (s==NULL) strcat(input_file,".gle");
	fptr = fopen(input_file,"r");
	if (fptr==NULL) {
		if (errno == ENOFILE) {
		sprintf(emess,"Input file does not exist (%s) ",input_file);
		fner(emess);
		delay(1000);
		} else {
			gprint("Unable to open input file {%s} \n",input_file);
			perror("Reason");
			fner("Press return to continue");
			text_inkey();
		}
	} else {
	 for (;!feof(fptr);) {
		if (fgets(inbuff,200,fptr)!=NULL) {
			i = strlen(inbuff);
			if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
			ngtxt++;
			if (ngtxt>(max_ngtxt-300)) {
				text_expand(2*(ngtxt+500));
			}
			(*gtxt)[ngtxt] = myalloc(i+1);
			strcpy((*gtxt)[ngtxt],inbuff);
		}
	 }
	 fclose(fptr);
	}
	if (ngtxt==0) (*gtxt)[++ngtxt] = sdup("size 24 18");
	if (ngtxt==1) (*gtxt)[++ngtxt] = sdup("");
	tfx = 1;
	tfy = 1;
}
char errgle[90];
int dont_clear;
gle_abort(char *s)
{
	printf("%s",s); scr_refresh();
	d_tidyup();
	delay(1000);
	dont_clear = true;
#ifdef _TURBOC_
	window(1,1,80,25);
	scr_norm();
	clrscr();
#endif
	printf("\n\n\n\n %s \nGle is aborting, Attempting to save file in abort.gle\n",s);
	strcpy(input_file,"abort.gle");
	text_save();
	printf("File is now saved (hopefully)\n");
	if (strstr(s,"alloc")!=NULL  || strstr(s,"Init")!=NULL) {
		printf("\nGLE is short of memory!!\n\n");
		printf("If you are using very large datasets you should try\n");
		printf("the BIGFILE option, otherwise you probably have too\n");
		printf("many memory resident programs on your pc and to make GLE work\n");
		printf("you should remove these from your CONFIG.SYS and AUTOEXEC.BAT\n");
		printf("\n  (make copies of these files before altering them)\n");
	}
	scr_refresh();
	scr_end();
	exit(1);
}
text_save()
{
static int tver=0;
char tbuf[15];
FILE *fptr;
int i;
	changed = false;
	fner("Saving file");
#ifdef __TURBOC__
	if (input_file[1] == ':') setdisk(toupper(input_file[0])-'A');
#endif
	tver++; if (tver==5) tver=1;
	sprintf(tbuf,"gletmp.t%d",tver);
	unlink(tbuf);
	unlink("glegle.tmp");
#ifdef VAXC
#include <file.h>
{
int file_desc;
	file_desc = open("glegle.tmp",O_WRONLY | O_CREAT | O_TRUNC ,0,"rat=cr","rfm=var");
	if (file_desc==-1) { gprint("Open glegle.tmp error \n");  return;}
	fptr = fdopen(file_desc,"w");
}
#else
	fptr = fopen("glegle.tmp","w");
#endif
	if (fptr==NULL) perror("Unable to open output file GLEGLE.TMP");
	for (i=1;i<=ngtxt;i++) {
		if (fputs(line(i),fptr)==EOF
			&& i<ngtxt &&  (strlen(line(i)) > 0) )
			printf("Unable to write line %d {%s} \n",i,line(i));
		fputs("\n",fptr);
	}
	if (fclose(fptr)!=0) perror("Unable to close output file GLEGLE.TMP");
#ifndef VMS
	if (rename(input_file,tbuf)!=0) ; /*
		perror("Unable to rename input file to gletmp.t*"); */
#endif
	if (rename("glegle.tmp",input_file)!=0) perror("Unable to rename GLEGLE.TMP to output file");
	fner_clear();
}
text_bol()
{
	tfx = 1;
}
text_eol()
{
	tfx = strlen(line(tfy))+1;
	text_move(tfx,tfy);
}
text_left()
{
	onmove = false;
	if (tfx==1) {
		if (tfy==1) return;
		tfy--; tfx = strlen(line(tfy))+1;
	} else tfx--;
	text_move(tfx,tfy);
}
text_right()
{
	onmove = false;
	if (tfx== 1+strlen(line(tfy)) ) {
		if (tfy==ngtxt) return;
		tfy++; tfx = 1;
	} else tfx++;
	text_move(tfx,tfy);
}
text_up()
{
	if (tfy==1) {fner("Backup past end of file"); text_move(tfx,tfy); return;}
	if (!onmove) {
		onmove = true;
		move_pos = scr_tab(line(tfy),tfx);
	}
	tfy--;
	scr_negtab(line(tfy),move_pos,&tfx,&ii);
	text_move(tfx,tfy);
}
text_down()
{
	if (tfy==ngtxt) {fner("Advance past end of file"); tfy--;}
	if (!onmove) {
		onmove = true;
		move_pos = scr_tab(line(tfy),tfx);
	}
	tfy++;
	scr_negtab(line(tfy),move_pos,&tfx,&ii);
 /*gotoxy(5,9);gprint("negtab line=%d m=%d f=%d \n",tfy,move_pos,tfx);*/
	text_move(tfx,tfy);
}
text_return()
{
	strcpy(gbuff,line(tfy)+tfx-1);
	ncpy(gbuff2,line(tfy),tfx-1);
	lineset(tfy,gbuff2);
	lineinsert(tfy+1,gbuff);
	text_right();
}
char line_buff[255];
text_undelete()
{
	lineinsert(tfy,line_buff);
	text_move(tfx,tfy);
}
text_undeleol()
{
	strcpy(gbuff2,line(tfy)+tfx-1);
	ncpy(gbuff,line(tfy),tfx-1);
	strcat(gbuff,line_buff);
	lineinsert(tfy,gbuff);
	lineset(tfy+1,gbuff2);
	text_move(tfx,tfy);
}
text_saveas()
{
	char *s;
	if (read_command(input_file,"New gle file name ")) return;
	s = strchr(input_file,'.');
	if (s==NULL) strcat(input_file,".gle");
	text_save();
}
char search_string[100];
text_search()
{
	if (read_command(search_string,"Enter string to search for ")) return;
	strlwr(search_string);
	text_findnext();
}
text_findnext()
{
	int i;
	char fline[100];
	char *p;
	for (i=tfy+1; i<=ngtxt; i++) {
		ncpy(fline,line(i),90);
		strlwr(fline);
		p = strstr(fline,search_string);
		if (p!=NULL) {
			tfy = i; tfx = p - &fline[0] + 1;
			text_move(tfx,tfy);
			return;
		}
	}
	fner("String was not found");
}
text_select()
{
	selx = tfx;	sely = tfy;
	text_move(tfx,tfy);
}
int swapint(int *a,int *b);
swapint(int *a, int *b)
{
	int c;
	c = *a; *a = *b; *b = c;
}
text_cut()
{
	int i,x1=selx,y1=sely,x2=tfx,y2=tfy;
	if (selx==0 && sely==0) return;
	if (y1==y2)  if (x2<x1) swapint(&x1,&x2);
	if (y2<y1) { swapint(&x1,&x2); swapint(&y1,&y2); }
	if (ncut>0) {
		myfrees(ctxt,"textcut");
		for (i=1;i<=ncut;i++) myfree((*ctxt)[i]);
	}
	ctxt = myalloc((y2-y1+3)*4);
	ncut = 1;
	if (y1==y2) {
		ncpy(gbuff,line(y1)+x1-1,x2-x1);
		(*ctxt)[1] = sdup(gbuff);
		ncpy(gbuff,line(y1),x1-1);
		strcat(gbuff,line(y1)+x2-1);
		lineset(y1,gbuff);
		text_move(x1,y1);
		return;
	}
	for (i=y1+1;i<y2;i++) (*ctxt)[++ncut] = sdup(line(i));
	for (i=y1+1;i<y2;i++) linedelete(y1+1);
	(*ctxt)[1] = sdup(line(y1)+x1-1);
	ncpy(gbuff2,line(y1+1),x2-1);
	(*ctxt)[++ncut] = sdup(gbuff2);
	ncpy(gbuff,line(y1),x1-1);
	strcat(gbuff,line(y1+1)+x2-1);
	lineset(y1,gbuff);
	linedelete(y1+1);
	text_move(x1,y1);
}
text_paste()
{
	int i;
	if (ncut==0) return;
	if (ncut==1) {
		ncpy(gbuff,line(tfy),tfx-1);
		strcat(gbuff,(*ctxt)[1]);
		strcat(gbuff,line(tfy)+tfx-1);
		lineset(tfy,gbuff);
		text_move(tfx+strlen((*ctxt)[1]),tfy);
		return;
	}
	ncpy(gbuff,line(tfy),tfx-1);
	strcat(gbuff,(*ctxt)[1]);
	strcpy(gbuff2,(*ctxt)[ncut]);
	strcat(gbuff2,line(tfy)+tfx-1);
	lineset(tfy,gbuff);
	lineinsert(tfy+1,gbuff2);
	for (i=ncut-1;i>1;i--) lineinsert(tfy+1, (*ctxt)[i]);
	text_move(strlen((*ctxt)[ncut])+1,tfy+ncut-1);
}
text_deleol()
{
	if (ngtxt+1==tfy) return;
	strcpy(line_buff,line(tfy)+tfx-1);
	ncpy(gbuff,line(tfy),tfx-1);
	if (tfy<ngtxt) strcat(gbuff,line(tfy+1));
	lineset(tfy,gbuff);
	if (ngtxt<=tfy) {
		gbuff[0] = 0;
		lineinsert(tfy+1,gbuff);
	} else 	linedelete(tfy+1);
	text_move(tfx,tfy);
}
text_deleteline()
{
	if (ngtxt==1) return;
	strcpy(line_buff,line(tfy));
	linedelete(tfy);
	if (ngtxt<tfy) {
		gbuff[0] = 0;
		lineinsert(tfy,gbuff);
	}
	text_move(tfx,tfy);
}
text_delete()
{
	int oldx;
	if (tfx==1) {
		if (tfy==1) {fner("Backup past top of file"); return;}
		text_left();
		oldx = tfx;
		strcpy(gbuff2,line(tfy));
		text_deleteline();
		strcat(gbuff2,line(tfy));
		lineset(tfy,gbuff2);
		tfx = oldx;
		text_move(tfx,tfy);
		return;
	}
	ncpy(gbuff,line(tfy),tfx-2);
	strcat(gbuff,line(tfy)+tfx-1);
	tfx--;
	lineset(tfy,gbuff);
	text_move(tfx,tfy);
}
text_setwindow()
{
	if (tfy>w_top-4 || tfy<w_bot+4) w_top = tfy - (w_len-1)/2;
	if (w_top<1) w_top = 1;
	w_bot = w_top + w_len - 1;
}
text_refresh()
{
	char doubleline[90];
	int e,i;
	iserr = true; /* so that function keys appear at bottom */
	window(1,1,80,25);
	scr_norm();
	clrscr();
	gotoxy(1,1); wprintf("Memory Used=%ld  Free=%ld   CGLE V3.3b  Current file={%s}"
		,mem_total(),coreleft(),input_file);

	memset(doubleline,HLINECHAR,80);
	doubleline[78] = 0;
	gotoxy(1,2); cputs(doubleline);

	fner_clear();
	window(2,3,79,23);
	gotoxy(1,1);
	e = w_bot;
	if (e>ngtxt) e = ngtxt;
	for (i=w_top;i<=e;i++) {
		gotoxy(1,i-w_top+1);
		cputs( sline(i) );
	}
	if (e<w_bot) {
		gotoxy(1,i-w_top+1);
		cputs("[EOF]");
	}
	gotoxy(scr_tab(line(tfy),tfx), tfy - w_top + 1);
}
/*---------- move cursor to file coloumn x, line y */
text_move(int x,int y)
{
	tfx = x;
	tfy = y;
	if (tfy>ngtxt) tfy = ngtxt;
	if (tfy<1) tfy = 1;
/*	if (tfx>79) tfx = 79; */
	if (tfx>strlen(line(tfy))+1) tfx = strlen(line(tfy))+1;
	if (tfx<1) tfx = 1;
	if (tfy<(w_top+5) || tfy>(w_bot-5)) {
		if (tfy<(w_top-25) || tfy>(w_bot+25)) {
			text_setwindow();
			text_refresh();
		} else {
			text_scroll();
		}
	}
	gotoxy(scr_tab(line(tfy),tfx), tfy - w_top + 1);
}
restofline(int y,int x)
{
	int sx;
	if (x <= strlen(line(y))) {
		sx = scr_tab(line(y),x);
		gotoxy(sx,y-w_top + 1);
		clreol();
		cputs(sline(y)+sx-1);
		gotoxy(scr_tab(line(y),tfx), y - w_top + 1);
	}
}
fixline(int y)
{
	gotoxy(1,y-w_top + 1);
	clreol();
	cputs(sline(y));
}
scrinsert(int y)
{
	gotoxy(1,y-w_top + 1);
	insline();
	cputs(sline(y)); clreol();
}
text_scroll()
{
	int n,i;
	n = w_top - tfy + 5;
	/* printf("n %d, w_top %d  tfy %d \n",n,w_top,tfy); */
	if (w_top-n<1) n = w_top - 1;
	if (n>0) {
		for (i=0;i<n;i++) text_scroll_down();
		return;
	}
	n = tfy - w_bot + 5;
	if (w_bot+n>ngtxt) n = ngtxt - w_bot;
	if (n>0) {
		for (i=0;i<n;i++) text_scroll_up();
		return;
	}
}
/* ------------------------ Find screen position given x pos in string */
scr_tab(char *s, int x)
{
	int p=0,i=0;
	for (;*s!=0 && i<(x-1);i++,s++) {
		if (*s==9)  p = (p/8)*8+8;
		else       p++;
	}
	if (p>= 77) p = 77;
	return ++p;
}
/*------------------------- Find file x position given x pos on screen */
/* and sets scrx to the correct screen position (if in middle of tab) */
scr_negtab(char *s, int x, int *fpos, int *scrx)
{
	int last_pos=0,i;
	*fpos=0;
	*scrx = 0;

	for (i=0;*s!=0;s++,i++) {
		if (*s==9) *scrx = (*scrx/8)*8+8;
		else (*scrx)++;
		if ((*scrx+1)>x) {
			*fpos = i+1;
			*scrx = last_pos;
			return;
		}
		last_pos = *scrx + 1;
	}
	if (*scrx==0) (*scrx)++;
	*fpos = i+1;
	if (i==0) *fpos = 1;
}
text_scroll_down()
{
#ifdef __TURBOC__
	window(2,3,79,22);
#endif
	gotoxy(1,1);insline();
#ifdef __TURBOC__
	window(2,3,79,23);
#endif
	w_top--;w_bot--;
	fixline(w_top);
}
text_scroll_up()
{
	char ss[90];
	gotoxy(1,1); delline();
	w_top++; w_bot++;
	fixline(w_bot);
}
scrdeleteline(int y)
{
	gotoxy(1, y - w_top + 1);
	delline();
	fixline(w_bot);
}
extern int noscreenio;
char *function_bar(void);
fner_clear()
{
	if (noscreenio) return;
	if (iserr==false) return;
	if (dont_clear) return;
	window(1,1,80,25);
	gotoxy(1,25);
	scr_grey();
	clreol();
	gotoxy(2,25);
	cputs(function_bar());
	scr_norm();
	iserr = false;
	window(2,3,79,23);
}
extern int noscreenio;
fner(char *s)
{
	if (dont_clear) return;
	if (noscreenio) {
		printf("%s\n",s);
		return;
	}
	scr_savexy();
	iserr = true;
	window(1,1,80,25);
	gotoxy(1,25);
	scr_inv();
	clreol();
	gotoxy(2,25);
	cputs(s);
	scr_norm();
	scr_restorexy();
	scr_refresh();
}
int read_command(char *ans,char *ques)
{
	int rr;
	iserr = true;
	window(1,1,80,25);
	gotoxy(1,24);
	scr_inv();
	clreol();
	gotoxy(2,24);
	cputs(ques);
	rr = read_str(ans);
	gotoxy(1,24);
	scr_norm();
	clreol();
	window(2,3,79,23);
	text_move(tfx,tfy);
	return rr;
}
int read_input(char *ans,char *ques)
{
	int rr;
	iserr = true;
	clreol();
	cputs(ques);
	rr = read_str(ans);
	wprintf("\n");
	return rr;
}

int read_str(char *s)
{
	int c,cx=0;
	char mbuff[80];
	*s = 0;
	for (;;) {
	 c = text_inkey();
	 switch (c) {
	   case eescape: /* ESCAPE */
	   case equit: /* control c */
		return true;
	   case epageup:
		return epageup;
	   case epagedown:
		return epagedown;
	   case eleft: /* left */
		if (cx <= 0) break;
		cx--;
		scr_left(1);
		break;
	   case eright: /* right */
		if (cx >= strlen(s)) break;
		cx++;
		scr_right(1);
		break;
	   case eup: /* arrow up */
	   case edown: /* arrow down */
	  case ehelp: /* f1 help */
		break;
	  case ereturn: /* carriage return */
		return false;
	  case edelete: /* delete */
		if (strlen(s)==0) break;
		if (cx<1) break;
		ncpy(mbuff,s,cx-1);
		strcat(mbuff,s + cx);
		strcpy(s,mbuff);
		cx--;
		scr_left(1);
		cputs(s + cx);
		putch(' ');
		scr_left(strlen(s+cx)+1);
		break;
	  case eshowerror:
	  case edrawit:
		break;
	  default: /* normal key */
		if (c<26  && c!=9) {fner("Key has no affect"); break;}
		if (c>200)  fner("Unimplemented command");
		else {
			ncpy(mbuff,s,cx);
			mbuff[cx] = c; mbuff[cx+1] = 0;
			strcat(mbuff,s + cx);
			strcpy(s,mbuff);
			cputs(s + cx);
			cx++;
			scr_left(strlen(s+cx));
		}
		break;
	   }
	 }
}
normal_key(int c)
{
	static char lbuff[255];
	if (ngtxt+1==tfy) {
		text_up();
		text_eol();
		text_return();
	}
	ncpy(lbuff,line(tfy),tfx-1);
	lbuff[tfx-1] = c; lbuff[tfx]=0;
	strcat(lbuff,line(tfy)+tfx-1);
	tfx++;
	lineset(tfy,lbuff);
}
text_showerror()
{
	int i,n;
	if (netxt==0) {
		fner("There were no errors, press return");
		text_inkey();
		return;
	}
	clrscr();
	n = netxt;
	if (n>20) n = 17;
	for (i=1;i<=n;i++) {
		gotoxy(3,i);
		cputs( (*etxt)[i] );
	}
	gotoxy(1,20); cputs("Press any key to continue");
	text_inkey();
}
#ifndef unix
void wprintf(va_list arg_list, ...)
/* Prints to the window */
{
 	va_list arg_ptr;
 	char *format;
	char output[200];

 	va_start(arg_ptr, arg_list);
 	format = arg_list;
 	vsprintf(output, format, arg_ptr);
#ifdef __TURBOC__
	printf(output);
#else
	cputs(output);
#endif
}
#endif


