/*        *****   **   **    *****    **********     *****
         *******  **   **   *******   **********    *******
         **   **  **   **   **            **       ***   ***
         **       **   **    ****         **       **     **
         **       **   **      ***        **       **     **
         **   **  **   **        **       **       ***   *** 
         *******  *** ***   *******       **        *******
          *****    *****     *****        **         ***** 
*/

/*  this program sees if there was a file name of command
 line.  If so it loads settings from file.  Else it chains to
 termdeaf. */
#include	"equs.c"
#include	"datacstz.c"

/* extern	 char	loadCHset();
extern	 char	verchar();
extern	 char	V5stat();
extern	 char	strmatch();
*/

main (argc,argv)
	int	argc;
	char	*argv[];
{	int	fd;

	if ((argc > 1) & (strcmp (argv [1],"MNGR") != 0))
		{
		fd = open (argv[1],0);
		if (fd == -1)
			printz ("Can't open file %s\n",argv[1]);
		else
			{
			printz ("\n     Reading file %s\n",argv[1]);
			biginit();
			if (readtable (fd) == -1) goto  bombo;
			curpos (23,0);
			if (ft.justUse) 
				{ if (ft.chsloc != 0)
					{ if (readUchar (fd) != -1)
						dnldUCHset ();
					curpos (23,0);
					}
				  if (ft.kbdloc != 0)
					{ lg.Ukeyb = TRUE;
					  if (readKeyb (fd) != -1)
					  	dnldTranTable (KBD);
					}
				putz (defunkseq);
				curpos (23,0);
				} /* file just contains user defined guys */
			else
				{
				STscreen();
				curpos (23,0);
				FKAllProg ();
				curpos (23,0);
				printz ("\n     Still reading file %s.\n",argv[1]);
				curpos (23,0);
				if (lg.charset == 'U')
					{ if (readUchar (fd) == -1)
						lg.charset = '*';
					}
				if (lg.doKeyb)
					{ if (lg.Ukeyb)
						{ if (readKeyb (fd) != -1)
					  		dnldTranTable (KBD);
						}
					  else dnldTranTable (KBD);
					}
				loadCHset(); /* loads language after its read */
				curpos (23,0);
				putz (defunkseq);
				emulcheck();
				} /* not just user file */
			}  /* good open */ 
		}  /* is entry on command line */
	else if ((argc > 1) & (strcmp (argv [1],"MNGR") == 0))
		{ execl ("CUSTOM2","MNGR",0);
		  execl ("A:CUSTOM2","MNGR",0);
		} /* no command line */
	else
		{ exec ("CUSTOM2");
		  exec ("A:CUSTOM2");
		} /* no command line */
	exit();
bombo:
	printz ("\n\nCan't read that file. %c",BELL);
	
}

abort()
{ exit(); }
  
biginit()
{	int	i;

  

		/* 5000 invert status query */	
	V5invenqseq[0] = ESC;
	V5invenqseq[1] = ENQ;
	V5invenqseq[2] = '\0';
	st.SCexLines = FALSE;

	gtVersion();
	gts();

	useesc = 0xFB; /* escape  char to use or this terminal */


	keyinit();
	gtVersion();

	st.SCdoBright = FALSE;
	st.SCdoVid = FALSE;
	st.SCdoSize = FALSE;
	st.SCdoCurse = FALSE;
	lg.charset = '*';
	lg.Ukeyb = FALSE;
	lg.doKeyb = TRUE;
	isUseLang = FALSE;
	isUseKeyb = FALSE;
	loadLang = FALSE;
	st.emulnum = 3;  /* none choice */
	strcpy (st.emulname,"      ");

	
	gts();
	if (isFox) FK.tablesize = FOXTABLESIZE;
	else FK.tablesize = V5TABLESIZE;
	FK.numfuncs = 0;
	FK.nextavail = 1;

	/* load escape sequences */
		/* prog keys as lits on - ESC p */
	funkseq[0] = useesc;
	funkseq[1] = 'p';
	funkseq[2] = '\0';
		/* prog keys as lits off - ESC P */
	defunkseq[0] = useesc;
	defunkseq[1] = 'P';
	defunkseq[2] = '\0';
		/* inquire fox video status - ESC i */
	fvenqseq[0] = useesc;
	fvenqseq[1] = 'i';
	fvenqseq[2] = '\0';
		/* set fox video status - ESC i */
	fvsetseq[0] = useesc;
	fvsetseq[1] = 'I';
	fvsetseq[2] = '\0';
		/* 5000 invert video toggle*/	
	V5invtogseq[0] = useesc;
	V5invtogseq[1] = 'T';
	V5invtogseq[2] = '\0';
		/* FOX invert video toggle*/	
	FXinvtogseq[0] = useesc;
	FXinvtogseq[1] = 'T';
	FXinvtogseq[2] = '\0';
		/* 5000 intensity up one */	
	intupseq[0] = useesc;
	intupseq[1] = 'b';
	intupseq[2] = '\0';
		/* 5000 intensity down one */	
	intdownseq[0] = useesc;
	intdownseq[1] = 'd';
	intdownseq[2] = '\0';
		/* set flashing cursor - ESC E ESC F */	
	crflashseq[0] = useesc;
	crflashseq[1] = 'E';  /* makes visible */
	crflashseq[2] = useesc;
	crflashseq[3] = 'F';
	crflashseq[4] = '\0';
		/* set non flashing cursor - ESC E ESC f */	
	crnonflseq[0] = useesc;
	crnonflseq[1] = 'E';  /* makes visible */
	crnonflseq[2] = useesc;
	crnonflseq[3] = 'f';
	crnonflseq[4] = '\0';
		/* set non invisible cursor - ESC D */	
	crinvseq[0] = useesc;
	crinvseq[1] = 'D';
	crinvseq[2] = '\0';
		/* download CRT transposition table - ESC W */
	ldCRTseq[0] = useesc;
	ldCRTseq[1] = 'W';
	ldCRTseq[2] = '\0';
		/* download KBD transposition table - ESC w */
	ldKBDseq[0] = useesc;
	ldKBDseq[1] = 'w';
	ldKBDseq[2] = '\0';
	/* clear screen sequence */
	clearseq [0] = CTRLL;
	clearseq [1] = '\0';
	/* clear ro end of line sequence */
	clrtoeolseq [0] = useesc;
	clrtoeolseq [1] = 'K';
	clrtoeolseq [2] = '\0';
	/* enable grahpics scaling sequence (4010  mode)*/
	g4010seq [0] = ESC;
	g4010seq [1] = '%';
	g4010seq [2] = '\0';


	charseq [0] = CTRLHAT;
	charseq [1] = '\0';
	/* cursor positon sequence */
	positseq [0] = ESC;
	positseq [1] = 'Y';
	positseq [2] = '\0';
	/* make cursor visible sequence */
	crvisseq [0] = ESC;
 	crvisseq [1] = 'E';
	crvisseq [2] = '\0';
	/* make letters small sequence */
	smallseq [0] = ESC;
 	smallseq [1] = 'S';
	smallseq [2] = '\0';
	/* make letters bigsequence */
	largeseq [0] = ESC;
 	largeseq [1] = 'H';
	largeseq [2] = '\0';
	/* download lagnuage choice to 5000 sequence */
	ldlangseq [0] = ESC;
 	ldlangseq [1] = 'L';
	ldlangseq [2] = '\0';
	/* set 24 lines on screen */
	big24seq [0] = ESC;
 	big24seq [1] = ':';
	big24seq [2] = '\0';
	/* set 26 lines on screen */
	big26seq [0] = ESC;
 	big26seq [1] = ';';
	big26seq [2] = '\0';
	/* load character set sequence  ESC c */
	ldcharseq[0] = ESC;
	ldcharseq [1] = 'c';
	ldcharseq [2] = '\0';
	/* descender table sequence ESC ` (60h) */
	lddescseq[0] = ESC;
	lddescseq [1] = '`';
	lddescseq [2] = '\0';

	/* home the cursor  ^A */
	homeseq [0] = 0x01;   
	homeseq [1] = '\0';




	if (isFox) isHoriz = FALSE;


	strcpy (&ft.headstring[0],"CUSTOMIZ VER");
	ft.headstring [12] = version;
	ft.headstring [13] = revision;
	ft.headstring [14] = '\0';
	strcpy (heado,ft.headstring);

	foò (é ½ 0» é ¼ 128» i++)
		lg.crttrantablå [iİ ½ é;
	for (i = 0; i < 128; i++)
		lg.keytrantable [i] = i;
	lg.keytrantable [CAPZERO] = '0';
	movmem (lg.keytrantable,keybBuffer,128);
		
	
	if (isFox) FK.tablesize = FOXTABLESIZE;
	else FK.tablesize = V5TABLESIZE;
	FK.numfuncs = 0;
	FK.nextavail = 1;
	for (i = 0; i < (3 * NUMFKEYS);i++)
		FK.off [i] = 0;
	FK.bytesleft = (FK.tablesize - (3 * NUMFKEYS));
	for (i = 0; i < (3 * NUMFKEYS);i++)
		FK.len [i] = 0;
	FK.buffer [0] = '\0'; /* for null string refs */



	/* zero keyboard transpostion tale */
	keybzeroseq [0] = ESC;
	if (isFox)
 		keybzeroseq [1] = 'z';
	else keybzeroseq [1] = 'x';
	keybzeroseq [2] = '\0';

}  /* end of big init */




/*  move a  char definiton from one place to another */
movechar (dp,sp,mode)
	 char *dp,*sp,mode; /* pointers to string */
{	int i,j;
	 char	setbyte,readbyte;

	/* mode is set if character needs to be rotated Vertical to
		Horizontal, Horizontal to vertical, or not at all */
	if (mode == NOROT)
		{
		for (i = 0; i < (charbytes); i++)
			{ *dp = *sp;
			   dp++; sp++;
			}
		}  /* no rotation */

	else if (mode == VtoH)
		{
		for (i = 0; i < HORZBYTES;i++)
			*(dp+i) = 0;
			
		 /* to rotate from vert to horiz, for byte B in the vert
			for each on bit (b) turn on the (7-B) bit of byte 
			number (7-b) the horiz structure. */
		setbyte = 0x80;
		for (i = 0; i < VERTBYTES; i++)
			{
			readbyte = *(sp+i);
			for (j = 0; j < HORZBYTES; j++)
				{ if (readbyte & 0x80)
					*(dp + j) |= setbyte;
				  else *(dp + j) &= ~setbyte;
				  readbyte = (readbyte << 1);
				}  /* j to horiz bytes */
			setbyte = (setbyte >> 1);
			} /* i to vertbytes */ 
		
		}  /* rotate a vertical to horiz */
		

	else	/* must be HtoV */
		{
		 /* to rotate from horiz to vert, for byte B in the horiz
			for each on bit b turn on the (7-B) bit of byte number
			(7-b) in the horiz structure. */
		setbyte = 0x80;
		for (i = 0; i < HORZBYTES; i++)
			{
			readbyte = *(sp + i);
			for (j = 0; j < VERTBYTES; j++)
				{ if (readbyte & 0x80) 
					*(dp + j) |= setbyte;
				  else *(dp + j) &= ~setbyte;
				  readbyte = (readbyte << 1);
				}  /* j to horiz bytes */
			setbyte = (setbyte >> 1);
			} /* i to vertbytes */ 
		
		}  /* rotate horiz to vertical */
	
}  /* end of movechar */

/* down load user defined character set, return TRUE if
    successful (failure is only possible with User file  */
 char	loadCHset ()
{
	/* see if user defined, if so download file */

	if (lg.charset == '*') return (TRUE);
	if (lg.charset == 'U')
		{  /* dowloading user file */
		dnldUCHset();
		}  /* if result = U */
	else   /* if 5000 send code, fox dnlad table */ 
		{ if (isFox) dnldTranTable (CRT);
		  else
			{ putz (ldlangseq);
			  ptch (lg.charset);
			} /* 5000 */
		} /* load a standard lagnuage */
	if (lg.doKeyb) dnldTranTable (KBD);
		
	return (TRUE);
}  /* load chset */


/* load character set in */
dnldUCHset()
{	int	i,j,downsize;
	 char	dnstr [HORZBYTES+1];

	/* make sure we can load this lagnuage */
	if (isFox | (st.SCdoSize & (cs.Usmall != st.isSmall))) return;

	/* size of language to download is langsize unless its 
		horizontal and small */
	if (cs.Usmall) 
		{ if (isHoriz) downsize = HORZBYTES * NUMCHARS;
		  else downsize = VERTBYTES * NUMCHARS;
		}
	else downsize = BIGBYTES * NUMCHARS;

	putz (ldcharseq);
	ptch (downsize - ((downsize/256)*256));
	ptch (downsize/256);
	if (! (cs.Usmall & isHoriz))
		{ for (i = 0; i < downsize; i++)
			gptch (cs.langbuffer [i]);
		}  /* not small,horizontal */
	else		/* small and horiz */
		{ for (i = 0; i < NUMCHARS; i++)
			{
			movechar (dnstr,&cs.langbuffer[(i * VERTBYTES)],VtoH);
			for (j = 0; j < HORZBYTES; j++)
				gptch (dnstr[j]); 
			}  /* i to numkeys */
		}  /* small and horiz */
	putz (lddescseq);
	for (i = 0; i < DESCENDBYTES; i++)
		ptch (descenders [i]);
	
}


/***   ***   ***   ***   ***   ***   ***   ***   ***
    ***   ***   ***   ***   ***   ***   ***   ***   ***
 ***   ***   ***   ***   ***   ***   ***   ***   ***   */

/*  down load tran table */
dnldTrantable (dev)
	int	dev;
{	int	i;
	if (dev == CRT)
		{
		putz (ldCRTseq);
		for (i = 0; i < 128; i++)
			ptch (lg.crttrantable[i]); 
		}	/* crt */
	else if (dev == KBD)
		{
		putz (ldKBDseq);
		for (i = 0; i < 128; i++)
			if (lg.Ukeyb) ptch (keybBuffer [i]); 
			else ptch (lg.keytrantable[i]); 
		}  /* kbd */
	else return;

}  /* end of dnld tran table */





int	readtable (fd)
	int	fd;
{	int	recs;

	if (read (fd,&filebuffer[0],2) == -1)
		goto badtabread;
	if (!(strmatch (&filebuffer[1],"CUSTOMIZ VER")))
		goto badtabread;
	/* move table from buffer into ft structure */
	movmem (&filebuffer [0],&ft,sizeof (ft));
	if (!ft.justUse)
		{  /* read in first few structures */
		recs = (roundUp (ft.fkloc + ft.fksize)/128) -2;
		if (read (fd,&filebuffer[256],recs) == -1)
			goto badtabread;
		movmem (&filebuffer [ft.scloc],&st,sizeof (st));
		movmem (&filebuffer [ft.lgloc],&lg,sizeof (lg));
		movmem (&filebuffer [ft.fkloc],&FK,ft.fksize);
		}

	return (0);
badtabread:
	return (-1);
}  /* end of readtable */





int	readUchar (fd)
	int fd;
{  int 	bytenum,i;
   struct CHset *checkptr;

	if (isFox) return;
	if (seek (fd,ft.chsloc/128,0) == -1) goto badchread;
	if (read (fd,&filebuffer[0],1) == -1) goto badchread;
	
	/* check language size */
	checkptr = filebuffer;
	if (checkptr->Usmall) bytenum = NUMCHARS * VERTBYTES;
	else 
		{ /* make sure screen ain't vertical */
		  if (!isHoriz) goto badchread;
		  bytenum = NUMCHARS * BIGBYTES;
		}
	bytenum += sizeof (cs.Usmall) + DESCENDBYTES;

	if (seek (fd,(ft.chsloc/128),0) == -1) goto badchread;
	if (read (fd,&filebuffer[0],((bytenum/128) + 1)) == -1)
		goto badchread;
	/* since successful read move from file buffer to langbuffer */
	movmem (filebuffer,&cs,(bytenum-DESCENDBYTES));
	movmem (&filebuffer [bytenum-DESCENDBYTES],descenders,DESCENDBYTES);
	isUseLang = TRUE;
	return (0);

	
badchread:
	return (-1);
}  /* end of read uchar */



int	readKeyb (fd)
	int fd;
{  int 	bytenum,i;

	bytenum = ft.kbdloc;
	if (bytenum == 0) goto badkbread;
	if (seek (fd,bytenum/128,0) == -1) goto badkbread;
	if (read (fd,&filebuffer[0],1) == -1) goto badkbread;

	/* since successful read move from file buffer to keybuffer */
	isUseKeyb = TRUE;
	movmem (filebuffer,keybBuffer,128);
	return (0);
	
badkbread:
	return (-1);
	
}  /* end of read readlg.Ukeyb */



/* see if size needs to be changed becuase of new user language,
     if so, set flags and return true */
 char	SZresetCheck()
{	if (cs.Usmall != st.isSmall) 
		{ st.isSmall = cs.Usmall;
		  if (st.SCdoSize)
			{ if (!st.isSmall)
				st.SCexLines = FALSE;
			}	
		  return (TRUE);
		}		
	else return (FALSE);
}



/* see if language is invalidated by new size setting, if 
	so, return true  */
 char	LGresetCheck()
{	if (cs.Usmall != st.isSmall)
		{ isUseLang = FALSE;
		  if (lg.charset == 'U')
			{ loadLang == FALSE;
			  lg.charset = '*';
			}
		   return (TRUE);
		}
	else return (FALSE);		

}



STbright ()
{	int i;
	/* set low and then inc */

	for (i = 1; i <= 16; i++)
		putz (intdownseq);
	for (i = 1; i <= (st.SCbright); i++)
		putz (intupseq);

} /* end of STintensity */




/* inquiry - returns 0 if inverse video off */
 char invEnq()
{    char set;
    int i;
	if (isFox)
		{
		
		putz (funkseq); /* disarm string return */
		/* flush key buffer */	
		while (gtstch())
			;
		putz (fvenqseq);
		set = gtchna();
		if (set & NORMVID) return (FALSE);
		   else return (TRUE);
		}  /* fox */
	else 
		{ /* 5000 */
		set = V5stat();
		set = (set & V5INVON);
		return (set);
		} /* for 5000 */
}







STvideo()
{
	if (invEnq())
		{ /* screen currently inverse */
		if (!st.SCinverse) 
			putz (FXinvtogseq);
		}
	else  /* screen currently normal */
		if (st.SCinverse)
			putz (FXinvtogseq);

} /* end of STvideo */





STcurse()
{
	switch (st.SCcurse)
		{
		case (1) : putz (crflashseq);
		           break;
		case (2) : putz (crnonflseq);
		           break;
		case (3) : putz (crinvseq);
		           break;
		}
} /* end of STcurse */




/*  programs character size */
STsize()
{
	if (!isHoriz) return;
	putz (clearseq); 
	if (st.isSmall) putz (smallseq);
	else 
		{ putz (largeseq);
		  if (st.SCexLines) 
			{ putz (big26seq);
			}
		  else 
			{ putz (big24seq);
			}
		} /* large  screen */
}  /* end of STscreen */



int	roundUp (num)
	int	num;
{	int new;
	new = (num/128)*128;
	if (num != new);
		new += 128;
	return (new);
}






STscreen()
{
	if (st.SCdoVid) STvideo();
	if (st.SCdoBright) STbright();
	if (st.SCdoCurse & !isFox) STcurse();
	if (st.SCdoSize & !isFox) STsize ();

}  /* set screen */




/* get string for entry */
 char	*FKget (fkey)
	 char fkey;
{	int num;
	 char *ptr;

	num = FKcalc (fkey);
	num = FK.off [num];
	ptr = FK.buffer + num;
	return (ptr);
}  /* end FKget */

#define	CAPTYPE		0x20
#define	CTRLTYPE	0x40
#define	FUNCTYPE	0x80


/* return table entry number of fkey */
int FKcalc (fkey)
	 char fkey;
{
	int num;
	num = (fkey & ~(CAPTYPE | CTRLTYPE | FUNCTYPE) & 0x00FF);
	if (fkey & CAPTYPE)
		num += NUMFKEYS;
	if (fkey & CTRLTYPE)
		num += (2 * NUMFKEYS);
	num--;	/* first enry is zero */
	return (num);
}  /* end of FKcalc */


/* send down the whole lot */
FKAllProg()
{	int	i,base;
	 char  *fptr,result;

	printz ("\n   PLEASE DON'T PRESS ANY KEYS ");
	/* three pass loop for normal (81h), cap (A1h) and control (C1h) keys */
	for (base = 0x81; base <= 0xC1; base += 0x20)
		{
		for ( i = 0; i < 0x1e; i++)
			{ if ((fptr = FKget (base + i)) != FK.buffer) 
				  FKprog ((base + i),fptr);
			  if ((base+i) == (((base+i)/10) * 10)) ptch ('.');
			}  /* for i to 0x1e */
		}  /* for base to 0xC1 */
}   /* end FKallprog */


/* program function key */
FKprog (fkey,str)
	 char fkey,*str;
{ 	 char	len;
	len = strlen (str);
	if (len == 0) return;
	/* put escape sequence */
	ptch (useesc); ptch ('l');
	/* send key, length and string */
	ptch (fkey); ptch (len);
	sputz (str);  /* uses output routine that won't expand \n */
}


/* get screen type and version */
gtVersion()
{	 char verseq [3],verstring [29],set;
	int	i;

	useesc = ESC;
verloop:
	verseq [0] = useesc;
	verseq [1] = 'V';
	verseq [2] = '\0';
	strcpy (verstring, "         ");
	/* flush buffer */
	while (gtstch() != '\0')
		;
	putz (verseq);
	for (i = 0; i < 28; i++)
		{ verstring [i] = verchar();
		  if (verstring [i] == '/0') 
	  	 	 break;
		}
	if (strlen (verstring) == 0) goto giveup;
	if (strmatch (verstring,"5000"))
		isFox = FALSE;
	else if (strmatch (verstring,"FOX"))
		isFox = TRUE;
	else goto giveup;
		
	if (!isFox) 
		{  /* set 5000 status */
		set = V5stat();
		if (set & VERTBIT) 
			{ isHoriz = FALSE;
			  st.isSmall = TRUE;
			}
		else isHoriz = TRUE;
		}
	return;

	giveup:
		printz ("\nProgram can not run on this terminal\n%c",BELL);
		exit ();

}     /* end of gtVersion */

 char verchar()
{	int i;  char	chr;
	
	for (i = 0; i < 100; i++)
		{ chr = gtstchna();
		  if (chr != '\0') return (chr);
		}
	return (chr);
	
}   /* verchar */


 char	V5stat()
{	 char	set,i;

	/* flush key buffer */	
	while (gtstch())
		;
	putz (V5invenqseq);
	set = verchar();
	/* dump other 5 status bytes */
	for (i = 1; i <= 5; i++)
		dummy = verchar();
	return (set);	
}


	/* chain to emualtions */
emulcheck()
{ char stringer [17];
	if (isFox)
		{
		if (st.emulname[0] != ' ')
			{
			/* erase .COM  */
			dummy = exec (st.emulname);
			strcpy (stringer,"A:");
			strcat (stringer,st.emulname);
			exec (stringer);
			}
		}

}  /* end of emulcheck */


curpos (r,c)
	 char	r,c;
{
	ptch (ESC); ptch('Y');
	ptch (r + 0x20); ptch (c + 0x20);
}


/* return true if strings match for length of the shorter one */
 char	strmatch (p1,p2)
	 char	*p1,*p2;
{	
	while ((*p1) && (*p2))
		{
		if (*p1 != *p2) return (FALSE);
		p1++;
		p2++;
		}
	return (TRUE);	
} /* end of strmatch */



