Support for UTF-8 mouse input (\033[1005h). This was added in xterm 262

and supports larger terminals than the older way.

If the new mouse-utf8 option is on, UTF-8 mouse input is enabled for all
UTF-8 terminals. The option defaults to on if LANG etc are set in the
same manner as the utf8 option.

With help and based on code from hsim at gmx.li.
This commit is contained in:
Nicholas Marriott 2011-01-03 23:35:21 +00:00
parent 5158dd9a8d
commit ac3b78a841
11 changed files with 128 additions and 22 deletions

View File

@ -202,11 +202,23 @@ input_key(struct window_pane *wp, int key)
void
input_mouse(struct window_pane *wp, struct mouse_event *m)
{
char out[8];
char buf[10];
size_t len;
if (wp->screen->mode & ALL_MOUSE_MODES) {
xsnprintf(out, sizeof out,
"\033[M%c%c%c", m->b + 32, m->x + 33, m->y + 33);
bufferevent_write(wp->event, out, strlen(out));
if (wp->screen->mode & MODE_MOUSE_UTF8) {
len = xsnprintf(buf, sizeof buf, "\033[M");
len += utf8_split2(m->b + 32, &buf[len]);
len += utf8_split2(m->x + 33, &buf[len]);
len += utf8_split2(m->y + 33, &buf[len]);
} else {
if (m->b > 223 || m->x >= 222 || m->y > 222)
return;
len = xsnprintf(buf, sizeof buf, "\033[M");
buf[len++] = m->b + 32;
buf[len++] = m->x + 33;
buf[len++] = m->y + 33;
}
bufferevent_write(wp->event, buf, len);
}
}

View File

@ -1161,6 +1161,9 @@ input_csi_dispatch(struct input_ctx *ictx)
case 1003:
screen_write_mousemode_off(&ictx->ctx);
break;
case 1005:
screen_write_utf8mousemode(&ictx->ctx, 0);
break;
case 1049:
window_pane_alternate_off(wp, &ictx->cell);
break;
@ -1209,6 +1212,9 @@ input_csi_dispatch(struct input_ctx *ictx)
case 1003:
screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
break;
case 1005:
screen_write_utf8mousemode(&ictx->ctx, 1);
break;
case 1049:
window_pane_alternate_on(wp, &ictx->cell);
break;

View File

@ -198,6 +198,11 @@ const struct options_table_entry session_options_table[] = {
.default_num = 0
},
{ .name = "mouse-utf8",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0
},
{ .name = "pane-active-border-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8

View File

@ -829,6 +829,18 @@ screen_write_insertmode(struct screen_write_ctx *ctx, int state)
s->mode &= ~MODE_INSERT;
}
/* Set UTF-8 mouse mode. */
void
screen_write_utf8mousemode(struct screen_write_ctx *ctx, int state)
{
struct screen *s = ctx->s;
if (state)
s->mode |= MODE_MOUSE_UTF8;
else
s->mode &= ~MODE_MOUSE_UTF8;
}
/* Set mouse mode off. */
void
screen_write_mousemode_off(struct screen_write_ctx *ctx)

View File

@ -451,6 +451,21 @@ server_client_reset_state(struct client *c)
if (TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry) != NULL &&
options_get_number(oo, "mouse-select-pane"))
mode |= MODE_MOUSE_STANDARD;
/*
* Set UTF-8 mouse input if required. If the terminal is UTF-8, the
* user has set mouse-utf8 and any mouse mode is in effect, turn on
* UTF-8 mouse input. If the receiving terminal hasn't requested it
* (that is, it isn't in s->mode), then it'll be converted in
* input_mouse.
*/
if ((c->tty.flags & TTY_UTF8) &&
(mode & ALL_MOUSE_MODES) && options_get_number(oo, "mouse-utf8"))
mode |= MODE_MOUSE_UTF8;
else
mode &= ~MODE_MOUSE_UTF8;
/* Set the terminal mode and reset attributes. */
tty_update_mode(&c->tty, mode);
tty_reset(&c->tty);
}

4
tmux.1
View File

@ -1806,6 +1806,10 @@ flag to
Repeat is enabled for the default keys bound to the
.Ic resize-pane
command.
.It Xo Ic mouse-utf8
.Op Ic on | off
.Xc
If enabled, request mouse input as UTF-8 on UTF-8 terminals.
.It Xo Ic set-remain-on-exit
.Op Ic on | off
.Xc

1
tmux.c
View File

@ -334,6 +334,7 @@ main(int argc, char **argv)
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
if (flags & IDENTIFY_UTF8) {
options_set_number(&global_s_options, "status-utf8", 1);
options_set_number(&global_s_options, "mouse-utf8", 1);
options_set_number(&global_w_options, "utf8", 1);
}

10
tmux.h
View File

@ -550,6 +550,7 @@ struct mode_key_table {
#define MODE_MOUSE_HIGHLIGHT 0x40
#define MODE_MOUSE_BUTTON 0x80
#define MODE_MOUSE_ANY 0x100
#define MODE_MOUSE_UTF8 0x200
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD| \
MODE_MOUSE_HIGHLIGHT|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
@ -1075,15 +1076,15 @@ struct tty_ctx {
*/
/* Mouse input. */
struct mouse_event {
u_char b;
u_int b;
#define MOUSE_1 0
#define MOUSE_2 1
#define MOUSE_3 2
#define MOUSE_UP 3
#define MOUSE_BUTTON 3
#define MOUSE_45 64
u_char x;
u_char y;
u_int x;
u_int y;
};
/* Saved message entry. */
@ -1817,6 +1818,7 @@ void screen_write_cursormode(struct screen_write_ctx *, int);
void screen_write_reverseindex(struct screen_write_ctx *);
void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
void screen_write_insertmode(struct screen_write_ctx *, int);
void screen_write_utf8mousemode(struct screen_write_ctx *, int);
void screen_write_mousemode_on(struct screen_write_ctx *, int);
void screen_write_mousemode_off(struct screen_write_ctx *);
void screen_write_linefeed(struct screen_write_ctx *, int);
@ -2017,6 +2019,8 @@ void session_group_synchronize1(struct session *, struct session *);
void utf8_build(void);
int utf8_open(struct utf8_data *, u_char);
int utf8_append(struct utf8_data *, u_char);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_split2(u_int, u_char *);
/* procname.c */
char *get_proc_name(int, char *);

View File

@ -38,7 +38,7 @@ 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(
int tty_keys_mouse(struct tty *,
const char *, size_t, size_t *, struct mouse_event *);
struct tty_key_ent {
@ -462,7 +462,7 @@ tty_keys_next(struct tty *tty)
}
/* Is this a mouse key press? */
switch (tty_keys_mouse(buf, len, &size, &mouse)) {
switch (tty_keys_mouse(tty, buf, len, &size, &mouse)) {
case 0: /* yes */
evbuffer_drain(tty->event->input, size);
key = KEYC_MOUSE;
@ -584,44 +584,74 @@ tty_keys_callback(unused int fd, unused short events, void *data)
* (probably a mouse sequence but need more data).
*/
int
tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m)
tty_keys_mouse(struct tty *tty,
const char *buf, size_t len, size_t *size, struct mouse_event *m)
{
struct utf8_data utf8data;
u_int i, value;
/*
* Mouse sequences are \033[M followed by three characters indicating
* buttons, X and Y, all based at 32 with 1,1 top-left.
* Standard mouse sequences are \033[M followed by three characters
* indicating buttons, X and Y, all based at 32 with 1,1 top-left.
*
* UTF-8 mouse sequences are similar but the three are expressed as
* UTF-8 characters.
*/
*size = 0;
/* First three bytes are always \033[M. */
if (buf[0] != '\033')
return (-1);
if (len == 1)
return (1);
if (buf[1] != '[')
return (-1);
if (len == 2)
return (1);
if (buf[2] != 'M')
return (-1);
if (len == 3)
return (1);
if (len < 6)
return (1);
*size = 6;
/* Read the three inputs. */
*size = 3;
for (i = 0; i < 3; i++) {
if (len < *size)
return (1);
log_debug(
"mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
if (tty->mode & MODE_MOUSE_UTF8) {
if (utf8_open(&utf8data, buf[*size])) {
if (utf8data.size != 2)
return (-1);
(*size)++;
if (len < *size)
return (1);
utf8_append(&utf8data, buf[*size]);
value = utf8_combine(&utf8data);
} else
value = buf[*size];
(*size)++;
} else {
value = buf[*size];
(*size)++;
}
m->b = buf[3];
m->x = buf[4];
m->y = buf[5];
if (i == 0)
m->b = value;
else if (i == 1)
m->x = value;
else
m->y = value;
}
log_debug("mouse input: %.*s", (int) *size, buf);
/* Check and return the mouse input. */
if (m->b < 32 || m->x < 33 || m->y < 33)
return (-1);
m->b -= 32;
m->x -= 33;
m->y -= 33;
log_debug("mouse position: x=%u y=%u b=%u", m->x, m->y, m->b);
return (0);
}

4
tty.c
View File

@ -405,6 +405,8 @@ tty_update_mode(struct tty *tty, int mode)
}
if (changed & ALL_MOUSE_MODES) {
if (mode & ALL_MOUSE_MODES) {
if (mode & MODE_MOUSE_UTF8)
tty_puts(tty, "\033[?1005h");
if (mode & MODE_MOUSE_STANDARD)
tty_puts(tty, "\033[?1000h");
else if (mode & MODE_MOUSE_HIGHLIGHT)
@ -422,6 +424,8 @@ tty_update_mode(struct tty *tty, int mode)
tty_puts(tty, "\033[?1002l");
else if (tty->mode & MODE_MOUSE_ANY)
tty_puts(tty, "\033[?1003l");
if (tty->mode & MODE_MOUSE_UTF8)
tty_puts(tty, "\033[?1005l");
}
}
if (changed & MODE_KKEYPAD) {

13
utf8.c
View File

@ -318,6 +318,19 @@ utf8_combine(const struct utf8_data *utf8data)
return (value);
}
/* Split a two-byte UTF-8 character. */
u_int
utf8_split2(u_int uc, u_char *ptr)
{
if (uc > 0x7f) {
ptr[0] = (uc >> 6) | 0xc0;
ptr[1] = (uc & 0x3f) | 0x80;
return (2);
}
ptr[0] = uc;
return (1);
}
/* Lookup width of UTF-8 data in tree. */
u_int
utf8_width(const struct utf8_data *utf8data)