Added the ncurses extensions define_key and keyok.
This commit is contained in:
parent
8465b6a98d
commit
5aec620ac6
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: curses.3,v 1.41 2002/10/21 13:55:07 blymn Exp $
|
||||
.\" $NetBSD: curses.3,v 1.42 2002/10/22 12:07:20 blymn Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1985, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -105,6 +105,7 @@ must be called before any of the other routines that deal with color are used.
|
|||
.It delay_output Ta Xr curses_tty 3
|
||||
.It def_prog_mode Ta Xr curses_tty 3
|
||||
.It def_shell_mode Ta Xr curses_tty 3
|
||||
.It define_key Ta Xr curses_input 3
|
||||
.It delch Ta Xr curses_delch 3
|
||||
.It deleteln Ta Xr curses_deleteln 3
|
||||
.It delscreen Ta Xr curses_screen 3
|
||||
|
@ -159,6 +160,7 @@ must be called before any of the other routines that deal with color are used.
|
|||
.It is_wintouched Ta Xr curses_touch 3
|
||||
.It isendwin Ta Xr curses_screen 3
|
||||
.It keypad Ta Xr curses_input 3
|
||||
.It keyok Ta Xr curses_input 3
|
||||
.It killchar Ta Xr curses_tty 3
|
||||
.It leaveok Ta Xr curses_tty 3
|
||||
.It longname Ta Xr curses_termcap 3
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: curses.h,v 1.68 2002/10/14 16:25:52 jdc Exp $ */
|
||||
/* $NetBSD: curses.h,v 1.69 2002/10/22 12:07:20 blymn Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1981, 1993, 1994
|
||||
|
@ -496,6 +496,7 @@ int copywin(const WINDOW *, WINDOW *, int, int, int, int, int, int, int);
|
|||
int curs_set(int);
|
||||
int def_prog_mode(void);
|
||||
int def_shell_mode(void);
|
||||
int define_key(char *, int);
|
||||
int delay_output(int);
|
||||
void delscreen(SCREEN *);
|
||||
int delwin(WINDOW *);
|
||||
|
@ -534,6 +535,7 @@ int intrflush(WINDOW *, bool);
|
|||
bool isendwin(void);
|
||||
bool is_linetouched(WINDOW *, int);
|
||||
bool is_wintouched(WINDOW *);
|
||||
int keyok(int, bool);
|
||||
void keypad(WINDOW *, bool);
|
||||
char killchar(void);
|
||||
int leaveok(WINDOW *, bool);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: curses_input.3,v 1.4 2002/10/21 14:31:36 wiz Exp $
|
||||
.\" $NetBSD: curses_input.3,v 1.5 2002/10/22 12:07:20 blymn Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2002
|
||||
.\" Brett Lymn (blymn@netbsd.org, brett_lymn@yahoo.com.au)
|
||||
|
@ -37,6 +37,8 @@
|
|||
.Nm curses_input ,
|
||||
.Nm getch ,
|
||||
.Nm wgetch ,
|
||||
.Nm define_key ,
|
||||
.Nm keyok ,
|
||||
.Nm getnstr ,
|
||||
.Nm wgetnstr ,
|
||||
.Nm mvgetnstr ,
|
||||
|
@ -61,6 +63,10 @@
|
|||
.Ft int
|
||||
.Fn wgetch "WINDOW *win"
|
||||
.Ft int
|
||||
.Fn keyok "int key_symbol" "bool flag"
|
||||
.Ft int
|
||||
.Fn define_key "char *sequence" "int key_symbol"
|
||||
.Ft int
|
||||
.Fn getnstr "char *str" "int limit"
|
||||
.Ft int
|
||||
.Fn wgetnstr "WINDOW *win" "char *str" "int limit"
|
||||
|
@ -119,6 +125,55 @@ function, exceptng that it reads from the input file descriptor associated
|
|||
with the window specified by
|
||||
.Fa win .
|
||||
.Pp
|
||||
If the
|
||||
.Fn keypad
|
||||
flag is
|
||||
.Dv TRUE
|
||||
then the assembly of specific key symbols can be disabled by using the
|
||||
.Fn keyok
|
||||
function.
|
||||
If the
|
||||
.Fa flag
|
||||
is set to
|
||||
.Dv FALSE
|
||||
on a key symbol then
|
||||
.Fn getch
|
||||
will behave as if the character sequence associated with that key symbol
|
||||
was not recognised and will return the component characters one at a time to
|
||||
the caller.
|
||||
.Pp
|
||||
Custom associations between sequences of characters and a key symbol can
|
||||
be made by using the
|
||||
.Fn define_key
|
||||
function.
|
||||
Normally, these associations are made by the information in the
|
||||
.Xr termcap 5
|
||||
database but the
|
||||
.Fn define_key
|
||||
function gives the capability to remove or add more associations.
|
||||
If
|
||||
.Fn define_key
|
||||
is passed a non-NULL string in
|
||||
.Fa sequence
|
||||
it will associate that sequence with the key symbol passed in
|
||||
.Fa key_symbol .
|
||||
The key symbol may be one of the ones listed below or a custom value that
|
||||
is application defined.
|
||||
It is valid to have multiple character sequences map to the same key
|
||||
symbol and there are no constraints on the length of the sequence allowed.
|
||||
The assembly of custom sequences follow the same rules for inter-character
|
||||
timing and so forth as the
|
||||
.Xr termcap 5
|
||||
derived ones.
|
||||
If
|
||||
.Fn define_key
|
||||
is passed a NULL in
|
||||
.Fa sequence
|
||||
then all associations for the key symbol in
|
||||
.Fa key_symbol
|
||||
will be deleted, this includes any associations that were derived from
|
||||
.Xr termcap 5 .
|
||||
.Pp
|
||||
The
|
||||
.Fn mvgetch
|
||||
and
|
||||
|
@ -482,6 +537,14 @@ The
|
|||
.Nx
|
||||
Curses library complies with the X/Open Curses specification, part of the
|
||||
Single Unix Specification.
|
||||
.Sh NOTES
|
||||
The
|
||||
.Fn keyok
|
||||
and
|
||||
.Fn define_key
|
||||
functions are implementations of extensions made by the NCurses library
|
||||
to the Curses standard.
|
||||
Portable implementations should avoid the use of these functions.
|
||||
.Sh HISTORY
|
||||
The Curses package appeared in
|
||||
.Bx 4.0 .
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: getch.c,v 1.36 2002/01/02 10:38:27 blymn Exp $ */
|
||||
/* $NetBSD: getch.c,v 1.37 2002/10/22 12:07:20 blymn Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1981, 1993, 1994
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)getch.c 8.2 (Berkeley) 5/4/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: getch.c,v 1.36 2002/01/02 10:38:27 blymn Exp $");
|
||||
__RCSID("$NetBSD: getch.c,v 1.37 2002/10/22 12:07:20 blymn Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -68,6 +68,7 @@ typedef struct key_entry key_entry_t;
|
|||
|
||||
struct key_entry {
|
||||
short type; /* type of key this is */
|
||||
bool enable; /* true if the key is active */
|
||||
union {
|
||||
keymap_t *next; /* next keymap is key is multi-key sequence */
|
||||
wchar_t symbol; /* key symbol if key is a leaf entry */
|
||||
|
@ -87,10 +88,15 @@ struct key_entry {
|
|||
/* The max number of different chars we can receive */
|
||||
#define MAX_CHAR 256
|
||||
|
||||
/*
|
||||
* Unused mapping flag.
|
||||
*/
|
||||
#define MAPPING_UNUSED (0 - MAX_CHAR) /* never been used */
|
||||
|
||||
struct keymap {
|
||||
int count; /* count of number of key structs allocated */
|
||||
int count; /* count of number of key structs allocated */
|
||||
short mapping[MAX_CHAR]; /* mapping of key to allocated structs */
|
||||
key_entry_t **key; /* dynamic array of keys */
|
||||
key_entry_t **key; /* dynamic array of keys */
|
||||
};
|
||||
|
||||
|
||||
|
@ -274,8 +280,11 @@ static const struct tcdata tc[] = {
|
|||
static const int num_tcs = (sizeof(tc) / sizeof(struct tcdata));
|
||||
|
||||
/* prototypes for private functions */
|
||||
static void add_key_sequence(SCREEN *screen, char *sequence, int key_type);
|
||||
static key_entry_t *add_new_key(keymap_t *current, char chr, int key_type,
|
||||
int symbol);
|
||||
static void delete_key_sequence(keymap_t *current, int key_type);
|
||||
static void do_keyok(keymap_t *current, int key_type, bool flag, int *retval);
|
||||
static keymap_t *new_keymap(void); /* create a new keymap */
|
||||
static key_entry_t *new_key(void); /* create a new key entry */
|
||||
static wchar_t inkey(int to, int delay);
|
||||
|
@ -318,36 +327,46 @@ static key_entry_t *
|
|||
add_new_key(keymap_t *current, char chr, int key_type, int symbol)
|
||||
{
|
||||
key_entry_t *the_key;
|
||||
int i;
|
||||
int i, ki;
|
||||
|
||||
#ifdef DEBUG
|
||||
__CTRACE("Adding character %s of type %d, symbol 0x%x\n", unctrl(chr),
|
||||
key_type, symbol);
|
||||
#endif
|
||||
if (current->mapping[(unsigned char) chr] < 0) {
|
||||
/* first time for this char */
|
||||
current->mapping[(unsigned char) chr] = current->count; /* map new entry */
|
||||
/* make sure we have room in the key array first */
|
||||
if ((current->count & (KEYMAP_ALLOC_CHUNK - 1)) == 0)
|
||||
{
|
||||
if ((current->key =
|
||||
realloc(current->key,
|
||||
(current->count) * sizeof(key_entry_t *)
|
||||
+ KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t *))) == NULL) {
|
||||
fprintf(stderr,
|
||||
"Could not malloc for key entry\n");
|
||||
exit(1);
|
||||
}
|
||||
if (current->mapping[(unsigned char) chr] == MAPPING_UNUSED) {
|
||||
/* first time for this char */
|
||||
current->mapping[(unsigned char) chr] =
|
||||
current->count; /* map new entry */
|
||||
ki = current->count;
|
||||
|
||||
the_key = new_key();
|
||||
for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) {
|
||||
current->key[current->count + i]
|
||||
= &the_key[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* point at the current key array element to use */
|
||||
the_key = current->key[current->count];
|
||||
/* make sure we have room in the key array first */
|
||||
if ((current->count & (KEYMAP_ALLOC_CHUNK - 1)) == 0)
|
||||
{
|
||||
if ((current->key =
|
||||
realloc(current->key,
|
||||
ki * sizeof(key_entry_t *)
|
||||
+ KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t *))) == NULL) {
|
||||
fprintf(stderr,
|
||||
"Could not malloc for key entry\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
the_key = new_key();
|
||||
for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) {
|
||||
current->key[ki + i] = &the_key[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* the mapping was used but freed, reuse it */
|
||||
ki = - current->mapping[(unsigned char) chr];
|
||||
current->mapping[(unsigned char) chr] = ki;
|
||||
}
|
||||
|
||||
current->count++;
|
||||
|
||||
/* point at the current key array element to use */
|
||||
the_key = current->key[ki];
|
||||
|
||||
the_key->type = key_type;
|
||||
|
||||
|
@ -358,6 +377,7 @@ add_new_key(keymap_t *current, char chr, int key_type, int symbol)
|
|||
__CTRACE("Creating new keymap\n");
|
||||
#endif
|
||||
the_key->value.next = new_keymap();
|
||||
the_key->enable = TRUE;
|
||||
break;
|
||||
|
||||
case KEYMAP_LEAF:
|
||||
|
@ -366,14 +386,13 @@ add_new_key(keymap_t *current, char chr, int key_type, int symbol)
|
|||
__CTRACE("Adding leaf key\n");
|
||||
#endif
|
||||
the_key->value.symbol = symbol;
|
||||
the_key->enable = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "add_new_key: bad type passed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current->count++;
|
||||
} else {
|
||||
/* the key is already known - just return the address. */
|
||||
#ifdef DEBUG
|
||||
|
@ -385,6 +404,85 @@ add_new_key(keymap_t *current, char chr, int key_type, int symbol)
|
|||
return the_key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the given key symbol from the key mappings for the screen.
|
||||
*
|
||||
*/
|
||||
void
|
||||
delete_key_sequence(keymap_t *current, int key_type)
|
||||
{
|
||||
key_entry_t *key;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* we need to iterate over all the keys as there may be
|
||||
* multiple instances of the leaf symbol.
|
||||
*/
|
||||
for (i = 0; i < MAX_CHAR; i++) {
|
||||
if (current->mapping[i] < 0)
|
||||
continue; /* no mapping for the key, next! */
|
||||
|
||||
key = current->key[current->mapping[i]];
|
||||
|
||||
if (key->type == KEYMAP_MULTI) {
|
||||
/* have not found the leaf, recurse down */
|
||||
delete_key_sequence(key->value.next, key_type);
|
||||
/* if we deleted the last key in the map, free */
|
||||
if (key->value.next->count == 0)
|
||||
_cursesi_free_keymap(key->value.next);
|
||||
} else if ((key->type == KEYMAP_LEAF)
|
||||
&& (key->value.symbol == key_type)) {
|
||||
/*
|
||||
* delete the mapping by negating the current
|
||||
* index - this "holds" the position in the
|
||||
* allocation just in case we later re-add
|
||||
* the key for that mapping.
|
||||
*/
|
||||
current->mapping[i] = - current->mapping[i];
|
||||
current->count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the sequence of characters given in sequence as the key mapping
|
||||
* for the given key symbol.
|
||||
*/
|
||||
void
|
||||
add_key_sequence(SCREEN *screen, char *sequence, int key_type)
|
||||
{
|
||||
key_entry_t *tmp_key;
|
||||
keymap_t *current;
|
||||
int length, j, key_ent;
|
||||
|
||||
current = screen->base_keymap; /* always start with
|
||||
* base keymap. */
|
||||
length = (int) strlen(sequence);
|
||||
|
||||
for (j = 0; j < length - 1; j++) {
|
||||
/* add the entry to the struct */
|
||||
tmp_key = add_new_key(current, sequence[j], KEYMAP_MULTI, 0);
|
||||
|
||||
/* index into the key array - it's
|
||||
clearer if we stash this */
|
||||
key_ent = current->mapping[(unsigned char) sequence[j]];
|
||||
|
||||
current->key[key_ent] = tmp_key;
|
||||
|
||||
/* next key uses this map... */
|
||||
current = current->key[key_ent]->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.
|
||||
*/
|
||||
tmp_key = add_new_key(current, sequence[length - 1], KEYMAP_LEAF,
|
||||
key_type);
|
||||
current->key[current->mapping[(int)sequence[length - 1]]] = tmp_key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init_getch - initialise all the pointers & structures needed to make
|
||||
* getch work in keypad mode.
|
||||
|
@ -394,12 +492,10 @@ void
|
|||
__init_getch(SCREEN *screen)
|
||||
{
|
||||
char entry[1024], *p;
|
||||
int i, j, length, key_ent;
|
||||
int i;
|
||||
size_t limit;
|
||||
key_entry_t *tmp_key;
|
||||
keymap_t *current;
|
||||
#ifdef DEBUG
|
||||
int k;
|
||||
int k, length;
|
||||
#endif
|
||||
|
||||
/* init the inkey state variable */
|
||||
|
@ -418,46 +514,17 @@ __init_getch(SCREEN *screen)
|
|||
limit = 1023;
|
||||
if (t_getstr(screen->cursesi_genbuf, tc[i].name,
|
||||
&p, &limit) != NULL) {
|
||||
current = screen->base_keymap; /* always start with
|
||||
* base keymap. */
|
||||
length = (int) strlen(entry);
|
||||
#ifdef DEBUG
|
||||
__CTRACE("Processing termcap entry %s, sequence ",
|
||||
tc[i].name);
|
||||
length = (int) strlen(entry);
|
||||
for (k = 0; k <= length -1; k++)
|
||||
__CTRACE("%s", unctrl(entry[k]));
|
||||
__CTRACE("\n");
|
||||
#endif
|
||||
for (j = 0; j < length - 1; j++) {
|
||||
/* add the entry to the struct */
|
||||
tmp_key = add_new_key(current,
|
||||
entry[j],
|
||||
KEYMAP_MULTI, 0);
|
||||
|
||||
/* index into the key array - it's
|
||||
clearer if we stash this */
|
||||
key_ent = current->mapping[
|
||||
(unsigned char) entry[j]];
|
||||
|
||||
current->key[key_ent] = tmp_key;
|
||||
|
||||
/* next key uses this map... */
|
||||
current = current->key[key_ent]->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.
|
||||
*/
|
||||
tmp_key = add_new_key(current,
|
||||
entry[length - 1],
|
||||
KEYMAP_LEAF,
|
||||
tc[i].symbol);
|
||||
current->key[
|
||||
current->mapping[(int)entry[length - 1]]] =
|
||||
tmp_key;
|
||||
add_key_sequence(screen, entry, tc[i].symbol);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,7 +548,7 @@ new_keymap(void)
|
|||
/* Initialise the new map */
|
||||
new_map->count = 0;
|
||||
for (i = 0; i < MAX_CHAR; i++) {
|
||||
new_map->mapping[i] = -1; /* no mapping for char */
|
||||
new_map->mapping[i] = MAPPING_UNUSED; /* no mapping for char */
|
||||
}
|
||||
|
||||
/* key array will be allocated when first key is added */
|
||||
|
@ -525,7 +592,7 @@ wchar_t
|
|||
inkey(int to, int delay)
|
||||
{
|
||||
wchar_t k;
|
||||
int c;
|
||||
int c, mapping;
|
||||
keymap_t *current = _cursesi_screen->base_keymap;
|
||||
FILE *infd = _cursesi_screen->infd;
|
||||
|
||||
|
@ -608,8 +675,14 @@ reread:
|
|||
exit(2);
|
||||
}
|
||||
|
||||
/* Check key has no special meaning and we have not timed out */
|
||||
if ((state == INKEY_TIMEOUT) || (current->mapping[k] < 0)) {
|
||||
/*
|
||||
* Check key has no special meaning and we have not
|
||||
* timed out and the key has not been disabled
|
||||
*/
|
||||
mapping = current->mapping[k];
|
||||
if (((state == INKEY_TIMEOUT) || (mapping < 0))
|
||||
|| ((current->key[mapping]->type == KEYMAP_LEAF)
|
||||
&& (current->key[mapping]->enable == FALSE))) {
|
||||
/* return the first key we know about */
|
||||
k = inbuf[start];
|
||||
|
||||
|
@ -689,6 +762,72 @@ mvwgetch(WINDOW *win, int y, int x)
|
|||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* keyok --
|
||||
* Set the enable flag for a keysym, if the flag is false then
|
||||
* getch will not return this keysym even if the matching key sequence
|
||||
* is seen.
|
||||
*/
|
||||
int
|
||||
keyok(int key_type, bool flag)
|
||||
{
|
||||
int result = ERR;
|
||||
|
||||
do_keyok(_cursesi_screen->base_keymap, key_type, flag, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_keyok --
|
||||
* Does the actual work for keyok, we need to recurse through the
|
||||
* keymaps finding the passed key symbol.
|
||||
*/
|
||||
void
|
||||
do_keyok(keymap_t *current, int key_type, bool flag, int *retval)
|
||||
{
|
||||
key_entry_t *key;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* we need to iterate over all the keys as there may be
|
||||
* multiple instances of the leaf symbol.
|
||||
*/
|
||||
for (i = 0; i < MAX_CHAR; i++) {
|
||||
if (current->mapping[i] < 0)
|
||||
continue; /* no mapping for the key, next! */
|
||||
|
||||
key = current->key[current->mapping[i]];
|
||||
|
||||
if (key->type == KEYMAP_MULTI)
|
||||
do_keyok(key->value.next, key_type, flag, retval);
|
||||
else if ((key->type == KEYMAP_LEAF)
|
||||
&& (key->value.symbol == key_type)) {
|
||||
key->enable = flag;
|
||||
*retval = OK; /* we found at least one instance, ok */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* define_key --
|
||||
* Add a custom mapping of a key sequence to key symbol.
|
||||
*
|
||||
*/
|
||||
int
|
||||
define_key(char *sequence, int symbol)
|
||||
{
|
||||
|
||||
if (symbol <= 0)
|
||||
return ERR;
|
||||
|
||||
if (sequence == NULL)
|
||||
delete_key_sequence(_cursesi_screen->base_keymap, symbol);
|
||||
else
|
||||
add_key_sequence(_cursesi_screen, sequence, symbol);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* wgetch --
|
||||
* Read in a character from the window.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# $NetBSD: shlib_version,v 1.25 2002/08/04 16:43:09 jdc Exp $
|
||||
# $NetBSD: shlib_version,v 1.26 2002/10/22 12:07:21 blymn Exp $
|
||||
# Remember to update distrib/sets/lists/base/shl.* when changing
|
||||
#
|
||||
major=5
|
||||
minor=2
|
||||
minor=3
|
||||
|
|
Loading…
Reference in New Issue