mirror of
https://github.com/tmux/tmux.git
synced 2026-03-07 08:15:36 +00:00
Merge branch 'tmux:master' into feature-floating-window-panes
This commit is contained in:
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
|||||||
.name = "command-prompt",
|
.name = "command-prompt",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
.args = { "1bFkliI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||||
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
.usage = "[-1bFkliN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||||
" [-T prompt-type] [template]",
|
" [-T prompt-type] [template]",
|
||||||
|
|
||||||
.flags = CMD_CLIENT_TFLAG,
|
.flags = CMD_CLIENT_TFLAG,
|
||||||
@@ -117,9 +117,15 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
next_input = inputs = xstrdup(s);
|
next_input = inputs = xstrdup(s);
|
||||||
else
|
else
|
||||||
next_input = NULL;
|
next_input = NULL;
|
||||||
|
if (args_has(args, 'l')) {
|
||||||
|
cdata->prompts = xcalloc(1, sizeof *cdata->prompts);
|
||||||
|
cdata->prompts[0].prompt = prompts;
|
||||||
|
cdata->prompts[0].input = inputs;
|
||||||
|
cdata->count = 1;
|
||||||
|
} else {
|
||||||
while ((prompt = strsep(&next_prompt, ",")) != NULL) {
|
while ((prompt = strsep(&next_prompt, ",")) != NULL) {
|
||||||
cdata->prompts = xreallocarray(cdata->prompts, cdata->count + 1,
|
cdata->prompts = xreallocarray(cdata->prompts,
|
||||||
sizeof *cdata->prompts);
|
cdata->count + 1, sizeof *cdata->prompts);
|
||||||
if (!space)
|
if (!space)
|
||||||
tmp = xstrdup(prompt);
|
tmp = xstrdup(prompt);
|
||||||
else
|
else
|
||||||
@@ -133,11 +139,11 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
} else
|
} else
|
||||||
input = "";
|
input = "";
|
||||||
cdata->prompts[cdata->count].input = xstrdup(input);
|
cdata->prompts[cdata->count].input = xstrdup(input);
|
||||||
|
|
||||||
cdata->count++;
|
cdata->count++;
|
||||||
}
|
}
|
||||||
free(inputs);
|
free(inputs);
|
||||||
free(prompts);
|
free(prompts);
|
||||||
|
}
|
||||||
|
|
||||||
if ((type = args_get(args, 'T')) != NULL) {
|
if ((type = args_get(args, 'T')) != NULL) {
|
||||||
cdata->prompt_type = status_prompt_type(type);
|
cdata->prompt_type = status_prompt_type(type);
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ const struct cmd_entry cmd_display_popup_entry = {
|
|||||||
.name = "display-popup",
|
.name = "display-popup",
|
||||||
.alias = "popup",
|
.alias = "popup",
|
||||||
|
|
||||||
.args = { "Bb:Cc:d:e:Eh:ks:S:t:T:w:x:y:", 0, -1, NULL },
|
.args = { "Bb:Cc:d:e:Eh:kNs:S:t:T:w:x:y:", 0, -1, NULL },
|
||||||
.usage = "[-BCEk] [-b border-lines] [-c target-client] "
|
.usage = "[-BCEkN] [-b border-lines] [-c target-client] "
|
||||||
"[-d start-directory] [-e environment] [-h height] "
|
"[-d start-directory] [-e environment] [-h height] "
|
||||||
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
|
"[-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] "
|
||||||
@@ -92,7 +92,7 @@ cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
|
cmd_display_menu_get_pos(struct client *tc, struct cmdq_item *item,
|
||||||
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
||||||
{
|
{
|
||||||
struct tty *tty = &tc->tty;
|
struct tty *tty = &tc->tty;
|
||||||
@@ -353,8 +353,8 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
if (!cmd_display_menu_get_position(tc, item, args, &px, &py,
|
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, menu->width + 4,
|
||||||
menu->width + 4, menu->count + 2)) {
|
menu->count + 2)) {
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
@@ -392,8 +392,10 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
const char *value, *shell, *shellcmd = NULL;
|
const char *value, *shell, *shellcmd = NULL;
|
||||||
const char *style = args_get(args, 's');
|
const char *style = args_get(args, 's');
|
||||||
const char *border_style = args_get(args, 'S');
|
const char *border_style = args_get(args, 'S');
|
||||||
char *cwd, *cause = NULL, **argv = NULL, *title;
|
char *cwd = NULL, *cause = NULL, **argv = NULL;
|
||||||
int flags = 0, argc = 0;
|
char *title;
|
||||||
|
int modify = popup_present(tc);
|
||||||
|
int flags = -1, argc = 0;
|
||||||
enum box_lines lines = BOX_LINES_DEFAULT;
|
enum box_lines lines = BOX_LINES_DEFAULT;
|
||||||
u_int px, py, w, h, count = args_count(args);
|
u_int px, py, w, h, count = args_count(args);
|
||||||
struct args_value *av;
|
struct args_value *av;
|
||||||
@@ -405,12 +407,14 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_client_clear_overlay(tc);
|
server_client_clear_overlay(tc);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
if (tc->overlay_draw != NULL)
|
if (!modify && tc->overlay_draw != NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
if (!modify) {
|
||||||
h = tty->sy / 2;
|
h = tty->sy / 2;
|
||||||
if (args_has(args, 'h')) {
|
if (args_has(args, 'h')) {
|
||||||
h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause);
|
h = args_percentage(args, 'h', 1, tty->sy, tty->sy,
|
||||||
|
&cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "height %s", cause);
|
cmdq_error(item, "height %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
@@ -420,7 +424,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
w = tty->sx / 2;
|
w = tty->sx / 2;
|
||||||
if (args_has(args, 'w')) {
|
if (args_has(args, 'w')) {
|
||||||
w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause);
|
w = args_percentage(args, 'w', 1, tty->sx, tty->sx,
|
||||||
|
&cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "width %s", cause);
|
cmdq_error(item, "width %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
@@ -432,31 +437,18 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
w = tty->sx;
|
w = tty->sx;
|
||||||
if (h > tty->sy)
|
if (h > tty->sy)
|
||||||
h = tty->sy;
|
h = tty->sy;
|
||||||
if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
|
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, w, h))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
value = args_get(args, 'b');
|
|
||||||
if (args_has(args, 'B'))
|
|
||||||
lines = BOX_LINES_NONE;
|
|
||||||
else if (value != NULL) {
|
|
||||||
oe = options_get(o, "popup-border-lines");
|
|
||||||
lines = options_find_choice(options_table_entry(oe), value,
|
|
||||||
&cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "popup-border-lines %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = args_get(args, 'd');
|
value = args_get(args, 'd');
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
cwd = format_single_from_target(item, value);
|
cwd = format_single_from_target(item, value);
|
||||||
else
|
else
|
||||||
cwd = xstrdup(server_client_get_cwd(tc, s));
|
cwd = xstrdup(server_client_get_cwd(tc, s));
|
||||||
if (count == 0)
|
if (count == 0) {
|
||||||
shellcmd = options_get_string(s->options, "default-command");
|
shellcmd = options_get_string(s->options,
|
||||||
else if (count == 1)
|
"default-command");
|
||||||
|
} else if (count == 1)
|
||||||
shellcmd = args_string(args, 0);
|
shellcmd = args_string(args, 0);
|
||||||
if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) {
|
if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) {
|
||||||
shellcmd = NULL;
|
shellcmd = NULL;
|
||||||
@@ -475,17 +467,49 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
av = args_next_value(av);
|
av = args_next_value(av);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = args_get(args, 'b');
|
||||||
|
if (args_has(args, 'B'))
|
||||||
|
lines = BOX_LINES_NONE;
|
||||||
|
else if (value != NULL) {
|
||||||
|
oe = options_get(o, "popup-border-lines");
|
||||||
|
lines = options_find_choice(options_table_entry(oe), value,
|
||||||
|
&cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "popup-border-lines %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args_has(args, 'T'))
|
if (args_has(args, 'T'))
|
||||||
title = format_single_from_target(item, args_get(args, 'T'));
|
title = format_single_from_target(item, args_get(args, 'T'));
|
||||||
else
|
else
|
||||||
title = xstrdup("");
|
title = xstrdup("");
|
||||||
if (args_has(args, 'E') > 1)
|
|
||||||
|
if (args_has(args, 'N') || !modify)
|
||||||
|
flags = 0;
|
||||||
|
if (args_has(args, 'E') > 1) {
|
||||||
|
if (flags == -1)
|
||||||
|
flags = 0;
|
||||||
flags |= POPUP_CLOSEEXITZERO;
|
flags |= POPUP_CLOSEEXITZERO;
|
||||||
else if (args_has(args, 'E'))
|
} else if (args_has(args, 'E')) {
|
||||||
|
if (flags == -1)
|
||||||
|
flags = 0;
|
||||||
flags |= POPUP_CLOSEEXIT;
|
flags |= POPUP_CLOSEEXIT;
|
||||||
if (args_has(args, 'k'))
|
}
|
||||||
|
if (args_has(args, 'k')) {
|
||||||
|
if (flags == -1)
|
||||||
|
flags = 0;
|
||||||
flags |= POPUP_CLOSEANYKEY;
|
flags |= POPUP_CLOSEANYKEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modify) {
|
||||||
|
popup_modify(tc, title, style, border_style, lines, flags);
|
||||||
|
free(title);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
|
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
|
||||||
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
|
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
|
||||||
cmd_free_argv(argc, argv);
|
cmd_free_argv(argc, argv);
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
cmdq_error(item, "%s: %s", path, strerror(error));
|
cmdq_error(item, "%s: %s", strerror(error), path);
|
||||||
else if (bsize != 0) {
|
else if (bsize != 0) {
|
||||||
copy = xmalloc(bsize);
|
copy = xmalloc(bsize);
|
||||||
memcpy(copy, bdata, bsize);
|
memcpy(copy, bdata, bsize);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ cmd_save_buffer_done(__unused struct client *c, const char *path, int error,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
cmdq_error(item, "%s: %s", path, strerror(error));
|
cmdq_error(item, "%s: %s", strerror(error), path);
|
||||||
cmdq_continue(item);
|
cmdq_continue(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
cmdq_error(item, "%s: %s", path, strerror(error));
|
cmdq_error(item, "%s: %s", strerror(error), path);
|
||||||
else if (bsize != 0) {
|
else if (bsize != 0) {
|
||||||
if (load_cfg_from_buffer(bdata, bsize, path, c, cdata->after,
|
if (load_cfg_from_buffer(bdata, bsize, path, c, cdata->after,
|
||||||
target, cdata->flags, &new_item) < 0)
|
target, cdata->flags, &new_item) < 0)
|
||||||
@@ -135,16 +135,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
|
|||||||
static void
|
static void
|
||||||
cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
|
cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
|
||||||
{
|
{
|
||||||
char resolved[PATH_MAX];
|
|
||||||
|
|
||||||
if (realpath(path, resolved) == NULL) {
|
|
||||||
log_debug("%s: realpath(\"%s\") failed: %s", __func__,
|
|
||||||
path, strerror(errno));
|
|
||||||
} else
|
|
||||||
path = resolved;
|
|
||||||
|
|
||||||
log_debug("%s: %s", __func__, path);
|
log_debug("%s: %s", __func__, path);
|
||||||
|
|
||||||
cdata->files = xreallocarray(cdata->files, cdata->nfiles + 1,
|
cdata->files = xreallocarray(cdata->files, cdata->nfiles + 1,
|
||||||
sizeof *cdata->files);
|
sizeof *cdata->files);
|
||||||
cdata->files[cdata->nfiles++] = xstrdup(path);
|
cdata->files[cdata->nfiles++] = xstrdup(path);
|
||||||
@@ -233,7 +224,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
error = strerror(ENOMEM);
|
error = strerror(ENOMEM);
|
||||||
else
|
else
|
||||||
error = strerror(EINVAL);
|
error = strerror(EINVAL);
|
||||||
cmdq_error(item, "%s: %s", path, error);
|
cmdq_error(item, "%s: %s", error, path);
|
||||||
retval = CMD_RETURN_ERROR;
|
retval = CMD_RETURN_ERROR;
|
||||||
}
|
}
|
||||||
globfree(&g);
|
globfree(&g);
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
wl_src->window = w_dst;
|
wl_src->window = w_dst;
|
||||||
TAILQ_INSERT_TAIL(&w_dst->winlinks, wl_src, wentry);
|
TAILQ_INSERT_TAIL(&w_dst->winlinks, wl_src, wentry);
|
||||||
|
|
||||||
|
if (marked_pane.wl == wl_src)
|
||||||
|
marked_pane.wl = wl_dst;
|
||||||
if (args_has(args, 'd')) {
|
if (args_has(args, 'd')) {
|
||||||
session_select(dst, wl_dst->idx);
|
session_select(dst, wl_dst->idx);
|
||||||
if (src != dst)
|
if (src != dst)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ utf8proc_mbtowc(wchar_t *pwc, const char *s, size_t n)
|
|||||||
* *pwc == -1 indicates invalid codepoint
|
* *pwc == -1 indicates invalid codepoint
|
||||||
* slen < 0 indicates an error
|
* slen < 0 indicates an error
|
||||||
*/
|
*/
|
||||||
slen = utf8proc_iterate(s, n, pwc);
|
slen = utf8proc_iterate(s, n, (utf8proc_int32_t*)pwc);
|
||||||
if (*pwc == (wchar_t)-1 || slen < 0)
|
if (*pwc == (wchar_t)-1 || slen < 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
return (slen);
|
return (slen);
|
||||||
|
|||||||
@@ -262,6 +262,12 @@ environ_for_session(struct session *s, int no_TERM)
|
|||||||
environ_set(env, "TERM", 0, "%s", value);
|
environ_set(env, "TERM", 0, "%s", value);
|
||||||
environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
|
environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
|
||||||
environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
|
environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
|
||||||
|
environ_set(env, "COLORTERM", 0, "truecolor");
|
||||||
|
} else {
|
||||||
|
environ_unset(env, "TERM");
|
||||||
|
environ_unset(env, "TERM_PROGRAM");
|
||||||
|
environ_unset(env, "TERM_PROGRAM_VERSION");
|
||||||
|
environ_unset(env, "COLORTERM");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
|
|||||||
16
file.c
16
file.c
@@ -41,13 +41,21 @@ RB_GENERATE(client_files, client_file, entry, file_cmp);
|
|||||||
static char *
|
static char *
|
||||||
file_get_path(struct client *c, const char *file)
|
file_get_path(struct client *c, const char *file)
|
||||||
{
|
{
|
||||||
char *path;
|
const char *home;
|
||||||
|
char *path, *full_path;
|
||||||
|
|
||||||
if (*file == '/')
|
if (strncmp(file, "~/", 2) != 0)
|
||||||
path = xstrdup(file);
|
path = xstrdup(file);
|
||||||
else
|
else {
|
||||||
xasprintf(&path, "%s/%s", server_client_get_cwd(c, NULL), file);
|
home = find_home();
|
||||||
|
if (home == NULL)
|
||||||
|
home = "";
|
||||||
|
xasprintf(&path, "%s%s", home, file + 1);
|
||||||
|
}
|
||||||
|
if (*path == '/')
|
||||||
return (path);
|
return (path);
|
||||||
|
xasprintf(&full_path, "%s/%s", server_client_get_cwd(c, NULL), path);
|
||||||
|
return (full_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tree comparison function. */
|
/* Tree comparison function. */
|
||||||
|
|||||||
2
grid.c
2
grid.c
@@ -1304,7 +1304,7 @@ grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
|
|||||||
if (!wrapped || want != from->cellused || width == sx)
|
if (!wrapped || want != from->cellused || width == sx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (lines == 0)
|
if (lines == 0 || from == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ sixel_scale(struct sixel_image *si, u_int xpixel, u_int ypixel, u_int ox,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colours) {
|
if (colours && si->ncolours != 0) {
|
||||||
new->colours = xmalloc(si->ncolours * sizeof *new->colours);
|
new->colours = xmalloc(si->ncolours * sizeof *new->colours);
|
||||||
for (i = 0; i < si->ncolours; i++)
|
for (i = 0; i < si->ncolours; i++)
|
||||||
new->colours[i] = si->colours[i];
|
new->colours[i] = si->colours[i];
|
||||||
|
|||||||
@@ -605,7 +605,9 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
|||||||
ud.data[0] = newkey;
|
ud.data[0] = newkey;
|
||||||
else if ((newkey & KEYC_MASK_MODIFIERS) == KEYC_CTRL) {
|
else if ((newkey & KEYC_MASK_MODIFIERS) == KEYC_CTRL) {
|
||||||
newkey &= KEYC_MASK_KEY;
|
newkey &= KEYC_MASK_KEY;
|
||||||
if (newkey >= 'A' && newkey <= 'Z')
|
if (newkey == '?')
|
||||||
|
ud.data[0] = 0x7f;
|
||||||
|
else if (newkey >= '@' && newkey <= '_')
|
||||||
ud.data[0] = newkey - 0x40;
|
ud.data[0] = newkey - 0x40;
|
||||||
else if (newkey >= 'a' && newkey <= 'z')
|
else if (newkey >= 'a' && newkey <= 'z')
|
||||||
ud.data[0] = newkey - 0x60;
|
ud.data[0] = newkey - 0x60;
|
||||||
|
|||||||
325
input.c
325
input.c
@@ -51,6 +51,21 @@
|
|||||||
* be passed to the underlying terminals.
|
* be passed to the underlying terminals.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Request sent by a pane. */
|
||||||
|
struct input_request {
|
||||||
|
struct client *c;
|
||||||
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
|
enum input_request_type type;
|
||||||
|
int idx;
|
||||||
|
time_t t;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(input_request) entry;
|
||||||
|
TAILQ_ENTRY(input_request) centry;
|
||||||
|
};
|
||||||
|
#define INPUT_REQUEST_TIMEOUT 2
|
||||||
|
|
||||||
/* Input parser cell. */
|
/* Input parser cell. */
|
||||||
struct input_cell {
|
struct input_cell {
|
||||||
struct grid_cell cell;
|
struct grid_cell cell;
|
||||||
@@ -72,6 +87,12 @@ struct input_param {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Type of terminator. */
|
||||||
|
enum input_end_type {
|
||||||
|
INPUT_END_ST,
|
||||||
|
INPUT_END_BEL
|
||||||
|
};
|
||||||
|
|
||||||
/* Input parser context. */
|
/* Input parser context. */
|
||||||
struct input_ctx {
|
struct input_ctx {
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
@@ -80,7 +101,6 @@ struct input_ctx {
|
|||||||
struct colour_palette *palette;
|
struct colour_palette *palette;
|
||||||
|
|
||||||
struct input_cell cell;
|
struct input_cell cell;
|
||||||
|
|
||||||
struct input_cell old_cell;
|
struct input_cell old_cell;
|
||||||
u_int old_cx;
|
u_int old_cx;
|
||||||
u_int old_cy;
|
u_int old_cy;
|
||||||
@@ -96,10 +116,7 @@ struct input_ctx {
|
|||||||
u_char *input_buf;
|
u_char *input_buf;
|
||||||
size_t input_len;
|
size_t input_len;
|
||||||
size_t input_space;
|
size_t input_space;
|
||||||
enum {
|
enum input_end_type input_end;
|
||||||
INPUT_END_ST,
|
|
||||||
INPUT_END_BEL
|
|
||||||
} input_end;
|
|
||||||
|
|
||||||
struct input_param param_list[24];
|
struct input_param param_list[24];
|
||||||
u_int param_list_len;
|
u_int param_list_len;
|
||||||
@@ -110,26 +127,34 @@ struct input_ctx {
|
|||||||
int ch;
|
int ch;
|
||||||
struct utf8_data last;
|
struct utf8_data last;
|
||||||
|
|
||||||
|
const struct input_state *state;
|
||||||
int flags;
|
int flags;
|
||||||
#define INPUT_DISCARD 0x1
|
#define INPUT_DISCARD 0x1
|
||||||
#define INPUT_LAST 0x2
|
#define INPUT_LAST 0x2
|
||||||
|
|
||||||
const struct input_state *state;
|
struct input_requests requests;
|
||||||
|
u_int request_count;
|
||||||
struct event timer;
|
struct event request_timer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All input received since we were last in the ground state. Sent to
|
* All input received since we were last in the ground state. Sent to
|
||||||
* control clients on connection.
|
* control clients on connection.
|
||||||
*/
|
*/
|
||||||
struct evbuffer *since_ground;
|
struct evbuffer *since_ground;
|
||||||
|
struct event ground_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Helper functions. */
|
/* Helper functions. */
|
||||||
struct input_transition;
|
struct input_transition;
|
||||||
|
static void input_request_timer_callback(int, short, void *);
|
||||||
|
static void input_start_request_timer(struct input_ctx *);
|
||||||
|
static struct input_request *input_make_request(struct input_ctx *,
|
||||||
|
enum input_request_type);
|
||||||
|
static void input_free_request(struct input_request *);
|
||||||
|
static int input_add_request(struct input_ctx *, enum input_request_type,
|
||||||
|
int);
|
||||||
static int input_split(struct input_ctx *);
|
static int input_split(struct input_ctx *);
|
||||||
static int input_get(struct input_ctx *, u_int, int, int);
|
static int input_get(struct input_ctx *, u_int, int, int);
|
||||||
static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
|
|
||||||
static void input_set_state(struct input_ctx *,
|
static void input_set_state(struct input_ctx *,
|
||||||
const struct input_transition *);
|
const struct input_transition *);
|
||||||
static void input_reset_cell(struct input_ctx *);
|
static void input_reset_cell(struct input_ctx *);
|
||||||
@@ -766,7 +791,7 @@ input_stop_utf8(struct input_ctx *ictx)
|
|||||||
* long, so reset to ground.
|
* long, so reset to ground.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
input_timer_callback(__unused int fd, __unused short events, void *arg)
|
input_ground_timer_callback(__unused int fd, __unused short events, void *arg)
|
||||||
{
|
{
|
||||||
struct input_ctx *ictx = arg;
|
struct input_ctx *ictx = arg;
|
||||||
|
|
||||||
@@ -776,12 +801,12 @@ input_timer_callback(__unused int fd, __unused short events, void *arg)
|
|||||||
|
|
||||||
/* Start the timer. */
|
/* Start the timer. */
|
||||||
static void
|
static void
|
||||||
input_start_timer(struct input_ctx *ictx)
|
input_start_ground_timer(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
|
struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
|
||||||
|
|
||||||
event_del(&ictx->timer);
|
event_del(&ictx->ground_timer);
|
||||||
event_add(&ictx->timer, &tv);
|
event_add(&ictx->ground_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset cell state to default. */
|
/* Reset cell state to default. */
|
||||||
@@ -842,8 +867,10 @@ input_init(struct window_pane *wp, struct bufferevent *bev,
|
|||||||
ictx->since_ground = evbuffer_new();
|
ictx->since_ground = evbuffer_new();
|
||||||
if (ictx->since_ground == NULL)
|
if (ictx->since_ground == NULL)
|
||||||
fatalx("out of memory");
|
fatalx("out of memory");
|
||||||
|
evtimer_set(&ictx->ground_timer, input_ground_timer_callback, ictx);
|
||||||
|
|
||||||
evtimer_set(&ictx->timer, input_timer_callback, ictx);
|
TAILQ_INIT(&ictx->requests);
|
||||||
|
evtimer_set(&ictx->request_timer, input_request_timer_callback, ictx);
|
||||||
|
|
||||||
input_reset(ictx, 0);
|
input_reset(ictx, 0);
|
||||||
return (ictx);
|
return (ictx);
|
||||||
@@ -853,6 +880,7 @@ input_init(struct window_pane *wp, struct bufferevent *bev,
|
|||||||
void
|
void
|
||||||
input_free(struct input_ctx *ictx)
|
input_free(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ictx->param_list_len; i++) {
|
for (i = 0; i < ictx->param_list_len; i++) {
|
||||||
@@ -860,10 +888,13 @@ input_free(struct input_ctx *ictx)
|
|||||||
free(ictx->param_list[i].str);
|
free(ictx->param_list[i].str);
|
||||||
}
|
}
|
||||||
|
|
||||||
event_del(&ictx->timer);
|
TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1)
|
||||||
|
input_free_request(ir);
|
||||||
|
event_del(&ictx->request_timer);
|
||||||
|
|
||||||
free(ictx->input_buf);
|
free(ictx->input_buf);
|
||||||
evbuffer_free(ictx->since_ground);
|
evbuffer_free(ictx->since_ground);
|
||||||
|
event_del(&ictx->ground_timer);
|
||||||
|
|
||||||
free(ictx);
|
free(ictx);
|
||||||
}
|
}
|
||||||
@@ -1098,31 +1129,44 @@ input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
|
|||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reply to terminal query. */
|
/* Send reply. */
|
||||||
static void
|
static void
|
||||||
input_reply(struct input_ctx *ictx, const char *fmt, ...)
|
input_send_reply(struct input_ctx *ictx, const char *reply)
|
||||||
{
|
{
|
||||||
struct bufferevent *bev = ictx->event;
|
struct bufferevent *bev = ictx->event;
|
||||||
|
|
||||||
|
if (bev != NULL) {
|
||||||
|
log_debug("%s: %s", __func__, reply);
|
||||||
|
bufferevent_write(bev, reply, strlen(reply));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reply to terminal query. */
|
||||||
|
static void printflike(3, 4)
|
||||||
|
input_reply(struct input_ctx *ictx, int add, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct input_request *ir;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *reply;
|
char *reply;
|
||||||
|
|
||||||
if (bev == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&reply, fmt, ap);
|
xvasprintf(&reply, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
log_debug("%s: %s", __func__, reply);
|
if (add && !TAILQ_EMPTY(&ictx->requests)) {
|
||||||
bufferevent_write(bev, reply, strlen(reply));
|
ir = input_make_request(ictx, INPUT_REQUEST_QUEUE);
|
||||||
|
ir->data = reply;
|
||||||
|
} else {
|
||||||
|
input_send_reply(ictx, reply);
|
||||||
free(reply);
|
free(reply);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear saved state. */
|
/* Clear saved state. */
|
||||||
static void
|
static void
|
||||||
input_clear(struct input_ctx *ictx)
|
input_clear(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
event_del(&ictx->timer);
|
event_del(&ictx->ground_timer);
|
||||||
|
|
||||||
*ictx->interm_buf = '\0';
|
*ictx->interm_buf = '\0';
|
||||||
ictx->interm_len = 0;
|
ictx->interm_len = 0;
|
||||||
@@ -1142,7 +1186,7 @@ input_clear(struct input_ctx *ictx)
|
|||||||
static void
|
static void
|
||||||
input_ground(struct input_ctx *ictx)
|
input_ground(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
event_del(&ictx->timer);
|
event_del(&ictx->ground_timer);
|
||||||
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
|
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
|
||||||
|
|
||||||
if (ictx->input_space > INPUT_BUF_START) {
|
if (ictx->input_space > INPUT_BUF_START) {
|
||||||
@@ -1509,9 +1553,9 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
input_reply(ictx, "\033[?1;2;4c");
|
input_reply(ictx, 1, "\033[?1;2;4c");
|
||||||
#else
|
#else
|
||||||
input_reply(ictx, "\033[?1;2c");
|
input_reply(ictx, 1, "\033[?1;2c");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1524,7 +1568,7 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
case -1:
|
case -1:
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
input_reply(ictx, "\033[>84;0;0c");
|
input_reply(ictx, 1, "\033[>84;0;0c");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||||
@@ -1575,22 +1619,22 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
/* blink for 1,3,5; steady for 0,2,4,6 */
|
/* blink for 1,3,5; steady for 0,2,4,6 */
|
||||||
n = (p == 1 || p == 3 || p == 5) ? 1 : 2;
|
n = (p == 1 || p == 3 || p == 5) ? 1 : 2;
|
||||||
}
|
}
|
||||||
input_reply(ictx, "\033[?12;%d$y", n);
|
input_reply(ictx, 1, "\033[?12;%d$y", n);
|
||||||
break;
|
break;
|
||||||
case 2004: /* bracketed paste */
|
case 2004: /* bracketed paste */
|
||||||
n = (s->mode & MODE_BRACKETPASTE) ? 1 : 2;
|
n = (s->mode & MODE_BRACKETPASTE) ? 1 : 2;
|
||||||
input_reply(ictx, "\033[?2004;%d$y", n);
|
input_reply(ictx, 1, "\033[?2004;%d$y", n);
|
||||||
break;
|
break;
|
||||||
case 1004: /* focus reporting */
|
case 1004: /* focus reporting */
|
||||||
n = (s->mode & MODE_FOCUSON) ? 1 : 2;
|
n = (s->mode & MODE_FOCUSON) ? 1 : 2;
|
||||||
input_reply(ictx, "\033[?1004;%d$y", n);
|
input_reply(ictx, 1, "\033[?1004;%d$y", n);
|
||||||
break;
|
break;
|
||||||
case 1006: /* SGR mouse */
|
case 1006: /* SGR mouse */
|
||||||
n = (s->mode & MODE_MOUSE_SGR) ? 1 : 2;
|
n = (s->mode & MODE_MOUSE_SGR) ? 1 : 2;
|
||||||
input_reply(ictx, "\033[?1006;%d$y", n);
|
input_reply(ictx, 1, "\033[?1006;%d$y", n);
|
||||||
break;
|
break;
|
||||||
case 2031:
|
case 2031:
|
||||||
input_reply(ictx, "\033[?2031;2$y");
|
input_reply(ictx, 1, "\033[?2031;2$y");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1599,10 +1643,11 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
case -1:
|
case -1:
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
input_reply(ictx, "\033[0n");
|
input_reply(ictx, 1, "\033[0n");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
|
input_reply(ictx, 1, "\033[%u;%uR", s->cy + 1,
|
||||||
|
s->cx + 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||||
@@ -1757,8 +1802,10 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
break;
|
break;
|
||||||
case INPUT_CSI_XDA:
|
case INPUT_CSI_XDA:
|
||||||
n = input_get(ictx, 0, 0, 0);
|
n = input_get(ictx, 0, 0, 0);
|
||||||
if (n == 0)
|
if (n == 0) {
|
||||||
input_reply(ictx, "\033P>|tmux %s\033\\", getversion());
|
input_reply(ictx, 1, "\033P>|tmux %s\033\\",
|
||||||
|
getversion());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1970,10 +2017,11 @@ input_csi_dispatch_sm_graphics(__unused struct input_ctx *ictx)
|
|||||||
m = input_get(ictx, 1, 0, 0);
|
m = input_get(ictx, 1, 0, 0);
|
||||||
o = input_get(ictx, 2, 0, 0);
|
o = input_get(ictx, 2, 0, 0);
|
||||||
|
|
||||||
if (n == 1 && (m == 1 || m == 2 || m == 4))
|
if (n == 1 && (m == 1 || m == 2 || m == 4)) {
|
||||||
input_reply(ictx, "\033[?%d;0;%uS", n, SIXEL_COLOUR_REGISTERS);
|
input_reply(ictx, 1, "\033[?%d;0;%uS", n,
|
||||||
else
|
SIXEL_COLOUR_REGISTERS);
|
||||||
input_reply(ictx, "\033[?%d;3;%dS", n, o);
|
} else
|
||||||
|
input_reply(ictx, 1, "\033[?%d;3;%dS", n, o);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2021,26 +2069,26 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
|
|||||||
case 14:
|
case 14:
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
break;
|
break;
|
||||||
input_reply(ictx, "\033[4;%u;%ut", y * w->ypixel,
|
input_reply(ictx, 1, "\033[4;%u;%ut", y * w->ypixel,
|
||||||
x * w->xpixel);
|
x * w->xpixel);
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
break;
|
break;
|
||||||
input_reply(ictx, "\033[5;%u;%ut", y * w->ypixel,
|
input_reply(ictx, 1, "\033[5;%u;%ut", y * w->ypixel,
|
||||||
x * w->xpixel);
|
x * w->xpixel);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
break;
|
break;
|
||||||
input_reply(ictx, "\033[6;%u;%ut", w->ypixel,
|
input_reply(ictx, 1, "\033[6;%u;%ut", w->ypixel,
|
||||||
w->xpixel);
|
w->xpixel);
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
input_reply(ictx, "\033[8;%u;%ut", y, x);
|
input_reply(ictx, 1, "\033[8;%u;%ut", y, x);
|
||||||
break;
|
break;
|
||||||
case 19:
|
case 19:
|
||||||
input_reply(ictx, "\033[9;%u;%ut", y, x);
|
input_reply(ictx, 1, "\033[9;%u;%ut", y, x);
|
||||||
break;
|
break;
|
||||||
case 22:
|
case 22:
|
||||||
m++;
|
m++;
|
||||||
@@ -2403,7 +2451,7 @@ input_enter_dcs(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2464,12 +2512,12 @@ input_handle_decrqss(struct input_ctx *ictx)
|
|||||||
log_debug("%s: DECRQSS cursor -> Ps=%d (cstyle=%d mode=%#x)", __func__,
|
log_debug("%s: DECRQSS cursor -> Ps=%d (cstyle=%d mode=%#x)", __func__,
|
||||||
ps, s->cstyle, s->mode);
|
ps, s->cstyle, s->mode);
|
||||||
|
|
||||||
input_reply(ictx, "\033P1$r q%d q\033\\", ps);
|
input_reply(ictx, 1, "\033P1$r q%d q\033\\", ps);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
not_recognized:
|
not_recognized:
|
||||||
/* Unrecognized DECRQSS: send DCS 0 $ r Pt ST. */
|
/* Unrecognized DECRQSS: send DCS 0 $ r Pt ST. */
|
||||||
input_reply(ictx, "\033P0$r\033\\");
|
input_reply(ictx, 1, "\033P0$r\033\\");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2547,7 +2595,7 @@ input_enter_osc(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2642,7 +2690,7 @@ input_enter_apc(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2673,7 +2721,7 @@ input_enter_rename(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2752,7 +2800,7 @@ input_top_bit_set(struct input_ctx *ictx)
|
|||||||
|
|
||||||
/* Reply to a colour request. */
|
/* Reply to a colour request. */
|
||||||
static void
|
static void
|
||||||
input_osc_colour_reply(struct input_ctx *ictx, u_int n, int idx, int c)
|
input_osc_colour_reply(struct input_ctx *ictx, int add, u_int n, int idx, int c)
|
||||||
{
|
{
|
||||||
u_char r, g, b;
|
u_char r, g, b;
|
||||||
const char *end;
|
const char *end;
|
||||||
@@ -2769,11 +2817,11 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int idx, int c)
|
|||||||
end = "\033\\";
|
end = "\033\\";
|
||||||
|
|
||||||
if (n == 4) {
|
if (n == 4) {
|
||||||
input_reply(ictx,
|
input_reply(ictx, add,
|
||||||
"\033]%u;%d;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
|
"\033]%u;%d;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
|
||||||
n, idx, r, r, g, g, b, b, end);
|
n, idx, r, r, g, g, b, b, end);
|
||||||
} else {
|
} else {
|
||||||
input_reply(ictx,
|
input_reply(ictx, add,
|
||||||
"\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
|
"\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
|
||||||
n, r, r, g, g, b, b, end);
|
n, r, r, g, g, b, b, end);
|
||||||
}
|
}
|
||||||
@@ -2803,8 +2851,12 @@ input_osc_4(struct input_ctx *ictx, const char *p)
|
|||||||
s = strsep(&next, ";");
|
s = strsep(&next, ";");
|
||||||
if (strcmp(s, "?") == 0) {
|
if (strcmp(s, "?") == 0) {
|
||||||
c = colour_palette_get(palette, idx|COLOUR_FLAG_256);
|
c = colour_palette_get(palette, idx|COLOUR_FLAG_256);
|
||||||
if (c != -1)
|
if (c != -1) {
|
||||||
input_osc_colour_reply(ictx, 4, idx, c);
|
input_osc_colour_reply(ictx, 1, 4, idx, c);
|
||||||
|
s = next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
input_add_request(ictx, INPUT_REQUEST_PALETTE, idx);
|
||||||
s = next;
|
s = next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2884,7 +2936,7 @@ input_osc_10(struct input_ctx *ictx, const char *p)
|
|||||||
else
|
else
|
||||||
c = defaults.fg;
|
c = defaults.fg;
|
||||||
}
|
}
|
||||||
input_osc_colour_reply(ictx, 10, 0, c);
|
input_osc_colour_reply(ictx, 1, 10, 0, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2927,7 +2979,7 @@ input_osc_11(struct input_ctx *ictx, const char *p)
|
|||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return;
|
return;
|
||||||
c = window_pane_get_bg(wp);
|
c = window_pane_get_bg(wp);
|
||||||
input_osc_colour_reply(ictx, 11, 0, c);
|
input_osc_colour_reply(ictx, 1, 11, 0, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2971,7 +3023,7 @@ input_osc_12(struct input_ctx *ictx, const char *p)
|
|||||||
c = ictx->ctx.s->ccolour;
|
c = ictx->ctx.s->ccolour;
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
c = ictx->ctx.s->default_ccolour;
|
c = ictx->ctx.s->default_ccolour;
|
||||||
input_osc_colour_reply(ictx, 12, 0, c);
|
input_osc_colour_reply(ictx, 1, 12, 0, c);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3146,15 +3198,166 @@ input_set_buffer_size(size_t buffer_size)
|
|||||||
input_buffer_size = buffer_size;
|
input_buffer_size = buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Request timer. Remove any requests that are too old. */
|
||||||
|
static void
|
||||||
|
input_request_timer_callback(__unused int fd, __unused short events, void *arg)
|
||||||
|
{
|
||||||
|
struct input_ctx *ictx = arg;
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
|
time_t t = time(NULL);
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1) {
|
||||||
|
if (ir->t >= t - INPUT_REQUEST_TIMEOUT)
|
||||||
|
continue;
|
||||||
|
if (ir->type == INPUT_REQUEST_QUEUE)
|
||||||
|
input_send_reply(ir->ictx, ir->data);
|
||||||
|
input_free_request(ir);
|
||||||
|
}
|
||||||
|
if (ictx->request_count != 0)
|
||||||
|
input_start_request_timer(ictx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the request timer. */
|
||||||
|
static void
|
||||||
|
input_start_request_timer(struct input_ctx *ictx)
|
||||||
|
{
|
||||||
|
struct timeval tv = { .tv_sec = 0, .tv_usec = 500000 };
|
||||||
|
|
||||||
|
event_del(&ictx->request_timer);
|
||||||
|
event_add(&ictx->request_timer, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a request. */
|
||||||
|
static struct input_request *
|
||||||
|
input_make_request(struct input_ctx *ictx, enum input_request_type type)
|
||||||
|
{
|
||||||
|
struct input_request *ir;
|
||||||
|
|
||||||
|
ir = xcalloc (1, sizeof *ir);
|
||||||
|
ir->type = type;
|
||||||
|
ir->ictx = ictx;
|
||||||
|
ir->t = time(NULL);
|
||||||
|
|
||||||
|
if (++ictx->request_count == 1)
|
||||||
|
input_start_request_timer(ictx);
|
||||||
|
TAILQ_INSERT_TAIL(&ictx->requests, ir, entry);
|
||||||
|
|
||||||
|
return (ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free a request. */
|
||||||
|
static void
|
||||||
|
input_free_request(struct input_request *ir)
|
||||||
|
{
|
||||||
|
struct input_ctx *ictx = ir->ictx;
|
||||||
|
|
||||||
|
if (ir->c != NULL)
|
||||||
|
TAILQ_REMOVE(&ir->c->input_requests, ir, centry);
|
||||||
|
|
||||||
|
ictx->request_count--;
|
||||||
|
TAILQ_REMOVE(&ictx->requests, ir, entry);
|
||||||
|
|
||||||
|
free(ir->data);
|
||||||
|
free(ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a request. */
|
||||||
|
static int
|
||||||
|
input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
|
||||||
|
{
|
||||||
|
struct window_pane *wp = ictx->wp;
|
||||||
|
struct window *w;
|
||||||
|
struct client *c = NULL, *loop;
|
||||||
|
struct input_request *ir;
|
||||||
|
char s[64];
|
||||||
|
|
||||||
|
if (wp == NULL)
|
||||||
|
return (-1);
|
||||||
|
w = wp->window;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(loop, &clients, entry) {
|
||||||
|
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
|
||||||
|
continue;
|
||||||
|
if (loop->session == NULL || !session_has(loop->session, w))
|
||||||
|
continue;
|
||||||
|
if (~loop->tty.flags & TTY_STARTED)
|
||||||
|
continue;
|
||||||
|
if (c == NULL)
|
||||||
|
c = loop;
|
||||||
|
else if (timercmp(&loop->activity_time, &c->activity_time, >))
|
||||||
|
c = loop;
|
||||||
|
}
|
||||||
|
if (c == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
ir = input_make_request(ictx, type);
|
||||||
|
ir->c = c;
|
||||||
|
ir->idx = idx;
|
||||||
|
TAILQ_INSERT_TAIL(&c->input_requests, ir, centry);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case INPUT_REQUEST_PALETTE:
|
||||||
|
xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx);
|
||||||
|
tty_puts(&c->tty, s);
|
||||||
|
break;
|
||||||
|
case INPUT_REQUEST_QUEUE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle a reply to a request. */
|
||||||
|
void
|
||||||
|
input_request_reply(struct client *c, enum input_request_type type, void *data)
|
||||||
|
{
|
||||||
|
struct input_request *ir, *ir1, *found = NULL;
|
||||||
|
struct input_request_palette_data *pd = data;
|
||||||
|
int complete = 0;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1) {
|
||||||
|
if (ir->type == type && pd->idx == ir->idx) {
|
||||||
|
found = ir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
input_free_request(ir);
|
||||||
|
}
|
||||||
|
if (found == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &found->ictx->requests, entry, ir1) {
|
||||||
|
if (complete && ir->type != INPUT_REQUEST_QUEUE)
|
||||||
|
break;
|
||||||
|
if (ir->type == INPUT_REQUEST_QUEUE)
|
||||||
|
input_send_reply(ir->ictx, ir->data);
|
||||||
|
else if (ir == found && ir->type == INPUT_REQUEST_PALETTE) {
|
||||||
|
input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c);
|
||||||
|
complete = 1;
|
||||||
|
}
|
||||||
|
input_free_request(ir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cancel pending requests for client. */
|
||||||
|
void
|
||||||
|
input_cancel_requests(struct client *c)
|
||||||
|
{
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &c->input_requests, entry, ir1)
|
||||||
|
input_free_request(ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report current theme. */
|
||||||
static void
|
static void
|
||||||
input_report_current_theme(struct input_ctx *ictx)
|
input_report_current_theme(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
switch (window_pane_get_theme(ictx->wp)) {
|
switch (window_pane_get_theme(ictx->wp)) {
|
||||||
case THEME_DARK:
|
case THEME_DARK:
|
||||||
input_reply(ictx, "\033[?997;1n");
|
input_reply(ictx, 0, "\033[?997;1n");
|
||||||
break;
|
break;
|
||||||
case THEME_LIGHT:
|
case THEME_LIGHT:
|
||||||
input_reply(ictx, "\033[?997;2n");
|
input_reply(ictx, 0, "\033[?997;2n");
|
||||||
break;
|
break;
|
||||||
case THEME_UNKNOWN:
|
case THEME_UNKNOWN:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -442,10 +442,10 @@ key_bindings_init(void)
|
|||||||
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
|
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
|
||||||
|
|
||||||
/* Mouse button 1 drag on pane. */
|
/* Mouse button 1 drag on pane. */
|
||||||
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
|
"bind -n MouseDrag1Pane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
|
||||||
|
|
||||||
/* Mouse wheel up on pane. */
|
/* Mouse wheel up on pane. */
|
||||||
"bind -n WheelUpPane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",
|
"bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",
|
||||||
|
|
||||||
/* Mouse button 2 down on pane. */
|
/* Mouse button 2 down on pane. */
|
||||||
"bind -n MouseDown2Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { paste -p } }",
|
"bind -n MouseDown2Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { paste -p } }",
|
||||||
@@ -497,6 +497,8 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode C-b { send -X cursor-left }",
|
"bind -Tcopy-mode C-b { send -X cursor-left }",
|
||||||
"bind -Tcopy-mode C-g { send -X clear-selection }",
|
"bind -Tcopy-mode C-g { send -X clear-selection }",
|
||||||
"bind -Tcopy-mode C-k { send -X copy-pipe-end-of-line-and-cancel }",
|
"bind -Tcopy-mode C-k { send -X copy-pipe-end-of-line-and-cancel }",
|
||||||
|
"bind -Tcopy-mode C-l { send -X cursor-centre-vertical }",
|
||||||
|
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
|
||||||
"bind -Tcopy-mode C-n { send -X cursor-down }",
|
"bind -Tcopy-mode C-n { send -X cursor-down }",
|
||||||
"bind -Tcopy-mode C-p { send -X cursor-up }",
|
"bind -Tcopy-mode C-p { send -X cursor-up }",
|
||||||
"bind -Tcopy-mode C-r { command-prompt -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental -- '%%' } }",
|
"bind -Tcopy-mode C-r { command-prompt -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental -- '%%' } }",
|
||||||
|
|||||||
43
mode-tree.c
43
mode-tree.c
@@ -82,6 +82,7 @@ struct mode_tree_data {
|
|||||||
char *filter;
|
char *filter;
|
||||||
int no_matches;
|
int no_matches;
|
||||||
enum mode_tree_search_dir search_dir;
|
enum mode_tree_search_dir search_dir;
|
||||||
|
int search_icase;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mode_tree_item {
|
struct mode_tree_item {
|
||||||
@@ -132,6 +133,17 @@ static const struct menu_item mode_tree_menu_items[] = {
|
|||||||
{ NULL, KEYC_NONE, NULL }
|
{ NULL, KEYC_NONE, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
mode_tree_is_lowercase(const char *ptr)
|
||||||
|
{
|
||||||
|
while (*ptr != '\0') {
|
||||||
|
if (*ptr != tolower((u_char)*ptr))
|
||||||
|
return (0);
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
static struct mode_tree_item *
|
static struct mode_tree_item *
|
||||||
mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag)
|
mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag)
|
||||||
{
|
{
|
||||||
@@ -882,6 +894,7 @@ static struct mode_tree_item *
|
|||||||
mode_tree_search_backward(struct mode_tree_data *mtd)
|
mode_tree_search_backward(struct mode_tree_data *mtd)
|
||||||
{
|
{
|
||||||
struct mode_tree_item *mti, *last, *prev;
|
struct mode_tree_item *mti, *last, *prev;
|
||||||
|
int icase = mtd->search_icase;
|
||||||
|
|
||||||
if (mtd->search == NULL)
|
if (mtd->search == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -890,8 +903,10 @@ mode_tree_search_backward(struct mode_tree_data *mtd)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if ((prev = TAILQ_PREV(mti, mode_tree_list, entry)) != NULL) {
|
if ((prev = TAILQ_PREV(mti, mode_tree_list, entry)) != NULL) {
|
||||||
/* Point to the last child in the previous subtree. */
|
/* Point to the last child in the previous subtree. */
|
||||||
while (!TAILQ_EMPTY(&prev->children))
|
while (!TAILQ_EMPTY(&prev->children)) {
|
||||||
prev = TAILQ_LAST(&prev->children, mode_tree_list);
|
prev = TAILQ_LAST(&prev->children,
|
||||||
|
mode_tree_list);
|
||||||
|
}
|
||||||
mti = prev;
|
mti = prev;
|
||||||
} else {
|
} else {
|
||||||
/* If prev is NULL, jump to the parent. */
|
/* If prev is NULL, jump to the parent. */
|
||||||
@@ -901,29 +916,34 @@ mode_tree_search_backward(struct mode_tree_data *mtd)
|
|||||||
if (mti == NULL) {
|
if (mti == NULL) {
|
||||||
/* Point to the last child in the last root subtree. */
|
/* Point to the last child in the last root subtree. */
|
||||||
prev = TAILQ_LAST(&mtd->children, mode_tree_list);
|
prev = TAILQ_LAST(&mtd->children, mode_tree_list);
|
||||||
while (!TAILQ_EMPTY(&prev->children))
|
while (!TAILQ_EMPTY(&prev->children)) {
|
||||||
prev = TAILQ_LAST(&prev->children, mode_tree_list);
|
prev = TAILQ_LAST(&prev->children,
|
||||||
|
mode_tree_list);
|
||||||
|
}
|
||||||
mti = prev;
|
mti = prev;
|
||||||
}
|
}
|
||||||
if (mti == last)
|
if (mti == last)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (mtd->searchcb == NULL) {
|
if (mtd->searchcb == NULL) {
|
||||||
if (strstr(mti->name, mtd->search) != NULL)
|
if (!icase && strstr(mti->name, mtd->search) != NULL)
|
||||||
|
return (mti);
|
||||||
|
if (icase && strcasestr(mti->name, mtd->search) != NULL)
|
||||||
return (mti);
|
return (mti);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search))
|
if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search,
|
||||||
|
icase))
|
||||||
return (mti);
|
return (mti);
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct mode_tree_item *
|
static struct mode_tree_item *
|
||||||
mode_tree_search_forward(struct mode_tree_data *mtd)
|
mode_tree_search_forward(struct mode_tree_data *mtd)
|
||||||
{
|
{
|
||||||
struct mode_tree_item *mti, *last, *next;
|
struct mode_tree_item *mti, *last, *next;
|
||||||
|
int icase = mtd->search_icase;
|
||||||
|
|
||||||
if (mtd->search == NULL)
|
if (mtd->search == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -951,11 +971,14 @@ mode_tree_search_forward(struct mode_tree_data *mtd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (mtd->searchcb == NULL) {
|
if (mtd->searchcb == NULL) {
|
||||||
if (strstr(mti->name, mtd->search) != NULL)
|
if (!icase && strstr(mti->name, mtd->search) != NULL)
|
||||||
|
return (mti);
|
||||||
|
if (icase && strcasestr(mti->name, mtd->search) != NULL)
|
||||||
return (mti);
|
return (mti);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search))
|
if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search,
|
||||||
|
icase))
|
||||||
return (mti);
|
return (mti);
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -1002,6 +1025,7 @@ mode_tree_search_callback(__unused struct client *c, void *data, const char *s,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
mtd->search = xstrdup(s);
|
mtd->search = xstrdup(s);
|
||||||
|
mtd->search_icase = mode_tree_is_lowercase(s);
|
||||||
mode_tree_search_set(mtd);
|
mode_tree_search_set(mtd);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@@ -1309,6 +1333,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
case '/':
|
case '/':
|
||||||
case 's'|KEYC_CTRL:
|
case 's'|KEYC_CTRL:
|
||||||
mtd->references++;
|
mtd->references++;
|
||||||
|
mtd->search_dir = MODE_TREE_SEARCH_FORWARD;
|
||||||
status_prompt_set(c, NULL, "(search) ", "",
|
status_prompt_set(c, NULL, "(search) ", "",
|
||||||
mode_tree_search_callback, mode_tree_search_free, mtd,
|
mode_tree_search_callback, mode_tree_search_free, mtd,
|
||||||
PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH);
|
PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH);
|
||||||
|
|||||||
50
popup.c
50
popup.c
@@ -639,6 +639,56 @@ popup_job_complete_cb(struct job *job)
|
|||||||
server_client_clear_overlay(pd->c);
|
server_client_clear_overlay(pd->c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
popup_present(struct client *c)
|
||||||
|
{
|
||||||
|
return (c->overlay_draw == popup_draw_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
popup_modify(struct client *c, const char *title, const char *style,
|
||||||
|
const char *border_style, enum box_lines lines, int flags)
|
||||||
|
{
|
||||||
|
struct popup_data *pd = c->overlay_data;
|
||||||
|
struct style sytmp;
|
||||||
|
|
||||||
|
if (title != NULL) {
|
||||||
|
if (pd->title != NULL)
|
||||||
|
free(pd->title);
|
||||||
|
pd->title = xstrdup(title);
|
||||||
|
}
|
||||||
|
if (border_style != NULL) {
|
||||||
|
style_set(&sytmp, &pd->border_cell);
|
||||||
|
if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) {
|
||||||
|
pd->border_cell.fg = sytmp.gc.fg;
|
||||||
|
pd->border_cell.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (style != NULL) {
|
||||||
|
style_set(&sytmp, &pd->defaults);
|
||||||
|
if (style_parse(&sytmp, &pd->defaults, style) == 0) {
|
||||||
|
pd->defaults.fg = sytmp.gc.fg;
|
||||||
|
pd->defaults.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lines != BOX_LINES_DEFAULT) {
|
||||||
|
if (lines == BOX_LINES_NONE && pd->border_lines != lines) {
|
||||||
|
screen_resize(&pd->s, pd->sx, pd->sy, 1);
|
||||||
|
job_resize(pd->job, pd->sx, pd->sy);
|
||||||
|
} else if (pd->border_lines == BOX_LINES_NONE && pd->border_lines != lines) {
|
||||||
|
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 1);
|
||||||
|
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
|
||||||
|
}
|
||||||
|
pd->border_lines = lines;
|
||||||
|
tty_resize(&c->tty);
|
||||||
|
}
|
||||||
|
if (flags != -1)
|
||||||
|
pd->flags = flags;
|
||||||
|
|
||||||
|
server_redraw_client(c);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
|
popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
|
||||||
u_int py, u_int sx, u_int sy, struct environ *env, const char *shellcmd,
|
u_int py, u_int sx, u_int sy, struct environ *env, const char *shellcmd,
|
||||||
|
|||||||
@@ -584,7 +584,8 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
|||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx, 0);
|
||||||
for (xx = px; xx < px + nx; xx++) {
|
for (xx = px; xx < px + nx; xx++) {
|
||||||
if (xx >= grid_get_line(gd, yy)->cellsize)
|
if (xx >= grid_get_line(gd, yy)->cellsize &&
|
||||||
|
s->cx >= grid_get_line(ctx->s->grid, s->cy)->cellsize)
|
||||||
break;
|
break;
|
||||||
grid_get_cell(gd, xx, yy, &gc);
|
grid_get_cell(gd, xx, yy, &gc);
|
||||||
if (xx + gc.data.width > px + nx)
|
if (xx + gc.data.width > px + nx)
|
||||||
@@ -2156,6 +2157,10 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
int force_wide = 0, zero_width = 0;
|
int force_wide = 0, zero_width = 0;
|
||||||
|
|
||||||
|
/* Ignore U+3164 HANGUL_FILLER entirely. */
|
||||||
|
if (utf8_is_hangul_filler(ud))
|
||||||
|
return (1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is this character which makes no sense without being combined? If
|
* Is this character which makes no sense without being combined? If
|
||||||
* this is true then flag it here and discard the character (return 1)
|
* this is true then flag it here and discard the character (return 1)
|
||||||
@@ -2200,11 +2205,9 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
case HANGULJAMO_STATE_COMPOSABLE:
|
case HANGULJAMO_STATE_COMPOSABLE:
|
||||||
break;
|
break;
|
||||||
case HANGULJAMO_STATE_NOT_HANGULJAMO:
|
case HANGULJAMO_STATE_NOT_HANGULJAMO:
|
||||||
if (utf8_is_modifier(ud)) {
|
if (utf8_should_combine(&last.data, ud))
|
||||||
if (last.data.size < 2)
|
|
||||||
return (0);
|
|
||||||
force_wide = 1;
|
force_wide = 1;
|
||||||
} else if (!utf8_has_zwj(&last.data))
|
else if (!utf8_has_zwj(&last.data))
|
||||||
return (0);
|
return (0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
10
screen.c
10
screen.c
@@ -91,6 +91,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
|||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
TAILQ_INIT(&s->images);
|
TAILQ_INIT(&s->images);
|
||||||
|
TAILQ_INIT(&s->saved_images);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s->write_list = NULL;
|
s->write_list = NULL;
|
||||||
@@ -643,6 +644,10 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
|
|||||||
}
|
}
|
||||||
memcpy(&s->saved_cell, gc, sizeof s->saved_cell);
|
memcpy(&s->saved_cell, gc, sizeof s->saved_cell);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SIXEL
|
||||||
|
TAILQ_CONCAT(&s->saved_images, &s->images, entry);
|
||||||
|
#endif
|
||||||
|
|
||||||
grid_view_clear(s->grid, 0, 0, sx, sy, 8);
|
grid_view_clear(s->grid, 0, 0, sx, sy, 8);
|
||||||
|
|
||||||
s->saved_flags = s->grid->flags;
|
s->saved_flags = s->grid->flags;
|
||||||
@@ -697,6 +702,11 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
|
|||||||
grid_destroy(s->saved_grid);
|
grid_destroy(s->saved_grid);
|
||||||
s->saved_grid = NULL;
|
s->saved_grid = NULL;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SIXEL
|
||||||
|
image_free_all(s);
|
||||||
|
TAILQ_CONCAT(&s->images, &s->saved_images, entry);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s->cx > screen_size_x(s) - 1)
|
if (s->cx > screen_size_x(s) - 1)
|
||||||
s->cx = screen_size_x(s) - 1;
|
s->cx = screen_size_x(s) - 1;
|
||||||
if (s->cy > screen_size_y(s) - 1)
|
if (s->cy > screen_size_y(s) - 1)
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ server_client_create(int fd)
|
|||||||
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
||||||
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
||||||
|
|
||||||
|
TAILQ_INIT(&c->input_requests);
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&clients, c, entry);
|
TAILQ_INSERT_TAIL(&clients, c, entry);
|
||||||
log_debug("new client %p", c);
|
log_debug("new client %p", c);
|
||||||
return (c);
|
return (c);
|
||||||
@@ -459,6 +461,7 @@ server_client_lost(struct client *c)
|
|||||||
tty_term_free_list(c->term_caps, c->term_ncaps);
|
tty_term_free_list(c->term_caps, c->term_ncaps);
|
||||||
|
|
||||||
status_free(c);
|
status_free(c);
|
||||||
|
input_cancel_requests(c);
|
||||||
|
|
||||||
free(c->title);
|
free(c->title);
|
||||||
free((void *)c->cwd);
|
free((void *)c->cwd);
|
||||||
|
|||||||
@@ -287,6 +287,8 @@ server_link_window(struct session *src, struct winlink *srcwl,
|
|||||||
if (dstwl == NULL)
|
if (dstwl == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
|
if (marked_pane.wl == srcwl)
|
||||||
|
marked_pane.wl = dstwl;
|
||||||
if (selectflag)
|
if (selectflag)
|
||||||
session_select(dst, dstwl->idx);
|
session_select(dst, dstwl->idx);
|
||||||
server_redraw_session_group(dst);
|
server_redraw_session_group(dst);
|
||||||
|
|||||||
48
tmux.1
48
tmux.1
@@ -599,7 +599,7 @@ This is called line continuation and applies both inside and outside quoted
|
|||||||
strings and in comments, but not inside braces.
|
strings and in comments, but not inside braces.
|
||||||
.Pp
|
.Pp
|
||||||
Command arguments may be specified as strings surrounded by single (\[aq])
|
Command arguments may be specified as strings surrounded by single (\[aq])
|
||||||
quotes, double quotes (\[dq]) or braces ({}).
|
quotes or double quotes (\[dq]), or as command lists surrounded by braces ({}).
|
||||||
.\" "
|
.\" "
|
||||||
This is required when the argument contains any special character.
|
This is required when the argument contains any special character.
|
||||||
Single and double quoted strings cannot span multiple lines except with line
|
Single and double quoted strings cannot span multiple lines except with line
|
||||||
@@ -1953,6 +1953,16 @@ Move the cursor right.
|
|||||||
.Xc
|
.Xc
|
||||||
Move the cursor up.
|
Move the cursor up.
|
||||||
.It Xo
|
.It Xo
|
||||||
|
.Ic cursor-centre-vertical
|
||||||
|
(emacs: C-l)
|
||||||
|
.Xc
|
||||||
|
Moves the cursor to the vertical centre of the pane.
|
||||||
|
.It Xo
|
||||||
|
.Ic cursor-centre-horizontal
|
||||||
|
(emacs: M-l)
|
||||||
|
.Xc
|
||||||
|
Moves the cursor to the horizontal centre of the pane.
|
||||||
|
.It Xo
|
||||||
.Ic end-of-line
|
.Ic end-of-line
|
||||||
(vi: $)
|
(vi: $)
|
||||||
(emacs: C-e)
|
(emacs: C-e)
|
||||||
@@ -2285,6 +2295,11 @@ Select the current line.
|
|||||||
.Xc
|
.Xc
|
||||||
Select the current word.
|
Select the current word.
|
||||||
.It Xo
|
.It Xo
|
||||||
|
.Ic selection-mode
|
||||||
|
.Op Ic char | word | line
|
||||||
|
.Xc
|
||||||
|
Change the selection mode.
|
||||||
|
.It Xo
|
||||||
.Ic set-mark
|
.Ic set-mark
|
||||||
(vi: X)
|
(vi: X)
|
||||||
(emacs: X)
|
(emacs: X)
|
||||||
@@ -6662,7 +6677,7 @@ See
|
|||||||
for possible values for
|
for possible values for
|
||||||
.Ar prompt-type .
|
.Ar prompt-type .
|
||||||
.It Xo Ic command-prompt
|
.It Xo Ic command-prompt
|
||||||
.Op Fl 1bFikN
|
.Op Fl 1bFiklN
|
||||||
.Op Fl I Ar inputs
|
.Op Fl I Ar inputs
|
||||||
.Op Fl p Ar prompts
|
.Op Fl p Ar prompts
|
||||||
.Op Fl t Ar target-client
|
.Op Fl t Ar target-client
|
||||||
@@ -6682,8 +6697,10 @@ With
|
|||||||
.Ar template
|
.Ar template
|
||||||
is expanded as a format.
|
is expanded as a format.
|
||||||
.Pp
|
.Pp
|
||||||
If present,
|
If
|
||||||
.Fl I
|
.Fl I
|
||||||
|
is present,
|
||||||
|
.Ar inputs
|
||||||
is a comma-separated list of the initial text for each prompt.
|
is a comma-separated list of the initial text for each prompt.
|
||||||
If
|
If
|
||||||
.Fl p
|
.Fl p
|
||||||
@@ -6695,6 +6712,12 @@ a single prompt is displayed, constructed from
|
|||||||
if it is present, or
|
if it is present, or
|
||||||
.Ql \&:
|
.Ql \&:
|
||||||
if not.
|
if not.
|
||||||
|
.Fl l
|
||||||
|
disables splitting of
|
||||||
|
.Ar inputs
|
||||||
|
and
|
||||||
|
.Ar prompts
|
||||||
|
at commas and treats them literally.
|
||||||
.Pp
|
.Pp
|
||||||
Before the command is executed, the first occurrence of the string
|
Before the command is executed, the first occurrence of the string
|
||||||
.Ql %%
|
.Ql %%
|
||||||
@@ -6978,7 +7001,7 @@ forwards any input read from stdin to the empty pane given by
|
|||||||
.Ar target-pane .
|
.Ar target-pane .
|
||||||
.Tg popup
|
.Tg popup
|
||||||
.It Xo Ic display-popup
|
.It Xo Ic display-popup
|
||||||
.Op Fl BCEk
|
.Op Fl BCEkN
|
||||||
.Op Fl b Ar border-lines
|
.Op Fl b Ar border-lines
|
||||||
.Op Fl c Ar target-client
|
.Op Fl c Ar target-client
|
||||||
.Op Fl d Ar start-directory
|
.Op Fl d Ar start-directory
|
||||||
@@ -7002,6 +7025,20 @@ when omitted) on
|
|||||||
.Ar target-client .
|
.Ar target-client .
|
||||||
A popup is a rectangular box drawn over the top of any panes.
|
A popup is a rectangular box drawn over the top of any panes.
|
||||||
Panes are not updated while a popup is present.
|
Panes are not updated while a popup is present.
|
||||||
|
If the command is run inside an existing popup, that popup is modified.
|
||||||
|
Only the
|
||||||
|
.Fl b ,
|
||||||
|
.Fl B ,
|
||||||
|
.Fl C ,
|
||||||
|
.Fl E ,
|
||||||
|
.Fl EE ,
|
||||||
|
.Fl K ,
|
||||||
|
.Fl N ,
|
||||||
|
.Fl s ,
|
||||||
|
and
|
||||||
|
.Fl S
|
||||||
|
options are accepted in this case;
|
||||||
|
all others are ignored.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl E
|
.Fl E
|
||||||
closes the popup automatically when
|
closes the popup automatically when
|
||||||
@@ -7065,6 +7102,9 @@ is a format for the popup title (see
|
|||||||
The
|
The
|
||||||
.Fl C
|
.Fl C
|
||||||
flag closes any popup on the client.
|
flag closes any popup on the client.
|
||||||
|
.Pp
|
||||||
|
.Fl N
|
||||||
|
disables any previously specified -E, -EE, or -k option.
|
||||||
.Tg showphist
|
.Tg showphist
|
||||||
.It Xo Ic show-prompt-history
|
.It Xo Ic show-prompt-history
|
||||||
.Op Fl T Ar prompt-type
|
.Op Fl T Ar prompt-type
|
||||||
|
|||||||
10
tmux.c
10
tmux.c
@@ -139,7 +139,7 @@ expand_path(const char *path, const char *home)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expand_paths(const char *s, char ***paths, u_int *n, int ignore_errors)
|
expand_paths(const char *s, char ***paths, u_int *n, int no_realpath)
|
||||||
{
|
{
|
||||||
const char *home = find_home();
|
const char *home = find_home();
|
||||||
char *copy, *next, *tmp, resolved[PATH_MAX], *expanded;
|
char *copy, *next, *tmp, resolved[PATH_MAX], *expanded;
|
||||||
@@ -156,15 +156,15 @@ expand_paths(const char *s, char ***paths, u_int *n, int ignore_errors)
|
|||||||
log_debug("%s: invalid path: %s", __func__, next);
|
log_debug("%s: invalid path: %s", __func__, next);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (no_realpath)
|
||||||
|
path = expanded;
|
||||||
|
else {
|
||||||
if (realpath(expanded, resolved) == NULL) {
|
if (realpath(expanded, resolved) == NULL) {
|
||||||
log_debug("%s: realpath(\"%s\") failed: %s", __func__,
|
log_debug("%s: realpath(\"%s\") failed: %s", __func__,
|
||||||
expanded, strerror(errno));
|
expanded, strerror(errno));
|
||||||
if (ignore_errors) {
|
|
||||||
free(expanded);
|
free(expanded);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
path = expanded;
|
|
||||||
} else {
|
|
||||||
path = xstrdup(resolved);
|
path = xstrdup(resolved);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ make_label(const char *label, char **cause)
|
|||||||
label = "default";
|
label = "default";
|
||||||
uid = getuid();
|
uid = getuid();
|
||||||
|
|
||||||
expand_paths(TMUX_SOCK, &paths, &n, 1);
|
expand_paths(TMUX_SOCK, &paths, &n, 0);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
xasprintf(cause, "no suitable socket path");
|
xasprintf(cause, "no suitable socket path");
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|||||||
31
tmux.h
31
tmux.h
@@ -54,6 +54,8 @@ struct format_tree;
|
|||||||
struct hyperlinks_uri;
|
struct hyperlinks_uri;
|
||||||
struct hyperlinks;
|
struct hyperlinks;
|
||||||
struct input_ctx;
|
struct input_ctx;
|
||||||
|
struct input_request;
|
||||||
|
struct input_requests;
|
||||||
struct job;
|
struct job;
|
||||||
struct menu_data;
|
struct menu_data;
|
||||||
struct mode_tree_data;
|
struct mode_tree_data;
|
||||||
@@ -982,6 +984,7 @@ struct screen {
|
|||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
struct images images;
|
struct images images;
|
||||||
|
struct images saved_images;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct screen_write_cline *write_list;
|
struct screen_write_cline *write_list;
|
||||||
@@ -1123,6 +1126,21 @@ struct window_mode_entry {
|
|||||||
TAILQ_ENTRY(window_mode_entry) entry;
|
TAILQ_ENTRY(window_mode_entry) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Type of request to client. */
|
||||||
|
enum input_request_type {
|
||||||
|
INPUT_REQUEST_PALETTE,
|
||||||
|
INPUT_REQUEST_QUEUE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Palette request reply data. */
|
||||||
|
struct input_request_palette_data {
|
||||||
|
int idx;
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Request sent to client on behalf of pane. */
|
||||||
|
TAILQ_HEAD(input_requests, input_request);
|
||||||
|
|
||||||
/* Offsets into pane buffer. */
|
/* Offsets into pane buffer. */
|
||||||
struct window_pane_offset {
|
struct window_pane_offset {
|
||||||
size_t used;
|
size_t used;
|
||||||
@@ -1959,6 +1977,8 @@ struct client {
|
|||||||
struct status_line status;
|
struct status_line status;
|
||||||
enum client_theme theme;
|
enum client_theme theme;
|
||||||
|
|
||||||
|
struct input_requests input_requests;
|
||||||
|
|
||||||
#define CLIENT_TERMINAL 0x1
|
#define CLIENT_TERMINAL 0x1
|
||||||
#define CLIENT_LOGIN 0x2
|
#define CLIENT_LOGIN 0x2
|
||||||
#define CLIENT_EXIT 0x4
|
#define CLIENT_EXIT 0x4
|
||||||
@@ -2984,6 +3004,8 @@ void input_parse_screen(struct input_ctx *, struct screen *,
|
|||||||
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
|
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
|
||||||
const char *);
|
const char *);
|
||||||
void input_set_buffer_size(size_t);
|
void input_set_buffer_size(size_t);
|
||||||
|
void input_request_reply(struct client *, enum input_request_type, void *);
|
||||||
|
void input_cancel_requests(struct client *);
|
||||||
|
|
||||||
/* input-key.c */
|
/* input-key.c */
|
||||||
void input_key_build(void);
|
void input_key_build(void);
|
||||||
@@ -3361,7 +3383,7 @@ typedef void (*mode_tree_build_cb)(void *, struct mode_tree_sort_criteria *,
|
|||||||
uint64_t *, const char *);
|
uint64_t *, const char *);
|
||||||
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
||||||
u_int, u_int);
|
u_int, u_int);
|
||||||
typedef int (*mode_tree_search_cb)(void *, void *, const char *);
|
typedef int (*mode_tree_search_cb)(void *, void *, const char *, int);
|
||||||
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
||||||
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
||||||
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
|
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
|
||||||
@@ -3549,7 +3571,9 @@ struct event_base *osdep_event_init(void);
|
|||||||
int utf8_has_zwj(const struct utf8_data *);
|
int utf8_has_zwj(const struct utf8_data *);
|
||||||
int utf8_is_zwj(const struct utf8_data *);
|
int utf8_is_zwj(const struct utf8_data *);
|
||||||
int utf8_is_vs(const struct utf8_data *);
|
int utf8_is_vs(const struct utf8_data *);
|
||||||
int utf8_is_modifier(const struct utf8_data *);
|
int utf8_is_hangul_filler(const struct utf8_data *);
|
||||||
|
int utf8_should_combine(const struct utf8_data *,
|
||||||
|
const struct utf8_data *);
|
||||||
enum hanguljamo_state hanguljamo_check_state(const struct utf8_data *,
|
enum hanguljamo_state hanguljamo_check_state(const struct utf8_data *,
|
||||||
const struct utf8_data *);
|
const struct utf8_data *);
|
||||||
|
|
||||||
@@ -3605,6 +3629,9 @@ int popup_display(int, enum box_lines, struct cmdq_item *, u_int,
|
|||||||
popup_close_cb, void *);
|
popup_close_cb, void *);
|
||||||
int popup_editor(struct client *, const char *, size_t,
|
int popup_editor(struct client *, const char *, size_t,
|
||||||
popup_finish_edit_cb, void *);
|
popup_finish_edit_cb, void *);
|
||||||
|
int popup_present(struct client *);
|
||||||
|
int popup_modify(struct client *, const char *, const char *,
|
||||||
|
const char *, enum box_lines, int);
|
||||||
|
|
||||||
/* style.c */
|
/* style.c */
|
||||||
int style_parse(struct style *,const struct grid_cell *,
|
int style_parse(struct style *,const struct grid_cell *,
|
||||||
|
|||||||
76
tty-keys.c
76
tty-keys.c
@@ -59,6 +59,7 @@ static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
|
|||||||
size_t *);
|
size_t *);
|
||||||
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
||||||
size_t, size_t *);
|
size_t, size_t *);
|
||||||
|
static int tty_keys_palette(struct tty *, const char *, size_t, size_t *);
|
||||||
|
|
||||||
/* A key tree entry. */
|
/* A key tree entry. */
|
||||||
struct tty_key {
|
struct tty_key {
|
||||||
@@ -804,6 +805,17 @@ tty_keys_next(struct tty *tty)
|
|||||||
goto partial_key;
|
goto partial_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is this a palette response? */
|
||||||
|
switch (tty_keys_palette(tty, buf, len, &size)) {
|
||||||
|
case 0: /* yes */
|
||||||
|
key = KEYC_UNKNOWN;
|
||||||
|
goto complete_key;
|
||||||
|
case -1: /* no, or not valid */
|
||||||
|
break;
|
||||||
|
case 1: /* partial */
|
||||||
|
goto partial_key;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is this a mouse key press? */
|
/* Is this a mouse key press? */
|
||||||
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
||||||
case 0: /* yes */
|
case 0: /* yes */
|
||||||
@@ -1699,3 +1711,67 @@ tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size,
|
|||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle OSC 4 palette colour responses. */
|
||||||
|
static int
|
||||||
|
tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||||
|
{
|
||||||
|
struct client *c = tty->client;
|
||||||
|
u_int i, start;
|
||||||
|
char tmp[128], *endptr;
|
||||||
|
int idx;
|
||||||
|
struct input_request_palette_data pd;
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
/* First three bytes are always \033]4. */
|
||||||
|
if (buf[0] != '\033')
|
||||||
|
return (-1);
|
||||||
|
if (len == 1)
|
||||||
|
return (1);
|
||||||
|
if (buf[1] != ']')
|
||||||
|
return (-1);
|
||||||
|
if (len == 2)
|
||||||
|
return (1);
|
||||||
|
if (buf[2] != '4')
|
||||||
|
return (-1);
|
||||||
|
if (len == 3)
|
||||||
|
return (1);
|
||||||
|
if (buf[3] != ';')
|
||||||
|
return (-1);
|
||||||
|
if (len == 4)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* Parse index. */
|
||||||
|
idx = strtol(buf + 4, &endptr, 10);
|
||||||
|
if (endptr == buf + 4 || *endptr != ';')
|
||||||
|
return (-1);
|
||||||
|
if (idx < 0 || idx > 255)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/* Copy the rest up to \033\ or \007. */
|
||||||
|
start = (endptr - buf) + 1;
|
||||||
|
for (i = start; i < len && i - start < sizeof tmp; i++) {
|
||||||
|
if (buf[i - 1] == '\033' && buf[i] == '\\')
|
||||||
|
break;
|
||||||
|
if (buf[i] == '\007')
|
||||||
|
break;
|
||||||
|
tmp[i - start] = buf[i];
|
||||||
|
}
|
||||||
|
if (i - start == sizeof tmp)
|
||||||
|
return (-1);
|
||||||
|
if (i > 0 && buf[i - 1] == '\033')
|
||||||
|
tmp[i - start - 1] = '\0';
|
||||||
|
else
|
||||||
|
tmp[i - start] = '\0';
|
||||||
|
*size = i + 1;
|
||||||
|
|
||||||
|
/* Work out the colour. */
|
||||||
|
pd.c = colour_parseX11(tmp);
|
||||||
|
if (pd.c == -1)
|
||||||
|
return (0);
|
||||||
|
pd.idx = idx;
|
||||||
|
input_request_reply(c, INPUT_REQUEST_PALETTE, &pd);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|||||||
11
tty-term.c
11
tty-term.c
@@ -535,6 +535,7 @@ tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps,
|
|||||||
size_t offset, namelen;
|
size_t offset, namelen;
|
||||||
char *first;
|
char *first;
|
||||||
int n;
|
int n;
|
||||||
|
struct environ_entry *envent;
|
||||||
|
|
||||||
log_debug("adding term %s", name);
|
log_debug("adding term %s", name);
|
||||||
|
|
||||||
@@ -603,6 +604,16 @@ tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps,
|
|||||||
(NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 6)
|
(NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 6)
|
||||||
del_curterm(cur_term);
|
del_curterm(cur_term);
|
||||||
#endif
|
#endif
|
||||||
|
/* Check for COLORTERM. */
|
||||||
|
envent = environ_find(tty->client->environ, "COLORTERM");
|
||||||
|
if (envent != NULL) {
|
||||||
|
log_debug("%s COLORTERM=%s", tty->client->name, envent->value);
|
||||||
|
if (strcasecmp(envent->value, "truecolor") == 0 ||
|
||||||
|
strcasecmp(envent->value, "24bit") == 0)
|
||||||
|
tty_add_features(feat, "RGB", ",");
|
||||||
|
else if (strstr(envent->value, "256") != NULL)
|
||||||
|
tty_add_features(feat, "256", ",");
|
||||||
|
}
|
||||||
|
|
||||||
/* Apply overrides so any capabilities used for features are changed. */
|
/* Apply overrides so any capabilities used for features are changed. */
|
||||||
tty_term_apply_overrides(term);
|
tty_term_apply_overrides(term);
|
||||||
|
|||||||
6
tty.c
6
tty.c
@@ -419,10 +419,12 @@ tty_repeat_requests(struct tty *tty, int force)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!force && n <= TTY_REQUEST_LIMIT) {
|
if (!force && n <= TTY_REQUEST_LIMIT) {
|
||||||
log_debug("%s: not repeating requests (%u seconds)", c->name, n);
|
log_debug("%s: not repeating requests (%u seconds)", c->name,
|
||||||
|
n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log_debug("%s: %srepeating requests (%u seconds)", c->name, force ? "(force) " : "" , n);
|
log_debug("%s: %srepeating requests (%u seconds)", c->name,
|
||||||
|
force ? "(force) " : "" , n);
|
||||||
tty->last_requests = t;
|
tty->last_requests = t;
|
||||||
|
|
||||||
if (tty->term->flags & TERM_VT100LIKE) {
|
if (tty->term->flags & TERM_VT100LIKE) {
|
||||||
|
|||||||
137
utf8-combined.c
137
utf8-combined.c
@@ -55,7 +55,7 @@ utf8_has_zwj(const struct utf8_data *ud)
|
|||||||
return (memcmp(ud->data + ud->size - 3, "\342\200\215", 3) == 0);
|
return (memcmp(ud->data + ud->size - 3, "\342\200\215", 3) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this a zero width joiner? */
|
/* Is this zero width joiner U+200D? */
|
||||||
int
|
int
|
||||||
utf8_is_zwj(const struct utf8_data *ud)
|
utf8_is_zwj(const struct utf8_data *ud)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ utf8_is_zwj(const struct utf8_data *ud)
|
|||||||
return (memcmp(ud->data, "\342\200\215", 3) == 0);
|
return (memcmp(ud->data, "\342\200\215", 3) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this a variation selector? */
|
/* Is this variation selector U+FE0F? */
|
||||||
int
|
int
|
||||||
utf8_is_vs(const struct utf8_data *ud)
|
utf8_is_vs(const struct utf8_data *ud)
|
||||||
{
|
{
|
||||||
@@ -73,49 +73,108 @@ utf8_is_vs(const struct utf8_data *ud)
|
|||||||
return (memcmp(ud->data, "\357\270\217", 3) == 0);
|
return (memcmp(ud->data, "\357\270\217", 3) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this in the modifier table? */
|
/* Is this Hangul filler U+3164? */
|
||||||
int
|
int
|
||||||
utf8_is_modifier(const struct utf8_data *ud)
|
utf8_is_hangul_filler(const struct utf8_data *ud)
|
||||||
{
|
{
|
||||||
wchar_t wc;
|
if (ud->size != 3)
|
||||||
|
return (0);
|
||||||
|
return (memcmp(ud->data, "\343\205\244", 3) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (utf8_towc(ud, &wc) != UTF8_DONE)
|
/* Should these two characters combine? */
|
||||||
|
int
|
||||||
|
utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add)
|
||||||
|
{
|
||||||
|
wchar_t w, a;
|
||||||
|
|
||||||
|
if (utf8_towc(with, &w) != UTF8_DONE)
|
||||||
return (0);
|
return (0);
|
||||||
switch (wc) {
|
if (utf8_towc(add, &a) != UTF8_DONE)
|
||||||
case 0x1F1E6:
|
return (0);
|
||||||
case 0x1F1E7:
|
|
||||||
case 0x1F1E8:
|
/* Regional indicators. */
|
||||||
case 0x1F1E9:
|
if ((a >= 0x1F1E6 && a <= 0x1F1FF) && (w >= 0x1F1E6 && w <= 0x1F1FF))
|
||||||
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 (1);
|
||||||
|
|
||||||
|
/* Emoji skin tone modifiers. */
|
||||||
|
switch (a) {
|
||||||
|
case 0x1F44B:
|
||||||
|
case 0x1F44C:
|
||||||
|
case 0x1F44D:
|
||||||
|
case 0x1F44E:
|
||||||
|
case 0x1F44F:
|
||||||
|
case 0x1F450:
|
||||||
|
case 0x1F466:
|
||||||
|
case 0x1F467:
|
||||||
|
case 0x1F468:
|
||||||
|
case 0x1F469:
|
||||||
|
case 0x1F46E:
|
||||||
|
case 0x1F470:
|
||||||
|
case 0x1F471:
|
||||||
|
case 0x1F472:
|
||||||
|
case 0x1F473:
|
||||||
|
case 0x1F474:
|
||||||
|
case 0x1F475:
|
||||||
|
case 0x1F476:
|
||||||
|
case 0x1F477:
|
||||||
|
case 0x1F478:
|
||||||
|
case 0x1F47C:
|
||||||
|
case 0x1F481:
|
||||||
|
case 0x1F482:
|
||||||
|
case 0x1F485:
|
||||||
|
case 0x1F486:
|
||||||
|
case 0x1F487:
|
||||||
|
case 0x1F4AA:
|
||||||
|
case 0x1F575:
|
||||||
|
case 0x1F57A:
|
||||||
|
case 0x1F590:
|
||||||
|
case 0x1F595:
|
||||||
|
case 0x1F596:
|
||||||
|
case 0x1F645:
|
||||||
|
case 0x1F646:
|
||||||
|
case 0x1F647:
|
||||||
|
case 0x1F64B:
|
||||||
|
case 0x1F64C:
|
||||||
|
case 0x1F64D:
|
||||||
|
case 0x1F64E:
|
||||||
|
case 0x1F64F:
|
||||||
|
case 0x1F6B4:
|
||||||
|
case 0x1F6B5:
|
||||||
|
case 0x1F6B6:
|
||||||
|
case 0x1F926:
|
||||||
|
case 0x1F937:
|
||||||
|
case 0x1F938:
|
||||||
|
case 0x1F939:
|
||||||
|
case 0x1F93D:
|
||||||
|
case 0x1F93E:
|
||||||
|
case 0x1F9B5:
|
||||||
|
case 0x1F9B6:
|
||||||
|
case 0x1F9B8:
|
||||||
|
case 0x1F9B9:
|
||||||
|
case 0x1F9CD:
|
||||||
|
case 0x1F9CE:
|
||||||
|
case 0x1F9CF:
|
||||||
|
case 0x1F9D1:
|
||||||
|
case 0x1F9D2:
|
||||||
|
case 0x1F9D3:
|
||||||
|
case 0x1F9D4:
|
||||||
|
case 0x1F9D5:
|
||||||
|
case 0x1F9D6:
|
||||||
|
case 0x1F9D7:
|
||||||
|
case 0x1F9D8:
|
||||||
|
case 0x1F9D9:
|
||||||
|
case 0x1F9DA:
|
||||||
|
case 0x1F9DB:
|
||||||
|
case 0x1F9DC:
|
||||||
|
case 0x1F9DD:
|
||||||
|
case 0x1F9DE:
|
||||||
|
case 0x1F9DF:
|
||||||
|
if (w >= 0x1F3FB && w <= 0x1F3FF)
|
||||||
|
return (1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum hanguljamo_subclass
|
static enum hanguljamo_subclass
|
||||||
|
|||||||
52
utf8.c
52
utf8.c
@@ -57,32 +57,32 @@ static struct utf8_width_item utf8_default_width_cache[] = {
|
|||||||
{ .wc = 0x0270B, .width = 2 },
|
{ .wc = 0x0270B, .width = 2 },
|
||||||
{ .wc = 0x0270C, .width = 2 },
|
{ .wc = 0x0270C, .width = 2 },
|
||||||
{ .wc = 0x0270D, .width = 2 },
|
{ .wc = 0x0270D, .width = 2 },
|
||||||
{ .wc = 0x1F1E6, .width = 2 },
|
{ .wc = 0x1F1E6, .width = 1 },
|
||||||
{ .wc = 0x1F1E7, .width = 2 },
|
{ .wc = 0x1F1E7, .width = 1 },
|
||||||
{ .wc = 0x1F1E8, .width = 2 },
|
{ .wc = 0x1F1E8, .width = 1 },
|
||||||
{ .wc = 0x1F1E9, .width = 2 },
|
{ .wc = 0x1F1E9, .width = 1 },
|
||||||
{ .wc = 0x1F1EA, .width = 2 },
|
{ .wc = 0x1F1EA, .width = 1 },
|
||||||
{ .wc = 0x1F1EB, .width = 2 },
|
{ .wc = 0x1F1EB, .width = 1 },
|
||||||
{ .wc = 0x1F1EC, .width = 2 },
|
{ .wc = 0x1F1EC, .width = 1 },
|
||||||
{ .wc = 0x1F1ED, .width = 2 },
|
{ .wc = 0x1F1ED, .width = 1 },
|
||||||
{ .wc = 0x1F1EE, .width = 2 },
|
{ .wc = 0x1F1EE, .width = 1 },
|
||||||
{ .wc = 0x1F1EF, .width = 2 },
|
{ .wc = 0x1F1EF, .width = 1 },
|
||||||
{ .wc = 0x1F1F0, .width = 2 },
|
{ .wc = 0x1F1F0, .width = 1 },
|
||||||
{ .wc = 0x1F1F1, .width = 2 },
|
{ .wc = 0x1F1F1, .width = 1 },
|
||||||
{ .wc = 0x1F1F2, .width = 2 },
|
{ .wc = 0x1F1F2, .width = 1 },
|
||||||
{ .wc = 0x1F1F3, .width = 2 },
|
{ .wc = 0x1F1F3, .width = 1 },
|
||||||
{ .wc = 0x1F1F4, .width = 2 },
|
{ .wc = 0x1F1F4, .width = 1 },
|
||||||
{ .wc = 0x1F1F5, .width = 2 },
|
{ .wc = 0x1F1F5, .width = 1 },
|
||||||
{ .wc = 0x1F1F6, .width = 2 },
|
{ .wc = 0x1F1F6, .width = 1 },
|
||||||
{ .wc = 0x1F1F7, .width = 2 },
|
{ .wc = 0x1F1F7, .width = 1 },
|
||||||
{ .wc = 0x1F1F8, .width = 2 },
|
{ .wc = 0x1F1F8, .width = 1 },
|
||||||
{ .wc = 0x1F1F9, .width = 2 },
|
{ .wc = 0x1F1F9, .width = 1 },
|
||||||
{ .wc = 0x1F1FA, .width = 2 },
|
{ .wc = 0x1F1FA, .width = 1 },
|
||||||
{ .wc = 0x1F1FB, .width = 2 },
|
{ .wc = 0x1F1FB, .width = 1 },
|
||||||
{ .wc = 0x1F1FC, .width = 2 },
|
{ .wc = 0x1F1FC, .width = 1 },
|
||||||
{ .wc = 0x1F1FD, .width = 2 },
|
{ .wc = 0x1F1FD, .width = 1 },
|
||||||
{ .wc = 0x1F1FE, .width = 2 },
|
{ .wc = 0x1F1FE, .width = 1 },
|
||||||
{ .wc = 0x1F1FF, .width = 2 },
|
{ .wc = 0x1F1FF, .width = 1 },
|
||||||
{ .wc = 0x1F385, .width = 2 },
|
{ .wc = 0x1F385, .width = 2 },
|
||||||
{ .wc = 0x1F3C2, .width = 2 },
|
{ .wc = 0x1F3C2, .width = 2 },
|
||||||
{ .wc = 0x1F3C3, .width = 2 },
|
{ .wc = 0x1F3C3, .width = 2 },
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -255,7 +256,30 @@ window_buffer_draw(__unused void *modedata, void *itemdata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
window_buffer_search(__unused void *modedata, void *itemdata, const char *ss)
|
window_buffer_find(const void *data, size_t datalen, const void *find,
|
||||||
|
size_t findlen, int icase)
|
||||||
|
{
|
||||||
|
const u_char *udata = data, *ufind = find;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
if (findlen == 0 || datalen < findlen)
|
||||||
|
return (0);
|
||||||
|
for (i = 0; i + findlen <= datalen; i++) {
|
||||||
|
for (j = 0; j < findlen; j++) {
|
||||||
|
if (!icase && udata[i + j] != ufind[j])
|
||||||
|
break;
|
||||||
|
if (icase && tolower(udata[i + j]) != tolower(ufind[j]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j == findlen)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
window_buffer_search(__unused void *modedata, void *itemdata, const char *ss,
|
||||||
|
int icase)
|
||||||
{
|
{
|
||||||
struct window_buffer_itemdata *item = itemdata;
|
struct window_buffer_itemdata *item = itemdata;
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
@@ -264,10 +288,19 @@ window_buffer_search(__unused void *modedata, void *itemdata, const char *ss)
|
|||||||
|
|
||||||
if ((pb = paste_get_name(item->name)) == NULL)
|
if ((pb = paste_get_name(item->name)) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
if (icase) {
|
||||||
|
if (strcasestr(item->name, ss) != NULL)
|
||||||
|
return (1);
|
||||||
|
bufdata = paste_buffer_data(pb, &bufsize);
|
||||||
|
return (window_buffer_find(bufdata, bufsize, ss, strlen(ss),
|
||||||
|
icase));
|
||||||
|
} else {
|
||||||
if (strstr(item->name, ss) != NULL)
|
if (strstr(item->name, ss) != NULL)
|
||||||
return (1);
|
return (1);
|
||||||
bufdata = paste_buffer_data(pb, &bufsize);
|
bufdata = paste_buffer_data(pb, &bufsize);
|
||||||
return (memmem(bufdata, bufsize, ss, strlen(ss)) != NULL);
|
return (window_buffer_find(bufdata, bufsize, ss, strlen(ss),
|
||||||
|
icase));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -234,7 +234,6 @@ struct window_copy_mode_data {
|
|||||||
|
|
||||||
struct screen *backing;
|
struct screen *backing;
|
||||||
int backing_written; /* backing display started */
|
int backing_written; /* backing display started */
|
||||||
struct screen *writing;
|
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
int viewmode; /* view mode entered */
|
int viewmode; /* view mode entered */
|
||||||
@@ -492,8 +491,6 @@ window_copy_view_init(struct window_mode_entry *wme,
|
|||||||
|
|
||||||
data->backing = xmalloc(sizeof *data->backing);
|
data->backing = xmalloc(sizeof *data->backing);
|
||||||
screen_init(data->backing, sx, screen_size_y(base), UINT_MAX);
|
screen_init(data->backing, sx, screen_size_y(base), UINT_MAX);
|
||||||
data->writing = xmalloc(sizeof *data->writing);
|
|
||||||
screen_init(data->writing, sx, screen_size_y(base), 0);
|
|
||||||
data->ictx = input_init(NULL, NULL, NULL);
|
data->ictx = input_init(NULL, NULL, NULL);
|
||||||
data->mx = data->cx;
|
data->mx = data->cx;
|
||||||
data->my = screen_hsize(data->backing) + data->cy - data->oy;
|
data->my = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
@@ -513,10 +510,6 @@ window_copy_free(struct window_mode_entry *wme)
|
|||||||
free(data->searchstr);
|
free(data->searchstr);
|
||||||
free(data->jumpchar);
|
free(data->jumpchar);
|
||||||
|
|
||||||
if (data->writing != NULL) {
|
|
||||||
screen_free(data->writing);
|
|
||||||
free(data->writing);
|
|
||||||
}
|
|
||||||
if (data->ictx != NULL)
|
if (data->ictx != NULL)
|
||||||
input_free(data->ictx);
|
input_free(data->ictx);
|
||||||
screen_free(data->backing);
|
screen_free(data->backing);
|
||||||
@@ -553,22 +546,11 @@ window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap)
|
|||||||
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
struct screen *backing = data->backing;
|
struct screen *backing = data->backing;
|
||||||
struct screen *writing = data->writing;
|
struct screen_write_ctx backing_ctx, ctx;
|
||||||
struct screen_write_ctx writing_ctx, backing_ctx, ctx;
|
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
u_int old_hsize, old_cy;
|
u_int old_hsize, old_cy;
|
||||||
u_int sx = screen_size_x(backing);
|
|
||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
if (parse) {
|
|
||||||
vasprintf(&text, fmt, ap);
|
|
||||||
screen_write_start(&writing_ctx, writing);
|
|
||||||
screen_write_reset(&writing_ctx);
|
|
||||||
input_parse_screen(data->ictx, writing, window_copy_init_ctx_cb,
|
|
||||||
data, text, strlen(text));
|
|
||||||
free(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
old_hsize = screen_hsize(data->backing);
|
old_hsize = screen_hsize(data->backing);
|
||||||
screen_write_start(&backing_ctx, backing);
|
screen_write_start(&backing_ctx, backing);
|
||||||
if (data->backing_written) {
|
if (data->backing_written) {
|
||||||
@@ -581,9 +563,12 @@ window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap)
|
|||||||
} else
|
} else
|
||||||
data->backing_written = 1;
|
data->backing_written = 1;
|
||||||
old_cy = backing->cy;
|
old_cy = backing->cy;
|
||||||
if (parse)
|
if (parse) {
|
||||||
screen_write_fast_copy(&backing_ctx, writing, 0, 0, sx, 1);
|
vasprintf(&text, fmt, ap);
|
||||||
else {
|
input_parse_screen(data->ictx, backing, window_copy_init_ctx_cb,
|
||||||
|
data, text, strlen(text));
|
||||||
|
free(text);
|
||||||
|
} else {
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
screen_write_vnputs(&backing_ctx, 0, &gc, fmt, ap);
|
screen_write_vnputs(&backing_ctx, 0, &gc, fmt, ap);
|
||||||
}
|
}
|
||||||
@@ -1512,6 +1497,28 @@ window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs)
|
|||||||
return (WINDOW_COPY_CMD_NOTHING);
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_centre_vertical(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
|
window_copy_update_cursor(wme, data->cx, wme->wp->sy / 2);
|
||||||
|
window_copy_update_selection(wme, 1, 0);
|
||||||
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_centre_horizontal(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
|
window_copy_update_cursor(wme, wme->wp->sx / 2, data->cy);
|
||||||
|
window_copy_update_selection(wme, 1, 0);
|
||||||
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
window_copy_cmd_end_of_line(struct window_copy_cmd_state *cs)
|
window_copy_cmd_end_of_line(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
@@ -1963,6 +1970,24 @@ window_copy_cmd_other_end(struct window_copy_cmd_state *cs)
|
|||||||
return (WINDOW_COPY_CMD_NOTHING);
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_selection_mode(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct options *so = cs->s->options;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
const char *s = args_string(cs->wargs, 0);
|
||||||
|
|
||||||
|
if (s == NULL || strcasecmp(s, "char") == 0 || strcasecmp(s, "c") == 0)
|
||||||
|
data->selflag = SEL_CHAR;
|
||||||
|
else if (strcasecmp(s, "word") == 0 || strcasecmp(s, "w") == 0) {
|
||||||
|
data->separators = options_get_string(so, "word-separators");
|
||||||
|
data->selflag = SEL_WORD;
|
||||||
|
} else if (strcasecmp(s, "line") == 0 || strcasecmp(s, "l") == 0)
|
||||||
|
data->selflag = SEL_LINE;
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
window_copy_cmd_page_down(struct window_copy_cmd_state *cs)
|
window_copy_cmd_page_down(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
@@ -2179,7 +2204,7 @@ static enum window_copy_cmd_action
|
|||||||
window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
|
window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
struct window_mode_entry *wme = cs->wme;
|
struct window_mode_entry *wme = cs->wme;
|
||||||
struct options *session_options = cs->s->options;
|
struct options *so = cs->s->options;
|
||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
u_int px, py, nextx, nexty;
|
u_int px, py, nextx, nexty;
|
||||||
|
|
||||||
@@ -2189,8 +2214,7 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
|
|||||||
data->dx = data->cx;
|
data->dx = data->cx;
|
||||||
data->dy = screen_hsize(data->backing) + data->cy - data->oy;
|
data->dy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
|
|
||||||
data->separators = options_get_string(session_options,
|
data->separators = options_get_string(so, "word-separators");
|
||||||
"word-separators");
|
|
||||||
window_copy_cursor_previous_word(wme, data->separators, 0);
|
window_copy_cursor_previous_word(wme, data->separators, 0);
|
||||||
px = data->cx;
|
px = data->cx;
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
@@ -2800,6 +2824,16 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_cursor_up
|
.f = window_copy_cmd_cursor_up
|
||||||
},
|
},
|
||||||
|
{ .command = "cursor-centre-vertical",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
|
.f = window_copy_cmd_centre_vertical,
|
||||||
|
},
|
||||||
|
{ .command = "cursor-centre-horizontal",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
|
.f = window_copy_cmd_centre_horizontal,
|
||||||
|
},
|
||||||
{ .command = "end-of-line",
|
{ .command = "end-of-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
@@ -3070,6 +3104,11 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_select_word
|
.f = window_copy_cmd_select_word
|
||||||
},
|
},
|
||||||
|
{ .command = "selection-mode",
|
||||||
|
.args = { "", 0, 1, NULL },
|
||||||
|
.clear = 0,
|
||||||
|
.f = window_copy_cmd_selection_mode
|
||||||
|
},
|
||||||
{ .command = "set-mark",
|
{ .command = "set-mark",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
|||||||
@@ -836,7 +836,8 @@ window_tree_draw(void *modedata, void *itemdata, struct screen_write_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
window_tree_search(__unused void *modedata, void *itemdata, const char *ss)
|
window_tree_search(__unused void *modedata, void *itemdata, const char *ss,
|
||||||
|
int icase)
|
||||||
{
|
{
|
||||||
struct window_tree_itemdata *item = itemdata;
|
struct window_tree_itemdata *item = itemdata;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
@@ -853,10 +854,14 @@ window_tree_search(__unused void *modedata, void *itemdata, const char *ss)
|
|||||||
case WINDOW_TREE_SESSION:
|
case WINDOW_TREE_SESSION:
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
if (icase)
|
||||||
|
return (strcasestr(s->name, ss) != NULL);
|
||||||
return (strstr(s->name, ss) != NULL);
|
return (strstr(s->name, ss) != NULL);
|
||||||
case WINDOW_TREE_WINDOW:
|
case WINDOW_TREE_WINDOW:
|
||||||
if (s == NULL || wl == NULL)
|
if (s == NULL || wl == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
if (icase)
|
||||||
|
return (strcasestr(wl->window->name, ss) != NULL);
|
||||||
return (strstr(wl->window->name, ss) != NULL);
|
return (strstr(wl->window->name, ss) != NULL);
|
||||||
case WINDOW_TREE_PANE:
|
case WINDOW_TREE_PANE:
|
||||||
if (s == NULL || wl == NULL || wp == NULL)
|
if (s == NULL || wl == NULL || wp == NULL)
|
||||||
@@ -866,6 +871,9 @@ window_tree_search(__unused void *modedata, void *itemdata, const char *ss)
|
|||||||
free(cmd);
|
free(cmd);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
if (icase)
|
||||||
|
retval = (strcasestr(cmd, ss) != NULL);
|
||||||
|
else
|
||||||
retval = (strstr(cmd, ss) != NULL);
|
retval = (strstr(cmd, ss) != NULL);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return (retval);
|
return (retval);
|
||||||
|
|||||||
2
window.c
2
window.c
@@ -1979,6 +1979,8 @@ window_pane_get_theme(struct window_pane *wp)
|
|||||||
void
|
void
|
||||||
window_pane_send_theme_update(struct window_pane *wp)
|
window_pane_send_theme_update(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
|
if (wp == NULL || window_pane_exited(wp))
|
||||||
|
return;
|
||||||
if (~wp->flags & PANE_THEMECHANGED)
|
if (~wp->flags & PANE_THEMECHANGED)
|
||||||
return;
|
return;
|
||||||
if (~wp->screen->mode & MODE_THEME_UPDATES)
|
if (~wp->screen->mode & MODE_THEME_UPDATES)
|
||||||
|
|||||||
Reference in New Issue
Block a user