|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 6283 (0x188b)
Types: TextFile
Names: »getch.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/wm/getch.c«
/*
*************
* DISTRIBUTION NOTICE July 30 1985
* A Revised Edition of WM, by Matt Lennon and Tom Truscott,
* Research Triangle Institute, (919) 541-7005.
* Based on the original by Robert Jacob (decvax!nrl-css!jacob),
* Naval Research Laboratory, (202) 767-3365.
* No claims or warranties of any sort are made for this distribution.
* General permission is granted to copy, but not for profit,
* any of this distribution, provided that this notice
* is always included in the copies.
*************
*/
#include "wm.h"
#include <signal.h>
char keycap[200]; /* termcap entries for keypad functions */
int tty_backcnt; /* number of pre-read terminal chars */
char tty_backbuf[10]; /* stack of pre-read chars */
char tty_text[10]; /* actual text corresponding to tty_getch code */
int tty_textlen; /* strlen(tty_text) */
/*
* Returns true iff a call to tty_realgetch would not block.
*/
tty_inputpending()
{
long n;
if (tty_backcnt > 0)
return(TRUE);
if (ioctl(0, (int)FIONREAD, (char *)&n) == 0 && n > 0)
return(TRUE);
return(FALSE);
}
/*
* Read the next character from the terminal (or the backbuf),
* return EOF if end of file, else (int)the_char, sans parity
*/
int
tty_realgetch()
{
char c;
if (tty_backcnt > 0)
c = tty_backbuf[--tty_backcnt];
else if (read(0, &c, 1) <= 0) {
tty_text[0] = '\0';
tty_textlen = 0;
return(EOF);
}
c = toascii(c);
tty_text[0] = c;
tty_text[1] = '\0';
tty_textlen = 1;
return(c);
}
#ifdef GAGMEKEYPAD
init_keypad()
{
register int i;
register char *p;
char buf1[10];
if (p = getcap("ks"))
putp(p);
for (i=1,p = "kbkukdklkrkhk0k1k2k3k4k5k6k7k8k9"; *p; i++,p+= 2) {
(void) sprintf(buf1, "%2.2s", p);
add_to_try(buf1, i+0400);
}
}
/*
** add_to_try() (Copyright Pavel Curtis, see notice in hacks.c)
**
** Construct the try for the current terminal's keypad keys.
**
*/
struct try
{
struct try *child; /* ptr to child. NULL if none */
struct try *sibling; /* ptr to sibling. NULL if none */
char ch; /* character at this node */
short value; /* code of string so far. NULL if none */
};
static struct try *newtry;
add_to_try(capname, code)
char *capname;
int code;
{
register struct try *ptr, *savedptr;
register char *str, *s;
static bool out_of_memory = FALSE;
str = getcap(capname);
if (! str || out_of_memory)
return;
strcat(keycap, capname); strcat(keycap, "=");
for (s = str; *s; s++) {
strcat(keycap, mkprint(*s));
}
strcat(keycap, ":");
if (newtry != NULL)
{
ptr = newtry;
for (;;)
{
while (ptr->ch != *str && ptr->sibling != NULL)
ptr = ptr->sibling;
if (ptr->ch == *str)
{
if (*(++str))
{
if (ptr->child != NULL)
ptr = ptr->child;
else
break;
}
else
{
ptr->value = code;
return;
}
}
else
{
if ((ptr->sibling = alloc(1, struct try)) == NULL)
{
out_of_memory = TRUE;
return;
}
savedptr = ptr = ptr->sibling;
ptr->child = ptr->sibling = NULL;
ptr->ch = *str++;
ptr->value = NULL;
break;
}
} /* end for (;;) */
}
else /* newtry == NULL :: First sequence to be added */
{
savedptr = ptr = newtry = alloc(1, struct try);
if (ptr == NULL)
{
out_of_memory = TRUE;
return;
}
ptr->child = ptr->sibling = NULL;
ptr->ch = *(str++);
ptr->value = NULL;
}
/* at this point, we are adding to the try. ptr->child == NULL */
while (*str)
{
ptr->child = alloc(1, struct try);
ptr = ptr->child;
if (ptr == NULL)
{
out_of_memory = TRUE;
ptr = savedptr;
while (ptr != NULL)
{
savedptr = ptr->child;
free((char *)ptr);
ptr = savedptr;
}
return;
}
ptr->child = ptr->sibling = NULL;
ptr->ch = *(str++);
ptr->value = NULL;
}
ptr->value = code;
return;
}
#include <setjmp.h>
static jmp_buf jmpbuf;
/*
** tty_getch() (Copyright Pavel Curtis, see notice in hacks.c)
**
** Get an input character, but take care of keypad sequences, returning
** an appropriate code when one matches the input. After each character
** is received, set an alarm call. If no more of the sequence
** is received by the time the alarm goes off, pass through the sequence
** gotten so far.
**
*/
tty_getch()
{
/* longjmp alert! beware of register variables */
register struct try *ptr;
int ch;
char buffer[10]; /* Assume no sequences longer than 10 */
char *bufp = buffer;
int (*oldsigalrm)();
int sigalrm();
bool alarmset;
ptr = newtry;
alarmset = FALSE;
oldsigalrm = SIG_DFL; /* to quiet lint */
do
{
if (setjmp(jmpbuf))
break;
ch = tty_realgetch();
if (ch != EOF) /* returns EOF on error, too */
*(bufp++) = ch;
while (ptr != NULL && ptr->ch != ch)
ptr = ptr->sibling;
if (ptr != NULL)
{
if (ptr->value != NULL)
{
if (alarmset) {
(void) ualarm(0L);
(void) signal(SIGALRM, oldsigalrm);
}
tty_textlen = bufp-buffer;
bcopy(buffer, tty_text, tty_textlen);
return(ptr->value);
}
else
{
ptr = ptr->child;
if (!alarmset) {
alarmset = TRUE;
oldsigalrm = signal(SIGALRM, sigalrm);
}
(void) ualarm(200000L);
}
}
} while (ptr != NULL);
if (alarmset) {
(void) ualarm(0L);
(void) signal(SIGALRM, oldsigalrm);
}
if (bufp <= buffer)
return(EOF);
while (--bufp > buffer)
tty_backbuf[tty_backcnt++] = *bufp;
return(*bufp);
}
static
sigalrm()
{
longjmp(jmpbuf, 1);
}
/*
* ualarm(usec). If this doesn't compile, just use alarm(0) and alarm(1).
*/
#include <sys/time.h>
#define MILLION 1000000L
ualarm(usecs)
long usecs;
{
struct itimerval it, oitv;
register struct itimerval *itp = ⁢
timerclear(&itp->it_interval);
itp->it_value.tv_sec = usecs/MILLION;
itp->it_value.tv_usec = usecs%MILLION;
if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
return (-1);
return (oitv.it_value.tv_sec*MILLION+oitv.it_value.tv_usec);
}
#endif