Get rid of bits from CellAttrs

This commit is contained in:
Kovid Goyal 2021-07-31 12:41:05 +05:30
parent b260a61c8f
commit ef76c075e0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
8 changed files with 54 additions and 54 deletions

View File

@ -140,7 +140,7 @@ apply_sgr_to_cells(GPUCell *first_cell, unsigned int cell_count, int *params, un
#define RANGE for(unsigned c = 0; c < cell_count; c++, cell++) #define RANGE for(unsigned c = 0; c < cell_count; c++, cell++)
#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;
#define S(which, val) RANGE { cell->attrs.bits.which = (val); } break; #define S(which, val) RANGE { cell->attrs.which = (val); } break;
unsigned int i = 0, attr; unsigned int i = 0, attr;
if (!count) { params[0] = 0; count = 1; } if (!count) { params[0] = 0; count = 1; }
@ -171,7 +171,7 @@ apply_sgr_to_cells(GPUCell *first_cell, unsigned int cell_count, int *params, un
case 21: case 21:
S(decoration, 2); S(decoration, 2);
case 22: case 22:
RANGE { cell->attrs.bits.bold = false; cell->attrs.bits.dim = false; } break; RANGE { cell->attrs.bold = false; cell->attrs.dim = false; } break;
case 23: case 23:
S(italic, false); S(italic, false);
case 24: case 24:

View File

@ -295,7 +295,7 @@ PyInit_fast_data_types(void) {
if (!init_fonts(m)) return NULL; if (!init_fonts(m)) return NULL;
CellAttrs a; CellAttrs a;
#define s(name, attr) { a.val = 0; a.bits.attr = 1; PyModule_AddIntConstant(m, #name, shift_to_first_set_bit(a)); } #define s(name, attr) { a.val = 0; a.attr = 1; PyModule_AddIntConstant(m, #name, shift_to_first_set_bit(a)); }
s(BOLD, bold); s(ITALIC, italic); s(REVERSE, reverse); s(MARK, mark); s(BOLD, bold); s(ITALIC, italic); s(REVERSE, reverse); s(MARK, mark);
s(STRIKETHROUGH, strike); s(DIM, dim); s(DECORATION, decoration); s(STRIKETHROUGH, strike); s(DIM, dim); s(DECORATION, decoration);
#undef s #undef s

View File

@ -141,12 +141,12 @@ typedef union CellAttrs {
uint16_t strike : 1; uint16_t strike : 1;
uint16_t dim : 1; uint16_t dim : 1;
uint16_t mark : 2; uint16_t mark : 2;
} bits; };
uint16_t val; uint16_t val;
} CellAttrs; } CellAttrs;
#define MARK_MASK (3u) #define MARK_MASK (3u)
#define WIDTH_MASK (3u) #define WIDTH_MASK (3u)
#define SGR_MASK (~(((CellAttrs){.bits={.width=WIDTH_MASK, .mark=MARK_MASK}}).val)) #define SGR_MASK (~(((CellAttrs){.width=WIDTH_MASK, .mark=MARK_MASK}).val))
typedef struct { typedef struct {
color_type fg, bg, decoration_fg; color_type fg, bg, decoration_fg;
@ -290,16 +290,16 @@ typedef struct {FONTS_DATA_HEAD} *FONTS_DATA_HANDLE;
static inline CellAttrs static inline CellAttrs
cursor_to_attrs(const Cursor *c, const uint16_t width) { cursor_to_attrs(const Cursor *c, const uint16_t width) {
CellAttrs ans = {.bits={ CellAttrs ans = {
.width=width, .decoration=c->decoration, .bold=c->bold, .italic=c->italic, .reverse=c->reverse, .width=width, .decoration=c->decoration, .bold=c->bold, .italic=c->italic, .reverse=c->reverse,
.strike=c->strikethrough, .dim=c->dim}}; .strike=c->strikethrough, .dim=c->dim};
return ans; return ans;
} }
static inline void static inline void
attrs_to_cursor(const CellAttrs attrs, Cursor *c) { attrs_to_cursor(const CellAttrs attrs, Cursor *c) {
c->decoration = attrs.bits.decoration; c->bold = attrs.bits.bold; c->italic = attrs.bits.italic; c->decoration = attrs.decoration; c->bold = attrs.bold; c->italic = attrs.italic;
c->reverse = attrs.bits.reverse; c->strikethrough = attrs.bits.strike; c->dim = attrs.bits.dim; c->reverse = attrs.reverse; c->strikethrough = attrs.strike; c->dim = attrs.dim;
} }

View File

@ -378,7 +378,7 @@ face_has_codepoint(PyObject* face, char_type cp) {
static bool static bool
has_emoji_presentation(CPUCell *cpu_cell, GPUCell *gpu_cell) { has_emoji_presentation(CPUCell *cpu_cell, GPUCell *gpu_cell) {
return gpu_cell->attrs.bits.width == 2 && is_emoji(cpu_cell->ch) && cpu_cell->cc_idx[0] != VS15; return gpu_cell->attrs.width == 2 && is_emoji(cpu_cell->ch) && cpu_cell->cc_idx[0] != VS15;
} }
static bool static bool
@ -458,8 +458,8 @@ load_fallback_font(FontGroup *fg, CPUCell *cell, bool bold, bool italic, bool em
static ssize_t static ssize_t
fallback_font(FontGroup *fg, CPUCell *cpu_cell, GPUCell *gpu_cell) { fallback_font(FontGroup *fg, CPUCell *cpu_cell, GPUCell *gpu_cell) {
bool bold = gpu_cell->attrs.bits.bold; bool bold = gpu_cell->attrs.bold;
bool italic = gpu_cell->attrs.bits.italic; bool italic = gpu_cell->attrs.italic;
bool emoji_presentation = has_emoji_presentation(cpu_cell, gpu_cell); bool emoji_presentation = has_emoji_presentation(cpu_cell, gpu_cell);
// Check if one of the existing fallback fonts has this text // Check if one of the existing fallback fonts has this text
@ -512,7 +512,7 @@ START_ALLOW_CASE_RANGE
default: default:
ans = in_symbol_maps(fg, cpu_cell->ch); ans = in_symbol_maps(fg, cpu_cell->ch);
if (ans > -1) return ans; if (ans > -1) return ans;
switch(gpu_cell->attrs.bits.bold | (gpu_cell->attrs.bits.italic << 1)) { switch(gpu_cell->attrs.bold | (gpu_cell->attrs.italic << 1)) {
case 0: case 0:
ans = fg->medium_font_idx; break; ans = fg->medium_font_idx; break;
case 1: case 1:
@ -605,7 +605,7 @@ load_hb_buffer(CPUCell *first_cpu_cell, GPUCell *first_gpu_cell, index_type num_
for (num = 0; num_cells && num < arraysz(shape_buffer) - 20 - arraysz(first_cpu_cell->cc_idx); first_cpu_cell++, first_gpu_cell++, num_cells--) { for (num = 0; num_cells && num < arraysz(shape_buffer) - 20 - arraysz(first_cpu_cell->cc_idx); first_cpu_cell++, first_gpu_cell++, num_cells--) {
if (prev_width == 2) { prev_width = 0; continue; } if (prev_width == 2) { prev_width = 0; continue; }
shape_buffer[num++] = first_cpu_cell->ch; shape_buffer[num++] = first_cpu_cell->ch;
prev_width = first_gpu_cell->attrs.bits.width; prev_width = first_gpu_cell->attrs.width;
for (unsigned i = 0; i < arraysz(first_cpu_cell->cc_idx) && first_cpu_cell->cc_idx[i]; i++) { for (unsigned i = 0; i < arraysz(first_cpu_cell->cc_idx) && first_cpu_cell->cc_idx[i]; i++) {
shape_buffer[num++] = codepoint_for_mark(first_cpu_cell->cc_idx[i]); shape_buffer[num++] = codepoint_for_mark(first_cpu_cell->cc_idx[i]);
} }
@ -660,7 +660,7 @@ render_group(FontGroup *fg, unsigned int num_cells, unsigned int num_glyphs, CPU
} }
ensure_canvas_can_fit(fg, num_cells + 1); ensure_canvas_can_fit(fg, num_cells + 1);
bool was_colored = gpu_cells->attrs.bits.width == 2 && is_emoji(cpu_cells->ch); bool was_colored = gpu_cells->attrs.width == 2 && is_emoji(cpu_cells->ch);
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas.buf, fg->cell_width, fg->cell_height, num_cells, fg->baseline, &was_colored, (FONTS_DATA_HANDLE)fg, center_glyph); render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas.buf, fg->cell_width, fg->cell_height, num_cells, fg->baseline, &was_colored, (FONTS_DATA_HANDLE)fg, center_glyph);
if (PyErr_Occurred()) PyErr_Print(); if (PyErr_Occurred()) PyErr_Print();
@ -780,7 +780,7 @@ static unsigned int
check_cell_consumed(CellData *cell_data, CPUCell *last_cpu_cell) { check_cell_consumed(CellData *cell_data, CPUCell *last_cpu_cell) {
cell_data->codepoints_consumed++; cell_data->codepoints_consumed++;
if (cell_data->codepoints_consumed >= cell_data->num_codepoints) { if (cell_data->codepoints_consumed >= cell_data->num_codepoints) {
uint16_t width = cell_data->gpu_cell->attrs.bits.width; uint16_t width = cell_data->gpu_cell->attrs.width;
cell_data->cpu_cell += MAX(1, width); cell_data->cpu_cell += MAX(1, width);
cell_data->gpu_cell += MAX(1, width); cell_data->gpu_cell += MAX(1, width);
cell_data->codepoints_consumed = 0; cell_data->codepoints_consumed = 0;
@ -829,7 +829,7 @@ ligature_type_from_glyph_name(const char *glyph_name, SpacerStrategy strategy) {
static void static void
detect_spacer_strategy(hb_font_t *hbf, Font *font) { detect_spacer_strategy(hb_font_t *hbf, Font *font) {
CPUCell cpu_cells[3] = {{.ch = '='}, {.ch = '='}, {.ch = '='}}; CPUCell cpu_cells[3] = {{.ch = '='}, {.ch = '='}, {.ch = '='}};
const CellAttrs w1 = {.bits={.width=1}}; const CellAttrs w1 = {.width=1};
GPUCell gpu_cells[3] = {{.attrs = w1}, {.attrs = w1}, {.attrs = w1}}; GPUCell gpu_cells[3] = {{.attrs = w1}, {.attrs = w1}, {.attrs = w1}};
shape(cpu_cells, gpu_cells, arraysz(cpu_cells), hbf, font, false); shape(cpu_cells, gpu_cells, arraysz(cpu_cells), hbf, font, false);
font->spacer_strategy = SPACERS_BEFORE; font->spacer_strategy = SPACERS_BEFORE;
@ -1088,7 +1088,7 @@ merge_groups_for_pua_space_ligature(void) {
static bool static bool
is_group_calt_ligature(const Group *group) { is_group_calt_ligature(const Group *group) {
GPUCell *first_cell = G(first_gpu_cell) + group->first_cell_idx; GPUCell *first_cell = G(first_gpu_cell) + group->first_cell_idx;
return group->num_cells > 1 && group->has_special_glyph && first_cell->attrs.bits.width == 1; return group->num_cells > 1 && group->has_special_glyph && first_cell->attrs.width == 1;
} }
@ -1142,7 +1142,7 @@ test_shape(PyObject UNUSED *self, PyObject *args) {
int index = 0; int index = 0;
if(!PyArg_ParseTuple(args, "O!|zi", &Line_Type, &line, &path, &index)) return NULL; if(!PyArg_ParseTuple(args, "O!|zi", &Line_Type, &line, &path, &index)) return NULL;
index_type num = 0; index_type num = 0;
while(num < line->xnum && line->cpu_cells[num].ch) num += line->gpu_cells[num].attrs.bits.width; while(num < line->xnum && line->cpu_cells[num].ch) num += line->gpu_cells[num].attrs.width;
PyObject *face = NULL; PyObject *face = NULL;
Font *font; Font *font;
if (!num_font_groups) { PyErr_SetString(PyExc_RuntimeError, "must create at least one font group first"); return NULL; } if (!num_font_groups) { PyErr_SetString(PyExc_RuntimeError, "must create at least one font group first"); return NULL; }
@ -1272,12 +1272,12 @@ render_line(FONTS_DATA_HANDLE fg_, Line *line, index_type lnum, Cursor *cursor,
render_run(fg, line->cpu_cells + i, line->gpu_cells + i, num_spaces + 1, cell_font_idx, true, center_glyph, -1, disable_ligature_strategy); render_run(fg, line->cpu_cells + i, line->gpu_cells + i, num_spaces + 1, cell_font_idx, true, center_glyph, -1, disable_ligature_strategy);
run_font_idx = NO_FONT; run_font_idx = NO_FONT;
first_cell_in_run = i + num_spaces + 1; first_cell_in_run = i + num_spaces + 1;
prev_width = line->gpu_cells[i+num_spaces].attrs.bits.width; prev_width = line->gpu_cells[i+num_spaces].attrs.width;
i += num_spaces; i += num_spaces;
continue; continue;
} }
} }
prev_width = gpu_cell->attrs.bits.width; prev_width = gpu_cell->attrs.width;
if (run_font_idx == NO_FONT) run_font_idx = cell_font_idx; if (run_font_idx == NO_FONT) run_font_idx = cell_font_idx;
if (run_font_idx == cell_font_idx) continue; if (run_font_idx == cell_font_idx) continue;
RENDER RENDER
@ -1549,8 +1549,8 @@ get_fallback_font(PyObject UNUSED *self, PyObject *args) {
if (!PyUnicode_AsUCS4(text, char_buf, arraysz(char_buf), 1)) return NULL; if (!PyUnicode_AsUCS4(text, char_buf, arraysz(char_buf), 1)) return NULL;
cpu_cell.ch = char_buf[0]; cpu_cell.ch = char_buf[0];
for (unsigned i = 0; i + 1 < (unsigned) PyUnicode_GetLength(text) && i < arraysz(cpu_cell.cc_idx); i++) cpu_cell.cc_idx[i] = mark_for_codepoint(char_buf[i + 1]); for (unsigned i = 0; i + 1 < (unsigned) PyUnicode_GetLength(text) && i < arraysz(cpu_cell.cc_idx); i++) cpu_cell.cc_idx[i] = mark_for_codepoint(char_buf[i + 1]);
if (bold) gpu_cell.attrs.bits.bold = true; if (bold) gpu_cell.attrs.bold = true;
if (italic) gpu_cell.attrs.bits.italic = true; if (italic) gpu_cell.attrs.italic = true;
FontGroup *fg = font_groups; FontGroup *fg = font_groups;
ssize_t ans = fallback_font(fg, &cpu_cell, &gpu_cell); ssize_t ans = fallback_font(fg, &cpu_cell, &gpu_cell);
if (ans == MISSING_FONT) { PyErr_SetString(PyExc_ValueError, "No fallback font found"); return NULL; } if (ans == MISSING_FONT) { PyErr_SetString(PyExc_ValueError, "No fallback font found"); return NULL; }

View File

@ -161,7 +161,7 @@ line(LineBuf *self, PyObject *y) {
unsigned int unsigned int
linebuf_char_width_at(LineBuf *self, index_type x, index_type y) { linebuf_char_width_at(LineBuf *self, index_type x, index_type y) {
return gpu_lineptr(self, self->line_map[y])[x].attrs.bits.width; return gpu_lineptr(self, self->line_map[y])[x].attrs.width;
} }
static PyObject* static PyObject*

View File

@ -249,7 +249,7 @@ unicode_in_range(const Line *self, const index_type start, const index_type limi
} else { } else {
n += cell_as_unicode(self->cpu_cells + i, include_cc, buf + n, ' '); n += cell_as_unicode(self->cpu_cells + i, include_cc, buf + n, ' ');
} }
previous_width = self->gpu_cells[i].attrs.bits.width; previous_width = self->gpu_cells[i].attrs.width;
} }
return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, n); return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, n);
} }
@ -350,7 +350,7 @@ line_as_ansi(Line *self, ANSIBuf *output, const GPUCell** prev_cell) {
WRITE_CH(codepoint_for_mark(self->cpu_cells[pos].cc_idx[c])); WRITE_CH(codepoint_for_mark(self->cpu_cells[pos].cc_idx[c]));
} }
} }
previous_width = cell->attrs.bits.width; previous_width = cell->attrs.width;
} }
#undef CMP_ATTRS #undef CMP_ATTRS
#undef CMP #undef CMP
@ -399,14 +399,14 @@ width(Line *self, PyObject *val) {
#define width_doc "width(x) -> the width of the character at x" #define width_doc "width(x) -> the width of the character at x"
unsigned long x = PyLong_AsUnsignedLong(val); unsigned long x = PyLong_AsUnsignedLong(val);
if (x >= self->xnum) { PyErr_SetString(PyExc_ValueError, "Out of bounds"); return NULL; } if (x >= self->xnum) { PyErr_SetString(PyExc_ValueError, "Out of bounds"); return NULL; }
return PyLong_FromUnsignedLong((unsigned long) (self->gpu_cells[x].attrs.bits.width)); return PyLong_FromUnsignedLong((unsigned long) (self->gpu_cells[x].attrs.width));
} }
void void
line_add_combining_char(Line *self, uint32_t ch, unsigned int x) { line_add_combining_char(Line *self, uint32_t ch, unsigned int x) {
CPUCell *cell = self->cpu_cells + x; CPUCell *cell = self->cpu_cells + x;
if (!cell->ch) { if (!cell->ch) {
if (x > 0 && (self->gpu_cells[x-1].attrs.bits.width) == 2 && self->cpu_cells[x-1].ch) cell = self->cpu_cells + x - 1; if (x > 0 && (self->gpu_cells[x-1].attrs.width) == 2 && self->cpu_cells[x-1].ch) cell = self->cpu_cells + x - 1;
else return; // don't allow adding combining chars to a null cell else return; // don't allow adding combining chars to a null cell
} }
for (unsigned i = 0; i < arraysz(cell->cc_idx); i++) { for (unsigned i = 0; i < arraysz(cell->cc_idx); i++) {
@ -494,7 +494,7 @@ line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch) {
for (index_type i = at; i < MIN(self->xnum, at + num); i++) { for (index_type i = at; i < MIN(self->xnum, at + num); i++) {
self->cpu_cells[i].ch = ch; memset(self->cpu_cells[i].cc_idx, 0, sizeof(self->cpu_cells[i].cc_idx)); self->cpu_cells[i].ch = ch; memset(self->cpu_cells[i].cc_idx, 0, sizeof(self->cpu_cells[i].cc_idx));
self->cpu_cells[i].hyperlink_id = 0; self->cpu_cells[i].hyperlink_id = 0;
self->gpu_cells[i].attrs.bits.width = width; self->gpu_cells[i].attrs.width = width;
} }
} }
@ -522,8 +522,8 @@ line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num,
self->gpu_cells[i].attrs = attrs; self->gpu_cells[i].attrs = attrs;
clear_sprite_position(self->gpu_cells[i]); clear_sprite_position(self->gpu_cells[i]);
} else { } else {
attrs.bits.width = self->gpu_cells[i].attrs.bits.width; attrs.width = self->gpu_cells[i].attrs.width;
attrs.bits.mark = self->gpu_cells[i].attrs.bits.mark; attrs.mark = self->gpu_cells[i].attrs.mark;
self->gpu_cells[i].attrs = attrs; self->gpu_cells[i].attrs = attrs;
} }
self->gpu_cells[i].fg = fg; self->gpu_cells[i].bg = bg; self->gpu_cells[i].fg = fg; self->gpu_cells[i].bg = bg;
@ -547,10 +547,10 @@ void line_right_shift(Line *self, unsigned int at, unsigned int num) {
COPY_SELF_CELL(i - num, i) COPY_SELF_CELL(i - num, i)
} }
// Check if a wide character was split at the right edge // Check if a wide character was split at the right edge
if (self->gpu_cells[self->xnum - 1].attrs.bits.width != 1) { if (self->gpu_cells[self->xnum - 1].attrs.width != 1) {
self->cpu_cells[self->xnum - 1].ch = BLANK_CHAR; self->cpu_cells[self->xnum - 1].ch = BLANK_CHAR;
self->cpu_cells[self->xnum - 1].hyperlink_id = 0; self->cpu_cells[self->xnum - 1].hyperlink_id = 0;
self->gpu_cells[self->xnum - 1].attrs = (CellAttrs){.bits={.width=BLANK_CHAR ? 1 : 0}}; self->gpu_cells[self->xnum - 1].attrs = (CellAttrs){.width=BLANK_CHAR ? 1 : 0};
clear_sprite_position(self->gpu_cells[self->xnum - 1]); clear_sprite_position(self->gpu_cells[self->xnum - 1]);
} }
} }
@ -586,7 +586,7 @@ left_shift(Line *self, PyObject *args) {
char_type char_type
line_get_char(Line *self, index_type at) { line_get_char(Line *self, index_type at) {
char_type ch = self->cpu_cells[at].ch; char_type ch = self->cpu_cells[at].ch;
if (!ch && at > 0 && (self->gpu_cells[at-1].attrs.bits.width) > 1) ch = self->cpu_cells[at-1].ch; if (!ch && at > 0 && (self->gpu_cells[at-1].attrs.width) > 1) ch = self->cpu_cells[at-1].ch;
return ch; return ch;
} }
@ -594,7 +594,7 @@ void
line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Cursor *cursor, hyperlink_id_type hyperlink_id) { line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Cursor *cursor, hyperlink_id_type hyperlink_id) {
GPUCell *g = self->gpu_cells + at; GPUCell *g = self->gpu_cells + at;
if (cursor == NULL) { if (cursor == NULL) {
g->attrs.bits.width = width; g->attrs.width = width;
} else { } else {
g->attrs = cursor_to_attrs(cursor, width); g->attrs = cursor_to_attrs(cursor, width);
g->fg = cursor->fg & COL_MASK; g->fg = cursor->fg & COL_MASK;
@ -668,8 +668,8 @@ cell_as_sgr(const GPUCell *cell, const GPUCell *prev) {
#define SZ sizeof(buf) - (p - buf) - 2 #define SZ sizeof(buf) - (p - buf) - 2
#define P(s) { size_t len = strlen(s); if (SZ > len) { memcpy(p, s, len); p += len; } } #define P(s) { size_t len = strlen(s); if (SZ > len) { memcpy(p, s, len); p += len; } }
char *p = buf; char *p = buf;
#define CA cell->attrs.bits #define CA cell->attrs
#define PA prev->attrs.bits #define PA prev->attrs
bool intensity_differs = CA.bold != PA.bold || CA.dim != PA.dim; bool intensity_differs = CA.bold != PA.bold || CA.dim != PA.dim;
if (intensity_differs) { if (intensity_differs) {
if (!CA.bold && !CA.dim) { P("22;"); } if (!CA.bold && !CA.dim) { P("22;"); }
@ -705,7 +705,7 @@ __eq__(Line *a, Line *b) {
bool bool
line_has_mark(Line *line, uint16_t mark) { line_has_mark(Line *line, uint16_t mark) {
for (index_type x = 0; x < line->xnum; x++) { for (index_type x = 0; x < line->xnum; x++) {
const uint16_t m = line->gpu_cells[x].attrs.bits.mark; const uint16_t m = line->gpu_cells[x].attrs.mark;
if (m && (!mark || mark == m)) return true; if (m && (!mark || mark == m)) return true;
} }
return false; return false;
@ -721,7 +721,7 @@ report_marker_error(PyObject *marker) {
static void static void
apply_mark(Line *line, const uint16_t mark, index_type *cell_pos, unsigned int *match_pos) { apply_mark(Line *line, const uint16_t mark, index_type *cell_pos, unsigned int *match_pos) {
#define MARK { line->gpu_cells[x].attrs.bits.mark = mark; } #define MARK { line->gpu_cells[x].attrs.mark = mark; }
index_type x = *cell_pos; index_type x = *cell_pos;
MARK; MARK;
(*match_pos)++; (*match_pos)++;
@ -733,7 +733,7 @@ apply_mark(Line *line, const uint16_t mark, index_type *cell_pos, unsigned int *
num_cells_to_skip_for_tab--; num_cells_to_skip_for_tab--;
MARK; MARK;
} }
} else if ((line->gpu_cells[x].attrs.bits.width) > 1 && x + 1 < line->xnum && !line->cpu_cells[x+1].ch) { } else if ((line->gpu_cells[x].attrs.width) > 1 && x + 1 < line->xnum && !line->cpu_cells[x+1].ch) {
x++; x++;
MARK; MARK;
} else { } else {
@ -769,21 +769,21 @@ apply_marker(PyObject *marker, Line *line, const PyObject *text) {
} }
Py_DECREF(iter); Py_DECREF(iter);
while(x < line->xnum) line->gpu_cells[x++].attrs.bits.mark = 0; while(x < line->xnum) line->gpu_cells[x++].attrs.mark = 0;
if (PyErr_Occurred()) report_marker_error(marker); if (PyErr_Occurred()) report_marker_error(marker);
} }
void void
mark_text_in_line(PyObject *marker, Line *line) { mark_text_in_line(PyObject *marker, Line *line) {
if (!marker) { if (!marker) {
for (index_type i = 0; i < line->xnum; i++) line->gpu_cells[i].attrs.bits.mark = 0; for (index_type i = 0; i < line->xnum; i++) line->gpu_cells[i].attrs.mark = 0;
return; return;
} }
PyObject *text = line_as_unicode(line, false); PyObject *text = line_as_unicode(line, false);
if (PyUnicode_GET_LENGTH(text) > 0) { if (PyUnicode_GET_LENGTH(text) > 0) {
apply_marker(marker, line, text); apply_marker(marker, line, text);
} else { } else {
for (index_type i = 0; i < line->xnum; i++) line->gpu_cells[i].attrs.bits.mark = 0; for (index_type i = 0; i < line->xnum; i++) line->gpu_cells[i].attrs.mark = 0;
} }
Py_DECREF(text); Py_DECREF(text);
} }

View File

@ -9,7 +9,7 @@
#include "data-types.h" #include "data-types.h"
#define set_attribute_on_line(cells, which, val, xnum) { \ #define set_attribute_on_line(cells, which, val, xnum) { \
for (index_type i__ = 0; i__ < xnum; i__++) cells[i__].attrs.bits.which = val; } for (index_type i__ = 0; i__ < xnum; i__++) cells[i__].attrs.which = val; }
static inline bool static inline bool
set_named_attribute_on_line(GPUCell *cells, const char* which, uint16_t val, index_type xnum) { set_named_attribute_on_line(GPUCell *cells, const char* which, uint16_t val, index_type xnum) {
@ -31,7 +31,7 @@ static inline void
clear_chars_in_line(CPUCell *cpu_cells, GPUCell *gpu_cells, index_type xnum, char_type ch) { clear_chars_in_line(CPUCell *cpu_cells, GPUCell *gpu_cells, index_type xnum, char_type ch) {
// Clear only the char part of each cell, the rest must have been cleared by a memset or similar // Clear only the char part of each cell, the rest must have been cleared by a memset or similar
if (ch) { if (ch) {
const CellAttrs empty = {.bits={.width=1}}; const CellAttrs empty = {.width=1};
for (index_type i = 0; i < xnum; i++) { cpu_cells[i].ch = ch; cpu_cells[i].hyperlink_id = 0; gpu_cells[i].attrs = empty; } for (index_type i = 0; i < xnum; i++) { cpu_cells[i].ch = ch; cpu_cells[i].hyperlink_id = 0; gpu_cells[i].attrs = empty; }
} }
} }
@ -41,7 +41,7 @@ xlimit_for_line(const Line *line) {
index_type xlimit = line->xnum; index_type xlimit = line->xnum;
if (BLANK_CHAR == 0) { if (BLANK_CHAR == 0) {
while (xlimit > 0 && (line->cpu_cells[xlimit - 1].ch) == BLANK_CHAR) xlimit--; while (xlimit > 0 && (line->cpu_cells[xlimit - 1].ch) == BLANK_CHAR) xlimit--;
if (xlimit < line->xnum && line->gpu_cells[xlimit > 0 ? xlimit - 1 : xlimit].attrs.bits.width == 2) xlimit++; if (xlimit < line->xnum && line->gpu_cells[xlimit > 0 ? xlimit - 1 : xlimit].attrs.width == 2) xlimit++;
} }
return xlimit; return xlimit;
} }
@ -63,9 +63,9 @@ left_shift_line(Line *line, index_type at, index_type num) {
for (index_type i = at; i < line->xnum - num; i++) { for (index_type i = at; i < line->xnum - num; i++) {
COPY_CELL(line, i + num, line, i); COPY_CELL(line, i + num, line, i);
} }
const CellAttrs empty = {.bits={.width=1}}; const CellAttrs empty = {.width=1};
const CellAttrs zero = {0}; const CellAttrs zero = {0};
if (at < line->xnum && line->gpu_cells[at].attrs.bits.width != 1) { if (at < line->xnum && line->gpu_cells[at].attrs.width != 1) {
line->cpu_cells[at].ch = BLANK_CHAR; line->cpu_cells[at].ch = BLANK_CHAR;
line->cpu_cells[at].hyperlink_id = 0; line->cpu_cells[at].hyperlink_id = 0;
line->gpu_cells[at].attrs = BLANK_CHAR ? empty : zero; line->gpu_cells[at].attrs = BLANK_CHAR ? empty : zero;

View File

@ -594,24 +594,24 @@ draw_combining_char(Screen *self, char_type ch) {
if (ch == 0xfe0f) { // emoji presentation variation marker makes default text presentation emoji (narrow emoji) into wide emoji if (ch == 0xfe0f) { // emoji presentation variation marker makes default text presentation emoji (narrow emoji) into wide emoji
CPUCell *cpu_cell = self->linebuf->line->cpu_cells + xpos; CPUCell *cpu_cell = self->linebuf->line->cpu_cells + xpos;
GPUCell *gpu_cell = self->linebuf->line->gpu_cells + xpos; GPUCell *gpu_cell = self->linebuf->line->gpu_cells + xpos;
if (gpu_cell->attrs.bits.width != 2 && cpu_cell->cc_idx[0] == VS16 && is_emoji_presentation_base(cpu_cell->ch)) { if (gpu_cell->attrs.width != 2 && cpu_cell->cc_idx[0] == VS16 && is_emoji_presentation_base(cpu_cell->ch)) {
if (self->cursor->x <= self->columns - 1) line_set_char(self->linebuf->line, self->cursor->x, 0, 0, self->cursor, self->active_hyperlink_id); if (self->cursor->x <= self->columns - 1) line_set_char(self->linebuf->line, self->cursor->x, 0, 0, self->cursor, self->active_hyperlink_id);
gpu_cell->attrs.bits.width = 2; gpu_cell->attrs.width = 2;
if (xpos == self->columns - 1) move_widened_char(self, cpu_cell, gpu_cell, xpos, ypos); if (xpos == self->columns - 1) move_widened_char(self, cpu_cell, gpu_cell, xpos, ypos);
else self->cursor->x++; else self->cursor->x++;
} }
} else if (ch == 0xfe0e) { } else if (ch == 0xfe0e) {
CPUCell *cpu_cell = self->linebuf->line->cpu_cells + xpos; CPUCell *cpu_cell = self->linebuf->line->cpu_cells + xpos;
GPUCell *gpu_cell = self->linebuf->line->gpu_cells + xpos; GPUCell *gpu_cell = self->linebuf->line->gpu_cells + xpos;
if (gpu_cell->attrs.bits.width == 0 && cpu_cell->ch == 0 && xpos > 0) { if (gpu_cell->attrs.width == 0 && cpu_cell->ch == 0 && xpos > 0) {
xpos--; xpos--;
if (self->cursor->x > 0) self->cursor->x--; if (self->cursor->x > 0) self->cursor->x--;
cpu_cell = self->linebuf->line->cpu_cells + xpos; cpu_cell = self->linebuf->line->cpu_cells + xpos;
gpu_cell = self->linebuf->line->gpu_cells + xpos; gpu_cell = self->linebuf->line->gpu_cells + xpos;
} }
if (gpu_cell->attrs.bits.width == 2 && cpu_cell->cc_idx[0] == VS15 && is_emoji_presentation_base(cpu_cell->ch)) { if (gpu_cell->attrs.width == 2 && cpu_cell->cc_idx[0] == VS15 && is_emoji_presentation_base(cpu_cell->ch)) {
gpu_cell->attrs.bits.width = 1; gpu_cell->attrs.width = 1;
} }
} }
} }
@ -3230,7 +3230,7 @@ marked_cells(Screen *self, PyObject *o UNUSED) {
linebuf_init_line(self->linebuf, y); linebuf_init_line(self->linebuf, y);
for (index_type x = 0; x < self->columns; x++) { for (index_type x = 0; x < self->columns; x++) {
GPUCell *gpu_cell = self->linebuf->line->gpu_cells + x; GPUCell *gpu_cell = self->linebuf->line->gpu_cells + x;
const unsigned int mark = gpu_cell->attrs.bits.mark; const unsigned int mark = gpu_cell->attrs.mark;
if (mark) { if (mark) {
PyObject *t = Py_BuildValue("III", x, y, mark); PyObject *t = Py_BuildValue("III", x, y, mark);
if (!t) { Py_DECREF(ans); return NULL; } if (!t) { Py_DECREF(ans); return NULL; }