Add visible range checks to screen_write.c functions and remove checks from tty.c.

This commit is contained in:
Michael Grant
2026-05-24 09:58:30 +01:00
parent 8b474429b7
commit 30866d06d5
2 changed files with 331 additions and 38 deletions

View File

@@ -1118,7 +1118,9 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
struct grid_cell gc; 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); memcpy(&gc, &grid_default_cell, sizeof gc);
utf8_set(&gc.data, 'E'); 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_initctx(ctx, &ttyctx, 1, 1);
screen_write_collect_clear(ctx, 0, screen_size_y(s) - 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. */ /* Insert nx characters. */
void void
screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; 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) if (nx == 0)
nx = 1; 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = nx; 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. */ /* Delete nx characters. */
void void
screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; 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) if (nx == 0)
nx = 1; 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = nx; 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. */ /* Clear nx characters. */
void void
screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; 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) if (nx == 0)
nx = 1; 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; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 0, 0); screen_write_initctx(ctx, &ttyctx, 0, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg); grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg);
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = nx; 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. */ /* Insert ny lines. */
void void
screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct tty_ctx ttyctx; 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 #ifdef ENABLE_SIXEL
u_int sy = screen_size_y(s); sy = screen_size_y(s);
#else
sy = screen_size_y(s);
#endif #endif
if (ny == 0) 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = ny; 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; 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = ny; 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. */ /* Delete ny lines. */
void void
screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sy = screen_size_y(s); 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) if (ny == 0)
ny = 1; 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = ny; 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; 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = ny; 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. */ /* Clear line at cursor. */
@@ -1486,8 +1720,12 @@ screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py,
void void
screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg) screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; 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) { if (s->cy == s->rupper) {
#ifdef ENABLE_SIXEL #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); screen_write_initctx(ctx, &ttyctx, 1, 0);
ttyctx.bg = bg; 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) } else if (s->cy > 0)
screen_write_set_cursor(ctx, -1, s->cy - 1); screen_write_set_cursor(ctx, -1, s->cy - 1);
} }
/* Set scroll region. */ /* Set scroll region. */
@@ -1604,10 +1865,13 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
void void
screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg) screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int i; 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); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; 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__); screen_write_collect_flush(ctx, 0, __func__);
ttyctx.n = lines; 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). */ /* 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_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); 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); tty_write(tty_cmd_sixelimage, &ttyctx);
screen_write_cursormove(ctx, 0, cy + y, 0); screen_write_cursormove(ctx, 0, cy + y, 0);

5
tty.c
View File

@@ -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, r = tty_check_overlay_range(tty, ctx->xoff,
ctx->yoff + py, nx); 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++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
if (ri->nx == 0) continue; 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_margin_off(tty);
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); 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); ctx->s->hyperlinks);
if (ctx->flags & TTY_CTX_CELL_INVALIDATE) if (ctx->flags & TTY_CTX_CELL_INVALIDATE)