From f5d400be7537e9ede7cfcd9971958341856bfb8a Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 23 Mar 2023 11:12:34 -0700 Subject: [PATCH] fix github issue #1002 - curses screen flash Reported by jeremyhetzler: with recently revised curses interface, when dismissing a menu or prompt with ESC the screen flashed. This was caused by calling beep() when the terminal is set for 'visible bell' (of flagged as incapable of 'audible bell'); the curses library flashed the screen deliberately. We don't want that. Change the function key handling to not call beep() when an ESC is typed by itself rather than being the leading part of a multi-character escape sequence. beep() will still be called if you type an arrow key (or other function key) when nethack is expecting text input. That's what the recent change intended. This also removes an early return from parse_escape_sequence() when a number pad key generates an escape sequence. I don't have a number pad to verify that this bit works as intended. Closes #1002 --- doc/fixes3-7-0.txt | 6 +++++- win/curses/cursmisc.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 47dd71311..83463ef36 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1,4 +1,4 @@ -HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1093 $ $NHDT-Date: 1672605786 2023/01/01 20:43:06 $ +HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1139 $ $NHDT-Date: 1679595146 2023/03/23 18:12:26 $ General Fixes and Modified Features ----------------------------------- @@ -1535,6 +1535,10 @@ curses: for screen refresh, don't attempt to refresh windows that haven't been set up yet or have already been shut down curses: for raw_print() in #if PDCURSES config, don't attempt to write to message window if it isn't set up yet or has already been shut down +curses: typing ESC to cancel something issued a beep; if the terminal was set + to 'visible bell', the screen flashed; only beep when the ESC is part + of an escape sequence--other than M-c generating ESC c--and nethack + is expecting text rather than a command or direction Qt: at Xp levels above 20 with 'showexp' On, the combined status field "Level:NN/nnnnnnnn" was too big and truncated by a char at each end Qt: searching a text window for something that wasn't found and then searching diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index adc8670d0..9c9c8cd42 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -32,7 +32,7 @@ static boolean modifiers_available = FALSE; static int modified(int ch); static void update_modifiers(void); -static int parse_escape_sequence(void); +static int parse_escape_sequence(boolean *); int curses_getch(void) @@ -864,7 +864,7 @@ int curses_convert_keys(int key) { boolean reject = !gp.program_state.getting_a_command, - as_is = FALSE; + as_is = FALSE, numpad_esc; int ret = key; if (modifiers_available) @@ -877,11 +877,9 @@ curses_convert_keys(int key) /* 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(); - if (ret != '\033') { - reject = FALSE; - as_is = TRUE; /* don't perform phonepad inversion */ - } + ret = parse_escape_sequence(&numpad_esc); + reject = ((uchar) ret < 1 || ret > 255); + as_is = !numpad_esc; /* don't perform phonepad inversion */ break; case KEY_BACKSPACE: /* we can't distinguish between a separate backspace key and @@ -980,8 +978,8 @@ curses_convert_keys(int key) if (reject) { /* an arrow or function key has been pressed during text entry */ - beep(); /* not curses_nhbell() because it might end up getting - * changed to deliver a sound effect */ + curses_nhbell(); /* calls beep() which might cause unwanted screen + * refresh if terminal is set for 'visible bell' */ ret = '\033'; /* ESC */ } @@ -1074,36 +1072,38 @@ curses_mouse_support(int mode) /* 0: off, 1: on, 2: alternate on */ 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(void) +parse_escape_sequence(boolean *keypadnum) { #ifndef PDCURSES int ret; - timeout(10); + *keypadnum = FALSE; + timeout(10); ret = getch(); if (ret == 'O') { /* Numeric keypad */ /* ESC O */ ret = getch(); - if (ret >= 112 && ret <= 121) { - timeout(-1); - return ret - 112 + '0'; /* Convert to number */ - } - if (ret == ERR) - ret = 'O'; /* there was no third char; treat as ESC O below */ + if (ret == ERR) { + ret = 'O'; /* there was no third char; treat as M-O below */ + } else if (ret >= 112 && ret <= 121) { /* 'p'..'y' */ + *keypadnum = TRUE; /* convert 'p'..'y' to '0'..'9' below */ + } } - if (ret != ERR && ret <= 255) { + timeout(-1); /* reset to 'wait unlimited time for next input' */ + + if (*keypadnum) { + ret -= (112 - '0'); /* Convert c from 'ESC O c' to digit */ + } else if (ret != ERR && ret <= 255) { /* ESC ; effectively 'altmeta' behind player's back */ ret = M(ret); /* Meta key support for most terminals */ } else { ret = '\033'; /* Just an escape character */ } - timeout(-1); - return ret; #else return '\033';