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.
pull/1/head
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)