mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-13 04:03:16 +02:00
Implement DECCARA
Ability to set text attributes/colors in arbitrary screen regions, instead of working via the cursor. Note that kitty extends the original DECCARA spec from the VT-510 to allow setting all supported SGR attributes.
This commit is contained in:
137
kitty/cursor.c
137
kitty/cursor.c
@@ -45,33 +45,38 @@ cursor_reset_display_attrs(Cursor *self) {
|
||||
self->decoration = 0; self->bold = false; self->italic = false; self->reverse = false; self->strikethrough = false;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
parse_color(unsigned int *params, unsigned int *i, unsigned int count, uint32_t *result) {
|
||||
unsigned int attr;
|
||||
uint8_t r, g, b;
|
||||
if (*i < count) {
|
||||
attr = params[(*i)++];
|
||||
switch(attr) {
|
||||
case 5:
|
||||
if (*i < count) *result = (params[(*i)++] & 0xFF) << 8 | 1;
|
||||
break;
|
||||
case 2: \
|
||||
if (*i < count - 2) {
|
||||
/* Ignore the first parameter in a four parameter RGB */
|
||||
/* sequence (unused color space id), see https://github.com/kovidgoyal/kitty/issues/227 */
|
||||
if (*i < count - 3) (*i)++;
|
||||
r = params[(*i)++] & 0xFF;
|
||||
g = params[(*i)++] & 0xFF;
|
||||
b = params[(*i)++] & 0xFF;
|
||||
*result = r << 24 | g << 16 | b << 8 | 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cursor_from_sgr(Cursor *self, unsigned int *params, unsigned int count) {
|
||||
#define SET_COLOR(which) \
|
||||
if (i < count) { \
|
||||
attr = params[i++];\
|
||||
switch(attr) { \
|
||||
case 5: \
|
||||
if (i < count) \
|
||||
self->which = (params[i++] & 0xFF) << 8 | 1; \
|
||||
break; \
|
||||
case 2: \
|
||||
if (i < count - 2) { \
|
||||
/* Ignore the first parameter in a four parameter RGB */ \
|
||||
/* sequence (unused color space id), see https://github.com/kovidgoyal/kitty/issues/227 */ \
|
||||
if (i < count - 3) i++; \
|
||||
r = params[i++] & 0xFF; \
|
||||
g = params[i++] & 0xFF; \
|
||||
b = params[i++] & 0xFF; \
|
||||
self->which = r << 24 | g << 16 | b << 8 | 2; \
|
||||
}\
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SET_COLOR(which) { parse_color(params, &i, count, &self->which); } break;
|
||||
START_ALLOW_CASE_RANGE
|
||||
unsigned int i = 0, attr;
|
||||
uint8_t r, g, b;
|
||||
if (!count) { params[0] = 0; count = 1; }
|
||||
while (i < count) {
|
||||
attr = params[i++];
|
||||
@@ -102,7 +107,6 @@ cursor_from_sgr(Cursor *self, unsigned int *params, unsigned int count) {
|
||||
self->reverse = false; break;
|
||||
case 29:
|
||||
self->strikethrough = false; break;
|
||||
START_ALLOW_CASE_RANGE
|
||||
case 30 ... 37:
|
||||
self->fg = ((attr - 30) << 8) | 1; break;
|
||||
case 38:
|
||||
@@ -119,13 +123,86 @@ START_ALLOW_CASE_RANGE
|
||||
self->fg = ((attr - 90 + 8) << 8) | 1; break;
|
||||
case 100 ... 107:
|
||||
self->bg = ((attr - 100 + 8) << 8) | 1; break;
|
||||
END_ALLOW_CASE_RANGE
|
||||
case DECORATION_FG_CODE:
|
||||
SET_COLOR(decoration_fg);
|
||||
SET_COLOR(decoration_fg);
|
||||
case DECORATION_FG_CODE + 1:
|
||||
self->decoration_fg = 0; break;
|
||||
}
|
||||
}
|
||||
#undef SET_COLOR
|
||||
END_ALLOW_CASE_RANGE
|
||||
}
|
||||
|
||||
void
|
||||
apply_sgr_to_cells(Cell *first_cell, unsigned int cell_count, unsigned int *params, unsigned int count) {
|
||||
#define RANGE for(unsigned c = 0; c < cell_count; c++, cell++)
|
||||
#define SET(shift) RANGE { cell->attrs |= (1 << shift); } break;
|
||||
#define RESET(shift) RANGE { cell->attrs &= ~(1 << shift); } break;
|
||||
#define SETM(val, mask, shift) { RANGE { cell->attrs &= ~(mask << shift); cell->attrs |= ((val) << shift); } break; }
|
||||
#define SET_COLOR(which) { color_type color = 0; parse_color(params, &i, count, &color); if (color) { RANGE { cell->which = color; }} } break;
|
||||
#define SIMPLE(which, val) RANGE { cell->which = (val); } break;
|
||||
|
||||
unsigned int i = 0, attr;
|
||||
if (!count) { params[0] = 0; count = 1; }
|
||||
while (i < count) {
|
||||
Cell *cell = first_cell;
|
||||
attr = params[i++];
|
||||
switch(attr) {
|
||||
case 0:
|
||||
RANGE { cell->attrs &= WIDTH_MASK; cell->fg = 0; cell->bg = 0; cell->decoration_fg = 0; }
|
||||
break;
|
||||
case 1:
|
||||
SET(BOLD_SHIFT);
|
||||
case 3:
|
||||
SET(ITALIC_SHIFT);
|
||||
case 4:
|
||||
if (i < count) { uint8_t val = MIN(3, params[i]); i++; SETM(val, DECORATION_MASK, DECORATION_SHIFT); }
|
||||
else { SETM(1, DECORATION_MASK, DECORATION_SHIFT); }
|
||||
case 7:
|
||||
SET(REVERSE_SHIFT);
|
||||
case 9:
|
||||
SET(STRIKE_SHIFT);
|
||||
case 21:
|
||||
SETM(2, DECORATION_MASK, DECORATION_SHIFT);
|
||||
case 22:
|
||||
RESET(BOLD_SHIFT);
|
||||
case 23:
|
||||
RESET(ITALIC_SHIFT);
|
||||
case 24:
|
||||
SETM(0, DECORATION_MASK, DECORATION_SHIFT);
|
||||
case 27:
|
||||
RESET(REVERSE_SHIFT);
|
||||
case 29:
|
||||
RESET(STRIKE_SHIFT);
|
||||
START_ALLOW_CASE_RANGE
|
||||
case 30 ... 37:
|
||||
SIMPLE(fg, ((attr - 30) << 8) | 1);
|
||||
case 38:
|
||||
SET_COLOR(fg);
|
||||
case 39:
|
||||
SIMPLE(fg, 0);
|
||||
case 40 ... 47:
|
||||
SIMPLE(bg, ((attr - 40) << 8) | 1);
|
||||
case 48:
|
||||
SET_COLOR(bg);
|
||||
case 49:
|
||||
SIMPLE(bg, 0);
|
||||
case 90 ... 97:
|
||||
SIMPLE(fg, ((attr - 90 + 8) << 8) | 1);
|
||||
case 100 ... 107:
|
||||
SIMPLE(bg, ((attr - 100 + 8) << 8) | 1);
|
||||
END_ALLOW_CASE_RANGE
|
||||
case DECORATION_FG_CODE:
|
||||
SET_COLOR(decoration_fg);
|
||||
case DECORATION_FG_CODE + 1:
|
||||
SIMPLE(decoration_fg, 0);
|
||||
}
|
||||
}
|
||||
#undef RESET
|
||||
#undef SET_COLOR
|
||||
#undef SET
|
||||
#undef SETM
|
||||
#undef RANGE
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -211,9 +288,9 @@ static PyMemberDef members[] = {
|
||||
{"y", T_UINT, offsetof(Cursor, y), 0, "y"},
|
||||
{"shape", T_INT, offsetof(Cursor, shape), 0, "shape"},
|
||||
{"decoration", T_UBYTE, offsetof(Cursor, decoration), 0, "decoration"},
|
||||
{"fg", T_ULONG, offsetof(Cursor, fg), 0, "fg"},
|
||||
{"bg", T_ULONG, offsetof(Cursor, bg), 0, "bg"},
|
||||
{"decoration_fg", T_ULONG, offsetof(Cursor, decoration_fg), 0, "decoration_fg"},
|
||||
{"fg", T_UINT, offsetof(Cursor, fg), 0, "fg"},
|
||||
{"bg", T_UINT, offsetof(Cursor, bg), 0, "bg"},
|
||||
{"decoration_fg", T_UINT, offsetof(Cursor, decoration_fg), 0, "decoration_fg"},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user