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

		DEFINING ROUTINES	*/

/* This module defines FUNCTION KEYS */
#define	   version	0
#define	   revision	2

/* bit marks for the function keys */
#define	   CTRLTYPE 	0x40
#define    CAPTYPE 	0x20
#define	   NOTCAPTYPE   0xDF
#define    FUNCTYPE	0x80

#define		CTRLF1	0xC1
#define		CTRLF2	0xC2
#define		CTRLF3	0xC3

#define		FKTOP	9   /* size of fk clearage area on screen */
#define		FKSTRLOC PROMPTLINE - 4

/* this module has a table of function keys, and a 3K byte
storage area.  The table gives the addr of the byte where the
key starts and the length of the info stored.  It also keeps
a running total of how much of the 3k buffer is being used. 

	Utilities are 
		FKmakstring
		FKcreate
		FKwipe
		FKget
*/	

#define	F1	0x81

#include	"equs.c"
#include	"data.c"

main()

{	char	result,old;
	char	fkey;
	char	keystring [FKEYMAX + 1];

	while (1)
		{    /* choose loop */
		dispbytes();
		old = mens [OfuncKeys].MENdefChoice [0];
		resulô ½ subControì (OfuncKeys);
		if (result == ESC) goto doner;
		if (result == CR)
			{   /* if chosen get level */
			if (old != mens [OfuncKeys].MENdefChoice [0])
				{ menItemdisp (mens [OfuncKeys],old);
				  menItemDisp (mens [OfuncKeys],mens [OfuncKeys].MENdefChoice [0]);
				}
			changeMade = TRUE;
			switch (mens [OfuncKeys].MENdefChoice [0])
				{ case (0)    : if (creFKey (TRUE,keystring)) goto doner;
						dispbot();
			        	        break;
				  case (1)    : if (creFKey (FALSE,keystring)) goto doner;
						dispbot();
				                break;
				  case (2)    : dispFKall ();
				                MainDisp ();
						mendisp (mens [OfuncKeys]);
				                break;
				  case (3)    : readFKey (keystring);
						defItem (OfuncKeys);
				                break;
				} /* switch  */ 
			}  /* CR */
		}   /* while 1 */ 
    doner:
	/* clear byte count */
	curpos ((mens [OfuncKeys].MENchRow [3] + 2 ),mens [OfuncKeys].MENchCol [3]);
	putz (clrtoeolseq);
	curpos ((mens [OfuncKeys].MENchRow [3] + 4 ),mens [OfuncKeys].MENchCol [3]);
	putz (clrtoeolseq);
	dispbot();
}	/* end of def Keys */





dispBytes()
{
	curpos ((mens [OfuncKeys].MENchRow [3] + 2 ),mens [OfuncKeys].MENchCol [3]);
	printz ("%s %d",ms85ptr,FK.bytesleft);
	curpos ((mens [OfuncKeys].MENchRow [3] + 4 ),mens [OfuncKeys].MENchCol [3]);
	putz (ms94ptr);
}


/* resdiplay bottom half of menu */
dispBot()
{	char	top,i;

	clrFKarea();
	for (i = 0; i < mainmen.MENnumChoice; i++)
		if (mainmen.MENchRow [i] != (PROMPTLINE - FKTOP + 1))
			goto gotit;
	/* on drop through do whole thing  */
	mainDisp();
	return;
   gotit:
	top = i;
	menFrame ();
	for (i = top; i < mainmen.MENnumChioce; i++)
		{
		menItemdisp (mainmen,i);
		defItem (i);
		}	
}




char creFKey (doCre,keystring)
	char	doCre,*keystring;
{	char	fkey,result;
	int	stlen,keymax;

	if (isFox) keymax = FKEYMAX;
	else keymax = V5KEYMAX;

while (1)
	{
	fkey = getFKey (doCre); 
	clrFKarea();
	if (fkey == ESC) return (TRUE);
	if (fkey == CR) return (FALSE);	
	
	curpos ((PROMPTLINE - FKTOP + 1),PROMCOL);
	putz (ms78ptr);
	FKptch (fkey);
	curpos ((PROMPTLINE - FKTOP + 2),PROMCOL);
	putz (ms79ptr);
	curpos ((PROMPTLINE - FKTOP + 3),PROMCOL);
	putz (ms80ptr);
	curpos ((PROMPTLINE - FKTOP + 4),PROMCOL);
	putz (ms81ptr);
	if (doCre) keystring [0] = '\0';
	else strcpy (keystring,FKget (fkey));
	stlen = FKinput (keystring,(min (keymax,(FK.bytesleft + strlen (FKget (fkey))))));
	/* store keystring in structure */	
	if (stlen == 0)
		{ 
		  FKwipe (fkey);
		  changeMade = TRUE;
		  }
	else if (stlen != 999)
		{
		changeMade = TRUE;
		FKcreate (fkey,keystring);
		}
	dispBytes();
	defItem (OfuncKeys);
	clrFKarea();

	}  /* while 1  main loop */
		
}	/* end of cre FKEYS */

	


dispFKall ()
{	char	fkey,result,*fstr;
	char	lineNum,i,base,gotone;
	int	col;

	gotone = FALSE;
	lineNum = 0;
	doPrompt (1,&ms83ptr);
	result = inpPrompt (PROMPTLINE,strlen (ms83ptr));
	clrPrompt (1);
	if (result == ESC) return;
	curpos (23,0);
	repchar (LF,3);
	
	for (base = 0x81; base <= 0xC1; base += 0x20)
		{
		for ( i = 0; i < 0x1E; i++) 
			{ if ((fstr = FKget (base + i)) != FK.buffer)
				{ if (lineNum > 19)
					{ repchar (LF,2);
					  if (!st.isSmall & st.SCdoSize & st.SCexLines)
						repchar (LF,2);
					  doPrompt (1,&ms82ptr);
					  result = inpPrompt (PROMPTLINE,strlen (ms82ptr));
					  clrPrompt (1);
					  if (result == ESC) return;
					  lineNum = 0;
					  curpos (23,0);
					}  /* line full */
				  gotone = TRUE;
				  col = 0;
				  col += FKptch (base+i); 
				  ptch ('>');ptch (' ');
				  col += FKputz (fstr) + 2;
				  putz ("\n");
				  lineNum += (col/linelen) + 1;
				}
			
			}  /* i to 1E */
		} /* base */	
	if (!gotone) putz (ms88ptr);
	repchar (LF,2);
	  if (!st.isSmall & st.SCdoSize & st.SCexLines)
		repchar (LF,2);
	doPrompt (1,&ms52ptr);
	result = inpPrompt (PROMPTLINE,strlen (ms52ptr));
	return;
	
}	/* end of display all*/



char readFKeys (kstring)
	char	*kstring;
{	char	base,i;
	PA.PAptr [1] = ms86ptr;
	PA.PAptr [0] = ms20ptr;
	doPrompt (2,PA);
	if (conPrompt (ms20ptr))
		{
		clrprompt (2);
		doPrompt (1,&ms87ptr);
			
		/* 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++)
				{ kstring [0] = 0;
				  inFK ((base+i),kstring);
				  if (strlen (kstring))
					{ if (strlen (kstring) < FK.bytesleft) 
						FKcreate ((base+i),kstring);
					}
				}  /* for i to 0x1e */
			}  /* for base to 0xC1 */
		}  /* read em in */
	doneread:
	clrPrompt (2);

}	/* end of read keys */



inFK (fkey,kstring)
	char	fkey,*kstring;
{	char	len,i;

	while (gtstch()); /* flush buffer */
	if (fkey == ((fkey/10) * 10)) ptch ('.');
	ptch (useesc); ptch ('g');ptch (fkey);  /* prompt */
	len = verchar();  /* check stat and read in loop routine */
	if (len)
		{
		for (i = 0; i < len; i++)
			kstring [i] = gtchna ();
		kstring [len] = '\0';		
		}
	else kstring [0] = '\0';
}




char	getFKey (isCreate)
	char	isCreate;
{	char	fkey;

	PA.PAptr [2] = ms73ptr;
	PA.PAptr [1] = ms74ptr;
	PA.PAptr [0] = ms75ptr;
	doPrompt (3,PA);
	curpos (PROMPTLINE - 2, (PROMCOL + strlen (ms73ptr) + 1));
	if (isCreate) putz (ms76ptr);
	else putz (ms77ptr);
	while (1)
		{ fkey = inpPrompt (PROMPTLINE,strlen (ms75ptr));
		   if ((fkey == CR) | (fkey == ESC) | (fkey > 0x80))
			return (fkey);
		   else ptch (BELL);
		} /* wait for a good key */
}	/* get FKey */

	

clrFKarea()
{	int	i;
	for (i = FKTOP; i >= 0; i--)
		{ curpos ((PROMPTLINE - i),0);
		  putz (clrtoeolseq);
		}
}



int	FKinput (ptr,max)
	char	*ptr;
	int	max;
{
	char 	atoff,hold;
	char	line,totlines;  /* lines displayed */
	int	x,y,i;
	int 	pllen,len;	/* display lengths of string */
	int	loglen,place;	/* logical length ofstring */

	
	place = strlen (ptr);
	loglen = place;
	curpos (FKSTRLOC,0);
	len = FKputz (ptr);
	pllen = len;
	line = (pllen)/linelen;  /* line cursor is currently on */
	totlines = line;       /* number of lines of display */
	while (1)
		{
		atoff = TRUE;
		hold = gtchna();
		if (hold == '@')
			{ atoff = FALSE;
			  hold = gtchna();
			}
		if ((hold == ESC) & atoff) return (999);
		if ((hold == CR) & atoff)
			{
			return (strlen (ptr));
			}	/* if CR or LF */
		if ((hold == DEL) & atoff)
			{ if (place > 0)
				{ /* move string down in array */
				repchar (BS,FKlen (ptr [place-1]));
				putz (clrtoeolseq);
				pllen -= FKlen (ptr [place-1]);
				line = (pllen)/linelen;
				for (i = line + 1; i <= totlines; i++)
					{ curpos (FKSTRLOC+i,0);
					  putz (clrtoeolseq);
					}
				len -= FKlen (ptr [place-1]);
				totlines = (len)/linelen;
				for (i = place-1; i <= loglen; i++)
					ptr [i] = ptr [i+1];
				place--;
				loglen--;
				/* position cursor using pllen */
				x = FKSTRLOC + line;
				y = pllen - (linelen * line);
				curpos (x,y);
				FKputz (&(ptr [place]));
				curpos (x,y);
				}  /* place > 0 */
			else ptch (BELL);
			}   /* back space */
		else if ((hold == RIGHTCUR) & atoff)
			{
			if (place < loglen)
				{ pllen += FKlen (ptr [place]);
				  repchar (CTRLF,FKlen (ptr [place]));
				  place++; 
				}  /* move cursor */
			else ptch (BELL);
			}	/* right */
		else if ((hold == LEFTCUR) & atoff)
			{
			if (place > 0)
				{ pllen -= FKlen (ptr [place-1]);
				  repchar (BS,FKlen (ptr [place-1]));
				  place--; 
				}  /* move cursor */
			else ptch (BELL);
			}	/* left */
		else		/* add char to string */ 
			{
			if (loglen < max)
				{
				for (i = loglen; i >= place; i--)
					ptr [i + 1] = ptr [i];
				ptr [place] = hold;
				FKputz (&(ptr [place]));
				loglen ++;
				place ++;
				pllen += FKlen (hold);
				len += FKlen (hold);
				totlines = (len)/linelen;
				line = (pllen)/linelen;
				x = FKSTRLOC + line;
				y = pllen - (linelen * line);
				curpos (x,y);
				}
			else ptch (BELL);
			}	/* add char to string */
		}  /* while 1 */

}	/* end of FKinput */




/* routine for outputting FK chars */
int	FKptch (chr)
	char chr;
{	char	i;
	int	len;
	if (chr == DEL)
		{ 
		  if (~isFox) putz (stunderseq);
		  putz ("DEL");
		  len = 3;
		  if (~isFox) putz (normseq);
		 }  /* chr == DEL */
	if (chr & FUNCTYPE)
		{
		/* calc where to put norm */
		len = 2; /* for F and DIGIT */
		if (chr & (CTRLTYPE | CAPTYPE)) len++;
		if ((chr & 0x1F) > 9) len++;  /* extra digit */
		if (~isFox) putz (stunderseq);
		if (chr & CTRLTYPE) 
			ptch ('^');
		else if (chr & CAPTYPE)
			ptch ('$');
		ptch ('F');
		printz ("%d",(chr & ~(FUNCTYPE | CTRLTYPE | CAPTYPE)));
		if (~isFox) putz (normseq);
		} /* function key */
	else if (chr < ' ')
		{
		len = 2;
		if (~isFox) putz (stunderseq);
		ptch ('^');
		ptch ((chr | CTRLTYPE) & (NOTCAPTYPE));
		if (~isFox) putz (normseq);
		} /* control key */
	else 
		{ len = 1;
		  ptch (chr);
		}
	return (len);

}  /* end of FKptch */



/* return length of character */
char	FKlen (chr)
	char	chr;
{	
	int	len;

	if (chr == DEL)
		  len = 3;
	if (chr & FUNCTYPE)
		{
		/* calc where to put norm */
		len = 2; /* for F and DIGIT */
		if (chr & (CTRLTYPE | CAPTYPE)) len++;
		if ((chr & 0x1F) > 9) len++;  /* extra digit */
		}
	else if (chr < ' ')
		len = 2;
	else 
		len = 1;
	return (len);

	
}   /* fk len */



/* is character uderlined */

char	FKunder (chr)
	char	chr;
{	
	if ((chr < ' ') | (chr == DEL) | (chr & FUNCTYPE))
		return (TRUE);
	return (FALSE);
 
}  /* fk under */




/* putting string with special characters */
int	FKputz (ptr)
	char *ptr;
{	int	len;
	len =0;
	while (*ptr)
		{ len += FKptch (*ptr);
		  ptr++;
		}
	return (len);
}  

/*  table handling routines */

/* create or modify a table entry */
FKcreate (fkey,str)
	char	fkey,*str;
{	int num,i;
	char *ptr;

	num = FKcalc (fkey);
	if (FK.off [num] != 0)
		FKwipe (fkey);
	ptr = FK.buffer + FK.nextavail;
	strcpy (ptr,str);
	FK.off [num] = FK.nextavail;
	FK.len [num] = strlen (str) + 1;
	FK.nextavail += (strlen (str) + 1); /* one for zero byte */
	FK.bytesleft -= strlen (str); /* zero doesn't count */
	FK.numfuncs++;
	FKprog (fkey,FKget (fkey));

}   /* end of FKcreate */


/* wipe an entry from table */ 
FKwipe (fkey)
	char fkey;
{	int num,wpstart,wplen;
	num = FKcalc (fkey);
	if (FK.off [num] != 0)
		{  /* do wipe */
		FK.numfuncs--;    /* number of keys */
		wpstart = FK.off [num];
		wplen = FK.len [num];
		FK.bytesleft += (wplen - 1); /* don't count zero */
		FK.off [num] = 0;
		FK.len [num] = 0;
		/* now move the data down */
		FK.nextavail -= wplen;
		movmem ((FK.buffer + wpstart + wplen),FK.buffer + wpstart,(FK.nextavail - wpstart));
		/* change table */
		for (num = 0; num < (3 * NUMFKEYS); num++)
			if (FK.off[num] > wpstart) 
			{ FK.off [num] -= wplen;
			}
		} /* do wipe */
	FKprog (fkey,FKget (fkey));

} /* end of FKwipe */

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



/* return table entry number of fkey */
int FKcalc (fkey)
	char fkey;
{
	int num;
	num = (fkey & ~(CAPTYPE | CTRLTYPE | FUNCTYPE));
	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;

	clrprompt (2);
	doPrompt (1,&ms87ptr);
	/* 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 */
	clrprompt (1);
}   /* 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 */
}





