summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm>2015-11-12 11:05:34 +0000
committernicm <nicm>2015-11-12 11:05:34 +0000
commit69e0b8326ad0a983759518b90ed8632146341acf (patch)
tree03f69cf9a96b5e87b760243cc535878940bc7a02
parent7062b0e65dcbb94bb190f6c50f4089b2ea6278bb (diff)
Support UTF-8 key bindings by expanding the key type from int to
uint64_t and converting UTF-8 to Unicode on input and the reverse on output. (This allows key bindings, there are still omissions - the largest being that the various prompts do not accept UTF-8.)
-rw-r--r--cmd-bind-key.c7
-rw-r--r--cmd-list-keys.c13
-rw-r--r--cmd-send-keys.c3
-rw-r--r--cmd-set-option.c2
-rw-r--r--cmd-unbind-key.c9
-rw-r--r--input-keys.c38
-rw-r--r--key-bindings.c10
-rw-r--r--key-string.c63
-rw-r--r--mode-key.c16
-rw-r--r--server-client.c42
-rw-r--r--status.c4
-rw-r--r--tmux.h84
-rw-r--r--tty-keys.c62
-rw-r--r--utf8.c34
-rw-r--r--window-choose.c23
-rw-r--r--window-clock.c5
-rw-r--r--window-copy.c12
-rw-r--r--window.c2
-rw-r--r--xterm-keys.c21
19 files changed, 281 insertions, 169 deletions
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index fda39efc..1867e814 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -29,7 +29,8 @@
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
-enum cmd_retval cmd_bind_key_mode_table(struct cmd *, struct cmd_q *, int);
+enum cmd_retval cmd_bind_key_mode_table(struct cmd *, struct cmd_q *,
+ key_code);
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
@@ -45,7 +46,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
char *cause;
struct cmd_list *cmdlist;
- int key;
+ key_code key;
const char *tablename;
if (args_has(args, 't')) {
@@ -89,7 +90,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
-cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
+cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
{
struct args *args = self->args;
const char *tablename;
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index d26486bd..c76f9f47 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -57,6 +57,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
char tmp[BUFSIZ];
size_t used;
int repeat, width, tablewidth, keywidth;
+ u_int i;
if (self->entry == &cmd_list_commands_entry)
return (cmd_list_keys_commands(self, cmdq));
@@ -83,8 +84,8 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
width = strlen(table->name);
if (width > tablewidth)
- tablewidth =width;
- width = strlen(key);
+ tablewidth = width;
+ width = utf8_cstrwidth(key);
if (width > keywidth)
keywidth = width;
}
@@ -102,8 +103,12 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
r = "-r ";
else
r = " ";
- used = xsnprintf(tmp, sizeof tmp, "%s-T %-*s %-*s ", r,
- (int)tablewidth, table->name, (int)keywidth, key);
+ used = xsnprintf(tmp, sizeof tmp, "%s-T %-*s %s", r,
+ (int)tablewidth, table->name, key);
+ for (i = 0; i < keywidth - utf8_cstrwidth(key); i++) {
+ if (strlcat(tmp, " ", sizeof tmp) < sizeof tmp)
+ used++;
+ }
if (used < sizeof tmp) {
cmd_list_print(bd->cmdlist, tmp + used,
(sizeof tmp) - used);
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index dd796d60..73a308ae 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -53,7 +53,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp;
struct session *s;
const u_char *str;
- int i, key;
+ int i;
+ key_code key;
if (args_has(args, 'M')) {
wp = cmd_mouse_pane(m, &s, NULL);
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 6762e6ad..c5a77b45 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -394,7 +394,7 @@ cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
- int key;
+ key_code key;
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
cmdq_error(cmdq, "bad key: %s", value);
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index 493f6dde..cec538c0 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -26,8 +26,9 @@
* Unbind key from command.
*/
-enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
-enum cmd_retval cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *, int);
+enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
+enum cmd_retval cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *,
+ key_code);
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
@@ -41,7 +42,7 @@ enum cmd_retval
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
- int key;
+ key_code key;
const char *tablename;
if (!args_has(args, 'a')) {
@@ -95,7 +96,7 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
-cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
+cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
{
struct args *args = self->args;
const char *tablename;
diff --git a/input-keys.c b/input-keys.c
index 579c0f39..a761a088 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -34,7 +34,7 @@
void input_key_mouse(struct window_pane *, struct mouse_event *);
struct input_key_ent {
- int key;
+ key_code key;
const char *data;
int flags;
@@ -137,15 +137,16 @@ const struct input_key_ent input_keys[] = {
/* Translate a key code into an output key sequence. */
void
-input_key(struct window_pane *wp, int key, struct mouse_event *m)
+input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
{
- const struct input_key_ent *ike;
- u_int i;
- size_t dlen;
- char *out;
- u_char ch;
+ const struct input_key_ent *ike;
+ u_int i;
+ size_t dlen;
+ char *out;
+ key_code justkey;
+ struct utf8_data utf8data;
- log_debug("writing key 0x%x (%s) to %%%u", key,
+ log_debug("writing key 0x%llx (%s) to %%%u", key,
key_string_lookup_key(key), wp->id);
/* If this is a mouse key, pass off to mouse function. */
@@ -157,13 +158,22 @@ input_key(struct window_pane *wp, int key, struct mouse_event *m)
/*
* If this is a normal 7-bit key, just send it, with a leading escape
- * if necessary.
+ * if necessary. If it is a UTF-8 key, split it and send it.
*/
- if (key != KEYC_NONE && (key & ~KEYC_ESCAPE) < 0x100) {
+ justkey = (key & ~KEYC_ESCAPE);
+ if (key != KEYC_NONE && justkey < 0x7f) {
if (key & KEYC_ESCAPE)
bufferevent_write(wp->event, "\033", 1);
- ch = key & ~KEYC_ESCAPE;
- bufferevent_write(wp->event, &ch, 1);
+ utf8data.data[0] = justkey;
+ bufferevent_write(wp->event, &utf8data.data[0], 1);
+ return;
+ }
+ if (key != KEYC_NONE && justkey > 0x7f && justkey < KEYC_BASE) {
+ if (utf8_split(justkey, &utf8data) != 0)
+ return;
+ if (key & KEYC_ESCAPE)
+ bufferevent_write(wp->event, "\033", 1);
+ bufferevent_write(wp->event, utf8data.data, utf8data.size);
return;
}
@@ -196,11 +206,11 @@ input_key(struct window_pane *wp, int key, struct mouse_event *m)
break;
}
if (i == nitems(input_keys)) {
- log_debug("key 0x%x missing", key);
+ log_debug("key 0x%llx missing", key);
return;
}
dlen = strlen(ike->data);
- log_debug("found key 0x%x: \"%s\"", key, ike->data);
+ log_debug("found key 0x%llx: \"%s\"", key, ike->data);
/* Prefix a \033 for escape. */
if (key & KEYC_ESCAPE)
diff --git a/key-bindings.c b/key-bindings.c
index 83b94ac1..47a7d867 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -37,7 +37,11 @@ key_table_cmp(struct key_table *e1, struct key_table *e2)
int
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
{
- return (bd1->key - bd2->key);
+ if (bd1->key < bd2->key)
+ return (-1);
+ if (bd1->key > bd2->key)
+ return (1);
+ return (0);
}
struct key_table *
@@ -80,7 +84,7 @@ key_bindings_unref_table(struct key_table *table)
}
void
-key_bindings_add(const char *name, int key, int can_repeat,
+key_bindings_add(const char *name, key_code key, int can_repeat,
struct cmd_list *cmdlist)
{
struct key_table *table;
@@ -105,7 +109,7 @@ key_bindings_add(const char *name, int key, int can_repeat,
}
void
-key_bindings_remove(const char *name, int key)
+key_bindings_remove(const char *name, key_code key)
{
struct key_table *table;
struct key_binding bd_find, *bd;
diff --git a/key-string.c b/key-string.c
index 88cd2a32..4285e129 100644
--- a/key-string.c
+++ b/key-string.c
@@ -22,12 +22,12 @@
#include "tmux.h"
-int key_string_search_table(const char *);
-int key_string_get_modifiers(const char **);
+key_code key_string_search_table(const char *);
+key_code key_string_get_modifiers(const char **);
const struct {
const char *string;
- int key;
+ key_code key;
} key_string_table[] = {
/* Function keys. */
{ "F1", KEYC_F1 },
@@ -98,7 +98,7 @@ const struct {
};
/* Find key string in table. */
-int
+key_code
key_string_search_table(const char *string)
{
u_int i;
@@ -111,10 +111,10 @@ key_string_search_table(const char *string)
}
/* Find modifiers. */
-int
+key_code
key_string_get_modifiers(const char **string)
{
- int modifiers;
+ key_code modifiers;
modifiers = 0;
while (((*string)[0] != '\0') && (*string)[1] == '-') {
@@ -138,13 +138,16 @@ key_string_get_modifiers(const char **string)
}
/* Lookup a string and convert to a key value. */
-int
+key_code
key_string_lookup_string(const char *string)
{
static const char *other = "!#()+,-.0123456789:;<=>?'\r\t";
- int key, modifiers;
+ key_code key;
u_short u;
int size;
+ key_code modifiers;
+ struct utf8_data utf8data;
+ u_int i;
/* Is this a hexadecimal value? */
if (string[0] == '0' && string[1] == 'x') {
@@ -164,11 +167,21 @@ key_string_lookup_string(const char *string)
return (KEYC_NONE);
/* Is this a standard ASCII key? */
- if (string[1] == '\0') {
- key = (u_char) string[0];
- if (key < 32 || key == 127 || key > 255)
+ if (string[1] == '\0' && (u_char)string[0] <= 127) {
+ key = (u_char)string[0];
+ if (key < 32 || key == 127)
return (KEYC_NONE);
} else {
+ /* Try as a UTF-8 key. */
+ if (utf8_open(&utf8data, (u_char)*string)) {
+ if (strlen(string) != utf8data.size)
+ return (KEYC_NONE);
+ for (i = 1; i < utf8data.size; i++)
+ utf8_append(&utf8data, (u_char)string[i]);
+ key = utf8_combine(&utf8data);
+ return (key | modifiers);
+ }
+
/* Otherwise look the key up in the table. */
key = key_string_search_table(string);
if (key == KEYC_NONE)
@@ -195,11 +208,12 @@ key_string_lookup_string(const char *string)
/* Convert a key code into string format, with prefix if necessary. */
const char *
-key_string_lookup_key(int key)
+key_string_lookup_key(key_code key)
{
- static char out[24];
- char tmp[8];
- u_int i;
+ static char out[24];
+ char tmp[8];
+ u_int i;
+ struct utf8_data utf8data;
*out = '\0';
@@ -237,23 +251,32 @@ key_string_lookup_key(int key)
return (out);
}
+ /* Is this a UTF-8 key? */
+ if (key > 127 && key < KEYC_BASE) {
+ if (utf8_split(key, &utf8data) == 0) {
+ memcpy(out, utf8data.data, utf8data.size);
+ out[utf8data.size] = '\0';
+ return (out);
+ }
+ }
+
/* Invalid keys are errors. */
if (key == 127 || key > 255) {
- snprintf(out, sizeof out, "<INVALID#%04x>", key);
+ snprintf(out, sizeof out, "<INVALID#%llx>", key);
return (out);
}
/* Check for standard or control key. */
- if (key >= 0 && key <= 32) {
+ if (key <= 32) {
if (key == 0 || key > 26)
- xsnprintf(tmp, sizeof tmp, "C-%c", 64 + key);
+ xsnprintf(tmp, sizeof tmp, "C-%c", (int)(64 + key));
else
- xsnprintf(tmp, sizeof tmp, "C-%c", 96 + key);
+ xsnprintf(tmp, sizeof tmp, "C-%c", (int)(96 + key));
} else if (key >= 32 && key <= 126) {
tmp[0] = key;
tmp[1] = '\0';
} else if (key >= 128)
- xsnprintf(tmp, sizeof tmp, "\\%o", key);
+ xsnprintf(tmp, sizeof tmp, "\\%llo", key);
strlcat(out, tmp, sizeof out);
return (out);
diff --git a/mode-key.c b/mode-key.c
index 5ed45bd8..a47cda0b 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -40,7 +40,7 @@
/* Entry in the default mode key tables. */
struct mode_key_entry {
- int key;
+ key_code key;
/*
* Editing mode for vi: 0 is edit mode, keys not in the table are
@@ -523,9 +523,15 @@ RB_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
int
mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
{
- if (mbind1->mode != mbind2->mode)
- return (mbind1->mode - mbind2->mode);
- return (mbind1->key - mbind2->key);
+ if (mbind1->mode < mbind2->mode)
+ return (-1);
+ if (mbind1->mode > mbind2->mode)
+ return (1);
+ if (mbind1->key < mbind2->key)
+ return (-1);
+ if (mbind1->key > mbind2->key)
+ return (1);
+ return (0);
}
const char *
@@ -588,7 +594,7 @@ mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
}
enum mode_key_cmd
-mode_key_lookup(struct mode_key_data *mdata, int key, const char **arg)
+mode_key_lookup(struct mode_key_data *mdata, key_code key, const char **arg)
{
struct mode_key_binding *mbind, mtmp;
diff --git a/server-client.c b/server-client.c
index 521f2737..fedc93bd 100644
--- a/server-client.c
+++ b/server-client.c
@@ -32,22 +32,22 @@
#include "tmux.h"
-void server_client_key_table(struct client *, const char *);
-void server_client_free(int, short, void *);
-void server_client_check_focus(struct window_pane *);
-void server_client_check_resize(struct window_pane *);
-int server_client_check_mouse(struct client *);
-void server_client_repeat_timer(int, short, void *);
-void server_client_check_exit(struct client *);
-void server_client_check_redraw(struct client *);
-void server_client_set_title(struct client *);
-void server_client_reset_state(struct client *);
-int server_client_assume_paste(struct session *);
-
-void server_client_dispatch(struct imsg *, void *);
-void server_client_dispatch_command(struct client *, struct imsg *);
-void server_client_dispatch_identify(struct client *, struct imsg *);
-void server_client_dispatch_shell(struct client *);
+void server_client_key_table(struct client *, const char *);
+void server_client_free(int, short, void *);
+void server_client_check_focus(struct window_pane *);
+void server_client_check_resize(struct window_pane *);
+key_code server_client_check_mouse(struct client *);
+void server_client_repeat_timer(int, short, void *);
+void server_client_check_exit(struct client *);
+void server_client_check_redraw(struct client *);
+void server_client_set_title(struct client *);
+void server_client_reset_state(struct client *);
+int server_client_assume_paste(struct session *);
+
+void server_client_dispatch(struct imsg *, void *);
+void server_client_dispatch_command(struct client *, struct imsg *);
+void server_client_dispatch_identify(struct client *, struct imsg *);
+void server_client_dispatch_shell(struct client *);
/* Check if this client is inside this server. */
int
@@ -257,7 +257,7 @@ server_client_free(unused int fd, unused short events, void *arg)
}
/* Check for mouse keys. */
-int
+key_code
server_client_check_mouse(struct client *c)
{
struct session *s = c->session;
@@ -267,7 +267,7 @@ server_client_check_mouse(struct client *c)
enum { NOTYPE, DOWN, UP, DRAG, WHEEL } type = NOTYPE;
enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE;
u_int x, y, b;
- int key;
+ key_code key;
log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
m->lx, m->ly, c->tty.mouse_drag_flag);
@@ -501,7 +501,7 @@ server_client_assume_paste(struct session *s)
/* Handle data key input from client. */
void
-server_client_handle_key(struct client *c, int key)
+server_client_handle_key(struct client *c, key_code key)
{
struct mouse_event *m = &c->tty.mouse;
struct session *s = c->session;
@@ -635,8 +635,8 @@ retry:
* No match, but in the root table. Prefix switches to the prefix table
* and everything else is passed through.
*/
- if (key == options_get_number(s->options, "prefix") ||
- key == options_get_number(s->options, "prefix2")) {
+ if (key == (key_code)options_get_number(s->options, "prefix") ||
+ key == (key_code)options_get_number(s->options, "prefix2")) {
server_client_key_table(c, "prefix");
server_status_client(c);
return;
diff --git a/status.c b/status.c
index a2f46b95..df80d2b8 100644
--- a/status.c
+++ b/status.c
@@ -812,7 +812,7 @@ status_prompt_redraw(struct client *c)
/* Handle keys in prompt. */
void
-status_prompt_key(struct client *c, int key)
+status_prompt_key(struct client *c, key_code key)
{
struct session *sess = c->session;
struct options *oo = sess->options;
@@ -1116,7 +1116,7 @@ status_prompt_key(struct client *c, int key)
status_prompt_clear(c);
break;
case MODEKEY_OTHER:
- if ((key & 0xff00) != 0 || key < 32 || key == 127)
+ if (key <= 0x1f || key >= 0x7f)
break;
c->prompt_buffer = xrealloc(c->prompt_buffer, size + 2);
diff --git a/tmux.h b/tmux.h
index 25b51350..51ceefd8 100644
--- a/tmux.h
+++ b/tmux.h
@@ -95,13 +95,13 @@ struct tmuxproc;
#define BELL_OTHER 3
/* Special key codes. */
-#define KEYC_NONE 0xfff
-#define KEYC_BASE 0x1000
+#define KEYC_NONE 0xffff00000000ULL
+#define KEYC_BASE 0x100000000000ULL
/* Key modifier bits. */
-#define KEYC_ESCAPE 0x2000
-#define KEYC_CTRL 0x4000
-#define KEYC_SHIFT 0x8000
+#define KEYC_ESCAPE 0x200000000000ULL
+#define KEYC_CTRL 0x400000000000ULL
+#define KEYC_SHIFT 0x800000000000ULL
/* Mask to obtain key w/o modifiers. */
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT)
@@ -121,8 +121,14 @@ struct tmuxproc;
{ #s "Status", KEYC_ ## name ## _STATUS }, \
{ #s "Border", KEYC_ ## name ## _BORDER }
+/*
+ * A single key. This can be ASCII or Unicode or one of the keys starting at
+ * KEYC_BASE.
+ */
+typedef uint64_t key_code;
+
/* Special key codes. */
-enum key_code {
+enum {
/* Focus events. */
KEYC_FOCUS_IN = KEYC_BASE,
KEYC_FOCUS_OUT,
@@ -570,7 +576,7 @@ struct mode_key_data {
/* Binding between a key and a command. */
struct mode_key_binding {
- int key;
+ key_code key;
int mode;
enum mode_key_cmd cmd;
@@ -776,7 +782,7 @@ struct window_mode {
void (*free)(struct window_pane *);
void (*resize)(struct window_pane *, u_int, u_int);
void (*key)(struct window_pane *, struct client *, struct session *,
- int, struct mouse_event *);
+ key_code, struct mouse_event *);
};
/* Structures for choose mode. */
@@ -1030,31 +1036,31 @@ RB_HEAD(sessions, session);
/* Mouse input. */
struct mouse_event {
- int valid;
+ int valid;
- int key;
- int statusat;
+ key_code key;
+ int statusat;
- u_int x;
- u_int y;
- u_int b;
+ u_int x;
+ u_int y;
+ u_int b;
- u_int lx;
- u_int ly;
- u_int lb;
+ u_int lx;
+ u_int ly;
+ u_int lb;
- int s;
- int w;
- int wp;
+ int s;
+ int w;
+ int wp;
- u_int sgr_type;
- u_int sgr_b;
+ u_int sgr_type;
+ u_int sgr_b;
};
/* TTY information. */
struct tty_key {
char ch;
- int key;
+ key_code key;
struct tty_key *left;
struct tty_key *right;
@@ -1340,7 +1346,7 @@ struct cmd_entry {
/* Key binding and key table. */
struct key_binding {
- int key;
+ key_code key;
struct cmd_list *cmdlist;
int can_repeat;
@@ -1488,7 +1494,8 @@ enum mode_key_cmd mode_key_fromstring(const struct mode_key_cmdstr *,
const struct mode_key_table *mode_key_findtable(const char *);
void mode_key_init_trees(void);
void mode_key_init(struct mode_key_data *, struct mode_key_tree *);
-enum mode_key_cmd mode_key_lookup(struct mode_key_data *, int, const char **);
+enum mode_key_cmd mode_key_lookup(struct mode_key_data *, key_code,
+ const char **);
/* notify.c */
void notify_enable(void);
@@ -1632,9 +1639,9 @@ const char *tty_term_describe(struct tty_term *, enum tty_code_code);
const char *tty_acs_get(struct tty *, u_char);
/* tty-keys.c */
-void tty_keys_build(struct tty *);
-void tty_keys_free(struct tty *);
-int tty_keys_next(struct tty *);
+void tty_keys_build(struct tty *);
+void tty_keys_free(struct tty *);
+key_code tty_keys_next(struct tty *);
/* arguments.c */
int args_cmp(struct args_entry *, struct args_entry *);
@@ -1720,16 +1727,16 @@ int key_table_cmp(struct key_table *, struct key_table *);
int key_bindings_cmp(struct key_binding *, struct key_binding *);
struct key_table *key_bindings_get_table(const char *, int);
void key_bindings_unref_table(struct key_table *);
-void key_bindings_add(const char *, int, int, struct cmd_list *);
-void key_bindings_remove(const char *, int);
+void key_bindings_add(const char *, key_code, int, struct cmd_list *);
+void key_bindings_remove(const char *, key_code);
void key_bindings_remove_table(const char *);
void key_bindings_init(void);
void key_bindings_dispatch(struct key_binding *, struct client *,
struct mouse_event *);
/* key-string.c */
-int key_string_lookup_string(const char *);
-const char *key_string_lookup_key(int);
+key_code key_string_lookup_string(const char *);
+const char *key_string_lookup_key(key_code);
/* alerts.c */
void alerts_reset_all(void);
@@ -1753,7 +1760,7 @@ void server_add_accept(int);
/* server-client.c */
int server_client_check_nested(struct client *);
-void server_client_handle_key(struct client *, int);
+void server_client_handle_key(struct client *, key_code);
void server_client_create(int);
int server_client_open(struct client *, char **);
void server_client_unref(struct client *);
@@ -1803,7 +1810,7 @@ void status_prompt_set(struct client *, const char *, const char *,
int (*)(void *, const char *), void (*)(void *), void *, int);
void status_prompt_clear(struct client *);
int status_prompt_redraw(struct client *);
-void status_prompt_key(struct client *, int);
+void status_prompt_key(struct client *, key_code);
void status_prompt_update(struct client *, const char *, const char *);
void status_prompt_load_history(void);
void status_prompt_save_history(void);
@@ -1819,11 +1826,11 @@ struct evbuffer *input_pending(struct window_pane *);
void input_parse(struct window_pane *);
/* input-key.c */
-void input_key(struct window_pane *, int, struct mouse_event *);
+void input_key(struct window_pane *, key_code, struct mouse_event *);
/* xterm-keys.c */
-char *xterm_keys_lookup(int);
-int xterm_keys_find(const char *, size_t, size_t *, int *);
+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);
@@ -2020,7 +2027,7 @@ int window_pane_set_mode(
struct window_pane *, const struct window_mode *);
void window_pane_reset_mode(struct window_pane *);
void window_pane_key(struct window_pane *, struct client *,
- struct session *, int, struct mouse_event *);
+ struct session *, key_code, struct mouse_event *);
int window_pane_visible(struct window_pane *);
char *window_pane_search(
struct window_pane *, const char *, u_int *);
@@ -2179,6 +2186,7 @@ void utf8_set(struct utf8_data *, u_char);
int utf8_open(struct utf8_data *, u_char);
int utf8_append(struct utf8_data *, u_char);
u_int utf8_combine(const struct utf8_data *);
+int utf8_split(u_int, struct utf8_data *);
u_int utf8_split2(u_int, u_char *);
int utf8_strvis(char *, const char *, size_t, int);
struct utf8_data *utf8_fromcstr(const char *);
diff --git a/tty-keys.c b/tty-keys.c
index 309e8c04..31adf0f0 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -33,11 +33,11 @@
* into a ternary tree.
*/
-void tty_keys_add1(struct tty_key **, const char *, int);
-void tty_keys_add(struct tty *, const char *, int);
+void tty_keys_add1(struct tty_key **, const char *, key_code);
+void tty_keys_add(struct tty *, const char *, key_code);
void tty_keys_free1(struct tty_key *);
-struct tty_key *tty_keys_find1(
- struct tty_key *, const char *, size_t, size_t *);
+struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t,
+ size_t *);
struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *);
void tty_keys_callback(int, short, void *);
int tty_keys_mouse(struct tty *, const char *, size_t, size_t *);
@@ -45,7 +45,7 @@ int tty_keys_mouse(struct tty *, const char *, size_t, size_t *);
/* Default raw keys. */
struct tty_default_key_raw {
const char *string;
- int key;
+ key_code key;
};
const struct tty_default_key_raw tty_default_raw_keys[] = {
/*
@@ -165,7 +165,7 @@ const struct tty_default_key_raw tty_default_raw_keys[] = {
/* Default terminfo(5) keys. */
struct tty_default_key_code {
enum tty_code_code code;
- int key;
+ key_code key;
};
const struct tty_default_key_code tty_default_code_keys[] = {
/* Function keys. */
@@ -317,7 +317,7 @@ const struct tty_default_key_code tty_default_code_keys[] = {
/* Add key to tree. */
void
-tty_keys_add(struct tty *tty, const char *s, int key)
+tty_keys_add(struct tty *tty, const char *s, key_code key)
{
struct tty_key *tk;
size_t size;
@@ -325,17 +325,17 @@ tty_keys_add(struct tty *tty, const char *s, int key)
keystr = key_string_lookup_key(key);
if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
- log_debug("new key %s: 0x%x (%s)", s, key, keystr);
+ log_debug("new key %s: 0x%llx (%s)", s, key, keystr);
tty_keys_add1(&tty->key_tree, s, key);
} else {
- log_debug("replacing key %s: 0x%x (%s)", s, key, keystr);
+ log_debug("replacing key %s: 0x%llx (%s)", s, key, keystr);
tk->key = key;
}
}
/* Add next node to the tree. */
void
-tty_keys_add1(struct tty_key **tkp, const char *s, int key)
+tty_keys_add1(struct tty_key **tkp, const char *s, key_code key)
{
struct tty_key *tk;
@@ -464,15 +464,18 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
* Process at least one key in the buffer and invoke tty->key_callback. Return
* 0 if there are no further keys, or 1 if there could be more in the buffer.
*/
-int
+key_code
tty_keys_next(struct tty *tty)
{
- struct tty_key *tk;
- struct timeval tv;
- const char *buf;
- size_t len, size;
- cc_t bspace;
- int key, delay, expired = 0;
+ struct tty_key *tk;
+ struct timeval tv;
+ const char *buf;
+ size_t len, size;
+ cc_t bspace;
+ int delay, expired = 0;
+ key_code key;
+ struct utf8_data utf8data;
+ u_int i;
/* Get key buffer. */
buf = EVBUFFER_DATA(tty->event->input);
@@ -535,8 +538,23 @@ first_key:
}
}
+ /* Is this valid UTF-8? */
+ if (utf8_open(&utf8data, (u_char)*buf)) {
+ size = utf8data.size;
+ if (len < size) {
+ if (expired)
+ goto discard_key;
+ goto partial_key;
+ }
+ for (i = 1; i < size; i++)
+ utf8_append(&utf8data, (u_char)buf[i]);
+ key = utf8_combine(&utf8data);
+ log_debug("UTF-8 key %.*s %#llx", (int)size, buf, key);
+ goto complete_key;
+ }
+
/* No key found, take first. */
- key = (u_char) *buf;
+ key = (u_char)*buf;
size = 1;
/*
@@ -578,7 +596,7 @@ partial_key:
return (0);
complete_key:
- log_debug("complete key %.*s %#x", (int) size, buf, key);
+ log_debug("complete key %.*s %#llx", (int)size, buf, key);
/* Remove data from buffer. */
evbuffer_drain(tty->event->input, size);
@@ -604,7 +622,7 @@ complete_key:
return (1);
discard_key:
- log_debug("discard key %.*s %#x", (int) size, buf, key);
+ log_debug("discard key %.*s %#llx", (int)size, buf, key);
/* Remove data from buffer. */
evbuffer_drain(tty->event->input, size);
@@ -684,10 +702,10 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
utf8_append(&utf8data, buf[*size]);
value = utf8_combine(&utf8data);
} else
- value = (u_char) buf[*size];
+ value = (u_char)buf[*size];
(*size)++;
} else {
- value = (u_char) buf[*size];
+ value = (u_char)buf[*size];
(*size)++;
}
diff --git a/utf8.c b/utf8.c
index 9a06c186..e61bf996 100644
--- a/utf8.c
+++ b/utf8.c
@@ -394,6 +394,8 @@ utf8_open(struct utf8_data *utf8data, u_char ch)
int
utf8_append(struct utf8_data *utf8data, u_char ch)
{
+ /* XXX this should do validity checks too! */
+
if (utf8data->have >= utf8data->size)
fatalx("UTF-8 character overflow");
if (utf8data->size > sizeof utf8data->data)
@@ -467,18 +469,46 @@ utf8_combine(const struct utf8_data *utf8data)
case 3:
value = utf8data->data[2] & 0x3f;
value |= (utf8data->data[1] & 0x3f) << 6;
- value |= (utf8data->data[0] & 0x0f) << 12;
+ value |= (utf8data->data[0] & 0xf) << 12;
break;
case 4:
value = utf8data->data[3] & 0x3f;
value |= (utf8data->data[2] & 0x3f) << 6;
value |= (utf8data->data[1] & 0x3f) << 12;
- value |= (utf8data->data[0] & 0x07) << 18;
+ value |= (utf8data->data[0] & 0x7) << 18;
break;
}
return (value);
}
+/* Split a UTF-8 character. */
+int
+utf8_split(u_int uc, struct utf8_data *utf8data)
+{
+ if (uc < 0x7f) {
+ utf8data->size = 1;
+ utf8data->data[0] = uc;
+ } else if (uc < 0x7ff) {
+ utf8data->size = 2;
+ utf8data->data[0] = 0xc0 | ((uc >> 6) & 0x1f);
+ utf8data->data[1] = 0x80 | (uc & 0x3f);
+ } else if (uc < 0xffff) {
+ utf8data->size = 3;
+ utf8data->data[0] = 0xe0 | ((uc >> 12) & 0xf);
+ utf8data->data[1] = 0x80 | ((uc >> 6) & 0x3f);
+ utf8data->data[2] = 0x80 | (uc & 0x3f);
+ } else if (uc < 0x1fffff) {
+ utf8data->size = 4;
+ utf8data->data[0] = 0xf0 | ((uc >> 18) & 0x7);
+ utf8data->data[1] = 0x80 | ((uc >> 12) & 0x3f);
+ utf8data->data[2] = 0x80 | ((uc >> 6) & 0x3f);
+ utf8data->data[3] = 0x80 | (uc & 0x3f);
+ } else
+ return (-1);
+ utf8data->width = utf8_width(utf8data);
+ return (0);
+}
+
/* Split a two-byte UTF-8 character. */
u_int
utf8_split2(u_int uc, u_char *ptr)</