Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam 2015-11-12 12:01:17 +00:00
commit 5f483499f3
30 changed files with 451 additions and 340 deletions

View File

@ -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;

View File

@ -51,7 +51,6 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
char *action, *action_data;
const char *template;
u_int idx;
int utf8flag;
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
cmdq_error(cmdq, "no client available");
@ -63,7 +62,6 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
utf8flag = options_get_number(wl->window->options, "utf8");
if (paste_get_top(NULL) == NULL)
return (CMD_RETURN_NORMAL);
@ -83,7 +81,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
cdata->idx = idx;
cdata->ft_template = xstrdup(template);
format_defaults_paste_buffer(cdata->ft, pb, utf8flag);
format_defaults_paste_buffer(cdata->ft, pb);
xasprintf(&action_data, "%s", paste_buffer_name(pb));
cdata->command = cmd_template_replace(action, action_data, 1);

View File

@ -55,7 +55,7 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
pb = NULL;
while ((pb = paste_walk(pb)) != NULL) {
ft = format_create();
format_defaults_paste_buffer(ft, pb, 0);
format_defaults_paste_buffer(ft, pb);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);

View File

@ -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);

View File

@ -133,7 +133,7 @@ void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
const char *bufname = data;
char *pdata, *cause;
char *pdata, *cause, *saved;
size_t psize;
if (!closed)
@ -154,6 +154,11 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
if (paste_set(pdata, psize, bufname, &cause) != 0) {
/* No context so can't use server_client_msg_error. */
if (~c->flags & CLIENT_UTF8) {
saved = cause;
cause = utf8_sanitize(saved);
free(saved);
}
evbuffer_add_printf(c->stderr_data, "%s", cause);
server_push_stderr(c);
free(pdata);

View File

@ -69,14 +69,21 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
struct client *c = cmdq->client;
struct window *w;
va_list ap;
char *tmp, *msg;
va_start(ap, fmt);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
if (~c->flags & CLIENT_UTF8) {
vasprintf(&tmp, fmt, ap);
msg = utf8_sanitize(tmp);
free(tmp);
evbuffer_add(c->stdout_data, msg, strlen(msg));
free(msg);
} else
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
} else {
@ -101,6 +108,7 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
va_list ap;
char *msg;
size_t msglen;
char *tmp;
va_start(ap, fmt);
msglen = xvasprintf(&msg, fmt, ap);
@ -109,9 +117,14 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL)
cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
if (~c->flags & CLIENT_UTF8) {
tmp = msg;
msg = utf8_sanitize(tmp);
free(tmp);
msglen = strlen(msg);
}
evbuffer_add(c->stderr_data, msg, msglen);
evbuffer_add(c->stderr_data, "\n", 1);
server_push_stderr(c);
c->retval = 1;
} else {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -1156,16 +1156,13 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
!!(wp->base.mode & MODE_MOUSE_STANDARD));
format_add(ft, "mouse_button_flag", "%d",
!!(wp->base.mode & MODE_MOUSE_BUTTON));
format_add(ft, "mouse_utf8_flag", "%d",
!!(wp->base.mode & MODE_MOUSE_UTF8));
format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
}
/* Set default format keys for paste buffer. */
void
format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
int utf8flag)
format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
{
size_t bufsize;
char *s;
@ -1174,7 +1171,7 @@ format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
format_add(ft, "buffer_size", "%zu", bufsize);
format_add(ft, "buffer_name", "%s", paste_buffer_name(pb));
s = paste_make_sample(pb, utf8flag);
s = paste_make_sample(pb);
format_add(ft, "buffer_sample", "%s", s);
free(s);
}

View File

@ -33,7 +33,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;
@ -136,15 +136,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. */
@ -156,13 +157,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;
}
@ -195,11 +205,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)

View File

@ -1921,11 +1921,6 @@ input_exit_rename(struct input_ctx *ictx)
int
input_utf8_open(struct input_ctx *ictx)
{
if (!options_get_number(ictx->wp->window->options, "utf8")) {
/* Print, and do not switch state. */
input_print(ictx);
return (-1);
}
log_debug("%s", __func__);
utf8_open(&ictx->utf8data, ictx->ch);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -415,11 +415,6 @@ const struct options_table_entry session_options_table[] = {
.default_str = "bg=green,fg=black"
},
{ .name = "status-utf8",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0 /* overridden in main() */
},
{ .name = "update-environment",
.type = OPTIONS_TABLE_STRING,
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
@ -623,11 +618,6 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0
},
{ .name = "utf8",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0 /* overridden in main() */
},
{ .name = "window-active-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"

View File

@ -274,7 +274,7 @@ paste_set(char *data, size_t size, const char *name, char **cause)
/* Convert start of buffer into a nice string. */
char *
paste_make_sample(struct paste_buffer *pb, int utf8flag)
paste_make_sample(struct paste_buffer *pb)
{
char *buf;
size_t len, used;
@ -286,10 +286,7 @@ paste_make_sample(struct paste_buffer *pb, int utf8flag)
len = width;
buf = xreallocarray(NULL, len, 4 + 4);
if (utf8flag)
used = utf8_strvis(buf, pb->data, len, flags);
else
used = strvisx(buf, pb->data, len, flags);
used = utf8_strvis(buf, pb->data, len, flags);
if (pb->size > width || used > width)
strlcpy(buf + width, "...", 4);
return (buf);

View File

@ -73,7 +73,7 @@ screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
/* Calculate string length, with embedded formatting. */
size_t
screen_write_cstrlen(int utf8flag, const char *fmt, ...)
screen_write_cstrlen(const char *fmt, ...)
{
va_list ap;
char *msg, *msg2, *ptr, *ptr2;
@ -98,7 +98,7 @@ screen_write_cstrlen(int utf8flag, const char *fmt, ...)
}
*ptr2 = '\0';
size = screen_write_strlen(utf8flag, "%s", msg2);
size = screen_write_strlen("%s", msg2);
free(msg);
free(msg2);
@ -108,7 +108,7 @@ screen_write_cstrlen(int utf8flag, const char *fmt, ...)
/* Calculate string length. */
size_t
screen_write_strlen(int utf8flag, const char *fmt, ...)
screen_write_strlen(const char *fmt, ...)
{
va_list ap;
char *msg;
@ -122,7 +122,7 @@ screen_write_strlen(int utf8flag, const char *fmt, ...)
ptr = msg;
while (*ptr != '\0') {
if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
if (*ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
ptr++;
left = strlen(ptr);
@ -134,7 +134,8 @@ screen_write_strlen(int utf8flag, const char *fmt, ...)
size += utf8data.width;
} else {
size++;
if (*ptr > 0x1f && *ptr < 0x7f)
size++;
ptr++;
}
}
@ -151,25 +152,25 @@ screen_write_puts(struct screen_write_ctx *ctx, struct grid_cell *gc,
va_list ap;
va_start(ap, fmt);
screen_write_vnputs(ctx, -1, gc, 0, fmt, ap);
screen_write_vnputs(ctx, -1, gc, fmt, ap);
va_end(ap);
}
/* Write string with length limit (-1 for unlimited). */
void
screen_write_nputs(struct screen_write_ctx *ctx, ssize_t maxlen,
struct grid_cell *gc, int utf8flag, const char *fmt, ...)
struct grid_cell *gc, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
screen_write_vnputs(ctx, maxlen, gc, utf8flag, fmt, ap);
screen_write_vnputs(ctx, maxlen, gc, fmt, ap);
va_end(ap);
}
void
screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
struct grid_cell *gc, int utf8flag, const char *fmt, va_list ap)
struct grid_cell *gc, const char *fmt, va_list ap)
{
char *msg;
struct utf8_data utf8data;
@ -180,7 +181,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
ptr = msg;
while (*ptr != '\0') {
if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
if (*ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
ptr++;
left = strlen(ptr);
@ -208,7 +209,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
if (*ptr == '\001')
gc->attr ^= GRID_ATTR_CHARSET;
else {
else if (*ptr > 0x1f && *ptr < 0x7f) {
size++;
screen_write_putc(ctx, gc, *ptr);
}
@ -221,8 +222,8 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
/* Write string, similar to nputs, but with embedded formatting (#[]). */
void
screen_write_cnputs(struct screen_write_ctx *ctx,
ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
struct grid_cell *gc, const char *fmt, ...)
{
struct grid_cell lgc;
struct utf8_data utf8data;
@ -253,7 +254,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
continue;
}
if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
if (*ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
ptr++;
left = strlen(ptr);
@ -279,8 +280,10 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
if (maxlen > 0 && size + 1 > (size_t) maxlen)
break;
size++;
screen_write_putc(ctx, &lgc, *ptr);
if (*ptr > 0x1f && *ptr < 0x7f) {
size++;
screen_write_putc(ctx, &lgc, *ptr);
}
ptr++;
}
}

View File

@ -30,22 +30,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_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 *);
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
@ -255,7 +255,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;
@ -265,7 +265,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);
@ -499,7 +499,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;
@ -633,8 +633,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;

View File

@ -29,10 +29,10 @@
#include "tmux.h"
char *status_redraw_get_left(struct client *, time_t, int, struct grid_cell *,
char *status_redraw_get_left(struct client *, time_t, struct grid_cell *,
size_t *);
char *status_redraw_get_right(struct client *, time_t, struct grid_cell *,
size_t *);
char *status_redraw_get_right(struct client *, time_t, int,
struct grid_cell *, size_t *);
char *status_print(struct client *, struct winlink *, time_t,
struct grid_cell *);
char *status_replace(struct client *, struct winlink *, const char *, time_t);
@ -208,8 +208,8 @@ status_at_line(struct client *c)
/* Retrieve options for left string. */
char *
status_redraw_get_left(struct client *c, time_t t, int utf8flag,
struct grid_cell *gc, size_t *size)
status_redraw_get_left(struct client *c, time_t t, struct grid_cell *gc,
size_t *size)
{
struct session *s = c->session;
const char *template;
@ -222,7 +222,7 @@ status_redraw_get_left(struct client *c, time_t t, int utf8flag,
left = status_replace(c, NULL, template, t);
*size = options_get_number(s->options, "status-left-length");
leftlen = screen_write_cstrlen(utf8flag, "%s", left);
leftlen = screen_write_cstrlen("%s", left);
if (leftlen < *size)
*size = leftlen;
return (left);
@ -230,8 +230,8 @@ status_redraw_get_left(struct client *c, time_t t, int utf8flag,
/* Retrieve options for right string. */
char *
status_redraw_get_right(struct client *c, time_t t, int utf8flag,
struct grid_cell *gc, size_t *size)
status_redraw_get_right(struct client *c, time_t t, struct grid_cell *gc,
size_t *size)
{
struct session *s = c->session;
const char *template;
@ -244,7 +244,7 @@ status_redraw_get_right(struct client *c, time_t t, int utf8flag,
right = status_replace(c, NULL, template, t);
*size = options_get_number(s->options, "status-right-length");
rightlen = screen_write_cstrlen(utf8flag, "%s", right);
rightlen = screen_write_cstrlen("%s", right);
if (rightlen < *size)
*size = rightlen;
return (right);
@ -286,7 +286,7 @@ status_redraw(struct client *c)
u_int offset, needed;
u_int wlstart, wlwidth, wlavailable, wloffset, wlsize;
size_t llen, rlen, seplen;
int larrow, rarrow, utf8flag;
int larrow, rarrow;
/* No status line? */
if (c->tty.sy == 0 || !options_get_number(s->options, "status"))
@ -312,14 +312,11 @@ status_redraw(struct client *c)
if (c->tty.sy <= 1)
goto out;
/* Get UTF-8 flag. */
utf8flag = options_get_number(s->options, "status-utf8");
/* Work out left and right strings. */
memcpy(&lgc, &stdgc, sizeof lgc);
left = status_redraw_get_left(c, t, utf8flag, &lgc, &llen);
left = status_redraw_get_left(c, t, &lgc, &llen);
memcpy(&rgc, &stdgc, sizeof rgc);
right = status_redraw_get_right(c, t, utf8flag, &rgc, &rlen);
right = status_redraw_get_right(c, t, &rgc, &rlen);
/*
* Figure out how much space we have for the window list. If there
@ -340,15 +337,14 @@ status_redraw(struct client *c)
free(wl->status_text);
memcpy(&wl->status_cell, &stdgc, sizeof wl->status_cell);
wl->status_text = status_print(c, wl, t, &wl->status_cell);
wl->status_width =
screen_write_cstrlen(utf8flag, "%s", wl->status_text);
wl->status_width = screen_write_cstrlen("%s", wl->status_text);
if (wl == s->curw)
wloffset = wlwidth;
oo = wl->window->options;
sep = options_get_string(oo, "window-status-separator");
seplen = screen_write_strlen(utf8flag, "%s", sep);
seplen = screen_write_strlen("%s", sep);
wlwidth += wl->status_width + seplen;
}
@ -358,12 +354,12 @@ status_redraw(struct client *c)
/* And draw the window list into it. */
screen_write_start(&ctx, NULL, &window_list);
RB_FOREACH(wl, winlinks, &s->windows) {
screen_write_cnputs(&ctx,
-1, &wl->status_cell, utf8flag, "%s", wl->status_text);
screen_write_cnputs(&ctx, -1, &wl->status_cell, "%s",
wl->status_text);
oo = wl->window->options;
sep = options_get_string(oo, "window-status-separator");
screen_write_nputs(&ctx, -1, &stdgc, utf8flag, "%s", sep);
screen_write_nputs(&ctx, -1, &stdgc, "%s", sep);
}
screen_write_stop(&ctx);
@ -435,7 +431,7 @@ draw:
/* Draw the left string and arrow. */
screen_write_cursormove(&ctx, 0, 0);
if (llen != 0)
screen_write_cnputs(&ctx, llen, &lgc, utf8flag, "%s", left);
screen_write_cnputs(&ctx, llen, &lgc, "%s", left);
if (larrow != 0) {
memcpy(&gc, &stdgc, sizeof gc);
if (larrow == -1)
@ -453,7 +449,7 @@ draw:
} else
screen_write_cursormove(&ctx, c->tty.sx - rlen, 0);
if (rlen != 0)
screen_write_cnputs(&ctx, rlen, &rgc, utf8flag, "%s", right);
screen_write_cnputs(&ctx, rlen, &rgc, "%s", right);
/* Figure out the offset for the window list. */
if (llen != 0)
@ -624,16 +620,13 @@ status_message_redraw(struct client *c)
struct screen old_status;
size_t len;
struct grid_cell gc;
int utf8flag;
if (c->tty.sx == 0 || c->tty.sy == 0)
return (0);
memcpy(&old_status, &c->status, sizeof old_status);
screen_init(&c->status, c->tty.sx, 1, 0);
utf8flag = options_get_number(s->options, "status-utf8");
len = screen_write_strlen(utf8flag, "%s", c->message_string);
len = screen_write_strlen("%s", c->message_string);
if (len > c->tty.sx)
len = c->tty.sx;
@ -642,7 +635,7 @@ status_message_redraw(struct client *c)
screen_write_start(&ctx, NULL, &c->status);
screen_write_cursormove(&ctx, 0, 0);
screen_write_nputs(&ctx, len, &gc, utf8flag, "%s", c->message_string);
screen_write_nputs(&ctx, len, &gc, "%s", c->message_string);
for (; len < c->tty.sx; len++)
screen_write_putc(&ctx, &gc, ' ');
@ -754,16 +747,13 @@ status_prompt_redraw(struct client *c)
struct screen old_status;
size_t i, size, left, len, off;
struct grid_cell gc, *gcp;
int utf8flag;
if (c->tty.sx == 0 || c->tty.sy == 0)
return (0);
memcpy(&old_status, &c->status, sizeof old_status);
screen_init(&c->status, c->tty.sx, 1, 0);
utf8flag = options_get_number(s->options, "status-utf8");
len = screen_write_strlen(utf8flag, "%s", c->prompt_string);
len = screen_write_strlen("%s", c->prompt_string);
if (len > c->tty.sx)
len = c->tty.sx;
off = 0;
@ -777,19 +767,19 @@ status_prompt_redraw(struct client *c)
screen_write_start(&ctx, NULL, &c->status);
screen_write_cursormove(&ctx, 0, 0);
screen_write_nputs(&ctx, len, &gc, utf8flag, "%s", c->prompt_string);
screen_write_nputs(&ctx, len, &gc, "%s", c->prompt_string);
left = c->tty.sx - len;
if (left != 0) {
size = screen_write_strlen(utf8flag, "%s", c->prompt_buffer);
size = screen_write_strlen("%s", c->prompt_buffer);
if (c->prompt_index >= left) {
off = c->prompt_index - left + 1;
if (c->prompt_index == size)
left--;
size = left;
}
screen_write_nputs(
&ctx, left, &gc, utf8flag, "%s", c->prompt_buffer + off);
screen_write_nputs(&ctx, left, &gc, "%s", c->prompt_buffer +
off);
for (i = len + size; i < c->tty.sx; i++)
screen_write_putc(&ctx, &gc, ' ');
@ -812,7 +802,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 +1106,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);

41
tmux.1
View File

@ -190,13 +190,11 @@ flag explicitly informs
.Nm
that UTF-8 is supported.
.Pp
If the server is started from a client passed
.Fl u
or where UTF-8 is detected, the
.Ic utf8
and
.Ic status-utf8
options are enabled in the global window and session options respectively.
Note that
.Nm
itself always accepts UTF-8, this controls whether it will send UTF-8
characters to the terminal it is running it (if not, they are replaced by
.Ql _ ) .
.It Fl v
Request verbose logging.
This option may be specified multiple times for increasing verbosity.
@ -2774,12 +2772,6 @@ Examples are:
#[fg=yellow,bold]#(apm -l)%%#[default] [#S]
.Ed
.Pp
By default, UTF-8 in
.Ar string
is not interpreted, to enable UTF-8, use the
.Ic status-utf8
option.
.Pp
The default is
.Ql "[#S] " .
.It Ic status-left-length Ar length
@ -2809,9 +2801,7 @@ As with
.Ar string
will be passed to
.Xr strftime 3 ,
character pairs are replaced, and UTF-8 is dependent on the
.Ic status-utf8
option.
character pairs are replaced.
.It Ic status-right-length Ar length
Set the maximum
.Ar length
@ -2831,17 +2821,6 @@ For how to specify
see the
.Ic message-command-style
option.
.It Xo Ic status-utf8
.Op Ic on | off
.Xc
Instruct
.Nm
to treat top-bit-set characters in the
.Ic status-left
and
.Ic status-right
strings as UTF-8; notably, this is important for wide characters.
This option defaults to off.
.It Ic update-environment Ar variables
Set a space-separated string containing a list of environment variables to be
copied into the session environment when a new session is created or an
@ -3088,13 +3067,6 @@ command.
Duplicate input to any pane to all other panes in the same window (only
for panes that are not in any special mode).
.Pp
.It Xo Ic utf8
.Op Ic on | off
.Xc
Instructs
.Nm
to expect UTF-8 sequences to appear in this window.
.Pp
.It Ic window-active-style Ar style
Set the style for the window's active pane.
For how to specify
@ -3398,7 +3370,6 @@ The following variables are available, where appropriate:
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
.It Li "pane_active" Ta "" Ta "1 if active pane"
.It Li "pane_bottom" Ta "" Ta "Bottom of pane"
.It Li "pane_current_command" Ta "" Ta "Current command if available"

44
tmux.c
View File

@ -193,8 +193,9 @@ find_home(void)
int
main(int argc, char **argv)
{
char *s, *path, *label, **var, tmp[PATH_MAX];
int opt, flags, keys;
char *path, *label, **var, tmp[PATH_MAX];
const char *s;
int opt, flags, keys;
#if defined(DEBUG) && defined(__OpenBSD__)
malloc_options = (char *) "AFGJPX";
@ -265,20 +266,25 @@ main(int argc, char **argv)
err(1, "pledge");
#endif
if (!(flags & CLIENT_UTF8)) {
/*
* If the user has set whichever of LC_ALL, LC_CTYPE or LANG
* exist (in that order) to contain UTF-8, it is a safe
* assumption that either they are using a UTF-8 terminal, or
* if not they know that output from UTF-8-capable programs may
* be wrong.
*/
if ((s = getenv("LC_ALL")) == NULL || *s == '\0') {
if ((s = getenv("LC_CTYPE")) == NULL || *s == '\0')
s = getenv("LANG");
}
if (s != NULL && (strcasestr(s, "UTF-8") != NULL ||
strcasestr(s, "UTF8") != NULL))
/*
* tmux is a UTF-8 terminal, so if TMUX is set, assume UTF-8.
* Otherwise, if the user has set LC_ALL, LC_CTYPE or LANG to contain
* UTF-8, it is a safe assumption that either they are using a UTF-8
* terminal, or if not they know that output from UTF-8-capable
* programs may be wrong.
*/
if (getenv("TMUX") != NULL)
flags |= CLIENT_UTF8;
else {
s = getenv("LC_ALL");
if (s == NULL || *s == '\0')
s = getenv("LC_CTYPE");
if (s == NULL || *s == '\0')
s = getenv("LANG");
if (s == NULL || *s == '\0')
s = "";
if (strcasestr(s, "UTF-8") != NULL ||
strcasestr(s, "UTF8") != NULL)
flags |= CLIENT_UTF8;
}
@ -298,12 +304,6 @@ main(int argc, char **argv)
global_w_options = options_create(NULL);
options_table_populate_tree(window_options_table, global_w_options);
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
if (flags & CLIENT_UTF8) {
options_set_number(global_s_options, "status-utf8", 1);
options_set_number(global_w_options, "utf8", 1);
}
/* Override keys to vi if VISUAL or EDITOR are set. */
if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
if (strrchr(s, '/') != NULL)

117
tmux.h
View File

@ -98,13 +98,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)
@ -124,8 +124,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,
@ -573,7 +579,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;
@ -779,7 +785,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. */
@ -1033,31 +1039,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;
@ -1343,7 +1349,7 @@ struct cmd_entry {
/* Key binding and key table. */
struct key_binding {
int key;
key_code key;
struct cmd_list *cmdlist;
int can_repeat;
@ -1453,7 +1459,7 @@ void paste_free(struct paste_buffer *);
void paste_add(char *, size_t);
int paste_rename(const char *, const char *, char **);
int paste_set(char *, size_t, const char *, char **);
char *paste_make_sample(struct paste_buffer *, int);
char *paste_make_sample(struct paste_buffer *);
/* format.c */
#define FORMAT_STATUS 0x1
@ -1472,7 +1478,7 @@ void format_defaults_window(struct format_tree *, struct window *);
void format_defaults_pane(struct format_tree *,
struct window_pane *);
void format_defaults_paste_buffer(struct format_tree *,
struct paste_buffer *, int);
struct paste_buffer *);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
@ -1491,7 +1497,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);
@ -1635,9 +1642,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 *);
@ -1723,16 +1730,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);
@ -1756,7 +1763,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 *);
@ -1806,7 +1813,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);
@ -1822,11 +1829,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);
@ -1888,24 +1895,24 @@ void grid_view_delete_cells(struct grid *, u_int, u_int, u_int);
char *grid_view_string_cells(struct grid *, u_int, u_int, u_int);
/* screen-write.c */
void screen_write_start(
struct screen_write_ctx *, struct window_pane *, struct screen *);
void screen_write_start(struct screen_write_ctx *, struct window_pane *,
struct screen *);
void screen_write_stop(struct screen_write_ctx *);
void screen_write_reset(struct screen_write_ctx *);
size_t printflike(2, 3) screen_write_cstrlen(int, const char *, ...);
void printflike(5, 6) screen_write_cnputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, ...);
size_t printflike(2, 3) screen_write_strlen(int, const char *, ...);
size_t printflike(1, 2) screen_write_cstrlen(const char *, ...);
void printflike(4, 5) screen_write_cnputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, const char *, ...);
size_t printflike(1, 2) screen_write_strlen(const char *, ...);
void printflike(3, 4) screen_write_puts(struct screen_write_ctx *,
struct grid_cell *, const char *, ...);
void printflike(5, 6) screen_write_nputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, ...);
void screen_write_vnputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, va_list);
void screen_write_putc(
struct screen_write_ctx *, struct grid_cell *, u_char);
void screen_write_copy(struct screen_write_ctx *,
struct screen *, u_int, u_int, u_int, u_int);
void printflike(4, 5) screen_write_nputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, const char *, ...);
void screen_write_vnputs(struct screen_write_ctx *, ssize_t,
struct grid_cell *, const char *, va_list);
void screen_write_putc(struct screen_write_ctx *, struct grid_cell *,
u_char);
void screen_write_copy(struct screen_write_ctx *, struct screen *, u_int,
u_int, u_int, u_int);
void screen_write_backspace(struct screen_write_ctx *);
void screen_write_mode_set(struct screen_write_ctx *, int);
void screen_write_mode_clear(struct screen_write_ctx *, int);
@ -2023,7 +2030,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 *);
@ -2182,8 +2189,10 @@ 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);
char *utf8_sanitize(const char *);
struct utf8_data *utf8_fromcstr(const char *);
char *utf8_tocstr(struct utf8_data *);
u_int utf8_cstrwidth(const char *);

View File

@ -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)++;
}

78
utf8.c
View File

@ -393,6 +393,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)
@ -466,18 +468,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)
@ -554,6 +584,50 @@ utf8_strvis(char *dst, const char *src, size_t len, int flag)
return (dst - start);
}
/*
* Sanitize a string, changing any UTF-8 characters to '_'. Caller should free
* the returned string. Anything not valid printable ASCII or UTF-8 is
* stripped.
*/
char *
utf8_sanitize(const char *src)
{
char *dst;
size_t n;
int more;
struct utf8_data utf8data;
u_int i;
dst = NULL;
n = 0;
while (*src != '\0') {
dst = xreallocarray(dst, n + 1, sizeof *dst);
if (utf8_open(&utf8data, *src)) {
more = 1;
while (*++src != '\0' && more)
more = utf8_append(&utf8data, *src);
if (!more) {
dst = xreallocarray(dst, n + utf8data.width,
sizeof *dst);
for (i = 0; i < utf8data.width; i++)
dst[n++] = '_';
continue;
}
src -= utf8data.have;
}
if (*src > 0x1f && *src < 0x7f)
dst[n] = *src;
src++;
n++;
}
dst = xreallocarray(dst, n + 1, sizeof *dst);
dst[n] = '\0';
return (dst);
}
/*
* Convert a string into a buffer of UTF-8 characters. Terminated by size == 0.
* Caller frees.

View File

@ -29,11 +29,11 @@ struct screen *window_choose_init(struct window_pane *);
void window_choose_free(struct window_pane *);
void window_choose_resize(struct window_pane *, u_int, u_int);
void window_choose_key(struct window_pane *, struct client *,
struct session *, int, struct mouse_event *);
struct session *, key_code, struct mouse_event *);
void window_choose_default_callback(struct window_choose_data *);
struct window_choose_mode_item *window_choose_get_item(struct window_pane *,
int, struct mouse_event *);
key_code, struct mouse_event *);
void window_choose_fire_callback(
struct window_pane *, struct window_choose_data *);
@ -86,9 +86,9 @@ struct window_choose_mode_data {
void window_choose_free1(struct window_choose_mode_data *);
int window_choose_key_index(struct window_choose_mode_data *, u_int);
int window_choose_index_key(struct window_choose_mode_data *, int);
int window_choose_index_key(struct window_choose_mode_data *, key_code);
void window_choose_prompt_input(enum window_choose_input_type,
const char *, struct window_pane *, int);
const char *, struct window_pane *, key_code);
void window_choose_reset_top(struct window_pane *, u_int);
void
@ -314,7 +314,7 @@ window_choose_fire_callback(
void
window_choose_prompt_input(enum window_choose_input_type input_type,
const char *prompt, struct window_pane *wp, int key)
const char *prompt, struct window_pane *wp, key_code key)
{
struct window_choose_mode_data *data = wp->modedata;
size_t input_len;
@ -490,7 +490,8 @@ window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
}
struct window_choose_mode_item *
window_choose_get_item(struct window_pane *wp, int key, struct mouse_event *m)
window_choose_get_item(struct window_pane *wp, key_code key,
struct mouse_event *m)
{
struct window_choose_mode_data *data = wp->modedata;
u_int x, y, idx;
@ -509,7 +510,7 @@ window_choose_get_item(struct window_pane *wp, int key, struct mouse_event *m)
void
window_choose_key(struct window_pane *wp, unused struct client *c,
unused struct session *sess, int key, struct mouse_event *m)
unused struct session *sess, key_code key, struct mouse_event *m)
{
struct window_choose_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
@ -743,8 +744,8 @@ window_choose_key(struct window_pane *wp, unused struct client *c,
}
void
window_choose_write_line(
struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
window_choose_write_line(struct window_pane *wp, struct screen_write_ctx *ctx,
u_int py)
{
struct window_choose_mode_data *data = wp->modedata;
struct window_choose_mode_item *item;
@ -753,13 +754,12 @@ window_choose_write_line(
struct grid_cell gc;
size_t last, xoff = 0;
char hdr[32], label[32];
int utf8flag, key;
int key;
if (data->callbackfn == NULL)
fatalx("called before callback assigned");
last = screen_size_y(s) - 1;
utf8flag = options_get_number(wp->window->options, "utf8");
memcpy(&gc, &grid_default_cell, sizeof gc);
if (data->selected == data->top + py)
style_apply(&gc, oo, "mode-style");
@ -776,7 +776,7 @@ window_choose_write_line(
xsnprintf(label, sizeof label, "(%c)", key);
else
xsnprintf(label, sizeof label, "(%d)", item->pos);
screen_write_nputs(ctx, screen_size_x(s) - 1, &gc, utf8flag,
screen_write_nputs(ctx, screen_size_x(s) - 1, &gc,
"%*s %s %s", data->width + 2, label,
/*
* Add indication to tree if necessary about whether it's
@ -821,7 +821,7 @@ window_choose_key_index(struct window_choose_mode_data *data, u_int idx)
}
int
window_choose_index_key(struct window_choose_mode_data *data, int key)
window_choose_index_key(struct window_choose_mode_data *data, key_code key)
{
static const char keys[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
@ -834,7 +834,7 @@ window_choose_index_key(struct window_choose_mode_data *data, int key)
mkey = mode_key_lookup(&data->mdata, *ptr, NULL);
if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER)
continue;
if (key == *ptr)
if (key == (key_code)*ptr)
return (idx);
idx++;
}

View File

@ -28,7 +28,7 @@ struct screen *window_clock_init(struct window_pane *);
void window_clock_free(struct window_pane *);
void window_clock_resize(struct window_pane *, u_int, u_int);
void window_clock_key(struct window_pane *, struct client *,
struct session *, int, struct mouse_event *);
struct session *, key_code, struct mouse_event *);
void window_clock_timer_callback(int, short, void *);
void window_clock_draw_screen(struct window_pane *);
@ -186,7 +186,8 @@ window_clock_resize(struct window_pane *wp, u_int sx, u_int sy)
void
window_clock_key(struct window_pane *wp, unused struct client *c,
unused struct session *sess, unused int key, unused struct mouse_event *m)
unused struct session *sess, unused key_code key,
unused struct mouse_event *m)
{
window_pane_reset_mode(wp);
}

View File

@ -28,9 +28,9 @@ struct screen *window_copy_init(struct window_pane *);
void window_copy_free(struct window_pane *);
void window_copy_resize(struct window_pane *, u_int, u_int);
void window_copy_key(struct window_pane *, struct client *, struct session *,
int, struct mouse_event *);
int window_copy_key_input(struct window_pane *, int);
int window_copy_key_numeric_prefix(struct window_pane *, int);
key_code, struct mouse_event *);
int window_copy_key_input(struct window_pane *, key_code);
int window_copy_key_numeric_prefix(struct window_pane *, key_code);
void window_copy_redraw_selection(struct window_pane *, u_int);
void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
@ -280,13 +280,11 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
struct screen *backing = data->backing;
struct screen_write_ctx back_ctx, ctx;
struct grid_cell gc;
int utf8flag;
u_int old_hsize, old_cy;
if (backing == &wp->base)
return;
utf8flag = options_get_number(wp->window->options, "utf8");
memcpy(&gc, &grid_default_cell, sizeof gc);
old_hsize = screen_hsize(data->backing);
@ -301,7 +299,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
} else
data->backing_written = 1;
old_cy = backing->cy;
screen_write_vnputs(&back_ctx, 0, &gc, utf8flag, fmt, ap);
screen_write_vnputs(&back_ctx, 0, &gc, fmt, ap);
screen_write_stop(&back_ctx);
data->oy += screen_hsize(data->backing) - old_hsize;
@ -368,7 +366,7 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
void
window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
int key, struct mouse_event *m)
key_code key, struct mouse_event *m)
{
const char *word_separators;
struct window_copy_mode_data *data = wp->modedata;
@ -800,7 +798,7 @@ input_off:
}
int
window_copy_key_input(struct window_pane *wp, int key)
window_copy_key_input(struct window_pane *wp, key_code key)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
@ -897,7 +895,7 @@ window_copy_key_input(struct window_pane *wp, int key)
}
int
window_copy_key_numeric_prefix(struct window_pane *wp, int key)
window_copy_key_numeric_prefix(struct window_pane *wp, key_code key)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
@ -1021,19 +1019,18 @@ window_copy_search_up(struct window_pane *wp, const char *searchstr)
struct grid_cell gc;
size_t searchlen;
u_int i, last, fx, fy, px;
int utf8flag, n, wrapped, wrapflag, cis;
int n, wrapped, wrapflag, cis;
const char *ptr;
if (*searchstr == '\0')
return;
utf8flag = options_get_number(wp->window->options, "utf8");
wrapflag = options_get_number(wp->window->options, "wrap-search");
searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
searchlen = screen_write_strlen("%s", searchstr);
screen_init(&ss, searchlen, 1, 0);
screen_write_start(&ctx, NULL, &ss);
memcpy(&gc, &grid_default_cell, sizeof gc);
screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr);
screen_write_nputs(&ctx, -1, &gc, "%s", searchstr);
screen_write_stop(&ctx);
fx = data->cx;
@ -1088,19 +1085,18 @@ window_copy_search_down(struct window_pane *wp, const char *searchstr)
struct grid_cell gc;
size_t searchlen;
u_int i, first, fx, fy, px;
int utf8flag, n, wrapped, wrapflag, cis;
int n, wrapped, wrapflag, cis;
const char *ptr;
if (*searchstr == '\0')
return;
utf8flag = options_get_number(wp->window->options, "utf8");
wrapflag = options_get_number(wp->window->options, "wrap-search");
searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
searchlen = screen_write_strlen("%s", searchstr);
screen_init(&ss, searchlen, 1, 0);
screen_write_start(&ctx, NULL, &ss);
memcpy(&gc, &grid_default_cell, sizeof gc);
screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr);
screen_write_nputs(&ctx, -1, &gc, "%s", searchstr);
screen_write_stop(&ctx);
fx = data->cx;

View File

@ -1116,7 +1116,7 @@ window_pane_reset_mode(struct window_pane *wp)
void
window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
int key, struct mouse_event *m)
key_code key, struct mouse_event *m)
{
struct window_pane *wp2;

View File

@ -40,11 +40,12 @@
* We accept any but always output the latter (it comes first in the table).
*/
int xterm_keys_match(const char *, const char *, size_t, size_t *, u_int *);
int xterm_keys_modifiers(const char *, size_t, size_t *, u_int *);
int xterm_keys_match(const char *, const char *, size_t, size_t *,
key_code *);
int xterm_keys_modifiers(const char *, size_t, size_t *, key_code *);
struct xterm_keys_entry {
int key;
key_code key;
const char *template;
};
@ -115,7 +116,7 @@ const struct xterm_keys_entry xterm_keys_table[] = {
*/
int
xterm_keys_match(const char *template, const char *buf, size_t len,
size_t *size, u_int *modifiers)
size_t *size, key_code *modifiers)
{
size_t pos;
int retval;
@ -148,7 +149,8 @@ xterm_keys_match(const char *template, const char *buf, size_t len,
/* Find modifiers from buffer. */
int
xterm_keys_modifiers(const char *buf, size_t len, size_t *pos, u_int *modifiers)
xterm_keys_modifiers(const char *buf, size_t len, size_t *pos,
key_code *modifiers)
{
u_int flags;
@ -179,11 +181,12 @@ xterm_keys_modifiers(const char *buf, size_t len, size_t *pos, u_int *modifiers)
* key), -1 for not found, 1 for partial match.
*/
int
xterm_keys_find(const char *buf, size_t len, size_t *size, int *key)
xterm_keys_find(const char *buf, size_t len, size_t *size, key_code *key)
{
const struct xterm_keys_entry *entry;
u_int i, modifiers;
u_int i;
int matched;
key_code modifiers;
for (i = 0; i < nitems(xterm_keys_table); i++) {
entry = &xterm_keys_table[i];
@ -201,11 +204,11 @@ xterm_keys_find(const char *buf, size_t len, size_t *size, int *key)
/* Lookup a key number from the table. */
char *
xterm_keys_lookup(int key)
xterm_keys_lookup(key_code key)
{
const struct xterm_keys_entry *entry;
u_int i;
int modifiers;
key_code modifiers;
char *out;
modifiers = 1;