From 35485f2b5ed19b5fb5d49f5c8b1a400c94dca6eb Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 21 Jan 2026 12:23:46 +0000 Subject: [PATCH] Fix selection with tty_draw_line. --- screen.c | 5 +++-- tmux.h | 4 +++- tty-draw.c | 25 +++++++++++++++++-------- tty.c | 2 +- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/screen.c b/screen.c index 247d596d..693b50dc 100644 --- a/screen.c +++ b/screen.c @@ -581,12 +581,12 @@ screen_check_selection(struct screen *s, u_int px, u_int py) } /* Get selected grid cell. */ -void +int screen_select_cell(struct screen *s, struct grid_cell *dst, const struct grid_cell *src) { if (s->sel == NULL || s->sel->hidden) - return; + return (0); memcpy(dst, &s->sel->cell, sizeof *dst); if (COLOUR_DEFAULT(dst->fg)) @@ -600,6 +600,7 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, dst->attr |= (src->attr & GRID_ATTR_CHARSET); else dst->attr |= src->attr; + return (1); } /* Reflow wrapped lines. */ diff --git a/tmux.h b/tmux.h index ec1bd543..424b6093 100644 --- a/tmux.h +++ b/tmux.h @@ -2559,6 +2559,8 @@ void tty_set_path(struct tty *, const char *); void tty_default_attributes(struct tty *, const struct grid_cell *, struct colour_palette *, u_int, struct hyperlinks *); void tty_update_mode(struct tty *, int, struct screen *); +const struct grid_cell *tty_check_codeset(struct tty *, + const struct grid_cell *); struct visible_ranges *tty_check_overlay_range(struct tty *, u_int, u_int, u_int); @@ -3237,7 +3239,7 @@ void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, void screen_clear_selection(struct screen *); void screen_hide_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); -void screen_select_cell(struct screen *, struct grid_cell *, +int screen_select_cell(struct screen *, struct grid_cell *, const struct grid_cell *); void screen_alternate_on(struct screen *, struct grid_cell *, int); void screen_alternate_off(struct screen *, struct grid_cell *, int); diff --git a/tty-draw.c b/tty-draw.c index d79325c3..3d77d4a1 100644 --- a/tty-draw.c +++ b/tty-draw.c @@ -113,7 +113,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, struct colour_palette *palette) { struct grid *gd = s->grid; - struct grid_cell gc, last; + struct grid_cell gc, *gcp, ngc, last; struct grid_line *gl; u_int i, j, last_i, cx, ex, width; u_int cellsize, bg; @@ -169,6 +169,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, } if (i == 0) bg = gc.bg; + else if (screen_select_cell(s, &ngc, &gc)) + bg = ngc.bg; else bg = defaults->bg; tty_attributes(tty, &last, defaults, palette, s->hyperlinks); @@ -220,6 +222,13 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, /* Get the current cell. */ grid_view_get_cell(gd, px + i, py, &gc); + /* Update for codeset if needed. */ + gcp = tty_check_codeset(tty, &gc); + + /* And for selection. */ + if (screen_select_cell(s, &ngc, gcp)) + gcp = &ngc; + /* Work out the the empty width. */ if (i >= ex) empty = 1; @@ -231,10 +240,10 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, next_state = TTY_DRAW_LINE_EMPTY; else if (current_state == TTY_DRAW_LINE_FIRST) next_state = TTY_DRAW_LINE_SAME; - else if (gc.flags & GRID_FLAG_PADDING) + else if (gcp->flags & GRID_FLAG_PADDING) next_state = TTY_DRAW_LINE_PAD; else if (grid_cells_look_equal(&gc, &last)) { - if (gc.data.size > (sizeof buf) - len) + if (gcp->data.size > (sizeof buf) - len) next_state = TTY_DRAW_LINE_FLUSH; else next_state = TTY_DRAW_LINE_SAME; @@ -244,7 +253,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, next_state = TTY_DRAW_LINE_NEW1; } log_debug("%s: cell %u empty %u, bg %u; state: current %s, " - "next %s", __func__, px + i, empty, gc.bg, + "next %s", __func__, px + i, empty, gcp->bg, tty_draw_line_states[current_state], tty_draw_line_states[next_state]); @@ -278,9 +287,9 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, /* Append the cell if it is not empty and not padding. */ if (next_state != TTY_DRAW_LINE_EMPTY && next_state != TTY_DRAW_LINE_PAD) { - memcpy(buf + len, gc.data.data, gc.data.size); - len += gc.data.size; - width += gc.data.width; + memcpy(buf + len, gcp->data.data, gcp->data.size); + len += gcp->data.size; + width += gcp->data.width; } /* If this is the last cell, we are done. */ @@ -289,7 +298,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, /* Otherwise move to the next. */ current_state = next_state; - memcpy(&last, &gc, sizeof last); + memcpy(&last, gcp, sizeof last); if (empty != 0) i += empty; else diff --git a/tty.c b/tty.c index 5ff225d6..2b5e91c5 100644 --- a/tty.c +++ b/tty.c @@ -1388,7 +1388,7 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py) } } -static const struct grid_cell * +const struct grid_cell * tty_check_codeset(struct tty *tty, const struct grid_cell *gc) { static struct grid_cell new;