/* BEGIN DOCUMENTATION Name: TCMINPUT.C Created: 07/20/83 DTS Last Update: 05/21/84 Title: Asynchronous character input for TCM Index: Abstract: Uses RSX qio and ast routine to input one character at a time from the terminal. Usage: rdastinit(lun,eflag); Sets input to ast routine & initializes buffer. ch = inchar(); Returns next character from buffer or EOF if empty. Parameters: int lun; ! Lun for terminal int eflag; ! Event flag set when characters are Input int timeout;! Read timeout in seconds int ch; ! Character returned as integer Environment: RSX 11M V4.0, DECUS C See Also: TCMEDIT.C, TCMTABLES.C Description: RDAST checks input character for control character or escape sequence and sets to value > 127 if defined in TCMTABLES as a special key. Before calling tdastinit TI: must be set to full duplex and typeahead mode. Example(s): Uses: Internal: Characters 1 - 127 are standard ASCII characters 128 - 159 are control characters 160 - 191 are escape sequence keys 192 - 255 are gold key sequences Update History: 12/02/83 Changed read qio to no echo mode. 03/22/84 Ignore break key Framing Error. END DOCUMENTATION */ #include #include #include #include "tcmdefs.h" #include "tcmpublic.h" #include "tcmerr.h" #define escch 155 /* 27 + 128 */ #define goldch 160 /* 32 + 128 */ #define RDBUFLEN 128 /* forward references */ extern rdast(); extern int match(); /* Values defined in TCMTABLES.C */ extern int esclen; /* Maximum escape sequence length */ extern char *esctab; /* Escape sequence table [32] */ extern char *gldtab; /* Gold key sequence table [64] */ /* Global area */ int timeout; /* Timeout in seconds */ char rdbuf[RDBUFLEN]; /* Read buffer for input commands */ charpointer rdchar; /* Pointer to next char to rdbuf */ charpointer inchr; /* Pointer to next char from rdbuf */ charpointer bufend; /* Pointer to end of rdbuf */ int ccount; /* char count in rdbuf */ int iosb[2]; /* iostatus block */ int readfnc; /* Function for qio read */ int eflag; /* event flag for input */ int devpar[3]; /* qio parms */ int lun; boolean esc; /* Flag to indicate esc sequence */ boolean gold; /* Flag to indicate gold key pressed */ rdastinit(iolun,eflg) /* Set up for ast input and do single character read */ int iolun,eflg; { /* initialize flags */ esc = gold = false; /* initialize buffer */ ccount = 0; /* char count in rdbuf */ bufend = rdchar = inchr = &rdbuf; bufend += RDBUFLEN; /* initialize qio parms */ eflag = eflg; /* event flag for input */ lun = iolun; devpar[1] = 1; /* Number of characters to read */ devpar[2] = timeout; /* Timeout in seconds */ iff timeout != 0 then readfnc = IO_RST | TF_RNE | TF_TMO; else readfnc = IO_RST | TF_RNE; rdastchar(); /*** Do initial qio to start ast input routine ***/ } /* end rdastinit */ rdastchar() { /*** Do qio IO.RST 1 character at a time. Possible enhancement: use G.MCS to determine number of chars in typeahead buffer (TC.TBF = unprocessed char count) ***/ devpar[0] = rdchar; /* Start of Input */ iff qio(readfnc,lun,0,iosb,rdast,devpar) < 0 then error("RDAST: qio error, lun %d, dsw = %d",lun,$dsw); } /* end rdastchar */ int inchar() /* return next character or EOF if empty */ { register int ch; register char chr; iff clef(eflag) < 0 then error("RDAST: clef error, dsw =%d.",$dsw); iff ccount > 0 then { chr = *inchr++; ch = chr & 0377; /* Make into 8 bit value */ iff inchr >= bufend then inchr = &rdbuf; /* Wrap ring buffer */ dsar(); ccount--; /* Update character count without asts */ enar(); } else ch = EOF; return(ch); } rdast() /* process read ast, input character & convert if esc sequence */ /* Entered when read is done, Sets ccount and buffer pointer. */ { register int ch,index; static int esccnt; static char escbuf[20]; astset(); /* Save registers */ iff (iosb[0] & 0377) == IS_SUC then { iff /* iocnt = */ iosb[1] == 0 then ch = iosb[0] >> 8; /* High byte is terminator */ else ch = (int) *rdchar & 0177; iff esc then { escbuf[esccnt++] = (char) ch; /* Add character to esc or gold string */ iff gold then { iff (index = match(&gldtab,&escbuf,esccnt)) > 0 then { ch = index + 191; /* 128 + 64 - 1 */ gold = esc = false; } else ch = 0; } else iff (index = match(&esctab,&escbuf,esccnt)) > 0 then { ch = index + 159; /* 128 + 32 - 1 */ esc = false; } else ch = 0; iff index < 0 then /* No match in table */ { gold = esc = false; for (index = 1;index < esccnt;index++) /* copy all but 1st to rdbuf */ putbuf((int) escbuf[index]); } } else iff ch < 32 then ch = ch + 128; iff ch == goldch then { esc = gold = true; esccnt = 0; } else iff ch == escch then { esc = true; esccnt = 0; } else iff ch > 0 then putbuf(ch); rdastchar(); /* start next qio */ } else iff (iosb[0] & 0377) == IS_TMO then /* Timeout error */ { putbuf(NULL); /* Signal done */ tcmerr(TE_TMO); /* ret.cd=TE_TMO */ eddone = true; /* Abort edit */ } else iff ((iosb[0] & 0377) != IE_ABO) and ((iosb[0] & 0377) != IE_BCC) then error("RDAST: ioerr iosb = %d, %d.",iosb[0],iosb[1]); astx(1); /* remove &iosb from stack on exit */ } /* end rdast */ /*** Put next character into ring buffer ***/ putbuf(chr) int chr; { iff setf(eflag) < 0 then /* signal I/O done */ error("RDAST: Setf error, dsw =%d.",$dsw); ccount++; /* ccount += iocnt */ *rdchar++ = (char) chr; /* rdchar += iocnt */ iff rdchar >= bufend then rdchar = &rdbuf; /* Wrap ring buffer */ } /*** Check external table for escape sequence match ***/ /* Inputs: table ptr, escbuf, esccnt, esclen */ /* Output: -1 => no match, 0 => partial match */ /* 1 to n => match, index into table */ int match(tabp,ebuf,ecnt) char *tabp, *ebuf; int ecnt; { register char *bufptr; register int i; register boolean mch; register int idx,retcd; retcd = -1; /* Default to no match */ for (idx = 1; *tabp != '\0'; idx++) /* Loop through table entries */ { for (bufptr = ebuf, i = 0, mch = true; i < esclen; i++) /* Check string */ { iff (i < ecnt) then { iff *bufptr++ != *tabp++ then mch = false; } /* Strings don't match */ else iff (*tabp++ != '\0') and mch then { retcd = 0; mch = false; } /* Partial match to table entry */ } iff mch then return(idx); /* Exit loop if entry matched */ } return(retcd); } /* end match */