From 91b4e02805a8ad6bcfb71bb5c294ffffbafcaf18 Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Sat, 23 May 2026 06:15:12 +0100 Subject: [PATCH 1/6] Fix merge messup where i is no longer x, use px and ri->px instead here. --- tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tty.c b/tty.c index 121e3b85..58c80950 100644 --- a/tty.c +++ b/tty.c @@ -1471,12 +1471,12 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py) } if (tty_clamp_line(tty, ctx, 0, py, nx, &px, &x, &rx, &ry)) { if (wp) { - r = tty_check_overlay_range(tty, i, py, rx); + r = tty_check_overlay_range(tty, px, py, rx); for (i=0; i < r->used; i++) { ri = &r->ranges[i]; if (ri->nx == 0) continue; - tty_draw_line(tty, s, i, py, ri->nx, + tty_draw_line(tty, s, ri->px, py, ri->nx, x + ri->px, ry, &ctx->defaults, ctx->palette); } From 5c3a4746b7814c2d07b1642bb00858a66a13925a Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 23 May 2026 07:22:50 +0000 Subject: [PATCH 2/6] Some code tidying up. --- layout-custom.c | 2 +- layout.c | 2 +- screen-redraw.c | 83 ++++++++++++++++++++++--------------------------- 3 files changed, 39 insertions(+), 48 deletions(-) diff --git a/layout-custom.c b/layout-custom.c index deced6d8..6c4881ce 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -288,7 +288,7 @@ layout_parse(struct window *w, const char *layout, char **cause) if (floating_lc != NULL) layout_assign(&wp, floating_lc, PANE_FLOATING); - /* Fix pane Z indexes. */ + /* Fix pane z-indexes. */ while (!TAILQ_EMPTY(&w->z_index)) { wp = TAILQ_FIRST(&w->z_index); TAILQ_REMOVE(&w->z_index, wp, zentry); diff --git a/layout.c b/layout.c index 7c687e51..5ecad949 100644 --- a/layout.c +++ b/layout.c @@ -233,7 +233,7 @@ layout_make_node(struct layout_cell *lc, enum layout_type type) lc->wp = NULL; } -/* Fix Z indexes. */ +/* Fix z-indexes. */ void layout_fix_zindexes(struct window *w, struct layout_cell *lc) { diff --git a/screen-redraw.c b/screen-redraw.c index d6a90a99..996c7ff0 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -711,10 +711,8 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) } r = screen_redraw_get_visible_ranges(wp, x, yoff, width, NULL); - if (ctx->statustop) yoff += ctx->statuslines; - for (i = 0; i < r->used; i++) { ri = &r->ranges[i]; if (ri->nx == 0) @@ -1265,7 +1263,6 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px, return (r); } - /* Draw one pane. */ static void screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) @@ -1289,25 +1286,20 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) wp->xoff >= (int)ctx->ox + (int)ctx->sx) return; - /* woy is window y offset in tty. */ if (ctx->statustop) woy = ctx->statuslines; else woy = 0; - for (j = 0; j < wp->sy; j++) { if (wp->yoff + (int)j < (int)ctx->oy || wp->yoff + (int)j >= (int)ctx->oy + (int)ctx->sy) continue; - wy = wp->yoff + j; /* y line within window w. */ - py = woy + wy - ctx->oy; /* y line within tty. */ - if (py > tty->sy) + wy = wp->yoff + j; /* y line within window w */ + py = woy + wy - ctx->oy; /* y line within tty */ + if (py > tty->sy) { /* Continue if this line is off of tty. */ continue; - - /* Note: i is apparenty not used now that the vr array - * returns where in s to read from. - */ + } if (wp->xoff >= (int)ctx->ox && wp->xoff + (int)wp->sx <= (int)ctx->ox + (int)ctx->sx) { /* All visible. */ @@ -1336,22 +1328,15 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) /* Get visible ranges of line before we draw it. */ r = screen_redraw_get_visible_ranges(wp, wx, wy, width, NULL); - tty_default_colours(&defaults, wp); - - for (i=0; i < r->used; i++) { + for (i = 0; i < r->used; i++) { ri = &r->ranges[i]; if (ri->nx == 0) continue; - px = ri->px; - tty_draw_line(tty, s, ri->px - wp->xoff, j, - ri->nx, px, py, &defaults, palette); + tty_draw_line(tty, s, ri->px - wp->xoff, j, ri->nx, + ri->px, py, &defaults, palette); } } - -#ifdef ENABLE_SIXEL - tty_draw_images(c, wp, s); -#endif } /* Draw the panes scrollbars */ @@ -1440,8 +1425,8 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, struct visible_ranges *r; /* - * Size and offset of window relative to tty. - * Status at top offsets window downward. + * Size and offset of window relative to tty. Status at top offsets + * window downward. */ sx = ctx->sx; sy = tty->sy - ctx->statuslines; @@ -1449,8 +1434,8 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, oy = ctx->oy; if (ctx->statustop) { sb_y += ctx->statuslines; - sy += ctx->statuslines; /* Height of window in tty. */ - oy += ctx->statuslines; /* Top of window in tty. */ + sy += ctx->statuslines; /* height of window */ + oy += ctx->statuslines; /* top of window */ } gc = sb_style->gc; @@ -1458,17 +1443,20 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, slgc.fg = gc.bg; slgc.bg = gc.fg; - if (sb_x + (int)sb_w < 0 || sb_x >= sx || sb_y >= sy) - /* Whole sb off screen. */ + if (sb_x + (int)sb_w < 0 || sb_x >= sx || sb_y >= sy) { + /* Whole scrollbar is off screen. */ return; - if (sb_x < 0) - /* Part of sb on screen. */ + } + if (sb_x < 0) { + /* Part of scrollbar on screen. */ imin = - sb_x; + } imax = sb_w + sb_pad; if ((int)imax + sb_x > sx) { - if (sb_x > sx) - /* Whole sb off screen. */ + if (sb_x > sx) { + /* Whole scrollbar off screen. */ return; + } imax = sx - sb_x; } jmax = sb_h; @@ -1482,41 +1470,44 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, * sb_y is a window coordinate; convert to tty coordinate by * subtracting the pan offset oy. */ - sb_tty_y = sb_y - oy; /* scrollbar top in tty coordinates */ - - if (sb_tty_y > (int)sy) - /* Whole sb off screen. */ + sb_tty_y = sb_y - oy; /* scrollbar top in tty coordinates */ + if (sb_tty_y > (int)sy) { + /* Whole scrollbar is off screen. */ return; - if (sb_tty_y < 0) + } + if (sb_tty_y < 0) { /* Scrollbar starts above visible area; skip those rows. */ jmin = -sb_tty_y; - if (sb_tty_y + (int)sb_h <= 0) - /* Whole sb above visible area. */ + } + if (sb_tty_y + (int)sb_h <= 0) { + /* Whole scrollbar above visible area. */ return; + } jmax = sb_h; - if (sb_tty_y + (int)jmax > (int)sy) + if (sb_tty_y + (int)jmax > (int)sy) { /* Clip to height of tty. */ jmax = sy - sb_tty_y; + } for (j = jmin; j < jmax; j++) { - wy = sb_y + j; /* window y coordinate. */ - py = sb_tty_y + j; /* tty y coordinate. */ + wy = sb_y + j; /* window y coordinate */ + py = sb_tty_y + j;/* tty y coordinate */ r = tty_check_overlay_range(tty, sb_x, wy, imax); r = screen_redraw_get_visible_ranges(wp, sb_x, wy, imax, r); for (i = imin; i < imax; i++) { - px = sb_x + ox + i; /* tty x coordinate. */ - wx = sb_x + i; /* window x coordinate. */ + px = sb_x + ox + i; /* tty x coordinate */ + wx = sb_x + i; /* window x coordinate */ if (wx < xoff - (int)sb_w - (int)sb_pad || px >= sx || px < 0 || wy < yoff - 1 || py >= sy || py < 0 || - ! screen_redraw_is_visible(r, wx)) + !screen_redraw_is_visible(r, wx)) continue; tty_cursor(tty, px, py); if ((sb_pos == PANE_SCROLLBARS_LEFT && i >= sb_w && i < sb_w + sb_pad) || (sb_pos == PANE_SCROLLBARS_RIGHT && - i < sb_pad)) { + i < sb_pad)) { tty_cell(tty, &grid_default_cell, &grid_default_cell, NULL, NULL); } else { From 3cfc96d4de8c616035106b8d1d1fe749afca24db Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 23 May 2026 16:43:04 +0000 Subject: [PATCH 3/6] Add missing argument to %unlinked-window-renamed, reported by Andrew Grangaard. --- tmux.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmux.1 b/tmux.1 index 56bf6386..bd235a70 100644 --- a/tmux.1 +++ b/tmux.1 @@ -8209,7 +8209,7 @@ was created but is not linked to the current session. The window with ID .Ar window\-id , which is not linked to the current session, was closed. -.It Ic %unlinked\-window\-renamed Ar window\-id +.It Ic %unlinked\-window\-renamed Ar window\-id Ar new\-name The window with ID .Ar window\-id , which is not linked to the current session, was renamed. From f047b3f8e70f42128501bf20c2bcfc1b3284d792 Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 24 May 2026 08:40:43 +0000 Subject: [PATCH 4/6] Do not crash when freeing layout cell, reported by Jere Viikari. --- layout-custom.c | 3 +-- layout.c | 3 +++ screen-redraw.c | 2 +- window.c | 6 ++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/layout-custom.c b/layout-custom.c index 6c4881ce..b2871f0d 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -304,8 +304,7 @@ layout_parse(struct window *w, const char *layout, char **cause) layout_print_cell(tiled_lc, __func__, 0); /* Free the floating layout cell, no longer needed. */ - if (floating_lc != NULL) - layout_free_cell(floating_lc); + layout_free_cell(floating_lc); notify_window("window-layout-changed", w); diff --git a/layout.c b/layout.c index 5ecad949..8ee80261 100644 --- a/layout.c +++ b/layout.c @@ -78,6 +78,9 @@ layout_free_cell(struct layout_cell *lc) { struct layout_cell *lcchild; + if (lc == NULL) + return; + switch (lc->type) { case LAYOUT_LEFTRIGHT: case LAYOUT_TOPBOTTOM: diff --git a/screen-redraw.c b/screen-redraw.c index 996c7ff0..020466c6 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1273,7 +1273,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) struct screen *s = wp->screen; struct colour_palette *palette = &wp->palette; struct grid_cell defaults; - u_int i, j, woy, wx, wy, px, py, width; + u_int i, j, woy, wx, wy, py, width; struct visible_ranges *r; struct visible_range *ri; diff --git a/window.c b/window.c index e6e6eba7..1d9e84f9 100644 --- a/window.c +++ b/window.c @@ -349,10 +349,8 @@ window_destroy(struct window *w) window_unzoom(w, 0); RB_REMOVE(windows, &windows, w); - if (w->layout_root != NULL) - layout_free_cell(w->layout_root); - if (w->saved_layout_root != NULL) - layout_free_cell(w->saved_layout_root); + layout_free_cell(w->layout_root); + layout_free_cell(w->saved_layout_root); free(w->old_layout); window_destroy_panes(w); From 30866d06d586ba43ba8ec5fea0ae8ee94870ae7f Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Sun, 24 May 2026 09:58:30 +0100 Subject: [PATCH 5/6] Add visible range checks to screen_write.c functions and remove checks from tty.c. --- screen-write.c | 364 ++++++++++++++++++++++++++++++++++++++++++++----- tty.c | 5 +- 2 files changed, 331 insertions(+), 38 deletions(-) diff --git a/screen-write.c b/screen-write.c index dbce6a9d..36bbcb28 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1118,7 +1118,9 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx) struct screen *s = ctx->s; struct tty_ctx ttyctx; struct grid_cell gc; - u_int xx, yy; + u_int xx, yy, sx, xoff, yoff, cx, i, n; + struct visible_ranges *r; + struct visible_range *ri; memcpy(&gc, &grid_default_cell, sizeof gc); utf8_set(&gc.data, 'E'); @@ -1141,15 +1143,45 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx) screen_write_initctx(ctx, &ttyctx, 1, 1); screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1); - tty_write(tty_cmd_alignmenttest, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_alignmenttest, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + for (yy = 0; yy < screen_size_y(s); yy++) { + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + yy, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + ttyctx.ocx = cx; + ttyctx.ocy = yy; + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } + } } /* Insert nx characters. */ void screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) { - struct screen *s = ctx->s; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct tty_ctx ttyctx; + u_int sx, xoff, yoff, cx, n, i; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; if (nx == 0) nx = 1; @@ -1174,15 +1206,44 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; - tty_write(tty_cmd_insertcharacter, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_insertcharacter, &ttyctx); + return; + } + + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + sx = screen_size_x(s); + + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff + s->cx, yoff + s->cy, sx - s->cx, NULL); + + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(s->grid, cx, s->cy, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } } /* Delete nx characters. */ void screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) { - struct screen *s = ctx->s; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct tty_ctx ttyctx; + u_int sx, xoff, yoff, cx, n, i; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; if (nx == 0) nx = 1; @@ -1207,15 +1268,44 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; - tty_write(tty_cmd_deletecharacter, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_deletecharacter, &ttyctx); + return; + } + + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + sx = screen_size_x(s); + + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff + s->cx, yoff + s->cy, sx - s->cx, NULL); + + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(s->grid, cx, s->cy, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } } /* Clear nx characters. */ void screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) { - struct screen *s = ctx->s; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct tty_ctx ttyctx; + u_int sx, xoff, yoff, cx, n, i; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; if (nx == 0) nx = 1; @@ -1233,26 +1323,57 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) ctx->wp->flags |= PANE_REDRAW; #endif - screen_write_initctx(ctx, &ttyctx, 0, 0); + screen_write_initctx(ctx, &ttyctx, 0, 1); ttyctx.bg = bg; grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg); screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; - tty_write(tty_cmd_clearcharacter, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_clearcharacter, &ttyctx); + return; + } + + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + sx = screen_size_x(s); + + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff + s->cx, yoff + s->cy, sx - s->cx, NULL); + + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(s->grid, cx, s->cy, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } } /* Insert ny lines. */ void screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) { - struct screen *s = ctx->s; - struct grid *gd = s->grid; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct grid *gd = s->grid; + struct tty_ctx ttyctx; + u_int sx, sy, xoff, yoff, y, cx, i, n; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; #ifdef ENABLE_SIXEL - u_int sy = screen_size_y(s); + sy = screen_size_y(s); +#else + sy = screen_size_y(s); #endif if (ny == 0) @@ -1276,7 +1397,34 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_insertline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_insertline, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + for (y = s->cy; y < sy; y++) { + screen_write_set_cursor(ctx, 0, y); + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + y, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(gd, cx, y, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } + } return; } @@ -1296,17 +1444,49 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_insertline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_insertline, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + for (y = s->cy; y <= s->rlower; y++) { + screen_write_set_cursor(ctx, 0, y); + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + y, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(gd, cx, y, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } + } } /* Delete ny lines. */ void screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) { - struct screen *s = ctx->s; - struct grid *gd = s->grid; - struct tty_ctx ttyctx; - u_int sy = screen_size_y(s); + struct screen *s = ctx->s; + struct grid *gd = s->grid; + struct tty_ctx ttyctx; + u_int sx, sy, xoff, yoff, y, cx, i, n; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; + + sy = screen_size_y(s); if (ny == 0) ny = 1; @@ -1329,7 +1509,34 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_deleteline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_deleteline, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + for (y = s->cy; y < sy; y++) { + screen_write_set_cursor(ctx, 0, y); + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + y, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(gd, cx, y, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } + } return; } @@ -1348,7 +1555,34 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_deleteline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_deleteline, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + for (y = s->cy; y <= s->rlower; y++) { + screen_write_set_cursor(ctx, 0, y); + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + y, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(gd, cx, y, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } + } } /* Clear line at cursor. */ @@ -1486,8 +1720,12 @@ screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py, void screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg) { - struct screen *s = ctx->s; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct tty_ctx ttyctx; + u_int sx, xoff, yoff, cx, i, n; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; if (s->cy == s->rupper) { #ifdef ENABLE_SIXEL @@ -1501,10 +1739,33 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 0); ttyctx.bg = bg; - tty_write(tty_cmd_reverseindex, &ttyctx); + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_reverseindex, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + screen_write_set_cursor(ctx, 0, s->rupper); + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + s->rupper, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(s->grid, cx, s->rupper, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } } else if (s->cy > 0) screen_write_set_cursor(ctx, -1, s->cy - 1); - } /* Set scroll region. */ @@ -1604,10 +1865,13 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg) void screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg) { - struct screen *s = ctx->s; - struct grid *gd = s->grid; - struct tty_ctx ttyctx; - u_int i; + struct screen *s = ctx->s; + struct grid *gd = s->grid; + struct tty_ctx ttyctx; + u_int sx, xoff, yoff, y, cx, i, n; + struct visible_ranges *r; + struct visible_range *ri; + struct grid_cell gc; screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; @@ -1627,7 +1891,34 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = lines; - tty_write(tty_cmd_scrolldown, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_scrolldown, &ttyctx); + return; + } + + sx = screen_size_x(s); + xoff = ctx->wp->xoff; + yoff = ctx->wp->yoff; + + for (y = s->rupper; y <= s->rlower; y++) { + screen_write_set_cursor(ctx, 0, y); + r = screen_redraw_get_visible_ranges(ctx->wp, + xoff, yoff + y, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(gd, cx, y, &gc); + screen_write_set_cursor(ctx, cx, -1); + ttyctx.cell = &gc; + tty_write(tty_cmd_cell, &ttyctx); + } + } + } } /* Carriage return (cursor to start of line). */ @@ -2774,9 +3065,14 @@ screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si, } screen_write_collect_flush(ctx, 0, __func__); - screen_write_initctx(ctx, &ttyctx, 0, 0); + screen_write_initctx(ctx, &ttyctx, 0, 1); ttyctx.image = image_store(s, si); + if ((ttyctx.flags & TTY_CTX_PANE_OBSCURED) && ctx->wp != NULL) { + ctx->wp->flags |= PANE_REDRAW; + return; + } + tty_write(tty_cmd_sixelimage, &ttyctx); screen_write_cursormove(ctx, 0, cy + y, 0); diff --git a/tty.c b/tty.c index e6fd3da7..710d15c5 100644 --- a/tty.c +++ b/tty.c @@ -1442,8 +1442,6 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py) */ r = tty_check_overlay_range(tty, ctx->xoff, ctx->yoff + py, nx); - r = screen_redraw_get_visible_ranges(wp, - ctx->xoff, ctx->yoff + py, nx, r); for (i = 0; i < r->used; i++) { ri = &r->ranges[i]; if (ri->nx == 0) continue; @@ -2113,8 +2111,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - if (screen_redraw_is_visible(r, px)) - tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette, + tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette, ctx->s->hyperlinks); if (ctx->flags & TTY_CTX_CELL_INVALIDATE) From eb330a6df64b80205e3c6c96adf6fbbdea1e768f Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 May 2026 10:05:41 +0100 Subject: [PATCH 6/6] Restore SIXEL bit. --- screen-redraw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/screen-redraw.c b/screen-redraw.c index 020466c6..dc96c517 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1337,6 +1337,10 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) ri->px, py, &defaults, palette); } } + +#ifdef ENABLE_SIXEL + tty_draw_images(c, wp, s); +#endif } /* Draw the panes scrollbars */