diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2020-05-16 16:32:22 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2020-05-16 16:32:22 +0000 |
commit | 936d6a1f1099b65aad1eea39698c2dbf8fe346c6 (patch) | |
tree | 901ce76386ec3ef2d6e3f08bfa69f041639135f1 /usr.bin | |
parent | eecb5e9b22b9c3f489053f463d254665407390b4 (diff) |
Recognise extended key sequences on input (both the forms xterm offers).
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/cmd-send-keys.c | 6 | ||||
-rw-r--r-- | usr.bin/tmux/tty-keys.c | 105 |
2 files changed, 106 insertions, 5 deletions
diff --git a/usr.bin/tmux/cmd-send-keys.c b/usr.bin/tmux/cmd-send-keys.c index 5abf3502f6e..e58294cbb17 100644 --- a/usr.bin/tmux/cmd-send-keys.c +++ b/usr.bin/tmux/cmd-send-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-send-keys.c,v 1.61 2020/04/14 13:22:05 nicm Exp $ */ +/* $OpenBSD: cmd-send-keys.c,v 1.62 2020/05/16 16:32:21 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -71,9 +71,7 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after, wme = TAILQ_FIRST(&wp->modes); if (wme == NULL || wme->mode->key_table == NULL) { - if (options_get_number(wp->window->options, "xterm-keys")) - key |= KEYC_XTERM; - if (window_pane_key(wp, tc, s, wl, key, NULL) != 0) + if (window_pane_key(wp, tc, s, wl, key|KEYC_XTERM, NULL) != 0) return (NULL); return (item); } diff --git a/usr.bin/tmux/tty-keys.c b/usr.bin/tmux/tty-keys.c index c9b6af525a8..ac76fe76805 100644 --- a/usr.bin/tmux/tty-keys.c +++ b/usr.bin/tmux/tty-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-keys.c,v 1.132 2020/05/16 16:30:59 nicm Exp $ */ +/* $OpenBSD: tty-keys.c,v 1.133 2020/05/16 16:32:21 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -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, @@ -690,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); @@ -828,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|KEYC_XTERM; + switch (modifiers) { + case 2: + (*key) |= KEYC_SHIFT; + break; + case 3: + (*key) |= KEYC_ESCAPE; + break; + case 4: + (*key) |= (KEYC_SHIFT|KEYC_ESCAPE); + break; + case 5: + (*key) |= KEYC_CTRL; + break; + case 6: + (*key) |= (KEYC_SHIFT|KEYC_CTRL); + break; + case 7: + (*key) |= (KEYC_ESCAPE|KEYC_CTRL); + break; + case 8: + (*key) |= (KEYC_SHIFT|KEYC_ESCAPE|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)); + } + return (0); +} + +/* * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial * (probably a mouse sequence but need more data). */ |