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 BLANK_CHAR 0
|
||||
#define ATTRS_MASK_WITHOUT_WIDTH 0xFFC
|
||||
#define ATTRS_MASK_WITHOUT_WIDTH 0xFFFC
|
||||
#define WIDTH_MASK 3
|
||||
#define DECORATION_SHIFT 2
|
||||
#define DECORATION_MASK 3
|
||||
@ -69,7 +69,7 @@ typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
||||
#define STRIKE_SHIFT 7
|
||||
#define DIM_SHIFT 8
|
||||
#define MARK_SHIFT 9
|
||||
#define MARK_MASK 3
|
||||
#define ATTRS_MASK_WITHOUT_MARK 0xf9ff
|
||||
#define COL_MASK 0xFFFFFFFF
|
||||
#define UTF8_ACCEPT 0
|
||||
#define UTF8_REJECT 1
|
||||
@ -143,6 +143,12 @@ typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
||||
#define END_ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic pop")
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject *callback;
|
||||
const char *name;
|
||||
} Marker;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t left, top, right, bottom;
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
||||
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 {{{
|
||||
static PyObject*
|
||||
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_refresh_sprite_positions(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) { \
|
||||
|
||||
@ -105,7 +105,6 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||
self->callbacks = callbacks; Py_INCREF(callbacks);
|
||||
self->test_child = test_child; Py_INCREF(test_child);
|
||||
self->cursor = alloc_cursor();
|
||||
self->markers.callbacks = PyList_New(0);
|
||||
self->color_profile = alloc_color_profile();
|
||||
self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns);
|
||||
self->linebuf = self->main_linebuf;
|
||||
@ -119,7 +118,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||
if (
|
||||
self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == 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;
|
||||
}
|
||||
@ -269,6 +268,12 @@ reset_callbacks(Screen *self, PyObject *a UNUSED) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
free_marker(Marker *marker) {
|
||||
Py_CLEAR(marker->callback);
|
||||
free((void*)marker->name);
|
||||
}
|
||||
|
||||
static void
|
||||
dealloc(Screen* self) {
|
||||
pthread_mutex_destroy(&self->read_buf_lock);
|
||||
@ -283,7 +288,10 @@ dealloc(Screen* self) {
|
||||
Py_CLEAR(self->alt_linebuf);
|
||||
Py_CLEAR(self->historybuf);
|
||||
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.gpu_cells);
|
||||
PyMem_Free(self->main_tabstops);
|
||||
@ -1509,6 +1517,12 @@ screen_reset_dirty(Screen *self) {
|
||||
self->history_line_added_count = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
screen_has_markers(Screen *self) {
|
||||
return self->markers.count > 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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;
|
||||
@ -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);
|
||||
if (self->historybuf->line->has_dirty_text) {
|
||||
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);
|
||||
}
|
||||
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 ||
|
||||
(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);
|
||||
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);
|
||||
}
|
||||
update_line_data(self->linebuf->line, y, address);
|
||||
@ -2247,26 +2264,59 @@ send_escape_code_to_child(Screen *self, PyObject *args) {
|
||||
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*
|
||||
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)) {
|
||||
PyErr_SetString(PyExc_TypeError, "marker must be a callable");
|
||||
return NULL;
|
||||
}
|
||||
if (!PySequence_Contains(self->markers.callbacks, marker)) {
|
||||
if (PyList_Append(self->markers.callbacks, marker) != 0) return NULL;
|
||||
self->markers.dirty = true;
|
||||
for (size_t i = 0; i < self->markers.count; i++) {
|
||||
if (strcmp(self->markers.items[i].name, name) == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
remove_marker(Screen *self, PyObject *marker) {
|
||||
Py_ssize_t idx = PySequence_Index(self->markers.callbacks, marker);
|
||||
if (idx > -1) {
|
||||
PySequence_DelItem(self->markers.callbacks, idx);
|
||||
self->markers.dirty = true;
|
||||
Py_RETURN_TRUE;
|
||||
remove_marker(Screen *self, PyObject *args) {
|
||||
const char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
|
||||
for (size_t i = 0; i < self->markers.count; i++) {
|
||||
if (strcmp(self->markers.items[i].name, name) == 0) {
|
||||
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;
|
||||
}
|
||||
@ -2370,8 +2420,8 @@ static PyMethodDef methods[] = {
|
||||
MND(paste, METH_O)
|
||||
MND(paste_bytes, METH_O)
|
||||
MND(copy_colors_from, METH_O)
|
||||
MND(add_marker, METH_O)
|
||||
MND(remove_marker, METH_O)
|
||||
MND(add_marker, METH_VARARGS)
|
||||
MND(remove_marker, METH_VARARGS)
|
||||
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
|
||||
@ -61,7 +61,6 @@ typedef struct {
|
||||
index_type xstart, ynum, xnum;
|
||||
} OverlayLine;
|
||||
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
@ -108,12 +107,10 @@ typedef struct {
|
||||
uint8_t stop_buf[32];
|
||||
} pending_mode;
|
||||
DisableLigature disable_ligatures;
|
||||
|
||||
struct {
|
||||
PyObject *callbacks;
|
||||
bool dirty;
|
||||
Marker *items;
|
||||
size_t count, capacity;
|
||||
} markers;
|
||||
|
||||
} Screen;
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user