mirror of
https://github.com/tmux/tmux.git
synced 2026-04-16 03:56:28 +00:00
Merge.
This commit is contained in:
12
Makefile.am
12
Makefile.am
@@ -240,9 +240,19 @@ dist_tmux_SOURCES += image.c image-sixel.c
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if NEED_FUZZING
|
if NEED_FUZZING
|
||||||
check_PROGRAMS = fuzz/input-fuzzer
|
check_PROGRAMS = \
|
||||||
|
fuzz/input-fuzzer \
|
||||||
|
fuzz/cmd-parse-fuzzer \
|
||||||
|
fuzz/format-fuzzer \
|
||||||
|
fuzz/style-fuzzer
|
||||||
fuzz_input_fuzzer_LDFLAGS = $(FUZZING_LIBS)
|
fuzz_input_fuzzer_LDFLAGS = $(FUZZING_LIBS)
|
||||||
fuzz_input_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
|
fuzz_input_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
|
||||||
|
fuzz_cmd_parse_fuzzer_LDFLAGS = $(FUZZING_LIBS)
|
||||||
|
fuzz_cmd_parse_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
|
||||||
|
fuzz_format_fuzzer_LDFLAGS = $(FUZZING_LIBS)
|
||||||
|
fuzz_format_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
|
||||||
|
fuzz_style_fuzzer_LDFLAGS = $(FUZZING_LIBS)
|
||||||
|
fuzz_style_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Install tmux.1 in the right format.
|
# Install tmux.1 in the right format.
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ cmd_list_keys_get_table_width(struct key_binding **l, u_int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct key_binding **
|
static struct key_binding **
|
||||||
cmd_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
|
cmd_list_keys_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
|
||||||
{
|
{
|
||||||
const char *tables[] = { "prefix", "root" };
|
const char *tables[] = { "prefix", "root" };
|
||||||
struct key_table *t;
|
struct key_table *t;
|
||||||
@@ -119,7 +119,7 @@ cmd_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_filter_key_list(int filter_notes, int filter_key, key_code only,
|
cmd_list_keys_filter_key_list(int filter_notes, int filter_key, key_code only,
|
||||||
struct key_binding **l, u_int *n)
|
struct key_binding **l, u_int *n)
|
||||||
{
|
{
|
||||||
key_code key;
|
key_code key;
|
||||||
@@ -137,10 +137,10 @@ cmd_filter_key_list(int filter_notes, int filter_key, key_code only,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_format_add_key_binding(struct format_tree *ft,
|
cmd_list_keys_format_add_key_binding(struct format_tree *ft,
|
||||||
const struct key_binding *bd, const char *prefix)
|
const struct key_binding *bd, const char *prefix)
|
||||||
{
|
{
|
||||||
const char *s;
|
char *s;
|
||||||
|
|
||||||
if (bd->flags & KEY_BINDING_REPEAT)
|
if (bd->flags & KEY_BINDING_REPEAT)
|
||||||
format_add(ft, "key_repeat", "1");
|
format_add(ft, "key_repeat", "1");
|
||||||
@@ -155,12 +155,12 @@ cmd_format_add_key_binding(struct format_tree *ft,
|
|||||||
format_add(ft, "key_prefix", "%s", prefix);
|
format_add(ft, "key_prefix", "%s", prefix);
|
||||||
format_add(ft, "key_table", "%s", bd->tablename);
|
format_add(ft, "key_table", "%s", bd->tablename);
|
||||||
|
|
||||||
s = key_string_lookup_key(bd->key, 0);
|
format_add(ft, "key_string", "%s", key_string_lookup_key(bd->key, 0));
|
||||||
format_add(ft, "key_string", "%s", s);
|
|
||||||
|
|
||||||
s = cmd_list_print(bd->cmdlist,
|
s = cmd_list_print(bd->cmdlist, CMD_LIST_PRINT_ESCAPED|
|
||||||
CMD_LIST_PRINT_ESCAPED|CMD_LIST_PRINT_NO_GROUPS);
|
CMD_LIST_PRINT_NO_GROUPS);
|
||||||
format_add(ft, "key_command", "%s", s);
|
format_add(ft, "key_command", "%s", s);
|
||||||
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
@@ -213,14 +213,16 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (table)
|
if (table)
|
||||||
l = sort_get_key_bindings_table(table, &n, &sort_crit);
|
l = sort_get_key_bindings_table(table, &n, &sort_crit);
|
||||||
else if (notes_only)
|
else if (notes_only)
|
||||||
l = cmd_get_root_and_prefix(&n, &sort_crit);
|
l = cmd_list_keys_get_root_and_prefix(&n, &sort_crit);
|
||||||
else
|
else
|
||||||
l = sort_get_key_bindings(&n, &sort_crit);
|
l = sort_get_key_bindings(&n, &sort_crit);
|
||||||
|
|
||||||
filter_notes = notes_only && !args_has(args, 'a');
|
filter_notes = notes_only && !args_has(args, 'a');
|
||||||
filter_key = only != KEYC_UNKNOWN;
|
filter_key = only != KEYC_UNKNOWN;
|
||||||
if (filter_notes || filter_key)
|
if (filter_notes || filter_key) {
|
||||||
cmd_filter_key_list(filter_notes, filter_key, only, l, &n);
|
cmd_list_keys_filter_key_list(filter_notes, filter_key, only, l,
|
||||||
|
&n);
|
||||||
|
}
|
||||||
if (single)
|
if (single)
|
||||||
n = 1;
|
n = 1;
|
||||||
|
|
||||||
@@ -232,7 +234,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
format_add(ft, "key_table_width", "%u",
|
format_add(ft, "key_table_width", "%u",
|
||||||
cmd_list_keys_get_table_width(l, n));
|
cmd_list_keys_get_table_width(l, n));
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
cmd_format_add_key_binding(ft, l[i], prefix);
|
cmd_list_keys_format_add_key_binding(ft, l[i], prefix);
|
||||||
|
|
||||||
line = format_expand(ft, template);
|
line = format_expand(ft, template);
|
||||||
if ((single && tc != NULL) || n == 1)
|
if ((single && tc != NULL) || n == 1)
|
||||||
|
|||||||
2
cmd.c
2
cmd.c
@@ -313,6 +313,8 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
|
|||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
if (argc < 0 || argc > 1000)
|
||||||
|
return (-1);
|
||||||
*argv = xcalloc(argc, sizeof **argv);
|
*argv = xcalloc(argc, sizeof **argv);
|
||||||
|
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ format_is_type(struct format_range *fr, struct style *sy)
|
|||||||
case STYLE_RANGE_NONE:
|
case STYLE_RANGE_NONE:
|
||||||
case STYLE_RANGE_LEFT:
|
case STYLE_RANGE_LEFT:
|
||||||
case STYLE_RANGE_RIGHT:
|
case STYLE_RANGE_RIGHT:
|
||||||
|
case STYLE_RANGE_CONTROL:
|
||||||
return (1);
|
return (1);
|
||||||
case STYLE_RANGE_PANE:
|
case STYLE_RANGE_PANE:
|
||||||
case STYLE_RANGE_WINDOW:
|
case STYLE_RANGE_WINDOW:
|
||||||
@@ -1065,6 +1066,10 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
log_debug("%s: range user|%u at %u-%u", __func__,
|
log_debug("%s: range user|%u at %u-%u", __func__,
|
||||||
sr->argument, sr->start, sr->end);
|
sr->argument, sr->start, sr->end);
|
||||||
break;
|
break;
|
||||||
|
case STYLE_RANGE_CONTROL:
|
||||||
|
log_debug("%s: range control|%u at %u-%u", __func__,
|
||||||
|
sr->argument, sr->start, sr->end);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
format_free_range(&frs, fr);
|
format_free_range(&frs, fr);
|
||||||
}
|
}
|
||||||
@@ -1116,7 +1121,7 @@ format_width(const char *expanded)
|
|||||||
/*
|
/*
|
||||||
* Trim on the left, taking #[] into account. Note, we copy the whole set of
|
* Trim on the left, taking #[] into account. Note, we copy the whole set of
|
||||||
* unescaped #s, but only add their escaped size to width. This is because the
|
* unescaped #s, but only add their escaped size to width. This is because the
|
||||||
* format_draw function will actually do the escaping when it runs
|
* format_draw function will actually do the escaping.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
format_trim_left(const char *expanded, u_int limit)
|
format_trim_left(const char *expanded, u_int limit)
|
||||||
|
|||||||
96
format.c
96
format.c
@@ -84,6 +84,12 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
|||||||
return (strcmp(fj1->cmd, fj2->cmd));
|
return (strcmp(fj1->cmd, fj2->cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Maimum pad and trim width. */
|
||||||
|
#define FORMAT_MAX_WIDTH 10000
|
||||||
|
|
||||||
|
/* Maimum repeat size. */
|
||||||
|
#define FORMAT_MAX_REPEAT 10000
|
||||||
|
|
||||||
/* Format modifiers. */
|
/* Format modifiers. */
|
||||||
#define FORMAT_TIMESTRING 0x1
|
#define FORMAT_TIMESTRING 0x1
|
||||||
#define FORMAT_BASENAME 0x2
|
#define FORMAT_BASENAME 0x2
|
||||||
@@ -1009,7 +1015,7 @@ static void *
|
|||||||
format_cb_pane_flags(struct format_tree *ft)
|
format_cb_pane_flags(struct format_tree *ft)
|
||||||
{
|
{
|
||||||
if (ft->wp != NULL)
|
if (ft->wp != NULL)
|
||||||
return (xstrdup(window_pane_printable_flags(ft->wp, 1)));
|
return (xstrdup(window_pane_printable_flags(ft->wp)));
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1344,6 +1350,8 @@ format_cb_mouse_status_range(struct format_tree *ft)
|
|||||||
return (xstrdup("session"));
|
return (xstrdup("session"));
|
||||||
case STYLE_RANGE_USER:
|
case STYLE_RANGE_USER:
|
||||||
return (xstrdup(sr->string));
|
return (xstrdup(sr->string));
|
||||||
|
case STYLE_RANGE_CONTROL:
|
||||||
|
return (xstrdup("control"));
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@@ -1378,6 +1386,18 @@ format_cb_alternate_saved_y(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for bracket_paste_flag. */
|
||||||
|
static void *
|
||||||
|
format_cb_bracket_paste_flag(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
if (ft->wp != NULL && ft->wp->screen != NULL) {
|
||||||
|
if (ft->wp->screen->mode & MODE_BRACKETPASTE)
|
||||||
|
return (xstrdup("1"));
|
||||||
|
return (xstrdup("0"));
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for buffer_name. */
|
/* Callback for buffer_name. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_buffer_name(struct format_tree *ft)
|
format_cb_buffer_name(struct format_tree *ft)
|
||||||
@@ -1616,9 +1636,13 @@ format_cb_client_user(struct format_tree *ft)
|
|||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if (ft->c != NULL) {
|
if (ft->c != NULL) {
|
||||||
|
if (ft->c->user != NULL)
|
||||||
|
return (xstrdup(ft->c->user));
|
||||||
uid = proc_get_peer_uid(ft->c->peer);
|
uid = proc_get_peer_uid(ft->c->peer);
|
||||||
if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL)
|
if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL) {
|
||||||
return (xstrdup(pw->pw_name));
|
ft->c->user = xstrdup(pw->pw_name);
|
||||||
|
return (xstrdup(ft->c->user));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@@ -2288,6 +2312,38 @@ format_cb_pane_pipe_pid(struct format_tree *ft)
|
|||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for pane_pb_progress. */
|
||||||
|
static void *
|
||||||
|
format_cb_pane_pb_progress(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
char *value = NULL;
|
||||||
|
|
||||||
|
if (ft->wp != NULL)
|
||||||
|
xasprintf(&value, "%d", ft->wp->base.progress_bar.progress);
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callback for pane_pb_state. */
|
||||||
|
static void *
|
||||||
|
format_cb_pane_pb_state(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
if (ft->wp != NULL) {
|
||||||
|
switch (ft->wp->base.progress_bar.state) {
|
||||||
|
case PROGRESS_BAR_HIDDEN:
|
||||||
|
return xstrdup("hidden");
|
||||||
|
case PROGRESS_BAR_NORMAL:
|
||||||
|
return xstrdup("normal");
|
||||||
|
case PROGRESS_BAR_ERROR:
|
||||||
|
return xstrdup("error");
|
||||||
|
case PROGRESS_BAR_INDETERMINATE:
|
||||||
|
return xstrdup("indeterminate");
|
||||||
|
case PROGRESS_BAR_PAUSED:
|
||||||
|
return xstrdup("paused");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for pane_right. */
|
/* Callback for pane_right. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_pane_right(struct format_tree *ft)
|
format_cb_pane_right(struct format_tree *ft)
|
||||||
@@ -3063,10 +3119,13 @@ format_cb_uid(__unused struct format_tree *ft)
|
|||||||
static void *
|
static void *
|
||||||
format_cb_user(__unused struct format_tree *ft)
|
format_cb_user(__unused struct format_tree *ft)
|
||||||
{
|
{
|
||||||
|
static char *cached;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if ((pw = getpwuid(getuid())) != NULL)
|
if (cached == NULL && (pw = getpwuid(getuid())) != NULL)
|
||||||
return (xstrdup(pw->pw_name));
|
cached = xstrdup(pw->pw_name);
|
||||||
|
if (cached != NULL)
|
||||||
|
return (xstrdup(cached));
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3101,6 +3160,9 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "alternate_saved_y", FORMAT_TABLE_STRING,
|
{ "alternate_saved_y", FORMAT_TABLE_STRING,
|
||||||
format_cb_alternate_saved_y
|
format_cb_alternate_saved_y
|
||||||
},
|
},
|
||||||
|
{ "bracket_paste_flag", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_bracket_paste_flag
|
||||||
|
},
|
||||||
{ "buffer_created", FORMAT_TABLE_TIME,
|
{ "buffer_created", FORMAT_TABLE_TIME,
|
||||||
format_cb_buffer_created
|
format_cb_buffer_created
|
||||||
},
|
},
|
||||||
@@ -3395,6 +3457,12 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "pane_path", FORMAT_TABLE_STRING,
|
{ "pane_path", FORMAT_TABLE_STRING,
|
||||||
format_cb_pane_path
|
format_cb_pane_path
|
||||||
},
|
},
|
||||||
|
{ "pane_pb_progress", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_pane_pb_progress
|
||||||
|
},
|
||||||
|
{ "pane_pb_state", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_pane_pb_state
|
||||||
|
},
|
||||||
{ "pane_pid", FORMAT_TABLE_STRING,
|
{ "pane_pid", FORMAT_TABLE_STRING,
|
||||||
format_cb_pane_pid
|
format_cb_pane_pid
|
||||||
},
|
},
|
||||||
@@ -4256,6 +4324,8 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
|||||||
/* Skip any separator character. */
|
/* Skip any separator character. */
|
||||||
if (*cp == ';')
|
if (*cp == ';')
|
||||||
cp++;
|
cp++;
|
||||||
|
if (*cp == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
/* Check single character modifiers with no arguments. */
|
/* Check single character modifiers with no arguments. */
|
||||||
if (strchr("labcdnwETSWPL!<>", cp[0]) != NULL &&
|
if (strchr("labcdnwETSWPL!<>", cp[0]) != NULL &&
|
||||||
@@ -4816,7 +4886,7 @@ format_replace_expression(struct format_modifier *mexp,
|
|||||||
|
|
||||||
/* The third argument may be precision. */
|
/* The third argument may be precision. */
|
||||||
if (argc >= 3) {
|
if (argc >= 3) {
|
||||||
prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr);
|
prec = strtonum(mexp->argv[2], INT_MIN + 1, INT_MAX, &errstr);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
format_log(es, "expression precision %s: %s", errstr,
|
format_log(es, "expression precision %s: %s", errstr,
|
||||||
mexp->argv[2]);
|
mexp->argv[2]);
|
||||||
@@ -4961,8 +5031,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case '=':
|
case '=':
|
||||||
if (fm->argc < 1)
|
if (fm->argc < 1)
|
||||||
break;
|
break;
|
||||||
limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
|
limit = strtonum(fm->argv[0], -FORMAT_MAX_WIDTH,
|
||||||
&errstr);
|
FORMAT_MAX_WIDTH, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
limit = 0;
|
limit = 0;
|
||||||
if (fm->argc >= 2 && fm->argv[1] != NULL)
|
if (fm->argc >= 2 && fm->argv[1] != NULL)
|
||||||
@@ -4971,8 +5041,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'p':
|
case 'p':
|
||||||
if (fm->argc < 1)
|
if (fm->argc < 1)
|
||||||
break;
|
break;
|
||||||
width = strtonum(fm->argv[0], INT_MIN, INT_MAX,
|
width = strtonum(fm->argv[0], -FORMAT_MAX_WIDTH,
|
||||||
&errstr);
|
FORMAT_MAX_WIDTH, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
width = 0;
|
width = 0;
|
||||||
break;
|
break;
|
||||||
@@ -5195,7 +5265,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
format_log(es, "repeat syntax error: %s", copy);
|
format_log(es, "repeat syntax error: %s", copy);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
nrep = strtonum(right, 1, 10000, &errstr);
|
nrep = strtonum(right, 1, FORMAT_MAX_REPEAT, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
value = xstrdup("");
|
value = xstrdup("");
|
||||||
else {
|
else {
|
||||||
@@ -5390,6 +5460,7 @@ done:
|
|||||||
if (marker != NULL && strcmp(new, value) != 0) {
|
if (marker != NULL && strcmp(new, value) != 0) {
|
||||||
free(value);
|
free(value);
|
||||||
xasprintf(&value, "%s%s", new, marker);
|
xasprintf(&value, "%s%s", new, marker);
|
||||||
|
free(new);
|
||||||
} else {
|
} else {
|
||||||
free(value);
|
free(value);
|
||||||
value = new;
|
value = new;
|
||||||
@@ -5400,6 +5471,7 @@ done:
|
|||||||
if (marker != NULL && strcmp(new, value) != 0) {
|
if (marker != NULL && strcmp(new, value) != 0) {
|
||||||
free(value);
|
free(value);
|
||||||
xasprintf(&value, "%s%s", marker, new);
|
xasprintf(&value, "%s%s", marker, new);
|
||||||
|
free(new);
|
||||||
} else {
|
} else {
|
||||||
free(value);
|
free(value);
|
||||||
value = new;
|
value = new;
|
||||||
@@ -5512,7 +5584,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
|||||||
buf[off++] = *fmt++;
|
buf[off++] = *fmt++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*fmt++ == '\0')
|
if (*++fmt == '\0')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ch = (u_char)*fmt++;
|
ch = (u_char)*fmt++;
|
||||||
|
|||||||
83
fuzz/cmd-parse-fuzzer.c
Normal file
83
fuzz/cmd-parse-fuzzer.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026 David Korczynski <david@adalogics.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fuzz the tmux command parser (cmd_parse_from_buffer).
|
||||||
|
*
|
||||||
|
* This exercises:
|
||||||
|
* - cmd-parse.y (yacc grammar, lexer, command building)
|
||||||
|
* - cmd.c (command lookup and validation)
|
||||||
|
* - arguments.c (argument parsing and flag handling)
|
||||||
|
* - cmd-find.c (target resolution)
|
||||||
|
* - options.c (option name lookups during parsing)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
struct event_base *libevent;
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerTestOneInput(const u_char *data, size_t size)
|
||||||
|
{
|
||||||
|
struct cmd_parse_input pi;
|
||||||
|
struct cmd_parse_result *pr;
|
||||||
|
|
||||||
|
if (size > 2048 || size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset(&pi, 0, sizeof pi);
|
||||||
|
pi.flags = CMD_PARSE_QUIET;
|
||||||
|
|
||||||
|
pr = cmd_parse_from_buffer(data, size, &pi);
|
||||||
|
switch (pr->status) {
|
||||||
|
case CMD_PARSE_SUCCESS:
|
||||||
|
cmd_list_free(pr->cmdlist);
|
||||||
|
break;
|
||||||
|
case CMD_PARSE_ERROR:
|
||||||
|
free(pr->error);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
|
||||||
|
{
|
||||||
|
const struct options_table_entry *oe;
|
||||||
|
|
||||||
|
global_environ = environ_create();
|
||||||
|
global_options = options_create(NULL);
|
||||||
|
global_s_options = options_create(NULL);
|
||||||
|
global_w_options = options_create(NULL);
|
||||||
|
for (oe = options_table; oe->name != NULL; oe++) {
|
||||||
|
if (oe->scope & OPTIONS_TABLE_SERVER)
|
||||||
|
options_default(global_options, oe);
|
||||||
|
if (oe->scope & OPTIONS_TABLE_SESSION)
|
||||||
|
options_default(global_s_options, oe);
|
||||||
|
if (oe->scope & OPTIONS_TABLE_WINDOW)
|
||||||
|
options_default(global_w_options, oe);
|
||||||
|
}
|
||||||
|
libevent = osdep_event_init();
|
||||||
|
socket_path = xstrdup("dummy");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
133
fuzz/cmd-parse-fuzzer.dict
Normal file
133
fuzz/cmd-parse-fuzzer.dict
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# tmux command names
|
||||||
|
"set-option"
|
||||||
|
"bind-key"
|
||||||
|
"unbind-key"
|
||||||
|
"send-keys"
|
||||||
|
"new-session"
|
||||||
|
"new-window"
|
||||||
|
"split-window"
|
||||||
|
"select-window"
|
||||||
|
"select-pane"
|
||||||
|
"kill-pane"
|
||||||
|
"kill-window"
|
||||||
|
"kill-session"
|
||||||
|
"kill-server"
|
||||||
|
"list-sessions"
|
||||||
|
"list-windows"
|
||||||
|
"list-panes"
|
||||||
|
"list-keys"
|
||||||
|
"list-buffers"
|
||||||
|
"list-clients"
|
||||||
|
"list-commands"
|
||||||
|
"attach-session"
|
||||||
|
"detach-client"
|
||||||
|
"switch-client"
|
||||||
|
"rename-session"
|
||||||
|
"rename-window"
|
||||||
|
"resize-pane"
|
||||||
|
"resize-window"
|
||||||
|
"display-message"
|
||||||
|
"display-menu"
|
||||||
|
"display-popup"
|
||||||
|
"display-panes"
|
||||||
|
"copy-mode"
|
||||||
|
"paste-buffer"
|
||||||
|
"capture-pane"
|
||||||
|
"save-buffer"
|
||||||
|
"load-buffer"
|
||||||
|
"set-buffer"
|
||||||
|
"delete-buffer"
|
||||||
|
"show-buffer"
|
||||||
|
"choose-buffer"
|
||||||
|
"choose-tree"
|
||||||
|
"choose-client"
|
||||||
|
"if-shell"
|
||||||
|
"run-shell"
|
||||||
|
"source-file"
|
||||||
|
"command-prompt"
|
||||||
|
"confirm-before"
|
||||||
|
"pipe-pane"
|
||||||
|
"wait-for"
|
||||||
|
"set-environment"
|
||||||
|
"show-environment"
|
||||||
|
"set-hook"
|
||||||
|
"show-hooks"
|
||||||
|
"show-messages"
|
||||||
|
"show-options"
|
||||||
|
"set-window-option"
|
||||||
|
"show-window-options"
|
||||||
|
"clear-history"
|
||||||
|
"clock-mode"
|
||||||
|
"find-window"
|
||||||
|
"join-pane"
|
||||||
|
"move-pane"
|
||||||
|
"break-pane"
|
||||||
|
"swap-pane"
|
||||||
|
"swap-window"
|
||||||
|
"move-window"
|
||||||
|
"link-window"
|
||||||
|
"unlink-window"
|
||||||
|
"rotate-window"
|
||||||
|
"next-window"
|
||||||
|
"previous-window"
|
||||||
|
"last-window"
|
||||||
|
"last-pane"
|
||||||
|
"next-layout"
|
||||||
|
"previous-layout"
|
||||||
|
"select-layout"
|
||||||
|
"customize-mode"
|
||||||
|
"refresh-client"
|
||||||
|
"suspend-client"
|
||||||
|
"lock-client"
|
||||||
|
"lock-server"
|
||||||
|
"lock-session"
|
||||||
|
"respawn-pane"
|
||||||
|
"respawn-window"
|
||||||
|
"start-server"
|
||||||
|
"server-access"
|
||||||
|
"send-prefix"
|
||||||
|
"clear-prompt-history"
|
||||||
|
"show-prompt-history"
|
||||||
|
|
||||||
|
# Common flags and syntax
|
||||||
|
"-t"
|
||||||
|
"-s"
|
||||||
|
"-g"
|
||||||
|
"-w"
|
||||||
|
"-p"
|
||||||
|
"-a"
|
||||||
|
"-o"
|
||||||
|
"-q"
|
||||||
|
"-u"
|
||||||
|
"-F"
|
||||||
|
"-f"
|
||||||
|
"-b"
|
||||||
|
"-d"
|
||||||
|
"-e"
|
||||||
|
"-n"
|
||||||
|
"-r"
|
||||||
|
|
||||||
|
# Targets and option names
|
||||||
|
"status"
|
||||||
|
"default"
|
||||||
|
"mouse"
|
||||||
|
"on"
|
||||||
|
"off"
|
||||||
|
"vi"
|
||||||
|
"emacs"
|
||||||
|
"set -g"
|
||||||
|
"set -s"
|
||||||
|
"setw"
|
||||||
|
"bind"
|
||||||
|
"unbind"
|
||||||
|
|
||||||
|
# Syntax elements
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
";"
|
||||||
|
"#{"
|
||||||
|
"%if"
|
||||||
|
"%elif"
|
||||||
|
"%else"
|
||||||
|
"%endif"
|
||||||
|
"%hidden"
|
||||||
2
fuzz/cmd-parse-fuzzer.options
Normal file
2
fuzz/cmd-parse-fuzzer.options
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[libfuzzer]
|
||||||
|
max_len = 2048
|
||||||
88
fuzz/format-fuzzer.c
Normal file
88
fuzz/format-fuzzer.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026 David Korczynski <david@adalogics.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fuzz the tmux format string expander (format_expand).
|
||||||
|
*
|
||||||
|
* This exercises:
|
||||||
|
* - format.c (format parsing, modifier chains, conditionals, math, regex)
|
||||||
|
* - colour.c (colour name and RGB parsing within formats)
|
||||||
|
* - utf8.c (UTF-8 width calculations in format padding)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
struct event_base *libevent;
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerTestOneInput(const u_char *data, size_t size)
|
||||||
|
{
|
||||||
|
struct format_tree *ft;
|
||||||
|
char *buf, *expanded;
|
||||||
|
|
||||||
|
if (size > 2048 || size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Null-terminate the input for format_expand. */
|
||||||
|
buf = malloc(size + 1);
|
||||||
|
if (buf == NULL)
|
||||||
|
return 0;
|
||||||
|
memcpy(buf, data, size);
|
||||||
|
buf[size] = '\0';
|
||||||
|
|
||||||
|
ft = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
|
||||||
|
format_add(ft, "session_name", "%s", "fuzz-session");
|
||||||
|
format_add(ft, "window_index", "%d", 0);
|
||||||
|
format_add(ft, "window_name", "%s", "fuzz-window");
|
||||||
|
format_add(ft, "pane_index", "%d", 0);
|
||||||
|
format_add(ft, "pane_id", "%s", "%%0");
|
||||||
|
format_add(ft, "host", "%s", "fuzzhost");
|
||||||
|
format_add(ft, "pane_width", "%d", 80);
|
||||||
|
format_add(ft, "pane_height", "%d", 25);
|
||||||
|
|
||||||
|
expanded = format_expand(ft, buf);
|
||||||
|
free(expanded);
|
||||||
|
format_free(ft);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
|
||||||
|
{
|
||||||
|
const struct options_table_entry *oe;
|
||||||
|
|
||||||
|
global_environ = environ_create();
|
||||||
|
global_options = options_create(NULL);
|
||||||
|
global_s_options = options_create(NULL);
|
||||||
|
global_w_options = options_create(NULL);
|
||||||
|
for (oe = options_table; oe->name != NULL; oe++) {
|
||||||
|
if (oe->scope & OPTIONS_TABLE_SERVER)
|
||||||
|
options_default(global_options, oe);
|
||||||
|
if (oe->scope & OPTIONS_TABLE_SESSION)
|
||||||
|
options_default(global_s_options, oe);
|
||||||
|
if (oe->scope & OPTIONS_TABLE_WINDOW)
|
||||||
|
options_default(global_w_options, oe);
|
||||||
|
}
|
||||||
|
libevent = osdep_event_init();
|
||||||
|
socket_path = xstrdup("dummy");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
71
fuzz/format-fuzzer.dict
Normal file
71
fuzz/format-fuzzer.dict
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Format expansion syntax
|
||||||
|
"#{"
|
||||||
|
"}"
|
||||||
|
"#{?"
|
||||||
|
"#{=="
|
||||||
|
"#{!="
|
||||||
|
"#{<"
|
||||||
|
"#{>"
|
||||||
|
"#{m:"
|
||||||
|
"#{C:"
|
||||||
|
"#{s/"
|
||||||
|
"#{t:"
|
||||||
|
"#{T:"
|
||||||
|
"#{E:"
|
||||||
|
"#{S:"
|
||||||
|
"#{W:"
|
||||||
|
"#{P:"
|
||||||
|
"##"
|
||||||
|
|
||||||
|
# Common format modifiers
|
||||||
|
"b:"
|
||||||
|
"d:"
|
||||||
|
"q:"
|
||||||
|
"l:"
|
||||||
|
"e:"
|
||||||
|
"t:"
|
||||||
|
"p:"
|
||||||
|
"w:"
|
||||||
|
"n:"
|
||||||
|
"a:"
|
||||||
|
"=:"
|
||||||
|
"||"
|
||||||
|
"&&"
|
||||||
|
","
|
||||||
|
"#{e|"
|
||||||
|
"#{p-1:"
|
||||||
|
"#{=/10/...:"
|
||||||
|
|
||||||
|
# Format variables
|
||||||
|
"session_name"
|
||||||
|
"window_index"
|
||||||
|
"window_name"
|
||||||
|
"pane_index"
|
||||||
|
"pane_id"
|
||||||
|
"host"
|
||||||
|
"pane_width"
|
||||||
|
"pane_height"
|
||||||
|
"pane_current_command"
|
||||||
|
"pane_pid"
|
||||||
|
"session_id"
|
||||||
|
"window_id"
|
||||||
|
"client_name"
|
||||||
|
"version"
|
||||||
|
"line"
|
||||||
|
|
||||||
|
# Conditionals
|
||||||
|
"#{?pane_active,"
|
||||||
|
",}"
|
||||||
|
"#{?#{==:"
|
||||||
|
|
||||||
|
# Math and comparison
|
||||||
|
"#{e|+:"
|
||||||
|
"#{e|-:"
|
||||||
|
"#{e|*:"
|
||||||
|
"#{e|/:"
|
||||||
|
"#{e|%:"
|
||||||
|
|
||||||
|
# Nested
|
||||||
|
"#{="
|
||||||
|
"#{"
|
||||||
|
"#{l:"
|
||||||
2
fuzz/format-fuzzer.options
Normal file
2
fuzz/format-fuzzer.options
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[libfuzzer]
|
||||||
|
max_len = 2048
|
||||||
79
fuzz/style-fuzzer.c
Normal file
79
fuzz/style-fuzzer.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026 David Korczynski <david@adalogics.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fuzz the tmux style parser (style_parse).
|
||||||
|
*
|
||||||
|
* This exercises:
|
||||||
|
* - style.c (style string parsing, alignment, ranges)
|
||||||
|
* - colour.c (colour name, RGB, and indexed colour parsing)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
struct event_base *libevent;
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerTestOneInput(const u_char *data, size_t size)
|
||||||
|
{
|
||||||
|
struct style sy;
|
||||||
|
struct grid_cell gc;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
if (size > 512 || size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Null-terminate the input for style_parse. */
|
||||||
|
buf = malloc(size + 1);
|
||||||
|
if (buf == NULL)
|
||||||
|
return 0;
|
||||||
|
memcpy(buf, data, size);
|
||||||
|
buf[size] = '\0';
|
||||||
|
|
||||||
|
memset(&gc, 0, sizeof gc);
|
||||||
|
style_set(&sy, &gc);
|
||||||
|
|
||||||
|
style_parse(&sy, &gc, buf);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
|
||||||
|
{
|
||||||
|
const struct options_table_entry *oe;
|
||||||
|
|
||||||
|
global_environ = environ_create();
|
||||||
|
global_options = options_create(NULL);
|
||||||
|
global_s_options = options_create(NULL);
|
||||||
|
global_w_options = options_create(NULL);
|
||||||
|
for (oe = options_table; oe->name != NULL; oe++) {
|
||||||
|
if (oe->scope & OPTIONS_TABLE_SERVER)
|
||||||
|
options_default(global_options, oe);
|
||||||
|
if (oe->scope & OPTIONS_TABLE_SESSION)
|
||||||
|
options_default(global_s_options, oe);
|
||||||
|
if (oe->scope & OPTIONS_TABLE_WINDOW)
|
||||||
|
options_default(global_w_options, oe);
|
||||||
|
}
|
||||||
|
libevent = osdep_event_init();
|
||||||
|
socket_path = xstrdup("dummy");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
73
fuzz/style-fuzzer.dict
Normal file
73
fuzz/style-fuzzer.dict
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Style attributes
|
||||||
|
"default"
|
||||||
|
"ignore"
|
||||||
|
"nodefaults"
|
||||||
|
"bright"
|
||||||
|
"bold"
|
||||||
|
"dim"
|
||||||
|
"underscore"
|
||||||
|
"blink"
|
||||||
|
"reverse"
|
||||||
|
"hidden"
|
||||||
|
"italics"
|
||||||
|
"overline"
|
||||||
|
"strikethrough"
|
||||||
|
"double-underscore"
|
||||||
|
"curly-underscore"
|
||||||
|
"dotted-underscore"
|
||||||
|
"dashed-underscore"
|
||||||
|
"nobright"
|
||||||
|
"nobold"
|
||||||
|
"nodim"
|
||||||
|
"nounderscore"
|
||||||
|
"noblink"
|
||||||
|
"noreverse"
|
||||||
|
"nohidden"
|
||||||
|
"noitalics"
|
||||||
|
"nooverline"
|
||||||
|
"nostrikethrough"
|
||||||
|
|
||||||
|
# Colours
|
||||||
|
"fg="
|
||||||
|
"bg="
|
||||||
|
"us="
|
||||||
|
"fill="
|
||||||
|
"colour0"
|
||||||
|
"colour255"
|
||||||
|
"red"
|
||||||
|
"green"
|
||||||
|
"blue"
|
||||||
|
"yellow"
|
||||||
|
"cyan"
|
||||||
|
"magenta"
|
||||||
|
"white"
|
||||||
|
"black"
|
||||||
|
|
||||||
|
# RGB and hex
|
||||||
|
"#ff0000"
|
||||||
|
"#00ff00"
|
||||||
|
"#0000ff"
|
||||||
|
|
||||||
|
# Alignment and ranges
|
||||||
|
"align=left"
|
||||||
|
"align=centre"
|
||||||
|
"align=right"
|
||||||
|
"align=absolute-centre"
|
||||||
|
"list=on"
|
||||||
|
"list=focus"
|
||||||
|
"list=left-marker"
|
||||||
|
"list=right-marker"
|
||||||
|
"range=left"
|
||||||
|
"range=right"
|
||||||
|
"range=pane"
|
||||||
|
"range=window"
|
||||||
|
"range=session"
|
||||||
|
"range=user"
|
||||||
|
|
||||||
|
# Width and padding
|
||||||
|
"width="
|
||||||
|
"pad="
|
||||||
|
|
||||||
|
# Delimiters
|
||||||
|
","
|
||||||
|
" "
|
||||||
2
fuzz/style-fuzzer.options
Normal file
2
fuzz/style-fuzzer.options
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[libfuzzer]
|
||||||
|
max_len = 512
|
||||||
10
grid.c
10
grid.c
@@ -200,7 +200,7 @@ grid_adjust_lines(struct grid *gd, u_int lines)
|
|||||||
|
|
||||||
/* Copy default into a cell. */
|
/* Copy default into a cell. */
|
||||||
static void
|
static void
|
||||||
grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
|
grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg, int moved)
|
||||||
{
|
{
|
||||||
struct grid_line *gl = &gd->linedata[py];
|
struct grid_line *gl = &gd->linedata[py];
|
||||||
struct grid_cell_entry *gce = &gl->celldata[px];
|
struct grid_cell_entry *gce = &gl->celldata[px];
|
||||||
@@ -209,7 +209,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
|
|||||||
int had_extd = (gce->flags & GRID_FLAG_EXTENDED);
|
int had_extd = (gce->flags & GRID_FLAG_EXTENDED);
|
||||||
|
|
||||||
memcpy(gce, &grid_cleared_entry, sizeof *gce);
|
memcpy(gce, &grid_cleared_entry, sizeof *gce);
|
||||||
if (had_extd && old_offset < gl->extdsize) {
|
if (!moved && had_extd && old_offset < gl->extdsize) {
|
||||||
gce->flags |= GRID_FLAG_EXTENDED;
|
gce->flags |= GRID_FLAG_EXTENDED;
|
||||||
gce->offset = old_offset;
|
gce->offset = old_offset;
|
||||||
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
|
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
|
||||||
@@ -515,7 +515,7 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
|
|||||||
(sx - gl->cellsize) * sizeof *gl->celldata);
|
(sx - gl->cellsize) * sizeof *gl->celldata);
|
||||||
}
|
}
|
||||||
for (xx = gl->cellsize; xx < sx; xx++)
|
for (xx = gl->cellsize; xx < sx; xx++)
|
||||||
grid_clear_cell(gd, xx, py, bg);
|
grid_clear_cell(gd, xx, py, bg, 0);
|
||||||
gl->cellsize = sx;
|
gl->cellsize = sx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +683,7 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
|
|||||||
|
|
||||||
grid_expand_line(gd, yy, px + ox, 8); /* default bg first */
|
grid_expand_line(gd, yy, px + ox, 8); /* default bg first */
|
||||||
for (xx = px; xx < px + ox; xx++)
|
for (xx = px; xx < px + ox; xx++)
|
||||||
grid_clear_cell(gd, xx, yy, bg);
|
grid_clear_cell(gd, xx, yy, bg, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,7 +777,7 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx,
|
|||||||
for (xx = px; xx < px + nx; xx++) {
|
for (xx = px; xx < px + nx; xx++) {
|
||||||
if (xx >= dx && xx < dx + nx)
|
if (xx >= dx && xx < dx + nx)
|
||||||
continue;
|
continue;
|
||||||
grid_clear_cell(gd, xx, py, bg);
|
grid_clear_cell(gd, xx, py, bg, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -487,9 +487,9 @@ static void
|
|||||||
sixel_print_add(char **buf, size_t *len, size_t *used, const char *s,
|
sixel_print_add(char **buf, size_t *len, size_t *used, const char *s,
|
||||||
size_t slen)
|
size_t slen)
|
||||||
{
|
{
|
||||||
if (*used + slen >= *len + 1) {
|
while (*used + slen >= *len + 1) {
|
||||||
|
*buf = xreallocarray(*buf, 2, *len);
|
||||||
(*len) *= 2;
|
(*len) *= 2;
|
||||||
*buf = xrealloc(*buf, *len);
|
|
||||||
}
|
}
|
||||||
memcpy(*buf + *used, s, slen);
|
memcpy(*buf + *used, s, slen);
|
||||||
(*used) += slen;
|
(*used) += slen;
|
||||||
|
|||||||
@@ -673,8 +673,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore internal function key codes. */
|
/* Ignore internal function key codes. */
|
||||||
if ((key >= KEYC_BASE && key < KEYC_BASE_END) ||
|
if (KEYC_IS_USER(key) || KEYC_IS_SPECIAL(key) || KEYC_IS_MOUSE(key)) {
|
||||||
(key >= KEYC_USER && key < KEYC_USER_END)) {
|
|
||||||
log_debug("%s: ignoring key 0x%llx", __func__, key);
|
log_debug("%s: ignoring key 0x%llx", __func__, key);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
57
input.c
57
input.c
@@ -164,6 +164,7 @@ static void input_reset_cell(struct input_ctx *);
|
|||||||
static void input_report_current_theme(struct input_ctx *);
|
static void input_report_current_theme(struct input_ctx *);
|
||||||
static void input_osc_4(struct input_ctx *, const char *);
|
static void input_osc_4(struct input_ctx *, const char *);
|
||||||
static void input_osc_8(struct input_ctx *, const char *);
|
static void input_osc_8(struct input_ctx *, const char *);
|
||||||
|
static void input_osc_9(struct input_ctx *, const char *);
|
||||||
static void input_osc_10(struct input_ctx *, const char *);
|
static void input_osc_10(struct input_ctx *, const char *);
|
||||||
static void input_osc_11(struct input_ctx *, const char *);
|
static void input_osc_11(struct input_ctx *, const char *);
|
||||||
static void input_osc_12(struct input_ctx *, const char *);
|
static void input_osc_12(struct input_ctx *, const char *);
|
||||||
@@ -2673,6 +2674,9 @@ input_exit_osc(struct input_ctx *ictx)
|
|||||||
case 8:
|
case 8:
|
||||||
input_osc_8(ictx, p);
|
input_osc_8(ictx, p);
|
||||||
break;
|
break;
|
||||||
|
case 9:
|
||||||
|
input_osc_9(ictx, p);
|
||||||
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
input_osc_10(ictx, p);
|
input_osc_10(ictx, p);
|
||||||
break;
|
break;
|
||||||
@@ -2941,6 +2945,57 @@ bad:
|
|||||||
free(id);
|
free(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper to handle setting the progress bar and redrawing. */
|
||||||
|
static void
|
||||||
|
input_set_progress_bar(struct input_ctx *ictx, enum progress_bar_state state,
|
||||||
|
int p)
|
||||||
|
{
|
||||||
|
screen_set_progress_bar(ictx->ctx.s, state, p);
|
||||||
|
if (ictx->wp != NULL) {
|
||||||
|
server_redraw_window_borders(ictx->wp->window);
|
||||||
|
server_status_window(ictx->wp->window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the OSC 9;4 sequence for progress bars. */
|
||||||
|
static void
|
||||||
|
input_osc_9(struct input_ctx *ictx, const char *p)
|
||||||
|
{
|
||||||
|
const char *pb = p;
|
||||||
|
enum progress_bar_state state;
|
||||||
|
int progress = 0;
|
||||||
|
|
||||||
|
if (*pb++ != '4')
|
||||||
|
return;
|
||||||
|
if (*pb == '\0' || (*pb == ';' && pb[1] == '\0'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*pb++ != ';')
|
||||||
|
return;
|
||||||
|
if (*pb < '0' || *pb > '4')
|
||||||
|
goto bad;
|
||||||
|
state = *pb++ - '0';
|
||||||
|
|
||||||
|
if (*pb == '\0' || (*pb == ';' && pb[1] == '\0')) {
|
||||||
|
input_set_progress_bar(ictx, state, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pb++ != ';')
|
||||||
|
goto bad;
|
||||||
|
while (*pb >= '0' && *pb <= '9') {
|
||||||
|
if (progress > 100)
|
||||||
|
goto bad;
|
||||||
|
progress = progress * 10 + *pb++ - '0';
|
||||||
|
}
|
||||||
|
if (*pb != '\0' || progress < 0 || progress > 100)
|
||||||
|
goto bad;
|
||||||
|
input_set_progress_bar(ictx, state, progress);
|
||||||
|
return;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
log_debug("bad OSC 9;4 %s", p);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
|
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
|
||||||
static void
|
static void
|
||||||
@@ -3151,7 +3206,7 @@ input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (strlen(end) / 4) * 3;
|
len = ((strlen(end) + 3) / 4) * 3;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ key_string_search_table(const char *string)
|
|||||||
return (key_string_table[i].key);
|
return (key_string_table[i].key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sscanf(string, "User%u", &user) == 1 && user < KEYC_NUSER)
|
if (sscanf(string, "User%u", &user) == 1 && user <= KEYC_NUSER)
|
||||||
return (KEYC_USER + user);
|
return (KEYC_USER + user);
|
||||||
|
|
||||||
return (KEYC_UNKNOWN);
|
return (KEYC_UNKNOWN);
|
||||||
@@ -418,7 +418,7 @@ key_string_lookup_key(key_code key, int with_flags)
|
|||||||
s = "MouseMoveBorder";
|
s = "MouseMoveBorder";
|
||||||
goto append;
|
goto append;
|
||||||
}
|
}
|
||||||
if (key >= KEYC_USER && key < KEYC_USER_END) {
|
if (KEYC_IS_USER(key)) {
|
||||||
snprintf(tmp, sizeof tmp, "User%u", (u_int)(key - KEYC_USER));
|
snprintf(tmp, sizeof tmp, "User%u", (u_int)(key - KEYC_USER));
|
||||||
strlcat(out, tmp, sizeof out);
|
strlcat(out, tmp, sizeof out);
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ static const char *options_table_window_size_list[] = {
|
|||||||
"largest", "smallest", "manual", "latest", NULL
|
"largest", "smallest", "manual", "latest", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_remain_on_exit_list[] = {
|
static const char *options_table_remain_on_exit_list[] = {
|
||||||
"off", "on", "failed", "keypress", NULL
|
"off", "on", "failed", "key", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_destroy_unattached_list[] = {
|
static const char *options_table_destroy_unattached_list[] = {
|
||||||
"off", "on", "keep-last", "keep-group", NULL
|
"off", "on", "keep-last", "keep-group", NULL
|
||||||
@@ -1429,8 +1429,9 @@ const struct options_table_entry options_table[] = {
|
|||||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||||
.choices = options_table_remain_on_exit_list,
|
.choices = options_table_remain_on_exit_list,
|
||||||
.default_num = 0,
|
.default_num = 0,
|
||||||
.text = "Whether panes should remain ('on') or be automatically "
|
.text = "Whether panes should remain ('on'), remain until a key is "
|
||||||
"killed ('off' or 'failed') when the program inside exits."
|
"pressed ('key') or be automatically killed ('off' or "
|
||||||
|
"'failed') when the program inside exits."
|
||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "remain-on-exit-format",
|
{ .name = "remain-on-exit-format",
|
||||||
|
|||||||
4
regsub.c
4
regsub.c
@@ -41,7 +41,7 @@ regsub_expand(char **buf, ssize_t *len, const char *with, const char *text,
|
|||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (cp = with; *cp != '\0'; cp++) {
|
for (cp = with; *cp != '\0'; cp++) {
|
||||||
if (*cp == '\\') {
|
if (cp[0] == '\\' && cp[1] != '\0') {
|
||||||
cp++;
|
cp++;
|
||||||
if (*cp >= '0' && *cp <= '9') {
|
if (*cp >= '0' && *cp <= '9') {
|
||||||
i = *cp - '0';
|
i = *cp - '0';
|
||||||
@@ -68,6 +68,8 @@ regsub(const char *pattern, const char *with, const char *text, int flags)
|
|||||||
|
|
||||||
if (*text == '\0')
|
if (*text == '\0')
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
|
if (*pattern == '\0')
|
||||||
|
return (xstrdup(text));
|
||||||
if (regcomp(&r, pattern, flags) != 0)
|
if (regcomp(&r, pattern, flags) != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -602,6 +602,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
|
|||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
const char *fmt, *border_opt;
|
const char *fmt, *border_opt;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
|
struct style_line_entry *sle = &wp->border_status_line;
|
||||||
char *expanded;
|
char *expanded;
|
||||||
int pane_status = rctx->pane_status, sb_w = 0;
|
int pane_status = rctx->pane_status, sb_w = 0;
|
||||||
int pane_scrollbars = rctx->pane_scrollbars;
|
int pane_scrollbars = rctx->pane_scrollbars;
|
||||||
@@ -660,12 +661,15 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
|
|||||||
gc.attr &= ~GRID_ATTR_CHARSET;
|
gc.attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
|
||||||
screen_write_cursormove(&ctx, 0, 0, 0);
|
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||||
format_draw(&ctx, &gc, width, expanded, NULL, 0);
|
style_ranges_free(&sle->ranges);
|
||||||
screen_write_stop(&ctx);
|
format_draw(&ctx, &gc, width, expanded, &sle->ranges, 0);
|
||||||
|
|
||||||
free(expanded);
|
screen_write_stop(&ctx);
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
|
|
||||||
|
free(sle->expanded);
|
||||||
|
sle->expanded = expanded;
|
||||||
|
|
||||||
if (grid_compare(wp->status_screen.grid, old.grid) == 0) {
|
if (grid_compare(wp->status_screen.grid, old.grid) == 0) {
|
||||||
screen_free(&old);
|
screen_free(&old);
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
19
screen.c
19
screen.c
@@ -131,6 +131,7 @@ screen_reinit(struct screen *s)
|
|||||||
image_free_all(s);
|
image_free_all(s);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
screen_set_progress_bar(s, PROGRESS_BAR_HIDDEN, 0);
|
||||||
screen_reset_hyperlinks(s);
|
screen_reset_hyperlinks(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +297,19 @@ screen_pop_title(struct screen *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the progress bar state and progress. The progress will not be updated
|
||||||
|
* if p is negative.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
screen_set_progress_bar(struct screen *s, enum progress_bar_state pbs, int p)
|
||||||
|
{
|
||||||
|
s->progress_bar.state = pbs;
|
||||||
|
if (p >= 0 && pbs != PROGRESS_BAR_INDETERMINATE)
|
||||||
|
s->progress_bar.progress = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Resize screen with options. */
|
/* Resize screen with options. */
|
||||||
void
|
void
|
||||||
screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow,
|
screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow,
|
||||||
@@ -772,8 +786,9 @@ screen_mode_to_string(int mode)
|
|||||||
return (tmp);
|
return (tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert screen to a string. */
|
||||||
const char *
|
const char *
|
||||||
screen_print(struct screen *s)
|
screen_print(struct screen *s, int line)
|
||||||
{
|
{
|
||||||
static char *buf;
|
static char *buf;
|
||||||
static size_t len = 16384;
|
static size_t len = 16384;
|
||||||
@@ -789,6 +804,8 @@ screen_print(struct screen *s)
|
|||||||
buf = xmalloc(len);
|
buf = xmalloc(len);
|
||||||
|
|
||||||
for (y = 0; y < screen_hsize(s) + s->grid->sy; y++) {
|
for (y = 0; y < screen_hsize(s) + s->grid->sy; y++) {
|
||||||
|
if (line >= 0 && y != (u_int)line)
|
||||||
|
continue;
|
||||||
n = snprintf(buf + last, len - last, "%.4d \"", y);
|
n = snprintf(buf + last, len - last, "%.4d \"", y);
|
||||||
if (n <= 0 || (u_int)n >= len - last)
|
if (n <= 0 || (u_int)n >= len - last)
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
1551
server-client.c
1551
server-client.c
File diff suppressed because it is too large
Load Diff
@@ -339,14 +339,13 @@ server_destroy_pane(struct window_pane *wp, int notify)
|
|||||||
switch (remain_on_exit) {
|
switch (remain_on_exit) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 3: /* keypress — fall through to draw remain-on-exit-format message */
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case 2:
|
case 2:
|
||||||
if (remain_on_exit == 2 &&
|
if (remain_on_exit == 2 &&
|
||||||
WIFEXITED(wp->status) && WEXITSTATUS(wp->status) == 0)
|
WIFEXITED(wp->status) && WEXITSTATUS(wp->status) == 0)
|
||||||
break;
|
break;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 1:
|
case 1:
|
||||||
|
case 3:
|
||||||
if (wp->flags & PANE_STATUSDRAWN)
|
if (wp->flags & PANE_STATUSDRAWN)
|
||||||
return;
|
return;
|
||||||
wp->flags |= PANE_STATUSDRAWN;
|
wp->flags |= PANE_STATUSDRAWN;
|
||||||
|
|||||||
1
sort.c
1
sort.c
@@ -505,6 +505,7 @@ sort_get_panes_session(struct session *s, u_int *n,
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
w = wl->window;
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (lsz <= i) {
|
if (lsz <= i) {
|
||||||
lsz += 100;
|
lsz += 100;
|
||||||
|
|||||||
27
status.c
27
status.c
@@ -284,27 +284,10 @@ struct style_range *
|
|||||||
status_get_range(struct client *c, u_int x, u_int y)
|
status_get_range(struct client *c, u_int x, u_int y)
|
||||||
{
|
{
|
||||||
struct status_line *sl = &c->status;
|
struct status_line *sl = &c->status;
|
||||||
struct style_range *sr;
|
|
||||||
|
|
||||||
if (y >= nitems(sl->entries))
|
if (y >= nitems(sl->entries))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
TAILQ_FOREACH(sr, &sl->entries[y].ranges, entry) {
|
return (style_ranges_get_range(&sl->entries[y].ranges, x));
|
||||||
if (x >= sr->start && x < sr->end)
|
|
||||||
return (sr);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free all ranges. */
|
|
||||||
static void
|
|
||||||
status_free_ranges(struct style_ranges *srs)
|
|
||||||
{
|
|
||||||
struct style_range *sr, *sr1;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(sr, srs, entry, sr1) {
|
|
||||||
TAILQ_REMOVE(srs, sr, entry);
|
|
||||||
free(sr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save old status line. */
|
/* Save old status line. */
|
||||||
@@ -341,7 +324,7 @@ status_init(struct client *c)
|
|||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < nitems(sl->entries); i++)
|
for (i = 0; i < nitems(sl->entries); i++)
|
||||||
TAILQ_INIT(&sl->entries[i].ranges);
|
style_ranges_init(&sl->entries[i].ranges);
|
||||||
|
|
||||||
screen_init(&sl->screen, c->tty.sx, 1, 0);
|
screen_init(&sl->screen, c->tty.sx, 1, 0);
|
||||||
sl->active = &sl->screen;
|
sl->active = &sl->screen;
|
||||||
@@ -355,7 +338,7 @@ status_free(struct client *c)
|
|||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < nitems(sl->entries); i++) {
|
for (i = 0; i < nitems(sl->entries); i++) {
|
||||||
status_free_ranges(&sl->entries[i].ranges);
|
style_ranges_free(&sl->entries[i].ranges);
|
||||||
free((void *)sl->entries[i].expanded);
|
free((void *)sl->entries[i].expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +357,7 @@ int
|
|||||||
status_redraw(struct client *c)
|
status_redraw(struct client *c)
|
||||||
{
|
{
|
||||||
struct status_line *sl = &c->status;
|
struct status_line *sl = &c->status;
|
||||||
struct status_line_entry *sle;
|
struct style_line_entry *sle;
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
@@ -454,7 +437,7 @@ status_redraw(struct client *c)
|
|||||||
screen_write_putc(&ctx, &gc, ' ');
|
screen_write_putc(&ctx, &gc, ' ');
|
||||||
screen_write_cursormove(&ctx, 0, i, 0);
|
screen_write_cursormove(&ctx, 0, i, 0);
|
||||||
|
|
||||||
status_free_ranges(&sle->ranges);
|
style_ranges_free(&sle->ranges);
|
||||||
format_draw(&ctx, &gc, width, expanded, &sle->ranges,
|
format_draw(&ctx, &gc, width, expanded, &sle->ranges,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
|||||||
47
style.c
47
style.c
@@ -137,6 +137,15 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
|
|||||||
sy->range_type = STYLE_RANGE_RIGHT;
|
sy->range_type = STYLE_RANGE_RIGHT;
|
||||||
sy->range_argument = 0;
|
sy->range_argument = 0;
|
||||||
style_set_range_string(sy, "");
|
style_set_range_string(sy, "");
|
||||||
|
} else if (strcasecmp(tmp + 6, "control") == 0) {
|
||||||
|
if (found == NULL)
|
||||||
|
goto error;
|
||||||
|
n = strtonum(found, 0, 9, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
goto error;
|
||||||
|
sy->range_type = STYLE_RANGE_CONTROL;
|
||||||
|
sy->range_argument = n;
|
||||||
|
style_set_range_string(sy, "");
|
||||||
} else if (strcasecmp(tmp + 6, "pane") == 0) {
|
} else if (strcasecmp(tmp + 6, "pane") == 0) {
|
||||||
if (found == NULL)
|
if (found == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -426,8 +435,10 @@ style_copy(struct style *dst, struct style *src)
|
|||||||
memcpy(dst, src, sizeof *dst);
|
memcpy(dst, src, sizeof *dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set scrollbar style from an option. */
|
||||||
void
|
void
|
||||||
style_set_scrollbar_style_from_option(struct style *sb_style, struct options *oo)
|
style_set_scrollbar_style_from_option(struct style *sb_style,
|
||||||
|
struct options *oo)
|
||||||
{
|
{
|
||||||
struct style *sy;
|
struct style *sy;
|
||||||
|
|
||||||
@@ -446,3 +457,37 @@ style_set_scrollbar_style_from_option(struct style *sb_style, struct options *oo
|
|||||||
utf8_set(&sb_style->gc.data, PANE_SCROLLBARS_CHARACTER);
|
utf8_set(&sb_style->gc.data, PANE_SCROLLBARS_CHARACTER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize style ranges. */
|
||||||
|
void
|
||||||
|
style_ranges_init(struct style_ranges *srs)
|
||||||
|
{
|
||||||
|
TAILQ_INIT(srs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free style ranges. */
|
||||||
|
void
|
||||||
|
style_ranges_free(struct style_ranges *srs)
|
||||||
|
{
|
||||||
|
struct style_range *sr, *sr1;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(sr, srs, entry, sr1) {
|
||||||
|
TAILQ_REMOVE(srs, sr, entry);
|
||||||
|
free(sr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get range for position from style ranges. */
|
||||||
|
struct style_range *
|
||||||
|
style_ranges_get_range(struct style_ranges *srs, u_int x)
|
||||||
|
{
|
||||||
|
struct style_range *sr;
|
||||||
|
|
||||||
|
if (srs == NULL)
|
||||||
|
return (NULL);
|
||||||
|
TAILQ_FOREACH(sr, srs, entry) {
|
||||||
|
if (x >= sr->start && x < sr->end)
|
||||||
|
return (sr);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|||||||
31
tmux.1
31
tmux.1
@@ -5769,7 +5769,7 @@ uses when the colour with that index is requested.
|
|||||||
The index may be from zero to 255.
|
The index may be from zero to 255.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic remain\-on\-exit
|
.It Xo Ic remain\-on\-exit
|
||||||
.Op Ic on | off | failed | keypress
|
.Op Ic on | off | failed | key
|
||||||
.Xc
|
.Xc
|
||||||
A pane with this flag set is not destroyed when the program running in it
|
A pane with this flag set is not destroyed when the program running in it
|
||||||
exits.
|
exits.
|
||||||
@@ -5777,9 +5777,8 @@ If set to
|
|||||||
.Ic failed ,
|
.Ic failed ,
|
||||||
then only when the program exit status is not zero.
|
then only when the program exit status is not zero.
|
||||||
If set to
|
If set to
|
||||||
.Ic keypress ,
|
.Ic key ,
|
||||||
the pane stays open and closes when the user presses any key (other than
|
the pane stays open and closes when a key is pressed.
|
||||||
a mouse button or paste).
|
|
||||||
The pane may be reactivated with the
|
The pane may be reactivated with the
|
||||||
.Ic respawn\-pane
|
.Ic respawn\-pane
|
||||||
command.
|
command.
|
||||||
@@ -6013,8 +6012,13 @@ and a location suffix, one of the following:
|
|||||||
.It Li "ScrollbarSlider" Ta "the scrollbar slider"
|
.It Li "ScrollbarSlider" Ta "the scrollbar slider"
|
||||||
.It Li "ScrollbarUp" Ta "above the scrollbar slider"
|
.It Li "ScrollbarUp" Ta "above the scrollbar slider"
|
||||||
.It Li "ScrollbarDown" Ta "below the scrollbar slider"
|
.It Li "ScrollbarDown" Ta "below the scrollbar slider"
|
||||||
|
.It Li "ControlN" Ta "on control range N"
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
See the
|
||||||
|
.Sx STYLES
|
||||||
|
section for information on control ranges.
|
||||||
|
.Pp
|
||||||
The following mouse events are available:
|
The following mouse events are available:
|
||||||
.Bl -column "MouseDown1" "MouseDrag1" "WheelDown" -offset indent
|
.Bl -column "MouseDown1" "MouseDrag1" "WheelDown" -offset indent
|
||||||
.It Li "WheelUp" Ta "WheelDown" Ta ""
|
.It Li "WheelUp" Ta "WheelDown" Ta ""
|
||||||
@@ -6475,6 +6479,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "alternate_on" Ta "" Ta "1 if pane is in alternate screen"
|
.It Li "alternate_on" Ta "" Ta "1 if pane is in alternate screen"
|
||||||
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
|
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
|
||||||
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
|
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
|
||||||
|
.It Li "bracket_paste_flag" Ta "" Ta "Pane bracketed paste flag"
|
||||||
.It Li "buffer_created" Ta "" Ta "Time buffer created"
|
.It Li "buffer_created" Ta "" Ta "Time buffer created"
|
||||||
.It Li "buffer_full" Ta "" Ta "Full buffer content"
|
.It Li "buffer_full" Ta "" Ta "Full buffer content"
|
||||||
.It Li "buffer_name" Ta "" Ta "Name of buffer"
|
.It Li "buffer_name" Ta "" Ta "Name of buffer"
|
||||||
@@ -6600,6 +6605,8 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
||||||
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
|
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
|
||||||
.It Li "pane_pipe_pid" Ta "" Ta "PID of pipe process, if any"
|
.It Li "pane_pipe_pid" Ta "" Ta "PID of pipe process, if any"
|
||||||
|
.It Li "pane_pb_state" Ta "" Ta "Pane progress bar state, one of hidden, normal, error, indeterminate, paused (can be set by application)"
|
||||||
|
.It Li "pane_pb_progress" Ta "" Ta "Pane progress bar progress percentage (can be set by application)"
|
||||||
.It Li "pane_right" Ta "" Ta "Right of pane"
|
.It Li "pane_right" Ta "" Ta "Right of pane"
|
||||||
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
|
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
|
||||||
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
||||||
@@ -6828,6 +6835,7 @@ replaces the previous saved default).
|
|||||||
.Ic range=window|X ,
|
.Ic range=window|X ,
|
||||||
.Ic range=pane|X ,
|
.Ic range=pane|X ,
|
||||||
.Ic range=user|X ,
|
.Ic range=user|X ,
|
||||||
|
.Ic range=control|N ,
|
||||||
.Ic norange
|
.Ic norange
|
||||||
.Xc
|
.Xc
|
||||||
Mark a range for mouse events in the
|
Mark a range for mouse events in the
|
||||||
@@ -6874,6 +6882,19 @@ will be available in the
|
|||||||
format variable.
|
format variable.
|
||||||
.Ql X
|
.Ql X
|
||||||
must be at most 15 bytes in length.
|
must be at most 15 bytes in length.
|
||||||
|
.Pp
|
||||||
|
.Ic range=control|N
|
||||||
|
is a set of ranges for users to define custom behavior.
|
||||||
|
.Ql N
|
||||||
|
can be 0 through 9.
|
||||||
|
When a mouse event occurs in the
|
||||||
|
.Ic range=control|N
|
||||||
|
range, the
|
||||||
|
.Ql ControlN
|
||||||
|
key binding is triggered.
|
||||||
|
See
|
||||||
|
.Sx MOUSE SUPPORT
|
||||||
|
for details.
|
||||||
.It Ic set\-default
|
.It Ic set\-default
|
||||||
Set the current colours and attributes as the default, overwriting any previous
|
Set the current colours and attributes as the default, overwriting any previous
|
||||||
default.
|
default.
|
||||||
@@ -7403,7 +7424,7 @@ If
|
|||||||
is not given, the
|
is not given, the
|
||||||
.Ic display\-time
|
.Ic display\-time
|
||||||
option is used; a delay of zero waits for a key press.
|
option is used; a delay of zero waits for a key press.
|
||||||
.Ql N
|
.Fl N
|
||||||
ignores key presses and closes only after the delay expires.
|
ignores key presses and closes only after the delay expires.
|
||||||
If
|
If
|
||||||
.Fl C
|
.Fl C
|
||||||
|
|||||||
299
tmux.h
299
tmux.h
@@ -129,18 +129,6 @@ struct winlink;
|
|||||||
#define VISUAL_ON 1
|
#define VISUAL_ON 1
|
||||||
#define VISUAL_BOTH 2
|
#define VISUAL_BOTH 2
|
||||||
|
|
||||||
/* No key or unknown key. */
|
|
||||||
#define KEYC_NONE 0x000ff000000000ULL
|
|
||||||
#define KEYC_UNKNOWN 0x000fe000000000ULL
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Base for special (that is, not Unicode) keys. An enum must be at most a
|
|
||||||
* signed int, so these are based in the highest Unicode PUA.
|
|
||||||
*/
|
|
||||||
#define KEYC_BASE 0x0000000010e000ULL
|
|
||||||
#define KEYC_USER 0x0000000010f000ULL
|
|
||||||
#define KEYC_USER_END (KEYC_USER + KEYC_NUSER)
|
|
||||||
|
|
||||||
/* Key modifier bits. */
|
/* Key modifier bits. */
|
||||||
#define KEYC_META 0x00100000000000ULL
|
#define KEYC_META 0x00100000000000ULL
|
||||||
#define KEYC_CTRL 0x00200000000000ULL
|
#define KEYC_CTRL 0x00200000000000ULL
|
||||||
@@ -156,45 +144,122 @@ struct winlink;
|
|||||||
#define KEYC_SENT 0x40000000000000ULL
|
#define KEYC_SENT 0x40000000000000ULL
|
||||||
|
|
||||||
/* Masks for key bits. */
|
/* Masks for key bits. */
|
||||||
#define KEYC_MASK_MODIFIERS 0x00f00000000000ULL
|
#define KEYC_MASK_TYPE 0x0000ff00000000ULL
|
||||||
|
#define KEYC_MASK_MODIFIERS 0x00ff0000000000ULL
|
||||||
#define KEYC_MASK_FLAGS 0xff000000000000ULL
|
#define KEYC_MASK_FLAGS 0xff000000000000ULL
|
||||||
#define KEYC_MASK_KEY 0x000fffffffffffULL
|
#define KEYC_MASK_KEY 0x0000ffffffffffULL
|
||||||
|
|
||||||
/* Available user keys. */
|
#define KEYC_NUSER 1000
|
||||||
#define KEYC_NUSER 1000
|
#define KEYC_SHIFT_TYPE(t) ((unsigned long long)(t) << 32)
|
||||||
|
#define KEYC_IS_TYPE(k, t) (((k) & KEYC_MASK_TYPE) == KEYC_SHIFT_TYPE(t))
|
||||||
|
enum key_code_type {
|
||||||
|
KEYC_TYPE_UNICODE,
|
||||||
|
KEYC_TYPE_USER,
|
||||||
|
KEYC_TYPE_FUNCTION,
|
||||||
|
KEYC_TYPE_MOUSEMOVE,
|
||||||
|
KEYC_TYPE_MOUSEDOWN,
|
||||||
|
KEYC_TYPE_MOUSEUP,
|
||||||
|
KEYC_TYPE_MOUSEDRAG,
|
||||||
|
KEYC_TYPE_MOUSEDRAGEND,
|
||||||
|
KEYC_TYPE_WHEELDOWN,
|
||||||
|
KEYC_TYPE_WHEELUP,
|
||||||
|
KEYC_TYPE_SECONDCLICK,
|
||||||
|
KEYC_TYPE_DOUBLECLICK,
|
||||||
|
KEYC_TYPE_TRIPLECLICK,
|
||||||
|
KEYC_TYPE_NOTYPE /* end */
|
||||||
|
};
|
||||||
|
|
||||||
/* Is this a mouse key? */
|
enum key_code_mouse_location {
|
||||||
#define KEYC_IS_MOUSE(key) \
|
KEYC_MOUSE_LOCATION_PANE,
|
||||||
(((key) & KEYC_MASK_KEY) >= KEYC_MOUSE && \
|
KEYC_MOUSE_LOCATION_STATUS,
|
||||||
((key) & KEYC_MASK_KEY) < KEYC_BSPACE)
|
KEYC_MOUSE_LOCATION_STATUS_LEFT,
|
||||||
|
KEYC_MOUSE_LOCATION_STATUS_RIGHT,
|
||||||
|
KEYC_MOUSE_LOCATION_STATUS_DEFAULT,
|
||||||
|
KEYC_MOUSE_LOCATION_BORDER,
|
||||||
|
KEYC_MOUSE_LOCATION_SCROLLBAR_UP,
|
||||||
|
KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER,
|
||||||
|
KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL0, /* keep order */
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL1,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL2,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL3,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL4,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL5,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL6,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL7,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL8,
|
||||||
|
KEYC_MOUSE_LOCATION_CONTROL9,
|
||||||
|
KEYC_MOUSE_LOCATION_NOWHERE /* end */
|
||||||
|
};
|
||||||
|
|
||||||
/* Is this a Unicode key? */
|
/* Is this a Unicode key? */
|
||||||
#define KEYC_IS_UNICODE(key) \
|
#define KEYC_IS_UNICODE(key) \
|
||||||
(((key) & KEYC_MASK_KEY) > 0x7f && \
|
(((key) & KEYC_MASK_TYPE) == KEYC_SHIFT_TYPE(KEYC_TYPE_UNICODE) && \
|
||||||
(((key) & KEYC_MASK_KEY) < KEYC_BASE || \
|
((key) & KEYC_MASK_KEY) > 0x7f)
|
||||||
((key) & KEYC_MASK_KEY) >= KEYC_BASE_END) && \
|
|
||||||
(((key) & KEYC_MASK_KEY) < KEYC_USER || \
|
/* Is this a user key? */
|
||||||
((key) & KEYC_MASK_KEY) >= KEYC_USER_END))
|
#define KEYC_IS_USER(key) \
|
||||||
|
(((key) & KEYC_MASK_TYPE) == KEYC_SHIFT_TYPE(KEYC_TYPE_USER))
|
||||||
|
|
||||||
|
/* Is this a function key? */
|
||||||
|
#define KEYC_IS_SPECIAL(key) \
|
||||||
|
(((key) & KEYC_MASK_TYPE) == KEYC_SHIFT_TYPE(KEYC_TYPE_FUNCTION))
|
||||||
|
|
||||||
|
/* Is this a mouse key? */
|
||||||
|
#define KEYC_IS_MOUSE(key) \
|
||||||
|
(((key) & KEYC_MASK_KEY) == KEYC_MOUSE || \
|
||||||
|
(((key) & KEYC_MASK_TYPE) >= KEYC_SHIFT_TYPE(KEYC_TYPE_MOUSEMOVE) && \
|
||||||
|
((key) & KEYC_MASK_TYPE) <= KEYC_SHIFT_TYPE(KEYC_TYPE_TRIPLECLICK)))
|
||||||
|
|
||||||
/* Is this a paste key? */
|
/* Is this a paste key? */
|
||||||
#define KEYC_IS_PASTE(key) \
|
#define KEYC_IS_PASTE(key) \
|
||||||
(((key) & KEYC_MASK_KEY) == KEYC_PASTE_START || \
|
(((key) & KEYC_MASK_TYPE) == KEYC_SHIFT_TYPE(KEYC_TYPE_FUNCTION) && \
|
||||||
((key) & KEYC_MASK_KEY) == KEYC_PASTE_END)
|
(((key) & KEYC_MASK_KEY) == KEYC_PASTE_START || \
|
||||||
|
((key) & KEYC_MASK_KEY) == KEYC_PASTE_END))
|
||||||
|
|
||||||
/* Multiple click timeout. */
|
/* Multiple click timeout. */
|
||||||
#define KEYC_CLICK_TIMEOUT 300
|
#define KEYC_CLICK_TIMEOUT 300
|
||||||
|
|
||||||
|
/* Bit shift for mouse events. */
|
||||||
|
#define KEYC_MOUSE_LOCATION_SHIFT 0
|
||||||
|
#define KEYC_MOUSE_BUTTON_SHIFT 8
|
||||||
|
|
||||||
/* Mouse key codes. */
|
/* Mouse key codes. */
|
||||||
#define KEYC_MOUSE_KEY(name) \
|
#define KEYC_MOUSE_KEYS(t) \
|
||||||
KEYC_ ## name ## _PANE, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, PANE), \
|
||||||
KEYC_ ## name ## _STATUS, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS), \
|
||||||
KEYC_ ## name ## _STATUS_LEFT, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_LEFT), \
|
||||||
KEYC_ ## name ## _STATUS_RIGHT, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_RIGHT), \
|
||||||
KEYC_ ## name ## _STATUS_DEFAULT, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_DEFAULT), \
|
||||||
KEYC_ ## name ## _SCROLLBAR_UP, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, BORDER), \
|
||||||
KEYC_ ## name ## _SCROLLBAR_SLIDER, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_UP), \
|
||||||
KEYC_ ## name ## _SCROLLBAR_DOWN, \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_SLIDER), \
|
||||||
KEYC_ ## name ## _BORDER
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_DOWN), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL0), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL1), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL2), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL3), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL4), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL5), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL6), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL7), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL8), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, CONTROL9)
|
||||||
|
#define KEYC_MOUSE_KEY(p, t, l) \
|
||||||
|
p ## _ ## l = KEYC_MAKE_MOUSE_KEY(t, 0, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 1_ ## l = KEYC_MAKE_MOUSE_KEY(t, 1, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 2_ ## l = KEYC_MAKE_MOUSE_KEY(t, 2, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 3_ ## l = KEYC_MAKE_MOUSE_KEY(t, 3, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 6_ ## l = KEYC_MAKE_MOUSE_KEY(t, 6, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 7_ ## l = KEYC_MAKE_MOUSE_KEY(t, 7, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 8_ ## l = KEYC_MAKE_MOUSE_KEY(t, 8, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 9_ ## l = KEYC_MAKE_MOUSE_KEY(t, 9, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 10_ ## l = KEYC_MAKE_MOUSE_KEY(t, 10, KEYC_MOUSE_LOCATION_ ## l), \
|
||||||
|
p ## 11_ ## l = KEYC_MAKE_MOUSE_KEY(t, 11, KEYC_MOUSE_LOCATION_ ## l)
|
||||||
|
#define KEYC_MAKE_MOUSE_KEY(t, b, l) \
|
||||||
|
((KEYC_SHIFT_TYPE(t)) | \
|
||||||
|
((unsigned long long)(b) << KEYC_MOUSE_BUTTON_SHIFT) | \
|
||||||
|
((unsigned long long)(l) << KEYC_MOUSE_LOCATION_SHIFT))
|
||||||
#define KEYC_MOUSE_STRING(name, s) \
|
#define KEYC_MOUSE_STRING(name, s) \
|
||||||
{ #s "Pane", KEYC_ ## name ## _PANE }, \
|
{ #s "Pane", KEYC_ ## name ## _PANE }, \
|
||||||
{ #s "Status", KEYC_ ## name ## _STATUS }, \
|
{ #s "Status", KEYC_ ## name ## _STATUS }, \
|
||||||
@@ -204,7 +269,17 @@ struct winlink;
|
|||||||
{ #s "ScrollbarUp", KEYC_ ## name ## _SCROLLBAR_UP }, \
|
{ #s "ScrollbarUp", KEYC_ ## name ## _SCROLLBAR_UP }, \
|
||||||
{ #s "ScrollbarSlider", KEYC_ ## name ## _SCROLLBAR_SLIDER }, \
|
{ #s "ScrollbarSlider", KEYC_ ## name ## _SCROLLBAR_SLIDER }, \
|
||||||
{ #s "ScrollbarDown", KEYC_ ## name ## _SCROLLBAR_DOWN }, \
|
{ #s "ScrollbarDown", KEYC_ ## name ## _SCROLLBAR_DOWN }, \
|
||||||
{ #s "Border", KEYC_ ## name ## _BORDER }
|
{ #s "Border", KEYC_ ## name ## _BORDER }, \
|
||||||
|
{ #s "Control0", KEYC_ ## name ## _CONTROL0 }, \
|
||||||
|
{ #s "Control1", KEYC_ ## name ## _CONTROL1 }, \
|
||||||
|
{ #s "Control2", KEYC_ ## name ## _CONTROL2 }, \
|
||||||
|
{ #s "Control3", KEYC_ ## name ## _CONTROL3 }, \
|
||||||
|
{ #s "Control4", KEYC_ ## name ## _CONTROL4 }, \
|
||||||
|
{ #s "Control5", KEYC_ ## name ## _CONTROL5 }, \
|
||||||
|
{ #s "Control6", KEYC_ ## name ## _CONTROL6 }, \
|
||||||
|
{ #s "Control7", KEYC_ ## name ## _CONTROL7 }, \
|
||||||
|
{ #s "Control8", KEYC_ ## name ## _CONTROL8 }, \
|
||||||
|
{ #s "Control9", KEYC_ ## name ## _CONTROL9 }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A single key. This can be ASCII or Unicode or one of the keys between
|
* A single key. This can be ASCII or Unicode or one of the keys between
|
||||||
@@ -250,8 +325,15 @@ enum {
|
|||||||
|
|
||||||
/* Special key codes. */
|
/* Special key codes. */
|
||||||
enum {
|
enum {
|
||||||
|
/* User key code range. */
|
||||||
|
KEYC_USER = KEYC_SHIFT_TYPE(KEYC_TYPE_USER),
|
||||||
|
|
||||||
|
/* Functional key code range. */
|
||||||
|
KEYC_NONE = KEYC_SHIFT_TYPE(KEYC_TYPE_FUNCTION),
|
||||||
|
KEYC_UNKNOWN,
|
||||||
|
|
||||||
/* Focus events. */
|
/* Focus events. */
|
||||||
KEYC_FOCUS_IN = KEYC_BASE,
|
KEYC_FOCUS_IN,
|
||||||
KEYC_FOCUS_OUT,
|
KEYC_FOCUS_OUT,
|
||||||
|
|
||||||
/* "Any" key, used if not found in key table. */
|
/* "Any" key, used if not found in key table. */
|
||||||
@@ -261,77 +343,6 @@ enum {
|
|||||||
KEYC_PASTE_START,
|
KEYC_PASTE_START,
|
||||||
KEYC_PASTE_END,
|
KEYC_PASTE_END,
|
||||||
|
|
||||||
/* Mouse keys. */
|
|
||||||
KEYC_MOUSE, /* unclassified mouse event */
|
|
||||||
KEYC_DRAGGING, /* dragging in progress */
|
|
||||||
KEYC_DOUBLECLICK, /* double click complete */
|
|
||||||
KEYC_MOUSE_KEY(MOUSEMOVE),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN1),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN2),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN3),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN6),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN7),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN8),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN9),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN10),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDOWN11),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP1),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP2),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP3),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP6),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP7),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP8),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP9),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP10),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEUP11),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG1),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG2),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG3),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG6),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG7),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG8),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG9),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG10),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAG11),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND1),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND2),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND3),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND6),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND7),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND8),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND9),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND10),
|
|
||||||
KEYC_MOUSE_KEY(MOUSEDRAGEND11),
|
|
||||||
KEYC_MOUSE_KEY(WHEELUP),
|
|
||||||
KEYC_MOUSE_KEY(WHEELDOWN),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK1),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK2),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK3),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK6),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK7),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK8),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK9),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK10),
|
|
||||||
KEYC_MOUSE_KEY(SECONDCLICK11),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK1),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK2),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK3),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK6),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK7),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK8),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK9),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK10),
|
|
||||||
KEYC_MOUSE_KEY(DOUBLECLICK11),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK1),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK2),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK3),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK6),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK7),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK8),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK9),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK10),
|
|
||||||
KEYC_MOUSE_KEY(TRIPLECLICK11),
|
|
||||||
|
|
||||||
/* Backspace key. */
|
/* Backspace key. */
|
||||||
KEYC_BSPACE,
|
KEYC_BSPACE,
|
||||||
|
|
||||||
@@ -384,8 +395,22 @@ enum {
|
|||||||
KEYC_REPORT_DARK_THEME,
|
KEYC_REPORT_DARK_THEME,
|
||||||
KEYC_REPORT_LIGHT_THEME,
|
KEYC_REPORT_LIGHT_THEME,
|
||||||
|
|
||||||
/* End of special keys. */
|
/* Mouse state. */
|
||||||
KEYC_BASE_END
|
KEYC_MOUSE, /* unclassified mouse event */
|
||||||
|
KEYC_DRAGGING, /* dragging in progress */
|
||||||
|
KEYC_DOUBLECLICK, /* double click complete */
|
||||||
|
|
||||||
|
/* Mouse key code ranges. Must be at the end. */
|
||||||
|
KEYC_MOUSE_KEYS(MOUSEMOVE),
|
||||||
|
KEYC_MOUSE_KEYS(WHEELDOWN),
|
||||||
|
KEYC_MOUSE_KEYS(WHEELUP),
|
||||||
|
KEYC_MOUSE_KEYS(MOUSEDOWN),
|
||||||
|
KEYC_MOUSE_KEYS(MOUSEUP),
|
||||||
|
KEYC_MOUSE_KEYS(MOUSEDRAG),
|
||||||
|
KEYC_MOUSE_KEYS(MOUSEDRAGEND),
|
||||||
|
KEYC_MOUSE_KEYS(SECONDCLICK),
|
||||||
|
KEYC_MOUSE_KEYS(DOUBLECLICK),
|
||||||
|
KEYC_MOUSE_KEYS(TRIPLECLICK),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Termcap codes. */
|
/* Termcap codes. */
|
||||||
@@ -880,7 +905,8 @@ enum style_range_type {
|
|||||||
STYLE_RANGE_PANE,
|
STYLE_RANGE_PANE,
|
||||||
STYLE_RANGE_WINDOW,
|
STYLE_RANGE_WINDOW,
|
||||||
STYLE_RANGE_SESSION,
|
STYLE_RANGE_SESSION,
|
||||||
STYLE_RANGE_USER
|
STYLE_RANGE_USER,
|
||||||
|
STYLE_RANGE_CONTROL
|
||||||
};
|
};
|
||||||
struct style_range {
|
struct style_range {
|
||||||
enum style_range_type type;
|
enum style_range_type type;
|
||||||
@@ -894,6 +920,12 @@ struct style_range {
|
|||||||
};
|
};
|
||||||
TAILQ_HEAD(style_ranges, style_range);
|
TAILQ_HEAD(style_ranges, style_range);
|
||||||
|
|
||||||
|
/* Ranges connected with a status line. */
|
||||||
|
struct style_line_entry {
|
||||||
|
char *expanded;
|
||||||
|
struct style_ranges ranges;
|
||||||
|
};
|
||||||
|
|
||||||
/* Default style width and pad. */
|
/* Default style width and pad. */
|
||||||
#define STYLE_WIDTH_DEFAULT -1
|
#define STYLE_WIDTH_DEFAULT -1
|
||||||
#define STYLE_PAD_DEFAULT -1
|
#define STYLE_PAD_DEFAULT -1
|
||||||
@@ -952,6 +984,20 @@ enum screen_cursor_style {
|
|||||||
SCREEN_CURSOR_BAR
|
SCREEN_CURSOR_BAR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Progress bar, OSC 9;4. */
|
||||||
|
enum progress_bar_state {
|
||||||
|
PROGRESS_BAR_HIDDEN = 0,
|
||||||
|
PROGRESS_BAR_NORMAL = 1,
|
||||||
|
PROGRESS_BAR_ERROR = 2,
|
||||||
|
PROGRESS_BAR_INDETERMINATE = 3,
|
||||||
|
PROGRESS_BAR_PAUSED = 4
|
||||||
|
};
|
||||||
|
struct progress_bar {
|
||||||
|
enum progress_bar_state state;
|
||||||
|
int progress;
|
||||||
|
};
|
||||||
|
|
||||||
/* Virtual screen. */
|
/* Virtual screen. */
|
||||||
struct screen_sel;
|
struct screen_sel;
|
||||||
struct screen_titles;
|
struct screen_titles;
|
||||||
@@ -993,6 +1039,7 @@ struct screen {
|
|||||||
struct screen_write_cline *write_list;
|
struct screen_write_cline *write_list;
|
||||||
|
|
||||||
struct hyperlinks *hyperlinks;
|
struct hyperlinks *hyperlinks;
|
||||||
|
struct progress_bar progress_bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Screen write context. */
|
/* Screen write context. */
|
||||||
@@ -1216,8 +1263,8 @@ struct window_pane {
|
|||||||
#define PANE_DROP 0x2
|
#define PANE_DROP 0x2
|
||||||
#define PANE_FOCUSED 0x4
|
#define PANE_FOCUSED 0x4
|
||||||
#define PANE_VISITED 0x8
|
#define PANE_VISITED 0x8
|
||||||
/* 0x10 unused */
|
#define PANE_ZOOMED 0x10
|
||||||
/* 0x20 unused */
|
#define PANE_FLOATING 0x20
|
||||||
#define PANE_INPUTOFF 0x40
|
#define PANE_INPUTOFF 0x40
|
||||||
#define PANE_CHANGED 0x80
|
#define PANE_CHANGED 0x80
|
||||||
#define PANE_EXITED 0x100
|
#define PANE_EXITED 0x100
|
||||||
@@ -1228,9 +1275,7 @@ struct window_pane {
|
|||||||
#define PANE_THEMECHANGED 0x2000
|
#define PANE_THEMECHANGED 0x2000
|
||||||
#define PANE_UNSEENCHANGES 0x4000
|
#define PANE_UNSEENCHANGES 0x4000
|
||||||
#define PANE_REDRAWSCROLLBAR 0x8000
|
#define PANE_REDRAWSCROLLBAR 0x8000
|
||||||
#define PANE_FLOATING 0x10000
|
|
||||||
#define PANE_MINIMISED 0x20000
|
#define PANE_MINIMISED 0x20000
|
||||||
#define PANE_ZOOMED 0x40000
|
|
||||||
#define PANE_SAVED_FLOAT 0x80000 /* saved_float_* fields are valid */
|
#define PANE_SAVED_FLOAT 0x80000 /* saved_float_* fields are valid */
|
||||||
|
|
||||||
/* Last floating position/size, saved when the pane is tiled. */
|
/* Last floating position/size, saved when the pane is tiled. */
|
||||||
@@ -1268,6 +1313,7 @@ struct window_pane {
|
|||||||
struct grid_cell cached_active_gc;
|
struct grid_cell cached_active_gc;
|
||||||
struct colour_palette palette;
|
struct colour_palette palette;
|
||||||
enum client_theme last_theme;
|
enum client_theme last_theme;
|
||||||
|
struct style_line_entry border_status_line;
|
||||||
|
|
||||||
int pipe_fd;
|
int pipe_fd;
|
||||||
pid_t pipe_pid;
|
pid_t pipe_pid;
|
||||||
@@ -1892,10 +1938,6 @@ struct cmd_entry {
|
|||||||
|
|
||||||
/* Status line. */
|
/* Status line. */
|
||||||
#define STATUS_LINES_LIMIT 5
|
#define STATUS_LINES_LIMIT 5
|
||||||
struct status_line_entry {
|
|
||||||
char *expanded;
|
|
||||||
struct style_ranges ranges;
|
|
||||||
};
|
|
||||||
struct status_line {
|
struct status_line {
|
||||||
struct event timer;
|
struct event timer;
|
||||||
|
|
||||||
@@ -1904,7 +1946,7 @@ struct status_line {
|
|||||||
int references;
|
int references;
|
||||||
|
|
||||||
struct grid_cell style;
|
struct grid_cell style;
|
||||||
struct status_line_entry entries[STATUS_LINES_LIMIT];
|
struct style_line_entry entries[STATUS_LINES_LIMIT];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Prompt type. */
|
/* Prompt type. */
|
||||||
@@ -1969,6 +2011,7 @@ typedef void (*overlay_resize_cb)(struct client *, void *);
|
|||||||
struct client {
|
struct client {
|
||||||
const char *name;
|
const char *name;
|
||||||
struct tmuxpeer *peer;
|
struct tmuxpeer *peer;
|
||||||
|
const char *user;
|
||||||
struct cmdq_list *queue;
|
struct cmdq_list *queue;
|
||||||
|
|
||||||
struct client_windows windows;
|
struct client_windows windows;
|
||||||
@@ -2009,7 +2052,7 @@ struct client {
|
|||||||
struct event repeat_timer;
|
struct event repeat_timer;
|
||||||
|
|
||||||
struct event click_timer;
|
struct event click_timer;
|
||||||
int click_where;
|
int click_loc;
|
||||||
int click_wp;
|
int click_wp;
|
||||||
u_int click_button;
|
u_int click_button;
|
||||||
struct mouse_event click_event;
|
struct mouse_event click_event;
|
||||||
@@ -3312,6 +3355,7 @@ int screen_set_title(struct screen *, const char *);
|
|||||||
void screen_set_path(struct screen *, const char *);
|
void screen_set_path(struct screen *, const char *);
|
||||||
void screen_push_title(struct screen *);
|
void screen_push_title(struct screen *);
|
||||||
void screen_pop_title(struct screen *);
|
void screen_pop_title(struct screen *);
|
||||||
|
void screen_set_progress_bar(struct screen *, enum progress_bar_state, int);
|
||||||
void screen_resize(struct screen *, u_int, u_int, int);
|
void screen_resize(struct screen *, u_int, u_int, int);
|
||||||
void screen_resize_cursor(struct screen *, u_int, u_int, int, int, int);
|
void screen_resize_cursor(struct screen *, u_int, u_int, int, int, int);
|
||||||
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int,
|
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int,
|
||||||
@@ -3324,7 +3368,7 @@ int screen_select_cell(struct screen *, struct grid_cell *,
|
|||||||
void screen_alternate_on(struct screen *, struct grid_cell *, int);
|
void screen_alternate_on(struct screen *, struct grid_cell *, int);
|
||||||
void screen_alternate_off(struct screen *, struct grid_cell *, int);
|
void screen_alternate_off(struct screen *, struct grid_cell *, int);
|
||||||
const char *screen_mode_to_string(int);
|
const char *screen_mode_to_string(int);
|
||||||
const char *screen_print(struct screen *);
|
const char *screen_print(struct screen *, int);
|
||||||
|
|
||||||
/* window.c */
|
/* window.c */
|
||||||
extern struct windows windows;
|
extern struct windows windows;
|
||||||
@@ -3404,7 +3448,7 @@ int window_pane_exited(struct window_pane *);
|
|||||||
u_int window_pane_search(struct window_pane *, const char *, int,
|
u_int window_pane_search(struct window_pane *, const char *, int,
|
||||||
int);
|
int);
|
||||||
const char *window_printable_flags(struct winlink *, int);
|
const char *window_printable_flags(struct winlink *, int);
|
||||||
const char *window_pane_printable_flags(struct window_pane *, int);
|
const char *window_pane_printable_flags(struct window_pane *);
|
||||||
struct window_pane *window_pane_find_up(struct window_pane *);
|
struct window_pane *window_pane_find_up(struct window_pane *);
|
||||||
struct window_pane *window_pane_find_down(struct window_pane *);
|
struct window_pane *window_pane_find_down(struct window_pane *);
|
||||||
struct window_pane *window_pane_find_left(struct window_pane *);
|
struct window_pane *window_pane_find_left(struct window_pane *);
|
||||||
@@ -3435,6 +3479,8 @@ int window_pane_get_bg_control_client(struct window_pane *);
|
|||||||
int window_get_bg_client(struct window_pane *);
|
int window_get_bg_client(struct window_pane *);
|
||||||
enum client_theme window_pane_get_theme(struct window_pane *);
|
enum client_theme window_pane_get_theme(struct window_pane *);
|
||||||
void window_pane_send_theme_update(struct window_pane *);
|
void window_pane_send_theme_update(struct window_pane *);
|
||||||
|
struct style_range *window_pane_border_status_get_range(struct window_pane *,
|
||||||
|
u_int, u_int);
|
||||||
|
|
||||||
/* layout.c */
|
/* layout.c */
|
||||||
u_int layout_count_cells(struct layout_cell *);
|
u_int layout_count_cells(struct layout_cell *);
|
||||||
@@ -3756,6 +3802,9 @@ void style_set(struct style *, const struct grid_cell *);
|
|||||||
void style_copy(struct style *, struct style *);
|
void style_copy(struct style *, struct style *);
|
||||||
void style_set_scrollbar_style_from_option(struct style *,
|
void style_set_scrollbar_style_from_option(struct style *,
|
||||||
struct options *);
|
struct options *);
|
||||||
|
void style_ranges_init(struct style_ranges *);
|
||||||
|
void style_ranges_free(struct style_ranges *);
|
||||||
|
struct style_range *style_ranges_get_range(struct style_ranges *, u_int);
|
||||||
|
|
||||||
/* spawn.c */
|
/* spawn.c */
|
||||||
struct winlink *spawn_window(struct spawn_context *, char **);
|
struct winlink *spawn_window(struct spawn_context *, char **);
|
||||||
|
|||||||
46
tty-draw.c
46
tty-draw.c
@@ -143,6 +143,14 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, px, py, nx,
|
log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, px, py, nx,
|
||||||
atx, aty);
|
atx, aty);
|
||||||
|
|
||||||
|
/* There is no point in drawing more than the end of the terminal. */
|
||||||
|
if (atx >= tty->sx)
|
||||||
|
return;
|
||||||
|
if (atx + nx >= tty->sx)
|
||||||
|
nx = tty->sx - atx;
|
||||||
|
if (nx == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clamp the width to cellsize - note this is not cellused, because
|
* Clamp the width to cellsize - note this is not cellused, because
|
||||||
* there may be empty background cells after it (from BCE).
|
* there may be empty background cells after it (from BCE).
|
||||||
@@ -150,19 +158,24 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
cellsize = grid_get_line(gd, gd->hsize + py)->cellsize;
|
cellsize = grid_get_line(gd, gd->hsize + py)->cellsize;
|
||||||
if (screen_size_x(s) > cellsize)
|
if (screen_size_x(s) > cellsize)
|
||||||
ex = cellsize;
|
ex = cellsize;
|
||||||
else {
|
else
|
||||||
ex = screen_size_x(s);
|
ex = screen_size_x(s);
|
||||||
if (px > ex)
|
|
||||||
return;
|
|
||||||
if (px + nx > ex)
|
|
||||||
nx = ex - px;
|
|
||||||
}
|
|
||||||
if (ex < nx)
|
|
||||||
ex = nx;
|
|
||||||
log_debug("%s: drawing %u-%u,%u (end %u) at %u,%u; defaults: fg=%d, "
|
log_debug("%s: drawing %u-%u,%u (end %u) at %u,%u; defaults: fg=%d, "
|
||||||
"bg=%d", __func__, px, px + nx, py, ex, atx, aty, defaults->fg,
|
"bg=%d", __func__, px, px + nx, py, ex, atx, aty, defaults->fg,
|
||||||
defaults->bg);
|
defaults->bg);
|
||||||
|
|
||||||
|
/* Turn off cursor while redrawing and reset region and margins. */
|
||||||
|
flags = (tty->flags & TTY_NOCURSOR);
|
||||||
|
tty->flags |= TTY_NOCURSOR;
|
||||||
|
tty_update_mode(tty, tty->mode, s);
|
||||||
|
tty_region_off(tty);
|
||||||
|
tty_margin_off(tty);
|
||||||
|
|
||||||
|
/* Start with the default cell as the last cell. */
|
||||||
|
memcpy(&last, &grid_default_cell, sizeof last);
|
||||||
|
last.bg = defaults->bg;
|
||||||
|
tty_default_attributes(tty, defaults, palette, 8, s->hyperlinks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is padding at the start, we must have truncated a wide
|
* If there is padding at the start, we must have truncated a wide
|
||||||
* character. Clear it.
|
* character. Clear it.
|
||||||
@@ -195,7 +208,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
log_debug("%s: clearing %u padding cells", __func__, cx);
|
log_debug("%s: clearing %u padding cells", __func__, cx);
|
||||||
tty_draw_line_clear(tty, atx, aty, cx, defaults, bg, 0);
|
tty_draw_line_clear(tty, atx, aty, cx, defaults, bg, 0);
|
||||||
if (cx == ex)
|
if (cx == ex)
|
||||||
return;
|
goto out;
|
||||||
atx += cx;
|
atx += cx;
|
||||||
px += cx;
|
px += cx;
|
||||||
nx -= cx;
|
nx -= cx;
|
||||||
@@ -209,18 +222,6 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
wrapped = 1;
|
wrapped = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn off cursor while redrawing and reset region and margins. */
|
|
||||||
flags = (tty->flags & TTY_NOCURSOR);
|
|
||||||
tty->flags |= TTY_NOCURSOR;
|
|
||||||
tty_update_mode(tty, tty->mode, s);
|
|
||||||
tty_region_off(tty);
|
|
||||||
tty_margin_off(tty);
|
|
||||||
|
|
||||||
/* Start with the default cell as the last cell. */
|
|
||||||
memcpy(&last, &grid_default_cell, sizeof last);
|
|
||||||
last.bg = defaults->bg;
|
|
||||||
tty_default_attributes(tty, defaults, palette, 8, s->hyperlinks);
|
|
||||||
|
|
||||||
/* Loop over each character in the range. */
|
/* Loop over each character in the range. */
|
||||||
last_i = i = 0;
|
last_i = i = 0;
|
||||||
len = 0;
|
len = 0;
|
||||||
@@ -252,7 +253,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Work out the the empty width. */
|
/* Work out the the empty width. */
|
||||||
if (i >= ex)
|
if (px >= ex || i >= ex - px)
|
||||||
empty = 1;
|
empty = 1;
|
||||||
else if (gcp->bg != last.bg)
|
else if (gcp->bg != last.bg)
|
||||||
empty = 0;
|
empty = 0;
|
||||||
@@ -331,6 +332,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
i += gcp->data.width;
|
i += gcp->data.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
tty->flags = (tty->flags & ~TTY_NOCURSOR)|flags;
|
tty->flags = (tty->flags & ~TTY_NOCURSOR)|flags;
|
||||||
tty_update_mode(tty, tty->mode, s);
|
tty_update_mode(tty, tty->mode, s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -474,23 +474,46 @@ tty_default_features(int *feat, const char *name, u_int version)
|
|||||||
#define TTY_FEATURES_BASE_MODERN_XTERM \
|
#define TTY_FEATURES_BASE_MODERN_XTERM \
|
||||||
"256,RGB,bpaste,clipboard,mouse,strikethrough,title"
|
"256,RGB,bpaste,clipboard,mouse,strikethrough,title"
|
||||||
{ .name = "mintty",
|
{ .name = "mintty",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
",ccolour,cstyle,extkeys,margins,overline,usstyle"
|
"ccolour,"
|
||||||
|
"cstyle,"
|
||||||
|
"extkeys,"
|
||||||
|
"margins,"
|
||||||
|
"overline,"
|
||||||
|
"usstyle"
|
||||||
},
|
},
|
||||||
{ .name = "tmux",
|
{ .name = "tmux",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
",ccolour,cstyle,focus,overline,usstyle,hyperlinks"
|
"ccolour,"
|
||||||
|
"cstyle,"
|
||||||
|
"extkeys,"
|
||||||
|
"focus,"
|
||||||
|
"overline,"
|
||||||
|
"usstyle,"
|
||||||
|
"hyperlinks"
|
||||||
},
|
},
|
||||||
{ .name = "rxvt-unicode",
|
{ .name = "rxvt-unicode",
|
||||||
.features = "256,bpaste,ccolour,cstyle,mouse,title,ignorefkeys"
|
.features = "256,"
|
||||||
|
"bpaste,"
|
||||||
|
"ccolour,"
|
||||||
|
"cstyle,"
|
||||||
|
"mouse,"
|
||||||
|
"title,"
|
||||||
|
"ignorefkeys"
|
||||||
},
|
},
|
||||||
{ .name = "iTerm2",
|
{ .name = "iTerm2",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
",cstyle,extkeys,margins,usstyle,sync,osc7,hyperlinks"
|
"cstyle,"
|
||||||
|
"extkeys,"
|
||||||
|
"margins,"
|
||||||
|
"usstyle,"
|
||||||
|
"sync,"
|
||||||
|
"osc7,hyperlinks"
|
||||||
},
|
},
|
||||||
{ .name = "foot",
|
{ .name = "foot",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
",cstyle,extkeys"
|
"cstyle,"
|
||||||
|
"extkeys"
|
||||||
},
|
},
|
||||||
{ .name = "XTerm",
|
{ .name = "XTerm",
|
||||||
/*
|
/*
|
||||||
@@ -498,8 +521,11 @@ tty_default_features(int *feat, const char *name, u_int version)
|
|||||||
* disabled so not set it here - they will be added if
|
* disabled so not set it here - they will be added if
|
||||||
* secondary DA shows VT420.
|
* secondary DA shows VT420.
|
||||||
*/
|
*/
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
",ccolour,cstyle,extkeys,focus"
|
"ccolour,"
|
||||||
|
"cstyle,"
|
||||||
|
"extkeys,"
|
||||||
|
"focus"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|||||||
@@ -1383,7 +1383,7 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
|
|||||||
copy[end] = '\0';
|
copy[end] = '\0';
|
||||||
|
|
||||||
/* Convert from base64. */
|
/* Convert from base64. */
|
||||||
needed = (end / 4) * 3;
|
needed = ((end + 3) / 4) * 3;
|
||||||
if (needed == 0) {
|
if (needed == 0) {
|
||||||
free(copy);
|
free(copy);
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1034,6 +1034,8 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
|
|||||||
|
|
||||||
screen_resize(s, sx, sy, 0);
|
screen_resize(s, sx, sy, 0);
|
||||||
cx = data->cx;
|
cx = data->cx;
|
||||||
|
if (data->oy > gd->hsize + data->cy)
|
||||||
|
data->oy = gd->hsize + data->cy;
|
||||||
cy = gd->hsize + data->cy - data->oy;
|
cy = gd->hsize + data->cy - data->oy;
|
||||||
reflow = (gd->sx != sx);
|
reflow = (gd->sx != sx);
|
||||||
if (reflow)
|
if (reflow)
|
||||||
@@ -2747,6 +2749,8 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs)
|
|||||||
|
|
||||||
if (data->viewmode)
|
if (data->viewmode)
|
||||||
return (WINDOW_COPY_CMD_NOTHING);
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
if (data->oy > screen_hsize(data->backing))
|
||||||
|
data->oy = screen_hsize(data->backing);
|
||||||
oy_from_top = screen_hsize(data->backing) - data->oy;
|
oy_from_top = screen_hsize(data->backing) - data->oy;
|
||||||
|
|
||||||
screen_free(data->backing);
|
screen_free(data->backing);
|
||||||
@@ -3340,7 +3344,7 @@ window_copy_command(struct window_mode_entry *wme, struct client *c,
|
|||||||
enum window_copy_cmd_clear clear = WINDOW_COPY_CMD_CLEAR_NEVER;
|
enum window_copy_cmd_clear clear = WINDOW_COPY_CMD_CLEAR_NEVER;
|
||||||
const char *command;
|
const char *command;
|
||||||
u_int i, count = args_count(args);
|
u_int i, count = args_count(args);
|
||||||
int keys;
|
int keys, flags;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@@ -3362,9 +3366,10 @@ window_copy_command(struct window_mode_entry *wme, struct client *c,
|
|||||||
action = WINDOW_COPY_CMD_NOTHING;
|
action = WINDOW_COPY_CMD_NOTHING;
|
||||||
for (i = 0; i < nitems(window_copy_cmd_table); i++) {
|
for (i = 0; i < nitems(window_copy_cmd_table); i++) {
|
||||||
if (strcmp(window_copy_cmd_table[i].command, command) == 0) {
|
if (strcmp(window_copy_cmd_table[i].command, command) == 0) {
|
||||||
if (c->flags & CLIENT_READONLY &&
|
flags = window_copy_cmd_table[i].flags;
|
||||||
(~window_copy_cmd_table[i].flags &
|
if (c != NULL &&
|
||||||
WINDOW_COPY_CMD_FLAG_READONLY)) {
|
c->flags & CLIENT_READONLY &&
|
||||||
|
(~flags & WINDOW_COPY_CMD_FLAG_READONLY)) {
|
||||||
status_message_set(c, -1, 1, 0, 0,
|
status_message_set(c, -1, 1, 0, 0,
|
||||||
"client is read-only");
|
"client is read-only");
|
||||||
return;
|
return;
|
||||||
|
|||||||
48
window.c
48
window.c
@@ -653,10 +653,10 @@ struct window_pane *
|
|||||||
window_get_active_at(struct window *w, u_int x, u_int y)
|
window_get_active_at(struct window *w, u_int x, u_int y)
|
||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
int status, xoff, yoff;
|
int pane_status, xoff, yoff;
|
||||||
u_int sx, sy;
|
u_int sx, sy;
|
||||||
|
|
||||||
status = options_get_number(w->options, "pane-border-status");
|
pane_status = options_get_number(w->options, "pane-border-status");
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
if (!window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
@@ -667,7 +667,7 @@ window_get_active_at(struct window *w, u_int x, u_int y)
|
|||||||
right border. */
|
right border. */
|
||||||
if ((int)x < xoff || x > xoff + sx)
|
if ((int)x < xoff || x > xoff + sx)
|
||||||
continue;
|
continue;
|
||||||
if (status == PANE_STATUS_TOP) {
|
if (pane_status == PANE_STATUS_TOP) {
|
||||||
if ((int)y < yoff - 1 || y > yoff + sy)
|
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@@ -678,8 +678,13 @@ window_get_active_at(struct window *w, u_int x, u_int y)
|
|||||||
/* Floating, include top or or left border. */
|
/* Floating, include top or or left border. */
|
||||||
if ((int)x < xoff - 1 || x > xoff + sx)
|
if ((int)x < xoff - 1 || x > xoff + sx)
|
||||||
continue;
|
continue;
|
||||||
if ((int)y < yoff - 1 || y > yoff + sy)
|
if (pane_status == PANE_STATUS_TOP) {
|
||||||
|
if ((int)y <= yoff - 2 || y > yoff + sy - 1)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (wp);
|
return (wp);
|
||||||
}
|
}
|
||||||
@@ -990,9 +995,8 @@ window_printable_flags(struct winlink *wl, int escape)
|
|||||||
{
|
{
|
||||||
struct session *s = wl->session;
|
struct session *s = wl->session;
|
||||||
static char flags[32];
|
static char flags[32];
|
||||||
int pos;
|
u_int pos = 0;
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
if (wl->flags & WINLINK_ACTIVITY) {
|
if (wl->flags & WINLINK_ACTIVITY) {
|
||||||
flags[pos++] = '#';
|
flags[pos++] = '#';
|
||||||
if (escape)
|
if (escape)
|
||||||
@@ -1015,7 +1019,7 @@ window_printable_flags(struct winlink *wl, int escape)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
window_pane_printable_flags(struct window_pane *wp, __unused int escape)
|
window_pane_printable_flags(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
static char flags[32];
|
static char flags[32];
|
||||||
struct window *w = wp->window;
|
struct window *w = wp->window;
|
||||||
@@ -1099,6 +1103,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
window_pane_default_cursor(wp);
|
window_pane_default_cursor(wp);
|
||||||
|
|
||||||
screen_init(&wp->status_screen, 1, 1, 0);
|
screen_init(&wp->status_screen, 1, 1, 0);
|
||||||
|
style_ranges_init(&wp->border_status_line.ranges);
|
||||||
|
|
||||||
if (gethostname(host, sizeof host) == 0)
|
if (gethostname(host, sizeof host) == 0)
|
||||||
screen_set_title(&wp->base, host);
|
screen_set_title(&wp->base, host);
|
||||||
@@ -1151,6 +1156,7 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
free(wp->shell);
|
free(wp->shell);
|
||||||
cmd_free_argv(wp->argc, wp->argv);
|
cmd_free_argv(wp->argc, wp->argv);
|
||||||
colour_palette_free(&wp->palette);
|
colour_palette_free(&wp->palette);
|
||||||
|
style_ranges_free(&wp->border_status_line.ranges);
|
||||||
free(wp);
|
free(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2121,3 +2127,31 @@ window_pane_send_theme_update(struct window_pane *wp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct style_range *
|
||||||
|
window_pane_border_status_get_range(struct window_pane *wp, u_int x, u_int y)
|
||||||
|
{
|
||||||
|
struct style_ranges *srs;
|
||||||
|
struct window *w = wp->window;
|
||||||
|
struct options *wo = w->options;
|
||||||
|
u_int line;
|
||||||
|
int pane_status;
|
||||||
|
|
||||||
|
if (wp == NULL)
|
||||||
|
return (NULL);
|
||||||
|
srs = &wp->border_status_line.ranges;
|
||||||
|
|
||||||
|
pane_status = options_get_number(wo, "pane-border-status");
|
||||||
|
if (pane_status == PANE_STATUS_TOP)
|
||||||
|
line = wp->yoff - 1;
|
||||||
|
else if (pane_status == PANE_STATUS_BOTTOM)
|
||||||
|
line = wp->yoff + wp->sy;
|
||||||
|
if (pane_status == PANE_STATUS_OFF || line != y)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The border formats start 2 off but that isn't reflected in
|
||||||
|
* the stored bounds of the range.
|
||||||
|
*/
|
||||||
|
return (style_ranges_get_range(srs, x - wp->xoff - 2));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user