diff --git a/kitty/history.c b/kitty/history.c index dd94b3310..bd8bb0569 100644 --- a/kitty/history.c +++ b/kitty/history.c @@ -279,8 +279,9 @@ void historybuf_rewrap(HistoryBuf *self, HistoryBuf *other) { return; } other->count = 0; other->start_of_data = 0; + index_type x = 0, y = 0; if (self->count > 0) { - rewrap_inner(self, other, self->count, NULL); + rewrap_inner(self, other, self->count, NULL, &x, &y); for (index_type i = 0; i < other->count; i++) other->line_attrs[(other->start_of_data + i) % other->ynum] |= TEXT_DIRTY_MASK; } } diff --git a/kitty/line-buf.c b/kitty/line-buf.c index ad1bcc74e..7a881e16e 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -494,7 +494,7 @@ copy_old(LineBuf *self, PyObject *y) { #include "rewrap.h" void -linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_before, index_type *num_content_lines_after, HistoryBuf *historybuf) { +linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_before, index_type *num_content_lines_after, HistoryBuf *historybuf, index_type *track_x, index_type *track_y) { index_type first, i; bool is_empty = true; @@ -523,7 +523,7 @@ linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_befo return; } - rewrap_inner(self, other, first + 1, historybuf); + rewrap_inner(self, other, first + 1, historybuf, track_x, track_y); *num_content_lines_after = other->line->ynum + 1; for (i = 0; i < *num_content_lines_after; i++) other->line_attrs[i] |= TEXT_DIRTY_MASK; *num_content_lines_before = first + 1; @@ -536,7 +536,8 @@ rewrap(LineBuf *self, PyObject *args) { unsigned int nclb, ncla; if (!PyArg_ParseTuple(args, "O!O!", &LineBuf_Type, &other, &HistoryBuf_Type, &historybuf)) return NULL; - linebuf_rewrap(self, other, &nclb, &ncla, historybuf); + index_type x = 0, y = 0; + linebuf_rewrap(self, other, &nclb, &ncla, historybuf, &x, &y); return Py_BuildValue("II", nclb, ncla); } diff --git a/kitty/lineops.h b/kitty/lineops.h index 741ecaea8..520e9d252 100644 --- a/kitty/lineops.h +++ b/kitty/lineops.h @@ -66,7 +66,7 @@ void linebuf_clear_line(LineBuf *self, index_type y); void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom); void linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom); void linebuf_set_attribute(LineBuf *, unsigned int , unsigned int ); -void linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *, index_type *, HistoryBuf *); +void linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *, index_type *, HistoryBuf *, index_type *, index_type *); void linebuf_mark_line_dirty(LineBuf *self, index_type y); void linebuf_mark_line_clean(LineBuf *self, index_type y); unsigned int linebuf_char_width_at(LineBuf *self, index_type x, index_type y); diff --git a/kitty/rewrap.h b/kitty/rewrap.h index d2c48023f..c10aa3176 100644 --- a/kitty/rewrap.h +++ b/kitty/rewrap.h @@ -48,12 +48,13 @@ copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_t static void -rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf UNUSED *historybuf) { +rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf UNUSED *historybuf, index_type *track_x, index_type *track_y) { 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; first_dest_line; do { + bool is_tracked_line = src_y == *track_y; init_src_line(src_y); src_line_is_continued = is_src_line_continued(src_y); src_x_limit = src->xnum; @@ -62,10 +63,15 @@ rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf while(src_x_limit && (src->line->cells[src_x_limit - 1].ch) == BLANK_CHAR) src_x_limit--; } + if (is_tracked_line && *track_x >= src_x_limit) *track_x = MAX(1, src_x_limit) - 1; 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); + if (is_tracked_line && src_x <= *track_x && *track_x < src_x + num) { + *track_y = dest_y; + *track_x = dest_x + (*track_x - src_x); + } src_x += num; dest_x += num; } src_y++; src_x = 0; diff --git a/kitty/screen.c b/kitty/screen.c index bf0b56839..9abd80dd6 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -135,10 +135,10 @@ realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns) { } static inline LineBuf* -realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *nclb, index_type *ncla, HistoryBuf *hb) { +realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *nclb, index_type *ncla, HistoryBuf *hb, index_type *x, index_type *y) { LineBuf *ans = alloc_linebuf(lines, columns); if (ans == NULL) { PyErr_NoMemory(); return NULL; } - linebuf_rewrap(old, ans, nclb, ncla, hb); + linebuf_rewrap(old, ans, nclb, ncla, hb, x, y); return ans; } @@ -147,31 +147,37 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { lines = MAX(1, lines); columns = MAX(1, columns); bool is_main = self->linebuf == self->main_linebuf; - index_type num_content_lines_before, num_content_lines_after; - index_type num_content_lines = 0, old_columns = self->columns; - bool cursor_on_last_content_line = false; + index_type num_content_lines_before, num_content_lines_after, num_content_lines; + unsigned int cursor_x = 0, cursor_y = 0; + bool cursor_is_beyond_content = false; +#define setup_cursor() { \ + cursor_x = x; cursor_y = y; \ + cursor_is_beyond_content = num_content_lines_before > 0 && self->cursor->y >= num_content_lines_before; \ + num_content_lines = num_content_lines_after; \ +} // Resize main linebuf HistoryBuf *nh = realloc_hb(self->historybuf, self->historybuf->ynum, columns); if (nh == NULL) return false; Py_CLEAR(self->historybuf); self->historybuf = nh; - LineBuf *n = realloc_lb(self->main_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, self->historybuf); + index_type x = self->cursor->x, y = self->cursor->y; + LineBuf *n = realloc_lb(self->main_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, self->historybuf, &x, &y); if (n == NULL) return false; Py_CLEAR(self->main_linebuf); self->main_linebuf = n; - if (is_main) { - num_content_lines = num_content_lines_after; - cursor_on_last_content_line = num_content_lines_before == self->cursor->y + 1 || !num_content_lines_before; - } + if (is_main) setup_cursor(); grman_resize(self->main_grman, self->lines, lines, self->columns, columns); // Resize alt linebuf - n = realloc_lb(self->alt_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, NULL); + x = self->cursor->x, y = self->cursor->y; + n = realloc_lb(self->alt_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, NULL, &x, &y); if (n == NULL) return false; Py_CLEAR(self->alt_linebuf); self->alt_linebuf = n; - if (!is_main) num_content_lines = num_content_lines_after; + if (!is_main) setup_cursor(); grman_resize(self->alt_grman, self->lines, lines, self->columns, columns); +#undef setup_cursor self->linebuf = is_main ? self->main_linebuf : self->alt_linebuf; + /* printf("\nold_size: (%u, %u) new_size: (%u, %u)\n", self->columns, self->lines, columns, lines); */ self->lines = lines; self->columns = columns; self->margin_top = 0; self->margin_bottom = self->lines - 1; @@ -186,18 +192,13 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { self->selection = EMPTY_SELECTION; self->url_range = EMPTY_SELECTION; self->selection_updated_once = false; - - // Ensure cursor is on the correct line - self->cursor->x = 0; - if (cursor_on_last_content_line) { - index_type delta; - if (self->columns > old_columns) delta = 1; - else delta = (old_columns / self->columns) + 1; - self->cursor->y = num_content_lines > delta ? num_content_lines - delta : 0; - } else self->cursor->y = num_content_lines; - self->cursor->y = MIN(self->cursor->y, self->lines - 1); - if (num_content_lines >= self->lines) screen_index(self); - + /* printf("old_cursor: (%u, %u) new_cursor: (%u, %u) beyond_content: %d\n", self->cursor->x, self->cursor->y, cursor_x, cursor_y, cursor_is_beyond_content); */ + self->cursor->x = MIN(cursor_x, self->columns - 1); + self->cursor->y = MIN(cursor_y, self->lines - 1); + if (cursor_is_beyond_content) { + self->cursor->y = num_content_lines; + if (self->cursor->y >= self->lines) { self->cursor->y = self->lines - 1; screen_index(self); } + } return true; } diff --git a/kitty_tests/screen.py b/kitty_tests/screen.py index 7940180b1..060bdb0ed 100644 --- a/kitty_tests/screen.py +++ b/kitty_tests/screen.py @@ -217,13 +217,13 @@ class TestScreen(BaseTest): s = self.create_screen(scrollback=6) s.draw(''.join([str(i) * s.columns for i in range(s.lines)])) s.resize(3, 10) - self.ae(str(s.line(0)), '2'*5 + '3'*5) - self.ae(str(s.line(1)), '4'*5) - self.ae(str(s.line(2)), ''*5) + self.ae(str(s.line(0)), '0'*5 + '1'*5) + self.ae(str(s.line(1)), '2'*5 + '3'*5) + self.ae(str(s.line(2)), '4'*5) s.resize(5, 1) self.ae(str(s.line(0)), '4') hb = s.historybuf - self.ae(str(hb), '4\n3\n3\n3\n3\n3') + self.ae(str(hb), '3\n3\n3\n3\n3\n2') s = self.create_screen(scrollback=20) s.draw(''.join(str(i) * s.columns for i in range(s.lines*2))) self.ae(str(s.linebuf), '55555\n66666\n77777\n88888\n99999')