curses number pad handling
This attempts to address the issue on hardfought (as described by K2 on reddit two weeks ago) which happened after updating their terminfo database. It's based on the reported workaround of having users force their terminals to avoid "application keypad mode". The fixes entry is my guess at what is happening so could be wrong.... I don't have a numeric keypad so this is untested; it /ought to work/. NetHack's curses interface is doing it's own keypad recognition when the curses library returns a multi-char sequence rather than converting that into corresponding KEY_xxx token. Numpad keys that the interface recognizes begin with 2 char 'ESC O' when transmitted as 7-bit sequences. This adds support for SS3 (as sent by DEC Vtxxx terminals and emulators; value is single char 'M-O') for 8-bit sequences. It shouldn't break typing Alt+O but that's something else that I can't test properly. Setting nethack's 'altmeta' option and manually typing 2 char 'ESC O' still works as intended. This is curses-specific; the tty interface is completely unaffected. [However, the vms port has supported SS3 with tty for decades. :-]
This commit is contained in:
@@ -1792,6 +1792,10 @@ curses: fix an off-by-one error when deciding whether a long line on the
|
||||
bottom line of the message window can fit ">>" (curses' "--More--")
|
||||
curses: selecting a partial stack, unselecting it, and then selecting it
|
||||
normally did not reset the quantity to the whole stack
|
||||
curses: if user's terminal was set to 'application keypad mode' (DEC VTxxx
|
||||
nomenclature; set via 2 char "ESC =") and the terminfo or termcap
|
||||
entry told the terminal to send 8-bit escape sequences (via 3 char
|
||||
"ESC SPC G"), nethack wasn't recognizing number pad keys
|
||||
macOS: Xcode project was failing to build if the path to the NetHack source
|
||||
tree contained a space; the issue was within some shell script code
|
||||
contained within the project
|
||||
|
||||
@@ -32,7 +32,7 @@ static boolean modifiers_available = FALSE;
|
||||
|
||||
static int modified(int ch);
|
||||
static void update_modifiers(void);
|
||||
static int parse_escape_sequence(boolean *);
|
||||
static int parse_escape_sequence(int, boolean *);
|
||||
|
||||
int
|
||||
curses_getch(void)
|
||||
@@ -866,11 +866,12 @@ curses_convert_keys(int key)
|
||||
/* Handle arrow and keypad keys, but only when getting a command
|
||||
(or a command-like keystroke for getpos() or getdir()). */
|
||||
switch (key) {
|
||||
case M('O'): /* 8-bit version of ESC 'O' c for keypad key */
|
||||
case '\033': /* ESC or ^[ */
|
||||
/* changes ESC c to M-c or number pad key to corresponding digit
|
||||
(but we only get here via key==ESC if curses' getch() didn't
|
||||
change the latter to KEY_xyz) */
|
||||
ret = parse_escape_sequence(&numpad_esc);
|
||||
ret = parse_escape_sequence(key, &numpad_esc);
|
||||
reject = ((uchar) ret < 1 || ret > 255);
|
||||
as_is = !numpad_esc; /* don't perform phonepad inversion */
|
||||
break;
|
||||
@@ -1068,11 +1069,11 @@ curses_mouse_support(int mode) /* 0: off, 1: on, 2: alternate on */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* caller just got an input character of ESC;
|
||||
/* caller just got an input character of ESC or M-O;
|
||||
note: curses converts a lot of escape sequences to single values greater
|
||||
than 255 and those won't look like ESC to caller so won't get here */
|
||||
static int
|
||||
parse_escape_sequence(boolean *keypadnum)
|
||||
parse_escape_sequence(int key, boolean *keypadnum)
|
||||
{
|
||||
#ifndef PDCURSES
|
||||
int ret;
|
||||
@@ -1082,12 +1083,26 @@ parse_escape_sequence(boolean *keypadnum)
|
||||
timeout(10);
|
||||
ret = getch();
|
||||
|
||||
if (ret == 'O') { /* Numeric keypad */
|
||||
/* ESC O <something> */
|
||||
ret = getch();
|
||||
if (ret == 'O' || key == M('O')) { /* handle numeric keypad */
|
||||
/*
|
||||
* ESC O <pending> or M-O <something|nothing>.
|
||||
*
|
||||
* For the former, we don't have the next char yet so get it now.
|
||||
* If there isn't one, treat ESC O as if user typed M-O (which
|
||||
* is probably the case, via alt+shift+O combo sending two char
|
||||
* "ESC O").
|
||||
*
|
||||
* For the latter, it there wasn't another char then 'ret' will
|
||||
* be ERR and we'll treat the result as M-O. However, if there
|
||||
* is another char and it is O meant as two characters "M-O O"
|
||||
* we'll be fooled, but that's not a valid escape sequence so
|
||||
* don't worry about those two characters arriving together.
|
||||
*/
|
||||
if (key == '\033')
|
||||
ret = getch();
|
||||
|
||||
if (ret == ERR) {
|
||||
ret = 'O'; /* there was no third char; treat as M-O below */
|
||||
ret = 'O'; /* there was no additional char; treat as M-O below */
|
||||
} else if (ret >= 112 && ret <= 121) { /* 'p'..'y' */
|
||||
*keypadnum = TRUE; /* convert 'p'..'y' to '0'..'9' below */
|
||||
}
|
||||
@@ -1106,6 +1121,7 @@ parse_escape_sequence(boolean *keypadnum)
|
||||
|
||||
return ret;
|
||||
#else
|
||||
nhUse(key);
|
||||
nhUse(keypadnum);
|
||||
return '\033';
|
||||
#endif /* !PDCURSES */
|
||||
|
||||
Reference in New Issue
Block a user