summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2020-05-16 16:31:00 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2020-05-16 16:31:00 +0000
commiteecb5e9b22b9c3f489053f463d254665407390b4 (patch)
treed83bcd93639c8c693272c6316cbcb8c20de1258c /usr.bin
parent44227a542147bb986da4a1643446ee89b5cb671c (diff)
xterm-keys has been on by default for five years and all other modern
terminals use these key sequences by default. Merge the code into the main tty and input tree processing (converting the latter to use a tree rather than a table at the same time) and make the option a no-op.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/tmux/Makefile5
-rw-r--r--usr.bin/tmux/input-keys.c510
-rw-r--r--usr.bin/tmux/options-table.c7
-rw-r--r--usr.bin/tmux/popup.c4
-rw-r--r--usr.bin/tmux/server.c3
-rw-r--r--usr.bin/tmux/tmux.112
-rw-r--r--usr.bin/tmux/tmux.h12
-rw-r--r--usr.bin/tmux/tty-keys.c137
-rw-r--r--usr.bin/tmux/xterm-keys.c252
9 files changed, 482 insertions, 460 deletions
diff --git a/usr.bin/tmux/Makefile b/usr.bin/tmux/Makefile
index d8ae81bdb36..1b47fc04c73 100644
--- a/usr.bin/tmux/Makefile
+++ b/usr.bin/tmux/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.105 2020/05/16 16:02:24 nicm Exp $
+# $OpenBSD: Makefile,v 1.106 2020/05/16 16:30:59 nicm Exp $
PROG= tmux
SRCS= alerts.c \
@@ -123,8 +123,7 @@ SRCS= alerts.c \
window-customize.c \
window-tree.c \
window.c \
- xmalloc.c \
- xterm-keys.c
+ xmalloc.c
CDIAGFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CDIAGFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
diff --git a/usr.bin/tmux/input-keys.c b/usr.bin/tmux/input-keys.c
index be7905a127c..78a0a4e031e 100644
--- a/usr.bin/tmux/input-keys.c
+++ b/usr.bin/tmux/input-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: input-keys.c,v 1.71 2020/04/07 13:38:30 nicm Exp $ */
+/* $OpenBSD: input-keys.c,v 1.72 2020/05/16 16:30:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -33,112 +33,331 @@
static void input_key_mouse(struct window_pane *, struct mouse_event *);
-struct input_key_ent {
- key_code key;
- const char *data;
+/* Entry in the key tree. */
+struct input_key_entry {
+ key_code key;
+ const char *data;
- int flags;
-#define INPUTKEY_KEYPAD 0x1 /* keypad key */
-#define INPUTKEY_CURSOR 0x2 /* cursor key */
+ RB_ENTRY(input_key_entry) entry;
};
+RB_HEAD(input_key_tree, input_key_entry);
-static const struct input_key_ent input_keys[] = {
+/* Tree of input keys. */
+static int input_key_cmp(struct input_key_entry *,
+ struct input_key_entry *);
+RB_GENERATE_STATIC(input_key_tree, input_key_entry, entry, input_key_cmp);
+struct input_key_tree input_key_tree = RB_INITIALIZER(&input_key_tree);
+
+/* List of default keys, the tree is built from this. */
+static struct input_key_entry input_key_defaults[] = {
/* Paste keys. */
- { KEYC_PASTE_START, "\033[200~", 0 },
- { KEYC_PASTE_END, "\033[201~", 0 },
+ { .key = KEYC_PASTE_START,
+ .data = "\033[200~"
+ },
+ { .key = KEYC_PASTE_END,
+ .data = "\033[201~"
+ },
/* Function keys. */
- { KEYC_F1, "\033OP", 0 },
- { KEYC_F2, "\033OQ", 0 },
- { KEYC_F3, "\033OR", 0 },
- { KEYC_F4, "\033OS", 0 },
- { KEYC_F5, "\033[15~", 0 },
- { KEYC_F6, "\033[17~", 0 },
- { KEYC_F7, "\033[18~", 0 },
- { KEYC_F8, "\033[19~", 0 },
- { KEYC_F9, "\033[20~", 0 },
- { KEYC_F10, "\033[21~", 0 },
- { KEYC_F11, "\033[23~", 0 },
- { KEYC_F12, "\033[24~", 0 },
- { KEYC_F1|KEYC_SHIFT, "\033[25~", 0 },
- { KEYC_F2|KEYC_SHIFT, "\033[26~", 0 },
- { KEYC_F3|KEYC_SHIFT, "\033[28~", 0 },
- { KEYC_F4|KEYC_SHIFT, "\033[29~", 0 },
- { KEYC_F5|KEYC_SHIFT, "\033[31~", 0 },
- { KEYC_F6|KEYC_SHIFT, "\033[32~", 0 },
- { KEYC_F7|KEYC_SHIFT, "\033[33~", 0 },
- { KEYC_F8|KEYC_SHIFT, "\033[34~", 0 },
- { KEYC_IC, "\033[2~", 0 },
- { KEYC_DC, "\033[3~", 0 },
- { KEYC_HOME, "\033[1~", 0 },
- { KEYC_END, "\033[4~", 0 },
- { KEYC_NPAGE, "\033[6~", 0 },
- { KEYC_PPAGE, "\033[5~", 0 },
- { KEYC_BTAB, "\033[Z", 0 },
-
- /*
- * Arrow keys. Cursor versions must come first. The codes are toggled
- * between CSI and SS3 versions when ctrl is pressed.
- */
- { KEYC_UP|KEYC_CTRL, "\033[A", INPUTKEY_CURSOR },
- { KEYC_DOWN|KEYC_CTRL, "\033[B", INPUTKEY_CURSOR },
- { KEYC_RIGHT|KEYC_CTRL, "\033[C", INPUTKEY_CURSOR },
- { KEYC_LEFT|KEYC_CTRL, "\033[D", INPUTKEY_CURSOR },
-
- { KEYC_UP, "\033OA", INPUTKEY_CURSOR },
- { KEYC_DOWN, "\033OB", INPUTKEY_CURSOR },
- { KEYC_RIGHT, "\033OC", INPUTKEY_CURSOR },
- { KEYC_LEFT, "\033OD", INPUTKEY_CURSOR },
-
- { KEYC_UP|KEYC_CTRL, "\033OA", 0 },
- { KEYC_DOWN|KEYC_CTRL, "\033OB", 0 },
- { KEYC_RIGHT|KEYC_CTRL, "\033OC", 0 },
- { KEYC_LEFT|KEYC_CTRL, "\033OD", 0 },
-
- { KEYC_UP, "\033[A", 0 },
- { KEYC_DOWN, "\033[B", 0 },
- { KEYC_RIGHT, "\033[C", 0 },
- { KEYC_LEFT, "\033[D", 0 },
-
- /* Keypad keys. Keypad versions must come first. */
- { KEYC_KP_SLASH, "\033Oo", INPUTKEY_KEYPAD },
- { KEYC_KP_STAR, "\033Oj", INPUTKEY_KEYPAD },
- { KEYC_KP_MINUS, "\033Om", INPUTKEY_KEYPAD },
- { KEYC_KP_SEVEN, "\033Ow", INPUTKEY_KEYPAD },
- { KEYC_KP_EIGHT, "\033Ox", INPUTKEY_KEYPAD },
- { KEYC_KP_NINE, "\033Oy", INPUTKEY_KEYPAD },
- { KEYC_KP_PLUS, "\033Ok", INPUTKEY_KEYPAD },
- { KEYC_KP_FOUR, "\033Ot", INPUTKEY_KEYPAD },
- { KEYC_KP_FIVE, "\033Ou", INPUTKEY_KEYPAD },
- { KEYC_KP_SIX, "\033Ov", INPUTKEY_KEYPAD },
- { KEYC_KP_ONE, "\033Oq", INPUTKEY_KEYPAD },
- { KEYC_KP_TWO, "\033Or", INPUTKEY_KEYPAD },
- { KEYC_KP_THREE, "\033Os", INPUTKEY_KEYPAD },
- { KEYC_KP_ENTER, "\033OM", INPUTKEY_KEYPAD },
- { KEYC_KP_ZERO, "\033Op", INPUTKEY_KEYPAD },
- { KEYC_KP_PERIOD, "\033On", INPUTKEY_KEYPAD },
-
- { KEYC_KP_SLASH, "/", 0 },
- { KEYC_KP_STAR, "*", 0 },
- { KEYC_KP_MINUS, "-", 0 },
- { KEYC_KP_SEVEN, "7", 0 },
- { KEYC_KP_EIGHT, "8", 0 },
- { KEYC_KP_NINE, "9", 0 },
- { KEYC_KP_PLUS, "+", 0 },
- { KEYC_KP_FOUR, "4", 0 },
- { KEYC_KP_FIVE, "5", 0 },
- { KEYC_KP_SIX, "6", 0 },
- { KEYC_KP_ONE, "1", 0 },
- { KEYC_KP_TWO, "2", 0 },
- { KEYC_KP_THREE, "3", 0 },
- { KEYC_KP_ENTER, "\n", 0 },
- { KEYC_KP_ZERO, "0", 0 },
- { KEYC_KP_PERIOD, ".", 0 },
+ { .key = KEYC_F1,
+ .data = "\033OP"
+ },
+ { .key = KEYC_F2,
+ .data = "\033OQ"
+ },
+ { .key = KEYC_F3,
+ .data = "\033OR"
+ },
+ { .key = KEYC_F4,
+ .data = "\033OS"
+ },
+ { .key = KEYC_F5,
+ .data = "\033[15~"
+ },
+ { .key = KEYC_F6,
+ .data = "\033[17~"
+ },
+ { .key = KEYC_F7,
+ .data = "\033[18~"
+ },
+ { .key = KEYC_F8,
+ .data = "\033[19~"
+ },
+ { .key = KEYC_F9,
+ .data = "\033[20~"
+ },
+ { .key = KEYC_F10,
+ .data = "\033[21~"
+ },
+ { .key = KEYC_F11,
+ .data = "\033[23~"
+ },
+ { .key = KEYC_F12,
+ .data = "\033[24~"
+ },
+ { .key = KEYC_F1|KEYC_SHIFT,
+ .data = "\033[25~"
+ },
+ { .key = KEYC_F2|KEYC_SHIFT,
+ .data = "\033[26~"
+ },
+ { .key = KEYC_F3|KEYC_SHIFT,
+ .data = "\033[28~"
+ },
+ { .key = KEYC_F4|KEYC_SHIFT,
+ .data = "\033[29~"
+ },
+ { .key = KEYC_F5|KEYC_SHIFT,
+ .data = "\033[31~"
+ },
+ { .key = KEYC_F6|KEYC_SHIFT,
+ .data = "\033[32~"
+ },
+ { .key = KEYC_F7|KEYC_SHIFT,
+ .data = "\033[33~"
+ },
+ { .key = KEYC_F8|KEYC_SHIFT,
+ .data = "\033[34~"
+ },
+ { .key = KEYC_IC,
+ .data = "\033[2~"
+ },
+ { .key = KEYC_DC,
+ .data = "\033[3~"
+ },
+ { .key = KEYC_HOME,
+ .data = "\033[1~"
+ },
+ { .key = KEYC_END,
+ .data = "\033[4~"
+ },
+ { .key = KEYC_NPAGE,
+ .data = "\033[6~"
+ },
+ { .key = KEYC_PPAGE,
+ .data = "\033[5~"
+ },
+ { .key = KEYC_BTAB,
+ .data = "\033[Z"
+ },
+
+ /* Arrow keys. */
+ { .key = KEYC_UP|KEYC_CURSOR,
+ .data = "\033OA"
+ },
+ { .key = KEYC_DOWN|KEYC_CURSOR,
+ .data = "\033OB"
+ },
+ { .key = KEYC_RIGHT|KEYC_CURSOR,
+ .data = "\033OC"
+ },
+ { .key = KEYC_LEFT|KEYC_CURSOR,
+ .data = "\033OD"
+ },
+ { .key = KEYC_UP,
+ .data = "\033[A"
+ },
+ { .key = KEYC_DOWN,
+ .data = "\033[B"
+ },
+ { .key = KEYC_RIGHT,
+ .data = "\033[C"
+ },
+ { .key = KEYC_LEFT,
+ .data = "\033[D"
+ },
+
+ /* Keypad keys. */
+ { .key = KEYC_KP_SLASH|KEYC_KEYPAD,
+ .data = "\033Oo"
+ },
+ { .key = KEYC_KP_STAR|KEYC_KEYPAD,
+ .data = "\033Oj"
+ },
+ { .key = KEYC_KP_MINUS|KEYC_KEYPAD,
+ .data = "\033Om"
+ },
+ { .key = KEYC_KP_SEVEN|KEYC_KEYPAD,
+ .data = "\033Ow"
+ },
+ { .key = KEYC_KP_EIGHT|KEYC_KEYPAD,
+ .data = "\033Ox"
+ },
+ { .key = KEYC_KP_NINE|KEYC_KEYPAD,
+ .data = "\033Oy"
+ },
+ { .key = KEYC_KP_PLUS|KEYC_KEYPAD,
+ .data = "\033Ok"
+ },
+ { .key = KEYC_KP_FOUR|KEYC_KEYPAD,
+ .data = "\033Ot"
+ },
+ { .key = KEYC_KP_FIVE|KEYC_KEYPAD,
+ .data = "\033Ou"
+ },
+ { .key = KEYC_KP_SIX|KEYC_KEYPAD,
+ .data = "\033Ov"
+ },
+ { .key = KEYC_KP_ONE|KEYC_KEYPAD,
+ .data = "\033Oq"
+ },
+ { .key = KEYC_KP_TWO|KEYC_KEYPAD,
+ .data = "\033Or"
+ },
+ { .key = KEYC_KP_THREE|KEYC_KEYPAD,
+ .data = "\033Os"
+ },
+ { .key = KEYC_KP_ENTER|KEYC_KEYPAD,
+ .data = "\033OM"
+ },
+ { .key = KEYC_KP_ZERO|KEYC_KEYPAD,
+ .data = "\033Op"
+ },
+ { .key = KEYC_KP_PERIOD|KEYC_KEYPAD,
+ .data = "\033On"
+ },
+ { .key = KEYC_KP_SLASH,
+ .data = "/"
+ },
+ { .key = KEYC_KP_STAR,
+ .data = "*"
+ },
+ { .key = KEYC_KP_MINUS,
+ .data = "-"
+ },
+ { .key = KEYC_KP_SEVEN,
+ .data = "7"
+ },
+ { .key = KEYC_KP_EIGHT,
+ .data = "8"
+ },
+ { .key = KEYC_KP_NINE,
+ .data = "9"
+ },
+ { .key = KEYC_KP_PLUS,
+ .data = "+"
+ },
+ { .key = KEYC_KP_FOUR,
+ .data = "4"
+ },
+ { .key = KEYC_KP_FIVE,
+ .data = "5"
+ },
+ { .key = KEYC_KP_SIX,
+ .data = "6"
+ },
+ { .key = KEYC_KP_ONE,
+ .data = "1"
+ },
+ { .key = KEYC_KP_TWO,
+ .data = "2"
+ },
+ { .key = KEYC_KP_THREE,
+ .data = "3"
+ },
+ { .key = KEYC_KP_ENTER,
+ .data = "\n"
+ },
+ { .key = KEYC_KP_ZERO,
+ .data = "0"
+ },
+ { .key = KEYC_KP_PERIOD,
+ .data = "."
+ },
+
+ /* Keys with an embedded modifier. */
+ { .key = KEYC_F1|KEYC_XTERM,
+ .data = "\033[1;_P"
+ },
+ { .key = KEYC_F2|KEYC_XTERM,
+ .data = "\033[1;_Q"
+ },
+ { .key = KEYC_F3|KEYC_XTERM,
+ .data = "\033[1;_R"
+ },
+ { .key = KEYC_F4|KEYC_XTERM,
+ .data = "\033[1;_S"
+ },
+ { .key = KEYC_F5|KEYC_XTERM,
+ .data = "\033[15;_~"
+ },
+ { .key = KEYC_F6|KEYC_XTERM,
+ .data = "\033[17;_~"
+ },
+ { .key = KEYC_F7|KEYC_XTERM,
+ .data = "\033[18;_~"
+ },
+ { .key = KEYC_F8|KEYC_XTERM,
+ .data = "\033[19;_~"
+ },
+ { .key = KEYC_F9|KEYC_XTERM,
+ .data = "\033[20;_~"
+ },
+ { .key = KEYC_F10|KEYC_XTERM,
+ .data = "\033[21;_~"
+ },
+ { .key = KEYC_F11|KEYC_XTERM,
+ .data = "\033[23;_~"
+ },
+ { .key = KEYC_F12|KEYC_XTERM,
+ .data = "\033[24;_~"
+ },
+ { .key = KEYC_UP|KEYC_XTERM,
+ .data = "\033[1;_A"
+ },
+ { .key = KEYC_DOWN|KEYC_XTERM,
+ .data = "\033[1;_B"
+ },
+ { .key = KEYC_RIGHT|KEYC_XTERM,
+ .data = "\033[1;_C"
+ },
+ { .key = KEYC_LEFT|KEYC_XTERM,
+ .data = "\033[1;_D"
+ },
+ { .key = KEYC_HOME|KEYC_XTERM,
+ .data = "\033[1;_H"
+ },
+ { .key = KEYC_END|KEYC_XTERM,
+ .data = "\033[1;_F"
+ },
+ { .key = KEYC_PPAGE|KEYC_XTERM,
+ .data = "\033[5;_~"
+ },
+ { .key = KEYC_NPAGE|KEYC_XTERM,
+ .data = "\033[6;_~"
+ },
+ { .key = KEYC_IC|KEYC_XTERM,
+ .data = "\033[2;_~"
+ },
+ { .key = KEYC_DC|KEYC_XTERM,
+ .data = "\033[3;_~" }
};
+static const key_code input_key_modifiers[] = {
+ 0,
+ 0,
+ KEYC_SHIFT|KEYC_XTERM,
+ KEYC_ESCAPE|KEYC_XTERM,
+ KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM,
+ KEYC_CTRL|KEYC_XTERM,
+ KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM,
+ KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM,
+ KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM
+};
+
+/* Input key comparison function. */
+static int
+input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2)
+{
+ if (ike1->key < ike2->key)
+ return (-1);
+ if (ike1->key > ike2->key)
+ return (1);
+ return (0);
+}
/* Split a character into two UTF-8 bytes. */
static size_t
-input_split2(u_int c, u_char *dst)
+input_key_split2(u_int c, u_char *dst)
{
if (c > 0x7f) {
dst[0] = (c >> 6) | 0xc0;
@@ -149,32 +368,63 @@ input_split2(u_int c, u_char *dst)
return (1);
}
+/* Build input key tree. */
+void
+input_key_build(void)
+{
+ struct input_key_entry *ike, *new;
+ u_int i, j;
+ char *data;
+
+ for (i = 0; i < nitems(input_key_defaults); i++) {
+ ike = &input_key_defaults[i];
+ if (~ike->key & KEYC_XTERM) {
+ RB_INSERT(input_key_tree, &input_key_tree, ike);
+ continue;
+ }
+
+ for (j = 2; j < nitems(input_key_modifiers); j++) {
+ data = xstrdup(ike->data);
+ data[strcspn(data, "_")] = '0' + j;
+
+ new = xcalloc(1, sizeof *new);
+ new->key = ike->key|input_key_modifiers[j];
+ new->data = data;
+ RB_INSERT(input_key_tree, &input_key_tree, new);
+ }
+ }
+
+ RB_FOREACH(ike, input_key_tree, &input_key_tree) {
+ log_debug("%s: 0x%llx (%s) is %s", __func__, ike->key,
+ key_string_lookup_key(ike->key), ike->data);
+ }
+}
+
/* Translate a key code into an output key sequence for a pane. */
int
input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
{
- log_debug("writing key 0x%llx (%s) to %%%u", key,
- key_string_lookup_key(key), wp->id);
+ if (log_get_level() != 0) {
+ log_debug("writing key 0x%llx (%s) to %%%u", key,
+ key_string_lookup_key(key), wp->id);
+ }
if (KEYC_IS_MOUSE(key)) {
if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
input_key_mouse(wp, m);
return (0);
}
- return (input_key(wp, wp->screen, wp->event, key));
+ return (input_key(wp->screen, wp->event, key));
}
/* Translate a key code into an output key sequence. */
int
-input_key(struct window_pane *wp, struct screen *s, struct bufferevent *bev,
- key_code key)
+input_key(struct screen *s, struct bufferevent *bev, key_code key)
{
- const struct input_key_ent *ike;
- u_int i;
- size_t dlen;
- char *out;
- key_code justkey, newkey;
- struct utf8_data ud;
+ struct input_key_entry *ike, entry;
+ size_t datalen;
+ key_code justkey, newkey;
+ struct utf8_data ud;
/* Mouse keys need a pane. */
if (KEYC_IS_MOUSE(key))
@@ -217,43 +467,25 @@ input_key(struct window_pane *wp, struct screen *s, struct bufferevent *bev,
}
/*
- * Then try to look this up as an xterm key, if the flag to output them
- * is set.
+ * Look up in the tree. If not in application keypad or cursor mode,
+ * remove the flags from the key.
*/
- if (wp == NULL || options_get_number(wp->window->options, "xterm-keys")) {
- if ((out = xterm_keys_lookup(key)) != NULL) {
- bufferevent_write(bev, out, strlen(out));
- free(out);
- return (0);
- }
- }
- key &= ~KEYC_XTERM;
-
- /* Otherwise look the key up in the table. */
- for (i = 0; i < nitems(input_keys); i++) {
- ike = &input_keys[i];
-
- if ((ike->flags & INPUTKEY_KEYPAD) && (~s->mode & MODE_KKEYPAD))
- continue;
- if ((ike->flags & INPUTKEY_CURSOR) && (~s->mode & MODE_KCURSOR))
- continue;
-
- if ((key & KEYC_ESCAPE) && (ike->key | KEYC_ESCAPE) == key)
- break;
- if (ike->key == key)
- break;
- }
- if (i == nitems(input_keys)) {
+ if (~s->mode & MODE_KKEYPAD)
+ key &= ~KEYC_KEYPAD;
+ if (~s->mode & MODE_KCURSOR)
+ key &= ~KEYC_CURSOR;
+ entry.key = key;
+ if ((ike = RB_FIND(input_key_tree, &input_key_tree, &entry)) == NULL) {
log_debug("key 0x%llx missing", key);
return (-1);
}
- dlen = strlen(ike->data);
+ datalen = strlen(ike->data);
log_debug("found key 0x%llx: \"%s\"", key, ike->data);
/* Prefix a \033 for escape. */
if (key & KEYC_ESCAPE)
bufferevent_write(bev, "\033", 1);
- bufferevent_write(bev, ike->data, dlen);
+ bufferevent_write(bev, ike->data, datalen);
return (0);
}
@@ -309,9 +541,9 @@ input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33)
return (0);
len = xsnprintf(buf, sizeof buf, "\033[M");
- len += input_split2(m->b + 32, &buf[len]);
- len += input_split2(x + 33, &buf[len]);
- len += input_split2(y + 33, &buf[len]);
+ len += input_key_split2(m->b + 32, &buf[len]);
+ len += input_key_split2(x + 33, &buf[len]);
+ len += input_key_split2(y + 33, &buf[len]);
} else {
if (m->b > 223)
return (0);
diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c
index 51907ec4051..cfd4d304bb6 100644
--- a/usr.bin/tmux/options-table.c
+++ b/usr.bin/tmux/options-table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options-table.c,v 1.129 2020/05/16 16:26:34 nicm Exp $ */
+/* $OpenBSD: options-table.c,v 1.130 2020/05/16 16:30:59 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1053,11 +1053,12 @@ const struct options_table_entry options_table[] = {
"bottom."
},
- { .name = "xterm-keys",
+ { .name = "xterm-keys", /* no longer used */
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_WINDOW,
.default_num = 1,
- .text = "Whether xterm-style function key sequences should be sent."
+ .text = "Whether xterm-style function key sequences should be sent. "
+ "This option is no longer used."
},
/* Hook options. */
diff --git a/usr.bin/tmux/popup.c b/usr.bin/tmux/popup.c
index 20175b5dcfe..6966d8292f9 100644
--- a/usr.bin/tmux/popup.c
+++ b/usr.bin/tmux/popup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: popup.c,v 1.17 2020/05/16 16:13:09 nicm Exp $ */
+/* $OpenBSD: popup.c,v 1.18 2020/05/16 16:30:59 nicm Exp $ */
/*
* Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -329,7 +329,7 @@ popup_key_cb(struct client *c, struct key_event *event)
bufferevent_write(job_get_event(pd->job), buf, len);
return (0);
}
- input_key(NULL, &pd->s, job_get_event(pd->job), event->key);
+ input_key(&pd->s, job_get_event(pd->job), event->key);
return (0);
}
diff --git a/usr.bin/tmux/server.c b/usr.bin/tmux/server.c
index 0cfbb5fce48..3ccba1652f5 100644
--- a/usr.bin/tmux/server.c
+++ b/usr.bin/tmux/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.191 2020/05/16 16:07:55 nicm Exp $ */
+/* $OpenBSD: server.c,v 1.192 2020/05/16 16:30:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -199,6 +199,7 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
"tty ps", NULL) != 0)
fatal("pledge failed");
+ input_key_build();
RB_INIT(&windows);
RB_INIT(&all_window_panes);
TAILQ_INIT(&clients);
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index 7781f15bebc..972dec9dcef 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.770 2020/05/16 16:26:34 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.771 2020/05/16 16:30:59 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -4054,16 +4054,6 @@ option.
.Xc
If this option is set, searches will wrap around the end of the pane contents.
The default is on.
-.Pp
-.It Xo Ic xterm-keys
-.Op Ic on | off
-.Xc
-If this option is set,
-.Nm
-will generate
-.Xr xterm 1 -style
-function key sequences; these have a number included to indicate modifiers such
-as Shift, Alt or Ctrl.
.El
.Pp
Available pane options are:
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index ae5dde53643..a1fb1519853 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1043 2020/05/16 16:26:34 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1044 2020/05/16 16:30:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -123,6 +123,8 @@ struct winlink;
#define KEYC_SHIFT 0x0400000000000ULL
#define KEYC_XTERM 0x0800000000000ULL
#define KEYC_LITERAL 0x1000000000000ULL
+#define KEYC_KEYPAD 0x2000000000000ULL
+#define KEYC_CURSOR 0x4000000000000ULL
/* Available user keys. */
#define KEYC_NUSER 1000
@@ -2415,16 +2417,12 @@ void input_parse_screen(struct input_ctx *, struct screen *,
screen_write_init_ctx_cb, void *, u_char *, size_t);
/* input-key.c */
+void input_key_build(void);
int input_key_pane(struct window_pane *, key_code, struct mouse_event *);
-int input_key(struct window_pane *, struct screen *, struct bufferevent *,
- key_code);
+int input_key(struct screen *, struct bufferevent *, key_code);
int input_key_get_mouse(struct screen *, struct mouse_event *, u_int,
u_int, const char **, size_t *);
-/* xterm-keys.c */
-char *xterm_keys_lookup(key_code);
-int xterm_keys_find(const char *, size_t, size_t *, key_code *);
-
/* colour.c */
int colour_find_rgb(u_char, u_char, u_char);
int colour_join_rgb(u_char, u_char, u_char);
diff --git a/usr.bin/tmux/tty-keys.c b/usr.bin/tmux/tty-keys.c
index c6191878cd1..c9b6af525a8 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.131 2020/05/16 15:41:54 nicm Exp $ */
+/* $OpenBSD: tty-keys.c,v 1.132 2020/05/16 16:30:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -69,33 +69,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 +182,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_XTERM,
+ KEYC_ESCAPE|KEYC_XTERM,
+ KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM,
+ KEYC_CTRL|KEYC_XTERM,
+ KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM,
+ KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM,
+ KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM
+};
+
/*
- * 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;
@@ -272,10 +320,10 @@ 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 },
@@ -403,17 +451,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 +577,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 +594,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) {
diff --git a/usr.bin/tmux/xterm-keys.c b/usr.bin/tmux/xterm-keys.c
deleted file mode 100644
index 36e7542ba46..00000000000
--- a/usr.bin/tmux/xterm-keys.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* $OpenBSD: xterm-keys.c,v 1.22 2017/05/07 21:25:59 nicm Exp $ */
-
-/*
- * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <string.h>
-
-#include "tmux.h"
-
-/*
- * xterm-style function keys append one of the following values before the last
- * character:
- *
- * 2 Shift
- * 3 Alt
- * 4 Shift + Alt
- * 5 Ctrl
- * 6 Shift + Ctrl
- * 7 Alt + Ctrl
- * 8 Shift + Alt + Ctrl
- *
- * Rather than parsing them, just match against a table.
- *
- * There are three forms for F1-F4 (\\033O_P and \\033O1;_P and \\033[1;_P).
- * We accept any but always output the latter (it comes first in the table).
- */
-
-static int xterm_keys_match(const char *, const char *, size_t, size_t *,
- key_code *);
-static int xterm_keys_modifiers(const char *, size_t, size_t *,
- key_code *);
-
-struct xterm_keys_entry {
- key_code key;
- const char *template;
-};
-
-static const struct xterm_keys_entry xterm_keys_table[] = {
- { KEYC_F1, "\033[1;_P" },
- { KEYC_F1, "\033O1;_P" },
- { KEYC_F1, "\033O_P" },
- { KEYC_F2, "\033[1;_Q" },
- { KEYC_F2, "\033O1;_Q" },
- { KEYC_F2, "\033O_Q" },
- { KEYC_F3, "\033[1;_R" },
- { KEYC_F3, "\033O1;_R" },
- { KEYC_F3, "\033O_R" },
- { KEYC_F4, "\033[1;_S" },
- { KEYC_F4, "\033O1;_S" },
- { KEYC_F4, "\033O_S" },
- { KEYC_F5, "\033[15;_~" },
- { KEYC_F6, "\033[17;_~" },
- { KEYC_F7, "\033[18;_~" },
- { KEYC_F8, "\033[19;_~" },
- { KEYC_F9, "\033[20;_~" },
- { KEYC_F10, "\033[21;_~" },
- { KEYC_F11, "\033[23;_~" },
- { KEYC_F12, "\033[24;_~" },
- { KEYC_UP, "\033[1;_A" },
- { KEYC_DOWN, "\033[1;_B" },
- { KEYC_RIGHT, "\033[1;_C" },
- { KEYC_LEFT, "\033[1;_D" },
- { KEYC_HOME, "\033[1;_H" },
- { KEYC_END, "\033[1;_F" },
- { KEYC_PPAGE, "\033[5;_~" },
- { KEYC_NPAGE, "\033[6;_~" },
- { KEYC_IC, "\033[2;_~" },
- { KEYC_DC, "\033[3;_~" },
-
- { '!', "\033[27;_;33~" },
- { '#', "\033[27;_;35~" },
- { '(', "\033[27;_;40~" },
- { ')', "\033[27;_;41~" },
- { '+', "\033[27;_;43~" },
- { ',', "\033[27;_;44~" },
- { '-', "\033[27;_;45~" },
- { '.', "\033[27;_;46~" },
- { '0', "\033[27;_;48~" },
- { '1', "\033[27;_;49~" },
- { '2', "\033[27;_;50~" },
- { '3', "\033[27;_;51~" },
- { '4', "\033[27;_;52~" },
- { '5', "\033[27;_;53~" },
- { '6', "\033[27;_;54~" },
- { '7', "\033[27;_;55~" },
- { '8', "\033[27;_;56~" },
- { '9', "\033[27;_;57~" },
- { ':', "\033[27;_;58~" },
- { ';', "\033[27;_;59~" },
- { '<', "\033[27;_;60~" },
- { '=', "\033[27;_;61~" },
- { '>', "\033[27;_;62~" },
- { '?', "\033[27;_;63~" },
- { '\'', "\033[27;_;39~" },
- { '\r', "\033[27;_;13~" },
- { '\t', "\033[27;_;9~" },
-};
-
-/*
- * Match key against buffer, treating _ as a wildcard. Return -1 for no match,
- * 0 for match, 1 if the end of the buffer is reached (need more data).
- */
-static int
-xterm_keys_match(const char *template, const char *buf, size_t len,
- size_t *size, key_code *modifiers)
-{
- size_t pos;
- int retval;
-
- *modifiers = 0;
-
- if (len == 0)
- return (0);
-
- pos = 0;
- do {
- if (*template == '_') {
- retval = xterm_keys_modifiers(buf, len, &pos,
- modifiers);
- if (retval != 0)
- return (retval);
- continue;
- }
- if (buf[pos] != *template)
- return (-1);
- pos++;
- } while (*++template != '\0' && pos != len);
-
- if (*template != '\0') /* partial */
- return (1);
-
- *size = pos;
- return (0);
-}
-
-/* Find modifiers from buffer. */
-static int
-xterm_keys_modifiers(const char *buf, size_t len, size_t *pos,
- key_code *modifiers)
-{
- u_int flags;
-
- if (len - *pos < 2)
- return (1);
-
- if (buf[*pos] < '0' || buf[*pos] > '9')
- return (-1);
- flags = buf[(*pos)++] - '0';
- if (buf[*pos] >= '0' && buf[*pos] <= '9')
- flags = (flags * 10) + (buf[(*pos)++] - '0');
- flags -= 1;
-
- *modifiers = 0;
- if (flags & 1)
- *modifiers |= KEYC_SHIFT;
- if (flags & 2)
- *modifiers |= KEYC_ESCAPE;
- if (flags & 4)
- *modifiers |= KEYC_CTRL;
- if (flags & 8)
- *modifiers |= KEYC_ESCAPE;
- return (0);
-}
-
-/*
- * Lookup key from a buffer against the table. Returns 0 for found (and the
- * key), -1 for not found, 1 for partial match.
- */
-int
-xterm_keys_find(const char *buf, size_t len, size_t *size, key_code *key)
-{
- const struct xterm_keys_entry *entry;
- u_int i;
- int matched;
- key_code modifiers;
-
- for (i = 0; i < nitems(xterm_keys_table); i++) {
- entry = &xterm_keys_table[i];
-
- matched = xterm_keys_match(entry->template, buf, len, size,
- &modifiers);
- if (matched == -1)
- continue;
- if (matched == 0)
- *key = (entry->key|modifiers|KEYC_XTERM);
- return (matched);
- }
- return (-1);
-}
-
-/* Lookup a key number from the table. */
-char *
-xterm_keys_lookup(key_code key)
-{
- const struct xterm_keys_entry *entry;
- u_int i;
- key_code modifiers;
- char *out;
-
- modifiers = 1;
- if (key & KEYC_SHIFT)
- modifiers += 1;
- if (key & KEYC_ESCAPE)
- modifiers += 2;
- if (key & KEYC_CTRL)
- modifiers += 4;
-
- /*
- * If the key has no modifiers, return NULL and let it fall through to
- * the normal lookup.
- */
- if (modifiers == 1)
- return (NULL);
-
- /*
- * If this has the escape modifier, but was not originally an xterm
- * key, it may be a genuine escape + key. So don't pass it through as
- * an xterm key or programs like vi may be confused.
- */
- if ((key & (KEYC_ESCAPE|KEYC_XTERM)) == KEYC_ESCAPE)
- return (NULL);
-
- /* Otherwise, find the key in the table. */
- key &= KEYC_MASK_KEY;
- for (i = 0; i < nitems(xterm_keys_table); i++) {
- entry = &xterm_keys_table[i];
- if (key == entry->key)
- break;
- }
- if (i == nitems(xterm_keys_table))
- return (NULL);
-
- /* Copy the template and replace the modifier. */
- out = xstrdup(entry->template);
- out[strcspn(out, "_")] = '0' + modifiers;
- return (out);
-}