Cleanup - screen_redraw_get_visible_ranges returns a value rather than pass addr of arg. Bugfix to redraw code.

This commit is contained in:
Michael Grant 2025-10-11 18:07:22 +01:00
parent 5faf41b695
commit ce03f1abea
3 changed files with 106 additions and 84 deletions

View File

@ -887,28 +887,30 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
/* Construct ranges of line at px,py of width cells of base_wp that are /* Construct ranges of line at px,py of width cells of base_wp that are
unobsructed. */ unobsructed. */
void struct visible_ranges *
screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width, screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
struct window_pane *base_wp, struct visible_range **vr_p, struct window_pane *base_wp) {
int *vr_count_p) {
struct window_pane *wp; struct window_pane *wp;
struct window *w; struct window *w;
struct visible_range *vr; static struct visible_ranges ranges = { NULL, 0, 0 };
int found_self, r, s; static struct visible_range *vr;
int vr_len, vr_count; int found_self;
u_int r, s;
/* Caller must call free(vr). */ /* For efficiency ranges is static and space reused. */
vr = xcalloc(4, sizeof(struct visible_range *)); if (ranges.array == NULL) {
vr_len = 4; ranges.array = xcalloc(4, sizeof(struct visible_range *));
ranges.size = 4;
}
/* Start with the entire width of the range. */
vr = ranges.array;
vr[0].px = px; vr[0].px = px;
vr[0].nx = width; vr[0].nx = width;
vr_count = 1; ranges.n = 1;
if (base_wp == NULL) { if (base_wp == NULL)
*vr_p = vr; return (&ranges);
*vr_count_p = vr_count;
return;
}
w = base_wp->window; w = base_wp->window;
@ -917,50 +919,59 @@ screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
found_self = 1; found_self = 1;
continue; continue;
} }
if (found_self && wp->layout_cell == NULL &&
!(wp->flags & PANE_MINIMISED) && if (!found_self || wp->layout_cell != NULL ||
(py >= wp->yoff && py <= wp->yoff + wp->sy)) { (wp->flags & PANE_MINIMISED) ||
for (r=0; r<vr_count; r++) { (py < wp->yoff || py > wp->yoff + wp->sy))
/* if the left edge of wp continue;
for (r=0; r<ranges.n; r++) {
/* If the left edge of floating wp
falls inside this range and right falls inside this range and right
edge greater than this range, edge covers up to right of range,
then shrink nx */ then shrink left edge of range. */
if (wp->xoff > vr[r].px && if (wp->xoff > vr[r].px &&
wp->xoff < vr[r].px + vr[r].nx && wp->xoff < vr[r].px + vr[r].nx &&
wp->xoff + wp->sx > vr[r].px + vr[r].nx) { wp->xoff + wp->sx >= vr[r].px + vr[r].nx) {
vr[r].nx = wp->xoff; vr[r].nx = wp->xoff;
/* else if the right edge of wp }
/* Else if the right edge of floating wp
falls inside of this range and left falls inside of this range and left
edge is less than the start of the range, edge covers the left of range,
then move px forward */ then move px forward to right edge of wp. */
} else if (wp->xoff + wp->sx > vr[r].px && else if (wp->xoff + wp->sx > vr[r].px &&
wp->xoff + wp->sx < vr[r].px + vr[r].nx && wp->xoff + wp->sx < vr[r].px + vr[r].nx &&
wp->xoff < vr[r].px) { wp->xoff <= vr[r].px) {
vr[r].px = vr[r].px + (wp->xoff + wp->sx); vr[r].px = vr[r].px + (wp->xoff + wp->sx);
vr[r].nx = vr[r].nx - (wp->xoff + wp->sx); vr[r].nx = vr[r].nx - (wp->xoff + wp->sx);
/* else if wp fully inside range
then split range into 2 ranges */
} else if (wp->xoff > vr[r].px &&
wp->xoff + wp->sx < vr[r].px + vr[r].nx) {
/* make space */
if (vr_len == vr_count) {
vr = xreallocarray(vr, vr_len +
4, sizeof *vr);
vr_len += 4;
} }
for (s=vr_count; s>r; s--) { /* Else if wp fully inside range
then split range into 2 ranges. */
else if (wp->xoff > vr[r].px &&
wp->xoff + wp->sx < vr[r].px + vr[r].nx) {
if (ranges.size == ranges.n) {
ranges.array = xreallocarray(vr,
ranges.size += 4, sizeof *vr);
ranges.array = vr;
}
for (s=ranges.n; s>r; s--) {
vr[s].px = vr[s-1].px; vr[s].px = vr[s-1].px;
vr[s].nx = vr[s-1].nx; vr[s].nx = vr[s-1].nx;
} }
vr[r].nx = wp->xoff; vr[r].nx = wp->xoff;
vr[r+1].px = wp->xoff + wp->sx; vr[r+1].px = wp->xoff + wp->sx;
vr_count++; ranges.n++;
} /* XXX what if it's completely obscured? */ }
/* If floating wp completely covers this range
then delete it (make it 0 length). */
else if (wp->xoff <= vr[r].px &&
wp->xoff+wp->sx >= vr[r].px+vr[r].nx) {
vr[r].nx = 0;
}
/* Else the range is already obscured, do nothing. */
} }
} }
} return (&ranges);
*vr_p = vr;
*vr_count_p = vr_count;
} }
@ -974,9 +985,9 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
struct screen *s = wp->screen; struct screen *s = wp->screen;
struct colour_palette *palette = &wp->palette; struct colour_palette *palette = &wp->palette;
struct grid_cell defaults; struct grid_cell defaults;
struct visible_ranges *visible_ranges;
struct visible_range *vr; struct visible_range *vr;
int vr_count, r; u_int i, j, top, x, y, width, r;
u_int i, j, top, x, y, width;
log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id); log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id);
@ -1019,15 +1030,21 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
__func__, c->name, wp->id, i, j, x, y, width); __func__, c->name, wp->id, i, j, x, y, width);
/* Get visible ranges of line before we draw it. */ /* Get visible ranges of line before we draw it. */
screen_redraw_get_visible_ranges(x, y, width, wp, visible_ranges = screen_redraw_get_visible_ranges(x, y, width,
&vr, &vr_count); wp);
vr = visible_ranges->array;
tty_default_colours(&defaults, wp); tty_default_colours(&defaults, wp);
for (r=0; r<vr_count; r++) for (r=0; r<visible_ranges->n; r++) {
tty_draw_line(tty, s, i + vr[r].px, j, if (vr[r].nx == 0)
continue;
/* i is px of cell, add px of region, sub the
pane offset. If you don't sub offset,
contents of pane shifted. */
tty_draw_line(tty, s, i+vr[r].px-wp->xoff, j,
vr[r].nx, vr[r].px, y, &defaults, palette); vr[r].nx, vr[r].px, y, &defaults, palette);
free(vr); }
} }
#ifdef ENABLE_SIXEL #ifdef ENABLE_SIXEL

View File

@ -1747,13 +1747,13 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct screen_write_cline *cl_src, *cl_dst; struct screen_write_cline *cl_src, *cl_dst;
u_int y, r_start, r_end; u_int y, r, r_start, r_end;
u_int ci_start, ci_end, new_end; u_int ci_start, ci_end, new_end;
char *saved; char *saved;
struct screen_write_citem *ci, *new_ci; struct screen_write_citem *ci, *new_ci;
struct window_pane *wp = ctx->wp; struct window_pane *wp = ctx->wp;
struct visible_ranges *visible_ranges;
struct visible_range *vr; struct visible_range *vr;
int vr_count, r;
log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy, log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
s->rupper, s->rlower); s->rupper, s->rlower);
@ -1766,11 +1766,10 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
for (y = s->rupper; y < s->rlower; y++) { for (y = s->rupper; y < s->rlower; y++) {
cl_src = &s->write_list[y + 1]; cl_src = &s->write_list[y + 1];
cl_dst = &s->write_list[y]; cl_dst = &s->write_list[y];
vr = NULL;
vr_count = 0;
screen_redraw_get_visible_ranges(0, y, screen_size_x(s), wp, visible_ranges = screen_redraw_get_visible_ranges(0, y,
&vr, &vr_count); screen_size_x(s), wp);
vr = visible_ranges->array;
TAILQ_INIT(&cl_dst->items); TAILQ_INIT(&cl_dst->items);
@ -1779,7 +1778,8 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
/* For each visible range, copy corresponding items from cl_src /* For each visible range, copy corresponding items from cl_src
to cl_dst. */ to cl_dst. */
for (r = 0; r < vr_count; r++) { for (r = 0; r < visible_ranges->n; r++) {
if (vr[r].nx == 0) continue;
r_start = vr[r].px; r_start = vr[r].px;
r_end = vr[r].px + vr[r].nx; r_end = vr[r].px + vr[r].nx;
@ -1806,7 +1806,6 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
entry); entry);
} }
} }
free(vr);
} }
s->write_list[s->rlower].data = saved; s->write_list[s->rlower].data = saved;
@ -1821,12 +1820,12 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct screen_write_citem *ci, *tmp; struct screen_write_citem *ci, *tmp;
struct screen_write_cline *cl; struct screen_write_cline *cl;
u_int y, cx, cy, last, items = 0; u_int y, cx, cy, last, items = 0, r;
u_int r_start, r_end, ci_start, ci_end; u_int r_start, r_end, ci_start, ci_end;
u_int wr_start, wr_end, wr_length; u_int wr_start, wr_end, wr_length;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
struct visible_range *vr = NULL; struct visible_ranges *visible_ranges;
int vr_count = 0; struct visible_range *vr;
struct window_pane *wp = ctx->wp; struct window_pane *wp = ctx->wp;
if (ctx->scrolled != 0) { if (ctx->scrolled != 0) {
@ -1854,8 +1853,9 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
for (y = 0; y < screen_size_y(s); y++) { for (y = 0; y < screen_size_y(s); y++) {
cl = &ctx->s->write_list[y]; cl = &ctx->s->write_list[y];
screen_redraw_get_visible_ranges(0, y, screen_size_x(s), wp, visible_ranges = screen_redraw_get_visible_ranges(0, y,
&vr, &vr_count); screen_size_x(s), wp);
vr = visible_ranges->array;
last = UINT_MAX; last = UINT_MAX;
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) { TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
@ -1863,7 +1863,8 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
fatalx("collect list not in order: %u <= %u", fatalx("collect list not in order: %u <= %u",
ci->x, last); ci->x, last);
} }
for (int r = 0; r < vr_count; r++) { for (r = 0; r < visible_ranges->n; r++) {
if (vr[r].nx == 0) continue;
r_start = vr[r].px; r_start = vr[r].px;
r_end = vr[r].px + vr[r].nx; r_end = vr[r].px + vr[r].nx;
ci_start = ci->x; ci_start = ci->x;
@ -1900,7 +1901,6 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
screen_write_free_citem(ci); screen_write_free_citem(ci);
last = ci->x; last = ci->x;
} }
free(vr);
} }
s->cx = cx; s->cy = cy; s->cx = cx; s->cy = cy;

13
tmux.h
View File

@ -2235,8 +2235,13 @@ struct mode_tree_sort_criteria {
}; };
struct visible_range { struct visible_range {
u_int px; u_int px; /* Start */
u_int nx; u_int nx; /* Length */
};
struct visible_ranges {
struct visible_range *array;
size_t n; /* Elements used */
size_t size; /* Array size */
}; };
/* tmux.c */ /* tmux.c */
@ -3169,8 +3174,8 @@ void screen_write_alternateoff(struct screen_write_ctx *,
/* screen-redraw.c */ /* screen-redraw.c */
void screen_redraw_screen(struct client *); void screen_redraw_screen(struct client *);
void screen_redraw_pane(struct client *, struct window_pane *, int); void screen_redraw_pane(struct client *, struct window_pane *, int);
void screen_redraw_get_visible_ranges(u_int, u_int, u_int, struct visible_ranges *screen_redraw_get_visible_ranges(u_int, u_int, u_int,
struct window_pane *, struct visible_range **, int *); struct window_pane *);
/* screen.c */ /* screen.c */