From 016519a868ad533b6c5a91e2220c8bad8caeeed4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 26 Oct 2024 14:22:33 +0530 Subject: [PATCH] Remove the 4KB mac chars limit in unicode_in_range --- kitty/cleanup.h | 1 + kitty/line.c | 31 ++++++++++++++++++++++--------- kitty/line.h | 1 + 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/kitty/cleanup.h b/kitty/cleanup.h index f5ac9f54e..906f24174 100644 --- a/kitty/cleanup.h +++ b/kitty/cleanup.h @@ -19,6 +19,7 @@ typedef enum { FREETYPE_CLEANUP_FUNC, SYSTEMD_CLEANUP_FUNC, SHADERS_CLEANUP_FUNC, + LINE_CLEANUP_FUNC, NUM_CLEANUP_FUNCS } AtExitCleanupFunc; diff --git a/kitty/line.c b/kitty/line.c index 2c7d66d5e..a48a67113 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -5,6 +5,9 @@ * Distributed under terms of the GPL3 license. */ +#include "cleanup.h" +#define EXTRA_INIT register_at_exit_cleanup_func(LINE_CLEANUP_FUNC, cleanup_module); + #include "state.h" #include "unicode-data.h" #include "lineops.h" @@ -255,35 +258,39 @@ cell_as_utf8_for_fallback(CPUCell *cell, TextCache *tc, char *buf) { return n; } +static ListOfChars global_unicode_in_range_buf = {0}; PyObject* unicode_in_range(const Line *self, const index_type start, const index_type limit, const bool include_cc, const bool add_trailing_newline, const bool skip_zero_cells) { size_t n = 0; - static Py_UCS4 buf[4096]; ListOfChars lc; char_type previous_width = 0; for (index_type i = start; i < limit; i++) { - lc.chars = buf + n; lc.capacity = arraysz(buf) - n; - if (!text_in_cell_without_alloc(self->cpu_cells + i, self->text_cache, &lc)) break; + lc.chars = global_unicode_in_range_buf.chars + n; lc.capacity = global_unicode_in_range_buf.capacity - n; + while (!text_in_cell_without_alloc(self->cpu_cells + i, self->text_cache, &lc)) { + size_t ns = MAX(4096, 2 * global_unicode_in_range_buf.capacity); + char_type *np = realloc(global_unicode_in_range_buf.chars, ns); + if (!np) return PyErr_NoMemory(); + global_unicode_in_range_buf.capacity = ns; global_unicode_in_range_buf.chars = np; + lc.chars = global_unicode_in_range_buf.chars + n; lc.capacity = global_unicode_in_range_buf.capacity - n; + } if (!lc.chars[0]) { if (previous_width == 2) { previous_width = 0; continue; }; if (skip_zero_cells) continue; lc.chars[0] = ' '; } if (lc.chars[0] == '\t') { - buf[n++] = '\t'; + n++; unsigned num_cells_to_skip_for_tab = lc.count > 1 ? lc.chars[1] : 0; while (num_cells_to_skip_for_tab && i + 1 < limit && cell_is_char(self->cpu_cells+i+1, ' ')) { i++; num_cells_to_skip_for_tab--; } - } else { - n += include_cc ? lc.count : 1; - } + } else n += include_cc ? lc.count : 1; previous_width = self->gpu_cells[i].attrs.width; } - if (add_trailing_newline && !self->gpu_cells[self->xnum-1].attrs.next_char_was_wrapped && n < arraysz(buf)) buf[n++] = '\n'; - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, n); + if (add_trailing_newline && !self->gpu_cells[self->xnum-1].attrs.next_char_was_wrapped && n < global_unicode_in_range_buf.capacity) global_unicode_in_range_buf.chars[n++] = '\n'; + return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, global_unicode_in_range_buf.chars, n); } PyObject * @@ -999,6 +1006,12 @@ Line *alloc_line(TextCache *tc) { return ans; } +static void +cleanup_module(void) { + free(global_unicode_in_range_buf.chars); + global_unicode_in_range_buf = (ListOfChars){0}; +} + RICHCMP(Line) INIT_TYPE(Line) // }}} diff --git a/kitty/line.h b/kitty/line.h index ec77c8be3..d7e455be8 100644 --- a/kitty/line.h +++ b/kitty/line.h @@ -96,6 +96,7 @@ static inline bool text_in_cell_without_alloc(const CPUCell *c, const TextCache *tc, ListOfChars *ans) { if (c->ch_is_idx) return tc_chars_at_index_without_alloc(tc, c->ch_or_idx, ans); ans->count = 1; + if (ans->capacity < 1) return false; ans->chars[0] = c->ch_or_idx; return true; }