From af8fdf1dbe8b9b1ba2dad2074565335ec48bace9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Feb 2020 15:33:12 +0530 Subject: [PATCH] Dont use a macro for as_text_generic --- kitty/history.c | 19 +++++++++++++++---- kitty/line-buf.c | 7 ++++--- kitty/line.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ kitty/lineops.h | 46 ++-------------------------------------------- kitty/screen.c | 13 ++++++++----- 5 files changed, 74 insertions(+), 56 deletions(-) diff --git a/kitty/history.c b/kitty/history.c index 8d1fcdbef..0a560c07f 100644 --- a/kitty/history.c +++ b/kitty/history.c @@ -379,12 +379,23 @@ end: Py_RETURN_NONE; } +typedef struct { + Line line; + HistoryBuf *self; +} GetLineWrapper; + +static Line* +get_line_wrapper(void *x, int y) { + GetLineWrapper *glw = x; + get_line(glw->self, y, &glw->line); + return &glw->line; +} + static PyObject* as_text(HistoryBuf *self, PyObject *args) { - Line l = {.xnum=self->xnum}; -#define gl(self, y) get_line(self, y, &l); - as_text_generic(args, self, gl, self->count, self->xnum); -#undef gl + GetLineWrapper glw = {.self=self}; + glw.line.xnum = self->xnum; + return as_text_generic(args, &glw, get_line_wrapper, self->count, self->xnum); } diff --git a/kitty/line-buf.c b/kitty/line-buf.c index 77b66d45a..dcd288ad9 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -421,14 +421,15 @@ as_ansi(LineBuf *self, PyObject *callback) { } static inline Line* -get_line(LineBuf *self, index_type y) { - linebuf_init_line(self, y); +get_line(void *x, int y) { + LineBuf *self = (LineBuf*)x; + linebuf_init_line(self, MAX(0, y)); return self->line; } static PyObject* as_text(LineBuf *self, PyObject *args) { - as_text_generic(args, self, get_line, self->ynum, self->xnum); + return as_text_generic(args, self, get_line, self->ynum, self->xnum); } diff --git a/kitty/line.c b/kitty/line.c index c25391de6..15c949185 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -737,6 +737,51 @@ mark_text_in_line(PyObject *marker, Line *line) { Py_DECREF(text); } +PyObject* +as_text_generic(PyObject *args, void *container, get_line_func get_line, index_type lines, index_type columns) { + PyObject *callback; + int as_ansi = 0, insert_wrap_markers = 0; + if (!PyArg_ParseTuple(args, "O|pp", &callback, &as_ansi, &insert_wrap_markers)) return NULL; + PyObject *ret = NULL, *t = NULL; + Py_UCS4 *buf = NULL; + PyObject *nl = PyUnicode_FromString("\n"); + PyObject *cr = PyUnicode_FromString("\r"); + const GPUCell *prev_cell = NULL; + if (nl == NULL || cr == NULL) goto end; + if (as_ansi) { + buf = malloc(sizeof(Py_UCS4) * columns * 100); + if (buf == NULL) { PyErr_NoMemory(); goto end; } + } + for (index_type y = 0; y < lines; y++) { + Line *line = get_line(container, y); + if (!line->continued && y > 0) { + ret = PyObject_CallFunctionObjArgs(callback, nl, NULL); + if (ret == NULL) goto end; + Py_CLEAR(ret); + } + if (as_ansi) { + bool truncated; + index_type num = line_as_ansi(line, buf, columns * 100 - 2, &truncated, &prev_cell); + t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num); + } else { + t = line_as_unicode(line); + } + if (t == NULL) goto end; + ret = PyObject_CallFunctionObjArgs(callback, t, NULL); + Py_DECREF(t); if (ret == NULL) goto end; Py_DECREF(ret); + if (insert_wrap_markers) { + ret = PyObject_CallFunctionObjArgs(callback, cr, NULL); + if (ret == NULL) goto end; + Py_CLEAR(ret); + } + } +end: + Py_CLEAR(nl); Py_CLEAR(cr); free(buf); + if (PyErr_Occurred()) return NULL; + Py_RETURN_NONE; +} + + // Boilerplate {{{ static PyObject* copy_char(Line* self, PyObject *args); diff --git a/kitty/lineops.h b/kitty/lineops.h index 2109ed49a..8ace7381d 100644 --- a/kitty/lineops.h +++ b/kitty/lineops.h @@ -54,6 +54,7 @@ line_reset_cells(Line *line, index_type start, index_type num, GPUCell *gpu_cell memcpy(line->cpu_cells + start, cpu_cells + start, sizeof(CPUCell) * num); } +typedef Line*(get_line_func)(void *, int); void line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch); void line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char); void line_set_char(Line *, unsigned int , uint32_t , unsigned int , Cursor *, bool); @@ -92,47 +93,4 @@ void historybuf_refresh_sprite_positions(HistoryBuf *self); void historybuf_clear(HistoryBuf *self); void mark_text_in_line(PyObject *marker, Line *line); bool line_has_mark(Line *, attrs_type mark); - - -#define as_text_generic(args, container, get_line, lines, columns) { \ - PyObject *callback; \ - int as_ansi = 0, insert_wrap_markers = 0; \ - if (!PyArg_ParseTuple(args, "O|pp", &callback, &as_ansi, &insert_wrap_markers)) return NULL; \ - PyObject *ret = NULL, *t = NULL; \ - Py_UCS4 *buf = NULL; \ - PyObject *nl = PyUnicode_FromString("\n"); \ - PyObject *cr = PyUnicode_FromString("\r"); \ - const GPUCell *prev_cell = NULL; \ - if (nl == NULL || cr == NULL) goto end; \ - if (as_ansi) { \ - buf = malloc(sizeof(Py_UCS4) * columns * 100); \ - if (buf == NULL) { PyErr_NoMemory(); goto end; } \ - } \ - for (index_type y = 0; y < lines; y++) { \ - Line *line = get_line(container, y); \ - if (!line->continued && y > 0) { \ - ret = PyObject_CallFunctionObjArgs(callback, nl, NULL); \ - if (ret == NULL) goto end; \ - Py_CLEAR(ret); \ - } \ - if (as_ansi) { \ - bool truncated; \ - index_type num = line_as_ansi(line, buf, columns * 100 - 2, &truncated, &prev_cell); \ - t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num); \ - } else { \ - t = line_as_unicode(line); \ - } \ - if (t == NULL) goto end; \ - ret = PyObject_CallFunctionObjArgs(callback, t, NULL); \ - Py_DECREF(t); if (ret == NULL) goto end; Py_DECREF(ret); \ - if (insert_wrap_markers) { \ - ret = PyObject_CallFunctionObjArgs(callback, cr, NULL); \ - if (ret == NULL) goto end; \ - Py_CLEAR(ret); \ - }\ - } \ -end: \ - Py_CLEAR(nl); Py_CLEAR(cr); free(buf); \ - if (PyErr_Occurred()) return NULL; \ - Py_RETURN_NONE; \ -} +PyObject* as_text_generic(PyObject *args, void *container, get_line_func get_line, index_type lines, index_type columns); diff --git a/kitty/screen.c b/kitty/screen.c index 134efcf00..c8e1eaf64 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1749,26 +1749,29 @@ set_pending_timeout(Screen *self, PyObject *val) { return ans; } +static Line* get_visual_line(void *x, int y) { return visual_line_(x, y); } +static Line* get_range_line(void *x, int y) { return range_line_(x, y); } + static PyObject* as_text(Screen *self, PyObject *args) { - as_text_generic(args, self, visual_line_, self->lines, self->columns); + return as_text_generic(args, self, get_visual_line, self->lines, self->columns); } static PyObject* as_text_non_visual(Screen *self, PyObject *args) { - as_text_generic(args, self, range_line_, self->lines, self->columns); + return as_text_generic(args, self, get_range_line, self->lines, self->columns); } static inline PyObject* -as_text_generic_wrapper(Screen *self, PyObject *args, Line*(get_line)(Screen *, int)) { - as_text_generic(args, self, get_line, self->lines, self->columns); +as_text_generic_wrapper(Screen *self, PyObject *args, get_line_func get_line) { + return as_text_generic(args, self, get_line, self->lines, self->columns); } static PyObject* as_text_alternate(Screen *self, PyObject *args) { LineBuf *original = self->linebuf; self->linebuf = original == self->main_linebuf ? self->alt_linebuf : self->main_linebuf; - PyObject *ans = as_text_generic_wrapper(self, args, range_line_); + PyObject *ans = as_text_generic_wrapper(self, args, get_range_line); self->linebuf = original; return ans; }