diff --git a/kitty/history.c b/kitty/history.c index f527f3413..0d254d382 100644 --- a/kitty/history.c +++ b/kitty/history.c @@ -114,7 +114,7 @@ pagerhist_clear(HistoryBuf *self) { } static HistoryBuf* -create_historybuf(PyTypeObject *type, unsigned int xnum, unsigned int ynum, unsigned int pagerhist_sz) { +create_historybuf(PyTypeObject *type, unsigned int xnum, unsigned int ynum, unsigned int pagerhist_sz, TextCache *tc) { if (xnum == 0 || ynum == 0) { PyErr_SetString(PyExc_ValueError, "Cannot create an empty history buffer"); return NULL; @@ -125,7 +125,8 @@ create_historybuf(PyTypeObject *type, unsigned int xnum, unsigned int ynum, unsi self->ynum = ynum; self->num_segments = 0; add_segment(self); - self->line = alloc_line(); + self->text_cache = tc_incref(tc); + self->line = alloc_line(self->text_cache); self->line->xnum = xnum; self->pagerhist = alloc_pagerhist(pagerhist_sz); } @@ -136,7 +137,10 @@ static PyObject * new_history_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { unsigned int xnum = 1, ynum = 1, pagerhist_sz = 0; if (!PyArg_ParseTuple(args, "II|I", &ynum, &xnum, &pagerhist_sz)) return NULL; - HistoryBuf *ans = create_historybuf(type, xnum, ynum, pagerhist_sz); + TextCache *tc = tc_alloc(); + if (!tc) return PyErr_NoMemory(); + HistoryBuf *ans = create_historybuf(type, xnum, ynum, pagerhist_sz, tc); + tc_decref(tc); return (PyObject*)ans; } @@ -146,6 +150,7 @@ dealloc(HistoryBuf* self) { for (size_t i = 0; i < self->num_segments; i++) free_segment(self->segments + i); free(self->segments); free_pagerhist(self); + tc_decref(self->text_cache); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -574,8 +579,8 @@ PyTypeObject HistoryBuf_Type = { INIT_TYPE(HistoryBuf) -HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns, unsigned int pagerhist_sz) { - return create_historybuf(&HistoryBuf_Type, columns, lines, pagerhist_sz); +HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns, unsigned int pagerhist_sz, TextCache *tc) { + return create_historybuf(&HistoryBuf_Type, columns, lines, pagerhist_sz, tc); } // }}} diff --git a/kitty/history.h b/kitty/history.h index 2dd94fa80..b795bea95 100644 --- a/kitty/history.h +++ b/kitty/history.h @@ -16,8 +16,9 @@ typedef struct { HistoryBufSegment *segments; PagerHistoryBuf *pagerhist; Line *line; + TextCache *text_cache; index_type start_of_data, count; } HistoryBuf; -HistoryBuf* alloc_historybuf(unsigned int, unsigned int, unsigned int); +HistoryBuf* alloc_historybuf(unsigned int, unsigned int, unsigned int, TextCache *tc); diff --git a/kitty/line-buf.c b/kitty/line-buf.c index e3cfe68aa..3035a83c1 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -71,7 +71,7 @@ clear(LineBuf *self, PyObject *a UNUSED) { } LineBuf * -alloc_linebuf_(PyTypeObject *cls, unsigned int lines, unsigned int columns) { +alloc_linebuf_(PyTypeObject *cls, unsigned int lines, unsigned int columns, TextCache *text_cache) { if (columns > 5000 || lines > 50000) { PyErr_SetString(PyExc_ValueError, "Number of rows or columns is too large."); return NULL; @@ -92,8 +92,9 @@ alloc_linebuf_(PyTypeObject *cls, unsigned int lines, unsigned int columns) { self->gpu_cell_buf = (GPUCell*)(self->cpu_cell_buf + area); self->line_map = (index_type*)(self->gpu_cell_buf + area); self->scratch = self->line_map + lines; + self->text_cache = tc_incref(text_cache); + self->line = alloc_line(self->text_cache); self->line_attrs = (LineAttrs*)(self->scratch + lines); - self->line = alloc_line(); self->line->xnum = columns; for(index_type i = 0; i < lines; i++) { self->line_map[i] = i; @@ -108,11 +109,16 @@ new_linebuf_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { unsigned int xnum = 1, ynum = 1; if (!PyArg_ParseTuple(args, "II", &ynum, &xnum)) return NULL; - return (PyObject*)alloc_linebuf_(type, ynum, xnum); + TextCache *tc = tc_alloc(); + if (!tc) return PyErr_NoMemory(); + PyObject *ans = (PyObject*)alloc_linebuf_(type, ynum, xnum, tc); + tc_decref(tc); + return ans; } static void dealloc(LineBuf* self) { + self->text_cache = tc_decref(self->text_cache); PyMem_Free(self->cpu_cell_buf); Py_CLEAR(self->line); Py_TYPE(self)->tp_free((PyObject*)self); @@ -249,7 +255,7 @@ allocate_line_storage(Line *line, bool initialize) { static PyObject* create_line_copy_inner(LineBuf* self, index_type y) { Line src, *line; - line = alloc_line(); + line = alloc_line(self->text_cache); if (line == NULL) return PyErr_NoMemory(); src.xnum = self->xnum; line->xnum = self->xnum; if (!allocate_line_storage(line, 0)) { Py_CLEAR(line); return PyErr_NoMemory(); } @@ -631,4 +637,4 @@ rewrap(LineBuf *self, PyObject *args) { LineBuf * -alloc_linebuf(unsigned int lines, unsigned int columns) { return alloc_linebuf_(&LineBuf_Type, lines, columns); } +alloc_linebuf(unsigned int lines, unsigned int columns, TextCache *tc) { return alloc_linebuf_(&LineBuf_Type, lines, columns, tc); } diff --git a/kitty/line-buf.h b/kitty/line-buf.h index f648f7641..f6a5c9fc2 100644 --- a/kitty/line-buf.h +++ b/kitty/line-buf.h @@ -8,6 +8,7 @@ #pragma once #include "line.h" +#include "text-cache.h" typedef struct { PyObject_HEAD @@ -17,7 +18,8 @@ typedef struct { index_type xnum, ynum, *line_map, *scratch; LineAttrs *line_attrs; Line *line; + TextCache *text_cache; } LineBuf; -LineBuf* alloc_linebuf(unsigned int, unsigned int); +LineBuf* alloc_linebuf(unsigned int, unsigned int, TextCache*); diff --git a/kitty/line.c b/kitty/line.c index 29d89bd43..e728eeac1 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -19,6 +19,7 @@ dealloc(Line* self) { PyMem_Free(self->cpu_cells); PyMem_Free(self->gpu_cells); } + tc_decref(self->text_cache); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -972,8 +973,10 @@ PyTypeObject Line_Type = { .tp_methods = methods, }; -Line *alloc_line(void) { - return (Line*)Line_Type.tp_alloc(&Line_Type, 0); +Line *alloc_line(TextCache *tc) { + Line *ans = (Line*)Line_Type.tp_alloc(&Line_Type, 0); + if (ans) ans->text_cache = tc_incref(tc); + return ans; } RICHCMP(Line) diff --git a/kitty/line.h b/kitty/line.h index 8eb7dec9a..406f76295 100644 --- a/kitty/line.h +++ b/kitty/line.h @@ -7,7 +7,7 @@ #pragma once -#include "data-types.h" +#include "text-cache.h" typedef struct { PyObject_HEAD @@ -17,6 +17,7 @@ typedef struct { index_type xnum, ynum; bool needs_free; LineAttrs attrs; + TextCache *text_cache; } Line; -Line* alloc_line(void); +Line* alloc_line(TextCache *text_cache); diff --git a/kitty/screen.c b/kitty/screen.c index 843e7dadb..27974278e 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -107,6 +107,7 @@ new_screen_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { } self->vt_parser = alloc_vt_parser(window_id); if (self->vt_parser == NULL) { Py_CLEAR(self); return PyErr_NoMemory(); } + self->text_cache = tc_alloc(); if (!self->text_cache) { Py_CLEAR(self); return PyErr_NoMemory(); } self->reload_all_gpu_data = true; self->cell_size.width = cell_width; self->cell_size.height = cell_height; self->columns = columns; self->lines = lines; @@ -125,9 +126,9 @@ new_screen_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { self->test_child = test_child; Py_INCREF(test_child); self->cursor = alloc_cursor(); 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->text_cache); self->alt_linebuf = alloc_linebuf(lines, columns, self->text_cache); self->linebuf = self->main_linebuf; - self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns, OPT(scrollback_pager_history_size)); + self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns, OPT(scrollback_pager_history_size), self->text_cache); self->main_grman = grman_alloc(false); self->alt_grman = grman_alloc(false); self->active_hyperlink_id = 0; @@ -214,7 +215,7 @@ screen_dirty_sprite_positions(Screen *self) { static HistoryBuf* realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns, ANSIBuf *as_ansi_buf) { - HistoryBuf *ans = alloc_historybuf(lines, columns, 0); + HistoryBuf *ans = alloc_historybuf(lines, columns, 0, old->text_cache); if (ans == NULL) { PyErr_NoMemory(); return NULL; } ans->pagerhist = old->pagerhist; old->pagerhist = NULL; historybuf_rewrap(old, ans, as_ansi_buf); @@ -232,7 +233,7 @@ typedef struct CursorTrack { static LineBuf* realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *nclb, index_type *ncla, HistoryBuf *hb, CursorTrack *a, CursorTrack *b, ANSIBuf *as_ansi_buf) { - LineBuf *ans = alloc_linebuf(lines, columns); + LineBuf *ans = alloc_linebuf(lines, columns, old->text_cache); if (ans == NULL) { PyErr_NoMemory(); return NULL; } a->temp.x = a->before.x; a->temp.y = a->before.y; b->temp.x = b->before.x; b->temp.y = b->before.y; @@ -398,7 +399,7 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { RAII_PyObject(prompt_copy, NULL); index_type num_of_prompt_lines = 0, num_of_prompt_lines_above_cursor = 0; if (is_main) { - prompt_copy = (PyObject*)alloc_linebuf(self->lines, self->columns); + prompt_copy = (PyObject*)alloc_linebuf(self->lines, self->columns, self->text_cache); num_of_prompt_lines = prevent_current_prompt_from_rewrapping(self, (LineBuf*)prompt_copy, &num_of_prompt_lines_above_cursor); } LineBuf *n = realloc_lb(self->main_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, self->historybuf, &cursor, &main_saved_cursor, &self->as_ansi_buf); @@ -500,6 +501,7 @@ static void dealloc(Screen* self) { pthread_mutex_destroy(&self->write_buf_lock); free_vt_parser(self->vt_parser); self->vt_parser = NULL; + self->text_cache = tc_decref(self->text_cache); Py_CLEAR(self->main_grman); Py_CLEAR(self->alt_grman); Py_CLEAR(self->last_reported_cwd); @@ -2539,7 +2541,7 @@ screen_pause_rendering(Screen *self, bool pause, int for_in_ms) { memcpy(&self->paused_rendering.color_profile, self->color_profile, sizeof(self->paused_rendering.color_profile)); if (!self->paused_rendering.linebuf || self->paused_rendering.linebuf->xnum != self->columns || self->paused_rendering.linebuf->ynum != self->lines) { if (self->paused_rendering.linebuf) Py_CLEAR(self->paused_rendering.linebuf); - self->paused_rendering.linebuf = alloc_linebuf(self->lines, self->columns); + self->paused_rendering.linebuf = alloc_linebuf(self->lines, self->columns, self->text_cache); if (!self->paused_rendering.linebuf) { PyErr_Clear(); self->paused_rendering.expires_at = 0; return false; } } for (index_type y = 0; y < self->lines; y++) { diff --git a/kitty/screen.h b/kitty/screen.h index 98a1b728f..6d8adc4ea 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -105,6 +105,7 @@ typedef struct { Cursor *cursor; Savepoint main_savepoint, alt_savepoint; PyObject *callbacks, *test_child; + TextCache *text_cache; LineBuf *linebuf, *main_linebuf, *alt_linebuf; GraphicsManager *grman, *main_grman, *alt_grman; HistoryBuf *historybuf;