DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T g

⟦1a4f3e7de⟧ TextFile

    Length: 6283 (0x188b)
    Types: TextFile
    Names: »getch.c«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/wm/getch.c« 

TextFile

/*
 *************
 * 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 = &it;

	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