home *** CD-ROM | disk | FTP | other *** search
- /*
- *************
- * 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
-