term: track cell color source

Each cell now tracks it’s current color source:

* default fg/bg
* base16 fg/bg (maps to *both* the regular and bright colors)
* base256 fg/bg
* RGB

Note that we don’t have enough bits to separate the regular from the
bright colors. These _shouldn’t_ be the same, so we ought to be
fine...
This commit is contained in:
Daniel Eklöf 2021-11-20 16:29:57 +01:00
parent 37b82efa77
commit d46af6bd7a
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 34 additions and 26 deletions

28
csi.c
View file

@ -115,7 +115,7 @@ csi_sgr(struct terminal *term)
case 35: case 35:
case 36: case 36:
case 37: case 37:
term->vt.attrs.have_fg = 1; term->vt.attrs.fg_src = COLOR_BASE16;
term->vt.attrs.fg = term->colors.table[param - 30]; term->vt.attrs.fg = term->colors.table[param - 30];
break; break;
@ -125,7 +125,7 @@ csi_sgr(struct terminal *term)
term->vt.params.v[i + 1].value == 5) term->vt.params.v[i + 1].value == 5)
{ {
uint8_t idx = term->vt.params.v[i + 2].value; uint8_t idx = term->vt.params.v[i + 2].value;
term->vt.attrs.have_fg = 1; term->vt.attrs.fg_src = COLOR_BASE256;
term->vt.attrs.fg = term->colors.table[idx]; term->vt.attrs.fg = term->colors.table[idx];
i += 2; i += 2;
@ -138,7 +138,7 @@ csi_sgr(struct terminal *term)
uint8_t r = term->vt.params.v[i + 2].value; uint8_t r = term->vt.params.v[i + 2].value;
uint8_t g = term->vt.params.v[i + 3].value; uint8_t g = term->vt.params.v[i + 3].value;
uint8_t b = term->vt.params.v[i + 4].value; uint8_t b = term->vt.params.v[i + 4].value;
term->vt.attrs.have_fg = 1; term->vt.attrs.fg_src = COLOR_RGB;
term->vt.attrs.fg = r << 16 | g << 8 | b; term->vt.attrs.fg = r << 16 | g << 8 | b;
i += 4; i += 4;
} }
@ -150,7 +150,7 @@ csi_sgr(struct terminal *term)
const struct vt_param *param = &term->vt.params.v[i]; const struct vt_param *param = &term->vt.params.v[i];
uint8_t idx = param->sub.value[1]; uint8_t idx = param->sub.value[1];
term->vt.attrs.have_fg = 1; term->vt.attrs.fg_src = COLOR_BASE256;
term->vt.attrs.fg = term->colors.table[idx]; term->vt.attrs.fg = term->colors.table[idx];
} }
@ -180,7 +180,7 @@ csi_sgr(struct terminal *term)
uint8_t g = param->sub.value[g_idx]; uint8_t g = param->sub.value[g_idx];
uint8_t b = param->sub.value[b_idx]; uint8_t b = param->sub.value[b_idx];
term->vt.attrs.have_fg = 1; term->vt.attrs.fg_src = COLOR_RGB;
term->vt.attrs.fg = r << 16 | g << 8 | b; term->vt.attrs.fg = r << 16 | g << 8 | b;
} }
@ -196,7 +196,7 @@ csi_sgr(struct terminal *term)
} }
case 39: case 39:
term->vt.attrs.have_fg = 0; term->vt.attrs.fg_src = COLOR_DEFAULT;
break; break;
/* Regular background colors */ /* Regular background colors */
@ -208,7 +208,7 @@ csi_sgr(struct terminal *term)
case 45: case 45:
case 46: case 46:
case 47: case 47:
term->vt.attrs.have_bg = 1; term->vt.attrs.bg_src = COLOR_BASE16;
term->vt.attrs.bg = term->colors.table[param - 40]; term->vt.attrs.bg = term->colors.table[param - 40];
break; break;
@ -218,7 +218,7 @@ csi_sgr(struct terminal *term)
term->vt.params.v[i + 1].value == 5) term->vt.params.v[i + 1].value == 5)
{ {
uint8_t idx = term->vt.params.v[i + 2].value; uint8_t idx = term->vt.params.v[i + 2].value;
term->vt.attrs.have_bg = 1; term->vt.attrs.bg_src = COLOR_BASE256;
term->vt.attrs.bg = term->colors.table[idx]; term->vt.attrs.bg = term->colors.table[idx];
i += 2; i += 2;
@ -231,7 +231,7 @@ csi_sgr(struct terminal *term)
uint8_t r = term->vt.params.v[i + 2].value; uint8_t r = term->vt.params.v[i + 2].value;
uint8_t g = term->vt.params.v[i + 3].value; uint8_t g = term->vt.params.v[i + 3].value;
uint8_t b = term->vt.params.v[i + 4].value; uint8_t b = term->vt.params.v[i + 4].value;
term->vt.attrs.have_bg = 1; term->vt.attrs.bg_src = COLOR_RGB;
term->vt.attrs.bg = r << 16 | g << 8 | b; term->vt.attrs.bg = r << 16 | g << 8 | b;
i += 4; i += 4;
} }
@ -243,7 +243,7 @@ csi_sgr(struct terminal *term)
const struct vt_param *param = &term->vt.params.v[i]; const struct vt_param *param = &term->vt.params.v[i];
uint8_t idx = param->sub.value[1]; uint8_t idx = param->sub.value[1];
term->vt.attrs.have_bg = 1; term->vt.attrs.bg_src = COLOR_BASE256;
term->vt.attrs.bg = term->colors.table[idx]; term->vt.attrs.bg = term->colors.table[idx];
} }
@ -273,7 +273,7 @@ csi_sgr(struct terminal *term)
uint8_t g = param->sub.value[g_idx]; uint8_t g = param->sub.value[g_idx];
uint8_t b = param->sub.value[b_idx]; uint8_t b = param->sub.value[b_idx];
term->vt.attrs.have_bg = 1; term->vt.attrs.bg_src = COLOR_RGB;
term->vt.attrs.bg = r << 16 | g << 8 | b; term->vt.attrs.bg = r << 16 | g << 8 | b;
} }
@ -287,7 +287,7 @@ csi_sgr(struct terminal *term)
break; break;
} }
case 49: case 49:
term->vt.attrs.have_bg = 0; term->vt.attrs.bg_src = COLOR_DEFAULT;
break; break;
/* Bright foreground colors */ /* Bright foreground colors */
@ -299,7 +299,7 @@ csi_sgr(struct terminal *term)
case 95: case 95:
case 96: case 96:
case 97: case 97:
term->vt.attrs.have_fg = 1; term->vt.attrs.fg_src = COLOR_BASE16;
term->vt.attrs.fg = term->colors.table[param - 90 + 8]; term->vt.attrs.fg = term->colors.table[param - 90 + 8];
break; break;
@ -312,7 +312,7 @@ csi_sgr(struct terminal *term)
case 105: case 105:
case 106: case 106:
case 107: case 107:
term->vt.attrs.have_bg = 1; term->vt.attrs.bg_src = COLOR_BASE16;
term->vt.attrs.bg = term->colors.table[param - 100 + 8]; term->vt.attrs.bg = term->colors.table[param - 100 + 8];
break; break;

6
osc.c
View file

@ -503,7 +503,7 @@ osc_notify(struct terminal *term, char *string)
* (https://pub.phyks.me/scripts/urxvt/notify) is very simple: * (https://pub.phyks.me/scripts/urxvt/notify) is very simple:
* *
* #!/usr/bin/perl * #!/usr/bin/perl
* *
* sub on_osc_seq_perl { * sub on_osc_seq_perl {
* my ($term, $osc, $resp) = @_; * my ($term, $osc, $resp) = @_;
* if ($osc =~ /^notify;(\S+);(.*)$/) { * if ($osc =~ /^notify;(\S+);(.*)$/) {
@ -560,7 +560,7 @@ update_color_in_grids(struct terminal *term, uint32_t old_color,
for (size_t c = 0; c < term->grid->num_cols; c++) { for (size_t c = 0; c < term->grid->num_cols; c++) {
struct cell *cell = &row->cells[c]; struct cell *cell = &row->cells[c];
if (cell->attrs.have_fg && if (cell->attrs.fg_src != COLOR_DEFAULT &&
cell->attrs.fg == old_color) cell->attrs.fg == old_color)
{ {
cell->attrs.fg = new_color; cell->attrs.fg = new_color;
@ -568,7 +568,7 @@ update_color_in_grids(struct terminal *term, uint32_t old_color,
row->dirty = true; row->dirty = true;
} }
if ( cell->attrs.have_bg && if (cell->attrs.bg_src != COLOR_DEFAULT &&
cell->attrs.bg == old_color) cell->attrs.bg == old_color)
{ {
cell->attrs.bg = new_color; cell->attrs.bg = new_color;

View file

@ -494,14 +494,14 @@ render_cell(struct terminal *term, pixman_image_t *pix,
_bg = term->colors.selection_bg; _bg = term->colors.selection_bg;
} else { } else {
/* Use cell specific color, if set, otherwise the default colors (possible reversed) */ /* Use cell specific color, if set, otherwise the default colors (possible reversed) */
_fg = cell->attrs.have_fg ? cell->attrs.fg : term->reverse ? term->colors.bg : term->colors.fg; _fg = cell->attrs.fg_src != COLOR_DEFAULT ? cell->attrs.fg : term->reverse ? term->colors.bg : term->colors.fg;
_bg = cell->attrs.have_bg ? cell->attrs.bg : term->reverse ? term->colors.fg : term->colors.bg; _bg = cell->attrs.bg_src != COLOR_DEFAULT ? cell->attrs.bg : term->reverse ? term->colors.fg : term->colors.bg;
if (cell->attrs.reverse ^ is_selected) { if (cell->attrs.reverse ^ is_selected) {
uint32_t swap = _fg; uint32_t swap = _fg;
_fg = _bg; _fg = _bg;
_bg = swap; _bg = swap;
} else if (!cell->attrs.have_bg) } else if (cell->attrs.bg_src == COLOR_DEFAULT)
alpha = term->colors.alpha; alpha = term->colors.alpha;
} }

View file

@ -70,7 +70,7 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
term->sixel.default_bg = term->sixel.transparent_bg term->sixel.default_bg = term->sixel.transparent_bg
? 0x00000000u ? 0x00000000u
: 0xffu << 24 | (term->vt.attrs.have_bg : 0xffu << 24 | (term->vt.attrs.bg_src != COLOR_DEFAULT
? term->vt.attrs.bg ? term->vt.attrs.bg
: term->colors.bg); : term->colors.bg);

View file

@ -1770,11 +1770,13 @@ erase_cell_range(struct terminal *term, struct row *row, int start, int end)
row->dirty = true; row->dirty = true;
if (unlikely(term->vt.attrs.have_bg)) { const enum color_source bg_src = term->vt.attrs.bg_src;
if (unlikely(bg_src != COLOR_DEFAULT)) {
for (int col = start; col <= end; col++) { for (int col = start; col <= end; col++) {
struct cell *c = &row->cells[col]; struct cell *c = &row->cells[col];
c->wc = 0; c->wc = 0;
c->attrs = (struct attributes){.have_bg = 1, .bg = term->vt.attrs.bg}; c->attrs = (struct attributes){.bg_src = bg_src, .bg = term->vt.attrs.bg};
} }
} else } else
memset(&row->cells[start], 0, (end - start + 1) * sizeof(row->cells[0])); memset(&row->cells[start], 0, (end - start + 1) * sizeof(row->cells[0]));

View file

@ -24,6 +24,13 @@
#include "shm.h" #include "shm.h"
#include "wayland.h" #include "wayland.h"
enum color_source {
COLOR_DEFAULT,
COLOR_BASE16,
COLOR_BASE256,
COLOR_RGB,
};
/* /*
* Note: we want the cells to be as small as possible. Larger cells * Note: we want the cells to be as small as possible. Larger cells
* means fewer scrollback lines (or performance drops due to cache * means fewer scrollback lines (or performance drops due to cache
@ -43,12 +50,11 @@ struct attributes {
uint32_t fg:24; uint32_t fg:24;
bool clean:1; bool clean:1;
enum color_source fg_src:2;
enum color_source bg_src:2;
bool confined:1; bool confined:1;
bool have_fg:1;
bool have_bg:1;
bool selected:1; bool selected:1;
bool url:1; bool url:1;
uint32_t reserved:2;
uint32_t bg:24; uint32_t bg:24;
}; };
static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large"); static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large");