mirror of
https://github.com/tmux/tmux.git
synced 2026-10-12 05:34:24 +00:00
Store background colour in padding cells and correctly clear adjacent
cells when tabs are overwritten, GitHu issue 5441 from Ayman Bagabas.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: grid-view.c,v 1.38 2026/01/22 08:55:01 nicm Exp $ */
|
/* $OpenBSD: grid-view.c,v 1.39 2026/08/03 12:58:53 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -47,9 +47,9 @@ grid_view_set_cell(struct grid *gd, u_int px, u_int py,
|
|||||||
|
|
||||||
/* Set padding. */
|
/* Set padding. */
|
||||||
void
|
void
|
||||||
grid_view_set_padding(struct grid *gd, u_int px, u_int py)
|
grid_view_set_padding(struct grid *gd, u_int px, u_int py, int bg)
|
||||||
{
|
{
|
||||||
grid_set_padding(gd, grid_view_x(gd, px), grid_view_y(gd, py));
|
grid_set_padding(gd, grid_view_x(gd, px), grid_view_y(gd, py), bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set cells. */
|
/* Set cells. */
|
||||||
|
|||||||
10
grid.c
10
grid.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: grid.c,v 1.155 2026/07/29 17:42:56 nicm Exp $ */
|
/* $OpenBSD: grid.c,v 1.156 2026/08/03 12:58:53 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -631,9 +631,13 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
|||||||
|
|
||||||
/* Set padding at position. */
|
/* Set padding at position. */
|
||||||
void
|
void
|
||||||
grid_set_padding(struct grid *gd, u_int px, u_int py)
|
grid_set_padding(struct grid *gd, u_int px, u_int py, int bg)
|
||||||
{
|
{
|
||||||
grid_set_cell(gd, px, py, &grid_padding_cell);
|
struct grid_cell gc;
|
||||||
|
|
||||||
|
memcpy(&gc, &grid_padding_cell, sizeof gc);
|
||||||
|
gc.bg = bg;
|
||||||
|
grid_set_cell(gd, px, py, &gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set cells at position. */
|
/* Set cells at position. */
|
||||||
|
|||||||
112
screen-write.c
112
screen-write.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: screen-write.c,v 1.285 2026/07/26 09:02:08 nicm Exp $ */
|
/* $OpenBSD: screen-write.c,v 1.286 2026/08/03 12:58:53 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -2393,15 +2393,62 @@ screen_write_collect_insert_clear(struct screen_write_ctx *ctx, u_int px,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear a cell that is being broken up by a write over part of it, keeping the
|
||||||
|
* background so the columns it covered do not lose their colour.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
screen_write_clear_cell(struct grid *gd, u_int px, u_int py)
|
||||||
|
{
|
||||||
|
struct grid_cell gc;
|
||||||
|
int bg;
|
||||||
|
|
||||||
|
grid_view_get_cell(gd, px, py, &gc);
|
||||||
|
bg = gc.bg;
|
||||||
|
|
||||||
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
|
gc.bg = bg;
|
||||||
|
grid_view_set_cell(gd, px, py, &gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert clears for a range of cells already cleared in the grid. Adjacent
|
||||||
|
* cells may have come from different characters and so have different
|
||||||
|
* backgrounds, so this is done in runs of the same colour.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
screen_write_insert_clears(struct screen_write_ctx *ctx, u_int px, u_int nx)
|
||||||
|
{
|
||||||
|
struct screen *s = ctx->s;
|
||||||
|
struct grid_cell gc;
|
||||||
|
u_int xx, start = px, n;
|
||||||
|
int bg = 8;
|
||||||
|
|
||||||
|
for (xx = px; xx < px + nx; xx++) {
|
||||||
|
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
||||||
|
if (xx == start)
|
||||||
|
bg = gc.bg;
|
||||||
|
else if (gc.bg != bg) {
|
||||||
|
n = xx - start;
|
||||||
|
log_debug("%s: from %u, size %u", __func__, start, n);
|
||||||
|
screen_write_collect_insert_clear(ctx, start, n, bg);
|
||||||
|
start = xx;
|
||||||
|
bg = gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_debug("%s: from %u, size %u", __func__, start, xx - start);
|
||||||
|
screen_write_collect_insert_clear(ctx, start, xx - start, bg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Finish and store collected cells. */
|
/* Finish and store collected cells. */
|
||||||
void
|
void
|
||||||
screen_write_collect_end(struct screen_write_ctx *ctx)
|
screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct screen_write_citem *ci = ctx->item, *bci = NULL, *aci;
|
struct screen_write_citem *ci = ctx->item;
|
||||||
struct screen_write_cline *cl = &s->write_list[s->cy];
|
struct screen_write_cline *cl = &s->write_list[s->cy];
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
u_int xx;
|
u_int xx, bx = 0, bnx = 0;
|
||||||
|
|
||||||
if (ci->used == 0)
|
if (ci->used == 0)
|
||||||
return;
|
return;
|
||||||
@@ -2417,8 +2464,7 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
|||||||
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
||||||
if (~gc.flags & GRID_FLAG_PADDING)
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
break;
|
break;
|
||||||
grid_view_set_cell(s->grid, xx, s->cy,
|
screen_write_clear_cell(s->grid, xx, s->cy);
|
||||||
&grid_default_cell);
|
|
||||||
log_debug("%s: padding erased (before) at %u (cx %u)",
|
log_debug("%s: padding erased (before) at %u (cx %u)",
|
||||||
__func__, xx, s->cx);
|
__func__, xx, s->cx);
|
||||||
}
|
}
|
||||||
@@ -2427,47 +2473,31 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
|||||||
grid_view_get_cell(s->grid, 0, s->cy, &gc);
|
grid_view_get_cell(s->grid, 0, s->cy, &gc);
|
||||||
if (gc.data.width > 1 ||
|
if (gc.data.width > 1 ||
|
||||||
(gc.flags & GRID_FLAG_PADDING)) {
|
(gc.flags & GRID_FLAG_PADDING)) {
|
||||||
grid_view_set_cell(s->grid, xx, s->cy,
|
screen_write_clear_cell(s->grid, xx, s->cy);
|
||||||
&grid_default_cell);
|
|
||||||
log_debug("%s: padding erased (before) at %u "
|
log_debug("%s: padding erased (before) at %u "
|
||||||
"(cx %u)", __func__, xx, s->cx);
|
"(cx %u)", __func__, xx, s->cx);
|
||||||
}
|
}
|
||||||
}
|
bx = xx;
|
||||||
if (xx != s->cx) {
|
bnx = s->cx - xx;
|
||||||
bci = ctx->item;
|
|
||||||
bci->type = CLEAR;
|
|
||||||
bci->x = xx;
|
|
||||||
bci->bg = 8;
|
|
||||||
bci->used = s->cx - xx;
|
|
||||||
log_debug("%s: padding erased (before): from %u, "
|
|
||||||
"size %u", __func__, bci->x, bci->used);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
|
grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
|
||||||
ci->used);
|
ci->used);
|
||||||
if (bci != NULL)
|
if (bnx != 0)
|
||||||
screen_write_collect_insert(ctx, bci);
|
screen_write_insert_clears(ctx, bx, bnx);
|
||||||
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
||||||
|
|
||||||
for (xx = s->cx; xx < screen_size_x(s); xx++) {
|
for (xx = s->cx; xx < screen_size_x(s); xx++) {
|
||||||
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
grid_view_get_cell(s->grid, xx, s->cy, &gc);
|
||||||
if (~gc.flags & GRID_FLAG_PADDING)
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
break;
|
break;
|
||||||
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
|
screen_write_clear_cell(s->grid, xx, s->cy);
|
||||||
log_debug("%s: padding erased (after) at %u (cx %u)",
|
log_debug("%s: padding erased (after) at %u (cx %u)", __func__,
|
||||||
__func__, xx, s->cx);
|
xx, s->cx);
|
||||||
}
|
|
||||||
if (xx != s->cx) {
|
|
||||||
aci = ctx->item;
|
|
||||||
aci->type = CLEAR;
|
|
||||||
aci->x = s->cx;
|
|
||||||
aci->bg = 8;
|
|
||||||
aci->used = xx - s->cx;
|
|
||||||
log_debug("%s: padding erased (after): from %u, size %u",
|
|
||||||
__func__, aci->x, aci->used);
|
|
||||||
screen_write_collect_insert(ctx, aci);
|
|
||||||
}
|
}
|
||||||
|
if (xx != s->cx)
|
||||||
|
screen_write_insert_clears(ctx, s->cx, xx - s->cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write cell data, collecting if necessary. */
|
/* Write cell data, collecting if necessary. */
|
||||||
@@ -2595,7 +2625,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
*/
|
*/
|
||||||
for (xx = s->cx + 1; xx < s->cx + width; xx++) {
|
for (xx = s->cx + 1; xx < s->cx + width; xx++) {
|
||||||
log_debug("%s: new padding at %u,%u", __func__, xx, s->cy);
|
log_debug("%s: new padding at %u,%u", __func__, xx, s->cy);
|
||||||
grid_view_set_padding(gd, xx, s->cy);
|
grid_view_set_padding(gd, xx, s->cy, gc->bg);
|
||||||
skip = 0;
|
skip = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2807,7 +2837,7 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
/* Set the new cell. */
|
/* Set the new cell. */
|
||||||
grid_view_set_cell(gd, cx - n, cy, &last);
|
grid_view_set_cell(gd, cx - n, cy, &last);
|
||||||
if (force_wide)
|
if (force_wide)
|
||||||
grid_view_set_padding(gd, cx - 1, cy);
|
grid_view_set_padding(gd, cx - 1, cy, last.bg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if all of this character is visible. No character will be
|
* Check if all of this character is visible. No character will be
|
||||||
@@ -2876,12 +2906,12 @@ screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
if (~tmp_gc.flags & GRID_FLAG_PADDING)
|
if (~tmp_gc.flags & GRID_FLAG_PADDING)
|
||||||
break;
|
break;
|
||||||
log_debug("%s: padding at %u,%u", __func__, xx, s->cy);
|
log_debug("%s: padding at %u,%u", __func__, xx, s->cy);
|
||||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
screen_write_clear_cell(gd, xx, s->cy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overwrite the character at the start of this padding. */
|
/* Overwrite the character at the start of this padding. */
|
||||||
log_debug("%s: character at %u,%u", __func__, xx, s->cy);
|
log_debug("%s: character at %u,%u", __func__, xx, s->cy);
|
||||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
screen_write_clear_cell(gd, xx, s->cy);
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2899,17 +2929,7 @@ screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
break;
|
break;
|
||||||
log_debug("%s: overwrite at %u,%u", __func__, xx,
|
log_debug("%s: overwrite at %u,%u", __func__, xx,
|
||||||
s->cy);
|
s->cy);
|
||||||
if (gc->flags & GRID_FLAG_TAB) {
|
screen_write_clear_cell(gd, xx, s->cy);
|
||||||
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
|
||||||
memset(tmp_gc.data.data, 0,
|
|
||||||
sizeof tmp_gc.data.data);
|
|
||||||
*tmp_gc.data.data = ' ';
|
|
||||||
tmp_gc.data.width = tmp_gc.data.size =
|
|
||||||
tmp_gc.data.have = 1;
|
|
||||||
grid_view_set_cell(gd, xx, s->cy, &tmp_gc);
|
|
||||||
} else
|
|
||||||
grid_view_set_cell(gd, xx, s->cy,
|
|
||||||
&grid_default_cell);
|
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
tmux.h
6
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tmux.h,v 1.1418 2026/07/29 17:42:56 nicm Exp $ */
|
/* $OpenBSD: tmux.h,v 1.1419 2026/08/03 12:58:53 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -3447,7 +3447,7 @@ void grid_clear_history(struct grid *);
|
|||||||
const struct grid_line *grid_peek_line(struct grid *, u_int);
|
const struct grid_line *grid_peek_line(struct grid *, u_int);
|
||||||
void grid_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
void grid_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
||||||
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
|
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
|
||||||
void grid_set_padding(struct grid *, u_int, u_int);
|
void grid_set_padding(struct grid *, u_int, u_int, int);
|
||||||
void grid_set_cells(struct grid *, u_int, u_int, const struct grid_cell *,
|
void grid_set_cells(struct grid *, u_int, u_int, const struct grid_cell *,
|
||||||
const char *, size_t);
|
const char *, size_t);
|
||||||
struct grid_line *grid_get_line(struct grid *, u_int);
|
struct grid_line *grid_get_line(struct grid *, u_int);
|
||||||
@@ -3492,7 +3492,7 @@ void grid_reader_cursor_back_to_indentation(struct grid_reader *);
|
|||||||
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
||||||
void grid_view_set_cell(struct grid *, u_int, u_int,
|
void grid_view_set_cell(struct grid *, u_int, u_int,
|
||||||
const struct grid_cell *);
|
const struct grid_cell *);
|
||||||
void grid_view_set_padding(struct grid *, u_int, u_int);
|
void grid_view_set_padding(struct grid *, u_int, u_int, int);
|
||||||
void grid_view_set_cells(struct grid *, u_int, u_int,
|
void grid_view_set_cells(struct grid *, u_int, u_int,
|
||||||
const struct grid_cell *, const char *, size_t);
|
const struct grid_cell *, const char *, size_t);
|
||||||
void grid_view_clear_history(struct grid *, u_int);
|
void grid_view_clear_history(struct grid *, u_int);
|
||||||
|
|||||||
Reference in New Issue
Block a user