diff --git a/kitty/history.c b/kitty/history.c index 93ec91fb8..e11c51a80 100644 --- a/kitty/history.c +++ b/kitty/history.c @@ -163,8 +163,37 @@ PyTypeObject HistoryBuf_Type = { }; INIT_TYPE(HistoryBuf) -// }}} HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns) { return (HistoryBuf*)new(&HistoryBuf_Type, Py_BuildValue("II", lines, columns), NULL); } +// }}} + +#define BufType HistoryBuf + +#define map_src_index(y) ((src->start_of_data + y) % src->ynum) + +#define init_src_line(src_y) init_line(src, map_src_index(src_y), src->line); + +#define is_src_line_continued(src_y) (map_src_index(src_y) < src->ynum - 1 ? *(start_of(src, map_src_index(src_y + 1))) : false) + +#define next_dest_line(cont) historybuf_push(dest); dest->line->continued = cont; + +#define first_dest_line next_dest_line(false); + +#include "rewrap.h" + +void historybuf_rewrap(HistoryBuf *self, HistoryBuf *other) { + // Fast path + if (other->xnum == self->xnum && other->ynum == self->ynum) { + Py_BEGIN_ALLOW_THREADS; + memcpy(other->buf, self->buf, CELL_SIZE_H * self->xnum * self->ynum); + other->count = self->count; other->start_of_data = self->start_of_data; + Py_END_ALLOW_THREADS; + return; + } + other->count = 0; other->start_of_data = 0; + if (self->count > 0) rewrap_inner(self, other, self->count, NULL); +} + + diff --git a/kitty/line-buf.c b/kitty/line-buf.c index 2acb01d72..0ff69573d 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -405,52 +405,7 @@ copy_old(LineBuf *self, PyObject *y) { Py_RETURN_NONE; } -static inline void copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) { - memcpy(dest->chars + dest_at, src->chars + src_at, num * sizeof(char_type)); - memcpy(dest->colors + dest_at, src->colors + src_at, num * sizeof(color_type)); - memcpy(dest->decoration_fg + dest_at, src->decoration_fg + src_at, num * sizeof(decoration_type)); - memcpy(dest->combining_chars + dest_at, src->combining_chars + src_at, num * sizeof(combining_type)); -} - -#define next_dest_line(continued) {\ - if (dest_y >= dest->ynum - 1) { \ - linebuf_index(dest, 0, dest->ynum - 1); \ - if (historybuf != NULL) { \ - linebuf_init_line(dest, dest->ynum - 1); \ - historybuf_add_line(historybuf, dest->line); \ - }\ - } else dest_y++; \ - INIT_LINE(dest, dest->line, dest->line_map[dest_y]); \ - dest->continued_map[dest_y] = continued; \ - dest_x = 0; \ -} - -static void rewrap_inner(LineBuf *src, LineBuf *dest, const index_type src_limit, HistoryBuf *historybuf) { - // TODO: Change this to put the extra lines into the history buf - bool src_line_is_continued = false; - index_type src_y = 0, src_x = 0, dest_x = 0, dest_y = 0, num = 0, src_x_limit = 0; - INIT_LINE(dest, dest->line, dest->line_map[dest_y]); - - do { - INIT_LINE(src, src->line, src->line_map[src_y]); - src_line_is_continued = src_y < src->ynum - 1 ? src->continued_map[src_y + 1] : false; - src_x_limit = src->xnum; - if (!src_line_is_continued) { - // Trim trailing white-space since there is a hard line break at the end of this line - while(src_x_limit && (src->line->chars[src_x_limit - 1] & CHAR_MASK) == 32) src_x_limit--; - - } - while (src_x < src_x_limit) { - if (dest_x >= dest->xnum) next_dest_line(true); - num = MIN(src->line->xnum - src_x, dest->xnum - dest_x); - copy_range(src->line, src_x, dest->line, dest_x, num); - src_x += num; dest_x += num; - } - src_y++; src_x = 0; - if (!src_line_is_continued && src_y < src_limit) next_dest_line(false); - } while (src_y < src_limit); - dest->line->ynum = dest_y; -} +#include "rewrap.h" void linebuf_rewrap(LineBuf *self, LineBuf *other, int *cursor_y_out, HistoryBuf *historybuf) { index_type first, i; diff --git a/kitty/rewrap.h b/kitty/rewrap.h new file mode 100644 index 000000000..da347dc6f --- /dev/null +++ b/kitty/rewrap.h @@ -0,0 +1,75 @@ +/* + * rewrap.h + * Copyright (C) 2016 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#pragma once + +#ifndef BufType +#define BufType LineBuf +#endif + +#ifndef init_src_line +#define init_src_line(src_y) INIT_LINE(src, src->line, src->line_map[src_y]); +#endif + +#ifndef init_dest_line +#define init_dest_line(dest_y) INIT_LINE(dest, dest->line, dest->line_map[dest_y]); +#endif + +#ifndef first_dest_line +#define first_dest_line init_dest_line(0) +#endif + +#ifndef next_dest_line +#define next_dest_line(continued) \ + if (dest_y >= dest->ynum - 1) { \ + linebuf_index(dest, 0, dest->ynum - 1); \ + linebuf_init_line(dest, dest->ynum - 1); \ + historybuf_add_line(historybuf, dest->line); \ + } else dest_y++; \ + init_dest_line(dest_y); \ + dest->continued_map[dest_y] = continued; +#endif + +#ifndef is_src_line_continued +#define is_src_line_continued(src_y) (src_y < src->ynum - 1 ? src->continued_map[src_y + 1] : false) +#endif + +static inline void copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) { + memcpy(dest->chars + dest_at, src->chars + src_at, num * sizeof(char_type)); + memcpy(dest->colors + dest_at, src->colors + src_at, num * sizeof(color_type)); + memcpy(dest->decoration_fg + dest_at, src->decoration_fg + src_at, num * sizeof(decoration_type)); + memcpy(dest->combining_chars + dest_at, src->combining_chars + src_at, num * sizeof(combining_type)); +} + + +static void rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf UNUSED *historybuf) { + bool src_line_is_continued = false; + index_type src_y = 0, src_x = 0, dest_x = 0, dest_y = 0, num = 0, src_x_limit = 0; + Py_BEGIN_ALLOW_THREADS; + + first_dest_line; + do { + init_src_line(src_y); + src_line_is_continued = is_src_line_continued(src_y); + src_x_limit = src->xnum; + if (!src_line_is_continued) { + // Trim trailing white-space since there is a hard line break at the end of this line + while(src_x_limit && (src->line->chars[src_x_limit - 1] & CHAR_MASK) == 32) src_x_limit--; + + } + while (src_x < src_x_limit) { + if (dest_x >= dest->xnum) { next_dest_line(true); dest_x = 0; } + num = MIN(src->line->xnum - src_x, dest->xnum - dest_x); + copy_range(src->line, src_x, dest->line, dest_x, num); + src_x += num; dest_x += num; + } + src_y++; src_x = 0; + if (!src_line_is_continued && src_y < src_limit) { next_dest_line(false); dest_x = 0; } + } while (src_y < src_limit); + dest->line->ynum = dest_y; + Py_END_ALLOW_THREADS; +}