Avoid a double call for mark functions
This commit is contained in:
parent
0b3602f764
commit
23bc2171c9
@ -58,7 +58,7 @@ typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
|||||||
|
|
||||||
#define MAX_CHILDREN 512
|
#define MAX_CHILDREN 512
|
||||||
#define BLANK_CHAR 0
|
#define BLANK_CHAR 0
|
||||||
#define ATTRS_MASK_WITHOUT_WIDTH 0xFFC
|
#define ATTRS_MASK_WITHOUT_WIDTH 0xFFFC
|
||||||
#define WIDTH_MASK 3
|
#define WIDTH_MASK 3
|
||||||
#define DECORATION_SHIFT 2
|
#define DECORATION_SHIFT 2
|
||||||
#define DECORATION_MASK 3
|
#define DECORATION_MASK 3
|
||||||
@ -69,7 +69,7 @@ typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
|||||||
#define STRIKE_SHIFT 7
|
#define STRIKE_SHIFT 7
|
||||||
#define DIM_SHIFT 8
|
#define DIM_SHIFT 8
|
||||||
#define MARK_SHIFT 9
|
#define MARK_SHIFT 9
|
||||||
#define MARK_MASK 3
|
#define ATTRS_MASK_WITHOUT_MARK 0xf9ff
|
||||||
#define COL_MASK 0xFFFFFFFF
|
#define COL_MASK 0xFFFFFFFF
|
||||||
#define UTF8_ACCEPT 0
|
#define UTF8_ACCEPT 0
|
||||||
#define UTF8_REJECT 1
|
#define UTF8_REJECT 1
|
||||||
@ -143,6 +143,12 @@ typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
|||||||
#define END_ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic pop")
|
#define END_ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic pop")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject *callback;
|
||||||
|
const char *name;
|
||||||
|
} Marker;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t left, top, right, bottom;
|
uint32_t left, top, right, bottom;
|
||||||
} Region;
|
} Region;
|
||||||
|
|||||||
12
kitty/line.c
12
kitty/line.c
@ -665,6 +665,18 @@ __eq__(Line *a, Line *b) {
|
|||||||
return a->xnum == b->xnum && memcmp(a->cpu_cells, b->cpu_cells, sizeof(CPUCell) * a->xnum) == 0 && memcmp(a->gpu_cells, b->gpu_cells, sizeof(GPUCell) * a->xnum) == 0;
|
return a->xnum == b->xnum && memcmp(a->cpu_cells, b->cpu_cells, sizeof(CPUCell) * a->xnum) == 0 && memcmp(a->gpu_cells, b->gpu_cells, sizeof(GPUCell) * a->xnum) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mark_text_in_line(Marker *markers, size_t markers_count, Line *line) {
|
||||||
|
if (!markers_count) {
|
||||||
|
for (index_type i = 0; i < line->xnum; i++) {
|
||||||
|
line->gpu_cells[i].attrs &= ATTRS_MASK_WITHOUT_MARK;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void)markers;
|
||||||
|
}
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
static PyObject*
|
static PyObject*
|
||||||
copy_char(Line* self, PyObject *args);
|
copy_char(Line* self, PyObject *args);
|
||||||
|
|||||||
@ -90,6 +90,7 @@ void historybuf_mark_line_clean(HistoryBuf *self, index_type y);
|
|||||||
void historybuf_mark_line_dirty(HistoryBuf *self, index_type y);
|
void historybuf_mark_line_dirty(HistoryBuf *self, index_type y);
|
||||||
void historybuf_refresh_sprite_positions(HistoryBuf *self);
|
void historybuf_refresh_sprite_positions(HistoryBuf *self);
|
||||||
void historybuf_clear(HistoryBuf *self);
|
void historybuf_clear(HistoryBuf *self);
|
||||||
|
void mark_text_in_line(Marker *markers, size_t markers_count, Line *line);
|
||||||
|
|
||||||
|
|
||||||
#define as_text_generic(args, container, get_line, lines, columns) { \
|
#define as_text_generic(args, container, get_line, lines, columns) { \
|
||||||
|
|||||||
@ -105,7 +105,6 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
self->callbacks = callbacks; Py_INCREF(callbacks);
|
self->callbacks = callbacks; Py_INCREF(callbacks);
|
||||||
self->test_child = test_child; Py_INCREF(test_child);
|
self->test_child = test_child; Py_INCREF(test_child);
|
||||||
self->cursor = alloc_cursor();
|
self->cursor = alloc_cursor();
|
||||||
self->markers.callbacks = PyList_New(0);
|
|
||||||
self->color_profile = alloc_color_profile();
|
self->color_profile = alloc_color_profile();
|
||||||
self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns);
|
self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns);
|
||||||
self->linebuf = self->main_linebuf;
|
self->linebuf = self->main_linebuf;
|
||||||
@ -119,7 +118,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
if (
|
if (
|
||||||
self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL ||
|
self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL ||
|
||||||
self->main_tabstops == NULL || self->historybuf == NULL || self->main_grman == NULL ||
|
self->main_tabstops == NULL || self->historybuf == NULL || self->main_grman == NULL ||
|
||||||
self->alt_grman == NULL || self->color_profile == NULL || self->markers.callbacks == NULL
|
self->alt_grman == NULL || self->color_profile == NULL
|
||||||
) {
|
) {
|
||||||
Py_CLEAR(self); return NULL;
|
Py_CLEAR(self); return NULL;
|
||||||
}
|
}
|
||||||
@ -269,6 +268,12 @@ reset_callbacks(Screen *self, PyObject *a UNUSED) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_marker(Marker *marker) {
|
||||||
|
Py_CLEAR(marker->callback);
|
||||||
|
free((void*)marker->name);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dealloc(Screen* self) {
|
dealloc(Screen* self) {
|
||||||
pthread_mutex_destroy(&self->read_buf_lock);
|
pthread_mutex_destroy(&self->read_buf_lock);
|
||||||
@ -283,7 +288,10 @@ dealloc(Screen* self) {
|
|||||||
Py_CLEAR(self->alt_linebuf);
|
Py_CLEAR(self->alt_linebuf);
|
||||||
Py_CLEAR(self->historybuf);
|
Py_CLEAR(self->historybuf);
|
||||||
Py_CLEAR(self->color_profile);
|
Py_CLEAR(self->color_profile);
|
||||||
Py_CLEAR(self->markers.callbacks);
|
if (self->markers.items) {
|
||||||
|
for (size_t i = 0; i < self->markers.count; i++) free_marker(self->markers.items + i);
|
||||||
|
free(self->markers.items);
|
||||||
|
}
|
||||||
PyMem_Free(self->overlay_line.cpu_cells);
|
PyMem_Free(self->overlay_line.cpu_cells);
|
||||||
PyMem_Free(self->overlay_line.gpu_cells);
|
PyMem_Free(self->overlay_line.gpu_cells);
|
||||||
PyMem_Free(self->main_tabstops);
|
PyMem_Free(self->main_tabstops);
|
||||||
@ -1509,6 +1517,12 @@ screen_reset_dirty(Screen *self) {
|
|||||||
self->history_line_added_count = 0;
|
self->history_line_added_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
screen_has_markers(Screen *self) {
|
||||||
|
return self->markers.count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_data, bool cursor_has_moved) {
|
screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_data, bool cursor_has_moved) {
|
||||||
unsigned int history_line_added_count = self->history_line_added_count;
|
unsigned int history_line_added_count = self->history_line_added_count;
|
||||||
@ -1522,6 +1536,7 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat
|
|||||||
historybuf_init_line(self->historybuf, lnum, self->historybuf->line);
|
historybuf_init_line(self->historybuf, lnum, self->historybuf->line);
|
||||||
if (self->historybuf->line->has_dirty_text) {
|
if (self->historybuf->line->has_dirty_text) {
|
||||||
render_line(fonts_data, self->historybuf->line, lnum, self->cursor, self->disable_ligatures);
|
render_line(fonts_data, self->historybuf->line, lnum, self->cursor, self->disable_ligatures);
|
||||||
|
if (screen_has_markers(self)) mark_text_in_line(self->markers.items, self->markers.count, self->historybuf->line);
|
||||||
historybuf_mark_line_clean(self->historybuf, lnum);
|
historybuf_mark_line_clean(self->historybuf, lnum);
|
||||||
}
|
}
|
||||||
update_line_data(self->historybuf->line, y, address);
|
update_line_data(self->historybuf->line, y, address);
|
||||||
@ -1532,6 +1547,8 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat
|
|||||||
if (self->linebuf->line->has_dirty_text ||
|
if (self->linebuf->line->has_dirty_text ||
|
||||||
(cursor_has_moved && (self->cursor->y == lnum || self->last_rendered_cursor_y == lnum))) {
|
(cursor_has_moved && (self->cursor->y == lnum || self->last_rendered_cursor_y == lnum))) {
|
||||||
render_line(fonts_data, self->linebuf->line, lnum, self->cursor, self->disable_ligatures);
|
render_line(fonts_data, self->linebuf->line, lnum, self->cursor, self->disable_ligatures);
|
||||||
|
if (self->linebuf->line->has_dirty_text && screen_has_markers(self)) mark_text_in_line(self->markers.items, self->markers.count, self->linebuf->line);
|
||||||
|
|
||||||
linebuf_mark_line_clean(self->linebuf, lnum);
|
linebuf_mark_line_clean(self->linebuf, lnum);
|
||||||
}
|
}
|
||||||
update_line_data(self->linebuf->line, y, address);
|
update_line_data(self->linebuf->line, y, address);
|
||||||
@ -2247,26 +2264,59 @@ send_escape_code_to_child(Screen *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
screen_mark_all(Screen *self) {
|
||||||
|
for (index_type y = 0; y < self->main_linebuf->ynum; y++) {
|
||||||
|
linebuf_init_line(self->main_linebuf, y);
|
||||||
|
mark_text_in_line(self->markers.items, self->markers.count, self->main_linebuf->line);
|
||||||
|
}
|
||||||
|
for (index_type y = 0; y < self->alt_linebuf->ynum; y++) {
|
||||||
|
linebuf_init_line(self->alt_linebuf, y);
|
||||||
|
mark_text_in_line(self->markers.items, self->markers.count, self->alt_linebuf->line);
|
||||||
|
}
|
||||||
|
for (index_type y = 0; y < self->historybuf->ynum; y++) {
|
||||||
|
historybuf_init_line(self->historybuf, y, self->historybuf->line);
|
||||||
|
mark_text_in_line(self->markers.items, self->markers.count, self->historybuf->line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
add_marker(Screen *self, PyObject *marker) {
|
add_marker(Screen *self, PyObject *args) {
|
||||||
|
const char *name;
|
||||||
|
PyObject *marker;
|
||||||
|
if (!PyArg_ParseTuple(args, "sO", &name, &marker)) return NULL;
|
||||||
if (!PyCallable_Check(marker)) {
|
if (!PyCallable_Check(marker)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "marker must be a callable");
|
PyErr_SetString(PyExc_TypeError, "marker must be a callable");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!PySequence_Contains(self->markers.callbacks, marker)) {
|
for (size_t i = 0; i < self->markers.count; i++) {
|
||||||
if (PyList_Append(self->markers.callbacks, marker) != 0) return NULL;
|
if (strcmp(self->markers.items[i].name, name) == 0) {
|
||||||
self->markers.dirty = true;
|
Py_DECREF(self->markers.items[i].callback);
|
||||||
|
self->markers.items[i].callback = marker;
|
||||||
|
Py_INCREF(marker);
|
||||||
|
screen_mark_all(self);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ensure_space_for(&self->markers, items, Marker, 1, capacity, 8, true);
|
||||||
|
self->markers.items[self->markers.count].name = strdup(name);
|
||||||
|
self->markers.items[self->markers.count++].callback = marker;
|
||||||
|
Py_INCREF(marker);
|
||||||
|
screen_mark_all(self);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
remove_marker(Screen *self, PyObject *marker) {
|
remove_marker(Screen *self, PyObject *args) {
|
||||||
Py_ssize_t idx = PySequence_Index(self->markers.callbacks, marker);
|
const char *name;
|
||||||
if (idx > -1) {
|
if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
|
||||||
PySequence_DelItem(self->markers.callbacks, idx);
|
for (size_t i = 0; i < self->markers.count; i++) {
|
||||||
self->markers.dirty = true;
|
if (strcmp(self->markers.items[i].name, name) == 0) {
|
||||||
Py_RETURN_TRUE;
|
free_marker(self->markers.items + i);
|
||||||
|
remove_i_from_array(self->markers.items, i, self->markers.count);
|
||||||
|
screen_mark_all(self);
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
}
|
}
|
||||||
@ -2370,8 +2420,8 @@ static PyMethodDef methods[] = {
|
|||||||
MND(paste, METH_O)
|
MND(paste, METH_O)
|
||||||
MND(paste_bytes, METH_O)
|
MND(paste_bytes, METH_O)
|
||||||
MND(copy_colors_from, METH_O)
|
MND(copy_colors_from, METH_O)
|
||||||
MND(add_marker, METH_O)
|
MND(add_marker, METH_VARARGS)
|
||||||
MND(remove_marker, METH_O)
|
MND(remove_marker, METH_VARARGS)
|
||||||
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
|
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
|
||||||
|
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
|||||||
@ -61,7 +61,6 @@ typedef struct {
|
|||||||
index_type xstart, ynum, xnum;
|
index_type xstart, ynum, xnum;
|
||||||
} OverlayLine;
|
} OverlayLine;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
@ -108,12 +107,10 @@ typedef struct {
|
|||||||
uint8_t stop_buf[32];
|
uint8_t stop_buf[32];
|
||||||
} pending_mode;
|
} pending_mode;
|
||||||
DisableLigature disable_ligatures;
|
DisableLigature disable_ligatures;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
PyObject *callbacks;
|
Marker *items;
|
||||||
bool dirty;
|
size_t count, capacity;
|
||||||
} markers;
|
} markers;
|
||||||
|
|
||||||
} Screen;
|
} Screen;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user