Implement SGR dim
kitty now supports the SGR DIM escape code, which makes text fade into the background. It works by alpha blending the text color into the background color. Fixes #446
This commit is contained in:
@@ -19,7 +19,7 @@ in float bg_alpha;
|
|||||||
|
|
||||||
#ifdef NEEDS_FOREGROUND
|
#ifdef NEEDS_FOREGROUND
|
||||||
uniform sampler2DArray sprites;
|
uniform sampler2DArray sprites;
|
||||||
uniform float inactive_text_alpha;
|
in float effective_text_alpha;
|
||||||
in vec3 sprite_pos;
|
in vec3 sprite_pos;
|
||||||
in vec3 underline_pos;
|
in vec3 underline_pos;
|
||||||
in vec3 strike_pos;
|
in vec3 strike_pos;
|
||||||
@@ -61,7 +61,7 @@ vec4 calculate_foreground() {
|
|||||||
// Since strike and text are the same color, we simply add the alpha values
|
// Since strike and text are the same color, we simply add the alpha values
|
||||||
float combined_alpha = min(text_alpha + strike_alpha, 1.0f);
|
float combined_alpha = min(text_alpha + strike_alpha, 1.0f);
|
||||||
// Underline color might be different, so alpha blend
|
// Underline color might be different, so alpha blend
|
||||||
return alpha_blend(decoration_fg, underline_alpha * inactive_text_alpha, fg, combined_alpha * inactive_text_alpha);
|
return alpha_blend(decoration_fg, underline_alpha * effective_text_alpha, fg, combined_alpha * effective_text_alpha);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#version GLSL_VERSION
|
#version GLSL_VERSION
|
||||||
#define WHICH_PROGRAM
|
#define WHICH_PROGRAM
|
||||||
#define NOT_TRANSPARENT
|
#define NOT_TRANSPARENT
|
||||||
|
#define SHIFTS
|
||||||
|
|
||||||
// Inputs {{{
|
// Inputs {{{
|
||||||
layout(std140) uniform CellRenderData {
|
layout(std140) uniform CellRenderData {
|
||||||
@@ -45,12 +46,14 @@ out float bg_alpha;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NEEDS_FOREGROUND
|
#ifdef NEEDS_FOREGROUND
|
||||||
|
uniform float inactive_text_alpha;
|
||||||
out vec3 sprite_pos;
|
out vec3 sprite_pos;
|
||||||
out vec3 underline_pos;
|
out vec3 underline_pos;
|
||||||
out vec3 strike_pos;
|
out vec3 strike_pos;
|
||||||
out vec3 foreground;
|
out vec3 foreground;
|
||||||
out vec3 decoration_fg;
|
out vec3 decoration_fg;
|
||||||
out float colored_sprite;
|
out float colored_sprite;
|
||||||
|
out float effective_text_alpha;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -63,9 +66,6 @@ const uint ONE = uint(1);
|
|||||||
const uint TWO = uint(2);
|
const uint TWO = uint(2);
|
||||||
const uint THREE = uint(3);
|
const uint THREE = uint(3);
|
||||||
const uint FOUR = uint(4);
|
const uint FOUR = uint(4);
|
||||||
const uint DECORATION_MASK = uint(3);
|
|
||||||
const uint STRIKE_MASK = uint(1);
|
|
||||||
const uint REVERSE_MASK = uint(1);
|
|
||||||
|
|
||||||
vec3 color_to_vec(uint c) {
|
vec3 color_to_vec(uint c) {
|
||||||
uint r, g, b;
|
uint r, g, b;
|
||||||
@@ -134,7 +134,7 @@ void main() {
|
|||||||
// set cell color indices {{{
|
// set cell color indices {{{
|
||||||
uvec2 default_colors = uvec2(default_fg, default_bg);
|
uvec2 default_colors = uvec2(default_fg, default_bg);
|
||||||
uint text_attrs = sprite_coords[3];
|
uint text_attrs = sprite_coords[3];
|
||||||
uint is_inverted = ((text_attrs >> 6) & REVERSE_MASK) + inverted;
|
uint is_inverted = ((text_attrs >> REVERSE_SHIFT) & ONE) + inverted;
|
||||||
int fg_index = fg_index_map[is_inverted];
|
int fg_index = fg_index_map[is_inverted];
|
||||||
int bg_index = 1 - fg_index;
|
int bg_index = 1 - fg_index;
|
||||||
float cursor = is_cursor(c, r);
|
float cursor = is_cursor(c, r);
|
||||||
@@ -151,13 +151,15 @@ void main() {
|
|||||||
// Foreground
|
// Foreground
|
||||||
uint resolved_fg = resolve_color(colors[fg_index], default_colors[fg_index]);
|
uint resolved_fg = resolve_color(colors[fg_index], default_colors[fg_index]);
|
||||||
foreground = color_to_vec(resolved_fg);
|
foreground = color_to_vec(resolved_fg);
|
||||||
|
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE);
|
||||||
|
effective_text_alpha = inactive_text_alpha * mix(1.0, 0.75, has_dim);
|
||||||
// Selection
|
// Selection
|
||||||
foreground = choose_color(float(is_selected & ONE), color_to_vec(highlight_fg), foreground);
|
foreground = choose_color(float(is_selected & ONE), color_to_vec(highlight_fg), foreground);
|
||||||
// Underline and strike through (rendered via sprites)
|
// Underline and strike through (rendered via sprites)
|
||||||
float in_url = float((is_selected & TWO) >> 1);
|
float in_url = float((is_selected & TWO) >> 1);
|
||||||
decoration_fg = choose_color(in_url, color_to_vec(url_color), to_color(colors[2], resolved_fg));
|
decoration_fg = choose_color(in_url, color_to_vec(url_color), to_color(colors[2], resolved_fg));
|
||||||
underline_pos = choose_color(in_url, to_sprite_pos(pos, url_style, ZERO, ZERO), to_sprite_pos(pos, (text_attrs >> 2) & DECORATION_MASK, ZERO, ZERO));
|
underline_pos = choose_color(in_url, to_sprite_pos(pos, url_style, ZERO, ZERO), to_sprite_pos(pos, (text_attrs >> DECORATION_SHIFT) & THREE, ZERO, ZERO));
|
||||||
strike_pos = to_sprite_pos(pos, ((text_attrs >> 7) & STRIKE_MASK) * FOUR, ZERO, ZERO);
|
strike_pos = to_sprite_pos(pos, ((text_attrs >> STRIKE_SHIFT) & ONE) * FOUR, ZERO, ZERO);
|
||||||
|
|
||||||
// Cursor
|
// Cursor
|
||||||
foreground = choose_color(cursor, bg, foreground);
|
foreground = choose_color(cursor, bg, foreground);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ dealloc(Cursor* self) {
|
|||||||
|
|
||||||
#define EQ(x) (a->x == b->x)
|
#define EQ(x) (a->x == b->x)
|
||||||
static int __eq__(Cursor *a, Cursor *b) {
|
static int __eq__(Cursor *a, Cursor *b) {
|
||||||
return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(blink);
|
return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(dim) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(blink);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "BEAM", "UNDERLINE" };
|
static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "BEAM", "UNDERLINE" };
|
||||||
@@ -33,16 +33,16 @@ static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
repr(Cursor *self) {
|
repr(Cursor *self) {
|
||||||
return PyUnicode_FromFormat(
|
return PyUnicode_FromFormat(
|
||||||
"Cursor(x=%u, y=%u, shape=%s, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, decoration=%d, decoration_fg=#%08x)",
|
"Cursor(x=%u, y=%u, shape=%s, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, dim=%R, decoration=%d, decoration_fg=#%08x)",
|
||||||
self->x, self->y, (self->shape < NUM_OF_CURSOR_SHAPES ? cursor_names[self->shape] : "INVALID"),
|
self->x, self->y, (self->shape < NUM_OF_CURSOR_SHAPES ? cursor_names[self->shape] : "INVALID"),
|
||||||
BOOL(self->blink), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), self->decoration, self->decoration_fg
|
BOOL(self->blink), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), BOOL(self->dim), self->decoration, self->decoration_fg
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursor_reset_display_attrs(Cursor *self) {
|
cursor_reset_display_attrs(Cursor *self) {
|
||||||
self->bg = 0; self->fg = 0; self->decoration_fg = 0;
|
self->bg = 0; self->fg = 0; self->decoration_fg = 0;
|
||||||
self->decoration = 0; self->bold = false; self->italic = false; self->reverse = false; self->strikethrough = false;
|
self->decoration = 0; self->bold = false; self->italic = false; self->reverse = false; self->strikethrough = false; self->dim = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -85,6 +85,8 @@ START_ALLOW_CASE_RANGE
|
|||||||
cursor_reset_display_attrs(self); break;
|
cursor_reset_display_attrs(self); break;
|
||||||
case 1:
|
case 1:
|
||||||
self->bold = true; break;
|
self->bold = true; break;
|
||||||
|
case 2:
|
||||||
|
self->dim = true; break;
|
||||||
case 3:
|
case 3:
|
||||||
self->italic = true; break;
|
self->italic = true; break;
|
||||||
case 4:
|
case 4:
|
||||||
@@ -98,7 +100,7 @@ START_ALLOW_CASE_RANGE
|
|||||||
case 21:
|
case 21:
|
||||||
self->decoration = 2; break;
|
self->decoration = 2; break;
|
||||||
case 22:
|
case 22:
|
||||||
self->bold = false; break;
|
self->bold = false; self->dim = false; break;
|
||||||
case 23:
|
case 23:
|
||||||
self->italic = false; break;
|
self->italic = false; break;
|
||||||
case 24:
|
case 24:
|
||||||
@@ -138,6 +140,7 @@ apply_sgr_to_cells(Cell *first_cell, unsigned int cell_count, unsigned int *para
|
|||||||
#define RANGE for(unsigned c = 0; c < cell_count; c++, cell++)
|
#define RANGE for(unsigned c = 0; c < cell_count; c++, cell++)
|
||||||
#define SET(shift) RANGE { cell->attrs |= (1 << shift); } break;
|
#define SET(shift) RANGE { cell->attrs |= (1 << shift); } break;
|
||||||
#define RESET(shift) RANGE { cell->attrs &= ~(1 << shift); } break;
|
#define RESET(shift) RANGE { cell->attrs &= ~(1 << shift); } break;
|
||||||
|
#define RESET2(shift1, shift2) RANGE { cell->attrs &= ~((1 << shift1) | (1 << shift2)); } break;
|
||||||
#define SETM(val, mask, shift) { RANGE { cell->attrs &= ~(mask << shift); cell->attrs |= ((val) << 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 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;
|
#define SIMPLE(which, val) RANGE { cell->which = (val); } break;
|
||||||
@@ -153,6 +156,8 @@ apply_sgr_to_cells(Cell *first_cell, unsigned int cell_count, unsigned int *para
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
SET(BOLD_SHIFT);
|
SET(BOLD_SHIFT);
|
||||||
|
case 2:
|
||||||
|
SET(DIM_SHIFT);
|
||||||
case 3:
|
case 3:
|
||||||
SET(ITALIC_SHIFT);
|
SET(ITALIC_SHIFT);
|
||||||
case 4:
|
case 4:
|
||||||
@@ -165,7 +170,7 @@ apply_sgr_to_cells(Cell *first_cell, unsigned int cell_count, unsigned int *para
|
|||||||
case 21:
|
case 21:
|
||||||
SETM(2, DECORATION_MASK, DECORATION_SHIFT);
|
SETM(2, DECORATION_MASK, DECORATION_SHIFT);
|
||||||
case 22:
|
case 22:
|
||||||
RESET(BOLD_SHIFT);
|
RESET2(DIM_SHIFT, BOLD_SHIFT);
|
||||||
case 23:
|
case 23:
|
||||||
RESET(ITALIC_SHIFT);
|
RESET(ITALIC_SHIFT);
|
||||||
case 24:
|
case 24:
|
||||||
@@ -199,6 +204,7 @@ END_ALLOW_CASE_RANGE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef RESET
|
#undef RESET
|
||||||
|
#undef RESET2
|
||||||
#undef SET_COLOR
|
#undef SET_COLOR
|
||||||
#undef SET
|
#undef SET
|
||||||
#undef SETM
|
#undef SETM
|
||||||
@@ -237,7 +243,11 @@ cursor_as_sgr(Cursor *self, Cursor *prev) {
|
|||||||
#define SZ sizeof(buf) - (p - buf) - 2
|
#define SZ sizeof(buf) - (p - buf) - 2
|
||||||
#define P(fmt, ...) { p += snprintf(p, SZ, fmt ";", __VA_ARGS__); }
|
#define P(fmt, ...) { p += snprintf(p, SZ, fmt ";", __VA_ARGS__); }
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
if (self->bold != prev->bold) P("%d", self->bold ? 1 : 22);
|
bool intensity_differs = self->bold != prev->bold || self->dim != prev->dim;
|
||||||
|
if (intensity_differs) {
|
||||||
|
if (!self->bold || !self->dim) { P("%d", 22); }
|
||||||
|
else P("%d;%d", 1, 2);
|
||||||
|
}
|
||||||
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
|
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
|
||||||
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);
|
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);
|
||||||
if (self->strikethrough != prev->strikethrough) P("%d", self->strikethrough ? 9 : 29);
|
if (self->strikethrough != prev->strikethrough) P("%d", self->strikethrough ? 9 : 29);
|
||||||
@@ -268,7 +278,7 @@ void cursor_reset(Cursor *self) {
|
|||||||
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
||||||
#define CCY(x) dest->x = src->x;
|
#define CCY(x) dest->x = src->x;
|
||||||
CCY(x); CCY(y); CCY(shape); CCY(blink);
|
CCY(x); CCY(y); CCY(shape); CCY(blink);
|
||||||
CCY(bold); CCY(italic); CCY(strikethrough); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg);
|
CCY(bold); CCY(italic); CCY(strikethrough); CCY(dim); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
@@ -281,6 +291,7 @@ BOOL_GETSET(Cursor, bold)
|
|||||||
BOOL_GETSET(Cursor, italic)
|
BOOL_GETSET(Cursor, italic)
|
||||||
BOOL_GETSET(Cursor, reverse)
|
BOOL_GETSET(Cursor, reverse)
|
||||||
BOOL_GETSET(Cursor, strikethrough)
|
BOOL_GETSET(Cursor, strikethrough)
|
||||||
|
BOOL_GETSET(Cursor, dim)
|
||||||
BOOL_GETSET(Cursor, blink)
|
BOOL_GETSET(Cursor, blink)
|
||||||
|
|
||||||
static PyMemberDef members[] = {
|
static PyMemberDef members[] = {
|
||||||
@@ -299,6 +310,7 @@ static PyGetSetDef getseters[] = {
|
|||||||
GETSET(italic)
|
GETSET(italic)
|
||||||
GETSET(reverse)
|
GETSET(reverse)
|
||||||
GETSET(strikethrough)
|
GETSET(strikethrough)
|
||||||
|
GETSET(dim)
|
||||||
GETSET(blink)
|
GETSET(blink)
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ PyInit_fast_data_types(void) {
|
|||||||
PyModule_AddIntConstant(m, "ITALIC", ITALIC_SHIFT);
|
PyModule_AddIntConstant(m, "ITALIC", ITALIC_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
||||||
|
PyModule_AddIntConstant(m, "DIM", DIM_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
|
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
|
||||||
PyModule_AddStringMacro(m, ERROR_PREFIX);
|
PyModule_AddStringMacro(m, ERROR_PREFIX);
|
||||||
#ifdef KITTY_VCS_REV
|
#ifdef KITTY_VCS_REV
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
|||||||
#define BI_VAL(attrs) ((attrs >> 4) & 3)
|
#define BI_VAL(attrs) ((attrs >> 4) & 3)
|
||||||
#define REVERSE_SHIFT 6
|
#define REVERSE_SHIFT 6
|
||||||
#define STRIKE_SHIFT 7
|
#define STRIKE_SHIFT 7
|
||||||
|
#define DIM_SHIFT 8
|
||||||
#define COL_MASK 0xFFFFFFFF
|
#define COL_MASK 0xFFFFFFFF
|
||||||
#define UTF8_ACCEPT 0
|
#define UTF8_ACCEPT 0
|
||||||
#define UTF8_REJECT 1
|
#define UTF8_REJECT 1
|
||||||
@@ -71,11 +72,12 @@ typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
|||||||
|
|
||||||
#define CURSOR_TO_ATTRS(c, w) \
|
#define CURSOR_TO_ATTRS(c, w) \
|
||||||
((w) | (((c->decoration & 3) << DECORATION_SHIFT) | ((c->bold & 1) << BOLD_SHIFT) | \
|
((w) | (((c->decoration & 3) << DECORATION_SHIFT) | ((c->bold & 1) << BOLD_SHIFT) | \
|
||||||
((c->italic & 1) << ITALIC_SHIFT) | ((c->reverse & 1) << REVERSE_SHIFT) | ((c->strikethrough & 1) << STRIKE_SHIFT)))
|
((c->italic & 1) << ITALIC_SHIFT) | ((c->reverse & 1) << REVERSE_SHIFT) | \
|
||||||
|
((c->strikethrough & 1) << STRIKE_SHIFT) | ((c->dim & 1) << DIM_SHIFT)))
|
||||||
|
|
||||||
#define ATTRS_TO_CURSOR(a, c) \
|
#define ATTRS_TO_CURSOR(a, c) \
|
||||||
(c)->decoration = (a >> DECORATION_SHIFT) & 3; (c)->bold = (a >> BOLD_SHIFT) & 1; (c)->italic = (a >> ITALIC_SHIFT) & 1; \
|
(c)->decoration = (a >> DECORATION_SHIFT) & 3; (c)->bold = (a >> BOLD_SHIFT) & 1; (c)->italic = (a >> ITALIC_SHIFT) & 1; \
|
||||||
(c)->reverse = (a >> REVERSE_SHIFT) & 1; (c)->strikethrough = (a >> STRIKE_SHIFT) & 1;
|
(c)->reverse = (a >> REVERSE_SHIFT) & 1; (c)->strikethrough = (a >> STRIKE_SHIFT) & 1; (c)->dim = (a >> DIM_SHIFT) & 1;
|
||||||
|
|
||||||
#define COPY_CELL(src, s, dest, d) \
|
#define COPY_CELL(src, s, dest, d) \
|
||||||
(dest)->cells[d] = (src)->cells[s];
|
(dest)->cells[d] = (src)->cells[s];
|
||||||
@@ -178,7 +180,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
bool bold, italic, reverse, strikethrough, blink;
|
bool bold, italic, reverse, strikethrough, blink, dim;
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
uint8_t decoration;
|
uint8_t decoration;
|
||||||
CursorShape shape;
|
CursorShape shape;
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ set_attribute(LineBuf *self, PyObject *args) {
|
|||||||
#define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line."
|
#define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line."
|
||||||
unsigned int shift, val;
|
unsigned int shift, val;
|
||||||
if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL;
|
if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL;
|
||||||
if (shift < DECORATION_SHIFT || shift > STRIKE_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; }
|
if (shift < DECORATION_SHIFT || shift > DIM_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; }
|
||||||
linebuf_set_attribute(self, shift, val);
|
linebuf_set_attribute(self, shift, val);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ set_attribute(Line *self, PyObject *args) {
|
|||||||
#define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line."
|
#define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line."
|
||||||
unsigned int shift, val;
|
unsigned int shift, val;
|
||||||
if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL;
|
if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL;
|
||||||
if (shift < DECORATION_SHIFT || shift > STRIKE_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; }
|
if (shift < DECORATION_SHIFT || shift > DIM_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; }
|
||||||
set_attribute_on_line(self->cells, shift, val, self->xnum);
|
set_attribute_on_line(self->cells, shift, val, self->xnum);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,10 @@ from .constants import (
|
|||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
||||||
CELL_SPECIAL_PROGRAM, CSI, CURSOR_PROGRAM, DCS, GRAPHICS_PREMULT_PROGRAM,
|
CELL_SPECIAL_PROGRAM, CSI, CURSOR_PROGRAM, DCS, DECORATION, DIM,
|
||||||
GRAPHICS_PROGRAM, OSC, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, OSC, REVERSE, SCROLL_FULL,
|
||||||
add_window, compile_program, get_clipboard_string, glfw_post_empty_event,
|
SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, Screen, add_window,
|
||||||
|
compile_program, get_clipboard_string, glfw_post_empty_event,
|
||||||
init_cell_program, init_cursor_program, set_clipboard_string,
|
init_cell_program, init_cursor_program, set_clipboard_string,
|
||||||
set_titlebar_color, set_window_render_data, update_window_title,
|
set_titlebar_color, set_window_render_data, update_window_title,
|
||||||
update_window_visibility, viewport_for_window
|
update_window_visibility, viewport_for_window
|
||||||
@@ -64,6 +65,10 @@ def load_shader_programs(semi_transparent=0):
|
|||||||
'FOREGROUND': CELL_FG_PROGRAM,
|
'FOREGROUND': CELL_FG_PROGRAM,
|
||||||
}.items():
|
}.items():
|
||||||
vv, ff = v.replace('WHICH_PROGRAM', which), f.replace('WHICH_PROGRAM', which)
|
vv, ff = v.replace('WHICH_PROGRAM', which), f.replace('WHICH_PROGRAM', which)
|
||||||
|
shifts = '\n'.join('#define {} {}'.format(name, val) for name, val in (
|
||||||
|
('DECORATION_SHIFT', DECORATION), ('REVERSE_SHIFT', REVERSE), ('STRIKE_SHIFT', STRIKETHROUGH), ('DIM_SHIFT', DIM),
|
||||||
|
))
|
||||||
|
vv = vv.replace('#define SHIFTS', shifts)
|
||||||
if semi_transparent:
|
if semi_transparent:
|
||||||
vv = vv.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
vv = vv.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
||||||
ff = ff.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
ff = ff.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ def filled_line_buf(ynum=5, xnum=5, cursor=Cursor()):
|
|||||||
|
|
||||||
def filled_cursor():
|
def filled_cursor():
|
||||||
ans = Cursor()
|
ans = Cursor()
|
||||||
ans.bold = ans.italic = ans.reverse = ans.strikethrough = True
|
ans.bold = ans.italic = ans.reverse = ans.strikethrough = ans.dim = True
|
||||||
ans.fg = 0x101
|
ans.fg = 0x101
|
||||||
ans.bg = 0x201
|
ans.bg = 0x201
|
||||||
ans.decoration_fg = 0x301
|
ans.decoration_fg = 0x301
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class TestDataTypes(BaseTest):
|
|||||||
self.assertEqual(str(l0), 'a' + t[1:])
|
self.assertEqual(str(l0), 'a' + t[1:])
|
||||||
|
|
||||||
c = C(3, 5)
|
c = C(3, 5)
|
||||||
c.bold = c.italic = c.reverse = c.strikethrough = True
|
c.bold = c.italic = c.reverse = c.strikethrough = c.dim = True
|
||||||
c.fg = c.bg = c.decoration_fg = 0x0101
|
c.fg = c.bg = c.decoration_fg = 0x0101
|
||||||
self.ae(c, c)
|
self.ae(c, c)
|
||||||
c2, c3 = c.copy(), c.copy()
|
c2, c3 = c.copy(), c.copy()
|
||||||
@@ -219,7 +219,7 @@ class TestDataTypes(BaseTest):
|
|||||||
|
|
||||||
l3.set_text(t, 0, len(t), C())
|
l3.set_text(t, 0, len(t), C())
|
||||||
q = C()
|
q = C()
|
||||||
q.bold = q.italic = q.reverse = q.strikethrough = True
|
q.bold = q.italic = q.reverse = q.strikethrough = c.dim = True
|
||||||
q.decoration = 2
|
q.decoration = 2
|
||||||
c = C()
|
c = C()
|
||||||
c.x = 3
|
c.x = 3
|
||||||
@@ -450,12 +450,12 @@ class TestDataTypes(BaseTest):
|
|||||||
self.ae(a, ['\x1b[0m' + str(lb.line(i)) + '\n' for i in range(lb.ynum)])
|
self.ae(a, ['\x1b[0m' + str(lb.line(i)) + '\n' for i in range(lb.ynum)])
|
||||||
l2 = lb.line(0)
|
l2 = lb.line(0)
|
||||||
c = C()
|
c = C()
|
||||||
c.bold = c.italic = c.reverse = c.strikethrough = True
|
c.bold = c.italic = c.reverse = c.strikethrough = c.dim = True
|
||||||
c.fg = (4 << 8) | 1
|
c.fg = (4 << 8) | 1
|
||||||
c.bg = (1 << 24) | (2 << 16) | (3 << 8) | 2
|
c.bg = (1 << 24) | (2 << 16) | (3 << 8) | 2
|
||||||
c.decoration_fg = (5 << 8) | 1
|
c.decoration_fg = (5 << 8) | 1
|
||||||
l2.set_text('1', 0, 1, c)
|
l2.set_text('1', 0, 1, c)
|
||||||
self.ae(l2.as_ansi(), '\x1b[0m\x1b[1;3;7;9;34;48:2:1:2:3;58:5:5m' '1'
|
self.ae(l2.as_ansi(), '\x1b[0m\x1b[1;2;3;7;9;34;48:2:1:2:3;58:5:5m' '1'
|
||||||
'\x1b[22;23;27;29;39;49;59m' '0000')
|
'\x1b[22;23;27;29;39;49;59m' '0000')
|
||||||
lb = filled_line_buf()
|
lb = filled_line_buf()
|
||||||
for i in range(lb.ynum):
|
for i in range(lb.ynum):
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ class TestParser(BaseTest):
|
|||||||
def sgr(params):
|
def sgr(params):
|
||||||
return (('select_graphic_rendition', '{} '.format(x)) for x in params.split())
|
return (('select_graphic_rendition', '{} '.format(x)) for x in params.split())
|
||||||
|
|
||||||
pb('\033[1;3;4;7;9;34;44m', *sgr('1 3 4 7 9 34 44'))
|
pb('\033[1;2;3;4;7;9;34;44m', *sgr('1 2 3 4 7 9 34 44'))
|
||||||
for attr in 'bold italic reverse strikethrough'.split():
|
for attr in 'bold italic reverse strikethrough dim'.split():
|
||||||
self.assertTrue(getattr(s.cursor, attr))
|
self.assertTrue(getattr(s.cursor, attr))
|
||||||
self.ae(s.cursor.decoration, 1)
|
self.ae(s.cursor.decoration, 1)
|
||||||
self.ae(s.cursor.fg, 4 << 8 | 1)
|
self.ae(s.cursor.fg, 4 << 8 | 1)
|
||||||
@@ -202,7 +202,7 @@ class TestParser(BaseTest):
|
|||||||
c.clear()
|
c.clear()
|
||||||
pb('\033P$qm\033\\', ('screen_request_capabilities', ord('$'), 'm'))
|
pb('\033P$qm\033\\', ('screen_request_capabilities', ord('$'), 'm'))
|
||||||
self.ae(c.wtcbuf, b'\033P1$rm\033\\')
|
self.ae(c.wtcbuf, b'\033P1$rm\033\\')
|
||||||
for sgr in '0;34;102;1;3;4 0;38:5:200;58:2:10:11:12'.split():
|
for sgr in '0;34;102;1;2;3;4 0;38:5:200;58:2:10:11:12'.split():
|
||||||
expected = set(sgr.split(';')) - {'0'}
|
expected = set(sgr.split(';')) - {'0'}
|
||||||
c.clear()
|
c.clear()
|
||||||
parse_bytes(s, '\033[{}m\033P$qm\033\\'.format(sgr).encode('ascii'))
|
parse_bytes(s, '\033[{}m\033P$qm\033\\'.format(sgr).encode('ascii'))
|
||||||
|
|||||||
Reference in New Issue
Block a user