From 36d904011a0620284ad3a51639a090024f2575fb Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Aug 2022 08:57:01 +0000 Subject: -u is no longer equivalent to -TUTF-8 so don't say it is. --- tmux.1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/tmux.1 b/tmux.1 index 1fc2d061..a1298fe0 100644 --- a/tmux.1 +++ b/tmux.1 @@ -214,8 +214,6 @@ that is set does not contain .Qq UTF-8 or .Qq UTF8 . -This is equivalent to -.Fl T Ar UTF-8 . .It Fl T Ar features Set terminal features for the client. This is a comma-separated list of features. -- cgit From 33c59100aeb49894550b97cce268f46032f4c8d6 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Aug 2022 09:23:34 +0000 Subject: Fix validation of missing percentage arguments. --- arguments.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arguments.c b/arguments.c index 485af2be..b08582ee 100644 --- a/arguments.c +++ b/arguments.c @@ -895,6 +895,10 @@ args_percentage(struct args *args, u_char flag, long long minval, *cause = xstrdup("missing"); return (0); } + if (TAILQ_EMPTY(&entry->values)) { + *cause = xstrdup("empty"); + return (0); + } value = TAILQ_LAST(&entry->values, args_values)->string; return (args_string_percentage(value, minval, maxval, curval, cause)); } @@ -909,6 +913,10 @@ args_string_percentage(const char *value, long long minval, long long maxval, size_t valuelen = strlen(value); char *copy; + if (valuelen == 0) { + *cause = xstrdup("empty"); + return (0); + } if (value[valuelen - 1] == '%') { copy = xstrdup(value); copy[valuelen - 1] = '\0'; @@ -955,6 +963,10 @@ args_percentage_and_expand(struct args *args, u_char flag, long long minval, *cause = xstrdup("missing"); return (0); } + if (TAILQ_EMPTY(&entry->values)) { + *cause = xstrdup("empty"); + return (0); + } value = TAILQ_LAST(&entry->values, args_values)->string; return (args_string_percentage_and_expand(value, minval, maxval, curval, item, cause)); -- cgit From 00812c9053a0b1067f833925b726086a67d8528d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 2 Aug 2022 11:52:09 +0100 Subject: Check for $YACC, from Wei Shih in GitHub issue 3267. --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index 276f71c8..8e846042 100644 --- a/configure.ac +++ b/configure.ac @@ -267,6 +267,12 @@ if test "x$found_libevent" = xno; then AC_MSG_ERROR("libevent not found") fi +# Look for yacc. +AC_CHECK_PROG(found_yacc, $YACC, yes, no) +if test "x$found_yacc" = xno; then + AC_MSG_ERROR("yacc not found") +fi + # Look for ncurses or curses. Try pkg-config first then directly for the # library. PKG_CHECK_MODULES( -- cgit From 42ba6c1b229c92256274e848e9c5ff1d59d9081b Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Aug 2022 11:09:26 +0000 Subject: Add a third state "all" to allow-passthrough to work even in invisible panes, from Sergei Grechanik in GitHub issue 3274. --- input.c | 11 ++++++++--- options-table.c | 10 ++++++++-- screen-write.c | 4 +++- tmux.1 | 8 +++++++- tmux.h | 46 +++++++++++++++++++++++++++------------------- tty.c | 21 ++++++++++++++------- 6 files changed, 67 insertions(+), 33 deletions(-) diff --git a/input.c b/input.c index 4252428b..d8b334de 100644 --- a/input.c +++ b/input.c @@ -2242,22 +2242,27 @@ static int input_dcs_dispatch(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; + struct options *oo = wp->options; struct screen_write_ctx *sctx = &ictx->ctx; u_char *buf = ictx->input_buf; size_t len = ictx->input_len; const char prefix[] = "tmux;"; const u_int prefixlen = (sizeof prefix) - 1; + long long allow_passthrough = 0; if (wp == NULL) return (0); if (ictx->flags & INPUT_DISCARD) return (0); - if (!options_get_number(ictx->wp->options, "allow-passthrough")) + allow_passthrough = options_get_number(oo, "allow-passthrough"); + if (!allow_passthrough) return (0); log_debug("%s: \"%s\"", __func__, buf); - if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) - screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen); + if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) { + screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen, + allow_passthrough == 2); + } return (0); } diff --git a/options-table.c b/options-table.c index d1e65f15..377835bb 100644 --- a/options-table.c +++ b/options-table.c @@ -88,6 +88,9 @@ static const char *options_table_detach_on_destroy_list[] = { static const char *options_table_extended_keys_list[] = { "off", "on", "always", NULL }; +static const char *options_table_allow_passthrough_list[] = { + "off", "on", "all", NULL +}; /* Status line format. */ #define OPTIONS_TABLE_STATUS_FORMAT1 \ @@ -804,11 +807,14 @@ const struct options_table_entry options_table[] = { }, { .name = "allow-passthrough", - .type = OPTIONS_TABLE_FLAG, + .type = OPTIONS_TABLE_CHOICE, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, + .choices = options_table_allow_passthrough_list, .default_num = 0, .text = "Whether applications are allowed to use the escape sequence " - "to bypass tmux." + "to bypass tmux. Can be 'off' (disallowed), 'on' (allowed " + "if the pane is visible), or 'all' (allowed even if the pane " + "is invisible)." }, { .name = "allow-rename", diff --git a/screen-write.c b/screen-write.c index 213b533c..476fe4dd 100644 --- a/screen-write.c +++ b/screen-write.c @@ -2100,13 +2100,15 @@ screen_write_setselection(struct screen_write_ctx *ctx, const char *flags, /* Write unmodified string. */ void -screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) +screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len, + int allow_invisible_panes) { struct tty_ctx ttyctx; screen_write_initctx(ctx, &ttyctx, 0); ttyctx.ptr = str; ttyctx.num = len; + ttyctx.allow_invisible_panes = allow_invisible_panes; tty_write(tty_cmd_rawstring, &ttyctx); } diff --git a/tmux.1 b/tmux.1 index a1298fe0..fa7fcbfb 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4461,11 +4461,17 @@ Available pane options are: .Pp .Bl -tag -width Ds -compact .It Xo Ic allow-passthrough -.Op Ic on | off +.Op Ic on | off | all .Xc Allow programs in the pane to bypass .Nm using a terminal escape sequence (\eePtmux;...\ee\e\e). +If set to +.Ic on , +passthrough sequences will be allowed only if the pane is visible. +If set to +.Ic all , +they will be allowed even if the pane is invisible. .Pp .It Xo Ic allow-rename .Op Ic on | off diff --git a/tmux.h b/tmux.h index 3f720e50..4196a31c 100644 --- a/tmux.h +++ b/tmux.h @@ -1431,38 +1431,45 @@ struct tty_ctx { void *ptr; void *ptr2; + /* + * Whether this command should be sent even when the pane is not + * visible (used for a passthrough sequence when allow-passthrough is + * "all"). + */ + int allow_invisible_panes; + /* * Cursor and region position before the screen was updated - this is * where the command should be applied; the values in the screen have * already been updated. */ - u_int ocx; - u_int ocy; + u_int ocx; + u_int ocy; - u_int orupper; - u_int orlower; + u_int orupper; + u_int orlower; /* Target region (usually pane) offset and size. */ - u_int xoff; - u_int yoff; - u_int rxoff; - u_int ryoff; - u_int sx; - u_int sy; + u_int xoff; + u_int yoff; + u_int rxoff; + u_int ryoff; + u_int sx; + u_int sy; /* The background colour used for clearing (erasing). */ - u_int bg; + u_int bg; /* The default colours and palette. */ - struct grid_cell defaults; - struct colour_palette *palette; + struct grid_cell defaults; + struct colour_palette *palette; /* Containing region (usually window) offset and size. */ - int bigger; - u_int wox; - u_int woy; - u_int wsx; - u_int wsy; + int bigger; + u_int wox; + u_int woy; + u_int wsx; + u_int wsy; }; /* Saved message entry. */ @@ -2889,7 +2896,8 @@ void screen_write_collect_add(struct screen_write_ctx *, void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_setselection(struct screen_write_ctx *, const char *, u_char *, u_int); -void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); +void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int, + int); void screen_write_alternateon(struct screen_write_ctx *, struct grid_cell *, int); void screen_write_alternateoff(struct screen_write_ctx *, diff --git a/tty.c b/tty.c index 1f373821..a7ad536f 100644 --- a/tty.c +++ b/tty.c @@ -1626,13 +1626,20 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *), if (ctx->set_client_cb == NULL) return; TAILQ_FOREACH(c, &clients, entry) { - if (!tty_client_ready(c)) - continue; - state = ctx->set_client_cb(ctx, c); - if (state == -1) - break; - if (state == 0) - continue; + if (ctx->allow_invisible_panes) { + if (c->session == NULL || + c->tty.term == NULL || + c->flags & CLIENT_SUSPENDED) + continue; + } else { + if (!tty_client_ready(c)) + continue; + state = ctx->set_client_cb(ctx, c); + if (state == -1) + break; + if (state == 0) + continue; + } cmdfn(&c->tty, ctx); } } -- cgit From c6e7568471f35f7a22e199b444adf17c685e86f3 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 3 Aug 2022 13:27:48 +0000 Subject: Do not crash when searching for .* with extremely long lines. Reported by Torbjorn Lonnemark, GitHub issue 3272. --- window-copy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/window-copy.c b/window-copy.c index ab7ed5b1..834a2d99 100644 --- a/window-copy.c +++ b/window-copy.c @@ -3673,6 +3673,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex) if (direction && window_copy_search_mark_at(data, fx, fy, &at) == 0 && at > 0 && + data->searchmark != NULL && data->searchmark[at] == data->searchmark[at - 1]) { window_copy_move_after_search_mark(data, &fx, &fy, wrapflag); @@ -3705,6 +3706,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex) &start) == 0) { while (window_copy_search_mark_at(data, fx, fy, &at) == 0 && + data->searchmark != NULL && data->searchmark[at] == data->searchmark[start]) { data->cx = fx; -- cgit From de5cd54124e37672adfdfe0229712e7e74acc9b0 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 4 Aug 2022 12:06:09 +0000 Subject: Change g and G to go to top and bottom of menu, GitHub issue 3286. --- menu.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/menu.c b/menu.c index dc3b289f..4aad1d8c 100644 --- a/menu.c +++ b/menu.c @@ -323,27 +323,64 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) } while ((name == NULL || *name == '-') && md->choice != old); c->flags |= CLIENT_REDRAWOVERLAY; return (0); - case 'g': case KEYC_PPAGE: case '\002': /* C-b */ - if (md->choice > 5) - md->choice -= 5; - else + if (md->choice < 6) md->choice = 0; - while (md->choice != count && (name == NULL || *name == '-')) - md->choice++; - if (md->choice == count) - md->choice = -1; + else { + i = 5; + while (i > 0) { + md->choice--; + name = menu->items[md->choice].name; + if (md->choice != 0 && + (name != NULL && *name != '-')) + i--; + else if (md->choice == 0) + break; + } + } c->flags |= CLIENT_REDRAWOVERLAY; break; - case 'G': case KEYC_NPAGE: - if (md->choice > count - 6) + if (md->choice > count - 6) { md->choice = count - 1; - else - md->choice += 5; - while (md->choice != -1 && (name == NULL || *name == '-')) + name = menu->items[md->choice].name; + } else { + i = 5; + while (i > 0) { + md->choice++; + name = menu->items[md->choice].name; + if (md->choice != count - 1 && + (name != NULL && *name != '-')) + i++; + else if (md->choice == count - 1) + break; + } + } + while (name == NULL || *name == '-') { md->choice--; + name = menu->items[md->choice].name; + } + c->flags |= CLIENT_REDRAWOVERLAY; + break; + case 'g': + case KEYC_HOME: + md->choice = 0; + name = menu->items[md->choice].name; + while (name == NULL || *name == '-') { + md->choice++; + name = menu->items[md->choice].name; + } + c->flags |= CLIENT_REDRAWOVERLAY; + break; + case 'G': + case KEYC_END: + md->choice = count - 1; + name = menu->items[md->choice].name; + while (name == NULL || *name == '-') { + md->choice--; + name = menu->items[md->choice].name; + } c->flags |= CLIENT_REDRAWOVERLAY; break; case '\006': /* C-f */ -- cgit From 273577ba0a88c8a373bc8a2ded7e6a08b82114d0 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 10 Aug 2022 14:03:59 +0000 Subject: Fix check of home directory (&& not ||), from Markus F X J Oberhumer, GitHub issue 3297. --- spawn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spawn.c b/spawn.c index 2349f1b3..98c9ba52 100644 --- a/spawn.c +++ b/spawn.c @@ -391,7 +391,7 @@ spawn_pane(struct spawn_context *sc, char **cause) */ if (chdir(new_wp->cwd) == 0) environ_set(child, "PWD", 0, "%s", new_wp->cwd); - else if ((tmp = find_home()) != NULL || chdir(tmp) == 0) + else if ((tmp = find_home()) != NULL && chdir(tmp) == 0) environ_set(child, "PWD", 0, "%s", tmp); else if (chdir("/") == 0) environ_set(child, "PWD", 0, "/"); -- cgit From e139f977b150d526b3403d7996fdc6690dea0932 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 11 Aug 2022 09:11:26 +0000 Subject: vi(1) Home/End bindings, from Markus F X J Oberhumer. --- key-bindings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/key-bindings.c b/key-bindings.c index bcc6004d..6ce9c14c 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -616,6 +616,8 @@ key_bindings_init(void) "bind -Tcopy-mode-vi '{' { send -X previous-paragraph }", "bind -Tcopy-mode-vi '}' { send -X next-paragraph }", "bind -Tcopy-mode-vi % { send -X next-matching-bracket }", + "bind -Tcopy-mode-vi Home { send -X start-of-line }", + "bind -Tcopy-mode-vi End { send -X end-of-line }", "bind -Tcopy-mode-vi MouseDown1Pane { select-pane }", "bind -Tcopy-mode-vi MouseDrag1Pane { select-pane; send -X begin-selection }", "bind -Tcopy-mode-vi MouseDragEnd1Pane { send -X copy-pipe-and-cancel }", -- cgit From cfdc5b62ad64a4a41a604cd3b8ae00d9bb928bdf Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 15 Aug 2022 08:37:03 +0000 Subject: Don't stop at first match when updating environment. --- environ.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/environ.c b/environ.c index 74d672e0..5abf383c 100644 --- a/environ.c +++ b/environ.c @@ -182,9 +182,11 @@ void environ_update(struct options *oo, struct environ *src, struct environ *dst) { struct environ_entry *envent; + struct environ_entry *envent1; struct options_entry *o; struct options_array_item *a; union options_value *ov; + int found; o = options_get(oo, "update-environment"); if (o == NULL) @@ -192,14 +194,15 @@ environ_update(struct options *oo, struct environ *src, struct environ *dst) a = options_array_first(o); while (a != NULL) { ov = options_array_item_value(a); - RB_FOREACH(envent, environ, src) { - if (fnmatch(ov->string, envent->name, 0) == 0) - break; + found = 0; + RB_FOREACH_SAFE(envent, environ, src, envent1) { + if (fnmatch(ov->string, envent->name, 0) == 0) { + environ_set(dst, envent->name, 0, "%s", envent->value); + found = 1; + } } - if (envent == NULL) + if (!found) environ_clear(dst, ov->string); - else - environ_set(dst, envent->name, 0, "%s", envent->value); a = options_array_next(a); } } -- cgit From 497021d0db40790cc9a98bb1d70ae091d170831e Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 15 Aug 2022 08:41:13 +0000 Subject: Add some const, from Markus F X J Oberhumer. --- key-bindings.c | 2 +- tty-features.c | 54 +++++++++++++++++++++++++++--------------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/key-bindings.c b/key-bindings.c index 6ce9c14c..4b790dfc 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -344,7 +344,7 @@ key_bindings_init_done(__unused struct cmdq_item *item, __unused void *data) void key_bindings_init(void) { - static const char *defaults[] = { + static const char *const defaults[] = { /* Prefix keys. */ "bind -N 'Send the prefix key' C-b { send-prefix }", "bind -N 'Rotate through the panes' C-o { rotate-window }", diff --git a/tty-features.c b/tty-features.c index 396a351e..261cb2b8 100644 --- a/tty-features.c +++ b/tty-features.c @@ -36,13 +36,13 @@ /* A named terminal feature. */ struct tty_feature { - const char *name; - const char **capabilities; - int flags; + const char *name; + const char *const *capabilities; + int flags; }; /* Terminal has xterm(1) title setting. */ -static const char *tty_feature_title_capabilities[] = { +static const char *const tty_feature_title_capabilities[] = { "tsl=\\E]0;", /* should be using TS really */ "fsl=\\a", NULL @@ -54,7 +54,7 @@ static const struct tty_feature tty_feature_title = { }; /* Terminal has OSC 7 working directory. */ -static const char *tty_feature_osc7_capabilities[] = { +static const char *const tty_feature_osc7_capabilities[] = { "Swd=\\E]7;", "fsl=\\a", NULL @@ -66,7 +66,7 @@ static const struct tty_feature tty_feature_osc7 = { }; /* Terminal has mouse support. */ -static const char *tty_feature_mouse_capabilities[] = { +static const char *const tty_feature_mouse_capabilities[] = { "kmous=\\E[M", NULL }; @@ -77,7 +77,7 @@ static const struct tty_feature tty_feature_mouse = { }; /* Terminal can set the clipboard with OSC 52. */ -static const char *tty_feature_clipboard_capabilities[] = { +static const char *const tty_feature_clipboard_capabilities[] = { "Ms=\\E]52;%p1%s;%p2%s\\a", NULL }; @@ -88,7 +88,7 @@ static const struct tty_feature tty_feature_clipboard = { }; /* Terminal supports OSC 8 hyperlinks. */ -static const char *tty_feature_hyperlinks_capabilities[] = { +static const char *const tty_feature_hyperlinks_capabilities[] = { "*:Hls=\\E]8;%?%p1%l%tid=%p1%s%;;%p2%s\\E\\\\", NULL }; @@ -103,7 +103,7 @@ static const struct tty_feature tty_feature_hyperlinks = { * terminals with RGB have versions that do not allow setting colours from the * 256 palette. */ -static const char *tty_feature_rgb_capabilities[] = { +static const char *const tty_feature_rgb_capabilities[] = { "AX", "setrgbf=\\E[38;2;%p1%d;%p2%d;%p3%dm", "setrgbb=\\E[48;2;%p1%d;%p2%d;%p3%dm", @@ -118,7 +118,7 @@ static const struct tty_feature tty_feature_rgb = { }; /* Terminal supports 256 colours. */ -static const char *tty_feature_256_capabilities[] = { +static const char *const tty_feature_256_capabilities[] = { "AX", "setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", "setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", @@ -131,7 +131,7 @@ static const struct tty_feature tty_feature_256 = { }; /* Terminal supports overline. */ -static const char *tty_feature_overline_capabilities[] = { +static const char *const tty_feature_overline_capabilities[] = { "Smol=\\E[53m", NULL }; @@ -142,7 +142,7 @@ static const struct tty_feature tty_feature_overline = { }; /* Terminal supports underscore styles. */ -static const char *tty_feature_usstyle_capabilities[] = { +static const char *const tty_feature_usstyle_capabilities[] = { "Smulx=\\E[4::%p1%dm", "Setulc=\\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m", "ol=\\E[59m", @@ -155,7 +155,7 @@ static const struct tty_feature tty_feature_usstyle = { }; /* Terminal supports bracketed paste. */ -static const char *tty_feature_bpaste_capabilities[] = { +static const char *const tty_feature_bpaste_capabilities[] = { "Enbp=\\E[?2004h", "Dsbp=\\E[?2004l", NULL @@ -167,7 +167,7 @@ static const struct tty_feature tty_feature_bpaste = { }; /* Terminal supports focus reporting. */ -static const char *tty_feature_focus_capabilities[] = { +static const char *const tty_feature_focus_capabilities[] = { "Enfcs=\\E[?1004h", "Dsfcs=\\E[?1004l", NULL @@ -179,7 +179,7 @@ static const struct tty_feature tty_feature_focus = { }; /* Terminal supports cursor styles. */ -static const char *tty_feature_cstyle_capabilities[] = { +static const char *const tty_feature_cstyle_capabilities[] = { "Ss=\\E[%p1%d q", "Se=\\E[2 q", NULL @@ -191,7 +191,7 @@ static const struct tty_feature tty_feature_cstyle = { }; /* Terminal supports cursor colours. */ -static const char *tty_feature_ccolour_capabilities[] = { +static const char *const tty_feature_ccolour_capabilities[] = { "Cs=\\E]12;%p1%s\\a", "Cr=\\E]112\\a", NULL @@ -203,7 +203,7 @@ static const struct tty_feature tty_feature_ccolour = { }; /* Terminal supports strikethrough. */ -static const char *tty_feature_strikethrough_capabilities[] = { +static const char *const tty_feature_strikethrough_capabilities[] = { "smxx=\\E[9m", NULL }; @@ -214,7 +214,7 @@ static const struct tty_feature tty_feature_strikethrough = { }; /* Terminal supports synchronized updates. */ -static const char *tty_feature_sync_capabilities[] = { +static const char *const tty_feature_sync_capabilities[] = { "Sync=\\EP=%p1%ds\\E\\\\", NULL }; @@ -225,7 +225,7 @@ static const struct tty_feature tty_feature_sync = { }; /* Terminal supports extended keys. */ -static const char *tty_feature_extkeys_capabilities[] = { +static const char *const tty_feature_extkeys_capabilities[] = { "Eneks=\\E[>4;1m", "Dseks=\\E[>4m", NULL @@ -237,7 +237,7 @@ static const struct tty_feature tty_feature_extkeys = { }; /* Terminal supports DECSLRM margins. */ -static const char *tty_feature_margins_capabilities[] = { +static const char *const tty_feature_margins_capabilities[] = { "Enmg=\\E[?69h", "Dsmg=\\E[?69l", "Clmg=\\E[s", @@ -251,7 +251,7 @@ static const struct tty_feature tty_feature_margins = { }; /* Terminal supports DECFRA rectangle fill. */ -static const char *tty_feature_rectfill_capabilities[] = { +static const char *const tty_feature_rectfill_capabilities[] = { "Rect", NULL }; @@ -262,7 +262,7 @@ static const struct tty_feature tty_feature_rectfill = { }; /* Use builtin function keys only. */ -static const char *tty_feature_ignorefkeys_capabilities[] = { +static const char *const tty_feature_ignorefkeys_capabilities[] = { "kf0@", "kf1@", "kf2@", @@ -336,7 +336,7 @@ static const struct tty_feature tty_feature_ignorefkeys = { }; /* Available terminal features. */ -static const struct tty_feature *tty_features[] = { +static const struct tty_feature *const tty_features[] = { &tty_feature_256, &tty_feature_bpaste, &tty_feature_ccolour, @@ -410,9 +410,9 @@ tty_get_features(int feat) int tty_apply_features(struct tty_term *term, int feat) { - const struct tty_feature *tf; - const char **capability; - u_int i; + const struct tty_feature *tf; + const char *const *capability; + u_int i; if (feat == 0) return (0); @@ -443,7 +443,7 @@ tty_apply_features(struct tty_term *term, int feat) void tty_default_features(int *feat, const char *name, u_int version) { - static struct { + static const struct { const char *name; u_int version; const char *features; -- cgit From 03149bf7f62e2c92d0e60087c52604d2dd51794f Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 15 Aug 2022 08:54:03 +0000 Subject: Add a Nobr terminfo capability to tell tmux the terminal does not use bright colours for bold (makes a difference to how tmux applies palette differences). From Damien Tardy-Panis in GitHub issue 3301. --- tmux.1 | 4 ++++ tmux.h | 1 + tty-term.c | 1 + tty.c | 8 +++++--- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tmux.1 b/tmux.1 index fa7fcbfb..b6283373 100644 --- a/tmux.1 +++ b/tmux.1 @@ -6430,6 +6430,10 @@ These are set automatically if the capability is present. .It Em \&Hls Set or clear a hyperlink annotation. +.It Em \&Nobr +Tell +.Nm +that the terminal does not use bright colors for bold display. .It Em \&Rect Tell .Nm diff --git a/tmux.h b/tmux.h index 4196a31c..413d8c38 100644 --- a/tmux.h +++ b/tmux.h @@ -514,6 +514,7 @@ enum tty_code_code { TTYC_KUP6, TTYC_KUP7, TTYC_MS, + TTYC_NOBR, TTYC_OL, TTYC_OP, TTYC_RECT, diff --git a/tty-term.c b/tty-term.c index a877ef6b..e3167f19 100644 --- a/tty-term.c +++ b/tty-term.c @@ -247,6 +247,7 @@ static const struct tty_term_code_entry tty_term_codes[] = { [TTYC_KUP6] = { TTYCODE_STRING, "kUP6" }, [TTYC_KUP7] = { TTYCODE_STRING, "kUP7" }, [TTYC_MS] = { TTYCODE_STRING, "Ms" }, + [TTYC_NOBR] = { TTYCODE_STRING, "Nobr" }, [TTYC_OL] = { TTYCODE_STRING, "ol" }, [TTYC_OP] = { TTYCODE_STRING, "op" }, [TTYC_RECT] = { TTYCODE_STRING, "Rect" }, diff --git a/tty.c b/tty.c index a7ad536f..1394075d 100644 --- a/tty.c +++ b/tty.c @@ -2690,12 +2690,14 @@ tty_check_fg(struct tty *tty, struct colour_palette *palette, /* * Perform substitution if this pane has a palette. If the bright - * attribute is set, use the bright entry in the palette by changing to - * the aixterm colour. + * attribute is set and Nobr is not present, use the bright entry in + * the palette by changing to the aixterm colour */ if (~gc->flags & GRID_FLAG_NOPALETTE) { c = gc->fg; - if (c < 8 && gc->attr & GRID_ATTR_BRIGHT) + if (c < 8 && + gc->attr & GRID_ATTR_BRIGHT && + !tty_term_has(tty->term, TTYC_NOBR)) c += 90; if ((c = colour_palette_get(palette, c)) != -1) gc->fg = c; -- cgit From 7c2dcd72380dc2d9e119e99cb423a67ae17b6bd2 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 15 Aug 2022 09:10:34 +0000 Subject: Notify when a paste buffer is deleted, GitHub issue 3302 from George Nachman. --- control-notify.c | 13 +++++++++++++ notify.c | 29 ++++++++++++++++++++++------- paste.c | 11 +++++++++++ tmux.1 | 4 ++++ tmux.h | 2 ++ 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/control-notify.c b/control-notify.c index 6ff0e436..a252dd05 100644 --- a/control-notify.c +++ b/control-notify.c @@ -234,3 +234,16 @@ control_notify_session_window_changed(struct session *s) s->curw->window->id); } } + +void +control_notify_paste_buffer_changed(const char *name) +{ + struct client *c; + + TAILQ_FOREACH(c, &clients, entry) { + if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) + continue; + + control_write(c, "%%paste-changed %s", name); + } +} diff --git a/notify.c b/notify.c index 619bd933..03730b98 100644 --- a/notify.c +++ b/notify.c @@ -33,6 +33,7 @@ struct notify_entry { struct session *session; struct window *window; int pane; + const char *pbname; }; static struct cmdq_item * @@ -150,6 +151,8 @@ notify_callback(struct cmdq_item *item, void *data) control_notify_session_closed(ne->session); if (strcmp(ne->name, "session-window-changed") == 0) control_notify_session_window_changed(ne->session); + if (strcmp(ne->name, "paste-buffer-changed") == 0) + control_notify_paste_buffer_changed(ne->pbname); notify_insert_hook(item, ne); @@ -165,6 +168,7 @@ notify_callback(struct cmdq_item *item, void *data) format_free(ne->formats); free((void *)ne->name); + free((void *)ne->pbname); free(ne); return (CMD_RETURN_NORMAL); @@ -172,7 +176,8 @@ notify_callback(struct cmdq_item *item, void *data) static void notify_add(const char *name, struct cmd_find_state *fs, struct client *c, - struct session *s, struct window *w, struct window_pane *wp) + struct session *s, struct window *w, struct window_pane *wp, + const char *pbname) { struct notify_entry *ne; struct cmdq_item *item; @@ -188,6 +193,7 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c, ne->session = s; ne->window = w; ne->pane = (wp != NULL ? wp->id : -1); + ne->pbname = (pbname != NULL ? xstrdup(pbname) : NULL); ne->formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS); format_add(ne->formats, "hook", "%s", name); @@ -249,7 +255,7 @@ notify_client(const char *name, struct client *c) struct cmd_find_state fs; cmd_find_from_client(&fs, c, 0); - notify_add(name, &fs, c, NULL, NULL, NULL); + notify_add(name, &fs, c, NULL, NULL, NULL, NULL); } void @@ -261,7 +267,7 @@ notify_session(const char *name, struct session *s) cmd_find_from_session(&fs, s, 0); else cmd_find_from_nothing(&fs, 0); - notify_add(name, &fs, NULL, s, NULL, NULL); + notify_add(name, &fs, NULL, s, NULL, NULL, NULL); } void @@ -270,7 +276,7 @@ notify_winlink(const char *name, struct winlink *wl) struct cmd_find_state fs; cmd_find_from_winlink(&fs, wl, 0); - notify_add(name, &fs, NULL, wl->session, wl->window, NULL); + notify_add(name, &fs, NULL, wl->session, wl->window, NULL, NULL); } void @@ -279,7 +285,7 @@ notify_session_window(const char *name, struct session *s, struct window *w) struct cmd_find_state fs; cmd_find_from_session_window(&fs, s, w, 0); - notify_add(name, &fs, NULL, s, w, NULL); + notify_add(name, &fs, NULL, s, w, NULL, NULL); } void @@ -288,7 +294,7 @@ notify_window(const char *name, struct window *w) struct cmd_find_state fs; cmd_find_from_window(&fs, w, 0); - notify_add(name, &fs, NULL, NULL, w, NULL); + notify_add(name, &fs, NULL, NULL, w, NULL, NULL); } void @@ -297,5 +303,14 @@ notify_pane(const char *name, struct window_pane *wp) struct cmd_find_state fs; cmd_find_from_pane(&fs, wp, 0); - notify_add(name, &fs, NULL, NULL, NULL, wp); + notify_add(name, &fs, NULL, NULL, NULL, wp, NULL); +} + +void +notify_paste_buffer(const char *pbname) +{ + struct cmd_find_state fs; + + cmd_find_clear_state(&fs, 0); + notify_add("paste-buffer-changed", &fs, NULL, NULL, NULL, NULL, pbname); } diff --git a/paste.c b/paste.c index 5ff36854..53477387 100644 --- a/paste.c +++ b/paste.c @@ -151,6 +151,8 @@ paste_get_name(const char *name) void paste_free(struct paste_buffer *pb) { + notify_paste_buffer(pb->name); + RB_REMOVE(paste_name_tree, &paste_by_name, pb); RB_REMOVE(paste_time_tree, &paste_by_time, pb); if (pb->automatic) @@ -207,6 +209,8 @@ paste_add(const char *prefix, char *data, size_t size) pb->order = paste_next_order++; RB_INSERT(paste_name_tree, &paste_by_name, pb); RB_INSERT(paste_time_tree, &paste_by_time, pb); + + notify_paste_buffer(pb->name); } /* Rename a paste buffer. */ @@ -254,6 +258,9 @@ paste_rename(const char *oldname, const char *newname, char **cause) RB_INSERT(paste_name_tree, &paste_by_name, pb); + notify_paste_buffer(oldname); + notify_paste_buffer(newname); + return (0); } @@ -302,6 +309,8 @@ paste_set(char *data, size_t size, const char *name, char **cause) RB_INSERT(paste_name_tree, &paste_by_name, pb); RB_INSERT(paste_time_tree, &paste_by_time, pb); + notify_paste_buffer(name); + return (0); } @@ -312,6 +321,8 @@ paste_replace(struct paste_buffer *pb, char *data, size_t size) free(pb->data); pb->data = data; pb->size = size; + + notify_paste_buffer(pb->name); } /* Convert start of buffer into a nice string. */ diff --git a/tmux.1 b/tmux.1 index b6283373..3a378c49 100644 --- a/tmux.1 +++ b/tmux.1 @@ -6596,6 +6596,10 @@ escapes non-printable characters and backslash as octal \\xxx. The pane with ID .Ar pane-id has changed mode. +.It Ic %paste-buffer-changed Ar name +Paste buffer +.Ar name +has been changed. .It Ic %pause Ar pane-id The pane has been paused (if the .Ar pause-after diff --git a/tmux.h b/tmux.h index 413d8c38..9b43e0fd 100644 --- a/tmux.h +++ b/tmux.h @@ -2154,6 +2154,7 @@ void notify_winlink(const char *, struct winlink *); void notify_session_window(const char *, struct session *, struct window *); void notify_window(const char *, struct window *); void notify_pane(const char *, struct window_pane *); +void notify_paste_buffer(const char *); /* options.c */ struct options *options_create(struct options *); @@ -3174,6 +3175,7 @@ void control_notify_session_renamed(struct session *); void control_notify_session_created(struct session *); void control_notify_session_closed(struct session *); void control_notify_session_window_changed(struct session *); +void control_notify_paste_buffer_changed(const char *); /* session.c */ extern struct sessions sessions; -- cgit From 19344efa78be23a02008be9da0991f54455c9f9e Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 22 Aug 2022 08:20:49 +0100 Subject: Fix fallback implementaion of getpeereid, from Pino Toscano. --- compat/getpeereid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compat/getpeereid.c b/compat/getpeereid.c index c194e886..b79f420a 100644 --- a/compat/getpeereid.c +++ b/compat/getpeereid.c @@ -18,6 +18,7 @@ #include #include +#include #ifdef HAVE_UCRED_H #include @@ -49,6 +50,8 @@ getpeereid(int s, uid_t *uid, gid_t *gid) ucred_free(ucred); return (0); #else - return (getuid()); + *uid = geteuid(); + *gid = getegid(); + return (0); #endif } -- cgit From 416c27c9958e928b9ff845c1701acf5b10d0db8d Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 23 Aug 2022 08:14:19 +0000 Subject: Add scroll-middle copy mode command to make cursor line in the middle, from Varun Kumar E in GitHub issue 3307. --- key-bindings.c | 1 + tmux.1 | 1 + window-copy.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/key-bindings.c b/key-bindings.c index 4b790dfc..528e0b73 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -605,6 +605,7 @@ key_bindings_init(void) "bind -Tcopy-mode-vi h { send -X cursor-left }", "bind -Tcopy-mode-vi j { send -X cursor-down }", "bind -Tcopy-mode-vi k { send -X cursor-up }", + "bind -Tcopy-mode-vi z { send -X scroll-middle }", "bind -Tcopy-mode-vi l { send -X cursor-right }", "bind -Tcopy-mode-vi n { send -X search-again }", "bind -Tcopy-mode-vi o { send -X other-end }", diff --git a/tmux.1 b/tmux.1 index 3a378c49..bf72cc0c 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1808,6 +1808,7 @@ The following commands are supported in copy mode: .It Li "search-forward " Ta "/" Ta "" .It Li "search-forward-incremental " Ta "" Ta "C-s" .It Li "search-forward-text " Ta "" Ta "" +.It Li "scroll-middle" Ta "z" Ta "" .It Li "search-reverse" Ta "N" Ta "N" .It Li "select-line" Ta "V" Ta "" .It Li "select-word" Ta "" Ta "" diff --git a/window-copy.c b/window-copy.c index 834a2d99..743364d6 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1250,6 +1250,32 @@ window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_NOTHING); } +static enum window_copy_cmd_action +window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct window_copy_mode_data *data = wme->data; + u_int mid_value, oy, delta; + int scroll_up; /* >0 up, <0 down */ + + mid_value = (screen_size_y(&data->screen) - 1) / 2; + scroll_up = data->cy - mid_value; + delta = abs(scroll_up); + oy = screen_hsize(data->backing) + data->cy - data->oy; + + log_debug ("XXX %u %u %u %d %u", mid_value, oy, delta, scroll_up, data->oy); + if (scroll_up > 0 && data->oy >= delta) { + window_copy_scroll_up(wme, delta); + data->cy -= delta; + } else if (scroll_up < 0 && oy >= delta) { + window_copy_scroll_down(wme, delta); + data->cy += delta; + } + + window_copy_update_selection(wme, 0, 0); + return (WINDOW_COPY_CMD_REDRAW); +} + static enum window_copy_cmd_action window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs) { @@ -2780,6 +2806,12 @@ static const struct { .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, .f = window_copy_cmd_scroll_down_and_cancel }, + { .command = "scroll-middle", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_scroll_middle + }, { .command = "scroll-up", .minargs = 0, .maxargs = 0, -- cgit From e86752820993a00e3d28350cbe46878ba95d9012 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 24 Aug 2022 07:22:30 +0000 Subject: Check for NULL returns from bufferevent_new. --- control.c | 4 ++++ file.c | 4 ++++ window.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/control.c b/control.c index f75035ef..8b44a274 100644 --- a/control.c +++ b/control.c @@ -776,12 +776,16 @@ control_start(struct client *c) cs->read_event = bufferevent_new(c->fd, control_read_callback, control_write_callback, control_error_callback, c); + if (cs->read_event == NULL) + fatalx("out of memory"); if (c->flags & CLIENT_CONTROLCONTROL) cs->write_event = cs->read_event; else { cs->write_event = bufferevent_new(c->out_fd, NULL, control_write_callback, control_error_callback, c); + if (cs->write_event == NULL) + fatalx("out of memory"); } bufferevent_setwatermark(cs->write_event, EV_WRITE, CONTROL_BUFFER_LOW, 0); diff --git a/file.c b/file.c index 7b956120..280f3547 100644 --- a/file.c +++ b/file.c @@ -588,6 +588,8 @@ file_write_open(struct client_files *files, struct tmuxpeer *peer, cf->event = bufferevent_new(cf->fd, NULL, file_write_callback, file_write_error_callback, cf); + if (cf->event == NULL) + fatalx("out of memory"); bufferevent_enable(cf->event, EV_WRITE); goto reply; @@ -747,6 +749,8 @@ file_read_open(struct client_files *files, struct tmuxpeer *peer, cf->event = bufferevent_new(cf->fd, file_read_callback, NULL, file_read_error_callback, cf); + if (cf->event == NULL) + fatalx("out of memory"); bufferevent_enable(cf->event, EV_READ); return; diff --git a/window.c b/window.c index 2be5d5e6..1b0066c2 100644 --- a/window.c +++ b/window.c @@ -1033,6 +1033,8 @@ window_pane_set_event(struct window_pane *wp) wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL, window_pane_error_callback, wp); + if (wp->event == NULL) + fatalx("out of memory"); wp->ictx = input_init(wp, wp->event, &wp->palette); bufferevent_enable(wp->event, EV_READ|EV_WRITE); -- cgit From 68dc9af9ac1a8ea332c82fd510b01c46602fa03a Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 31 Aug 2022 08:07:05 +0000 Subject: Fix window size report, from Vincent Bernat. --- input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.c b/input.c index d8b334de..37d64218 100644 --- a/input.c +++ b/input.c @@ -1899,7 +1899,7 @@ input_csi_dispatch_winops(struct input_ctx *ictx) } break; case 18: - input_reply(ictx, "\033[8;%u;%ut", x, y); + input_reply(ictx, "\033[8;%u;%ut", y, x); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); -- cgit From 0a0ded32685edafe934b767e6df9d218e227eb95 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 7 Sep 2022 07:28:26 +0100 Subject: Regress typos. --- regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf | 2 +- regress/conf/a46e6e84cd1071105aa807256dbc158d.conf | 2 +- regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf | 2 +- regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf | 6 +++--- regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf b/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf index c09adc24..c3a4da4b 100644 --- a/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf +++ b/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf @@ -12,7 +12,7 @@ set-window-option -g pane-base-index 1 unbind ^B bind ^B select-pane -t :.+ -# Reload config wtih a key +# Reload config with a key bind-key r source-file ~/.tmux.conf \; display "Config reloaded!" # Mouse works as expected diff --git a/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf b/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf index bfbb2d3e..d8fd9d20 100644 --- a/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf +++ b/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf @@ -24,7 +24,7 @@ set-option -g default-terminal 'screen-256color' # allow Vim to receive focus events from terminal window set-option -g focus-events on -# allow Vim to recieve modifier keys: Shift, Control, Alt +# allow Vim to receive modifier keys: Shift, Control, Alt set-window-option -g xterm-keys on # prevent tmux from catching modifier keys meant for Vim diff --git a/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf b/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf index 27d8f310..0c41caa4 100644 --- a/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf +++ b/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf @@ -552,7 +552,7 @@ setw -g status-keys emacs # Changelog: https://github.com/tmux/tmux/blob/master/CHANGES # style colors: default, black, red, green, yellow, blue, magenta, cyan, white, -# colour0-colour255, hexdecimal RGB string '#ffffff' +# colour0-colour255, hexadecimal RGB string '#ffffff' # Use $SCRIPTS/bash/256-colors.sh to figure out the color number you want # style attributes: none, bold/bright, dim, underscore, blink, reverse, hidden, # or italics diff --git a/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf b/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf index 0a878369..845002c2 100644 --- a/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf +++ b/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf @@ -1,6 +1,6 @@ -# none of these attempts worked, to bind keys, except sometimes during the sesssion. Oh well. +# none of these attempts worked, to bind keys, except sometimes during the session. Oh well. # I thought maybe that was because F1 is handled differently in a console than in X, but -# even just C-1 didnt work. Using just "a" or "x" as the key did, but not yet sure why not "C-". +# even just C-1 didn't work. Using just "a" or "x" as the key did, but not yet sure why not "C-". #bind-key -T root C-1 attach-session -t$0 #But this one works now, only picks the wrong one? Mbe need2understand what "$1" or $0 mean, better, #but with the stub maybe this doesn't matter: @@ -47,7 +47,7 @@ select-window -t :=3 #$3 for email (mutt) new-session sula new-window sula ; send-keys mutt Enter -#nah, probly betr not?: +#nah, probably better not?: #send-keys -l z #send-keys -l "thepassifdecide" #send-keys Enter diff --git a/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf b/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf index 79f46df1..3cf1ae9d 100644 --- a/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf +++ b/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf @@ -63,7 +63,7 @@ bind N command-prompt -p hosts: 'run-shell -b "bash -c \"~/lbin/nw %% >/dev/null #05:59 < Celti> annihilannic: I believe the #{pane_in_mode} format does what you want #05:59 < Celti> put it in your statusline #05:59 < Celti> annihilannic: No, my mistake, I should have read farther down, you want #{pane_synchronized} -# only works in tmux 2.0?, higher than 1.6.3 anyawy +# only works in tmux 2.0?, higher than 1.6.3 anyway set-option -g window-status-format ' #I:#W#F#{?pane_synchronized,S,}' #set-option -g window-status-current-format ' #I:#W#{?pane_synchronized,[sync],}#F' # to highlight in red when sync is on... not sure why I did this with set-window-option instead of set-option, perhaps -- cgit From f03c3ca6c36cd52ae5ec4ae8cd4fa137cf79aaf3 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 9 Sep 2022 11:02:23 +0000 Subject: Add message-line option to control where message and prompt go, from Varun Kumar E in GitHub issue 3324. --- options-table.c | 13 ++++++++++++- status.c | 37 ++++++++++++++++++++++++++++--------- tmux.1 | 4 ++++ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/options-table.c b/options-table.c index 377835bb..6fc5a96f 100644 --- a/options-table.c +++ b/options-table.c @@ -42,6 +42,9 @@ static const char *options_table_clock_mode_style_list[] = { static const char *options_table_status_list[] = { "off", "on", "2", "3", "4", "5", NULL }; +static const char *options_table_message_line_list[] = { + "0", "1", "2", "3", "4", NULL +}; static const char *options_table_status_keys_list[] = { "emacs", "vi", NULL }; @@ -542,13 +545,21 @@ const struct options_table_entry options_table[] = { "'mode-keys' is set to 'vi'." }, + { .name = "message-line", + .type = OPTIONS_TABLE_CHOICE, + .scope = OPTIONS_TABLE_SESSION, + .choices = options_table_message_line_list, + .default_num = 0, + .text = "Position (line) of messages and the command prompt." + }, + { .name = "message-style", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, .default_str = "bg=yellow,fg=black", .flags = OPTIONS_TABLE_IS_STYLE, .separator = ",", - .text = "Style of the command prompt." + .text = "Style of messages and the command prompt." }, { .name = "mouse", diff --git a/status.c b/status.c index 929276d2..baf6ed2b 100644 --- a/status.c +++ b/status.c @@ -263,6 +263,17 @@ status_line_size(struct client *c) return (s->statuslines); } +/* Get the prompt line number for client's session. 1 means at the bottom. */ +static u_int +status_prompt_line_at(struct client *c) +{ + struct session *s = c->session; + + if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL)) + return (1); + return (options_get_number(s->options, "status-prompt-line")); +} + /* Get window at window list position. */ struct style_range * status_get_range(struct client *c, u_int x, u_int y) @@ -533,7 +544,7 @@ status_message_redraw(struct client *c) struct session *s = c->session; struct screen old_screen; size_t len; - u_int lines, offset; + u_int lines, offset, messageline; struct grid_cell gc; struct format_tree *ft; @@ -546,6 +557,10 @@ status_message_redraw(struct client *c) lines = 1; screen_init(sl->active, c->tty.sx, lines, 0); + messageline = status_prompt_line_at(c); + if (messageline > lines - 1) + messageline = lines - 1; + len = screen_write_strlen("%s", c->message_string); if (len > c->tty.sx) len = c->tty.sx; @@ -555,11 +570,11 @@ status_message_redraw(struct client *c) format_free(ft); screen_write_start(&ctx, sl->active); - screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines); + screen_write_cursormove(&ctx, 0, messageline, 0); for (offset = 0; offset < c->tty.sx; offset++) screen_write_putc(&ctx, &gc, ' '); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_cursormove(&ctx, 0, messageline, 0); if (c->message_ignore_styles) screen_write_nputs(&ctx, len, &gc, "%s", c->message_string); else @@ -695,7 +710,7 @@ status_prompt_redraw(struct client *c) struct session *s = c->session; struct screen old_screen; u_int i, lines, offset, left, start, width; - u_int pcursor, pwidth; + u_int pcursor, pwidth, promptline; struct grid_cell gc, cursorgc; struct format_tree *ft; @@ -708,6 +723,10 @@ status_prompt_redraw(struct client *c) lines = 1; screen_init(sl->active, c->tty.sx, lines, 0); + promptline = status_prompt_line_at(c); + if (promptline > lines - 1) + promptline = lines - 1; + ft = format_create_defaults(NULL, c, NULL, NULL, NULL); if (c->prompt_mode == PROMPT_COMMAND) style_apply(&gc, s->options, "message-command-style", ft); @@ -723,13 +742,13 @@ status_prompt_redraw(struct client *c) start = c->tty.sx; screen_write_start(&ctx, sl->active); - screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines); + screen_write_cursormove(&ctx, 0, promptline, 0); for (offset = 0; offset < c->tty.sx; offset++) screen_write_putc(&ctx, &gc, ' '); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_cursormove(&ctx, 0, promptline, 0); format_draw(&ctx, &gc, start, c->prompt_string, NULL, 0); - screen_write_cursormove(&ctx, start, lines - 1, 0); + screen_write_cursormove(&ctx, start, promptline, 0); left = c->tty.sx - start; if (left == 0) diff --git a/tmux.1 b/tmux.1 index bf72cc0c..485b5d3a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3873,6 +3873,10 @@ For how to specify see the .Sx STYLES section. +.It Xo Ic message-line +.Op Ic 0 | 1 | 2 | 3 | 4 +.Xc +Set line on which status line messages and the command prompt are shown. .It Ic message-style Ar style Set status line message style. This is used for messages and for the command prompt. -- cgit From 9ab1ba36cd2de4ca83694c3d475061323ffcc4d4 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 10 Sep 2022 17:01:33 +0000 Subject: Use correct option name. --- status.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/status.c b/status.c index baf6ed2b..b504bbbe 100644 --- a/status.c +++ b/status.c @@ -271,7 +271,7 @@ status_prompt_line_at(struct client *c) if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL)) return (1); - return (options_get_number(s->options, "status-prompt-line")); + return (options_get_number(s->options, "message-line")); } /* Get window at window list position. */ -- cgit From a2cc601c3d1a569037ccd238b2638b5c416baca8 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 12 Sep 2022 12:02:17 +0000 Subject: Don't use options from pane if pane is NULL. --- input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/input.c b/input.c index 37d64218..8b174769 100644 --- a/input.c +++ b/input.c @@ -2242,7 +2242,6 @@ static int input_dcs_dispatch(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; - struct options *oo = wp->options; struct screen_write_ctx *sctx = &ictx->ctx; u_char *buf = ictx->input_buf; size_t len = ictx->input_len; @@ -2254,7 +2253,8 @@ input_dcs_dispatch(struct input_ctx *ictx) return (0); if (ictx->flags & INPUT_DISCARD) return (0); - allow_passthrough = options_get_number(oo, "allow-passthrough"); + allow_passthrough = options_get_number(wp->options, + "allow-passthrough"); if (!allow_passthrough) return (0); log_debug("%s: \"%s\"", __func__, buf); -- cgit From 19344ec890e0c4343e3c20695806d482c631d67c Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 19 Sep 2022 07:03:17 +0100 Subject: Add headers and fix type, from Marvin Schmidt. GitHub issue 3332. --- compat/systemd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compat/systemd.c b/compat/systemd.c index 7317e43a..9a3adbb3 100644 --- a/compat/systemd.c +++ b/compat/systemd.c @@ -21,6 +21,8 @@ #include +#include + #include "tmux.h" int @@ -29,7 +31,7 @@ systemd_create_socket(int flags, char **cause) int fds; int fd; struct sockaddr_un sa; - int addrlen = sizeof sa; + socklen_t addrlen = sizeof sa; fds = sd_listen_fds(0); if (fds > 1) { /* too many file descriptors */ -- cgit From 9cc8e40aa08ff91bc1c5d0211c1d2cef02f2c7a2 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 28 Sep 2022 07:55:29 +0000 Subject: Add a -T flag to capture-pane to stop at the last used cell instead of the full width. Restore the previous behaviour by making it default to off unless -J is used (the only time it matters). Fixes mosh unit tests; GitHub issue 3339. --- cmd-capture-pane.c | 18 ++++++----- grid-view.c | 2 +- grid.c | 88 ++++++++++++++++++++++++++++++------------------------ tmux.h | 11 ++++++- 4 files changed, 71 insertions(+), 48 deletions(-) diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c index 422f87d6..57e9716d 100644 --- a/cmd-capture-pane.c +++ b/cmd-capture-pane.c @@ -40,7 +40,7 @@ const struct cmd_entry cmd_capture_pane_entry = { .alias = "capturep", .args = { "ab:CeE:JNpPqS:t:", 0, 0, NULL }, - .usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] " + .usage = "[-aCeJNpPqT] " CMD_BUFFER_USAGE " [-E end-line] " "[-S start-line] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -110,7 +110,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item, struct grid *gd; const struct grid_line *gl; struct grid_cell *gc = NULL; - int n, with_codes, escape_c0, join_lines, no_trim; + int n, join_lines, flags = 0; u_int i, sx, top, bottom, tmp; char *cause, *buf, *line; const char *Sflag, *Eflag; @@ -169,15 +169,19 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item, top = tmp; } - with_codes = args_has(args, 'e'); - escape_c0 = args_has(args, 'C'); join_lines = args_has(args, 'J'); - no_trim = args_has(args, 'N'); + if (args_has(args, 'e')) + flags |= GRID_STRING_WITH_SEQUENCES; + if (args_has(args, 'C')) + flags |= GRID_STRING_ESCAPE_SEQUENCES; + if (!join_lines && !args_has(args, 'T')) + flags |= GRID_STRING_EMPTY_CELLS; + if (!join_lines && !args_has(args, 'N')) + flags |= GRID_STRING_TRIM_SPACES; buf = NULL; for (i = top; i <= bottom; i++) { - line = grid_string_cells(gd, 0, i, sx, &gc, with_codes, - escape_c0, !join_lines && !no_trim, wp->screen); + line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen); linelen = strlen(line); buf = cmd_capture_pane_append(buf, len, line, linelen); diff --git a/grid-view.c b/grid-view.c index 689ac4e4..4d687339 100644 --- a/grid-view.c +++ b/grid-view.c @@ -231,5 +231,5 @@ grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) px = grid_view_x(gd, px); py = grid_view_y(gd, py); - return (grid_string_cells(gd, px, py, nx, NULL, 0, 0, 0, NULL)); + return (grid_string_cells(gd, px, py, nx, NULL, 0, NULL)); } diff --git a/grid.c b/grid.c index b1afd398..58de03a3 100644 --- a/grid.c +++ b/grid.c @@ -861,40 +861,45 @@ grid_string_cells_us(const struct grid_cell *gc, int *values) /* Add on SGR code. */ static void grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc, - int *oldc, size_t nnewc, size_t noldc, int escape_c0) + int *oldc, size_t nnewc, size_t noldc, int flags) { u_int i; char tmp[64]; - - if (nnewc != 0 && - (nnewc != noldc || - memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 || - (n != 0 && s[0] == 0))) { - if (escape_c0) - strlcat(buf, "\\033[", len); + int reset = (n != 0 && s[0] == 0); + + if (nnewc == 0) + return; /* no code to add */ + if (!reset && + nnewc == noldc && + memcmp(newc, oldc, nnewc * sizeof newc[0]) == 0) + return; /* no reset and colour unchanged */ + if (reset && (newc[0] == 49 || newc[0] == 39)) + return; /* reset and colour default */ + + if (flags & GRID_STRING_ESCAPE_SEQUENCES) + strlcat(buf, "\\033[", len); + else + strlcat(buf, "\033[", len); + for (i = 0; i < nnewc; i++) { + if (i + 1 < nnewc) + xsnprintf(tmp, sizeof tmp, "%d;", newc[i]); else - strlcat(buf, "\033[", len); - for (i = 0; i < nnewc; i++) { - if (i + 1 < nnewc) - xsnprintf(tmp, sizeof tmp, "%d;", newc[i]); - else - xsnprintf(tmp, sizeof tmp, "%d", newc[i]); - strlcat(buf, tmp, len); - } - strlcat(buf, "m", len); + xsnprintf(tmp, sizeof tmp, "%d", newc[i]); + strlcat(buf, tmp, len); } + strlcat(buf, "m", len); } static int grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, - const char *uri, int escape_c0) + const char *uri, int flags) { char *tmp; if (strlen(uri) + strlen(id) + 17 >= len) return (0); - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\033]8;", len); else strlcat(buf, "\033]8;", len); @@ -905,7 +910,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, } else strlcat(buf, ";", len); strlcat(buf, uri, len); - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\033\\\\", len); else strlcat(buf, "\033\\", len); @@ -918,7 +923,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, */ static void grid_string_cells_code(const struct grid_cell *lastgc, - const struct grid_cell *gc, char *buf, size_t len, int escape_c0, + const struct grid_cell *gc, char *buf, size_t len, int flags, struct screen *sc, int *has_link) { int oldc[64], newc[64], s[128]; @@ -927,7 +932,7 @@ grid_string_cells_code(const struct grid_cell *lastgc, char tmp[64]; const char *uri, *id; - struct { + static const struct { u_int mask; u_int code; } attrs[] = { @@ -966,7 +971,7 @@ grid_string_cells_code(const struct grid_cell *lastgc, /* Write the attributes. */ *buf = '\0'; if (n > 0) { - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\033[", len); else strlcat(buf, "\033[", len); @@ -988,29 +993,29 @@ grid_string_cells_code(const struct grid_cell *lastgc, nnewc = grid_string_cells_fg(gc, newc); noldc = grid_string_cells_fg(lastgc, oldc); grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, - escape_c0); + flags); /* If the background colour changed, append its parameters. */ nnewc = grid_string_cells_bg(gc, newc); noldc = grid_string_cells_bg(lastgc, oldc); grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, - escape_c0); + flags); /* If the underscore colour changed, append its parameters. */ nnewc = grid_string_cells_us(gc, newc); noldc = grid_string_cells_us(lastgc, oldc); grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, - escape_c0); + flags); /* Append shift in/shift out if needed. */ if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) { - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\016", len); /* SO */ else strlcat(buf, "\016", len); /* SO */ } if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) { - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\017", len); /* SI */ else strlcat(buf, "\017", len); /* SI */ @@ -1020,10 +1025,10 @@ grid_string_cells_code(const struct grid_cell *lastgc, if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) { if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) { *has_link = grid_string_cells_add_hyperlink(buf, len, - id, uri, escape_c0); + id, uri, flags); } else if (*has_link) { grid_string_cells_add_hyperlink(buf, len, "", "", - escape_c0); + flags); *has_link = 0; } } @@ -1032,15 +1037,14 @@ grid_string_cells_code(const struct grid_cell *lastgc, /* Convert cells into a string. */ char * grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, - struct grid_cell **lastgc, int with_codes, int escape_c0, int trim, - struct screen *s) + struct grid_cell **lastgc, int flags, struct screen *s) { struct grid_cell gc; static struct grid_cell lastgc1; const char *data; char *buf, code[8192]; size_t len, off, size, codelen; - u_int xx, has_link = 0; + u_int xx, has_link = 0, end; const struct grid_line *gl; if (lastgc != NULL && *lastgc == NULL) { @@ -1053,16 +1057,20 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, off = 0; gl = grid_peek_line(gd, py); + if (flags & GRID_STRING_EMPTY_CELLS) + end = gl->cellsize; + else + end = gl->cellused; for (xx = px; xx < px + nx; xx++) { - if (gl == NULL || xx >= gl->cellused) + if (gl == NULL || xx >= end) break; grid_get_cell(gd, xx, py, &gc); if (gc.flags & GRID_FLAG_PADDING) continue; - if (with_codes) { + if (flags & GRID_STRING_WITH_SEQUENCES) { grid_string_cells_code(*lastgc, &gc, code, sizeof code, - escape_c0, s, &has_link); + flags, s, &has_link); codelen = strlen(code); memcpy(*lastgc, &gc, sizeof **lastgc); } else @@ -1070,7 +1078,9 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, data = gc.data.data; size = gc.data.size; - if (escape_c0 && size == 1 && *data == '\\') { + if ((flags & GRID_STRING_ESCAPE_SEQUENCES) && + size == 1 && + *data == '\\') { data = "\\\\"; size = 2; } @@ -1090,7 +1100,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, if (has_link) { grid_string_cells_add_hyperlink(code, sizeof code, "", "", - escape_c0); + flags); codelen = strlen(code); while (len < off + size + codelen + 1) { buf = xreallocarray(buf, 2, len); @@ -1100,7 +1110,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, off += codelen; } - if (trim) { + if (flags & GRID_STRING_TRIM_SPACES) { while (off > 0 && buf[off - 1] == ' ') off--; } diff --git a/tmux.h b/tmux.h index 9b43e0fd..77019edc 100644 --- a/tmux.h +++ b/tmux.h @@ -667,6 +667,14 @@ struct colour_palette { #define GRID_LINE_EXTENDED 0x2 #define GRID_LINE_DEAD 0x4 +/* Grid string flags. */ +#define GRID_STRING_WITH_SEQUENCES 0x1 +#define GRID_STRING_ESCAPE_SEQUENCES 0x2 +#define GRID_STRING_TRIM_SPACES 0x4 +#define GRID_STRING_USED_ONLY 0x8 +#define GRID_STRING_EMPTY_CELLS 0x10 + +/* Cell positions. */ #define CELL_INSIDE 0 #define CELL_TOPBOTTOM 1 #define CELL_LEFTRIGHT 2 @@ -681,6 +689,7 @@ struct colour_palette { #define CELL_JOIN 11 #define CELL_OUTSIDE 12 +/* Cell borders. */ #define CELL_BORDERS " xqlkmjwvtun~" #define SIMPLE_BORDERS " |-+++++++++." #define PADDED_BORDERS " " @@ -2783,7 +2792,7 @@ void grid_clear_lines(struct grid *, u_int, u_int, u_int); void grid_move_lines(struct grid *, u_int, u_int, u_int, u_int); void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int, u_int); char *grid_string_cells(struct grid *, u_int, u_int, u_int, - struct grid_cell **, int, int, int, struct screen *); + struct grid_cell **, int, struct screen *); void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, u_int); void grid_reflow(struct grid *, u_int); -- cgit From a10452be2d84d4ff1b9d4e636627b7a9c5a2c42a Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 28 Sep 2022 07:59:50 +0000 Subject: Add scroll-top and scroll-bottom commands to scroll so cursor is at top or bottom. From Anindya Mukherjee, GitHub issue 3334. --- tmux.1 | 11 +++++++++-- window-copy.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/tmux.1 b/tmux.1 index 485b5d3a..5e896902 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1808,7 +1808,9 @@ The following commands are supported in copy mode: .It Li "search-forward " Ta "/" Ta "" .It Li "search-forward-incremental " Ta "" Ta "C-s" .It Li "search-forward-text " Ta "" Ta "" +.It Li "scroll-bottom" Ta "" Ta "" .It Li "scroll-middle" Ta "z" Ta "" +.It Li "scroll-top" Ta "" Ta "" .It Li "search-reverse" Ta "N" Ta "N" .It Li "select-line" Ta "V" Ta "" .It Li "select-word" Ta "" Ta "" @@ -2011,7 +2013,7 @@ but a different format may be specified with .Fl F . .Tg capturep .It Xo Ic capture-pane -.Op Fl aepPqCJN +.Op Fl aAepPqCJN .Op Fl b Ar buffer-name .Op Fl E Ar end-line .Op Fl S Ar start-line @@ -2036,10 +2038,15 @@ is given, the output includes escape sequences for text and background attributes. .Fl C also escapes non-printable characters as octal \exxx. +.Fl T +ignores trailing positions that do not contain a character. .Fl N preserves trailing spaces at each line's end and .Fl J -preserves trailing spaces and joins any wrapped lines. +preserves trailing spaces and joins any wrapped lines; +.Fl J +implies +.Fl T . .Fl P captures only any output that the pane has received that is the beginning of an as-yet incomplete escape sequence. diff --git a/window-copy.c b/window-copy.c index 743364d6..ed481d70 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1250,20 +1250,23 @@ window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_NOTHING); } +/* Scroll line containing the cursor to the given position. */ static enum window_copy_cmd_action -window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs) +window_copy_cmd_scroll_to(struct window_copy_cmd_state *cs, u_int to) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - u_int mid_value, oy, delta; + u_int oy, delta; int scroll_up; /* >0 up, <0 down */ - mid_value = (screen_size_y(&data->screen) - 1) / 2; - scroll_up = data->cy