summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2020-05-16 16:32:22 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2020-05-16 16:32:22 +0000
commit936d6a1f1099b65aad1eea39698c2dbf8fe346c6 (patch)
tree901ce76386ec3ef2d6e3f08bfa69f041639135f1 /usr.bin
parenteecb5e9b22b9c3f489053f463d254665407390b4 (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.c6
-rw-r--r--usr.bin/tmux/tty-keys.c105
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).
*/