Fix selection with tty_draw_line.

This commit is contained in:
Nicholas Marriott
2026-01-21 12:23:46 +00:00
parent b108653f02
commit 35485f2b5e
4 changed files with 24 additions and 12 deletions

View File

@@ -581,12 +581,12 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
} }
/* Get selected grid cell. */ /* Get selected grid cell. */
void int
screen_select_cell(struct screen *s, struct grid_cell *dst, screen_select_cell(struct screen *s, struct grid_cell *dst,
const struct grid_cell *src) const struct grid_cell *src)
{ {
if (s->sel == NULL || s->sel->hidden) if (s->sel == NULL || s->sel->hidden)
return; return (0);
memcpy(dst, &s->sel->cell, sizeof *dst); memcpy(dst, &s->sel->cell, sizeof *dst);
if (COLOUR_DEFAULT(dst->fg)) 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); dst->attr |= (src->attr & GRID_ATTR_CHARSET);
else else
dst->attr |= src->attr; dst->attr |= src->attr;
return (1);
} }
/* Reflow wrapped lines. */ /* Reflow wrapped lines. */

4
tmux.h
View File

@@ -2559,6 +2559,8 @@ void tty_set_path(struct tty *, const char *);
void tty_default_attributes(struct tty *, const struct grid_cell *, void tty_default_attributes(struct tty *, const struct grid_cell *,
struct colour_palette *, u_int, struct hyperlinks *); struct colour_palette *, u_int, struct hyperlinks *);
void tty_update_mode(struct tty *, int, struct screen *); 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, struct visible_ranges *tty_check_overlay_range(struct tty *, u_int, 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_clear_selection(struct screen *);
void screen_hide_selection(struct screen *); void screen_hide_selection(struct screen *);
int screen_check_selection(struct screen *, u_int, u_int); 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 *); const struct grid_cell *);
void screen_alternate_on(struct screen *, struct grid_cell *, int); void screen_alternate_on(struct screen *, struct grid_cell *, int);
void screen_alternate_off(struct screen *, struct grid_cell *, int); void screen_alternate_off(struct screen *, struct grid_cell *, int);

View File

@@ -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 colour_palette *palette)
{ {
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct grid_cell gc, last; struct grid_cell gc, *gcp, ngc, last;
struct grid_line *gl; struct grid_line *gl;
u_int i, j, last_i, cx, ex, width; u_int i, j, last_i, cx, ex, width;
u_int cellsize, bg; 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) if (i == 0)
bg = gc.bg; bg = gc.bg;
else if (screen_select_cell(s, &ngc, &gc))
bg = ngc.bg;
else else
bg = defaults->bg; bg = defaults->bg;
tty_attributes(tty, &last, defaults, palette, s->hyperlinks); 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. */ /* Get the current cell. */
grid_view_get_cell(gd, px + i, py, &gc); 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. */ /* Work out the the empty width. */
if (i >= ex) if (i >= ex)
empty = 1; 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; next_state = TTY_DRAW_LINE_EMPTY;
else if (current_state == TTY_DRAW_LINE_FIRST) else if (current_state == TTY_DRAW_LINE_FIRST)
next_state = TTY_DRAW_LINE_SAME; 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; next_state = TTY_DRAW_LINE_PAD;
else if (grid_cells_look_equal(&gc, &last)) { 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; next_state = TTY_DRAW_LINE_FLUSH;
else else
next_state = TTY_DRAW_LINE_SAME; 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; next_state = TTY_DRAW_LINE_NEW1;
} }
log_debug("%s: cell %u empty %u, bg %u; state: current %s, " 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[current_state],
tty_draw_line_states[next_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. */ /* Append the cell if it is not empty and not padding. */
if (next_state != TTY_DRAW_LINE_EMPTY && if (next_state != TTY_DRAW_LINE_EMPTY &&
next_state != TTY_DRAW_LINE_PAD) { next_state != TTY_DRAW_LINE_PAD) {
memcpy(buf + len, gc.data.data, gc.data.size); memcpy(buf + len, gcp->data.data, gcp->data.size);
len += gc.data.size; len += gcp->data.size;
width += gc.data.width; width += gcp->data.width;
} }
/* If this is the last cell, we are done. */ /* 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. */ /* Otherwise move to the next. */
current_state = next_state; current_state = next_state;
memcpy(&last, &gc, sizeof last); memcpy(&last, gcp, sizeof last);
if (empty != 0) if (empty != 0)
i += empty; i += empty;
else else

2
tty.c
View File

@@ -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) tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
{ {
static struct grid_cell new; static struct grid_cell new;