diff --git a/tmux.h b/tmux.h index f215cf15..36de238c 100644 --- a/tmux.h +++ b/tmux.h @@ -3316,6 +3316,7 @@ void session_renumber_windows(struct session *); /* utf8.c */ enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *); +enum utf8_state utf8_fromwc(wchar_t wc, struct utf8_data *); int utf8_in_table(wchar_t, const wchar_t *, u_int); utf8_char utf8_build_one(u_char); enum utf8_state utf8_from_data(const struct utf8_data *, utf8_char *); diff --git a/tty-keys.c b/tty-keys.c index d838e4e9..17fe47ad 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -911,6 +911,8 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, cc_t bspace; key_code nkey; key_code onlykey; + struct utf8_data ud; + utf8_char uc; *size = 0; @@ -960,6 +962,15 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, else nkey = number; + /* Convert UTF-32 codepoint into internal representation. */ + if (nkey & ~0x7f) { + if (utf8_fromwc(nkey, &ud) == UTF8_DONE && + utf8_from_data(&ud, &uc) == UTF8_DONE) + nkey = uc; + else + return (-1); + } + /* Update the modifiers. */ if (modifiers > 0) { modifiers--; diff --git a/utf8.c b/utf8.c index 1b3acd53..7dd75d57 100644 --- a/utf8.c +++ b/utf8.c @@ -449,6 +449,28 @@ utf8_towc(const struct utf8_data *ud, wchar_t *wc) return (UTF8_DONE); } +/* Convert wide character to UTF-8 character. */ +enum utf8_state +utf8_fromwc(wchar_t wc, struct utf8_data *ud) +{ + int size, width; + + size = wctomb(ud->data, wc); + if (size < 0) { + log_debug("UTF-8 %d, wctomb() %d", wc, errno); + wctomb(NULL, 0); + return (UTF8_ERROR); + } + if (size == 0) + return (UTF8_ERROR); + ud->size = ud->have = size; + if (utf8_width(ud, &width) == UTF8_DONE) { + ud->width = width; + return (UTF8_DONE); + } + return (UTF8_ERROR); +} + /* * Open UTF-8 sequence. *