[comp.unix.questions] a question about using curses lib

xwu@pollux.usc.edu (Xinhua Wu) (02/20/88)

I'm writing a program using curses lib.  I want to use function keys (eg,
use arrow keys to choose from a menu).  The program should work for different
terminal types (vt100, xterm, ibmaed, h19, etc).

My general question is: how can I make the program recognize a function key
immediately after the user hits it?

I'm now using wgetch(win) to read the input (wgetstr(win, str) needs a newline
or EOF).  The problem is that in this case the program needs to know in advance
the code for a function key and how long the code is.  Since the code and the
length vary for different terminal types (eg, the code for uparrow is \033A
for ibmaed, \033[A for xterm and vt100 under X), the program may not work
for new terminal types.

Thanks in advance for any help.


Xinhua Wu
xwu@cse.usc.edu

turtle@sdsu.UUCP (Andrew Scherpbier) (02/21/88)

In article <7078@oberon.USC.EDU> xwu@pollux.usc.edu (Xinhua Wu) writes:
>I'm writing a program using curses lib.  I want to use function keys (eg,
>use arrow keys to choose from a menu).  The program should work for different
>terminal types (vt100, xterm, ibmaed, h19, etc).
>
>My general question is: how can I make the program recognize a function key
>immediately after the user hits it?
	[The rest deleted]

(I do not know if the following holds true for BSD 4.*, I only have access
to Xenix V.2 and SysV.3)
Yes, there is a function called `keypad()'.  The call should look someting
like this:
	keypad(stdscr,TRUE);	/* the 'TRUE' is to enable keypad mode */
After this call, wgetch() will return special characters as described in
curses.h (ie KEY_LEFT for the left arrow key)
Be aware (I have made this mistake MANY times..) that with keypad mode enabled,
wgetch will return a character of type `chtype'.  This is normally a `short'.
Without the keypad mode, wgetch can be assumed to return only charaters of
type `char'.
Another thing to look at is the `notimeout()' call.  Normally, in keypad mode,
wgetch will set a timer.  The purpose of the timer is to differentiate between
sequences received from a function key and those typed by a user' [from ATT Unix
System V Programmer's Reference Manual, page 437]
The call to `notimeout()' looks like this:
	notimeout(stdscr,TRUE);	/* this will turn OFF the delay timer feature */

Happy hacking,

-Andrew

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~T~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"I sometimes get the feeling that   |  Andrew Scherpbier
 things cannot possibly get worse...|  Computer Science Department
 and sure enough, they do."         |  San Diego State University
	-Don Perkins Jr.            |  ihnp4!jack!sdsu!turtle

cjc@ulysses.homer.nj.att.com (Chris Calabrese[rs]) (02/23/88)

In article <2931@sdsu.UUCP>, turtle@sdsu.UUCP (Andrew Scherpbier) writes:
> In article <7078@oberon.USC.EDU> xwu@pollux.usc.edu (Xinhua Wu) writes:
> >I'm writing a program using curses lib.  I want to use function keys (eg,
> >use arrow keys to choose from a menu).  The program should work for different
> 
> (I do not know if the following holds true for BSD 4.*, I only have access
> to Xenix V.2 and SysV.3)
> Yes, there is a function called `keypad()'.  The call should look someting
> like this:
> 	keypad(stdscr,TRUE);	/* the 'TRUE' is to enable keypad mode */


Keypad is a feature of the Terminfo terminal independant
input and output database.  Essentially the system keeps
keyboard maps around so that various terminals will all
map to one standard.

Unfortunately, BSD unix does not have Terminfo, it has termcap
instead, so it doesn't have keypad().  The way to get
arround this is to assume that the arrow keys (and home keys, etc)
return the same escape sequences as the corresponding screen
functions.  In other words, the up arrow probably returns the
sequence which moves the cursor up, etc.  These output
codes are kept in the termcap database, and the termcap
library can be used to bring them out and test for them.

Of course, the above idea will not produce portable code, so
you should include things like:

#if _TermCap
...
#else
#if _TermInfo
...
#endif
#endif

In the dependant code.


	Christopher Calabrese
	AT&T Bell Laboratories
	ulysses!cjc

hst@mhres.mh.nl (Klaas Hemstra) (02/23/88)

You have to use cbreak() or raw(). Only then every character is
available to the program immediately after it is typed.

Function keys should be defined in the terminfo (or termcap on BSD) library.
If your terminfo file is ok (most likely it is not!) then the curses package
will decode the escape sequences for you if you use the keypad(stdscr,1) call.
In the program you use e.g.  :   if (getch() = KEY_F(1)   to test for a 
function key (check the curses manual for all keys).

Using function keys together with the numeric keypad is not that simple.
If you want that you should not specify the rmkx & smkx entries in the terminfo
file.

Hope this will help,

-- 
Klaas Hemstra  (hst@mh.nl)                   |    /  / ,~~~  ~~/~~
uucp: ..{uunet!}mcvax!mh.nl!jv               |   /--/  `-,    /  ___  |_/ |__|
Multihouse N.V., Gouda, the Netherlands      |  /  / ___/    /   ---  | \ |  | 

rbj@icst-cmr.arpa (Root Boy Jim) (02/27/88)

   From: Xinhua Wu <xwu@pollux.usc.EDU>

   I'm writing a program using curses lib.  I want to use function
   keys (eg, use arrow keys to choose from a menu).  The program
   should work for different terminal types (vt100, xterm, ibmaed,
   h19, etc).

   My general question is: how can I make the program recognize a function key
   immediately after the user hits it?

Several people have mentioned that you need to use CBREAK mode, or
whatever TPC calls their version of it. I will assume you use BSD.

   I'm now using wgetch(win) to read the input (wgetstr(win, str)
   needs a newline or EOF).  The problem is that in this case the
   program needs to know in advance the code for a function key and
   how long the code is.  Since the code and the length vary for
   different terminal types (eg, the code for uparrow is \033A for
   ibmaed, \033[A for xterm and vt100 under X), the program may not
   work for new terminal types.

Curses is a great package for output, but I have heard it is somewhat
broken for input. Even if not, I don't see it handling input very well
anyway. It doesn't seem to recognize function keys either, so you'll
have to pick them out of the term{cap,info} entry anyway.

Which brings me to another point. Why bother using function keys?
Not all terminals have the same ones; some have none, altho arrow
keys do seem to be the first to appear. Try using control characters
instead. If you do decide to use function keys, the length should be
no problem. There will only be one set of `keymaps' active at a time,
the one for the current terminal type, so there should be no confusion.

   Thanks in advance for any help.

   Xinhua Wu   xwu@cse.usc.edu

	(Root Boy) Jim Cottrell	<rbj@icst-cmr.arpa>
	National Bureau of Standards
	Flamer's Hotline: (301) 975-5688
	Eisenhower!!  Your mimeograph machine upsets my stomach!!

xwu@pollux.usc.edu (Xinhua Wu) (02/27/88)

In article <7078@oberon.USC.EDU> xwu@pollux.usc.edu (Xinhua Wu) writes:
>I'm writing a program using curses lib.  I want to use function keys (eg,
>...

Thanks a lot to those who responded to my original posting.  I'm sorry that
I failed to state clearly what the problem really is.

I'm using 4.3 (on IBM RT).  I want to use 4 arrow keys and an escape key
(f12 right now) while I'm in a window.  Now I have something like this:

	...
	crmode();
	...
	switch (inbuf[0] = wgetch(win)) {
	  case '\033': 	/* Esc	*/
	    read the rest into inbuf[], again using wgetch();
	    if (strcmp(inbuf, leftarrow) == 0)
	    then ...
	    else if (strcmp(inbuf, rightarrow) == 0)
	    ...

	  case '': ...;

	  ...

	  default: ...;
	}


1. Right now I have a function to set the variable leftarrow (and the length 
of it, to control how many times wgetch() is called - the code for <leftarrow>
is \033A for ibmaed, \033[A for xterm and vt100 under X) etc for known terminal
types.  Can someone show me an example of using termcap database?  How does
getcap(name) work?  tgetstr()?  Is KL (or kl) etc set by setterm()?

2. I'd like to use <Esc> instead of <f12> as the escape key.  How can I
distinguish <Esc> with leftarrow (for example) whose code also begins with an
escape?  Timed input?  How do I know I'm reading just an escape?


Again, thanks in advance for any help.

Xinhua Wu
xwu@cse.usc.edu

brad@bradley.UUCP (02/29/88)

I too need a way to use funciton keys on BSD machines and have the
code I right work also on system V machines.....here are some routines
I wrote....they seem to work on BSD....haven't tested on system V,
but will shortly. I suppose I could you keypad as well, but then
more code rewriting would be needed.

Also this version need more work....but you can build on it.


Bradley Smith			UUCP: {cepu,ihnp4,noao,uiucdcs}!bradley!brad
Text Processing			ARPA: cepu!bradley!brad@seas.ucla.edu
Bradley University		PH: (309) 677-2337
Peoria, IL 61625

You never get a second chance to make a first impression.
================cut here==============
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by bradley!brad on Mon Feb 29 09:10:26 CST 1988
# Contents:  curses.c curses.h
 
echo x - curses.c
sed 's/^@//' > "curses.c" <<'@//E*O*F curses.c//'
#include	<curses.h>
#include	<ctype.h>
#include	<signal.h>
#include	<setjmp.h>
#include	"curses.h"	/* this is my include */

/* this file sets up terminal */

extern char *malloc();

char *function_keys[8]; /* where we store what each function key is */
char *other_keys[5];	/* KEYUP, KEYDOWN, KEYRIGHT, KEYLEFT, KEYHOME */

/* used to see if more chars come in */
int cur_alrm();
jmp_buf cur_buf;
/*  */


/* get function returns the number of function keys it found */
/* returns -1 if it has a major error */
get_function_key()
{
	int err, i;
	extern char *tgetstr(), *getenv();
	char *cp, bbp[1024], bp[1024], key[16];

	tgetent(bbp,getenv("TERM"));
	err = 0;
	for(i=0;i<8;i++) {
		sprintf(key,"k%d", i);
		cp = tgetstr(key,bp);
		if(cp) {
			err++;
			function_keys[i] = malloc(strlen(cp) +1);
			if(function_keys[i] == (char *) NULL) {
				perror("malloc on function_keys");
				return(-1);
			}
			strcpy(function_keys[i], cp);
		}
	}
	/* now we get arrow keys & home */
	cp = tgetstr("ku", bp);
	if(cp ) {
		other_keys[0] = malloc(strlen(cp)+1);
		if(other_keys[0] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[0], cp);
	}
	cp = tgetstr("kd", bp);
	if(cp ) {
		other_keys[1] = malloc(strlen(cp)+1);
		if(other_keys[1] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[1], cp);
	}
	cp = tgetstr("kr", bp);
	if(cp ) {
		other_keys[2] = malloc(strlen(cp)+1);
		if(other_keys[2] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[2], cp);
	}
	cp = tgetstr("kl", bp);
	if(cp ) {
		other_keys[3] = malloc(strlen(cp)+1);
		if(other_keys[3] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[3], cp);
	}
	cp = tgetstr("kh", bp);
	if(cp ) {
		other_keys[4] = malloc(strlen(cp)+1);
		if(other_keys[4] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[4], cp);
	}
	return(err);
}

/*	mgets		version 1.0
 *
 * mgets is similiar to gets execpt that it is always checking
 * if function keys are entered as well as ESC's and returns
 *
 * returns are as follows
	MAXRT	12	 maxiumn number of chars typed in 
	RTNO	13	 Return with no chars 
	RT	14	 return with chars
	TAB	16	 tab no chars
	TABCH	17	 tab with chars
	DELCH	18	 del with chars
	DEL	19
 */

/*
 * Mon Sep 23 19:08:21 CDT 1985
 * modified such that a ^L will redraw the screen
 */
mgets(maxcnt,str,doecho)
int maxcnt, doecho;
char *str;
{
	char m_buffer[256];
	int m_count = 0;
	char *cp,c;
	register int i, j;
	WINDOW *mwin;
			/* i = character count, */
	cp = str;
	*cp = 0;
	for(i=0;i<maxcnt;) {
		c = getch();
		/* addition for ^L */
		if(c == '\f') {
			mwin = newwin(0,0,0,0);
			wclear(mwin);
			wrefresh(mwin);
			delwin(mwin);
			touchwin(stdscr);
			refresh();
			continue;
		}
		if(iscntrl(c)) {
			switch(c) {
			case '\010':
				if(cp > str) {
					cp--;
					if(iscntrl(*cp)) {
					    i--;
					    printw("\010 \010");
					}
					printw("\010 \010");
					refresh();
					i--;
				}
				break;
			case '\n':
			case '\r':
				*cp = '\0';
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				if(cp > str)
					return(RT);
				return(RTNO);
			case '\t':
				*cp = '\0';
				if(cp > str)
					return(TABCH);
				return(TAB);
			case '\177':
				*cp = '\0';
				if(cp > str)
					return(DELCH);
				return(DEL);
			default:
				*cp++ = c;
				if(doecho) {
					addch('^');
					addch(c | 0100);
					refresh();
				}
				i++;
				*cp = 0;
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				break;
			}
		}
		else {
			switch(c) {
			case '\r':
				*cp++ = c;
				*cp = '\0';
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				cp--;
				*cp = 0;
				if(cp > str)
					return(RT);
				return(RTNO);
				break;
			case '\n':
				*cp++ = c;
				*cp = '\0';
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				cp--;
				*cp = 0;
				if(cp > str)
					return(RT);
				return(RTNO);
				break;
			case '\t':
				*cp = '\0';
				if(cp > str)
					return(TABCH);
				return(TAB);
			default:
				*cp++ = c;
				if(doecho) {
					if(c < ' ') {
						addch('^');
						addch(c | 0100);
					} else
						addch(c);
					refresh();
				}
				i++;
				*cp = 0;
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				break;
			}
			refresh();
		}
		*cp = '\0';
	}
	*cp = '\0';
	/* once here I want to make sure that we don't have a
	 * function key typed.  What we do is do a timed input.
	 * I keep taking chars until nothing is gotten with
	 * 1 sec.  We are going to use the SIGALRM
	 */
	if(func_compare(str)) 
		return(MAXRT);	/* looks like it is not a funt key */
	signal(SIGALRM, cur_alrm);
	strcpy(m_buffer, str);
	m_count = cp - str;
	for(;;) {
		if(setjmp(cur_buf)) {	/* 1 sec has pasted */
			return(MAXRT);
		}
		alarm(1);
		c = getch();	/* wait for char */
		alarm(0);
		if(doecho) {
			if(c < ' ') {
				addch('^');
			addch(c | 0100);
			} else
				addch(c);
			refresh();
		}
		m_buffer[m_count++] = c;
		m_buffer[m_count] = 0;
		j = compare_func(m_buffer,doecho);
		if(j != -1)
			return(j);
	}
	return(MAXRT);
}
/* compare_func - returns -1 if not a function key
 *		  returns 0-7 for function key 1-8
 */
compare_func(str,doecho)
char *str;
int doecho;
{
	int i;
	char *cp;

	for(i=0;i<8;i++) {
		if(tindex(str,function_keys[i]) != -1) {
			/* erase chars on screen */
			if(doecho) {
				for(cp = str; *cp;cp++) {
					if(iscntrl(*cp)) {
					    printw("\010 \010");
					}
					printw("\010 \010");
				}
				refresh();
			}
			return(i);
		}
	}
	/* check arrow and home keys */
	for(i=0;i<5;i++) {
		if(tindex(str,other_keys[i])!= -1) {
			if(doecho) {
				/* erase chars on screen */
				for(cp = str; *cp ;cp++) {
					if(iscntrl(*cp)) {
					    printw("\010 \010");
					}
					printw("\010 \010");
				}
				refresh();
			}
			return(i+KEYBASE);
		}
	}
	return(-1);	/* not it ? */
}
/* func_compare - returns -1 if not a function key (ie close to it)
 *		  returns 0   if it looks like it might be a fun key
 */
func_compare(str)
char *str;
{
	int i;
	char *cp;

	for(i=0;i<8;i++) {
		if(tindex(function_keys[i],str) != -1) {
			return(0);
		}
	}
	/* check arrow and home keys */
	for(i=0;i<5;i++) {
		if(tindex(other_keys[i],str)!= -1) {
			return(0);
		}
	}
	return(-1);	/* not it ? */
}
cur_alrm()
{
	longjmp(cur_buf,1);
}
@//E*O*F curses.c//
chmod u=rw,g=rw,o= curses.c
 
echo x - curses.h
sed 's/^@//' > "curses.h" <<'@//E*O*F curses.h//'
/*
 * defines for mgets.c
 */

#define	MAXRT	12	/* maxiumn number of chars typed in */
#define RTNO	13	/* Return with no chars */
#define	RT	14	/* return with chars */
#define TAB	15
#define	TABCH	16
#define	DELCH	17	/* del with chars */
#define	DEL	18

/* */
#define	FUN1	0	/* function key 1 */
#define	FUN2	1	/* function key 2 */
#define	FUN3	2	/* function key 3 */
#define	FUN4	3	/* function key 4 */
#define	FUN5	4	/* function key 5 */
#define	FUN6	5	/* function key 6 */
#define	FUN7	6	/* function key 7 */
#define	FUN8	7	/* function key 8 */
/* */
#define KEYBASE		20 /* BASE for BELOW */
#define	KEYEND		(KEYBASE+4) /* highest number for KEYS */
#define KEYUP		(0+KEYBASE)
#define KEYDOWN		(1+KEYBASE)
#define KEYRIGHT	(2+KEYBASE)
#define KEYLEFT		(3+KEYBASE)
#define KEYHOME		(4+KEYBASE)
@//E*O*F curses.h//
chmod u=rw,g=rw,o= curses.h
 
exit 0

brad@bradley.UUCP (02/29/88)

Forgot one other routine

=======
tindex(s,t)
char s[], t[];
{
	register int j,k,i;
	for(i=0;s[i] != '\0'; i++) {
		for(j=i,k=0;t[k] != '\0' && s[j]== t[k]; j++, k++)
			;
		if(t[k] == '\0')
			return(i);
	}
	return(-1);
}

brad@bradley.UUCP (03/01/88)

well the first file worked on my venix/86 machine...but my vax
died....so I fixed it...here it is

======curses.c======
#include	<curses.h>
#include	<ctype.h>
#include	<signal.h>
#include	<setjmp.h>
#include	"curses.h"	/* this is my include */

/* this file sets up terminal */

extern char *malloc();

char *function_keys[8]; /* where we store what each function key is */
char *other_keys[5];	/* KEYUP, KEYDOWN, KEYRIGHT, KEYLEFT, KEYHOME */

/* used to see if more chars come in */
int cur_alrm();
jmp_buf cur_buf;
/*  */


/* get function returns the number of function keys it found */
/* returns -1 if it has a major error */
get_function_key()
{
	int err, i;
	extern char *tgetstr(), *getenv();
	char *cp, bbp[1024], *sp, bp[1024], key[16];

	err = tgetent(bbp,getenv("TERM"));
	if(err != 1) {
		/* not all is well */
		fprintf(stderr,"tgetent returned %d\n", err);
		return(-1);
	}
	err = 0;
	for(i=0;i<8;i++) {
		sprintf(key,"k%d", i);
		sp = bp;
		cp = tgetstr(key,&sp);
		if(cp) {
			err++;
			function_keys[i] = malloc(strlen(cp) +1);
			if(function_keys[i] == (char *) NULL) {
				perror("malloc on function_keys");
				return(-1);
			}
			strcpy(function_keys[i], cp);
		}
	}
	/* now we get arrow keys & home */
	sp = bp;
	cp = tgetstr("ku", &bp);
	if(cp ) {
		other_keys[0] = malloc(strlen(cp)+1);
		if(other_keys[0] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[0], cp);
	}
	sp = bp;
	cp = tgetstr("kd", &sp);
	if(cp ) {
		other_keys[1] = malloc(strlen(cp)+1);
		if(other_keys[1] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[1], cp);
	}
	sp = bp;
	cp = tgetstr("kr", &sp);
	if(cp ) {
		other_keys[2] = malloc(strlen(cp)+1);
		if(other_keys[2] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[2], cp);
	}
	sp = bp;
	cp = tgetstr("kl", &sp);
	if(cp ) {
		other_keys[3] = malloc(strlen(cp)+1);
		if(other_keys[3] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[3], cp);
	}
	sp = bp;
	cp = tgetstr("kh", &sp);
	if(cp ) {
		other_keys[4] = malloc(strlen(cp)+1);
		if(other_keys[4] == (char *) NULL ) {
			perror("malloc on other_keys");
			return(-1);
		}
		strcpy(other_keys[4], cp);
	}
	return(err);
}

/*	mgets		version 1.0
 *
 * mgets is similiar to gets execpt that it is always checking
 * if function keys are entered as well as ESC's and returns
 *
 * returns are as follows
	MAXRT	12	 maxiumn number of chars typed in 
	RTNO	13	 Return with no chars 
	RT	14	 return with chars
	TAB	16	 tab no chars
	TABCH	17	 tab with chars
	DELCH	18	 del with chars
	DEL	19
 */

/*
 * Mon Sep 23 19:08:21 CDT 1985
 * modified such that a ^L will redraw the screen
 */
mgets(maxcnt,str,doecho)
int maxcnt, doecho;
char *str;
{
	char m_buffer[256];
	int m_count = 0;
	char *cp,c;
	register int i, j;
	WINDOW *mwin;
			/* i = character count, */
	cp = str;
	*cp = 0;
	for(i=0;i<maxcnt;) {
		c = getch();
		/* addition for ^L */
		if(c == '\f') {
			mwin = newwin(0,0,0,0);
			wclear(mwin);
			wrefresh(mwin);
			delwin(mwin);
			touchwin(stdscr);
			refresh();
			continue;
		}
		if(iscntrl(c)) {
			switch(c) {
			case '\010':
				if(cp > str) {
					cp--;
					if(iscntrl(*cp)) {
					    i--;
					    printw("\010 \010");
					}
					printw("\010 \010");
					refresh();
					i--;
				}
				break;
			case '\n':
			case '\r':
				*cp = '\0';
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				if(cp > str)
					return(RT);
				return(RTNO);
			case '\t':
				*cp = '\0';
				if(cp > str)
					return(TABCH);
				return(TAB);
			case '\177':
				*cp = '\0';
				if(cp > str)
					return(DELCH);
				return(DEL);
			default:
				*cp++ = c;
				if(doecho) {
					addch('^');
					addch(c | 0100);
					refresh();
				}
				i++;
				*cp = 0;
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				break;
			}
		}
		else {
			switch(c) {
			case '\r':
				*cp++ = c;
				*cp = '\0';
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				cp--;
				*cp = 0;
				if(cp > str)
					return(RT);
				return(RTNO);
				break;
			case '\n':
				*cp++ = c;
				*cp = '\0';
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				cp--;
				*cp = 0;
				if(cp > str)
					return(RT);
				return(RTNO);
				break;
			case '\t':
				*cp = '\0';
				if(cp > str)
					return(TABCH);
				return(TAB);
			default:
				*cp++ = c;
				if(doecho) {
					if(c < ' ') {
						addch('^');
						addch(c | 0100);
					} else
						addch(c);
					refresh();
				}
				i++;
				*cp = 0;
				j = compare_func(str,doecho);
				if(j != -1)
					return(j);
				break;
			}
			refresh();
		}
		*cp = '\0';
	}
	*cp = '\0';
	/* once here I want to make sure that we don't have a
	 * function key typed.  What we do is do a timed input.
	 * I keep taking chars until nothing is gotten with
	 * 1 sec.  We are going to use the SIGALRM
	 */
	if(func_compare(str)) 
		return(MAXRT);	/* looks like it is not a funt key */
	signal(SIGALRM, cur_alrm);
	strcpy(m_buffer, str);
	m_count = cp - str;
	for(;;) {
		if(setjmp(cur_buf)) {	/* 1 sec has pasted */
			return(MAXRT);
		}
		alarm(1);
		c = getch();	/* wait for char */
		alarm(0);
		if(doecho) {
			if(c < ' ') {
				addch('^');
			addch(c | 0100);
			} else
				addch(c);
			refresh();
		}
		m_buffer[m_count++] = c;
		m_buffer[m_count] = 0;
		j = compare_func(m_buffer,doecho);
		if(j != -1)
			return(j);
	}
	return(MAXRT);
}
/* compare_func - returns -1 if not a function key
 *		  returns 0-7 for function key 1-8
 */
compare_func(str,doecho)
char *str;
int doecho;
{
	int i;
	char *cp;

	for(i=0;i<8;i++) {
		if(tindex(str,function_keys[i]) != -1) {
			/* erase chars on screen */
			if(doecho) {
				for(cp = str; *cp;cp++) {
					if(iscntrl(*cp)) {
					    printw("\010 \010");
					}
					printw("\010 \010");
				}
				refresh();
			}
			return(i);
		}
	}
	/* check arrow and home keys */
	for(i=0;i<5;i++) {
		if(tindex(str,other_keys[i])!= -1) {
			if(doecho) {
				/* erase chars on screen */
				for(cp = str; *cp ;cp++) {
					if(iscntrl(*cp)) {
					    printw("\010 \010");
					}
					printw("\010 \010");
				}
				refresh();
			}
			return(i+KEYBASE);
		}
	}
	return(-1);	/* not it ? */
}
/* func_compare - returns -1 if not a function key (ie close to it)
 *		  returns 0   if it looks like it might be a fun key
 */
func_compare(str)
char *str;
{
	int i;
	char *cp;

	for(i=0;i<8;i++) {
		if(tindex(function_keys[i],str) != -1) {
			return(0);
		}
	}
	/* check arrow and home keys */
	for(i=0;i<5;i++) {
		if(tindex(other_keys[i],str)!= -1) {
			return(0);
		}
	}
	return(-1);	/* not it ? */
}
cur_alrm()
{
	longjmp(cur_buf,1);
}