From 0f39109d6bb4ed14b51164791621620cc6b5d461 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Sat, 4 Apr 2026 13:48:45 +0200 Subject: Curses: handle window resizes when blocking in `^T` and don't return function keys * There was a logic error in teco_interface_getch() that caused Curses function key codes to be returned directly. These codes however are useless to macro authors and can be confused with codepoints. You cannot report function keys in the same "namespace" along with Unicode codepoints. They are now filtered out. * Also make sure that Backspace and Return are reported as 8 and 10 respectively in all Curses variants. All control codes reported by Curses are passed down unmodified - in contrast to the command-line input handling. I.e. 13 is not normalized to 10. * PDCursesMod/WinGUI may return bogus key presses, that also have to be filtered out as we already did in the main input handling. A function teco_interface_check_key() has been introduced. * NOTE: teco_interface_blocking_getch() already makes sure that recovery files are dumped even when blocking in `^T`. --- src/interface-curses/interface.c | 75 ++++++++++++++++++++++++++++------------ src/interface-gtk/interface.c | 1 + 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c index 45821f9..b49540b 100644 --- a/src/interface-curses/interface.c +++ b/src/interface-curses/interface.c @@ -137,6 +137,7 @@ teco_console_ctrl_handler(DWORD type) static gint teco_xterm_version(void) G_GNUC_UNUSED; static gint teco_interface_blocking_getch(void); +static inline gboolean teco_interface_check_key(gint key); /** * Get bright variant of one of the 8 standard @@ -1004,15 +1005,30 @@ teco_interface_getch(gboolean widechar) gint32 cp; do { - cp = teco_interface_blocking_getch(); - if (cp == TECO_CTL_KEY('C')) - teco_interrupted = TRUE; - if (cp == TECO_CTL_KEY('C') || cp == TECO_CTL_KEY('D')) { - cp = -1; - break; - } - if (cp < 0 || cp > 0xFF) - continue; + do { + cp = teco_interface_blocking_getch(); + switch (cp) { +#ifdef KEY_RESIZE + case KEY_RESIZE: + teco_interface_resize_all_windows(); + teco_interface_refresh(FALSE); + /* cursor was moved by the resize */ + wmove(teco_interface.msg_window, 0, 0); + wrefresh(teco_interface.msg_window); + break; +#endif + case KEY_BACKSPACE: + return TECO_CTL_KEY('H'); + case KEY_ENTER: + return '\n'; + case TECO_CTL_KEY('C'): + teco_interrupted = TRUE; + /* fall through */ + case TECO_CTL_KEY('D'): + /* emulates EOF on stdin */ + return -1; + } + } while (cp < 0 || cp > 0xFF || !teco_interface_check_key(cp)); if (!widechar || !cp) break; @@ -2122,6 +2138,31 @@ teco_interface_blocking_getch(void) return key; } +#ifdef __PDCURSES__ + +/* + * Especially PDCurses/WinGUI likes to report two keypresses, + * e.g. for CTRL+Shift+6 (CTRL+^). + * Make sure we don't filter out AltGr, which may be reported as CTRL+ALT. + */ +static inline gboolean +teco_interface_check_key(gint key) +{ + return (PDC_get_key_modifiers() & + (PDC_KEY_MODIFIER_CONTROL | PDC_KEY_MODIFIER_ALT)) != PDC_KEY_MODIFIER_CONTROL || + TECO_IS_CTL(key); +} + +#else /* __PDCURSES__ */ + +static inline gboolean +teco_interface_check_key(gint key) +{ + return TRUE; +} + +#endif + /** * One iteration of the event loop. * @@ -2227,22 +2268,10 @@ teco_interface_event_loop_iter(void) * Control keys and keys with printable representation */ default: - if (key > 0xFF) - /* unhandled function key */ + if (key > 0xFF || !teco_interface_check_key(key)) + /* unhandled function key or bogus key press */ return; -#ifdef __PDCURSES__ - /* - * Especially PDCurses/WinGUI likes to report two keypresses, - * e.g. for CTRL+Shift+6 (CTRL+^). - * Make sure we don't filter out AltGr, which may be reported as CTRL+ALT. - */ - if ((PDC_get_key_modifiers() & - (PDC_KEY_MODIFIER_CONTROL | PDC_KEY_MODIFIER_ALT)) == PDC_KEY_MODIFIER_CONTROL && - !TECO_IS_CTL(key)) - return; -#endif - /* * NOTE: There's also wget_wch(), but it requires * a widechar version of Curses. diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c index 08ccf5d..f88813b 100644 --- a/src/interface-gtk/interface.c +++ b/src/interface-gtk/interface.c @@ -479,6 +479,7 @@ teco_interface_getch_input_cb(GtkWidget *widget, GdkEvent *event, gpointer user_ teco_interrupted = TRUE; /* fall through */ case TECO_CTL_KEY('D'): + /* emulates EOF on stdin */ *cp = -1; } break; -- cgit v1.2.3