From cd60de443e294a6aa5c967832372f01855b82eca Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 4 Apr 2026 11:20:01 +0000 Subject: [PATCH 1/4] Clamp width to terminal width, also change calculation of end of screen (it is OK to be outside the screen). Fixes problem reported by Dane Jensen in GitHub issue 4969. --- tty-draw.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tty-draw.c b/tty-draw.c index bd643f98..d0a74fca 100644 --- a/tty-draw.c +++ b/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, 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 * there may be empty background cells after it (from BCE). @@ -150,15 +158,8 @@ 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; if (screen_size_x(s) > cellsize) ex = cellsize; - else { + else 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, " "bg=%d", __func__, px, px + nx, py, ex, atx, aty, defaults->fg, defaults->bg); @@ -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. */ - if (i >= ex) + if (px >= ex || i >= ex - px) empty = 1; else if (gcp->bg != last.bg) empty = 0; From 3badbc50e0d1c45ebfca2d2d1fad059a055584a5 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 4 Apr 2026 11:32:05 +0000 Subject: [PATCH 2/4] Do not read off end of buffer if it ends in \ when expanding \c, found by ossfuzz. --- regsub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regsub.c b/regsub.c index 91be3994..a863f9fd 100644 --- a/regsub.c +++ b/regsub.c @@ -41,7 +41,7 @@ regsub_expand(char **buf, ssize_t *len, const char *with, const char *text, u_int i; for (cp = with; *cp != '\0'; cp++) { - if (*cp == '\\') { + if (cp[0] == '\\' && cp[1] != '\0') { cp++; if (*cp >= '0' && *cp <= '9') { i = *cp - '0'; From a827725a8d6afb73ac27a4f316c48605afde57ea Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 4 Apr 2026 11:39:49 +0000 Subject: [PATCH 3/4] Set up default and last cell before clearing padding, reported by someone on GitHub. --- tty-draw.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tty-draw.c b/tty-draw.c index d0a74fca..b5ecbe50 100644 --- a/tty-draw.c +++ b/tty-draw.c @@ -164,6 +164,18 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, "bg=%d", __func__, px, px + nx, py, ex, atx, aty, defaults->fg, 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 * character. Clear it. @@ -196,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); tty_draw_line_clear(tty, atx, aty, cx, defaults, bg, 0); if (cx == ex) - return; + goto out; atx += cx; px += cx; nx -= cx; @@ -210,18 +222,6 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, 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. */ last_i = i = 0; len = 0; @@ -332,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; } +out: tty->flags = (tty->flags & ~TTY_NOCURSOR)|flags; tty_update_mode(tty, tty->mode, s); } From d2d86ac36029e851820487b9908db71d250652ce Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 4 Apr 2026 11:48:00 +0000 Subject: [PATCH 4/4] Document control ranges, from Dane Jensen. --- tmux.1 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tmux.1 b/tmux.1 index 80824d3b..dd0f7c4a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5795,8 +5795,13 @@ and a location suffix, one of the following: .It Li "ScrollbarSlider" Ta "the scrollbar slider" .It Li "ScrollbarUp" Ta "above the scrollbar slider" .It Li "ScrollbarDown" Ta "below the scrollbar slider" +.It Li "ControlN" Ta "on control range N" .El .Pp +See the +.Sx STYLES +section for information on control ranges. +.Pp The following mouse events are available: .Bl -column "MouseDown1" "MouseDrag1" "WheelDown" -offset indent .It Li "WheelUp" Ta "WheelDown" Ta "" @@ -6609,6 +6614,7 @@ replaces the previous saved default). .Ic range=window|X , .Ic range=pane|X , .Ic range=user|X , +.Ic range=control|N , .Ic norange .Xc Mark a range for mouse events in the @@ -6655,6 +6661,19 @@ will be available in the format variable. .Ql X 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 Set the current colours and attributes as the default, overwriting any previous default.