|
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