mirror of
https://github.com/tmux/tmux.git
synced 2026-01-13 10:10:21 +00:00
Merge branch 'tmux:master' into non-blocking-popup-windows
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
---
|
||||
name: Use this issue template
|
||||
about: Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Issue description
|
||||
|
||||
Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md
|
||||
35
.gitignore
vendored
35
.gitignore
vendored
@@ -1,23 +1,24 @@
|
||||
*.o
|
||||
*~
|
||||
*.diff
|
||||
*.patch
|
||||
*.core
|
||||
core
|
||||
tags
|
||||
*.dSYM
|
||||
*.diff
|
||||
*.o
|
||||
*.patch
|
||||
*.swp
|
||||
*~
|
||||
.deps/
|
||||
compat/.dirstamp
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
config.log
|
||||
config.status
|
||||
etc/
|
||||
tmux
|
||||
.dirstamp
|
||||
Makefile
|
||||
Makefile.in
|
||||
configure
|
||||
tmux.1.*
|
||||
*.dSYM
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
cmd-parse.c
|
||||
compat/.dirstamp
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
core
|
||||
etc/
|
||||
fuzz/*-fuzzer
|
||||
.dirstamp
|
||||
tags
|
||||
tmux
|
||||
tmux.1.*
|
||||
|
||||
8
alerts.c
8
alerts.c
@@ -315,11 +315,11 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option)
|
||||
if (visual == VISUAL_OFF)
|
||||
continue;
|
||||
if (c->session->curw == wl) {
|
||||
status_message_set(c, -1, 1, 0, "%s in current window",
|
||||
type);
|
||||
status_message_set(c, -1, 1, 0, 0,
|
||||
"%s in current window", type);
|
||||
} else {
|
||||
status_message_set(c, -1, 1, 0, "%s in window %d", type,
|
||||
wl->idx);
|
||||
status_message_set(c, -1, 1, 0, 0,
|
||||
"%s in window %d", type, wl->idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ const struct cmd_entry cmd_capture_pane_entry = {
|
||||
.name = "capture-pane",
|
||||
.alias = "capturep",
|
||||
|
||||
.args = { "ab:CeE:JNpPqS:Tt:", 0, 0, NULL },
|
||||
.usage = "[-aCeJNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
|
||||
.args = { "ab:CeE:JMNpPqS:Tt:", 0, 0, NULL },
|
||||
.usage = "[-aCeJMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
|
||||
"[-S start-line] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -107,14 +107,16 @@ static char *
|
||||
cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
struct window_pane *wp, size_t *len)
|
||||
{
|
||||
struct grid *gd;
|
||||
const struct grid_line *gl;
|
||||
struct grid_cell *gc = NULL;
|
||||
int n, join_lines, flags = 0;
|
||||
u_int i, sx, top, bottom, tmp;
|
||||
char *cause, *buf, *line;
|
||||
const char *Sflag, *Eflag;
|
||||
size_t linelen;
|
||||
struct grid *gd;
|
||||
const struct grid_line *gl;
|
||||
struct screen *s;
|
||||
struct grid_cell *gc = NULL;
|
||||
struct window_mode_entry *wme;
|
||||
int n, join_lines, flags = 0;
|
||||
u_int i, sx, top, bottom, tmp;
|
||||
char *cause, *buf, *line;
|
||||
const char *Sflag, *Eflag;
|
||||
size_t linelen;
|
||||
|
||||
sx = screen_size_x(&wp->base);
|
||||
if (args_has(args, 'a')) {
|
||||
@@ -126,8 +128,20 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
}
|
||||
return (xstrdup(""));
|
||||
}
|
||||
} else
|
||||
s = &wp->base;
|
||||
} else if (args_has(args, 'M')) {
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
if (wme != NULL && wme->mode->get_screen != NULL) {
|
||||
s = wme->mode->get_screen (wme);
|
||||
gd = s->grid;
|
||||
} else {
|
||||
s = &wp->base;
|
||||
gd = wp->base.grid;
|
||||
}
|
||||
} else {
|
||||
s = &wp->base;
|
||||
gd = wp->base.grid;
|
||||
}
|
||||
|
||||
Sflag = args_get(args, 'S');
|
||||
if (Sflag != NULL && strcmp(Sflag, "-") == 0)
|
||||
@@ -181,7 +195,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
|
||||
buf = NULL;
|
||||
for (i = top; i <= bottom; i++) {
|
||||
line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen);
|
||||
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
|
||||
linelen = strlen(line);
|
||||
|
||||
buf = cmd_capture_pane_append(buf, len, line, linelen);
|
||||
|
||||
@@ -41,7 +41,7 @@ const struct cmd_entry cmd_display_menu_entry = {
|
||||
.args = { "b:c:C:H:s:S:MOt:T:x:y:", 1, -1, cmd_display_menu_args_parse },
|
||||
.usage = "[-MO] [-b border-lines] [-c target-client] "
|
||||
"[-C starting-choice] [-H selected-style] [-s style] "
|
||||
"[-S border-style] " CMD_TARGET_PANE_USAGE "[-T title] "
|
||||
"[-S border-style] " CMD_TARGET_PANE_USAGE " [-T title] "
|
||||
"[-x position] [-y position] name key command ...",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -58,7 +58,7 @@ const struct cmd_entry cmd_display_popup_entry = {
|
||||
.usage = "[-BCE] [-b border-lines] [-c target-client] "
|
||||
"[-d start-directory] [-e environment] [-h height] "
|
||||
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
|
||||
"[-T title] [-w width] [-x position] [-y position] "
|
||||
" [-T title] [-w width] [-x position] [-y position] "
|
||||
"[shell-command]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@@ -39,8 +39,8 @@ const struct cmd_entry cmd_display_message_entry = {
|
||||
.name = "display-message",
|
||||
.alias = "display",
|
||||
|
||||
.args = { "ac:d:lINpt:F:v", 0, 1, NULL },
|
||||
.usage = "[-aIlNpv] [-c target-client] [-d delay] [-F format] "
|
||||
.args = { "aCc:d:lINpt:F:v", 0, 1, NULL },
|
||||
.usage = "[-aCIlNpv] [-c target-client] [-d delay] [-F format] "
|
||||
CMD_TARGET_PANE_USAGE " [message]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||
@@ -69,6 +69,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
const char *template;
|
||||
char *msg, *cause;
|
||||
int delay = -1, flags, Nflag = args_has(args, 'N');
|
||||
int Cflag = args_has(args, 'C');
|
||||
struct format_tree *ft;
|
||||
u_int count = args_count(args);
|
||||
struct evbuffer *evb;
|
||||
@@ -150,7 +151,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
server_client_print(tc, 0, evb);
|
||||
evbuffer_free(evb);
|
||||
} else if (tc != NULL)
|
||||
status_message_set(tc, delay, 0, Nflag, "%s", msg);
|
||||
status_message_set(tc, delay, 0, Nflag, Cflag, "%s", msg);
|
||||
free(msg);
|
||||
|
||||
format_free(ft);
|
||||
|
||||
@@ -157,7 +157,7 @@ cmd_if_shell_callback(struct job *job)
|
||||
if (cmdlist == NULL) {
|
||||
if (cdata->item == NULL) {
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
status_message_set(c, -1, 1, 0, 0, "%s", error);
|
||||
} else
|
||||
cmdq_error(cdata->item, "%s", error);
|
||||
free(error);
|
||||
|
||||
@@ -91,7 +91,7 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
|
||||
struct key_binding *bd;
|
||||
const char *key;
|
||||
char *tmp, *note;
|
||||
int found = 0;
|
||||
int found = 0;
|
||||
|
||||
table = key_bindings_get_table(tablename, 0);
|
||||
if (table == NULL)
|
||||
@@ -114,8 +114,8 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
|
||||
note = xstrdup(bd->note);
|
||||
tmp = utf8_padcstr(key, keywidth + 1);
|
||||
if (args_has(args, '1') && tc != NULL) {
|
||||
status_message_set(tc, -1, 1, 0, "%s%s%s", prefix, tmp,
|
||||
note);
|
||||
status_message_set(tc, -1, 1, 0, 0, "%s%s%s", prefix,
|
||||
tmp, note);
|
||||
} else
|
||||
cmdq_print(item, "%s%s%s", prefix, tmp, note);
|
||||
free(tmp);
|
||||
@@ -298,8 +298,8 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
free(cp);
|
||||
|
||||
if (args_has(args, '1') && tc != NULL) {
|
||||
status_message_set(tc, -1, 1, 0, "bind-key %s",
|
||||
tmp);
|
||||
status_message_set(tc, -1, 1, 0, 0,
|
||||
"bind-key %s", tmp);
|
||||
} else
|
||||
cmdq_print(item, "bind-key %s", tmp);
|
||||
free(key);
|
||||
@@ -321,6 +321,31 @@ out:
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_list_single_command(const struct cmd_entry *entry, struct format_tree *ft,
|
||||
const char *template, struct cmdq_item *item)
|
||||
{
|
||||
const char *s;
|
||||
char *line;
|
||||
|
||||
format_add(ft, "command_list_name", "%s", entry->name);
|
||||
if (entry->alias != NULL)
|
||||
s = entry->alias;
|
||||
else
|
||||
s = "";
|
||||
format_add(ft, "command_list_alias", "%s", s);
|
||||
if (entry->usage != NULL)
|
||||
s = entry->usage;
|
||||
else
|
||||
s = "";
|
||||
format_add(ft, "command_list_usage", "%s", s);
|
||||
|
||||
line = format_expand(ft, template);
|
||||
if (*line != '\0')
|
||||
cmdq_print(item, "%s", line);
|
||||
free(line);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
@@ -328,8 +353,8 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
|
||||
const struct cmd_entry **entryp;
|
||||
const struct cmd_entry *entry;
|
||||
struct format_tree *ft;
|
||||
const char *template, *s, *command;
|
||||
char *line;
|
||||
const char *template, *command;
|
||||
char *cause;
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL) {
|
||||
template = "#{command_list_name}"
|
||||
@@ -341,30 +366,19 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
|
||||
format_defaults(ft, NULL, NULL, NULL, NULL);
|
||||
|
||||
command = args_string(args, 0);
|
||||
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
||||
entry = *entryp;
|
||||
if (command != NULL &&
|
||||
(strcmp(entry->name, command) != 0 &&
|
||||
(entry->alias == NULL ||
|
||||
strcmp(entry->alias, command) != 0)))
|
||||
continue;
|
||||
|
||||
format_add(ft, "command_list_name", "%s", entry->name);
|
||||
if (entry->alias != NULL)
|
||||
s = entry->alias;
|
||||
else
|
||||
s = "";
|
||||
format_add(ft, "command_list_alias", "%s", s);
|
||||
if (entry->usage != NULL)
|
||||
s = entry->usage;
|
||||
else
|
||||
s = "";
|
||||
format_add(ft, "command_list_usage", "%s", s);
|
||||
|
||||
line = format_expand(ft, template);
|
||||
if (*line != '\0')
|
||||
cmdq_print(item, "%s", line);
|
||||
free(line);
|
||||
if (command == NULL) {
|
||||
for (entryp = cmd_table; *entryp != NULL; entryp++)
|
||||
cmd_list_single_command(*entryp, ft, template, item);
|
||||
} else {
|
||||
entry = cmd_find(command, &cause);
|
||||
if (entry != NULL)
|
||||
cmd_list_single_command(entry, ft, template, item);
|
||||
else {
|
||||
cmdq_error(item, "%s", cause);
|
||||
free(cause);
|
||||
format_free(ft);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
|
||||
10
cmd-parse.y
10
cmd-parse.y
@@ -1627,6 +1627,7 @@ yylex_token_tilde(char **buf, size_t *len)
|
||||
static char *
|
||||
yylex_token(int ch)
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
char *buf;
|
||||
size_t len;
|
||||
enum { START,
|
||||
@@ -1650,9 +1651,12 @@ yylex_token(int ch)
|
||||
ch = '\r';
|
||||
}
|
||||
}
|
||||
if (state == NONE && ch == '\n') {
|
||||
log_debug("%s: end at EOL", __func__);
|
||||
break;
|
||||
if (ch == '\n') {
|
||||
if (state == NONE) {
|
||||
log_debug("%s: end at EOL", __func__);
|
||||
break;
|
||||
}
|
||||
ps->input->line++;
|
||||
}
|
||||
|
||||
/* Whitespace or ; or } ends a token unless inside quotes. */
|
||||
|
||||
@@ -892,7 +892,7 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
|
||||
c->retval = 1;
|
||||
} else {
|
||||
*msg = toupper((u_char) *msg);
|
||||
status_message_set(c, -1, 1, 0, "%s", msg);
|
||||
status_message_set(c, -1, 1, 0, 0, "%s", msg);
|
||||
}
|
||||
|
||||
free(msg);
|
||||
|
||||
@@ -204,7 +204,7 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
|
||||
if (cmdlist == NULL) {
|
||||
if (cdata->item == NULL) {
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
status_message_set(c, -1, 1, 0, 0, "%s", error);
|
||||
} else
|
||||
cmdq_error(cdata->item, "%s", error);
|
||||
free(error);
|
||||
|
||||
@@ -42,7 +42,7 @@ const struct cmd_entry cmd_split_window_entry = {
|
||||
.args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL },
|
||||
.usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE
|
||||
"[shell-command]",
|
||||
" [shell-command]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
|
||||
2
cmd.c
2
cmd.c
@@ -444,7 +444,7 @@ cmd_get_alias(const char *name)
|
||||
}
|
||||
|
||||
/* Look up a command entry by name. */
|
||||
static const struct cmd_entry *
|
||||
const struct cmd_entry *
|
||||
cmd_find(const char *name, char **cause)
|
||||
{
|
||||
const struct cmd_entry **loop, *entry, *found = NULL;
|
||||
|
||||
@@ -638,9 +638,9 @@ else
|
||||
AC_LIBOBJ(err)
|
||||
fi
|
||||
|
||||
# Look for imsg_init in libutil.
|
||||
AC_SEARCH_LIBS(imsg_init, util, found_imsg_init=yes, found_imsg_init=no)
|
||||
if test "x$found_imsg_init" = xyes; then
|
||||
# Look for imsg_add in libutil.
|
||||
AC_SEARCH_LIBS(imsg_add, util, found_imsg_add=yes, found_imsg_add=no)
|
||||
if test "x$found_imsg_add" = xyes; then
|
||||
AC_DEFINE(HAVE_IMSG)
|
||||
else
|
||||
AC_LIBOBJ(imsg)
|
||||
|
||||
27
input-keys.c
27
input-keys.c
@@ -585,17 +585,29 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
/* Is this backspace? */
|
||||
if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
|
||||
newkey = options_get_number(global_options, "backspace");
|
||||
if (newkey == KEYC_BSPACE)
|
||||
newkey = '\b';
|
||||
newkey |= (key & (KEYC_MASK_FLAGS|KEYC_MASK_MODIFIERS));
|
||||
log_debug("%s: key 0x%llx is backspace -> 0x%llx", __func__, key,
|
||||
newkey);
|
||||
key = newkey;
|
||||
log_debug("%s: key 0x%llx is backspace -> 0x%llx", __func__,
|
||||
key, newkey);
|
||||
if ((key & KEYC_MASK_MODIFIERS) == 0) {
|
||||
ud.data[0] = 255;
|
||||
if ((newkey & KEYC_MASK_MODIFIERS) == 0)
|
||||
ud.data[0] = newkey;
|
||||
else if ((newkey & KEYC_MASK_MODIFIERS) == KEYC_CTRL) {
|
||||
newkey &= KEYC_MASK_KEY;
|
||||
if (newkey >= 'A' && newkey <= 'Z')
|
||||
ud.data[0] = newkey - 0x40;
|
||||
else if (newkey >= 'a' && newkey <= 'z')
|
||||
ud.data[0] = newkey - 0x60;
|
||||
}
|
||||
if (ud.data[0] != 255)
|
||||
input_key_write(__func__, bev, &ud.data[0], 1);
|
||||
return (0);
|
||||
}
|
||||
key = newkey|(key & (KEYC_MASK_FLAGS|KEYC_MASK_MODIFIERS));
|
||||
}
|
||||
|
||||
/* Is this backtab? */
|
||||
if ((key & KEYC_MASK_KEY) == KEYC_BTAB) {
|
||||
if ((s->mode & EXTENDED_KEY_MODES) != 0) {
|
||||
if (s->mode & MODE_KEYS_EXTENDED_2) {
|
||||
/* When in xterm extended mode, remap into S-Tab. */
|
||||
key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
|
||||
} else {
|
||||
@@ -612,7 +624,6 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
if (!(key & ~KEYC_MASK_KEY)) {
|
||||
if (key == C0_HT ||
|
||||
key == C0_CR ||
|
||||
key == C0_BS ||
|
||||
key == C0_ESC ||
|
||||
(key >= 0x20 && key <= 0x7f)) {
|
||||
ud.data[0] = key;
|
||||
|
||||
22
mode-tree.c
22
mode-tree.c
@@ -66,6 +66,7 @@ struct mode_tree_data {
|
||||
u_int line_size;
|
||||
|
||||
u_int depth;
|
||||
u_int maxdepth;
|
||||
|
||||
u_int width;
|
||||
u_int height;
|
||||
@@ -196,6 +197,8 @@ mode_tree_build_lines(struct mode_tree_data *mtd,
|
||||
int flat = 1;
|
||||
|
||||
mtd->depth = depth;
|
||||
if (depth > mtd->maxdepth)
|
||||
mtd->maxdepth = depth;
|
||||
TAILQ_FOREACH(mti, mtl, entry) {
|
||||
mtd->line_list = xreallocarray(mtd->line_list,
|
||||
mtd->line_size + 1, sizeof *mtd->line_list);
|
||||
@@ -528,6 +531,7 @@ mode_tree_build(struct mode_tree_data *mtd)
|
||||
TAILQ_INIT(&mtd->saved);
|
||||
|
||||
mode_tree_clear_lines(mtd);
|
||||
mtd->maxdepth = 0;
|
||||
mode_tree_build_lines(mtd, &mtd->children, 0);
|
||||
|
||||
if (mtd->line_list != NULL && tag == UINT64_MAX)
|
||||
@@ -658,7 +662,7 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
char *text, *start, *key;
|
||||
const char *tag, *symbol;
|
||||
size_t size, n;
|
||||
int keylen, pad;
|
||||
int keylen, pad, namelen[mtd->maxdepth + 1];
|
||||
|
||||
if (mtd->line_size == 0)
|
||||
return;
|
||||
@@ -682,6 +686,15 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
keylen = mti->keylen + 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < mtd->maxdepth + 1; i++)
|
||||
namelen[i] = 0;
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
line = &mtd->line_list[i];
|
||||
mti = line->item;
|
||||
if ((int)strlen(mti->name) > namelen[line->depth])
|
||||
namelen[line->depth] = strlen(mti->name);
|
||||
}
|
||||
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
if (i < mtd->offset)
|
||||
continue;
|
||||
@@ -731,8 +744,9 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
tag = "*";
|
||||
else
|
||||
tag = "";
|
||||
xasprintf(&text, "%-*s%s%s%s%s", keylen, key, start, mti->name,
|
||||
tag, (mti->text != NULL) ? ": " : "" );
|
||||
xasprintf(&text, "%-*s%s%*s%s%s", keylen, key, start,
|
||||
namelen[line->depth], mti->name, tag,
|
||||
(mti->text != NULL) ? ": " : "" );
|
||||
width = utf8_cstrwidth(text);
|
||||
if (width > w)
|
||||
width = w;
|
||||
@@ -1297,7 +1311,7 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs,
|
||||
if (status == CMD_PARSE_ERROR) {
|
||||
if (c != NULL) {
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
status_message_set(c, -1, 1, 0, 0, "%s", error);
|
||||
}
|
||||
free(error);
|
||||
}
|
||||
|
||||
@@ -253,6 +253,15 @@ const struct options_table_entry options_table[] = {
|
||||
"Each entry is an alias and a command separated by '='."
|
||||
},
|
||||
|
||||
{ .name = "codepoint-widths",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_ARRAY,
|
||||
.default_str = "",
|
||||
.separator = ",",
|
||||
.text = "Array of override widths for Unicode codepoints."
|
||||
},
|
||||
|
||||
{ .name = "copy-command",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
|
||||
@@ -1185,7 +1185,8 @@ options_push_changes(const char *name)
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
layout_fix_panes(w, NULL);
|
||||
}
|
||||
|
||||
if (strcmp(name, "codepoint-widths") == 0)
|
||||
utf8_update_width_cache();
|
||||
if (strcmp(name, "input-buffer-size") == 0)
|
||||
input_set_buffer_size(options_get_number(global_options, name));
|
||||
RB_FOREACH(s, sessions, &sessions)
|
||||
|
||||
8
popup.c
8
popup.c
@@ -352,9 +352,11 @@ popup_make_pane(struct popup_data *pd, enum layout_type type)
|
||||
new_wp = window_add_pane(wp->window, NULL, hlimit, 0);
|
||||
layout_assign_pane(lc, new_wp, 0);
|
||||
|
||||
new_wp->fd = job_transfer(pd->job, &new_wp->pid, new_wp->tty,
|
||||
sizeof new_wp->tty);
|
||||
pd->job = NULL;
|
||||
if (pd->job != NULL) {
|
||||
new_wp->fd = job_transfer(pd->job, &new_wp->pid, new_wp->tty,
|
||||
sizeof new_wp->tty);
|
||||
pd->job = NULL;
|
||||
}
|
||||
|
||||
screen_set_title(&pd->s, new_wp->base.title);
|
||||
screen_free(&new_wp->base);
|
||||
|
||||
@@ -152,10 +152,12 @@ server_client_clear_overlay(struct client *c)
|
||||
c->overlay_draw = NULL;
|
||||
c->overlay_key = NULL;
|
||||
c->overlay_free = NULL;
|
||||
c->overlay_resize = NULL;
|
||||
c->overlay_data = NULL;
|
||||
|
||||
c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
|
||||
window_update_focus(c->session->curw->window);
|
||||
if (c->session != NULL)
|
||||
window_update_focus(c->session->curw->window);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
|
||||
|
||||
1
server.c
1
server.c
@@ -207,6 +207,7 @@ server_start(struct tmuxproc *client, uint64_t flags, struct event_base *base,
|
||||
fatal("pledge failed");
|
||||
|
||||
input_key_build();
|
||||
utf8_update_width_cache();
|
||||
RB_INIT(&windows);
|
||||
RB_INIT(&all_window_panes);
|
||||
TAILQ_INIT(&clients);
|
||||
|
||||
6
status.c
6
status.c
@@ -470,7 +470,7 @@ status_redraw(struct client *c)
|
||||
/* Set a status line message. */
|
||||
void
|
||||
status_message_set(struct client *c, int delay, int ignore_styles,
|
||||
int ignore_keys, const char *fmt, ...)
|
||||
int ignore_keys, int no_freeze, const char *fmt, ...)
|
||||
{
|
||||
struct timeval tv;
|
||||
va_list ap;
|
||||
@@ -514,7 +514,9 @@ status_message_set(struct client *c, int delay, int ignore_styles,
|
||||
c->message_ignore_keys = ignore_keys;
|
||||
c->message_ignore_styles = ignore_styles;
|
||||
|
||||
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
||||
if (!no_freeze)
|
||||
c->tty.flags |= TTY_FREEZE;
|
||||
c->tty.flags |= TTY_NOCURSOR;
|
||||
c->flags |= CLIENT_REDRAWSTATUS;
|
||||
}
|
||||
|
||||
|
||||
27
tmux.1
27
tmux.1
@@ -2331,6 +2331,15 @@ repeats the last search and
|
||||
does the same but reverses the direction (forward becomes backward and backward
|
||||
becomes forward).
|
||||
.Pp
|
||||
The default incremental search key bindings,
|
||||
.Ql C-r
|
||||
and
|
||||
.Ql C-s ,
|
||||
are designed to emulate
|
||||
.Xr emacs 1 .
|
||||
When first pressed they allow a new search term to be entered; if pressed with
|
||||
an empty search term they repeat the previously used search term.
|
||||
.Pp
|
||||
The
|
||||
.Ql next-prompt
|
||||
and
|
||||
@@ -2547,7 +2556,7 @@ but a different format may be specified with
|
||||
.Fl F .
|
||||
.Tg capturep
|
||||
.It Xo Ic capture-pane
|
||||
.Op Fl aAepPqCJN
|
||||
.Op Fl aepPqCJMN
|
||||
.Op Fl b Ar buffer-name
|
||||
.Op Fl E Ar end-line
|
||||
.Op Fl S Ar start-line
|
||||
@@ -2566,6 +2575,9 @@ is given, the alternate screen is used, and the history is not accessible.
|
||||
If no alternate screen exists, an error will be returned unless
|
||||
.Fl q
|
||||
is given.
|
||||
Similarly, if the pane is in a mode,
|
||||
.Fl M
|
||||
uses the screen for the mode.
|
||||
If
|
||||
.Fl e
|
||||
is given, the output includes escape sequences for text and background
|
||||
@@ -4059,6 +4071,14 @@ Note that aliases are expanded when a command is parsed rather than when it is
|
||||
executed, so binding an alias with
|
||||
.Ic bind-key
|
||||
will bind the expanded form.
|
||||
.It Ic codepoint-widths[] Ar string
|
||||
An array option allowing widths of Unicode codepoints to be overridden.
|
||||
Note the new width applies to all clients.
|
||||
Each entry is of the form
|
||||
.Em codepoint=width ,
|
||||
where codepoint may be a UTF-8 character or an identifier of the form
|
||||
.Ql U+number
|
||||
where the number is a hexadecimal number.
|
||||
.It Ic copy-command Ar shell-command
|
||||
Give the command to pipe to if the
|
||||
.Ic copy-pipe
|
||||
@@ -6736,7 +6756,7 @@ The following keys are available in menus:
|
||||
.El
|
||||
.Tg display
|
||||
.It Xo Ic display-message
|
||||
.Op Fl aIlNpv
|
||||
.Op Fl aCIlNpv
|
||||
.Op Fl c Ar target-client
|
||||
.Op Fl d Ar delay
|
||||
.Op Fl t Ar target-pane
|
||||
@@ -6759,6 +6779,9 @@ option is used; a delay of zero waits for a key press.
|
||||
.Ql N
|
||||
ignores key presses and closes only after the delay expires.
|
||||
If
|
||||
.Fl C
|
||||
is given, the pane will continue to be updated while the message is displayed.
|
||||
If
|
||||
.Fl l
|
||||
is given,
|
||||
.Ar message
|
||||
|
||||
5
tmux.h
5
tmux.h
@@ -1090,6 +1090,7 @@ struct window_mode {
|
||||
struct mouse_event *);
|
||||
void (*formats)(struct window_mode_entry *,
|
||||
struct format_tree *);
|
||||
struct screen *(*get_screen)(struct window_mode_entry *);
|
||||
};
|
||||
|
||||
/* Active window mode. */
|
||||
@@ -2641,6 +2642,7 @@ int cmd_find_from_nothing(struct cmd_find_state *, int);
|
||||
|
||||
/* cmd.c */
|
||||
extern const struct cmd_entry *cmd_table[];
|
||||
const struct cmd_entry *cmd_find(const char *, char **);
|
||||
void printflike(3, 4) cmd_log_argv(int, char **, const char *, ...);
|
||||
void cmd_prepend_argv(int *, char ***, const char *);
|
||||
void cmd_append_argv(int *, char ***, const char *);
|
||||
@@ -2890,7 +2892,7 @@ struct style_range *status_get_range(struct client *, u_int, u_int);
|
||||
void status_init(struct client *);
|
||||
void status_free(struct client *);
|
||||
int status_redraw(struct client *);
|
||||
void printflike(5, 6) status_message_set(struct client *, int, int, int,
|
||||
void printflike(6, 7) status_message_set(struct client *, int, int, int, int,
|
||||
const char *, ...);
|
||||
void status_message_clear(struct client *);
|
||||
int status_message_redraw(struct client *);
|
||||
@@ -3445,6 +3447,7 @@ void session_renumber_windows(struct session *);
|
||||
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);
|
||||
void utf8_update_width_cache(void);
|
||||
utf8_char utf8_build_one(u_char);
|
||||
enum utf8_state utf8_from_data(const struct utf8_data *, utf8_char *);
|
||||
void utf8_to_data(utf8_char, struct utf8_data *);
|
||||
|
||||
21
tty-keys.c
21
tty-keys.c
@@ -885,6 +885,17 @@ first_key:
|
||||
if ((key & KEYC_MASK_KEY) == C0_NUL)
|
||||
key = ' ' | KEYC_CTRL | (key & KEYC_META);
|
||||
|
||||
/*
|
||||
* Check for backspace key using termios VERASE - the terminfo
|
||||
* kbs entry is extremely unreliable, so cannot be safely
|
||||
* used. termios should have a better idea.
|
||||
*/
|
||||
bspace = tty->tio.c_cc[VERASE];
|
||||
if (bspace != _POSIX_VDISABLE && key == bspace) {
|
||||
log_debug("%s: key %#llx is backspace", c->name, key);
|
||||
key = KEYC_BSPACE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up all C0 control codes that don't have a dedicated key into
|
||||
* corresponding Ctrl keys. Convert characters in the A-Z range into
|
||||
@@ -894,7 +905,6 @@ first_key:
|
||||
if (onlykey < 0x20 &&
|
||||
onlykey != C0_HT &&
|
||||
onlykey != C0_CR &&
|
||||
onlykey != C0_BS &&
|
||||
onlykey != C0_ESC) {
|
||||
onlykey |= 0x40;
|
||||
if (onlykey >= 'A' && onlykey <= 'Z')
|
||||
@@ -936,15 +946,6 @@ partial_key:
|
||||
complete_key:
|
||||
log_debug("%s: complete key %.*s %#llx", c->name, (int)size, buf, key);
|
||||
|
||||
/*
|
||||
* Check for backspace key using termios VERASE - the terminfo
|
||||
* kbs entry is extremely unreliable, so cannot be safely
|
||||
* used. termios should have a better idea.
|
||||
*/
|
||||
bspace = tty->tio.c_cc[VERASE];
|
||||
if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace)
|
||||
key = (key & KEYC_MASK_MODIFIERS)|KEYC_BSPACE;
|
||||
|
||||
/* Remove key timer. */
|
||||
if (event_initialized(&tty->key_timer))
|
||||
evtimer_del(&tty->key_timer);
|
||||
|
||||
2
tty.c
2
tty.c
@@ -2880,6 +2880,8 @@ tty_check_fg(struct tty *tty, struct colour_palette *palette,
|
||||
gc->fg &= 7;
|
||||
if (colours >= 16)
|
||||
gc->fg += 90;
|
||||
else if (gc->fg == 0 && gc->bg == 0)
|
||||
gc->fg = 7;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -24,40 +24,6 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static const wchar_t utf8_modifier_table[] = {
|
||||
0x1F1E6,
|
||||
0x1F1E7,
|
||||
0x1F1E8,
|
||||
0x1F1E9,
|
||||
0x1F1EA,
|
||||
0x1F1EB,
|
||||
0x1F1EC,
|
||||
0x1F1ED,
|
||||
0x1F1EE,
|
||||
0x1F1EF,
|
||||
0x1F1F0,
|
||||
0x1F1F1,
|
||||
0x1F1F2,
|
||||
0x1F1F3,
|
||||
0x1F1F4,
|
||||
0x1F1F5,
|
||||
0x1F1F6,
|
||||
0x1F1F7,
|
||||
0x1F1F8,
|
||||
0x1F1F9,
|
||||
0x1F1FA,
|
||||
0x1F1FB,
|
||||
0x1F1FC,
|
||||
0x1F1FD,
|
||||
0x1F1FE,
|
||||
0x1F1FF,
|
||||
0x1F3FB,
|
||||
0x1F3FC,
|
||||
0x1F3FD,
|
||||
0x1F3FE,
|
||||
0x1F3FF
|
||||
};
|
||||
|
||||
/* Has this got a zero width joiner at the end? */
|
||||
int
|
||||
utf8_has_zwj(const struct utf8_data *ud)
|
||||
@@ -93,8 +59,39 @@ utf8_is_modifier(const struct utf8_data *ud)
|
||||
|
||||
if (utf8_towc(ud, &wc) != UTF8_DONE)
|
||||
return (0);
|
||||
if (!utf8_in_table(wc, utf8_modifier_table,
|
||||
nitems(utf8_modifier_table)))
|
||||
return (0);
|
||||
return (1);
|
||||
switch (wc) {
|
||||
case 0x1F1E6:
|
||||
case 0x1F1E7:
|
||||
case 0x1F1E8:
|
||||
case 0x1F1E9:
|
||||
case 0x1F1EA:
|
||||
case 0x1F1EB:
|
||||
case 0x1F1EC:
|
||||
case 0x1F1ED:
|
||||
case 0x1F1EE:
|
||||
case 0x1F1EF:
|
||||
case 0x1F1F0:
|
||||
case 0x1F1F1:
|
||||
case 0x1F1F2:
|
||||
case 0x1F1F3:
|
||||
case 0x1F1F4:
|
||||
case 0x1F1F5:
|
||||
case 0x1F1F6:
|
||||
case 0x1F1F7:
|
||||
case 0x1F1F8:
|
||||
case 0x1F1F9:
|
||||
case 0x1F1FA:
|
||||
case 0x1F1FB:
|
||||
case 0x1F1FC:
|
||||
case 0x1F1FD:
|
||||
case 0x1F1FE:
|
||||
case 0x1F1FF:
|
||||
case 0x1F3FB:
|
||||
case 0x1F3FC:
|
||||
case 0x1F3FD:
|
||||
case 0x1F3FE:
|
||||
case 0x1F3FF:
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
509
utf8.c
509
utf8.c
@@ -27,169 +27,192 @@
|
||||
#include "compat.h"
|
||||
#include "tmux.h"
|
||||
|
||||
static const wchar_t utf8_force_wide[] = {
|
||||
0x0261D,
|
||||
0x026F9,
|
||||
0x0270A,
|
||||
0x0270B,
|
||||
0x0270C,
|
||||
0x0270D,
|
||||
0x1F1E6,
|
||||
0x1F1E7,
|
||||
0x1F1E8,
|
||||
0x1F1E9,
|
||||
0x1F1EA,
|
||||
0x1F1EB,
|
||||
0x1F1EC,
|
||||
0x1F1ED,
|
||||
0x1F1EE,
|
||||
0x1F1EF,
|
||||
0x1F1F0,
|
||||
0x1F1F1,
|
||||
0x1F1F2,
|
||||
0x1F1F3,
|
||||
0x1F1F4,
|
||||
0x1F1F5,
|
||||
0x1F1F6,
|
||||
0x1F1F7,
|
||||
0x1F1F8,
|
||||
0x1F1F9,
|
||||
0x1F1FA,
|
||||
0x1F1FB,
|
||||
0x1F1FC,
|
||||
0x1F1FD,
|
||||
0x1F1FE,
|
||||
0x1F1FF,
|
||||
0x1F385,
|
||||
0x1F3C2,
|
||||
0x1F3C3,
|
||||
0x1F3C4,
|
||||
0x1F3C7,
|
||||
0x1F3CA,
|
||||
0x1F3CB,
|
||||
0x1F3CC,
|
||||
0x1F3FB,
|
||||
0x1F3FC,
|
||||
0x1F3FD,
|
||||
0x1F3FE,
|
||||
0x1F3FF,
|
||||
0x1F442,
|
||||
0x1F443,
|
||||
0x1F446,
|
||||
0x1F447,
|
||||
0x1F448,
|
||||
0x1F449,
|
||||
0x1F44A,
|
||||
0x1F44B,
|
||||
0x1F44C,
|
||||
0x1F44D,
|
||||
0x1F44E,
|
||||
0x1F44F,
|
||||
0x1F450,
|
||||
0x1F466,
|
||||
0x1F467,
|
||||
0x1F468,
|
||||
0x1F469,
|
||||
0x1F46B,
|
||||
0x1F46C,
|
||||
0x1F46D,
|
||||
0x1F46E,
|
||||
0x1F470,
|
||||
0x1F471,
|
||||
0x1F472,
|
||||
0x1F473,
|
||||
0x1F474,
|
||||
0x1F475,
|
||||
0x1F476,
|
||||
0x1F477,
|
||||
0x1F478,
|
||||
0x1F47C,
|
||||
0x1F481,
|
||||
0x1F482,
|
||||
0x1F483,
|
||||
0x1F485,
|
||||
0x1F486,
|
||||
0x1F487,
|
||||
0x1F48F,
|
||||
0x1F491,
|
||||
0x1F4AA,
|
||||
0x1F574,
|
||||
0x1F575,
|
||||
0x1F57A,
|
||||
0x1F590,
|
||||
0x1F595,
|
||||
0x1F596,
|
||||
0x1F645,
|
||||
0x1F646,
|
||||
0x1F647,
|
||||
0x1F64B,
|
||||
0x1F64C,
|
||||
0x1F64D,
|
||||
0x1F64E,
|
||||
0x1F64F,
|
||||
0x1F6A3,
|
||||
0x1F6B4,
|
||||
0x1F6B5,
|
||||
0x1F6B6,
|
||||
0x1F6C0,
|
||||
0x1F6CC,
|
||||
0x1F90C,
|
||||
0x1F90F,
|
||||
0x1F918,
|
||||
0x1F919,
|
||||
0x1F91A,
|
||||
0x1F91B,
|
||||
0x1F91C,
|
||||
0x1F91D,
|
||||
0x1F91E,
|
||||
0x1F91F,
|
||||
0x1F926,
|
||||
0x1F930,
|
||||
0x1F931,
|
||||
0x1F932,
|
||||
0x1F933,
|
||||
0x1F934,
|
||||
0x1F935,
|
||||
0x1F936,
|
||||
0x1F937,
|
||||
0x1F938,
|
||||
0x1F939,
|
||||
0x1F93D,
|
||||
0x1F93E,
|
||||
0x1F977,
|
||||
0x1F9B5,
|
||||
0x1F9B6,
|
||||
0x1F9B8,
|
||||
0x1F9B9,
|
||||
0x1F9BB,
|
||||
0x1F9CD,
|
||||
0x1F9CE,
|
||||
0x1F9CF,
|
||||
0x1F9D1,
|
||||
0x1F9D2,
|
||||
0x1F9D3,
|
||||
0x1F9D4,
|
||||
0x1F9D5,
|
||||
0x1F9D6,
|
||||
0x1F9D7,
|
||||
0x1F9D8,
|
||||
0x1F9D9,
|
||||
0x1F9DA,
|
||||
0x1F9DB,
|
||||
0x1F9DC,
|
||||
0x1F9DD,
|
||||
0x1FAC3,
|
||||
0x1FAC4,
|
||||
0x1FAC5,
|
||||
0x1FAF0,
|
||||
0x1FAF1,
|
||||
0x1FAF2,
|
||||
0x1FAF3,
|
||||
0x1FAF4,
|
||||
0x1FAF5,
|
||||
0x1FAF6,
|
||||
0x1FAF7,
|
||||
0x1FAF8
|
||||
struct utf8_width_item {
|
||||
wchar_t wc;
|
||||
u_int width;
|
||||
int allocated;
|
||||
|
||||
RB_ENTRY(utf8_width_item) entry;
|
||||
};
|
||||
|
||||
static int
|
||||
utf8_width_cache_cmp(struct utf8_width_item *uw1, struct utf8_width_item *uw2)
|
||||
{
|
||||
if (uw1->wc < uw2->wc)
|
||||
return (-1);
|
||||
if (uw1->wc > uw2->wc)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
RB_HEAD(utf8_width_cache, utf8_width_item);
|
||||
RB_GENERATE_STATIC(utf8_width_cache, utf8_width_item, entry,
|
||||
utf8_width_cache_cmp);
|
||||
static struct utf8_width_cache utf8_width_cache =
|
||||
RB_INITIALIZER(utf8_width_cache);
|
||||
|
||||
static struct utf8_width_item utf8_default_width_cache[] = {
|
||||
{ .wc = 0x0261D, .width = 2 },
|
||||
{ .wc = 0x026F9, .width = 2 },
|
||||
{ .wc = 0x0270A, .width = 2 },
|
||||
{ .wc = 0x0270B, .width = 2 },
|
||||
{ .wc = 0x0270C, .width = 2 },
|
||||
{ .wc = 0x0270D, .width = 2 },
|
||||
{ .wc = 0x1F1E6, .width = 2 },
|
||||
{ .wc = 0x1F1E7, .width = 2 },
|
||||
{ .wc = 0x1F1E8, .width = 2 },
|
||||
{ .wc = 0x1F1E9, .width = 2 },
|
||||
{ .wc = 0x1F1EA, .width = 2 },
|
||||
{ .wc = 0x1F1EB, .width = 2 },
|
||||
{ .wc = 0x1F1EC, .width = 2 },
|
||||
{ .wc = 0x1F1ED, .width = 2 },
|
||||
{ .wc = 0x1F1EE, .width = 2 },
|
||||
{ .wc = 0x1F1EF, .width = 2 },
|
||||
{ .wc = 0x1F1F0, .width = 2 },
|
||||
{ .wc = 0x1F1F1, .width = 2 },
|
||||
{ .wc = 0x1F1F2, .width = 2 },
|
||||
{ .wc = 0x1F1F3, .width = 2 },
|
||||
{ .wc = 0x1F1F4, .width = 2 },
|
||||
{ .wc = 0x1F1F5, .width = 2 },
|
||||
{ .wc = 0x1F1F6, .width = 2 },
|
||||
{ .wc = 0x1F1F7, .width = 2 },
|
||||
{ .wc = 0x1F1F8, .width = 2 },
|
||||
{ .wc = 0x1F1F9, .width = 2 },
|
||||
{ .wc = 0x1F1FA, .width = 2 },
|
||||
{ .wc = 0x1F1FB, .width = 2 },
|
||||
{ .wc = 0x1F1FC, .width = 2 },
|
||||
{ .wc = 0x1F1FD, .width = 2 },
|
||||
{ .wc = 0x1F1FE, .width = 2 },
|
||||
{ .wc = 0x1F1FF, .width = 2 },
|
||||
{ .wc = 0x1F385, .width = 2 },
|
||||
{ .wc = 0x1F3C2, .width = 2 },
|
||||
{ .wc = 0x1F3C3, .width = 2 },
|
||||
{ .wc = 0x1F3C4, .width = 2 },
|
||||
{ .wc = 0x1F3C7, .width = 2 },
|
||||
{ .wc = 0x1F3CA, .width = 2 },
|
||||
{ .wc = 0x1F3CB, .width = 2 },
|
||||
{ .wc = 0x1F3CC, .width = 2 },
|
||||
{ .wc = 0x1F3FB, .width = 2 },
|
||||
{ .wc = 0x1F3FC, .width = 2 },
|
||||
{ .wc = 0x1F3FD, .width = 2 },
|
||||
{ .wc = 0x1F3FE, .width = 2 },
|
||||
{ .wc = 0x1F3FF, .width = 2 },
|
||||
{ .wc = 0x1F442, .width = 2 },
|
||||
{ .wc = 0x1F443, .width = 2 },
|
||||
{ .wc = 0x1F446, .width = 2 },
|
||||
{ .wc = 0x1F447, .width = 2 },
|
||||
{ .wc = 0x1F448, .width = 2 },
|
||||
{ .wc = 0x1F449, .width = 2 },
|
||||
{ .wc = 0x1F44A, .width = 2 },
|
||||
{ .wc = 0x1F44B, .width = 2 },
|
||||
{ .wc = 0x1F44C, .width = 2 },
|
||||
{ .wc = 0x1F44D, .width = 2 },
|
||||
{ .wc = 0x1F44E, .width = 2 },
|
||||
{ .wc = 0x1F44F, .width = 2 },
|
||||
{ .wc = 0x1F450, .width = 2 },
|
||||
{ .wc = 0x1F466, .width = 2 },
|
||||
{ .wc = 0x1F467, .width = 2 },
|
||||
{ .wc = 0x1F468, .width = 2 },
|
||||
{ .wc = 0x1F469, .width = 2 },
|
||||
{ .wc = 0x1F46B, .width = 2 },
|
||||
{ .wc = 0x1F46C, .width = 2 },
|
||||
{ .wc = 0x1F46D, .width = 2 },
|
||||
{ .wc = 0x1F46E, .width = 2 },
|
||||
{ .wc = 0x1F470, .width = 2 },
|
||||
{ .wc = 0x1F471, .width = 2 },
|
||||
{ .wc = 0x1F472, .width = 2 },
|
||||
{ .wc = 0x1F473, .width = 2 },
|
||||
{ .wc = 0x1F474, .width = 2 },
|
||||
{ .wc = 0x1F475, .width = 2 },
|
||||
{ .wc = 0x1F476, .width = 2 },
|
||||
{ .wc = 0x1F477, .width = 2 },
|
||||
{ .wc = 0x1F478, .width = 2 },
|
||||
{ .wc = 0x1F47C, .width = 2 },
|
||||
{ .wc = 0x1F481, .width = 2 },
|
||||
{ .wc = 0x1F482, .width = 2 },
|
||||
{ .wc = 0x1F483, .width = 2 },
|
||||
{ .wc = 0x1F485, .width = 2 },
|
||||
{ .wc = 0x1F486, .width = 2 },
|
||||
{ .wc = 0x1F487, .width = 2 },
|
||||
{ .wc = 0x1F48F, .width = 2 },
|
||||
{ .wc = 0x1F491, .width = 2 },
|
||||
{ .wc = 0x1F4AA, .width = 2 },
|
||||
{ .wc = 0x1F574, .width = 2 },
|
||||
{ .wc = 0x1F575, .width = 2 },
|
||||
{ .wc = 0x1F57A, .width = 2 },
|
||||
{ .wc = 0x1F590, .width = 2 },
|
||||
{ .wc = 0x1F595, .width = 2 },
|
||||
{ .wc = 0x1F596, .width = 2 },
|
||||
{ .wc = 0x1F645, .width = 2 },
|
||||
{ .wc = 0x1F646, .width = 2 },
|
||||
{ .wc = 0x1F647, .width = 2 },
|
||||
{ .wc = 0x1F64B, .width = 2 },
|
||||
{ .wc = 0x1F64C, .width = 2 },
|
||||
{ .wc = 0x1F64D, .width = 2 },
|
||||
{ .wc = 0x1F64E, .width = 2 },
|
||||
{ .wc = 0x1F64F, .width = 2 },
|
||||
{ .wc = 0x1F6A3, .width = 2 },
|
||||
{ .wc = 0x1F6B4, .width = 2 },
|
||||
{ .wc = 0x1F6B5, .width = 2 },
|
||||
{ .wc = 0x1F6B6, .width = 2 },
|
||||
{ .wc = 0x1F6C0, .width = 2 },
|
||||
{ .wc = 0x1F6CC, .width = 2 },
|
||||
{ .wc = 0x1F90C, .width = 2 },
|
||||
{ .wc = 0x1F90F, .width = 2 },
|
||||
{ .wc = 0x1F918, .width = 2 },
|
||||
{ .wc = 0x1F919, .width = 2 },
|
||||
{ .wc = 0x1F91A, .width = 2 },
|
||||
{ .wc = 0x1F91B, .width = 2 },
|
||||
{ .wc = 0x1F91C, .width = 2 },
|
||||
{ .wc = 0x1F91D, .width = 2 },
|
||||
{ .wc = 0x1F91E, .width = 2 },
|
||||
{ .wc = 0x1F91F, .width = 2 },
|
||||
{ .wc = 0x1F926, .width = 2 },
|
||||
{ .wc = 0x1F930, .width = 2 },
|
||||
{ .wc = 0x1F931, .width = 2 },
|
||||
{ .wc = 0x1F932, .width = 2 },
|
||||
{ .wc = 0x1F933, .width = 2 },
|
||||
{ .wc = 0x1F934, .width = 2 },
|
||||
{ .wc = 0x1F935, .width = 2 },
|
||||
{ .wc = 0x1F936, .width = 2 },
|
||||
{ .wc = 0x1F937, .width = 2 },
|
||||
{ .wc = 0x1F938, .width = 2 },
|
||||
{ .wc = 0x1F939, .width = 2 },
|
||||
{ .wc = 0x1F93D, .width = 2 },
|
||||
{ .wc = 0x1F93E, .width = 2 },
|
||||
{ .wc = 0x1F977, .width = 2 },
|
||||
{ .wc = 0x1F9B5, .width = 2 },
|
||||
{ .wc = 0x1F9B6, .width = 2 },
|
||||
{ .wc = 0x1F9B8, .width = 2 },
|
||||
{ .wc = 0x1F9B9, .width = 2 },
|
||||
{ .wc = 0x1F9BB, .width = 2 },
|
||||
{ .wc = 0x1F9CD, .width = 2 },
|
||||
{ .wc = 0x1F9CE, .width = 2 },
|
||||
{ .wc = 0x1F9CF, .width = 2 },
|
||||
{ .wc = 0x1F9D1, .width = 2 },
|
||||
{ .wc = 0x1F9D2, .width = 2 },
|
||||
{ .wc = 0x1F9D3, .width = 2 },
|
||||
{ .wc = 0x1F9D4, .width = 2 },
|
||||
{ .wc = 0x1F9D5, .width = 2 },
|
||||
{ .wc = 0x1F9D6, .width = 2 },
|
||||
{ .wc = 0x1F9D7, .width = 2 },
|
||||
{ .wc = 0x1F9D8, .width = 2 },
|
||||
{ .wc = 0x1F9D9, .width = 2 },
|
||||
{ .wc = 0x1F9DA, .width = 2 },
|
||||
{ .wc = 0x1F9DB, .width = 2 },
|
||||
{ .wc = 0x1F9DC, .width = 2 },
|
||||
{ .wc = 0x1F9DD, .width = 2 },
|
||||
{ .wc = 0x1FAC3, .width = 2 },
|
||||
{ .wc = 0x1FAC4, .width = 2 },
|
||||
{ .wc = 0x1FAC5, .width = 2 },
|
||||
{ .wc = 0x1FAF0, .width = 2 },
|
||||
{ .wc = 0x1FAF1, .width = 2 },
|
||||
{ .wc = 0x1FAF2, .width = 2 },
|
||||
{ .wc = 0x1FAF3, .width = 2 },
|
||||
{ .wc = 0x1FAF4, .width = 2 },
|
||||
{ .wc = 0x1FAF5, .width = 2 },
|
||||
{ .wc = 0x1FAF6, .width = 2 },
|
||||
{ .wc = 0x1FAF7, .width = 2 },
|
||||
{ .wc = 0x1FAF8, .width = 2 }
|
||||
};
|
||||
|
||||
struct utf8_item {
|
||||
@@ -227,7 +250,8 @@ RB_HEAD(utf8_index_tree, utf8_item);
|
||||
RB_GENERATE_STATIC(utf8_index_tree, utf8_item, index_entry, utf8_index_cmp);
|
||||
static struct utf8_index_tree utf8_index_tree = RB_INITIALIZER(utf8_index_tree);
|
||||
|
||||
static u_int utf8_next_index;
|
||||
static int utf8_no_width;
|
||||
static u_int utf8_next_index;
|
||||
|
||||
#define UTF8_GET_SIZE(uc) (((uc) >> 24) & 0x1f)
|
||||
#define UTF8_GET_WIDTH(uc) (((uc) >> 29) - 1)
|
||||
@@ -258,6 +282,120 @@ utf8_item_by_index(u_int index)
|
||||
return (RB_FIND(utf8_index_tree, &utf8_index_tree, &ui));
|
||||
}
|
||||
|
||||
/* Find a codepoint in the cache. */
|
||||
static struct utf8_width_item *
|
||||
utf8_find_in_width_cache(wchar_t wc)
|
||||
{
|
||||
struct utf8_width_item uw;
|
||||
|
||||
uw.wc = wc;
|
||||
return RB_FIND(utf8_width_cache, &utf8_width_cache, &uw);
|
||||
}
|
||||
|
||||
/* Parse a single codepoint option. */
|
||||
static void
|
||||
utf8_add_to_width_cache(const char *s)
|
||||
{
|
||||
struct utf8_width_item *uw, *old;
|
||||
char *copy, *cp, *endptr;
|
||||
u_int width;
|
||||
const char *errstr;
|
||||
struct utf8_data *ud;
|
||||
wchar_t wc;
|
||||
unsigned long long n;
|
||||
|
||||
copy = xstrdup(s);
|
||||
if ((cp = strchr(copy, '=')) == NULL) {
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
|
||||
width = strtonum(cp, 0, 2, &errstr);
|
||||
if (errstr != NULL) {
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(copy, "U+", 2) == 0) {
|
||||
errno = 0;
|
||||
n = strtoull(copy + 2, &endptr, 16);
|
||||
if (copy[2] == '\0' ||
|
||||
*endptr != '\0' ||
|
||||
n == 0 ||
|
||||
n > WCHAR_MAX ||
|
||||
(errno == ERANGE && n == ULLONG_MAX)) {
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
wc = n;
|
||||
} else {
|
||||
utf8_no_width = 1;
|
||||
ud = utf8_fromcstr(copy);
|
||||
utf8_no_width = 0;
|
||||
if (ud[0].size == 0 || ud[1].size != 0) {
|
||||
free(ud);
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_UTF8PROC
|
||||
if (utf8proc_mbtowc(&wc, ud[0].data, ud[0].size) <= 0) {
|
||||
#else
|
||||
if (mbtowc(&wc, ud[0].data, ud[0].size) <= 0) {
|
||||
#endif
|
||||
free(ud);
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
free(ud);
|
||||
}
|
||||
|
||||
log_debug("Unicode width cache: %08X=%u", (u_int)wc, width);
|
||||
|
||||
uw = xcalloc(1, sizeof *uw);
|
||||
uw->wc = wc;
|
||||
uw->width = width;
|
||||
uw->allocated = 1;
|
||||
|
||||
old = RB_INSERT(utf8_width_cache, &utf8_width_cache, uw);
|
||||
if (old != NULL) {
|
||||
RB_REMOVE(utf8_width_cache, &utf8_width_cache, old);
|
||||
if (old->allocated)
|
||||
free(old);
|
||||
RB_INSERT(utf8_width_cache, &utf8_width_cache, uw);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
||||
|
||||
/* Rebuild cache of widths. */
|
||||
void
|
||||
utf8_update_width_cache(void)
|
||||
{
|
||||
struct utf8_width_item *uw, *uw1;
|
||||
struct options_entry *o;
|
||||
struct options_array_item *a;
|
||||
u_int i;
|
||||
|
||||
RB_FOREACH_SAFE (uw, utf8_width_cache, &utf8_width_cache, uw1) {
|
||||
RB_REMOVE(utf8_width_cache, &utf8_width_cache, uw);
|
||||
if (uw->allocated)
|
||||
free(uw);
|
||||
}
|
||||
|
||||
for (i = 0; i < nitems(utf8_default_width_cache); i++) {
|
||||
RB_INSERT(utf8_width_cache, &utf8_width_cache,
|
||||
&utf8_default_width_cache[i]);
|
||||
}
|
||||
|
||||
o = options_get(global_options, "codepoint-widths");
|
||||
a = options_array_first(o);
|
||||
while (a != NULL) {
|
||||
utf8_add_to_width_cache(options_array_item_value(a)->string);
|
||||
a = options_array_next(a);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a UTF-8 item. */
|
||||
static int
|
||||
utf8_put_item(const u_char *data, size_t size, u_int *index)
|
||||
@@ -288,28 +426,6 @@ utf8_put_item(const u_char *data, size_t size, u_int *index)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
utf8_table_cmp(const void *vp1, const void *vp2)
|
||||
{
|
||||
const wchar_t *wc1 = vp1, *wc2 = vp2;
|
||||
|
||||
if (*wc1 < *wc2)
|
||||
return (-1);
|
||||
if (*wc1 > *wc2)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Check if character in table. */
|
||||
int
|
||||
utf8_in_table(wchar_t find, const wchar_t *table, u_int count)
|
||||
{
|
||||
wchar_t *found;
|
||||
|
||||
found = bsearch(&find, table, count, sizeof *table, utf8_table_cmp);
|
||||
return (found != NULL);
|
||||
}
|
||||
|
||||
/* Get UTF-8 character from data. */
|
||||
enum utf8_state
|
||||
utf8_from_data(const struct utf8_data *ud, utf8_char *uc)
|
||||
@@ -402,12 +518,15 @@ utf8_copy(struct utf8_data *to, const struct utf8_data *from)
|
||||
static enum utf8_state
|
||||
utf8_width(struct utf8_data *ud, int *width)
|
||||
{
|
||||
wchar_t wc;
|
||||
struct utf8_width_item *uw;
|
||||
wchar_t wc;
|
||||
|
||||
if (utf8_towc(ud, &wc) != UTF8_DONE)
|
||||
return (UTF8_ERROR);
|
||||
if (utf8_in_table(wc, utf8_force_wide, nitems(utf8_force_wide))) {
|
||||
*width = 2;
|
||||
uw = utf8_find_in_width_cache(wc);
|
||||
if (uw != NULL) {
|
||||
*width = uw->width;
|
||||
log_debug("cached width for %08X is %d", (u_int)wc, *width);
|
||||
return (UTF8_DONE);
|
||||
}
|
||||
#ifdef HAVE_UTF8PROC
|
||||
@@ -517,11 +636,13 @@ utf8_append(struct utf8_data *ud, u_char ch)
|
||||
if (ud->have != ud->size)
|
||||
return (UTF8_MORE);
|
||||
|
||||
if (ud->width == 0xff)
|
||||
return (UTF8_ERROR);
|
||||
if (utf8_width(ud, &width) != UTF8_DONE)
|
||||
return (UTF8_ERROR);
|
||||
ud->width = width;
|
||||
if (!utf8_no_width) {
|
||||
if (ud->width == 0xff)
|
||||
return (UTF8_ERROR);
|
||||
if (utf8_width(ud, &width) != UTF8_DONE)
|
||||
return (UTF8_ERROR);
|
||||
ud->width = width;
|
||||
}
|
||||
|
||||
return (UTF8_DONE);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ static void window_copy_free(struct window_mode_entry *);
|
||||
static void window_copy_resize(struct window_mode_entry *, u_int, u_int);
|
||||
static void window_copy_formats(struct window_mode_entry *,
|
||||
struct format_tree *);
|
||||
static struct screen *window_copy_get_screen(struct window_mode_entry *);
|
||||
static void window_copy_scroll1(struct window_mode_entry *,
|
||||
struct window_pane *wp, int, u_int, int);
|
||||
static void window_copy_pageup1(struct window_mode_entry *, int);
|
||||
@@ -160,6 +161,7 @@ const struct window_mode window_copy_mode = {
|
||||
.key_table = window_copy_key_table,
|
||||
.command = window_copy_command,
|
||||
.formats = window_copy_formats,
|
||||
.get_screen = window_copy_get_screen
|
||||
};
|
||||
|
||||
const struct window_mode window_view_mode = {
|
||||
@@ -171,6 +173,7 @@ const struct window_mode window_view_mode = {
|
||||
.key_table = window_copy_key_table,
|
||||
.command = window_copy_command,
|
||||
.formats = window_copy_formats,
|
||||
.get_screen = window_copy_get_screen
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -972,6 +975,14 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
|
||||
window_copy_cursor_hyperlink_cb);
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_copy_get_screen(struct window_mode_entry *wme)
|
||||
{
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
|
||||
return (data->backing);
|
||||
}
|
||||
|
||||
static void
|
||||
window_copy_size_changed(struct window_mode_entry *wme)
|
||||
{
|
||||
|
||||
@@ -1000,7 +1000,7 @@ window_customize_set_option_callback(struct client *c, void *itemdata,
|
||||
|
||||
fail:
|
||||
*cause = toupper((u_char)*cause);
|
||||
status_message_set(c, -1, 1, 0, "%s", cause);
|
||||
status_message_set(c, -1, 1, 0, 0, "%s", cause);
|
||||
free(cause);
|
||||
return (0);
|
||||
}
|
||||
@@ -1203,7 +1203,7 @@ window_customize_set_command_callback(struct client *c, void *itemdata,
|
||||
|
||||
fail:
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
status_message_set(c, -1, 1, 0, 0, "%s", error);
|
||||
free(error);
|
||||
return (0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user