diff --git a/putty.h b/putty.h index 04091afe..544e54da 100644 --- a/putty.h +++ b/putty.h @@ -1533,7 +1533,15 @@ void term_set_focus(Terminal *term, bool has_focus); char *term_get_ttymode(Terminal *term, const char *mode); int term_get_userpass_input(Terminal *term, prompts_t *p, bufchain *input); +typedef enum SmallKeypadKey { + SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN, +} SmallKeypadKey; int format_arrow_key(char *buf, Terminal *term, int xkey, bool ctrl); +int format_function_key(char *buf, Terminal *term, int key_number, + bool shift, bool ctrl); +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); /* * Exports from logging.c. diff --git a/terminal.c b/terminal.c index ae5255e4..40e130f5 100644 --- a/terminal.c +++ b/terminal.c @@ -6447,7 +6447,7 @@ int format_arrow_key(char *buf, Terminal *term, int xkey, bool ctrl) char *p = buf; if (term->vt52_mode) - p += sprintf((char *) p, "\x1B%c", xkey); + p += sprintf(p, "\x1B%c", xkey); else { bool app_flg = (term->app_cursor_keys && !term->no_applic_c); #if 0 @@ -6470,9 +6470,186 @@ int format_arrow_key(char *buf, Terminal *term, int xkey, bool ctrl) app_flg = !app_flg; if (app_flg) - p += sprintf((char *) p, "\x1BO%c", xkey); + p += sprintf(p, "\x1BO%c", xkey); else - p += sprintf((char *) p, "\x1B[%c", xkey); + p += sprintf(p, "\x1B[%c", xkey); + } + + return p - buf; +} + +int format_function_key(char *buf, Terminal *term, int key_number, + bool shift, bool ctrl) +{ + char *p = buf; + + static const int key_number_to_tilde_code[] = { + -1, /* no such key as F0 */ + 11, 12, 13, 14, 15, /*gap*/ 17, 18, 19, 20, 21, /*gap*/ + 23, 24, 25, 26, /*gap*/ 28, 29, /*gap*/ 31, 32, 33, 34, + }; + + 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 code = key_number_to_tilde_code[index]; + + if (term->funky_type == FUNKY_SCO) { + /* SCO function keys */ + static const char sco_codes[] = + "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{"; + index = (key_number >= 1 && key_number <= 12) ? key_number - 1 : 0; + if (shift) index += 12; + if (ctrl) index += 24; + p += sprintf(p, "\x1B[%c", sco_codes[index]); + } else if ((term->vt52_mode || term->funky_type == FUNKY_VT100P) && + code >= 11 && code <= 24) { + int offt = 0; + if (code > 15) + offt++; + if (code > 21) + offt++; + if (term->vt52_mode) + p += sprintf(p, "\x1B%c", code + 'P' - 11 - offt); + else + 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) { + if (term->vt52_mode) + p += sprintf(p, "\x1B%c", code + 'P' - 11); + else + p += sprintf(p, "\x1BO%c", code + 'P' - 11); + } else { + p += sprintf(p, "\x1B[%d~", code); + } + + return p - buf; +} + +int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key) +{ + char *p = buf; + + int code; + switch (key) { + case SKK_HOME: code = 1; break; + case SKK_INSERT: code = 2; break; + case SKK_DELETE: code = 3; break; + case SKK_END: code = 4; break; + case SKK_PGUP: code = 5; break; + case SKK_PGDN: code = 6; break; + default: assert(false && "bad small keypad key enum value"); + } + + /* Reorder edit keys to physical order */ + if (term->funky_type == FUNKY_VT400 && code <= 6) + code = "\0\2\1\4\5\3\6"[code]; + + if (term->vt52_mode && code > 0 && code <= 6) { + p += sprintf(p, "\x1B%c", " HLMEIG"[code]); + } else if (term->funky_type == FUNKY_SCO) { + static const char codes[] = "HL.FIG"; + if (code == 3) { + *p++ = '\x7F'; + } else { + p += sprintf(p, "\x1B[%c", codes[code-1]); + } + } else if ((code == 1 || code == 4) && term->rxvt_homeend) { + p += sprintf(p, code == 1 ? "\x1B[H" : "\x1BOw"); + } else { + p += sprintf(p, "\x1B[%d~", code); + } + + return p - buf; +} + +int format_numeric_keypad_key(char *buf, Terminal *term, char key, + bool shift, bool ctrl) +{ + char *p = buf; + bool app_keypad = (term->app_keypad_keys && !term->no_applic_k); + + if (term->nethack_keypad && (key >= '1' && key <= '9')) { + static const char nh_base[] = "bjnh.lyku"; + char c = nh_base[key - '1']; + if (ctrl && c != '.') + c &= 0x1F; + else if (shift && c != '.') + c += 'A'-'a'; + *p++ = c; + } else { + int xkey = 0; + + if (term->funky_type == FUNKY_VT400 || + (term->funky_type <= FUNKY_LINUX && app_keypad)) { + switch (key) { + case 'G': xkey = 'P'; break; + case '/': xkey = 'Q'; break; + case '*': xkey = 'R'; break; + case '-': xkey = 'S'; break; + } + } + + if (app_keypad) { + switch (key) { + case '0': xkey = 'p'; break; + case '1': xkey = 'q'; break; + case '2': xkey = 'r'; break; + case '3': xkey = 's'; break; + case '4': xkey = 't'; break; + case '5': xkey = 'u'; break; + case '6': xkey = 'v'; break; + case '7': xkey = 'w'; break; + case '8': xkey = 'x'; break; + case '9': xkey = 'y'; break; + case '.': xkey = 'n'; break; + case '\r': xkey = 'M'; break; + + case '+': + /* + * Keypad + is tricky. It covers a space that would + * be taken up on the VT100 by _two_ keys; so we + * let Shift select between the two. Worse still, + * in xterm function key mode we change which two... + */ + if (term->funky_type == FUNKY_XTERM) + xkey = shift ? 'l' : 'k'; + else + xkey = shift ? 'm' : 'l'; + break; + + case '/': + if (term->funky_type == FUNKY_XTERM) + xkey = 'o'; + break; + case '*': + if (term->funky_type == FUNKY_XTERM) + xkey = 'j'; + break; + case '-': + if (term->funky_type == FUNKY_XTERM) + xkey = 'm'; + break; + } + } + + if (xkey) { + if (term->vt52_mode) { + if (xkey >= 'P' && xkey <= 'S') + p += sprintf(p, "\x1B%c", xkey); + else + p += sprintf(p, "\x1B?%c", xkey); + } else + p += sprintf(p, "\x1BO%c", xkey); + } + } + + if (p == buf && !app_keypad && key != 'G') { + /* Fallback: numeric keypad keys decode as their ASCII + * representation. */ + p += sprintf(p, "%c", key); } return p - buf; diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 369e9942..c450c252 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -983,7 +983,9 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) int ucsval, start, end, output_charset; bool special, use_ucsoutput; bool nethack_mode, app_keypad_mode; + bool force_format_numeric_keypad = false; bool generated_something = false; + char num_keypad_key = '\0'; #ifdef OSX_META_KEY_CONFIG if (event->state & inst->system_mod_mask) @@ -1405,56 +1407,44 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) * numeric keypad presses if Num Lock is on, but we don't want * it to. */ - if (app_keypad_mode && - (event->keyval == GDK_KEY_Num_Lock || - event->keyval == GDK_KEY_KP_Divide || - event->keyval == GDK_KEY_KP_Multiply || - event->keyval == GDK_KEY_KP_Subtract || - event->keyval == GDK_KEY_KP_Add || - event->keyval == GDK_KEY_KP_Enter || - event->keyval == GDK_KEY_KP_0 || - event->keyval == GDK_KEY_KP_Insert || - event->keyval == GDK_KEY_KP_1 || - event->keyval == GDK_KEY_KP_End || - event->keyval == GDK_KEY_KP_2 || - event->keyval == GDK_KEY_KP_Down || - event->keyval == GDK_KEY_KP_3 || - event->keyval == GDK_KEY_KP_Page_Down || - event->keyval == GDK_KEY_KP_4 || - event->keyval == GDK_KEY_KP_Left || - event->keyval == GDK_KEY_KP_5 || - event->keyval == GDK_KEY_KP_Begin || - event->keyval == GDK_KEY_KP_6 || - event->keyval == GDK_KEY_KP_Right || - event->keyval == GDK_KEY_KP_7 || - event->keyval == GDK_KEY_KP_Home || - event->keyval == GDK_KEY_KP_8 || - event->keyval == GDK_KEY_KP_Up || - event->keyval == GDK_KEY_KP_9 || - event->keyval == GDK_KEY_KP_Page_Up || - event->keyval == GDK_KEY_KP_Decimal || - event->keyval == GDK_KEY_KP_Delete)) { - /* app keypad; do nothing */ - } else if (nethack_mode && - (event->keyval == GDK_KEY_KP_1 || - event->keyval == GDK_KEY_KP_End || - event->keyval == GDK_KEY_KP_2 || - event->keyval == GDK_KEY_KP_Down || - event->keyval == GDK_KEY_KP_3 || - event->keyval == GDK_KEY_KP_Page_Down || - event->keyval == GDK_KEY_KP_4 || - event->keyval == GDK_KEY_KP_Left || - event->keyval == GDK_KEY_KP_5 || - event->keyval == GDK_KEY_KP_Begin || - event->keyval == GDK_KEY_KP_6 || - event->keyval == GDK_KEY_KP_Right || - event->keyval == GDK_KEY_KP_7 || - event->keyval == GDK_KEY_KP_Home || - event->keyval == GDK_KEY_KP_8 || - event->keyval == GDK_KEY_KP_Up || - event->keyval == GDK_KEY_KP_9 || - event->keyval == GDK_KEY_KP_Page_Up)) { - /* nethack mode; do nothing */ + bool numeric = false; + switch (event->keyval) { + case GDK_KEY_Num_Lock: num_keypad_key = 'G'; break; + case GDK_KEY_KP_Divide: num_keypad_key = '/'; break; + case GDK_KEY_KP_Multiply: num_keypad_key = '*'; break; + case GDK_KEY_KP_Subtract: num_keypad_key = '-'; break; + case GDK_KEY_KP_Add: num_keypad_key = '+'; break; + case GDK_KEY_KP_Enter: num_keypad_key = '\r'; break; + case GDK_KEY_KP_0: num_keypad_key = '0'; numeric = true; break; + case GDK_KEY_KP_Insert: num_keypad_key = '0'; break; + case GDK_KEY_KP_1: num_keypad_key = '1'; numeric = true; break; + case GDK_KEY_KP_End: num_keypad_key = '1'; break; + case GDK_KEY_KP_2: num_keypad_key = '2'; numeric = true; break; + case GDK_KEY_KP_Down: num_keypad_key = '2'; break; + case GDK_KEY_KP_3: num_keypad_key = '3'; numeric = true; break; + case GDK_KEY_KP_Page_Down: num_keypad_key = '3'; break; + case GDK_KEY_KP_4: num_keypad_key = '4'; numeric = true; break; + case GDK_KEY_KP_Left: num_keypad_key = '4'; break; + case GDK_KEY_KP_5: num_keypad_key = '5'; numeric = true; break; + case GDK_KEY_KP_Begin: num_keypad_key = '5'; break; + case GDK_KEY_KP_6: num_keypad_key = '6'; numeric = true; break; + case GDK_KEY_KP_Right: num_keypad_key = '6'; break; + case GDK_KEY_KP_7: num_keypad_key = '7'; numeric = true; break; + case GDK_KEY_KP_Home: num_keypad_key = '7'; break; + case GDK_KEY_KP_8: num_keypad_key = '8'; numeric = true; break; + case GDK_KEY_KP_Up: num_keypad_key = '8'; break; + case GDK_KEY_KP_9: num_keypad_key = '9'; numeric = true; break; + case GDK_KEY_KP_Page_Up: num_keypad_key = '9'; break; + case GDK_KEY_KP_Decimal: num_keypad_key = '.'; numeric = true; break; + case GDK_KEY_KP_Delete: num_keypad_key = '.'; break; + } + if ((app_keypad_mode && num_keypad_key && + (numeric || inst->term->funky_type != FUNKY_XTERM)) || + (nethack_mode && num_keypad_key >= '1' && num_keypad_key <= '9')) { + /* In these modes, we override the keypad handling: + * regardless of Num Lock, the keys are handled by + * format_numeric_keypad_key below. */ + force_format_numeric_keypad = true; } else { bool try_filter = true; @@ -1763,345 +1753,108 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) end = 2; } - /* - * NetHack keypad mode. - */ - if (nethack_mode) { - const char *keys = NULL; - switch (event->keyval) { - case GDK_KEY_KP_1: case GDK_KEY_KP_End: - keys = "bB\002"; break; - case GDK_KEY_KP_2: case GDK_KEY_KP_Down: - keys = "jJ\012"; break; - case GDK_KEY_KP_3: case GDK_KEY_KP_Page_Down: - keys = "nN\016"; break; - case GDK_KEY_KP_4: case GDK_KEY_KP_Left: - keys = "hH\010"; break; - case GDK_KEY_KP_5: case GDK_KEY_KP_Begin: - keys = "..."; break; - case GDK_KEY_KP_6: case GDK_KEY_KP_Right: - keys = "lL\014"; break; - case GDK_KEY_KP_7: case GDK_KEY_KP_Home: - keys = "yY\031"; break; - case GDK_KEY_KP_8: case GDK_KEY_KP_Up: - keys = "kK\013"; break; - case GDK_KEY_KP_9: case GDK_KEY_KP_Page_Up: - keys = "uU\025"; break; - } - if (keys) { - end = 2; - if (event->state & GDK_CONTROL_MASK) - output[1] = keys[2]; - else if (event->state & GDK_SHIFT_MASK) - output[1] = keys[1]; - else - output[1] = keys[0]; + if (num_keypad_key && force_format_numeric_keypad) { + end = 1 + format_numeric_keypad_key( + output+1, inst->term, num_keypad_key, + event->state & GDK_SHIFT_MASK, + event->state & GDK_CONTROL_MASK); #ifdef KEY_EVENT_DIAGNOSTICS - debug((" - Nethack-mode key")); + debug((" - numeric keypad key")); #endif - use_ucsoutput = false; - goto done; - } + use_ucsoutput = false; + goto done; } - /* - * Application keypad mode. - */ - if (app_keypad_mode) { - int xkey = 0; - switch (event->keyval) { - case GDK_KEY_Num_Lock: xkey = 'P'; break; - case GDK_KEY_KP_Divide: xkey = 'Q'; break; - case GDK_KEY_KP_Multiply: xkey = 'R'; break; - case GDK_KEY_KP_Subtract: xkey = 'S'; break; - /* - * Keypad + is tricky. It covers a space that would - * be taken up on the VT100 by _two_ keys; so we - * let Shift select between the two. Worse still, - * in xterm function key mode we change which two... - */ - case GDK_KEY_KP_Add: - if (conf_get_int(inst->conf, CONF_funky_type) == FUNKY_XTERM) { - if (event->state & GDK_SHIFT_MASK) - xkey = 'l'; - else - xkey = 'k'; - } else if (event->state & GDK_SHIFT_MASK) - xkey = 'm'; - else - xkey = 'l'; - break; - case GDK_KEY_KP_Enter: xkey = 'M'; break; - case GDK_KEY_KP_0: case GDK_KEY_KP_Insert: xkey = 'p'; break; - case GDK_KEY_KP_1: case GDK_KEY_KP_End: xkey = 'q'; break; - case GDK_KEY_KP_2: case GDK_KEY_KP_Down: xkey = 'r'; break; - case GDK_KEY_KP_3: case GDK_KEY_KP_Page_Down: xkey = 's'; break; - case GDK_KEY_KP_4: case GDK_KEY_KP_Left: xkey = 't'; break; - case GDK_KEY_KP_5: case GDK_KEY_KP_Begin: xkey = 'u'; break; - case GDK_KEY_KP_6: case GDK_KEY_KP_Right: xkey = 'v'; break; - case GDK_KEY_KP_7: case GDK_KEY_KP_Home: xkey = 'w'; break; - case GDK_KEY_KP_8: case GDK_KEY_KP_Up: xkey = 'x'; break; - case GDK_KEY_KP_9: case GDK_KEY_KP_Page_Up: xkey = 'y'; break; - case GDK_KEY_KP_Decimal: case GDK_KEY_KP_Delete: - xkey = 'n'; break; - } - if (xkey) { - if (inst->term->vt52_mode) { - if (xkey >= 'P' && xkey <= 'S') - end = 1 + sprintf(output+1, "\033%c", xkey); - else - end = 1 + sprintf(output+1, "\033?%c", xkey); - } else - end = 1 + sprintf(output+1, "\033O%c", xkey); - use_ucsoutput = false; + switch (event->keyval) { + int fkey_number; + case GDK_KEY_F1: fkey_number = 1; goto numbered_function_key; + case GDK_KEY_F2: fkey_number = 2; goto numbered_function_key; + case GDK_KEY_F3: fkey_number = 3; goto numbered_function_key; + case GDK_KEY_F4: fkey_number = 4; goto numbered_function_key; + case GDK_KEY_F5: fkey_number = 5; goto numbered_function_key; + case GDK_KEY_F6: fkey_number = 6; goto numbered_function_key; + case GDK_KEY_F7: fkey_number = 7; goto numbered_function_key; + case GDK_KEY_F8: fkey_number = 8; goto numbered_function_key; + case GDK_KEY_F9: fkey_number = 9; goto numbered_function_key; + case GDK_KEY_F10: fkey_number = 10; goto numbered_function_key; + case GDK_KEY_F11: fkey_number = 11; goto numbered_function_key; + case GDK_KEY_F12: fkey_number = 12; goto numbered_function_key; + case GDK_KEY_F13: fkey_number = 13; goto numbered_function_key; + case GDK_KEY_F14: fkey_number = 14; goto numbered_function_key; + case GDK_KEY_F15: fkey_number = 15; goto numbered_function_key; + case GDK_KEY_F16: fkey_number = 16; goto numbered_function_key; + case GDK_KEY_F17: fkey_number = 17; goto numbered_function_key; + case GDK_KEY_F18: fkey_number = 18; goto numbered_function_key; + 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: + end = 1 + format_function_key(output+1, inst->term, fkey_number, + event->state & GDK_SHIFT_MASK, + event->state & GDK_CONTROL_MASK); #ifdef KEY_EVENT_DIAGNOSTICS - debug((" - Application keypad mode key")); + debug((" - function key F%d", fkey_number)); #endif - goto done; - } + use_ucsoutput = false; + goto done; + + SmallKeypadKey sk_key; + case GDK_KEY_Home: case GDK_KEY_KP_Home: + sk_key = SKK_HOME; goto small_keypad_key; + case GDK_KEY_Insert: case GDK_KEY_KP_Insert: + sk_key = SKK_INSERT; goto small_keypad_key; + case GDK_KEY_Delete: case GDK_KEY_KP_Delete: + sk_key = SKK_DELETE; goto small_keypad_key; + case GDK_KEY_End: case GDK_KEY_KP_End: + sk_key = SKK_END; goto small_keypad_key; + case GDK_KEY_Page_Up: case GDK_KEY_KP_Page_Up: + sk_key = SKK_PGUP; goto small_keypad_key; + case GDK_KEY_Page_Down: case GDK_KEY_KP_Page_Down: + sk_key = SKK_PGDN; goto small_keypad_key; + small_keypad_key: + /* These keys don't generate terminal input with Ctrl */ + if (event->state & GDK_CONTROL_MASK) + break; + + end = 1 + format_small_keypad_key(output+1, inst->term, sk_key); +#ifdef KEY_EVENT_DIAGNOSTICS + debug((" - small keypad key")); +#endif + use_ucsoutput = false; + goto done; + + int xkey; + case GDK_KEY_Up: case GDK_KEY_KP_Up: + xkey = 'A'; goto arrow_key; + case GDK_KEY_Down: case GDK_KEY_KP_Down: + xkey = 'B'; goto arrow_key; + case GDK_KEY_Right: case GDK_KEY_KP_Right: + xkey = 'C'; goto arrow_key; + case GDK_KEY_Left: case GDK_KEY_KP_Left: + xkey = 'D'; goto arrow_key; + case GDK_KEY_Begin: case GDK_KEY_KP_Begin: + xkey = 'G'; goto arrow_key; + arrow_key: + end = 1 + format_arrow_key(output+1, inst->term, xkey, + event->state & GDK_CONTROL_MASK); +#ifdef KEY_EVENT_DIAGNOSTICS + debug((" - arrow key")); +#endif + use_ucsoutput = false; + goto done; } - /* - * Next, all the keys that do tilde codes. (ESC '[' nn '~', - * for integer decimal nn.) - * - * We also deal with the weird ones here. Linux VCs replace F1 - * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but - * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w - * respectively. - */ - { - int code = 0; - int funky_type = conf_get_int(inst->conf, CONF_funky_type); - switch (event->keyval) { - case GDK_KEY_F1: - code = (event->state & GDK_SHIFT_MASK ? 23 : 11); - break; - case GDK_KEY_F2: - code = (event->state & GDK_SHIFT_MASK ? 24 : 12); - break; - case GDK_KEY_F3: - code = (event->state & GDK_SHIFT_MASK ? 25 : 13); - break; - case GDK_KEY_F4: - code = (event->state & GDK_SHIFT_MASK ? 26 : 14); - break; - case GDK_KEY_F5: - code = (event->state & GDK_SHIFT_MASK ? 28 : 15); - break; - case GDK_KEY_F6: - code = (event->state & GDK_SHIFT_MASK ? 29 : 17); - break; - case GDK_KEY_F7: - code = (event->state & GDK_SHIFT_MASK ? 31 : 18); - break; - case GDK_KEY_F8: - code = (event->state & GDK_SHIFT_MASK ? 32 : 19); - break; - case GDK_KEY_F9: - code = (event->state & GDK_SHIFT_MASK ? 33 : 20); - break; - case GDK_KEY_F10: - code = (event->state & GDK_SHIFT_MASK ? 34 : 21); - break; - case GDK_KEY_F11: - code = 23; - break; - case GDK_KEY_F12: - code = 24; - break; - case GDK_KEY_F13: - code = 25; - break; - case GDK_KEY_F14: - code = 26; - break; - case GDK_KEY_F15: - code = 28; - break; - case GDK_KEY_F16: - code = 29; - break; - case GDK_KEY_F17: - code = 31; - break; - case GDK_KEY_F18: - code = 32; - break; - case GDK_KEY_F19: - code = 33; - break; - case GDK_KEY_F20: - code = 34; - break; - } - if (!(event->state & GDK_CONTROL_MASK)) switch (event->keyval) { - case GDK_KEY_Home: case GDK_KEY_KP_Home: - code = 1; - break; - case GDK_KEY_Insert: case GDK_KEY_KP_Insert: - code = 2; - break; - case GDK_KEY_Delete: case GDK_KEY_KP_Delete: - code = 3; - break; - case GDK_KEY_End: case GDK_KEY_KP_End: - code = 4; - break; - case GDK_KEY_Page_Up: case GDK_KEY_KP_Page_Up: - code = 5; - break; - case GDK_KEY_Page_Down: case GDK_KEY_KP_Page_Down: - code = 6; - break; - } - /* Reorder edit keys to physical order */ - if (funky_type == FUNKY_VT400 && code <= 6) - code = "\0\2\1\4\5\3\6"[code]; - - if (inst->term->vt52_mode && code > 0 && code <= 6) { - end = 1 + sprintf(output+1, "\x1B%c", " HLMEIG"[code]); + if (num_keypad_key) { + end = 1 + format_numeric_keypad_key( + output+1, inst->term, num_keypad_key, + event->state & GDK_SHIFT_MASK, + event->state & GDK_CONTROL_MASK); #ifdef KEY_EVENT_DIAGNOSTICS - debug((" - VT52 mode small keypad key")); + debug((" - numeric keypad key")); #endif - use_ucsoutput = false; - goto done; - } - - if (funky_type == FUNKY_SCO && /* SCO function keys */ - code >= 11 && code <= 34) { - char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{"; - int index = 0; - switch (event->keyval) { - case GDK_KEY_F1: index = 0; break; - case GDK_KEY_F2: index = 1; break; - case GDK_KEY_F3: index = 2; break; - case GDK_KEY_F4: index = 3; break; - case GDK_KEY_F5: index = 4; break; - case GDK_KEY_F6: index = 5; break; - case GDK_KEY_F7: index = 6; break; - case GDK_KEY_F8: index = 7; break; - case GDK_KEY_F9: index = 8; break; - case GDK_KEY_F10: index = 9; break; - case GDK_KEY_F11: index = 10; break; - case GDK_KEY_F12: index = 11; break; - } - if (event->state & GDK_SHIFT_MASK) index += 12; - if (event->state & GDK_CONTROL_MASK) index += 24; - end = 1 + sprintf(output+1, "\x1B[%c", codes[index]); -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - SCO mode function key")); -#endif - use_ucsoutput = false; - goto done; - } - if (funky_type == FUNKY_SCO && /* SCO small keypad */ - code >= 1 && code <= 6) { - char codes[] = "HL.FIG"; - if (code == 3) { - output[1] = '\x7F'; - end = 2; - } else { - end = 1 + sprintf(output+1, "\x1B[%c", codes[code-1]); - } -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - SCO mode small keypad key")); -#endif - use_ucsoutput = false; - goto done; - } - if ((inst->term->vt52_mode || funky_type == FUNKY_VT100P) && - code >= 11 && code <= 24) { - int offt = 0; - if (code > 15) - offt++; - if (code > 21) - offt++; - if (inst->term->vt52_mode) { -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - VT52 mode function key")); -#endif - end = 1 + sprintf(output+1, - "\x1B%c", code + 'P' - 11 - offt); - } else { -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - VT100+ mode function key")); -#endif - end = 1 + sprintf(output+1, - "\x1BO%c", code + 'P' - 11 - offt); - } - use_ucsoutput = false; - goto done; - } - if (funky_type == FUNKY_LINUX && code >= 11 && code <= 15) { - end = 1 + sprintf(output+1, "\x1B[[%c", code + 'A' - 11); -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - Linux mode F1-F5 function key")); -#endif - use_ucsoutput = false; - goto done; - } - if (funky_type == FUNKY_XTERM && code >= 11 && code <= 14) { - if (inst->term->vt52_mode) { -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - VT52 mode (overriding xterm) F1-F4 function" - " key")); -#endif - end = 1 + sprintf(output+1, "\x1B%c", code + 'P' - 11); - } else { -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - xterm mode F1-F4 function key")); -#endif - end = 1 + sprintf(output+1, "\x1BO%c", code + 'P' - 11); - } - use_ucsoutput = false; - goto done; - } - if ((code == 1 || code == 4) && - conf_get_bool(inst->conf, CONF_rxvt_homeend)) { -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - rxvt style Home/End")); -#endif - end = 1 + sprintf(output+1, code == 1 ? "\x1B[H" : "\x1BOw"); - use_ucsoutput = false; - goto done; - } - if (code) { -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - ordinary function key encoding")); -#endif - end = 1 + sprintf(output+1, "\x1B[%d~", code); - use_ucsoutput = false; - goto done; - } + use_ucsoutput = false; + goto done; } - /* - * Cursor keys. (This includes the numberpad cursor keys, - * if we haven't already done them due to app keypad mode.) - * - * Here we also process un-numlocked un-appkeypadded KP5, - * which sends ESC [ G. - */ - { - int xkey = 0; - switch (event->keyval) { - case GDK_KEY_Up: case GDK_KEY_KP_Up: xkey = 'A'; break; - case GDK_KEY_Down: case GDK_KEY_KP_Down: xkey = 'B'; break; - case GDK_KEY_Right: case GDK_KEY_KP_Right: xkey = 'C'; break; - case GDK_KEY_Left: case GDK_KEY_KP_Left: xkey = 'D'; break; - case GDK_KEY_Begin: case GDK_KEY_KP_Begin: xkey = 'G'; break; - } - if (xkey) { - end = 1 + format_arrow_key(output+1, inst->term, xkey, - event->state & GDK_CONTROL_MASK); -#ifdef KEY_EVENT_DIAGNOSTICS - debug((" - arrow key")); -#endif - use_ucsoutput = false; - goto done; - } - } goto done; } diff --git a/windows/window.c b/windows/window.c index 913e453d..3a8de2fe 100644 --- a/windows/window.c +++ b/windows/window.c @@ -4068,7 +4068,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, BYTE keystate[256]; int scan, shift_state; bool left_alt = false, key_down; - int r, i, code; + int r, i; unsigned char *p = output; static int alt_sum = 0; int funky_type = conf_get_int(conf, CONF_funky_type); @@ -4388,137 +4388,6 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, return 0; } - /* Nethack keypad */ - if (nethack_keypad && !left_alt) { - switch (wParam) { - case VK_NUMPAD1: - *p++ = "bB\002\002"[shift_state & 3]; - return p - output; - case VK_NUMPAD2: - *p++ = "jJ\012\012"[shift_state & 3]; - return p - output; - case VK_NUMPAD3: - *p++ = "nN\016\016"[shift_state & 3]; - return p - output; - case VK_NUMPAD4: - *p++ = "hH\010\010"[shift_state & 3]; - return p - output; - case VK_NUMPAD5: - *p++ = '.'; - return p - output; - case VK_NUMPAD6: - *p++ = "lL\014\014"[shift_state & 3]; - return p - output; - case VK_NUMPAD7: - *p++ = "yY\031\031"[shift_state & 3]; - return p - output; - case VK_NUMPAD8: - *p++ = "kK\013\013"[shift_state & 3]; - return p - output; - case VK_NUMPAD9: - *p++ = "uU\025\025"[shift_state & 3]; - return p - output; - } - } - - /* Application Keypad */ - if (!left_alt) { - int xkey = 0; - - if (funky_type == FUNKY_VT400 || - (funky_type <= FUNKY_LINUX && - term->app_keypad_keys && !no_applic_k)) switch (wParam) { - case VK_EXECUTE: - xkey = 'P'; - break; - case VK_DIVIDE: - xkey = 'Q'; - break; - case VK_MULTIPLY: - xkey = 'R'; - break; - case VK_SUBTRACT: - xkey = 'S'; - break; - } - if (term->app_keypad_keys && !no_applic_k) - switch (wParam) { - case VK_NUMPAD0: - xkey = 'p'; - break; - case VK_NUMPAD1: - xkey = 'q'; - break; - case VK_NUMPAD2: - xkey = 'r'; - break; - case VK_NUMPAD3: - xkey = 's'; - break; - case VK_NUMPAD4: - xkey = 't'; - break; - case VK_NUMPAD5: - xkey = 'u'; - break; - case VK_NUMPAD6: - xkey = 'v'; - break; - case VK_NUMPAD7: - xkey = 'w'; - break; - case VK_NUMPAD8: - xkey = 'x'; - break; - case VK_NUMPAD9: - xkey = 'y'; - break; - - case VK_DECIMAL: - xkey = 'n'; - break; - case VK_ADD: - if (funky_type == FUNKY_XTERM) { - if (shift_state) - xkey = 'l'; - else - xkey = 'k'; - } else if (shift_state) - xkey = 'm'; - else - xkey = 'l'; - break; - - case VK_DIVIDE: - if (funky_type == FUNKY_XTERM) - xkey = 'o'; - break; - case VK_MULTIPLY: - if (funky_type == FUNKY_XTERM) - xkey = 'j'; - break; - case VK_SUBTRACT: - if (funky_type == FUNKY_XTERM) - xkey = 'm'; - break; - - case VK_RETURN: - if (HIWORD(lParam) & KF_EXTENDED) - xkey = 'M'; - break; - } - if (xkey) { - if (term->vt52_mode) { - if (xkey >= 'P' && xkey <= 'S') - p += sprintf((char *) p, "\x1B%c", xkey); - else - p += sprintf((char *) p, "\x1B?%c", xkey); - } else - p += sprintf((char *) p, "\x1BO%c", xkey); - return p - output; - } - } - if (wParam == VK_BACK && shift_state == 0) { /* Backspace */ *p++ = (conf_get_bool(conf, CONF_bksp_is_delete) ? 0x7F : 0x08); *p++ = 0; @@ -4577,217 +4446,101 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, return p - output; } - /* - * Next, all the keys that do tilde codes. (ESC '[' nn '~', - * for integer decimal nn.) - * - * We also deal with the weird ones here. Linux VCs replace F1 - * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but - * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w - * respectively. - */ - code = 0; switch (wParam) { - case VK_F1: - code = (keystate[VK_SHIFT] & 0x80 ? 23 : 11); - break; - case VK_F2: - code = (keystate[VK_SHIFT] & 0x80 ? 24 : 12); - break; - case VK_F3: - code = (keystate[VK_SHIFT] & 0x80 ? 25 : 13); - break; - case VK_F4: - code = (keystate[VK_SHIFT] & 0x80 ? 26 : 14); - break; - case VK_F5: - code = (keystate[VK_SHIFT] & 0x80 ? 28 : 15); - break; - case VK_F6: - code = (keystate[VK_SHIFT] & 0x80 ? 29 : 17); - break; - case VK_F7: - code = (keystate[VK_SHIFT] & 0x80 ? 31 : 18); - break; - case VK_F8: - code = (keystate[VK_SHIFT] & 0x80 ? 32 : 19); - break; - case VK_F9: - code = (keystate[VK_SHIFT] & 0x80 ? 33 : 20); - break; - case VK_F10: - code = (keystate[VK_SHIFT] & 0x80 ? 34 : 21); - break; - case VK_F11: - code = 23; - break; - case VK_F12: - code = 24; - break; - case VK_F13: - code = 25; - break; - case VK_F14: - code = 26; - break; - case VK_F15: - code = 28; - break; - case VK_F16: - code = 29; - break; - case VK_F17: - code = 31; - break; - case VK_F18: - code = 32; - break; - case VK_F19: - code = 33; - break; - case VK_F20: - code = 34; - break; - } - if ((shift_state&2) == 0) switch (wParam) { - case VK_HOME: - code = 1; - break; - case VK_INSERT: - code = 2; - break; - case VK_DELETE: - code = 3; - break; - case VK_END: - code = 4; - break; - case VK_PRIOR: - code = 5; - break; - case VK_NEXT: - code = 6; - break; - } - /* Reorder edit keys to physical order */ - if (funky_type == FUNKY_VT400 && code <= 6) - code = "\0\2\1\4\5\3\6"[code]; + char keypad_key; + case VK_NUMPAD0: keypad_key = '0'; goto numeric_keypad; + case VK_NUMPAD1: keypad_key = '1'; goto numeric_keypad; + case VK_NUMPAD2: keypad_key = '2'; goto numeric_keypad; + case VK_NUMPAD3: keypad_key = '3'; goto numeric_keypad; + case VK_NUMPAD4: keypad_key = '4'; goto numeric_keypad; + case VK_NUMPAD5: keypad_key = '5'; goto numeric_keypad; + case VK_NUMPAD6: keypad_key = '6'; goto numeric_keypad; + case VK_NUMPAD7: keypad_key = '7'; goto numeric_keypad; + case VK_NUMPAD8: keypad_key = '8'; goto numeric_keypad; + case VK_NUMPAD9: keypad_key = '9'; goto numeric_keypad; + case VK_DECIMAL: keypad_key = '.'; goto numeric_keypad; + case VK_ADD: keypad_key = '+'; goto numeric_keypad; + case VK_SUBTRACT: keypad_key = '-'; goto numeric_keypad; + case VK_MULTIPLY: keypad_key = '*'; goto numeric_keypad; + case VK_DIVIDE: keypad_key = '/'; goto numeric_keypad; + case VK_EXECUTE: keypad_key = 'G'; goto numeric_keypad; + /* also the case for VK_RETURN below can sometimes come here */ + numeric_keypad: + /* Left Alt overrides all numeric keypad usage to act as + * numeric character code input */ + if (left_alt) { + if (keypad_key >= '0' && keypad_key <= '9') + alt_sum = alt_sum * 10 + keypad_key - '0'; + else + alt_sum = 0; + break; + } - if (term->vt52_mode && code > 0 && code <= 6) { - p += sprintf((char *) p, "\x1B%c", " HLMEIG"[code]); - return p - output; - } + p += format_numeric_keypad_key( + (char *)p, term, keypad_key, + shift_state & 1, shift_state & 2); + return p - output; - if (funky_type == FUNKY_SCO && code >= 11 && code <= 34) { - /* SCO function keys */ - char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{"; - int index = 0; - switch (wParam) { - case VK_F1: index = 0; break; - case VK_F2: index = 1; break; - case VK_F3: index = 2; break; - case VK_F4: index = 3; break; - case VK_F5: index = 4; break; - case VK_F6: index = 5; break; - case VK_F7: index = 6; break; - case VK_F8: index = 7; break; - case VK_F9: index = 8; break; - case VK_F10: index = 9; break; - case VK_F11: index = 10; break; - case VK_F12: index = 11; break; - } - if (keystate[VK_SHIFT] & 0x80) index += 12; - if (keystate[VK_CONTROL] & 0x80) index += 24; - p += sprintf((char *) p, "\x1B[%c", codes[index]); - return p - output; - } - if (funky_type == FUNKY_SCO && /* SCO small keypad */ - code >= 1 && code <= 6) { - char codes[] = "HL.FIG"; - if (code == 3) { - *p++ = '\x7F'; - } else { - p += sprintf((char *) p, "\x1B[%c", codes[code-1]); - } - return p - output; - } - if ((term->vt52_mode || funky_type == FUNKY_VT100P) && code >= 11 && code <= 24) { - int offt = 0; - if (code > 15) - offt++; - if (code > 21) - offt++; - if (term->vt52_mode) - p += sprintf((char *) p, "\x1B%c", code + 'P' - 11 - offt); - else - p += - sprintf((char *) p, "\x1BO%c", code + 'P' - 11 - offt); - return p - output; - } - if (funky_type == FUNKY_LINUX && code >= 11 && code <= 15) { - p += sprintf((char *) p, "\x1B[[%c", code + 'A' - 11); - return p - output; - } - if (funky_type == FUNKY_XTERM && code >= 11 && code <= 14) { - if (term->vt52_mode) - p += sprintf((char *) p, "\x1B%c", code + 'P' - 11); - else - p += sprintf((char *) p, "\x1BO%c", code + 'P' - 11); - return p - output; - } - if ((code == 1 || code == 4) && - conf_get_bool(conf, CONF_rxvt_homeend)) { - p += sprintf((char *) p, code == 1 ? "\x1B[H" : "\x1BOw"); - return p - output; - } - if (code) { - p += sprintf((char *) p, "\x1B[%d~", code); - return p - output; - } + int fkey_number; + case VK_F1: fkey_number = 1; goto numbered_function_key; + case VK_F2: fkey_number = 2; goto numbered_function_key; + case VK_F3: fkey_number = 3; goto numbered_function_key; + case VK_F4: fkey_number = 4; goto numbered_function_key; + case VK_F5: fkey_number = 5; goto numbered_function_key; + case VK_F6: fkey_number = 6; goto numbered_function_key; + case VK_F7: fkey_number = 7; goto numbered_function_key; + case VK_F8: fkey_number = 8; goto numbered_function_key; + case VK_F9: fkey_number = 9; goto numbered_function_key; + case VK_F10: fkey_number = 10; goto numbered_function_key; + case VK_F11: fkey_number = 11; goto numbered_function_key; + case VK_F12: fkey_number = 12; goto numbered_function_key; + case VK_F13: fkey_number = 13; goto numbered_function_key; + case VK_F14: fkey_number = 14; goto numbered_function_key; + case VK_F15: fkey_number = 15; goto numbered_function_key; + case VK_F16: fkey_number = 16; goto numbered_function_key; + case VK_F17: fkey_number = 17; goto numbered_function_key; + case VK_F18: fkey_number = 18; goto numbered_function_key; + case VK_F19: fkey_number = 19; goto numbered_function_key; + case VK_F20: fkey_number = 20; goto numbered_function_key; + numbered_function_key: + p += format_function_key((char *)p, term, fkey_number, + shift_state & 1, shift_state & 2); + return p - output; - /* - * Now the remaining keys (arrows and Keypad 5. Keypad 5 for - * some reason seems to send VK_CLEAR to Windows...). - */ - { - char xkey = 0; - switch (wParam) { - case VK_UP: - xkey = 'A'; - break; - case VK_DOWN: - xkey = 'B'; - break; - case VK_RIGHT: - xkey = 'C'; - break; - case VK_LEFT: - xkey = 'D'; - break; - case VK_CLEAR: - xkey = 'G'; - break; - } - if (xkey) { - p += format_arrow_key((char *)p, term, xkey, shift_state); - return p - output; - } - } + SmallKeypadKey sk_key; + case VK_HOME: sk_key = SKK_HOME; goto small_keypad_key; + case VK_END: sk_key = SKK_END; goto small_keypad_key; + case VK_INSERT: sk_key = SKK_INSERT; goto small_keypad_key; + case VK_DELETE: sk_key = SKK_DELETE; goto small_keypad_key; + case VK_PRIOR: sk_key = SKK_PGUP; goto small_keypad_key; + case VK_NEXT: sk_key = SKK_PGDN; goto small_keypad_key; + small_keypad_key: + /* These keys don't generate terminal input with Ctrl */ + if (shift_state & 2) + break; - /* - * Finally, deal with Return ourselves. (Win95 seems to - * foul it up when Alt is pressed, for some reason.) - */ - if (wParam == VK_RETURN) { /* Return */ + p += format_small_keypad_key((char *)p, term, sk_key); + return p - output; + + char xkey; + case VK_UP: xkey = 'A'; goto arrow_key; + case VK_DOWN: xkey = 'B'; goto arrow_key; + case VK_RIGHT: xkey = 'C'; goto arrow_key; + case VK_LEFT: xkey = 'D'; goto arrow_key; + case VK_CLEAR: xkey = 'G'; goto arrow_key; /* close enough */ + arrow_key: + p += format_arrow_key((char *)p, term, xkey, shift_state & 2); + return p - output; + + case VK_RETURN: + if (HIWORD(lParam) & KF_EXTENDED) { + keypad_key = '\r'; + goto numeric_keypad; + } *p++ = 0x0D; *p++ = 0; return -2; } - - if (left_alt && wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9) - alt_sum = alt_sum * 10 + wParam - VK_NUMPAD0; - else - alt_sum = 0; } /* Okay we've done everything interesting; let windows deal with