diff --git a/kitty/line-buf.c b/kitty/line-buf.c index 04343e902..863a67868 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -544,7 +544,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, index_type *track_x, index_type *track_y, ANSIBuf *as_ansi_buf) { +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 *track_x2, index_type *track_y2, ANSIBuf *as_ansi_buf) { index_type first, i; bool is_empty = true; @@ -574,9 +574,10 @@ linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_befo return; } - TrackCursor tcarr[2] = {{.x = *track_x, .y = *track_y }, {.is_sentinel = true}}; + TrackCursor tcarr[3] = {{.x = *track_x, .y = *track_y }, {.x = *track_x2, .y = *track_y2}, {.is_sentinel = true}}; rewrap_inner(self, other, first + 1, historybuf, (TrackCursor*)tcarr, as_ansi_buf); *track_x = tcarr[0].x; *track_y = tcarr[0].y; + *track_x2 = tcarr[1].x; *track_y2 = tcarr[1].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; @@ -589,9 +590,9 @@ rewrap(LineBuf *self, PyObject *args) { unsigned int nclb, ncla; if (!PyArg_ParseTuple(args, "O!O!", &LineBuf_Type, &other, &HistoryBuf_Type, &historybuf)) return NULL; - index_type x = 0, y = 0; + index_type x = 0, y = 0, x2 = 0, y2 = 0; ANSIBuf as_ansi_buf = {0}; - linebuf_rewrap(self, other, &nclb, &ncla, historybuf, &x, &y, &as_ansi_buf); + linebuf_rewrap(self, other, &nclb, &ncla, historybuf, &x, &y, &x2, &y2, &as_ansi_buf); free(as_ansi_buf.buf); return Py_BuildValue("II", nclb, ncla); diff --git a/kitty/lineops.h b/kitty/lineops.h index 50443121e..5e93f2dbe 100644 --- a/kitty/lineops.h +++ b/kitty/lineops.h @@ -95,7 +95,7 @@ void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsig void linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom); void linebuf_copy_line_to(LineBuf *, Line *, index_type); void linebuf_set_attribute(LineBuf *, unsigned int , unsigned int ); -void linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *, index_type *, HistoryBuf *, index_type *, index_type *, ANSIBuf*); +void linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *, index_type *, HistoryBuf *, index_type *, index_type *, index_type *, index_type *, ANSIBuf*); void linebuf_mark_line_dirty(LineBuf *self, index_type y); void linebuf_mark_line_clean(LineBuf *self, index_type y); void linebuf_mark_line_as_not_continued(LineBuf *self, index_type y); diff --git a/kitty/screen.c b/kitty/screen.c index e0a8e1a0d..a8adb50e1 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -204,11 +204,22 @@ realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns, ANSIBuf *a return ans; } + +typedef struct CursorTrack { + index_type num_content_lines; + bool is_beyond_content; + struct { index_type x, y; } before; + struct { index_type x, y; } after; + struct { index_type x, y; } temp; +} CursorTrack; + static inline LineBuf* -realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *nclb, index_type *ncla, HistoryBuf *hb, index_type *x, index_type *y, ANSIBuf *as_ansi_buf) { +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); if (ans == NULL) { PyErr_NoMemory(); return NULL; } - linebuf_rewrap(old, ans, nclb, ncla, hb, x, y, as_ansi_buf); + a->temp.x = a->before.x; a->temp.y = a->before.y; + b->temp.x = b->before.x; b->temp.y = b->before.y; + linebuf_rewrap(old, ans, nclb, ncla, hb, &a->temp.x, &a->temp.y, &b->temp.x, &b->temp.y, as_ansi_buf); return ans; } @@ -263,21 +274,21 @@ index_selection(const Screen *self, Selections *selections, bool up) { self->is_dirty = true; \ index_selection(self, &self->selections, false); - static bool screen_resize(Screen *self, unsigned int lines, unsigned int columns) { if (self->overlay_line.is_active) deactivate_overlay_line(self); lines = MAX(1u, lines); columns = MAX(1u, columns); bool is_main = self->linebuf == self->main_linebuf; - 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; + index_type num_content_lines_before, num_content_lines_after; unsigned int lines_after_cursor_before_resize = self->lines - self->cursor->y; -#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; \ + CursorTrack cursor = {.before = {self->cursor->x, self->cursor->y}}; + CursorTrack main_saved_cursor = {.before = {self->main_savepoint.cursor.x, self->main_savepoint.cursor.y}}; + CursorTrack alt_saved_cursor = {.before = {self->alt_savepoint.cursor.x, self->alt_savepoint.cursor.y}}; +#define setup_cursor(which) { \ + which.after.x = which.temp.x; which.after.y = which.temp.y; \ + which.is_beyond_content = num_content_lines_before > 0 && self->cursor->y >= num_content_lines_before; \ + which.num_content_lines = num_content_lines_after; \ } // Resize overlay line if (!init_overlay_line(self, columns)) return false; @@ -286,21 +297,19 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { HistoryBuf *nh = realloc_hb(self->historybuf, self->historybuf->ynum, columns, &self->as_ansi_buf); if (nh == NULL) return false; Py_CLEAR(self->historybuf); self->historybuf = nh; - 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, &self->as_ansi_buf); + 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); if (n == NULL) return false; - - Py_CLEAR(self->main_linebuf); self->main_linebuf = n; - if (is_main) setup_cursor(); + if (is_main) setup_cursor(cursor); + setup_cursor(main_saved_cursor); grman_resize(self->main_grman, self->lines, lines, self->columns, columns); // Resize alt linebuf - 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, &self->as_ansi_buf); + n = realloc_lb(self->alt_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, NULL, &cursor, &alt_saved_cursor, &self->as_ansi_buf); if (n == NULL) return false; Py_CLEAR(self->alt_linebuf); self->alt_linebuf = n; - if (!is_main) setup_cursor(); + if (!is_main) setup_cursor(cursor); + setup_cursor(alt_saved_cursor); grman_resize(self->alt_grman, self->lines, lines, self->columns, columns); #undef setup_cursor @@ -320,19 +329,24 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { clear_selection(&self->selections); clear_selection(&self->url_ranges); /* 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; +#define S(c, w) c->x = MIN(w.after.x, self->columns - 1); c->y = MIN(w.after.y, self->lines - 1); + S(self->cursor, cursor); + S((&(self->main_savepoint.cursor)), main_saved_cursor); + S((&(self->alt_savepoint.cursor)), alt_saved_cursor); +#undef S + if (cursor.is_beyond_content) { + self->cursor->y = cursor.num_content_lines; if (self->cursor->y >= self->lines) { self->cursor->y = self->lines - 1; screen_index(self); } } if (is_main && OPT(scrollback_fill_enlarged_window)) { const unsigned int top = 0, bottom = self->lines-1; + Savepoint *sp = is_main ? &self->main_savepoint : &self->alt_savepoint; while (self->cursor->y + 1 < self->lines && self->lines - self->cursor->y > lines_after_cursor_before_resize) { if (!historybuf_pop_line(self->historybuf, self->alt_linebuf->line)) break; INDEX_DOWN; linebuf_copy_line_to(self->main_linebuf, self->alt_linebuf->line, 0); self->cursor->y++; + sp->cursor.y = MIN(sp->cursor.y + 1, self->lines - 1); } } return true;