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

/*  File  KKEY.C  -  RML Kermit  -  Keyboard/Screen Routines
		Chris Kennington,	RML.	6th June 1985	*/

#define	 DEFS1	1
#define  F4	0x9b

#include  "stdio.h"
#include  "ctype.h"
#include  "b:kext.h"



/* Globals local to this file:					*/
static	int	dtr = 1;	/* DTR toggle-switch		*/

static  char	*valid[] = {0,	/* validity strings per mode	*/
/* one string for each kmode, contains all valid chars as l.c.;
    ESC maps to {, ? maps to DELT (\175 & \177)			*/
	0,				/* KERMit mode		*/
	"\177bcefhklpqrsz",		/* CONN mode		*/
	"\177abcfhklnqrt",		/* SEND mode		*/
	"\177abcfhklnqt",		/* RECeive mode		*/
	"\177abcfhklnqrt",		/* CoMmaND mode		*/
	"\177kq",			/* PARaMeter mode	*/
	"\177abcfhklnqrt",		/* AUTO mode		*/
	"\177cefhklpqrs",		/* DISK mode		*/
	0,0};			/* end of table			*/

static  char	*texts[] = {   /* help-texts or 0, one per char	*/
	0,
	"A  -  Abort transfer",
	"B  -  send 1-sec line-Break",
	"C  -  Clear screen",
	0,"E+ E- switch Echo on/off",
	"F  -  Front panel",
	0,"H  -  Help on ESC facility",
	0,0,"K  -  return to Kermit command-mode",
	"L  -  Set Listing/Debugging level",
	0,"N  -  set slow-Network option",
	0,
	"P  -  set Parameters",
	"Q  -  Quit from Kermit",
	"R  -  switch to Receive mode",
	"S  -  switch to Send mode",
	"T  -  simulate Timeout (send NAK)",
	0,0,0,0,0,"Z+ Z- toggle DTR on/off", 
	0,0,0,0,"?  -  print this help-text",0};

static  char  confm[] = {NL,"To confirm, hit CR or \"Y\".  Enter new <F4> for each command."};



confirm()		/* verify destructive action		*/
/* Prod user for "Y" as confirmation, return TRUE or FALSE 	*/
{
    char c;

    txtout(" - Yes? ");
    while( (c = kbdin()) == 0 )
	;			/* force next read	*/
    c &= 0x5f;
    if ( (c == 'Y') || (c == CR) ) {
	txtout("OK ");
	return(TRUE);
    }
    else {
	outc(c);
	return(FALSE);
}   }		/* end of confirm()			*/



keyget(ic)		/* get char from keyboard	*/
/* Returns 1 if char, else 0; char in *ic;
   Handles low-level escape-sequences.			*/
char  *ic;
{
    char  c, ch, i, *string;
    int   *ip;

    if ( (ch = kbdin()) == 0 )	/* try to read		*/
	return(0);		/* no char (or null)	*/

/* there is a char to deal with				*/
    *ic = ch;
    ch &= (char)0x7f;
    if ( (ch == CTLC) && (kmode != CONN) )
	kermkill(0);		/* kill if confirmed	*/
  /* if not confirmed, fall through			*/
    if (ch != ESC)
	return(1);		/* normal return	*/

/* ESC (or F4) is break-in				*/
    if ( (kmode == CONN) && (*ic == ESC) )
	return(1);		/* ESC in CONN		*/

    string = valid[kmode];	/* validity string	*/
    if (string == 0)		/* F4s invalid		*/
	return(0);

Rept:
    txtout(eprompt);		/* respond with prompt	*/
Ignore:
    while ( (ch = kbdin()) == 0)
	;			/* force next read	*/

    for (i=0; (ch|(char)0x60) != (c = string[i]); ++i) {
/* search string for match to char; ESC matches {, ? matches DEL */
	if (c == 0) {	      /* end of string, invalid	*/
	    if (ch == F4)	/* F4			*/
		goto Rept;
	    goto End;
    }	}

/* fall through when test satisfied, i.e. matching char in string;
	char represents an action valid in this mode		*/
    ch |= 0x20;			/* force lower case	*/
    switch(ch) {		/* select action	*/
  /* come out of case by break if CR/prompt wanted, by return(0) if not	*/
      case SP:
      case '-':
	goto Ignore;
      case 0x23:		/* CTLC - quit or abort	*/
	kermkill(0);
  /* if not confirmed, fall through			*/
      case 'a':			/* abort transfer	*/
	txtout("A ** Abort current transfer");
	if (confirm() == TRUE) {
	    printmsg("Aborting;%s%s",dots,trying);
	    abtflag = 1;
	    *ic = CR;		/* supply phantom CR	*/
	    return(1);
	}
	break;
      case 'b':			/* send break		*/
	txtout("B - sending 1-sec \"break\" ... ");
	s4break(10);
	txtout("Sent");
	break;
      case 'c':			/* clear screen		*/
	clrscrn();
	break;
      case 'e':			/* Echo switch		*/
	txtout("E ** Echo now ");
	ip = &echo;
	goto Next;
      case 'f':			/* Front panel		*/
	txtout("F ** calling Front Panel - K to continue; ");
	fpanel();
	break;
      case 'h':
	txtout("The F4 key provides a means of setting some parameters or");
	txtout("\r  taking actions, depending on what Kermit mode you are in.");
	txtout("\rInput is a single character or one followed by +, - or a digit;");
	txtout("\r  <F4>? will tell you what chars are valid at any time. ");
	break;
      case 'k':			/* Back to Kermit	*/
	outc('K');
	abtflag = 1;
	kmode = KERM;
	return(0);
      case 'l':		/* list chars transferred	*/
	txtout("L ** List/Debug now ");
	ip = &list;
	goto Next;
      case 'n':			/* slow-network option	*/
	txtout("N ** Slow-network option now ");
	ip = &netslow;
	goto Next;
      case 'p':			/* set parameters	*/
	i = kmode;
	kmode = PARM;
	setshow();
	cursor(9);		/* this is arbitrary	*/
	kmode = i;
	break;
      case 'q':			/* cancel program	*/
	outc('Q');
	kermkill(0);
	break;
      case 'r':			/* switch to receive	*/
	outc('R');
	kmode = RECV;
	return(0);
     case 's':			/* switch to send	*/
	outc('S');
	kmode = SEND;
	return(0);
     case 't':			/* simulate timeout	*/
	txtout("T ** simulate Timeout ");
	++timouts;
	nakflag = 1;
	break;
      case 'z':			/* toggle DTR		*/
	txtout("Z - toggle DTR (enter + or -) ");
	ip = &dtr;
	goto Next;
      case '?':			/* help			*/
	txtout("? - Valid inputs after F4 in this mode are:-");
	while ( (c = *string++) != 0 ) {
	    outc(NL);
	    txtout("    ");
	    c &= 0x1f;		/* range 0-31		*/
	    txtout(texts[c]);
	}
	txtout(confm);
	break;
      default:
	bell();
    }			/* end switch			*/
    goto End;

/* end of main-line code				*/

Next:		/* 3rd char of input, +, - or digit	*/
    while ( (c = kbdin()) == 0 )
	;
    outc(c);
Next2:
    switch (c) {
      case '+':
      case ';':
	++(*ip);
	printf(" ON = %d ",(char)*ip);
	break;
      case '-':
      case '=':
      case '0':
	*ip = 0;
	txtout(" OFF ");
	break;
      case '1':
      case '2':
      case '3':
	if (ip != &parity) {
	    c - '+';
	    goto Next2;
	}
	*ip = c - '0';
	printf(" = %s. ", parsets[parity]);
	setpar();
	break;
      case F4:
	goto Rept;
      default:
	bell();
	txtout(" unchanged ");
    }			/* end of switch		*/
    if (ip == &dtr) {
	if (dtr == 0)
	    comctrl &= 0x7f;		/* drop DTR	*/	
	else
	    comctrl |= 0x80;		/* raise DTR	*/
	s4set(commode,comctrl);
    }
/* end of second-character processing			*/

End:
    outc(NL);
    return(0);			/* no char for Kermit	*/

}			/* end of keyget()		*/



keyline(str)		/* get line of text from keyboard	*/
char	*str;
/* Read keyboard until a line has accumulated in str[], max
     length 80 char.  Terminate on CR or LF, cancel (returning
     null string) on CTL-C, allow deletion by DELT or CTL-H,
     store & echo all other chars except controls after conversion to U.C.
   Return length of string.					 */
{
    char  ptr, c;

    outc(DEOL);
    ptr = 0;
    while (TRUE) {
	while (keyget(&c) == 0)
	    ;
	switch(c) {
	  case CTLC:
	    ptr = 0;
	  case CR:
	  case LF:
	    str[ptr] = 0;
	    txtout(".  ");
	    return(ptr);
	  case DELT:
	  case BKSP:
	    if (ptr > 0) {
		--ptr;
		outc(BKSP);
		outc(SP);
		outc(BKSP);
	    }
	    else
		bell();
	    break;
	  default:		/* other chars		*/
	    if (c < SP)
		;		/* discard controls	*/
	    else if (ptr < 80) {
		outc(c);
		str[ptr++] = c;
	    }
	    else
		bell();		/* overfull		*/

    }	}		/* end of while & switch	*/
/* we never reach here		*/
}		/* End of keyline()			*/



upper(line)		/* convert line to upper case	*/
char	*line;
{
    CHAR	c;

    while ( (c = *line) != 0 ) {
	if (islower(c))
	    *line &= (CHAR)0x0df;
	++line;
   }
   return;
}			/* end of upper()		*/

/*************  END of file KERMKEY.C  *****************/

