Subject: lib/3969: Updates to libcurses in a more friendly format (supercedes 3962 & 3966)
To: None <gnats-bugs@gnats.netbsd.org>
From: Brett Lymn (Master of the Siren) <blymn@baea.com.au>
List: netbsd-bugs
Date: 08/12/1997 11:17:21
>Number:         3969
>Category:       lib
>Synopsis:       Correct problems with 3962 submission
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 11 18:50:02 1997
>Last-Modified:
>Originator:     Brett Lymn (Master of the Siren)
>Organization:
Brett Lymn
>Release:        2nd August 1997
>Environment:
	
System: NetBSD siren 1.2G NetBSD 1.2G (SIREN) #0: Sat Aug 9 17:10:14 CST 1997 toor@siren:/usr/src/sys/arch/i386/compile/SIREN i386


>Description:
	My original send-pr (3962) was a compressed uuencoded tar file
which is not reviewer friendly.  Below is the patch file uncompressed, this
patch also folds in send-pr 3966 which corrects an endian bug in the original
submission.
>How-To-Repeat:
	n/a
>Fix:

Index: src/lib/libcurses/Makefile
diff -c src/lib/libcurses/Makefile:1.1.1.2 src/lib/libcurses/Makefile:1.5
*** src/lib/libcurses/Makefile:1.1.1.2	Tue Aug  5 19:33:59 1997
--- src/lib/libcurses/Makefile	Sun Aug 10 17:58:21 1997
***************
*** 8,16 ****
  SRCS=	addbytes.c addch.c addnstr.c box.c clear.c clrtobot.c clrtoeol.c \
  	cr_put.c ctrace.c cur_hash.c curses.c delch.c deleteln.c delwin.c \
  	erase.c fullname.c getch.c getstr.c id_subwins.c idlok.c initscr.c \
! 	insch.c insertln.c longname.c move.c mvwin.c newwin.c overlay.c \
! 	overwrite.c printw.c putchar.c refresh.c scanw.c scroll.c setterm.c \
! 	standout.c toucholap.c touchwin.c tscroll.c tstp.c tty.c unctrl.c
  MAN=	curses.3
  INCS=	curses.h unctrl.h
  INCSDIR=/usr/include
--- 8,17 ----
  SRCS=	addbytes.c addch.c addnstr.c box.c clear.c clrtobot.c clrtoeol.c \
  	cr_put.c ctrace.c cur_hash.c curses.c delch.c deleteln.c delwin.c \
  	erase.c fullname.c getch.c getstr.c id_subwins.c idlok.c initscr.c \
! 	insch.c insertln.c keypad.c longname.c move.c mvwin.c newwin.c \
! 	nodelay.c notimeout.c overlay.c overwrite.c printw.c putchar.c \
! 	refresh.c scanw.c scroll.c setterm.c standout.c toucholap.c \
!         touchwin.c tscroll.c tstp.c tty.c unctrl.c
  MAN=	curses.3
  INCS=	curses.h unctrl.h
  INCSDIR=/usr/include
Index: src/lib/libcurses/curses.3
diff -c src/lib/libcurses/curses.3:1.1.1.2 src/lib/libcurses/curses.3:1.2
*** src/lib/libcurses/curses.3:1.1.1.2	Tue Aug  5 19:34:11 1997
--- src/lib/libcurses/curses.3	Sun Aug 10 17:55:08 1997
***************
*** 87,93 ****
  .It delch()	delete a character
  .It deleteln()	delete a line
  .It delwin(win)	delete
! .Em stdscr
  .It echo()	set echo mode
  .It endwin()	end window modes
  .It erase()	erase
--- 87,93 ----
  .It delch()	delete a character
  .It deleteln()	delete a line
  .It delwin(win)	delete
! .Em win
  .It echo()	set echo mode
  .It endwin()	end window modes
  .It erase()	erase
***************
*** 106,111 ****
--- 106,113 ----
  .It initscr()	initialize screens
  .It insch(c)	insert a char
  .It insertln()	insert a line
+ .It keypad(win, boolf)	set keypad flag for
+ .Em win
  .It leaveok(win,boolf)	set leave flag for
  .Em stdscr
  .It longname(termbuf,name)	get long name from
***************
*** 116,124 ****
--- 118,130 ----
  .It newwin(lines,cols,begin_y,begin_x)\ 	create a new window
  .It nl()	set newline mapping
  .It nocbreak()	unset cbreak mode
+ .It nodelay(win, boolf)	unset blocking reads for
+ .Em win
  .It noecho()	unset echo mode
  .It nonl()	unset newline mapping
  .It noraw()	unset raw mode
+ .It notimeout(win, boolf)	unset infinite timeout on keypad assembly for
+ .Em win
  .It overlay(win1,win2)	overlay win1 on win2
  .It overwrite(win1,win2)	overwrite win1 on top of win2
  .It printw(fmt,arg1,arg2,...)	printf on
Index: src/lib/libcurses/curses.h
diff -c src/lib/libcurses/curses.h:1.1.1.2 src/lib/libcurses/curses.h:1.4
*** src/lib/libcurses/curses.h:1.1.1.2	Tue Aug  5 19:34:13 1997
--- src/lib/libcurses/curses.h	Tue Aug  5 20:16:49 1997
***************
*** 93,98 ****
--- 93,204 ----
  
  /* END BACKWARD COMPATIBILITY ONLY. */
  
+ /* symbols for values returned by getch in keypad mode */
+ #define    KEY_BREAK      0x101    /* break key */
+ #define    KEY_DOWN       0x102    /* down arrow */
+ #define    KEY_UP         0x103    /* up arrow */
+ #define    KEY_LEFT       0x104    /* left arrow */
+ #define    KEY_RIGHT      0x105    /* right arrow*/
+ #define    KEY_HOME       0x106    /* home key */
+ #define    KEY_BACKSPACE  0x107    /* Backspace */
+ 
+ /* First function key (block of 64 follow) */
+ #define    KEY_F0         0x108    
+ /* Function defining other function key values*/
+ #define    KEY_F(n)       (KEY_F0+(n))  
+ 
+ #define    KEY_DL         0x148    /* Delete Line */
+ #define    KEY_IL         0x149    /* Insert Line*/
+ #define    KEY_DC         0x14A    /* Delete Character */
+ #define    KEY_IC         0x14B    /* Insert Character */
+ #define    KEY_EIC        0x14C    /* Exit Insert Char mode */
+ #define    KEY_CLEAR      0x14D    /* Clear screen */
+ #define    KEY_EOS        0x14E    /* Clear to end of screen */
+ #define    KEY_EOL        0x14F    /* Clear to end of line */
+ #define    KEY_SF         0x150    /* Scroll one line forward */
+ #define    KEY_SR         0x151    /* Scroll one line back */
+ #define    KEY_NPAGE      0x152    /* Next Page */
+ #define    KEY_PPAGE      0x153    /* Prev Page */
+ #define    KEY_STAB       0x154    /* Set Tab */
+ #define    KEY_CTAB       0x155    /* Clear Tab */
+ #define    KEY_CATAB      0x156    /* Clear All Tabs */
+ #define    KEY_ENTER      0x157    /* Enter or Send */
+ #define    KEY_SRESET     0x158    /* Soft Reset */
+ #define    KEY_RESET      0x159    /* Hard Reset */
+ #define    KEY_PRINT      0x15A    /* Print */
+ #define    KEY_LL         0x15B    /* Home Down */
+ 
+ /*
+  * "Keypad" keys arranged like this:
+  *
+  *  A1   up  A3
+  * left  B2 right
+  *  C1  down C3
+  *
+  */
+ #define    KEY_A1         0x15C    /* Keypad upper left */
+ #define    KEY_A3         0x15D    /* Keypad upper right */
+ #define    KEY_B2         0x15E    /* Keypad centre key */
+ #define    KEY_C1         0x15F    /* Keypad lower left */
+ #define    KEY_C3         0x160    /* Keypad lower right */
+ 
+ #define    KEY_BTAB       0x161    /* Back Tab */
+ #define    KEY_BEG        0x162    /* Begin key */
+ #define    KEY_CANCEL     0x163    /* Cancel key */
+ #define    KEY_CLOSE      0x164    /* Close Key */
+ #define    KEY_COMMAND    0x165    /* Command Key */
+ #define    KEY_COPY       0x166    /* Copy key */
+ #define    KEY_CREATE     0x167    /* Create key */
+ #define    KEY_END        0x168    /* End key */
+ #define    KEY_EXIT       0x169    /* Exit key */
+ #define    KEY_FIND       0x16A    /* Find key */
+ #define    KEY_HELP       0x16B    /* Help key */
+ #define    KEY_MARK       0x16C    /* Mark key */
+ #define    KEY_MESSAGE    0x16D    /* Message key */
+ #define    KEY_MOVE       0x16E    /*  Move key */
+ #define    KEY_NEXT       0x16F    /* Next Object key */
+ #define    KEY_OPEN       0x170    /* Open key */
+ #define    KEY_OPTIONS    0x171    /* Options key */
+ #define    KEY_PREVIOUS   0x172    /* Previous Object key */
+ #define    KEY_REDO       0x173    /* redo key */
+ #define    KEY_REFERENCE  0x174    /* Ref Key */
+ #define    KEY_REFRESH    0x175    /* Refresh key */
+ #define    KEY_REPLACE    0x176    /* Replace key */
+ #define    KEY_RESTART    0x177    /* Restart key */
+ #define    KEY_RESUME     0x178    /* Resume key */
+ #define    KEY_SAVE       0x179    /* Save key */
+ #define    KEY_SBEG       0x17A    /* Shift begin key */
+ #define    KEY_SCANCEL    0x17B    /* Shift Cancel key */
+ #define    KEY_SCOMMAND   0x17C    /* Shift Command key */
+ #define    KEY_SCOPY      0x17D    /* Shift Copy key */
+ #define    KEY_SCREATE    0x17E    /* Shift Create key */
+ #define    KEY_SDC        0x17F    /* Shift Delete Character */
+ #define    KEY_SDL        0x180    /* Shift Delete Line */
+ #define    KEY_SELECT     0x181    /* Select key */
+ #define    KEY_SEND       0x182    /* Send key */
+ #define    KEY_SEOL       0x183    /* Shift Clear Line key */
+ #define    KEY_SEXIT      0x184    /* Shift Exit key */
+ #define    KEY_SFIND      0x185    /* Shift Find key */
+ #define    KEY_SHELP      0x186    /* Shift Help key */
+ #define    KEY_SHOME      0x187    /* Shift Home key */
+ #define    KEY_SIC        0x188    /* Shift Input key */
+ #define    KEY_SLEFT      0x189    /* Shift Left Arrow key */
+ #define    KEY_SMESSAGE   0x18A    /* Shift Message key */
+ #define    KEY_SMOVE      0x18B    /* Shift Move key */
+ #define    KEY_SNEXT      0x18C    /* Shift Next key */
+ #define    KEY_SOPTIONS   0x18D    /* Shift Options key */
+ #define    KEY_SPREVIOUS  0x18E    /* Shift Previous key */
+ #define    KEY_SPRINT     0x18F    /* Shift Print key */
+ #define    KEY_SREDO      0x190    /* Shift Redo key */
+ #define    KEY_SREPLACE   0x191    /* Shift Replace key */
+ #define    KEY_SRIGHT     0x192    /* Shift Right Arrow key */
+ #define    KEY_SRESUME    0x193    /* Shift Resume key */
+ #define    KEY_SSAVE      0x194    /* Shift Save key */
+ #define    KEY_SSUSPEND   0x195    /* Shift Suspend key */
+ #define    KEY_SUNDO      0x196    /* Shift Undo key */
+ #define    KEY_SUSPEND    0x197    /* Suspend key */
+ #define    KEY_UNDO       0x198    /* Undo key  */
+ 
  /* 8-bit ASCII characters. */
  #define	unctrl(c)		__unctrl[(c) & 0xff]
  #define	unctrllen(ch)		__unctrllen[(ch) & 0xff]
***************
*** 149,154 ****
--- 255,263 ----
  #define	__CLEAROK	0x040		/* Clear on next refresh. */
  #define __WSTANDOUT	0x080		/* Standout window */
  #define __LEAVEOK	0x100		/* If curser left */	
+ #define __KEYPAD        0x1000          /* If interpreting keypad codes */
+ #define __NODELAY       0x2000          /* Don't block in getch */
+ #define __NOTIMEOUT     0x4000          /* Wait indefinitely for func keys */
  	unsigned int flags;
  } WINDOW;
  
***************
*** 255,260 ****
--- 364,370 ----
  int	 gettmode __P((void));
  void	 idlok __P((WINDOW *, int));
  WINDOW	*initscr __P((void));
+ void	 keypad __P((WINDOW *, int));
  char	*longname __P((char *, char *));
  int	 mvcur __P((int, int, int, int));
  int	 mvprintw __P((int, int, const char *, ...));
***************
*** 265,273 ****
--- 375,385 ----
  WINDOW	*newwin __P((int, int, int, int));
  int	 nl __P((void));
  int	 nocbreak __P((void));
+ void     nodelay __P((WINDOW *, int));
  int	 noecho __P((void));
  int	 nonl __P((void));
  int	 noraw __P((void));
+ void     notimeout __P((WINDOW *, int));
  int	 overlay __P((WINDOW *, WINDOW *));
  int	 overwrite __P((WINDOW *, WINDOW *));
  int	 printw __P((const char *, ...));
***************
*** 326,331 ****
--- 438,448 ----
  int	 __touchwin __P((WINDOW *));
  char	*__tscroll __P((const char *, int, int));
  int	 __waddch __P((WINDOW *, __LDATA *));
+ void     __init_getch __P((char *));
+ int      __nodelay __P((void));
+ int      __delay __P((void));
+ int      __notimeout __P((void));
+ int      __timeout __P((void));
  
  /* Private #defines. */
  #define	min(a,b)	(a < b ? a : b)
Index: src/lib/libcurses/getch.c
diff -c src/lib/libcurses/getch.c:1.1.1.2 src/lib/libcurses/getch.c:1.7
*** src/lib/libcurses/getch.c:1.1.1.2	Tue Aug  5 19:34:20 1997
--- src/lib/libcurses/getch.c	Tue Aug 12 11:11:48 1997
***************
*** 42,50 ****
--- 42,401 ----
  #endif
  #endif	/* not lint */
  
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <stdio.h>
  #include "curses.h"
  
  /*
+  * Keyboard input handler.  Do this by snarfing
+  * all the info we can out of the termcap entry for TERM and putting it
+  * into a set of keymaps.  A keymap is an array the size of all the possible
+  * single characters we can get, the contents of the array is a structure
+  * that contains the type of entry this character is (i.e. part/end of a
+  * multi-char sequence or a plain char) and either a pointer which will point 
+  * to another keymap (in the case of a multi-char sequence) OR the data value
+  * that this key should return.
+  *
+  */
+ 
+ /* private data structures for holding the key definitions */
+ typedef struct keymap keymap_t;
+ typedef struct key_entry key_entry_t;
+ 
+ struct key_entry {
+   short type;  /* type of key this is */
+   union {
+     keymap_t *next;  /* next keymap is key is multi-key sequence */
+     int symbol;      /* key symbol if key is a leaf entry */
+   } value;
+ };
+ 
+ /* Types of key structures we can have */
+ #define KEYMAP_MULTI  1 /* part of a multi char sequence */
+ #define KEYMAP_LEAF   2 /* key has a symbol associated with it, either it
+                            is the end of a multi-char sequence or a single
+                            char key that generates a symbol */
+ 
+ /* The max number of different chars we can receive */
+ #define MAX_CHAR 256
+ 
+ struct keymap {
+   int count; /* count of number of key structs allocated */
+   short mapping[MAX_CHAR]; /* mapping of key to allocated structs */
+   key_entry_t *key[0];  /* dynamic array of keys */
+ };
+ 
+ 
+ /* Key buffer */
+ #define INBUF_SZ 16  /* size of key buffer - must be larger than longest
+                         multi-key sequence */
+ char inbuf[INBUF_SZ];
+ int start, end, working; /* pointers for manipulating inbuf data */
+ 
+ #define INC_POINTER(ptr)  do {                                            \
+         (ptr)++;                                                          \
+         ptr %= INBUF_SZ;                                                  \
+ } while(0)
+ 
+ short state; /* state of the inkey function */
+ 
+ #define INKEY_NORM       0  /* no key backlog to process */
+ #define INKEY_ASSEMBLING 1 /* assembling a multi-key sequence */
+ #define INKEY_BACKOUT    2 /* recovering from an unrecognised key */
+ #define INKEY_TIMEOUT    3 /* multi-key sequence timeout */
+ 
+ /* The termcap data we are interested in and the symbols they map to */
+ struct tcdata {
+   char *name;  /* name of termcap entry */
+   int symbol;  /* the symbol associated with it */
+ };
+ 
+ const struct tcdata tc[] = {
+   {"K1", KEY_A1},
+   {"K2", KEY_B2},
+   {"K3", KEY_A3},
+   {"K4", KEY_C1},
+   {"K5", KEY_C3},
+   {"k0", KEY_F0},
+   {"k1", KEY_F(1)},
+   {"k2", KEY_F(2)},
+   {"k3", KEY_F(3)},
+   {"k4", KEY_F(4)},
+   {"k5", KEY_F(5)},
+   {"k6", KEY_F(6)},
+   {"k7", KEY_F(7)},
+   {"k8", KEY_F(8)},
+   {"k9", KEY_F(9)},
+   {"kA", KEY_IL},
+   {"ka", KEY_CATAB},
+   {"kb", KEY_BACKSPACE},
+   {"kC", KEY_CLEAR},
+   {"kD", KEY_DC},
+   {"kd", KEY_DOWN},
+   {"kE", KEY_EOL},
+   {"kF", KEY_SF},
+   {"kH", KEY_LL},
+   {"kh", KEY_HOME},
+   {"kI", KEY_IC},
+   {"kL", KEY_DL},
+   {"kl", KEY_LEFT},
+   {"kN", KEY_NPAGE},
+   {"kP", KEY_PPAGE},
+   {"kR", KEY_SR},
+   {"kr", KEY_RIGHT},
+   {"kS", KEY_EOS},
+   {"kT", KEY_STAB},
+   {"kt", KEY_CTAB},
+   {"ku", KEY_UP}
+ };
+ 
+ /* Number of TC entries .... */
+ const int num_tcs = (sizeof(tc)/sizeof(struct tcdata));
+ 
+ /* The root keymap */
+ 
+ keymap_t *base_keymap;
+ 
+ /* prototypes for private functions */
+ keymap_t *
+ new_keymap(void);  /* create a new keymap */
+ 
+ key_entry_t *
+ new_key(void);  /* create a new key entry */
+ 
+ unsigned
+ inkey(int);
+ 
+ /*
+  * Init_inkey - initialise all the pointers & structures needed to make
+  * inkey work.
+  *
+  */
+ void
+ __init_getch(sp)
+      char *sp;
+ {
+   int i, j, length;
+   keymap_t *current;
+   char termcap[1024], entry[1024], termname[1024], *p;
+   key_entry_t *the_key;
+ 
+   /* init the inkey state variable */
+   state = INKEY_NORM;
+ 
+   /* init the base keymap */
+   base_keymap = new_keymap();
+ 
+   /* key input buffer pointers */
+   start = end = working = 0;
+ 
+   /* now do the termcap snarfing ... */
+   strncpy(termname, sp, 1022);
+   termname[1023] = 0;
+ 
+   if (tgetent(termcap, termname) > 0)
+   {
+     for (i = 0; i < num_tcs; i++)
+     {
+       p = entry;
+       if (tgetstr(tc[i].name, &p) != NULL)
+       {
+         current = base_keymap; /* always start with base keymap. */
+         length = strlen(entry);
+ 
+         for (j = 0; j < length - 1; j++)
+         {
+           if (current->mapping[(unsigned) entry[j]] < 0) /* first time for this char */
+           {
+             current->mapping[(unsigned) entry[j]] = current->count; /* map new entry */
+             the_key = new_key();
+             the_key->type = KEYMAP_MULTI; /* must be coz we are here */
+             the_key->value.next = new_keymap(); /* need for next key */
+ 
+             current->key[current->count++] = the_key; /* put into key array */
+             
+           }
+ 
+           /* next key uses this map... */
+           current = current->key[current->mapping[(unsigned) entry[j]]]->value.next;
+        }
+ 
+         /* this is the last key in the sequence (it may have been the
+            only one but that does not matter) this means it is a leaf
+            key and should have a symbol associated with it */
+         current->mapping[(unsigned) entry[length - 1]] = current->count;
+         the_key = new_key();
+         the_key->type = KEYMAP_LEAF; /* leaf key */
+         the_key->value.symbol = tc[i].symbol; /* the associated symbol */
+         current->key[current->count++] = the_key;
+       }
+     } 
+   }
+ }
+ 
+ 
+ /*
+  * new_keymap - allocates & initialises a new keymap structure.  This
+  * function returns a pointer to the new keymap.
+  *
+  */
+ keymap_t *
+ new_keymap(void)
+ {
+   int i;
+   keymap_t *new_map;
+ 
+   if ((new_map = malloc(sizeof(keymap_t))) == NULL)
+   {
+     perror("Inkey: Cannot allocate new keymap");
+     exit(2);
+   }
+ 
+   /* initialise the new map */
+   new_map->count = 0;
+   for (i = 0; i < MAX_CHAR; i++)
+   {
+     new_map->mapping[i] = -1; /* no mapping for char */
+   }
+ 
+   return new_map;
+ }
+ 
+ /*
+  * new_key - allocates & initialises a new key entry.  This function returns
+  * a pointer to the newly allocated key entry.
+  * 
+  */
+ key_entry_t *
+ new_key(void)
+ {
+   key_entry_t *new_one;
+ 
+   if ((new_one = malloc(sizeof(key_entry_t))) == NULL)
+   {
+     perror("inkey: Cannot allocate new key entry");
+     exit(2);
+   }
+ 
+   new_one->type = 0;
+   new_one->value.next = NULL;
+ 
+   return new_one;
+ }
+ 
+ /*
+  * inkey - do the work to process keyboard input, check for multi-key
+  * sequences and return the appropriate symbol if we get a match.
+  * 
+  */
+ 
+ unsigned
+ inkey(to)
+      int to;
+ {
+   int k, nchar;
+   char c;
+   keymap_t *current = base_keymap;
+ 
+   while (1) /* loop until we get a complete key sequence */
+   {
+ reread:
+     if (state == INKEY_NORM)
+     {
+       if ((nchar = read(STDIN_FILENO, &c, sizeof(char))) < 0) return ERR;
+       k = (unsigned int) c;
+       if (nchar == 0) return ERR; /* just in case we are nodelay mode */
+ 
+       working = start;
+       inbuf[working] = k;
+       INC_POINTER(working);
+       end = working;
+       state = INKEY_ASSEMBLING; /* go to the assembling state now */
+     }
+     else if (state == INKEY_BACKOUT)
+     {
+       k = inbuf[working];
+       INC_POINTER(working);
+       if (working == end) /* see if we have run out of keys in the backlog */
+       {
+         state = INKEY_ASSEMBLING; /* if we have then switch to assembling */
+       }
+     }
+     else if (state == INKEY_ASSEMBLING) /* assembling a key sequence */
+     {
+       if (to && (__timeout() == ERR)) return ERR;
+       if ((nchar = read(STDIN_FILENO, &c, sizeof(char))) < 0) return ERR;
+       if (to && (__notimeout() == ERR)) return ERR;
+ 
+       k = (unsigned int) c;
+       if (nchar == 0) /* inter-char timeout, start backing out */
+       {
+         if (start == end) goto reread; /* no chars in the buffer, restart */
+         k = inbuf[start];
+         state = INKEY_TIMEOUT;
+       }
+       else
+       {
+         inbuf[working] = k;
+         INC_POINTER(working);
+         end = working;
+       }
+     }
+     else
+     {
+       fprintf(stderr, "Inkey state screwed - exiting!!!");
+       exit(2);
+     }
+ 
+     /* Check key has no special meaning and we have not timed out */
+     if ((current->mapping[k] < 0) || (state == INKEY_TIMEOUT)) 
+     {
+       k = inbuf[start]; /* return the first key we know about */
+       
+       INC_POINTER(start);
+       working = start;
+ 
+       if (start == end) /* only one char processed */
+       {
+         state = INKEY_NORM;
+       }
+       else /* otherwise we must have more than one char to backout */
+       {
+         state = INKEY_BACKOUT;
+       }
+       return k;
+     }
+     else /* must be part of a multikey sequence */
+     {
+       /* check for completed key sequence */
+       if (current->key[current->mapping[k]]->type == KEYMAP_LEAF)
+       {
+         start = working; /* eat the key sequence in inbuf */
+ 
+         if (start == end) /* check if inbuf empty now */
+         {
+           state = INKEY_NORM; /* if it is go back to normal */
+         }
+         else /* otherwise go to backout state */
+         {
+           state = INKEY_BACKOUT;
+         }
+ 
+         /* return the symbol */
+         return current->key[current->mapping[k]]->value.symbol;
+ 
+       }
+       else /* step on to next part of the multi-key sequence */
+       {
+         current = current->key[current->mapping[k]]->value.next;
+       }
+     }
+   }
+ }
+ 
+ /*
   * wgetch --
   *	Read in a character from the window.
   */
***************
*** 52,58 ****
  wgetch(win)
  	register WINDOW *win;
  {
! 	register int inp, weset;
  
  	if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN)
  	    && win->curx == win->maxx - 1 && win->cury == win->maxy - 1)
--- 403,411 ----
  wgetch(win)
  	register WINDOW *win;
  {
! 	register int weset;
!         int inp;
!         char c;
  
  	if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN)
  	    && win->curx == win->maxx - 1 && win->cury == win->maxy - 1)
***************
*** 67,76 ****
  	} else
  		weset = 0;
  
! 	inp = getchar();
  #ifdef DEBUG
  	__CTRACE("wgetch got '%s'\n", unctrl(inp));
  #endif
  	if (__echoit) {
  		mvwaddch(curscr,
  		    win->cury + win->begy, win->curx + win->begx, inp);
--- 420,453 ----
  	} else
  		weset = 0;
  
!         if (win->flags & __NODELAY)
!         {
!           if (__nodelay() == ERR) return ERR;
!         }
! 
!         if (win->flags & __KEYPAD)
!         {
!           inp = inkey(win->flags & __NOTIMEOUT);
!         }
!         else
!         {
!           if (read(STDIN_FILENO, &c, sizeof(char)) < 0)
!           {
!             inp = ERR;
!           }
!           else
!           {
!             inp = (unsigned int) c;
!           }
!         }
  #ifdef DEBUG
  	__CTRACE("wgetch got '%s'\n", unctrl(inp));
  #endif
+         if (win->flags & __NODELAY)
+         {
+           if (__delay() == ERR) return ERR;
+         }
+ 
  	if (__echoit) {
  		mvwaddch(curscr,
  		    win->cury + win->begy, win->curx + win->begx, inp);
***************
*** 78,82 ****
  	}
  	if (weset)
  		nocbreak();
! 	return (inp);
  }
--- 455,459 ----
  	}
  	if (weset)
  		nocbreak();
! 	return ((inp < 0) || (inp == ERR) ? ERR : inp);
  }
Index: src/lib/libcurses/initscr.c
diff -c src/lib/libcurses/initscr.c:1.1.1.2 src/lib/libcurses/initscr.c:1.3
*** src/lib/libcurses/initscr.c:1.1.1.2	Tue Aug  5 19:34:25 1997
--- src/lib/libcurses/initscr.c	Tue Aug  5 20:16:51 1997
***************
*** 91,96 ****
--- 91,98 ----
  		return (NULL);
  	}
  
+         __init_getch(sp);
+ 
  	__set_stophandler();
  
  #ifdef DEBUG
Index: src/lib/libcurses/keypad.c
diff -c /dev/null src/lib/libcurses/keypad.c:1.2
*** /dev/null	Tue Aug 12 11:12:46 1997
--- src/lib/libcurses/keypad.c	Tue Aug  5 20:16:52 1997
***************
*** 0 ****
--- 1,59 ----
+ /*
+  * Copyright (c) 1981, 1993, 1994
+  *	The Regents of the University of California.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the University of
+  *	California, Berkeley and its contributors.
+  * 4. Neither the name of the University nor the names of its contributors
+  *    may be used to endorse or promote products derived from this software
+  *    without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  */
+ 
+ #include <sys/cdefs.h>
+ #ifndef lint
+ #if 0
+ static char sccsid[] = "@(#)initscr.c	8.2 (Berkeley) 5/4/94";
+ #else
+ __RCSID("$NetBSD: initscr.c,v 1.7 1997/07/22 07:36:47 mikel Exp $");
+ #endif
+ #endif	/* not lint */
+ 
+ #include "curses.h"
+ 
+ /*
+  * keypad --
+  *	Turn on and off interpretation of function/keypad keys in the
+  *	given window.
+  */
+ void
+ keypad(win, bf)
+ 	WINDOW *win;
+ 	int bf;
+ {
+ 	if (bf)
+ 		win->flags |= __KEYPAD;
+ 	else
+ 		win->flags &= ~__KEYPAD;
+ }
Index: src/lib/libcurses/nodelay.c
diff -c /dev/null src/lib/libcurses/nodelay.c:1.3
*** /dev/null	Tue Aug 12 11:12:46 1997
--- src/lib/libcurses/nodelay.c	Sun Aug 10 16:34:33 1997
***************
*** 0 ****
--- 1,59 ----
+ /*
+  * Copyright (c) 1981, 1993, 1994
+  *	The Regents of the University of California.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the University of
+  *	California, Berkeley and its contributors.
+  * 4. Neither the name of the University nor the names of its contributors
+  *    may be used to endorse or promote products derived from this software
+  *    without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  */
+ 
+ #include <sys/cdefs.h>
+ #ifndef lint
+ #if 0
+ static char sccsid[] = "@(#)initscr.c	8.2 (Berkeley) 5/4/94";
+ #else
+ __RCSID("$NetBSD: initscr.c,v 1.7 1997/07/22 07:36:47 mikel Exp $");
+ #endif
+ #endif	/* not lint */
+ 
+ #include "curses.h"
+ 
+ /*
+  * nodelay --
+  *	Turn on and off blocking reads in getch for a 
+  *	given window.
+  */
+ void
+ nodelay(win, bf)
+ 	WINDOW *win;
+ 	int bf;
+ {
+ 	if (bf)
+           win->flags |= __NODELAY;
+ 	else
+           win->flags &= ~__NODELAY;
+ }
Index: src/lib/libcurses/notimeout.c
diff -c /dev/null src/lib/libcurses/notimeout.c:1.3
*** /dev/null	Tue Aug 12 11:12:47 1997
--- src/lib/libcurses/notimeout.c	Tue Aug  5 20:16:55 1997
***************
*** 0 ****
--- 1,59 ----
+ /*
+  * Copyright (c) 1981, 1993, 1994
+  *	The Regents of the University of California.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the University of
+  *	California, Berkeley and its contributors.
+  * 4. Neither the name of the University nor the names of its contributors
+  *    may be used to endorse or promote products derived from this software
+  *    without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  */
+ 
+ #include <sys/cdefs.h>
+ #ifndef lint
+ #if 0
+ static char sccsid[] = "@(#)initscr.c	8.2 (Berkeley) 5/4/94";
+ #else
+ __RCSID("$NetBSD: initscr.c,v 1.7 1997/07/22 07:36:47 mikel Exp $");
+ #endif
+ #endif	/* not lint */
+ 
+ #include "curses.h"
+ 
+ /*
+  * notimeout --
+  *	Turn on and off inter-key timeout when assembling function keys for a
+  *	given window.
+  */
+ void
+ notimeout(win, bf)
+ 	WINDOW *win;
+ 	int bf;
+ {
+ 	if (bf)
+ 		win->flags &= ~__NOTIMEOUT;
+ 	else
+ 		win->flags |= __NOTIMEOUT;
+ }
Index: src/lib/libcurses/tty.c
diff -c src/lib/libcurses/tty.c:1.1.1.2 src/lib/libcurses/tty.c:1.3
*** src/lib/libcurses/tty.c:1.1.1.2	Tue Aug  5 19:34:48 1997
--- src/lib/libcurses/tty.c	Tue Aug  5 20:16:56 1997
***************
*** 64,69 ****
--- 64,71 ----
  struct termios __orig_termios, __baset;
  static struct termios cbreakt, rawt, *curt;
  static int useraw;
+ static int ovmin = 1;
+ static int ovtime = 0;
  
  #ifndef	OXTABS
  #ifdef	XTABS			/* SMI uses XTABS. */
***************
*** 166,171 ****
--- 168,215 ----
  }
  	
  int
+ __delay()
+ {
+ 	cbreakt.c_cc[VMIN] = 1;
+         cbreakt.c_cc[VTIME] = 0;
+ 
+ 	return (tcsetattr(STDIN_FILENO, __tcaction ?
+ 	    TCSASOFT : TCSANOW, curt) ? ERR : OK);
+ }
+ 	
+ int
+ __nodelay()
+ {
+ 	cbreakt.c_cc[VMIN] = 0;
+         cbreakt.c_cc[VTIME] = 0;
+ 
+ 	return (tcsetattr(STDIN_FILENO, __tcaction ?
+ 	    TCSASOFT : TCSANOW, curt) ? ERR : OK);
+ }
+ 	
+ int
+ __timeout()
+ {
+ 	ovmin = cbreakt.c_cc[VMIN];
+         ovtime = cbreakt.c_cc[VTIME];
+ 	cbreakt.c_cc[VMIN] = 0;
+         cbreakt.c_cc[VTIME] = 2;
+ 
+ 	return (tcsetattr(STDIN_FILENO, __tcaction ?
+ 	    TCSASOFT | TCSANOW : TCSANOW, curt) ? ERR : OK);
+ }
+ 	
+ int
+ __notimeout()
+ {
+ 	cbreakt.c_cc[VMIN] = ovmin;
+         cbreakt.c_cc[VTIME] = ovtime;
+ 
+ 	return (tcsetattr(STDIN_FILENO, __tcaction ?
+ 	    TCSASOFT | TCSANOW : TCSANOW, curt) ? ERR : OK);
+ }
+ 	
+ int
  echo()
  {
  	rawt.c_lflag |= ECHO;
***************
*** 189,194 ****
--- 233,239 ----
  	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
  }
  
+ 
  int
  nl()
  {
***************
*** 244,249 ****
--- 289,295 ----
  
  	tputs(TI, 0, __cputchar);
  	tputs(VS, 0, __cputchar);
+ 	tputs(KS, 0, __cputchar);
  }
  
  int
***************
*** 261,266 ****
--- 307,313 ----
  
  	(void)tputs(VE, 0, __cputchar);
  	(void)tputs(TE, 0, __cputchar);
+ 	(void)tputs(KE, 0, __cputchar);
  	(void)fflush(stdout);
  	(void)setvbuf(stdout, NULL, _IOLBF, 0);
  
Index: src/lib/libcurses/EXAMPLES/ex2.c
diff -c /dev/null src/lib/libcurses/EXAMPLES/ex2.c:1.1
*** /dev/null	Tue Aug 12 11:12:47 1997
--- src/lib/libcurses/EXAMPLES/ex2.c	Sun Aug 10 17:55:46 1997
***************
*** 0 ****
--- 1,110 ----
+ /*
+  * Test the function of the keypad, nodelay and notimeout functions.
+  * Follow the instructions printed out.
+  *
+  * $Log: ex2.c,v $
+  * Revision 1.1  1997/08/10 08:25:46  blymn
+  * New example file showing keypad, notimeout and nodelay functions.
+  *
+  *
+  */
+ 
+ #include <unistd.h>
+ #include <curses.h>
+ 
+ int
+ main(void)
+ {
+   WINDOW *term;
+   int i;
+   int key;
+   int padstate = FALSE;
+   int tostate = TRUE;
+   int delstate = FALSE;
+   
+ 
+   term = initscr();
+   cbreak();
+   noecho();
+   mvprintw(1, 2, "Curses testing: press k to toggle keypad mode, q to quit");
+   mvprintw(2, 2, "                press t to toggle timeout, d to toggle delay");
+   mvprintw(3, 2, "                press other keys to see what happens");
+   refresh();
+ 
+   i = 6;
+   while ((key = getch()) != (int) 'q')
+   {
+     if (key < (int) ' ')
+     {
+       if (key == ERR)
+       {
+         mvprintw(i,2, "Got ERR back for key - sleeping for 1 second");
+         refresh();
+         sleep(1); /* don't go busy wait */
+       }
+       else
+       {
+         mvprintw(i,2, "Got non-printable key 0x%x", key);
+       }
+     }
+     else if (key < 256)
+     {
+       switch (key)
+       {
+       case 'd':
+         delstate = !delstate;
+         nodelay(stdscr, delstate);
+         mvprintw(i,2, "Nodelay is now %s\n", (delstate) ? "TRUE" : "FALSE");
+         break;
+ 
+       case 'k':
+         padstate = !padstate;
+         keypad(stdscr, padstate);
+         mvprintw(i,2, "Keypad is now %s\n", (padstate) ? "TRUE" : "FALSE");
+         break;
+ 
+       case 't':
+         tostate = !tostate;
+         notimeout(stdscr, tostate);
+         mvprintw(i,2, "Notimeout is now %s\n", (tostate) ? "TRUE" : "FALSE");
+         break;
+ 
+       default:
+         mvprintw(i,2, "Got key %c (0x%x)", (char) key, key);
+         break;
+       }
+     }
+     else
+     {
+       switch (key)
+       {
+       case KEY_UP:
+         mvprintw(i,2, "Got key_up");
+         break;
+ 
+       case KEY_DOWN:
+         mvprintw(i,2, "Got key_down");
+         break;
+ 
+       case KEY_LEFT:
+         mvprintw(i,2, "Got key_left");
+         break;
+ 
+       case KEY_RIGHT:
+         mvprintw(i,2, "Got key_right");
+         break;
+ 
+       default:
+         mvprintw(i,2, "Got keysym 0x%x", key);
+         break;
+       }
+     }
+ 
+     i++; i %= LINES; i = (i < 6) ? 6 : i;
+     move(i, 2); clrtoeol();
+     refresh();
+   }
+ 
+   endwin();
+   exit(0);
+ }
>Audit-Trail:
>Unformatted: