/*+++*
* title: fkeys.c
* abstract: almost terminal-independent function key support for JOVE
* author: T.R.Hageman, AZG, Groningen
* created: august 1988
* modified: 3-Oct-88 [TRH] add delayed prompt support
* 1-Dec-88, rename getkey() to getchar()
* 2-Apr-89, complete revision of recognizer algorithm
* tuned to fast recognition of first character.
* Replaced delayed display kludge with timeout.
* 1-Jul-89, fix bug with 8-bit characters which prevented
* them to be stored in macros.
* 28-Jul-89, remove K0,K6-K9 (not supported by terminfo)
* add kb(backspace), kB(backtab) k;(f10)
* PU,PD,HM,EN(XENIX keynames)
* 12-Jan-90, some cleanups; improve DEBUG mode.
* 5-Feb-90, add "extended" special keys (AIX);
* add `keycode remap' for some keys;
* match states instead of characters now.
* 28-Feb-90, put error messages in buffer.
* 16-Dec-90, add kY(Undo).
* 10-Jan-91, implement KEYALIAS for weird capability names.
* 9-Feb-91, fix bug in KEYALIAS
* 15-Feb-91, "use-function-keys" now defaults to "on";
* new variable "keypad" controls appl/numeric keypad.
* 25-Mar-92, revise KEYALIAS; systems to support aliases for
* can now be specified as a compilation option.
* 13-Apr-92, update KEYALIAS with new termcap keydefs;
* write DEBUG info to JOVE buffer.
* description:
* FKeyInit() builds a recognizer for all function keys that can be
* defined in the termcap entry. The available keys are mapped to
* characters within the range FK_BASE..FK_BASE+NFKEYS.
* The keymap command tables are extended to support this range.
* The actual code assigned to a key is not fixed, but rather depends
* on the available key definitions.
* However this is transparent for the user since the function keys
* can be assigned to by symbolic names of the form "^:xx",
* where "xx" is the 'termcap' key name (see extend.c(addgetc) and fmt.c).
*
* getchar() supersedes the original which is now named rawchar()
* (see tty.c). It parses the "raw" input sequence to intercept
* the function keys. rawchar() expects a parameter 'time_out'
* which indicates whether it should time out.
*
* Finally the boolean variable "use-function-keys" (UseFkeys)
* is available to enable/disable function key recognition.
* You may want to disable it if you have a terminal that 'eats'
* some standard emacs functions (like tviXXX arrow keys that send
* ^H ^J ^K ^L)
*---*/
#include "tune.h" /* to allow definition of debug flags there. */
#ifdef DEBUG /* General debug flag, turn on file-specific flag. */
# ifndef FKEYS_DEBUG
# define FKEYS_DEBUG 1
# endif
#else
# if FKEYS_DEBUG /* File-specific debug flag, turn on general flag. */
# define DEBUG
# endif
#endif
#include "jove.h"
#ifdef FUNCKEYS /* the whole file */
RCS("$Id: fkeys.c,v 14.32.0.12 1994/06/24 17:55:03 tom Exp tom $")
DEF_INT( "keypad", UseKeyPad, V_BOOL|V_TTY_RESET ) = YES; _IF(def FUNCKEYS)
#ifdef TERMCAP /* the whole file */
DEF_INT( "use-function-keys", UseFKeys, V_BOOL ) = YES; _IF(def FUNCKEYS)_IF(def TERMCAP)_IF(def PRIVATE)
#include "termcap.h"
#if FKEYS_DEBUG
# include "io.h"
# define DPRINTF(x) ins_str(sprint x, 0)
# define KEYID(i) (((char *)&FKeyMap[i])[0]&0177), (((char *)&FKeyMap[i])[1]&0177)
# define STATE(p) (int)((p) - FKeyState)
#else
# define DPRINTF(x)
#endif
/* Where to start numbering function keys. */
#ifndef FK_BASE
# define FK_BASE 0200
#endif
/*
* KEYALIAS
* stuff to map system-dependent obscure termcap keynames to JOVEs standard.
*/
#define KEY_SCO (1<<0)
#define KEY_AIX (1<<1)
#define KEY_EXT (1<<2)
#define KEY_SUN KEY_EXT /* obsolete name */
#ifndef KEYALIAS
/* provide some defaults */
# if (sun || __sun__)
# define KEYALIAS KEY_SUN
# endif
# if (aiws || __aiws__ || aix || __aix__)
# define KEYALIAS KEY_AIX
# endif
# ifdef SCO_SYSV
# define KEYALIAS KEY_SCO
# endif
# ifndef KEYALIAS
# ifndef TINY
# define KEYALIAS KEY_EXT
# else
# define KEYALIAS 0
# endif
# endif
#else
# if (2 * KEYALIAS -1 == 2 * -1) /* defined, but empty */
# define KEYALIAS KEY_EXT /* to generate a warning */
# endif
#endif
#if KEYALIAS
# define ALIAS '\200'
# define AliasTo ALIAS |
# define Aliased(cp) (((char *)(cp))[0] & ALIAS)
# define UnAlias(cp) (((char *)(cp))[0] &= ~ALIAS)
#
# define SHIFT ALIAS
# define shifted | SHIFT
# define Shifted(cp) (((char *)(cp))[1] & SHIFT)
# define UnShift(cp) (((char *)(cp))[1] &= ~SHIFT)
#
# define FK_SHIFT 01000
#endif
#ifndef SIZEOF_SHORT /* assume we can get away with dirty short * casts */
# define SIZEOF_SHORT 2
#endif
#define KEYLEN 5 /* max. average key sequence length */
#if (MAXSTATE > 256 || MAXSTATE < -256) /* no checks if negative */
# define Index short
#else
# define Index char
# if !MAXSTATE /* includes !defined(MAXSTATE) */
# if (!__CHAR_UNSIGNED__) && (KEYALIAS <= KEY_SCO)
# define MAXSTATE -128
# else
# define MAXSTATE -256
# endif
# endif
#endif
#if (!__CHAR_UNSIGNED__) && (128 < MAXSTATE && MAXSTATE <= 256) || (-256 <= MAXSTATE && MAXSTATE < -128)
# define UI _UC_
#else
# define UI
#endif
typedef struct {
Index fk_prev; /* previous state to be matched */
Index fk_alt; /* next state taken if no match */
short fk_final; /* character to translate to */
} FKEY;
/*
* The next table is indexed by the raw input character to retrieve the
* index of the head of its state list. Initial states are marked with
* a NIL fk_prevc field and are always at the head of the list.
* Index NIL means no state is available.
* [ for reasons of space efficiency this vector is overlaid with the
* keyname scan string, which isn't needed after the initialisation ]
* The scan string contains a list of entries "kx" or "kx=c",
* where the latter form requests a `keycode remap' to code `c'.
#if KEYALIAS
* or "kx" AliasTo "ky", which internally renames real capability `kx' to `ky'.
# if KEYSHIFT
* or "ka" AliasTo "kb" shifted, which also maps key to `MetaKey key'.
* a `shifted' key should be defined AFTER its unshifted equivalent
* in this table.
# endif
#endif
*/
#if (KEYALIAS > KEY_SCO)
private Index FKeyVec[256];
private const char possible[] =
#else
# define FKeyVec ((Index *) possible)
private char possible[256 * sizeof(Index)] =
#endif
{
/* arrow keys */
'k','u', 'k','d', 'k','r', 'k','l',
/* function keys 0-10 */
'k','0', 'k','1', 'k','2', 'k','3', 'k','4', 'k','5',
'k','6', 'k','7', 'k','8', 'k','9', 'k',';',
/* 3x3 keypad keys */
'K','1', 'K','2', 'K','3', 'K','4', 'K','5',
/* special keys */
'k','a', 'k','A', 'k','b','=','\b', 'k','C', 'k','D', 'k','E',
'k','F', 'k','h', 'k','H', 'k','I', 'k','L', 'k','M',
'k','N', 'k','P', 'k','R', 'k','S', 'k','T', 'k','t',
/* extra special keys */
'k','B', 'k','c', 'k','i', 'k','n','=','\r', 'k','o','=','\t',
'k','p', 'k','q', 'k','Q', 'k','U', 'k','v', 'k','V',
'k','W', 'k','Y', 'k','z', 'k','Z',
/* extra function keys 11-45 */
'F','1', 'F','2', 'F','3', 'F','4', 'F','5', 'F','6',
'F','7', 'F','8', 'F','9', 'F','0', 'F','A', 'F','B',
'F','C', 'F','D', 'F','E', 'F','F', 'F','G', 'F','H',
'F','I', 'F','J', 'F','K', 'F','L', 'F','M', 'F','N',
'F','O', 'F','P', 'F','Q', 'F','R', 'F','S', 'F','T',
'F','U', 'F','V', 'F','W', 'F','X', 'F','Y', 'F','Z',
/* still more function keys 46-63 */
#if (NFKEYS == 128)
'F','a', 'F','b', 'F','c', 'F','d', 'F','e', 'F','f',
'F','g', 'F','h', 'F','i', 'F','j', 'F','k', 'F','l',
'F','m', 'F','n', 'F','o', 'F','p', 'F','q', 'F','r',
#endif
#if (KEYALIAS & KEY_EXT)
'@','1', AliasTo 'K','B', /* beg(inning) */
'@','2', AliasTo 'k','X', /* cancel */
'@','3', AliasTo 'k','x', /* close */
'@','4', AliasTo 'k','c', /* command */
'@','5', AliasTo 'K','C', /* copy */
'@','6', AliasTo 'K','c', /* create */
'@','7', AliasTo 'k','H', /* end */
'@','8', '=','\r', /* enter */
'@','9', AliasTo 'k','Q', /* exit (quit) */
'@','0', AliasTo 'k','f', /* find */
'%','1', AliasTo 'k','q', /* help */
'%','2', AliasTo 'k','k', /* mark */
'%','3', AliasTo 'K','M', /* message */
'%','4', AliasTo 'k','m', /* move */
'%','5', AliasTo 'k','v', /* next */
'%','6', AliasTo 'k','O', /* open */
'%','7', AliasTo 'K','O', /* options */
'%','8', AliasTo 'k','V', /* previous */
'%','9', AliasTo 'K','P', /* print */
'%','0', AliasTo 'k','i', /* redo */
'&','1', AliasTo 'K','f', /* reference */
'&','2', AliasTo 'K','F', /* refresh */
'&','3', AliasTo 'K','R', /* replace */
'&','4', AliasTo 'K','r', /* restart */
'&','5', AliasTo 'k','g', /* resume (go) */
'&','6', AliasTo 'k','s', /* save */
'&','7', AliasTo 'k','G', /* suspend (!go) */
'&','8', AliasTo 'k','Y', /* undo */
# define WANT_KEYSHIFT
'&','9', AliasTo 'k','B' shifted, /* shift-begin */
'&','0', AliasTo 'k','X' shifted, /* shift-cancel */
'*','1', AliasTo 'k','c' shifted, /* shift-command */
'*','2', AliasTo 'K','C' shifted, /* shift-copy */
'*','3', AliasTo 'K','c' shifted, /* shift-create */
'*','4', AliasTo 'k','D' shifted, /* shift-delete-character */
'*','5', AliasTo 'k','L' shifted, /* shift-delete-line */
'*','6', AliasTo 'k','U', /* select */
'*','7', AliasTo 'k','H' shifted, /* shift-end */
'*','8', AliasTo 'k','E' shifted, /* shift-clear-to-eol */
'*','9', AliasTo 'k','Q' shifted, /* shift-exit */
'*','0', AliasTo 'k','f' shifted, /* shift-find */
'#','1', AliasTo 'k','q' shifted, /* shift-help */
'#','2', AliasTo 'k','h' shifted, /* shift-home */
'#','3', AliasTo 'k','I' shifted, /* shift-insert */
'#','4', AliasTo 'k','z', /* shift-left-arrow (word left) */
'%','a', AliasTo 'K','M' shifted, /* shift-message */
'%','b', AliasTo 'K','m' shifted, /* shift-move */
'%','c', AliasTo 'k','v' shifted, /* shift-next */
'%','d', AliasTo 'K','O' shifted, /* shift-options */
'%','e', AliasTo 'k','V' shifted, /* shift-previous */
'%','f', AliasTo 'K','P' shifted, /* shift-print */
'%','g', AliasTo 'k','i' shifted, /* shift-redo */
'%','h', AliasTo 'K','R' shifted, /* shift-replace */
'%','i', AliasTo 'k','Z', /* shift-right-arrow (word right) */
'%','j', AliasTo 'k','g' shifted, /* shift-resume */
'!','1', AliasTo 'k','s' shifted, /* shift-save */
'!','2', AliasTo 'k','G' shifted, /* shift-suspend */
'!','3', AliasTo 'k','Y' shifted, /* shift-undo */
#endif /* (KEYALIAS & KEY_EXT) */
#if (KEYALIAS & KEY_SCO)
/*
* PU,PD,HM,EN are XENIX/SCO termcap specific; we internally alias these
* to their "official" termcap equivalents kP,kN,kh,kH so as to keep
* our .joverc portable.
*/
'P','U', AliasTo 'k','P',
'P','D', AliasTo 'k','N',
'H','M', AliasTo 'k','h',
'E','N', AliasTo 'k','H',
#endif /* (KEYALIAS & KEY_SCO) */
#if (KEYALIAS & KEY_AIX)
'k','w', AliasTo 'k','H',
'k','<', AliasTo 'F','1',
'k','>', AliasTo 'F','2',
'k','!', AliasTo 'F','3',
'k','@', AliasTo 'F','4',
'k','#', AliasTo 'F','5',
'k','$', AliasTo 'F','6',
'k','%', AliasTo 'F','7',
'k','^', AliasTo 'F','8',
'k','&', AliasTo 'F','9',
'k','*', AliasTo 'F','A',
'k','(', AliasTo 'F','B',
'k',')', AliasTo 'F','C',
'k','-', AliasTo 'F','D',
'k','_', AliasTo 'F','E',
'k','+', AliasTo 'F','F',
'k',',', AliasTo 'F','G',
'k',':', AliasTo 'F','H',
'k','?', AliasTo 'F','I',
'k','[', AliasTo 'F','J',
'k',']', AliasTo 'F','K',
'k','{', AliasTo 'F','L',
'k','}', AliasTo 'F','M',
'k','|', AliasTo 'F','N',
'k','~', AliasTo 'F','O',
'k','/', AliasTo 'F','P',
'S','1', AliasTo 'F','Q',
'S','2', AliasTo 'F','R',
'S','3', AliasTo 'F','S',
'S','4', AliasTo 'F','T',
'S','5', AliasTo 'F','U',
'S','6', AliasTo 'F','V',
'S','7', AliasTo 'F','W',
'S','8', AliasTo 'F','X',
'S','9', AliasTo 'F','Y',
'S','A', AliasTo 'F','Z',
#endif /* (KEYALIAS & KEY_AIX) */
'\0'
};
#ifndef KEYSHIFT
# ifdef WANT_KEYSHIFT
# define KEYSHIFT 1
# endif
#else
# if (2 * KEYSHIFT -1 == 2 * -1) /* defined but empty */
# define KEYSHIFT 1
# endif
#endif
private FKEY *FKeyState; /* the states */
short FKeyMap[NFKEYS]; /* IDs of actual function keys */
public int
getchar()
{
/* buffer must be big enough to hold longest function key sequence */
# define RINGSIZE 10
static short Ringbuf[RINGSIZE];
static short *head = Ringbuf;
static int navail = 0;
/* yet another peek buffer. Sigh... */
static int peekc = -1;
register short *p = head;
register FKEY *state;
register int c;
register int nleft;
register Index prev;
if ((c = peekc) >= 0) {
peekc = -1;
return c;
}
/* PRE: head not at end of ring buffer */
if (nleft = navail) {
--navail;
c = *p++;
if (p == &Ringbuf[RINGSIZE])
p -= RINGSIZE; /* wraparound */
head = p;
} else {
c = rawchar(NO);
}
/*
* If function key recognition is disabled, or no state exists for
* the current input character, or it is not a valid initial
* state, we are ready very soon.
*/
if (True(UseFKeys) && (prev = FKeyVec[c]) &&
!(state = &FKeyState[UI(prev)])->fk_prev) {
/*
* If it is a final state we are ready now.
*/
if (state->fk_final) {
# if notyet
/* Return untranslated character if we do not allow
single-char function key sequences. This is so
that ordinary JOVE bindings are not overridden. */
/* {{Should we introduce a new variable for this?
If not, we must either change the type of
`UseFKeys', or allow assignment of arbitrary
integers to V_BOOL variables.}} */
if (UseFKeys > 1 && c < 0200)
return c;
# endif
# if KEYSHIFT
goto final_state;
# else
return state->fk_final;
# endif
}
{
register int savc = c; /* remember this char */
# if FKEYS_DEBUG
register Buffer *savb = curbuf;
SetBuf(do_select((Window *)0, "*DEBUG*"));
SETBUFTYPE(curbuf, B_SCRATCH);
ToLast();
# endif
do {
DPRINTF(("(%d)", UI(prev)));
if (--nleft > 0) {
c = *p++;
} else {
if ((c = rawchar(YES)) < 0)
break; /* timeout */
*p++ = c;
++navail;
}
if (p == &Ringbuf[RINGSIZE])
p -= RINGSIZE; /* wraparound */
if (c = UI(FKeyVec[c])) do {
state = &FKeyState[c];
if (state->fk_prev == prev) { /* match */
if (!state->fk_final)
break;
/*
* If we get here we recognized a key
* sequence. Update the state of our
* character buffer and return result.
*/
DPRINTF(("(%d)[match: %s%p]\n", c,
(state->fk_final & FK_SHIFT) ?
"*" : NullStr,
state->fk_final));
head = p;
navail = (--nleft > 0) ? nleft : 0;
# if FKEYS_DEBUG
SetBuf(savb);
# endif
# if KEYSHIFT
final_state:
if ((c = state->fk_final) & FK_SHIFT) {
peekc = _UC_(c);
if (!(c = MetaKey))
c = ESC;
}
return c;
# else
return state->fk_final;
# endif
}
} while (c = UI(state->fk_alt));
} while (prev = c);
DPRINTF(((navail == 0) ? "\n" : "[%d available]\n", navail));
# if FKEYS_DEBUG
SetBuf(savb);
# endif
c = savc;
}
}
/*
* Handle 8-bit characters here (instead of in rawchar).
* {{this used to remember next character by Ungetc() but that
* screwed up keyboard macro definition. We can't push it back on
* our ring buffer either since 8th bit (if still on) would be
* re-interpreted the next time}}
*/
if (c & 0200) {
if (MetaKey) {
# ifdef META_FKEYS
/*
* This will recognize key sequences with the Meta-bit
* ORed into its first (and only the first) character,
* and translate it into .
* Maybe some terminals are capable of doing that.
*/
if (p == Ringbuf) /* wraparound */
p += RINGSIZE;
*--p = (c &= 0177); /* push back into ring buffer */
head = p;
navail++;
# else
peekc = (c &= 0177);
# endif
return MetaKey;
} else {
peekc = c; /* cheat to get literal 8-bit char */
return QuoteChar;
}
}
return c;
} /* getchar */
public void
FKeyInit() /* to be called (once) when termcap is still available */
{
char *keydefs[NFKEYS+1];
char keybuf[(NFKEYS+1)*(KEYLEN+1)];
int nkeys = 0;
int err = 0;
/* select a buffer where to put our eventual error messages */
SetBuf(do_select((Window *)0, "*INIT errors*"));
# define Error(x) (++err, ins_str(x, NO))
/* get key definitions from termcap */
{
#ifdef FKeyVec /* overlays possible[], so should be cleared */
# define CLEAR(x) x = 0
#else /* no overlay, const possible[], so don't touch */
# define CLEAR(x) x
#endif
#if (SIZEOF_SHORT == 2) /* do some dastardly dirty casts and hope we can get away with it... */
# define SCAN_T short
# define DO(x) x
# define GET(s) (*s)
#else /* ... but provide a way out if we don't */
# define SCAN_T char
# define DO(x) x, x
union { short i; char c[2]; } u;
# define GET(s) (u.i = 0, u.c[0] = s[0], u.c[1] = s[1], u.i)
#endif
register SCAN_T *s = (SCAN_T *) possible;
register short *mp = FKeyMap;
register char **vp = keydefs;
char *p = keybuf;
do {
#if KEYALIAS
if (!Aliased(s))
#endif
if (*vp = tgetstr((char *) s, &p)) {
if (mp == &FKeyMap[NFKEYS]) {
Error(sprint("FKeyInit: can't handle more than %d keydefs\n", NFKEYS));
break;
}
/* key remap kludge: store remap sequence in FKeyMap */
if (((char *) s)[2] == '='
#if KEYALIAS
|| Aliased(&((char *) s)[2])
#endif
) {
DO(CLEAR(*s++));
}
*mp++ = GET(s); /* record key name */
#if FKEYS_DEBUG
{
register char *t = *vp;
DPRINTF(("%2d: %s%c%c @%04X ", nkeys,
Shifted(s) ? "*" : "", KEYID(nkeys), (long)t));
while (*t)
DPRINTF(("\t%02x %p", *t, *t)), t++;
DPRINTF(("\n"));
}
#endif /* FKEYS_DEBUG */
*vp++;
nkeys++;
if (p > &keybuf[sizeof keybuf - KEYLEN - 2]) {
Error(("FKeyInit: buffer overflow\n"));
break;
}
}
DO(CLEAR(*s++));
} while (*(char *) s);
#ifdef FKeyVec
/* we must still clear the rest of the name table if we encountered an error. */
while (*(char *) s)
*s++ = 0;
#endif
}
DPRINTF(("FKeyInit: nkeys=%d\n", nkeys));
{
# if (0 < MAXSTATE && MAXSTATE < NFKEYS*KEYLEN)
# define NSTATES MAXSTATE
# else
# define NSTATES NFKEYS*KEYLEN
# endif
FKEY states[NSTATES + 2];
register FKEY *last = states + 1;
{
register FKEY *curr;
register char *s;
register int c;
register int ic, /* curr == &states[ic] */
il = 1; /* last == &states[il] */
register int key;
/* build state table from function key definitions */
for (key = 0; key < nkeys; key++) {
s = keydefs[key];
DPRINTF(("%s%c%c:\t", Shifted(&FKeyMap[key]) ? "*" : "", KEYID(key)));
for (last->fk_prev = 0; c = _UC_(*s++); last->fk_prev = ic) {
last->fk_alt = 0;
last->fk_final = 0;
/*
* Insert new state at the beginning of the alternates
* list for this character if the list is empty,
* or this is an initial state and this is not yet
* present.
*/
if (!(ic = UI(FKeyVec[c])) ||
((curr = &states[ic])->fk_prev && !last->fk_prev)) {
DPRINTF((ic ? "<" : "+"));
last->fk_alt = ic;
FKeyVec[c] = ic = il++;
curr = last++;
} else {
while (curr->fk_prev != last->fk_prev) {
if (!(ic = curr->fk_alt)) {
DPRINTF((">"));
curr->fk_alt = ic = il++;
curr = last++;
break;
}
curr = &states[ic];
}
}
DPRINTF(("%02x'%c'(%d)\t", c, c, (int)(curr - states)));
/* sanity checks */
#if (MAXSTATE > 0)
if (curr == &states[MAXSTATE]) {
Error(("FKeyInit: too many states\n"));
goto fail;
}
#endif
if (curr->fk_final) {
Error(sprint("FKeyInit: %p is subsequence of %p\n",
curr->fk_final, key + FK_BASE));
break;
}
}
s = (char *) &FKeyMap[key]; /* key remap kludge */
curr->fk_final = (*s++ == '=') ? *s : key + FK_BASE;
#if KEYALIAS
if (Aliased(--s)) {
# if KEYSHIFT
register short fk_shift = 0;
if (Shifted(s)) {
UnShift(s);
fk_shift = FK_SHIFT;
}
# endif
UnAlias(s);
/*
* Search keymap for its alias. If it is there, use
* its keynumber instead, and invalidate this entry.
*/
for (c = key; --c >= 0; ) {
if (FKeyMap[c] == *(short *) s) {
curr->fk_final = c + FK_BASE;
*(short *) s = 0;
break;
}
}
# if KEYSHIFT
curr->fk_final |= fk_shift;
# endif
}
#endif /* KEYALIAS */
DPRINTF(("-> %02x\n", curr->fk_final));
} /* for */
fail: ;
#if FKEYS_DEBUG
dump(states, (int)(last - (states + 1)));
err++;
#endif /* FKEYS_DEBUG */
}
/*
* Save states to more permanent location.
*/
{
register char *base = (char *)(states + 1);
register size_t siz = (size_t)((char *)last - base);
last = (FKEY *) emalloc(siz);
byte_copy(base, (char *)last, siz);
FKeyState = --last; /* adjust for base-1 indexing */
}
}
if (!err) {
kill_buf(curbuf); /* i.e. our error message buffer */
}
} /* FKeyInit */
#if FKEYS_DEBUG
private
dump(states, nstates)
FKEY *states;
int nstates;
{
register FKEY *state;
register int c, next;
int count = 0;
DPRINTF(("\n\
Char\tState\tPrevSt\tFinal\n\
----\t-----\t------\t-----\n"));
for (c = 0; c < 256; c++)
if (next = FKeyVec[c]) {
DPRINTF(("%02x %c:", c, c));
do {
state = &states[UI(next)];
count++;
DPRINTF(("\t%5d\t%5d\t%02x %c%p\n",
next,
state->fk_prev,
state->fk_final,
state->fk_final & FK_SHIFT ? '*' : ' ',
state->fk_final
));
} while (next = state->fk_alt);
}
if (count != nstates)
DPRINTF(("[state count? expected %d found %d]\n", nstates, count));
}
#endif /* FKEYS_DEBUG */
#endif /* TERMCAP */
#endif /* FUNCKEYS */
/*======================================================================
* $Log: fkeys.c,v $
* Revision 14.32.0.12 1994/06/24 17:55:03 tom
* (FKeyInit): remove redundant decl. of tgetent(), fix name of scratch buffer,
* Error: move sprint outside macro definition.
*
* Revision 14.32.0.10 1994/05/22 22:22:02 tom
* (KEYALIAS): set default to KEY_EXT for non-TINY systems.
*
* Revision 14.32 1993/07/06 00:53:07 tom
* (use-function-keys): remove V_TTY_RESET;
* (FK_BASE): new constant, replace 0200 with FK_BASE where appropriate;
* (FK_SHIFT): change from 0400 to 01000.
*
* Revision 14.31 1993/02/13 04:14:47 tom
* allow debug options to be specified in "tune.h" cf. "Local.h".
*
* Revision 14.30 1993/02/05 00:07:27 tom
* cleanup whitespace; some random optimizations; standardize DEBUG.
*
* Revision 14.28 1992/10/05 13:25:08 tom
* convert to "port{ansi,defs}.h" conventions.
*
* Revision 14.27 1992/09/21 14:54:03 tom
* replace CTL('Q') with `QuoteChar'; cleanup empty `#' directives.
*
* Revision 14.26 1992/08/26 23:56:53 tom
* PRIVATE-ized some Variable defs; add RCS directives.
*
*/