mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-07 04:06:07 -05:00
osc: extend damage-cells-by-color to default fg/bg as well
When changing part of the color palette, through either OSC-4, or OSC-10 and OSC-11 (and the corresponding reset OSCs: 104, 110 and 111), only dirty affected cells. We've always done this, but only for OSC-4. This patch breaks out that logic, and extends it to handle default fg/bg too. It also fixes a bug where cells with colored underlines were not dirtied if the underline was the only part of the cell that was affected by a OSC-4 change.
This commit is contained in:
parent
e5ed387426
commit
22c8637610
4 changed files with 102 additions and 51 deletions
6
csi.c
6
csi.c
|
|
@ -2098,8 +2098,10 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
sizeof(term->colors));
|
||||
term->color_stack.idx = slot - 1;
|
||||
|
||||
/* TODO: we _could_ iterate all cells and only dirty
|
||||
those that are affected by the palette change... */
|
||||
/* Assume a full palette switch *will* affect almost
|
||||
all cells. The alternative is to call
|
||||
term_damage_color() for all 256 palette entries
|
||||
*and* the default fg/bg (256 + 2 calls in total) */
|
||||
term_damage_view(term);
|
||||
term_damage_margins(term);
|
||||
} else if (slot == 0) {
|
||||
|
|
|
|||
56
osc.c
56
osc.c
|
|
@ -651,47 +651,7 @@ osc_dispatch(struct terminal *term)
|
|||
idx, term->colors.table[idx], color);
|
||||
|
||||
term->colors.table[idx] = color;
|
||||
|
||||
/* Dirty visible, affected cells */
|
||||
for (int r = 0; r < term->rows; r++) {
|
||||
struct row *row = grid_row_in_view(term->grid, r);
|
||||
struct cell *cell = &row->cells[0];
|
||||
|
||||
for (int c = 0; c < term->cols; c++, cell++) {
|
||||
bool dirty = false;
|
||||
|
||||
switch (cell->attrs.fg_src) {
|
||||
case COLOR_BASE16:
|
||||
case COLOR_BASE256:
|
||||
if (cell->attrs.fg == idx)
|
||||
dirty = true;
|
||||
break;
|
||||
|
||||
case COLOR_DEFAULT:
|
||||
case COLOR_RGB:
|
||||
/* Not affected */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cell->attrs.bg_src) {
|
||||
case COLOR_BASE16:
|
||||
case COLOR_BASE256:
|
||||
if (cell->attrs.bg == idx)
|
||||
dirty = true;
|
||||
break;
|
||||
|
||||
case COLOR_DEFAULT:
|
||||
case COLOR_RGB:
|
||||
/* Not affected */
|
||||
break;
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
cell->attrs.clean = 0;
|
||||
row->dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
term_damage_color(term, COLOR_BASE256, idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +732,7 @@ osc_dispatch(struct terminal *term)
|
|||
switch (param) {
|
||||
case 10:
|
||||
term->colors.fg = color;
|
||||
term_damage_view(term);
|
||||
term_damage_color(term, COLOR_DEFAULT, 0);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
|
|
@ -786,7 +746,7 @@ osc_dispatch(struct terminal *term)
|
|||
term_font_subpixel_changed(term);
|
||||
}
|
||||
}
|
||||
term_damage_view(term);
|
||||
term_damage_color(term, COLOR_DEFAULT, 0);
|
||||
term_damage_margins(term);
|
||||
break;
|
||||
|
||||
|
|
@ -798,13 +758,11 @@ osc_dispatch(struct terminal *term)
|
|||
case 17:
|
||||
term->colors.selection_bg = color;
|
||||
term->colors.use_custom_selection = true;
|
||||
term_damage_view(term);
|
||||
break;
|
||||
|
||||
case 19:
|
||||
term->colors.selection_fg = color;
|
||||
term->colors.use_custom_selection = true;
|
||||
term_damage_view(term);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -829,6 +787,7 @@ osc_dispatch(struct terminal *term)
|
|||
LOG_DBG("resetting all colors");
|
||||
for (size_t i = 0; i < ALEN(term->colors.table); i++)
|
||||
term->colors.table[i] = term->conf->colors.table[i];
|
||||
term_damage_view(term);
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
@ -850,11 +809,10 @@ osc_dispatch(struct terminal *term)
|
|||
|
||||
LOG_DBG("resetting color #%u", idx);
|
||||
term->colors.table[idx] = term->conf->colors.table[idx];
|
||||
term_damage_color(term, COLOR_BASE256, idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
term_damage_view(term);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -864,14 +822,14 @@ osc_dispatch(struct terminal *term)
|
|||
case 110: /* Reset default text foreground color */
|
||||
LOG_DBG("resetting foreground color");
|
||||
term->colors.fg = term->conf->colors.fg;
|
||||
term_damage_view(term);
|
||||
term_damage_color(term, COLOR_DEFAULT, 0);
|
||||
break;
|
||||
|
||||
case 111: /* Reset default text background color */
|
||||
LOG_DBG("resetting background color");
|
||||
term->colors.bg = term->conf->colors.bg;
|
||||
term->colors.alpha = term->conf->colors.alpha;
|
||||
term_damage_view(term);
|
||||
term_damage_color(term, COLOR_DEFAULT, 0);
|
||||
term_damage_margins(term);
|
||||
break;
|
||||
|
||||
|
|
|
|||
90
terminal.c
90
terminal.c
|
|
@ -2386,6 +2386,96 @@ term_damage_margins(struct terminal *term)
|
|||
term->render.margins = true;
|
||||
}
|
||||
|
||||
void
|
||||
term_damage_color(struct terminal *term, enum color_source src, int idx)
|
||||
{
|
||||
xassert(src == COLOR_DEFAULT || src == COLOR_BASE256);
|
||||
|
||||
for (int r = 0; r < term->rows; r++) {
|
||||
struct row *row = grid_row_in_view(term->grid, r);
|
||||
struct cell *cell = &row->cells[0];
|
||||
const struct cell *end = &row->cells[term->cols];
|
||||
|
||||
for (; cell < end; cell++) {
|
||||
bool dirty = false;
|
||||
|
||||
switch (cell->attrs.fg_src) {
|
||||
case COLOR_BASE16:
|
||||
case COLOR_BASE256:
|
||||
if (src == COLOR_BASE256 && cell->attrs.fg == idx)
|
||||
dirty = true;
|
||||
break;
|
||||
|
||||
case COLOR_DEFAULT:
|
||||
if (src == COLOR_DEFAULT) {
|
||||
/* Doesn't matter whether we've updated the
|
||||
default foreground, or background, we still
|
||||
want to dirty this cell, to be sure we handle
|
||||
all cases of color inversion/reversal */
|
||||
dirty = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB:
|
||||
/* Not affected */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cell->attrs.bg_src) {
|
||||
case COLOR_BASE16:
|
||||
case COLOR_BASE256:
|
||||
if (src == COLOR_BASE256 && cell->attrs.bg == idx)
|
||||
dirty = true;
|
||||
break;
|
||||
|
||||
case COLOR_DEFAULT:
|
||||
if (src == COLOR_DEFAULT) {
|
||||
/* Doesn't matter whether we've updated the
|
||||
default foreground, or background, we still
|
||||
want to dirty this cell, to be sure we handle
|
||||
all cases of color inversion/reversal */
|
||||
dirty = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB:
|
||||
/* Not affected */
|
||||
break;
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
cell->attrs.clean = 0;
|
||||
row->dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Colored underlines */
|
||||
if (row->extra != NULL) {
|
||||
const struct row_ranges *underlines = &row->extra->underline_ranges;
|
||||
|
||||
for (int i = 0; i < underlines->count; i++) {
|
||||
const struct row_range *range = &underlines->v[i];
|
||||
|
||||
/* Underline colors are either default, or
|
||||
BASE256/RGB, but never BASE16 */
|
||||
xassert(range->underline.color_src == COLOR_DEFAULT ||
|
||||
range->underline.color_src == COLOR_BASE256 ||
|
||||
range->underline.color_src == COLOR_RGB);
|
||||
|
||||
if (range->underline.color_src == src) {
|
||||
struct cell *c = &row->cells[range->start];
|
||||
const struct cell *e = &row->cells[range->end + 1];
|
||||
|
||||
for (; c < e; c++)
|
||||
c->attrs.clean = 0;
|
||||
|
||||
row->dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
term_damage_scroll(struct terminal *term, enum damage_type damage_type,
|
||||
struct scroll_region region, int lines)
|
||||
|
|
|
|||
|
|
@ -845,6 +845,7 @@ void term_damage_view(struct terminal *term);
|
|||
|
||||
void term_damage_cursor(struct terminal *term);
|
||||
void term_damage_margins(struct terminal *term);
|
||||
void term_damage_color(struct terminal *term, enum color_source src, int idx);
|
||||
|
||||
void term_reset_view(struct terminal *term);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue