From b13f3d079b66f25d26179185c65d40b348b4b570 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 23 Oct 2021 11:04:53 +0100 Subject: [PATCH] New function-key mode similar to modern xterm. This is the same as the previous FUNKY_XTERM mode if you don't press any modifier keys, but now Shift or Ctrl or Alt with function keys adds an extra bitmap parameter. The bitmaps are the same as the ones used by the new SHARROW_BITMAP arrow key mode. --- config.c | 12 +++++++++--- doc/config.but | 9 +++++++++ putty.h | 5 +++-- terminal/terminal.c | 34 ++++++++++++++++++++++++++++------ unix/window.c | 7 ++++++- windows/window.c | 6 +++++- 6 files changed, 60 insertions(+), 13 deletions(-) diff --git a/config.c b/config.c index dd39862d..e7597831 100644 --- a/config.c +++ b/config.c @@ -2010,12 +2010,18 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_bool_handler, I(CONF_rxvt_homeend), "Standard", I(false), "rxvt", I(true), NULL); - ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3, + ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 4, HELPCTX(keyboard_funkeys), conf_radiobutton_handler, I(CONF_funky_type), - "ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2), - "VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL); + "ESC[n~", I(FUNKY_TILDE), + "Linux", I(FUNKY_LINUX), + "Xterm R6", I(FUNKY_XTERM), + "VT400", I(FUNKY_VT400), + "VT100+", I(FUNKY_VT100P), + "SCO", I(FUNKY_SCO), + "Xterm 216+", I(FUNKY_XTERM_216), + NULL); ctrl_radiobuttons(s, "Shift/Ctrl/Alt with the arrow keys", 'w', 2, HELPCTX(keyboard_sharrow), conf_radiobutton_handler, diff --git a/doc/config.but b/doc/config.but index a6a14ce9..df935388 100644 --- a/doc/config.but +++ b/doc/config.but @@ -596,6 +596,15 @@ through to \c{ESC [j}. With control they generate \c{ESC [k} through to \c{ESC [v}, and with shift and control together they generate \c{ESC [w} through to \c{ESC [\{}. +\b In \I{xterm}Xterm 216 mode, the unshifted function keys behave the +same as Xterm R6 mode. But pressing a function key together with Shift +or Alt or Ctrl generates a different sequence containing an extra +numeric parameter of the form (1 for Shift) + (2 for Alt) + (4 for +Ctrl) + 1. For F1-F4, the basic sequences like \c{ESC OP} become +\cw{ESC [1;}\e{bitmap}\cw{P} and similar; for F5 and above, +\cw{ESC[}\e{index}\cw{~} becomes +\cw{ESC[}\e{index}\cw{;}\e{bitmap}\cw{~}. + If you don't know what any of this means, you probably don't need to fiddle with it. diff --git a/putty.h b/putty.h index 1719e8db..ff679752 100644 --- a/putty.h +++ b/putty.h @@ -530,7 +530,8 @@ enum { FUNKY_XTERM, FUNKY_VT400, FUNKY_VT100P, - FUNKY_SCO + FUNKY_SCO, + FUNKY_XTERM_216 }; enum { @@ -1947,7 +1948,7 @@ typedef enum SmallKeypadKey { int format_arrow_key(char *buf, Terminal *term, int xkey, bool shift, bool ctrl, bool alt, bool *consumed_alt); int format_function_key(char *buf, Terminal *term, int key_number, - bool shift, bool ctrl); + bool shift, bool ctrl, bool alt, bool *consumed_alt); int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key); int format_numeric_keypad_key(char *buf, Terminal *term, char key, bool shift, bool ctrl); diff --git a/terminal/terminal.c b/terminal/terminal.c index dc12755c..424683dc 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -7301,7 +7301,7 @@ int format_arrow_key(char *buf, Terminal *term, int xkey, } int format_function_key(char *buf, Terminal *term, int key_number, - bool shift, bool ctrl) + bool shift, bool ctrl, bool alt, bool *consumed_alt) { char *p = buf; @@ -7314,7 +7314,14 @@ int format_function_key(char *buf, Terminal *term, int key_number, assert(key_number > 0); assert(key_number < lenof(key_number_to_tilde_code)); - int index = (shift && key_number <= 10) ? key_number + 10 : key_number; + int index = key_number; + if (term->funky_type != FUNKY_XTERM_216) { + if (shift && index <= 10) { + shift = false; + index += 10; + } + } + int code = key_number_to_tilde_code[index]; if (term->funky_type == FUNKY_SCO) { @@ -7338,13 +7345,28 @@ int format_function_key(char *buf, Terminal *term, int key_number, p += sprintf(p, "\x1BO%c", code + 'P' - 11 - offt); } else if (term->funky_type == FUNKY_LINUX && code >= 11 && code <= 15) { p += sprintf(p, "\x1B[[%c", code + 'A' - 11); - } else if (term->funky_type == FUNKY_XTERM && code >= 11 && code <= 14) { + } else if ((term->funky_type == FUNKY_XTERM || + term->funky_type == FUNKY_XTERM_216) && + code >= 11 && code <= 14) { if (term->vt52_mode) p += sprintf(p, "\x1B%c", code + 'P' - 11); - else - p += sprintf(p, "\x1BO%c", code + 'P' - 11); + else { + int bitmap = 0; + if (term->funky_type == FUNKY_XTERM_216) + bitmap = shift_bitmap(shift, ctrl, alt, consumed_alt); + if (bitmap) + p += sprintf(p, "\x1B[1;%d%c", bitmap, code + 'P' - 11); + else + p += sprintf(p, "\x1BO%c", code + 'P' - 11); + } } else { - p += sprintf(p, "\x1B[%d~", code); + int bitmap = 0; + if (term->funky_type == FUNKY_XTERM_216) + bitmap = shift_bitmap(shift, ctrl, alt, consumed_alt); + if (bitmap) + p += sprintf(p, "\x1B[%d;%d~", code, bitmap); + else + p += sprintf(p, "\x1B[%d~", code); } return p - buf; diff --git a/unix/window.c b/unix/window.c index 73ff5760..8740bc50 100644 --- a/unix/window.c +++ b/unix/window.c @@ -1831,9 +1831,14 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) case GDK_KEY_F19: fkey_number = 19; goto numbered_function_key; case GDK_KEY_F20: fkey_number = 20; goto numbered_function_key; numbered_function_key: + consumed_meta_key = false; end = 1 + format_function_key(output+1, inst->term, fkey_number, event->state & GDK_SHIFT_MASK, - event->state & GDK_CONTROL_MASK); + event->state & GDK_CONTROL_MASK, + event->state & inst->meta_mod_mask, + &consumed_meta_key); + if (consumed_meta_key) + start = 1; /* supersedes the usual prefixing of Esc */ #ifdef KEY_EVENT_DIAGNOSTICS debug(" - function key F%d", fkey_number); #endif diff --git a/windows/window.c b/windows/window.c index a5bad374..2f7cb274 100644 --- a/windows/window.c +++ b/windows/window.c @@ -4512,8 +4512,12 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, case VK_F19: fkey_number = 19; goto numbered_function_key; case VK_F20: fkey_number = 20; goto numbered_function_key; numbered_function_key: + consumed_alt = false; p += format_function_key((char *)p, term, fkey_number, - shift_state & 1, shift_state & 2); + shift_state & 1, shift_state & 2, + left_alt, &consumed_alt); + if (consumed_alt) + left_alt = false; /* supersedes the usual prefixing of Esc */ return p - output; SmallKeypadKey sk_key;