summaryrefslogtreecommitdiffstats
path: root/tty-keys.c
diff options
context:
space:
mode:
authornicm <nicm>2020-05-16 16:44:54 +0000
committernicm <nicm>2020-05-16 16:44:54 +0000
commit0ab82d95314e7a26a48452c77ad710f3aff97dd7 (patch)
tree8a7439d2a3007bb7de92f6c8c801bb5303754fae /tty-keys.c
parent292b335ca5b594729cf9ff79f0f4273c725537a4 (diff)
Add a terminal feature for enable/disable extended keys (supported by
xterm and mintty) and add an option to make tmux send it. Only forward extended keys if the application has requested them, even though we use the CSI u sequence and xterm uses CSI 27 ~ - this is what mintty does as well.
Diffstat (limited to 'tty-keys.c')
-rw-r--r--tty-keys.c484
1 files changed, 320 insertions, 164 deletions
diff --git a/tty-keys.c b/tty-keys.c
index dc064a17..5a2b3817 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -21,6 +21,7 @@
#include <netinet/in.h>
+#include <ctype.h>
#include <limits.h>
#include <resolv.h>
#include <stdlib.h>
@@ -46,6 +47,8 @@ static struct tty_key *tty_keys_find(struct tty *, const char *, size_t,
static int tty_keys_next1(struct tty *, const char *, size_t, key_code *,
size_t *, int);
static void tty_keys_callback(int, short, void *);
+static int tty_keys_extended_key(struct tty *, const char *, size_t,
+ size_t *, key_code *);
static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *,
struct mouse_event *);
static int tty_keys_clipboard(struct tty *, const char *, size_t,
@@ -69,33 +72,33 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = {
* put the terminal into keypad_xmit mode. Translation of numbers
* mode/applications mode is done in input-keys.c.
*/
- { "\033Oo", KEYC_KP_SLASH },
- { "\033Oj", KEYC_KP_STAR },
- { "\033Om", KEYC_KP_MINUS },
- { "\033Ow", KEYC_KP_SEVEN },
- { "\033Ox", KEYC_KP_EIGHT },
- { "\033Oy", KEYC_KP_NINE },
- { "\033Ok", KEYC_KP_PLUS },
- { "\033Ot", KEYC_KP_FOUR },
- { "\033Ou", KEYC_KP_FIVE },
- { "\033Ov", KEYC_KP_SIX },
- { "\033Oq", KEYC_KP_ONE },
- { "\033Or", KEYC_KP_TWO },
- { "\033Os", KEYC_KP_THREE },
- { "\033OM", KEYC_KP_ENTER },
- { "\033Op", KEYC_KP_ZERO },
- { "\033On", KEYC_KP_PERIOD },
+ { "\033Oo", KEYC_KP_SLASH|KEYC_KEYPAD },
+ { "\033Oj", KEYC_KP_STAR|KEYC_KEYPAD },
+ { "\033Om", KEYC_KP_MINUS|KEYC_KEYPAD },
+ { "\033Ow", KEYC_KP_SEVEN|KEYC_KEYPAD },
+ { "\033Ox", KEYC_KP_EIGHT|KEYC_KEYPAD },
+ { "\033Oy", KEYC_KP_NINE|KEYC_KEYPAD },
+ { "\033Ok", KEYC_KP_PLUS|KEYC_KEYPAD },
+ { "\033Ot", KEYC_KP_FOUR|KEYC_KEYPAD },
+ { "\033Ou", KEYC_KP_FIVE|KEYC_KEYPAD },
+ { "\033Ov", KEYC_KP_SIX|KEYC_KEYPAD },
+ { "\033Oq", KEYC_KP_ONE|KEYC_KEYPAD },
+ { "\033Or", KEYC_KP_TWO|KEYC_KEYPAD },
+ { "\033Os", KEYC_KP_THREE|KEYC_KEYPAD },
+ { "\033OM", KEYC_KP_ENTER|KEYC_KEYPAD },
+ { "\033Op", KEYC_KP_ZERO|KEYC_KEYPAD },
+ { "\033On", KEYC_KP_PERIOD|KEYC_KEYPAD },
/* Arrow keys. */
- { "\033OA", KEYC_UP },
- { "\033OB", KEYC_DOWN },
- { "\033OC", KEYC_RIGHT },
- { "\033OD", KEYC_LEFT },
+ { "\033OA", KEYC_UP|KEYC_CURSOR },
+ { "\033OB", KEYC_DOWN|KEYC_CURSOR },
+ { "\033OC", KEYC_RIGHT|KEYC_CURSOR },
+ { "\033OD", KEYC_LEFT|KEYC_CURSOR },
- { "\033[A", KEYC_UP },
- { "\033[B", KEYC_DOWN },
- { "\033[C", KEYC_RIGHT },
- { "\033[D", KEYC_LEFT },
+ { "\033[A", KEYC_UP|KEYC_CURSOR },
+ { "\033[B", KEYC_DOWN|KEYC_CURSOR },
+ { "\033[C", KEYC_RIGHT|KEYC_CURSOR },
+ { "\033[D", KEYC_LEFT|KEYC_CURSOR },
/* Other (xterm) "cursor" keys. */
{ "\033OH", KEYC_HOME },
@@ -182,11 +185,59 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = {
{ "\033[201~", KEYC_PASTE_END },
};
+/* Default xterm keys. */
+struct tty_default_key_xterm {
+ const char *template;
+ key_code key;
+};
+static const struct tty_default_key_xterm tty_default_xterm_keys[] = {
+ { "\033[1;_P", KEYC_F1 },
+ { "\033O1;_P", KEYC_F1 },
+ { "\033O_P", KEYC_F1 },
+ { "\033[1;_Q", KEYC_F2 },
+ { "\033O1;_Q", KEYC_F2 },
+ { "\033O_Q", KEYC_F2 },
+ { "\033[1;_R", KEYC_F3 },
+ { "\033O1;_R", KEYC_F3 },
+ { "\033O_R", KEYC_F3 },
+ { "\033[1;_S", KEYC_F4 },
+ { "\033O1;_S", KEYC_F4 },
+ { "\033O_S", KEYC_F4 },
+ { "\033[15;_~", KEYC_F5 },
+ { "\033[17;_~", KEYC_F6 },
+ { "\033[18;_~", KEYC_F7 },
+ { "\033[19;_~", KEYC_F8 },
+ { "\033[20;_~", KEYC_F9 },
+ { "\033[21;_~", KEYC_F10 },
+ { "\033[23;_~", KEYC_F11 },
+ { "\033[24;_~", KEYC_F12 },
+ { "\033[1;_A", KEYC_UP },
+ { "\033[1;_B", KEYC_DOWN },
+ { "\033[1;_C", KEYC_RIGHT },
+ { "\033[1;_D", KEYC_LEFT },
+ { "\033[1;_H", KEYC_HOME },
+ { "\033[1;_F", KEYC_END },
+ { "\033[5;_~", KEYC_PPAGE },
+ { "\033[6;_~", KEYC_NPAGE },
+ { "\033[2;_~", KEYC_IC },
+ { "\033[3;_~", KEYC_DC },
+};
+static const key_code tty_default_xterm_modifiers[] = {
+ 0,
+ 0,
+ KEYC_SHIFT,
+ KEYC_META|KEYC_IMPLIED_META,
+ KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META,
+ KEYC_CTRL,
+ KEYC_SHIFT|KEYC_CTRL,
+ KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
+ KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL
+};
+
/*
- * Default terminfo(5) keys. Any keys that have builtin modifiers
- * (that is, where the key itself contains the modifiers) has the
- * KEYC_XTERM flag set so a leading escape is not treated as meta (and
- * probably removed).
+ * Default terminfo(5) keys. Any keys that have builtin modifiers (that is,
+ * where the key itself contains the modifiers) has the KEYC_XTERM flag set so
+ * a leading escape is not treated as meta (and probably removed).
*/
struct tty_default_key_code {
enum tty_code_code code;
@@ -207,61 +258,61 @@ static const struct tty_default_key_code tty_default_code_keys[] = {
{ TTYC_KF11, KEYC_F11 },
{ TTYC_KF12, KEYC_F12 },
- { TTYC_KF13, KEYC_F1|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF14, KEYC_F2|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF15, KEYC_F3|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF16, KEYC_F4|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF17, KEYC_F5|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF18, KEYC_F6|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF19, KEYC_F7|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF20, KEYC_F8|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF21, KEYC_F9|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF22, KEYC_F10|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF23, KEYC_F11|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF24, KEYC_F12|KEYC_SHIFT|KEYC_XTERM },
-
- { TTYC_KF25, KEYC_F1|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF26, KEYC_F2|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF27, KEYC_F3|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF28, KEYC_F4|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF29, KEYC_F5|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF30, KEYC_F6|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF31, KEYC_F7|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF32, KEYC_F8|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF33, KEYC_F9|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF34, KEYC_F10|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF35, KEYC_F11|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF36, KEYC_F12|KEYC_CTRL|KEYC_XTERM },
-
- { TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
-
- { TTYC_KF49, KEYC_F1|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF50, KEYC_F2|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF51, KEYC_F3|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF52, KEYC_F4|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF53, KEYC_F5|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF54, KEYC_F6|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF55, KEYC_F7|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF56, KEYC_F8|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF57, KEYC_F9|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF58, KEYC_F10|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF59, KEYC_F11|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KF60, KEYC_F12|KEYC_ESCAPE|KEYC_XTERM },
-
- { TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
+ { TTYC_KF13, KEYC_F1|KEYC_SHIFT },
+ { TTYC_KF14, KEYC_F2|KEYC_SHIFT },
+ { TTYC_KF15, KEYC_F3|KEYC_SHIFT },
+ { TTYC_KF16, KEYC_F4|KEYC_SHIFT },
+ { TTYC_KF17, KEYC_F5|KEYC_SHIFT },
+ { TTYC_KF18, KEYC_F6|KEYC_SHIFT },
+ { TTYC_KF19, KEYC_F7|KEYC_SHIFT },
+ { TTYC_KF20, KEYC_F8|KEYC_SHIFT },
+ { TTYC_KF21, KEYC_F9|KEYC_SHIFT },
+ { TTYC_KF22, KEYC_F10|KEYC_SHIFT },
+ { TTYC_KF23, KEYC_F11|KEYC_SHIFT },
+ { TTYC_KF24, KEYC_F12|KEYC_SHIFT },
+
+ { TTYC_KF25, KEYC_F1|KEYC_CTRL },
+ { TTYC_KF26, KEYC_F2|KEYC_CTRL },
+ { TTYC_KF27, KEYC_F3|KEYC_CTRL },
+ { TTYC_KF28, KEYC_F4|KEYC_CTRL },
+ { TTYC_KF29, KEYC_F5|KEYC_CTRL },
+ { TTYC_KF30, KEYC_F6|KEYC_CTRL },
+ { TTYC_KF31, KEYC_F7|KEYC_CTRL },
+ { TTYC_KF32, KEYC_F8|KEYC_CTRL },
+ { TTYC_KF33, KEYC_F9|KEYC_CTRL },
+ { TTYC_KF34, KEYC_F10|KEYC_CTRL },
+ { TTYC_KF35, KEYC_F11|KEYC_CTRL },
+ { TTYC_KF36, KEYC_F12|KEYC_CTRL },
+
+ { TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL },
+
+ { TTYC_KF49, KEYC_F1|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF50, KEYC_F2|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF51, KEYC_F3|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF52, KEYC_F4|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF53, KEYC_F5|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF54, KEYC_F6|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF55, KEYC_F7|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF56, KEYC_F8|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF57, KEYC_F9|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF58, KEYC_F10|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF59, KEYC_F11|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KF60, KEYC_F12|KEYC_META|KEYC_IMPLIED_META },
+
+ { TTYC_KF61, KEYC_F1|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
+ { TTYC_KF62, KEYC_F2|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
+ { TTYC_KF63, KEYC_F3|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
{ TTYC_KICH1, KEYC_IC },
{ TTYC_KDCH1, KEYC_DC },
@@ -272,74 +323,74 @@ static const struct tty_default_key_code tty_default_code_keys[] = {
{ TTYC_KCBT, KEYC_BTAB },
/* Arrow keys from terminfo. */
- { TTYC_KCUU1, KEYC_UP },
- { TTYC_KCUD1, KEYC_DOWN },
- { TTYC_KCUB1, KEYC_LEFT },
- { TTYC_KCUF1, KEYC_RIGHT },
+ { TTYC_KCUU1, KEYC_UP|KEYC_CURSOR },
+ { TTYC_KCUD1, KEYC_DOWN|KEYC_CURSOR },
+ { TTYC_KCUB1, KEYC_LEFT|KEYC_CURSOR },
+ { TTYC_KCUF1, KEYC_RIGHT|KEYC_CURSOR },
/* Key and modifier capabilities. */
- { TTYC_KDC2, KEYC_DC|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KDC3, KEYC_DC|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KDC5, KEYC_DC|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KDC7, KEYC_DC|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KIND, KEYC_DOWN|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KDN3, KEYC_DOWN|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KDN5, KEYC_DOWN|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KDN7, KEYC_DOWN|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KEND2, KEYC_END|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KEND3, KEYC_END|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KEND5, KEYC_END|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KEND7, KEYC_END|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KHOM3, KEYC_HOME|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KHOM5, KEYC_HOME|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KHOM7, KEYC_HOME|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KIC2, KEYC_IC|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KIC3, KEYC_IC|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KIC5, KEYC_IC|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KIC7, KEYC_IC|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KLFT3, KEYC_LEFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KLFT7, KEYC_LEFT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KNXT3, KEYC_NPAGE|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KNXT7, KEYC_NPAGE|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KPRV3, KEYC_PPAGE|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KPRV7, KEYC_PPAGE|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KRIT3, KEYC_RIGHT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KRIT7, KEYC_RIGHT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KRI, KEYC_UP|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KUP2, KEYC_UP|KEYC_SHIFT|KEYC_XTERM },
- { TTYC_KUP3, KEYC_UP|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
- { TTYC_KUP5, KEYC_UP|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
- { TTYC_KUP7, KEYC_UP|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
+ { TTYC_KDC2, KEYC_DC|KEYC_SHIFT },
+ { TTYC_KDC3, KEYC_DC|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KDC5, KEYC_DC|KEYC_CTRL },
+ { TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KDC7, KEYC_DC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KIND, KEYC_DOWN|KEYC_SHIFT },
+ { TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT },
+ { TTYC_KDN3, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KDN5, KEYC_DOWN|KEYC_CTRL },
+ { TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KDN7, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KEND2, KEYC_END|KEYC_SHIFT },
+ { TTYC_KEND3, KEYC_END|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KEND5, KEYC_END|KEYC_CTRL },
+ { TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KEND7, KEYC_END|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT },
+ { TTYC_KHOM3, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KHOM5, KEYC_HOME|KEYC_CTRL },
+ { TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KHOM7, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KIC2, KEYC_IC|KEYC_SHIFT },
+ { TTYC_KIC3, KEYC_IC|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KIC5, KEYC_IC|KEYC_CTRL },
+ { TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KIC7, KEYC_IC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT },
+ { TTYC_KLFT3, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL },
+ { TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KLFT7, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT },
+ { TTYC_KNXT3, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL },
+ { TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KNXT7, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT },
+ { TTYC_KPRV3, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL },
+ { TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KPRV7, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT },
+ { TTYC_KRIT3, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL },
+ { TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KRIT7, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
+ { TTYC_KRI, KEYC_UP|KEYC_SHIFT },
+ { TTYC_KUP2, KEYC_UP|KEYC_SHIFT },
+ { TTYC_KUP3, KEYC_UP|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
+ { TTYC_KUP5, KEYC_UP|KEYC_CTRL },
+ { TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KUP7, KEYC_UP|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
};
/* Add key to tree. */
@@ -350,7 +401,7 @@ tty_keys_add(struct tty *tty, const char *s, key_code key)
size_t size;
const char *keystr;
- keystr = key_string_lookup_key(key);
+ keystr = key_string_lookup_key(key, 1);
if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
log_debug("new key %s: 0x%llx (%s)", s, key, keystr);
tty_keys_add1(&tty->key_tree, s, key);
@@ -403,17 +454,30 @@ void
tty_keys_build(struct tty *tty)
{
const struct tty_default_key_raw *tdkr;
+ const struct tty_default_key_xterm *tdkx;
const struct tty_default_key_code *tdkc;
- u_int i;
+ u_int i, j;
const char *s;
struct options_entry *o;
struct options_array_item *a;
union options_value *ov;
+ char copy[16];
+ key_code key;
if (tty->key_tree != NULL)
tty_keys_free(tty);
tty->key_tree = NULL;
+ for (i = 0; i < nitems(tty_default_xterm_keys); i++) {
+ tdkx = &tty_default_xterm_keys[i];
+ for (j = 2; j < nitems(tty_default_xterm_modifiers); j++) {
+ strlcpy(copy, tdkx->template, sizeof copy);
+ copy[strcspn(copy, "_")] = '0' + j;
+
+ key = tdkx->key|tty_default_xterm_modifiers[j];
+ tty_keys_add(tty, copy, key);
+ }
+ }
for (i = 0; i < nitems(tty_default_raw_keys); i++) {
tdkr = &tty_default_raw_keys[i];
@@ -516,7 +580,6 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
enum utf8_state more;
u_int i;
wchar_t wc;
- int n;
log_debug("%s: next key is %zu (%.*s) (expired=%d)", c->name, len,
(int)len, buf, expired);
@@ -534,13 +597,6 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
return (0);
}
- /* Is this an an xterm(1) key? */
- n = xterm_keys_find(buf, len, size, key);
- if (n == 0)
- return (0);
- if (n == 1 && !expired)
- return (1);
-
/* Is this valid UTF-8? */
more = utf8_open(&ud, (u_char)*buf);
if (more == UTF8_MORE) {
@@ -637,6 +693,16 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}
+ /* Is this an extended key press? */
+ switch (tty_keys_extended_key(tty, buf, len, &size, &key)) {
+ case 0: /* yes */
+ goto complete_key;
+ case -1: /* no, or not valid */
+ break;
+ case 1: /* partial */
+ goto partial_key;
+ }
+
first_key:
/* Try to lookup complete key. */
n = tty_keys_next1(tty, buf, len, &key, &size, expired);
@@ -653,7 +719,7 @@ first_key:
/* Look for a key without the escape. */
n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired);
if (n == 0) { /* found */
- if (key & KEYC_XTERM) {
+ if (key & KEYC_IMPLIED_META) {
/*
* We want the escape key as well as the xterm
* key, because the xterm sequence implicitly
@@ -665,7 +731,7 @@ first_key:
size = 1;
goto complete_key;
}
- key |= KEYC_ESCAPE;
+ key |= KEYC_META;
size++;
goto complete_key;
}
@@ -678,7 +744,7 @@ first_key:
* escape). So pass it through even if the timer has not expired.
*/
if (*buf == '\033' && len >= 2) {
- key = (u_char)buf[1] | KEYC_ESCAPE;
+ key = (u_char)buf[1] | KEYC_META;
size = 2;
} else {
key = (u_char)buf[0];
@@ -723,7 +789,7 @@ complete_key:
*/
bspace = tty->tio.c_cc[VERASE];
if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace)
- key = (key & KEYC_MASK_MOD) | KEYC_BSPACE;
+ key = (key & KEYC_MASK_MODIFIERS)|KEYC_BSPACE;
/* Remove data from buffer. */
evbuffer_drain(tty->in, size);
@@ -775,6 +841,96 @@ tty_keys_callback(__unused int fd, __unused short events, void *data)
}
/*
+ * Handle extended key input. This has two forms: \033[27;m;k~ and \033[k;mu,
+ * where k is key as a number and m is a modifier. Returns 0 for success, -1
+ * for failure, 1 for partial;
+ */
+static int
+tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
+ size_t *size, key_code *key)
+{
+ struct client *c = tty->client;
+ size_t end;
+ u_int number, modifiers;
+ char tmp[64];
+
+ *size = 0;
+
+ /* First two bytes are always \033[. */
+ if (buf[0] != '\033')
+ return (-1);
+ if (len == 1)
+ return (1);
+ if (buf[1] != '[')
+ return (-1);
+ if (len == 2)
+ return (1);
+
+ /*
+ * Look for a terminator. Stop at either '~' or anything that isn't a
+ * number or ';'.
+ */
+ for (end = 2; end < len && end != sizeof tmp; end++) {
+ if (buf[end] == '~')
+ break;
+ if (!isdigit((u_char)buf[end]) && buf[end] != ';')
+ break;
+ }
+ if (end == len)
+ return (1);
+ if (end == sizeof tmp || (buf[end] != '~' && buf[end] != 'u'))
+ return (-1);
+
+ /* Copy to the buffer. */
+ memcpy(tmp, buf + 2, end);
+ tmp[end] = '\0';
+
+ /* Try to parse either form of key. */
+ if (buf[end] == '~') {
+ if (sscanf(tmp, "27;%u;%u", &modifiers, &number) != 2)
+ return (-1);
+ } else {
+ if (sscanf(tmp ,"%u;%u", &number, &modifiers) != 2)
+ return (-1);
+ }
+ *size = end + 1;
+
+ /* Store the key and modifiers. */
+ *key = number;
+ switch (modifiers) {
+ case 2:
+ (*key) |= KEYC_SHIFT;
+ break;
+ case 3:
+ (*key) |= (KEYC_META|KEYC_IMPLIED_META);
+ break;
+ case 4:
+ (*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
+ break;
+ case 5:
+ (*key) |= KEYC_CTRL;
+ break;
+ case 6:
+ (*key) |= (KEYC_SHIFT|KEYC_CTRL);
+ break;
+ case 7:
+ (*key) |= (KEYC_META|KEYC_CTRL);
+ break;
+ case 8:
+ (*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
+ break;
+ default:
+ *key = KEYC_NONE;
+ break;
+ }
+ if (log_get_level() != 0) {
+ log_debug("%s: extended key %.*s is %llx (%s)", c->name,
+ (int)*size, buf, *key, key_string_lookup_key(*key, 1));
+ }
+ return (0);
+}
+
+/*
* Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
* (probably a mouse sequence but need more data).
*/
@@ -1137,7 +1293,7 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
else if (strncmp(tmp, "tmux ", 5) == 0)
tty_default_features(&c->term_features, "tmux", 0);
else if (strncmp(tmp, "XTerm(", 6) == 0)
- tty_default_features(&c->term_features, "xterm", 0);
+ tty_default_features(&c->term_features, "XTerm", 0);
else if (strncmp(tmp, "mintty ", 7) == 0)
tty_default_features(&c->term_features, "mintty", 0);
log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf);