diff options
-rw-r--r-- | cmd-break-pane.c | 2 | ||||
-rw-r--r-- | input-keys.c | 2 | ||||
-rw-r--r-- | input.c | 10 | ||||
-rw-r--r-- | key-string.c | 6 | ||||
-rw-r--r-- | server-client.c | 6 | ||||
-rw-r--r-- | tmux.1 | 13 | ||||
-rw-r--r-- | tmux.c | 1 | ||||
-rw-r--r-- | tmux.h | 3 | ||||
-rw-r--r-- | tty-keys.c | 7 | ||||
-rw-r--r-- | utf8.c | 44 |
10 files changed, 61 insertions, 33 deletions
diff --git a/cmd-break-pane.c b/cmd-break-pane.c index b5a2743f..85873227 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -35,7 +35,7 @@ const struct cmd_entry cmd_break_pane_entry = { .alias = "breakp", .args = { "dPF:s:t:", 0, 0 }, - .usage = "[-dP] [-F format] " CMD_SRCDST_PANE_USAGE, + .usage = "[-dP] [-F format] [-s src-pane] [-t dst-window]", .sflag = CMD_PANE, .tflag = CMD_WINDOW_INDEX, diff --git a/input-keys.c b/input-keys.c index 2a22b089..9538e876 100644 --- a/input-keys.c +++ b/input-keys.c @@ -262,6 +262,8 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m) len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c", m->sgr_b, x + 1, y + 1, m->sgr_type); } else if (wp->screen->mode & MODE_MOUSE_UTF8) { + if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33) + return; len = xsnprintf(buf, sizeof buf, "\033[M"); len += input_split2(m->b + 32, &buf[len]); len += input_split2(x + 33, &buf[len]); @@ -1960,8 +1960,14 @@ input_utf8_close(struct input_ctx *ictx) { struct utf8_data *ud = &ictx->utf8data; - if (utf8_append(ud, ictx->ch) != UTF8_DONE) - fatalx("UTF-8 close invalid %#x", ictx->ch); + if (utf8_append(ud, ictx->ch) != UTF8_DONE) { + /* + * An error here could be invalid UTF-8 or it could be a + * nonprintable character for which we can't get the + * width. Drop it. + */ + return (0); + } log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size, (int)ud->size, ud->data, ud->width); diff --git a/key-string.c b/key-string.c index dc211696..c56681f1 100644 --- a/key-string.c +++ b/key-string.c @@ -149,6 +149,7 @@ key_string_lookup_string(const char *string) struct utf8_data ud; u_int i; enum utf8_state more; + wchar_t wc; /* Is this no key? */ if (strcasecmp(string, "None") == 0) @@ -185,8 +186,9 @@ key_string_lookup_string(const char *string) more = utf8_append(&ud, (u_char)string[i]); if (more != UTF8_DONE) return (KEYC_UNKNOWN); - key = utf8_combine(&ud); - return (key | modifiers); + if (utf8_combine(&ud, &wc) != UTF8_DONE) + return (KEYC_UNKNOWN); + return (wc | modifiers); } /* Otherwise look the key up in the table. */ diff --git a/server-client.c b/server-client.c index 680350df..3810416e 100644 --- a/server-client.c +++ b/server-client.c @@ -457,8 +457,10 @@ server_client_check_mouse(struct client *c) } } - /* Begin a drag by setting the flag to nonzero, where the value - corresponds to the mouse button doing the dragging. */ + /* + * Begin a drag by setting the flag to a non-zero value that + * corresponds to the mouse button in use. + */ c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1; break; case WHEEL: @@ -721,7 +721,7 @@ will set the session working directory (used for new windows) to .Pp If .Fl E -is used, +is used, the .Ic update-environment option will not be applied. .It Xo Ic detach-client @@ -857,13 +857,12 @@ with .Ar target-session . This means they share the same set of windows - all windows from .Ar target-session -are linked to the new session and any subsequent new windows or windows being -closed are applied to both sessions. +are linked to the new session, any new windows are linked to both sessions and +any windows closed removed from both sessions. The current and previous window and any session options remain independent and either session may be killed without affecting the other. -Giving .Fl n -or +and .Ar shell-command are invalid if .Fl t @@ -879,7 +878,7 @@ but a different format may be specified with .Pp If .Fl E -is used, +is used, the .Ic update-environment option will not be applied. .It Xo Ic refresh-client @@ -1254,7 +1253,7 @@ Commands related to windows and panes are as follows: .Op Fl dP .Op Fl F Ar format .Op Fl s Ar src-pane -.Op Fl t Ar dst-pane +.Op Fl t Ar dst-window .Xc .D1 (alias: Ic breakp ) Break @@ -190,7 +190,6 @@ main(int argc, char **argv) const char *s; int opt, flags, keys; - setlocale(LC_CTYPE, "en_US.UTF-8"); setlocale(LC_TIME, ""); @@ -2318,8 +2318,7 @@ void utf8_set(struct utf8_data *, u_char); void utf8_copy(struct utf8_data *, const struct utf8_data *); enum utf8_state utf8_open(struct utf8_data *, u_char); enum utf8_state utf8_append(struct utf8_data *, u_char); -u_int utf8_width(wchar_t); -wchar_t utf8_combine(const struct utf8_data *); +enum utf8_state utf8_combine(const struct utf8_data *, wchar_t *); enum utf8_state utf8_split(wchar_t, struct utf8_data *); int utf8_strvis(char *, const char *, size_t, int); char *utf8_sanitize(const char *); @@ -477,6 +477,7 @@ tty_keys_next(struct tty *tty) struct utf8_data ud; enum utf8_state more; u_int i; + wchar_t wc; /* Get key buffer. */ buf = EVBUFFER_DATA(tty->event->input); @@ -552,7 +553,11 @@ first_key: more = utf8_append(&ud, (u_char)buf[i]); if (more != UTF8_DONE) goto discard_key; - key = utf8_combine(&ud); + + if (utf8_combine(&ud, &wc) != UTF8_DONE) + goto discard_key; + key = wc; + log_debug("UTF-8 key %.*s %#llx", (int)size, buf, key); goto complete_key; } @@ -20,10 +20,11 @@ #include <stdlib.h> #include <string.h> -#include <wchar.h> #include "tmux.h" +static int utf8_width(wchar_t); + /* Set a single character. */ void utf8_set(struct utf8_data *ud, u_char ch) @@ -79,6 +80,9 @@ utf8_open(struct utf8_data *ud, u_char ch) enum utf8_state utf8_append(struct utf8_data *ud, u_char ch) { + wchar_t wc; + int width; + if (ud->have >= ud->size) fatalx("UTF-8 character overflow"); if (ud->size > sizeof ud->data) @@ -93,39 +97,49 @@ utf8_append(struct utf8_data *ud, u_char ch) if (ud->width == 0xff) return (UTF8_ERROR); - ud->width = utf8_width(utf8_combine(ud)); + + if (utf8_combine(ud, &wc) != UTF8_DONE) + return (UTF8_ERROR); + if ((width = utf8_width(wc)) < 0) + return (UTF8_ERROR); + ud->width = width; + return (UTF8_DONE); } /* Get width of Unicode character. */ -u_int +static int utf8_width(wchar_t wc) { - int width; + int width; width = wcwidth(wc); - if (width < 0) - return (0); + if (width < 0 || width > 0xff) + return (-1); return (width); } /* Combine UTF-8 into Unicode. */ -wchar_t -utf8_combine(const struct utf8_data *ud) +enum utf8_state +utf8_combine(const struct utf8_data *ud, wchar_t *wc) { - wchar_t wc; - - if (mbtowc(&wc, ud->data, ud->size) <= 0) - return (0xfffd); - return (wc); + switch (mbtowc(wc, ud->data, ud->size)) { + case -1: + mbtowc(NULL, NULL, MB_CUR_MAX); + return (UTF8_ERROR); + case 0: + return (UTF8_ERROR); + default: + return (UTF8_DONE); + } } /* Split Unicode into UTF-8. */ enum utf8_state utf8_split(wchar_t wc, struct utf8_data *ud) { - char s[MB_CUR_MAX]; - int slen; + char s[MB_LEN_MAX]; + int slen; slen = wctomb(s, wc); if (slen <= 0 || slen > (int)sizeof ud->data) |