mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
xterm-keys has been on by default for 5 years and all other modern terminals
use these key sequences by default. Merge the code into the main tty and input tree processing (convering the latter to use a tree rather than a table at the same time) and make the option a no-op.
This commit is contained in:
parent
c4d8100b2f
commit
5ee4d991b6
@ -184,8 +184,7 @@ dist_tmux_SOURCES = \
|
||||
window-tree.c \
|
||||
window.c \
|
||||
xmalloc.c \
|
||||
xmalloc.h \
|
||||
xterm-keys.c
|
||||
xmalloc.h
|
||||
nodist_tmux_SOURCES = osdep-@PLATFORM@.c
|
||||
|
||||
# Add compat file for forkpty.
|
||||
|
502
input-keys.c
502
input-keys.c
@ -32,112 +32,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 },
|
||||
{ .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. 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 },
|
||||
/* 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"
|
||||
},
|
||||
|
||||
{ KEYC_UP, "\033OA", INPUTKEY_CURSOR },
|
||||
{ KEYC_DOWN, "\033OB", INPUTKEY_CURSOR },
|
||||
{ KEYC_RIGHT, "\033OC", INPUTKEY_CURSOR },
|
||||
{ KEYC_LEFT, "\033OD", INPUTKEY_CURSOR },
|
||||
/* 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 = "."
|
||||
},
|
||||
|
||||
{ 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 },
|
||||
/* 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;
|
||||
@ -148,32 +367,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))
|
||||
@ -216,43 +466,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);
|
||||
}
|
||||
|
||||
@ -308,9 +540,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);
|
||||
|
@ -1052,11 +1052,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. */
|
||||
|
2
popup.c
2
popup.c
@ -328,7 +328,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);
|
||||
}
|
||||
|
||||
|
1
server.c
1
server.c
@ -198,6 +198,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);
|
||||
|
10
tmux.1
10
tmux.1
@ -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:
|
||||
|
10
tmux.h
10
tmux.h
@ -125,6 +125,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
|
||||
@ -2417,16 +2419,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);
|
||||
|
135
tty-keys.c
135
tty-keys.c
@ -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) {
|
||||
|
252
xterm-keys.c
252
xterm-keys.c
@ -1,252 +0,0 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user