When reflowing the screen, also reflow the saved cursor position

This commit is contained in:
Kovid Goyal 2021-06-03 15:35:48 +05:30
parent c60a941d1b
commit 4ab299d0af
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 42 additions and 27 deletions

View File

@ -544,7 +544,7 @@ copy_old(LineBuf *self, PyObject *y) {
#include "rewrap.h" #include "rewrap.h"
void 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; index_type first, i;
bool is_empty = true; bool is_empty = true;
@ -574,9 +574,10 @@ linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_befo
return; 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); rewrap_inner(self, other, first + 1, historybuf, (TrackCursor*)tcarr, as_ansi_buf);
*track_x = tcarr[0].x; *track_y = tcarr[0].y; *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; *num_content_lines_after = other->line->ynum + 1;
for (i = 0; i < *num_content_lines_after; i++) other->line_attrs[i] |= TEXT_DIRTY_MASK; for (i = 0; i < *num_content_lines_after; i++) other->line_attrs[i] |= TEXT_DIRTY_MASK;
*num_content_lines_before = first + 1; *num_content_lines_before = first + 1;
@ -589,9 +590,9 @@ rewrap(LineBuf *self, PyObject *args) {
unsigned int nclb, ncla; unsigned int nclb, ncla;
if (!PyArg_ParseTuple(args, "O!O!", &LineBuf_Type, &other, &HistoryBuf_Type, &historybuf)) return NULL; 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}; 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); free(as_ansi_buf.buf);
return Py_BuildValue("II", nclb, ncla); return Py_BuildValue("II", nclb, ncla);

View File

@ -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_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom);
void linebuf_copy_line_to(LineBuf *, Line *, index_type); void linebuf_copy_line_to(LineBuf *, Line *, index_type);
void linebuf_set_attribute(LineBuf *, unsigned int , unsigned int ); 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_dirty(LineBuf *self, index_type y);
void linebuf_mark_line_clean(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); void linebuf_mark_line_as_not_continued(LineBuf *self, index_type y);

View File

@ -204,11 +204,22 @@ realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns, ANSIBuf *a
return ans; 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* 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); LineBuf *ans = alloc_linebuf(lines, columns);
if (ans == NULL) { PyErr_NoMemory(); return NULL; } 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; return ans;
} }
@ -263,21 +274,21 @@ index_selection(const Screen *self, Selections *selections, bool up) {
self->is_dirty = true; \ self->is_dirty = true; \
index_selection(self, &self->selections, false); index_selection(self, &self->selections, false);
static bool static bool
screen_resize(Screen *self, unsigned int lines, unsigned int columns) { screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
if (self->overlay_line.is_active) deactivate_overlay_line(self); if (self->overlay_line.is_active) deactivate_overlay_line(self);
lines = MAX(1u, lines); columns = MAX(1u, columns); lines = MAX(1u, lines); columns = MAX(1u, columns);
bool is_main = self->linebuf == self->main_linebuf; bool is_main = self->linebuf == self->main_linebuf;
index_type num_content_lines_before, num_content_lines_after, num_content_lines; index_type num_content_lines_before, num_content_lines_after;
unsigned int cursor_x = 0, cursor_y = 0;
bool cursor_is_beyond_content = false;
unsigned int lines_after_cursor_before_resize = self->lines - self->cursor->y; unsigned int lines_after_cursor_before_resize = self->lines - self->cursor->y;
#define setup_cursor() { \ CursorTrack cursor = {.before = {self->cursor->x, self->cursor->y}};
cursor_x = x; cursor_y = y; \ CursorTrack main_saved_cursor = {.before = {self->main_savepoint.cursor.x, self->main_savepoint.cursor.y}};
cursor_is_beyond_content = num_content_lines_before > 0 && self->cursor->y >= num_content_lines_before; \ CursorTrack alt_saved_cursor = {.before = {self->alt_savepoint.cursor.x, self->alt_savepoint.cursor.y}};
num_content_lines = num_content_lines_after; \ #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 // Resize overlay line
if (!init_overlay_line(self, columns)) return false; 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); HistoryBuf *nh = realloc_hb(self->historybuf, self->historybuf->ynum, columns, &self->as_ansi_buf);
if (nh == NULL) return false; if (nh == NULL) return false;
Py_CLEAR(self->historybuf); self->historybuf = nh; 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, &cursor, &main_saved_cursor, &self->as_ansi_buf);
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);
if (n == NULL) return false; if (n == NULL) return false;
Py_CLEAR(self->main_linebuf); self->main_linebuf = n; 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); grman_resize(self->main_grman, self->lines, lines, self->columns, columns);
// Resize alt linebuf // 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, &cursor, &alt_saved_cursor, &self->as_ansi_buf);
n = realloc_lb(self->alt_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, NULL, &x, &y, &self->as_ansi_buf);
if (n == NULL) return false; if (n == NULL) return false;
Py_CLEAR(self->alt_linebuf); self->alt_linebuf = n; 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); grman_resize(self->alt_grman, self->lines, lines, self->columns, columns);
#undef setup_cursor #undef setup_cursor
@ -320,19 +329,24 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
clear_selection(&self->selections); clear_selection(&self->selections);
clear_selection(&self->url_ranges); 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); */ /* 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); #define S(c, w) c->x = MIN(w.after.x, self->columns - 1); c->y = MIN(w.after.y, self->lines - 1);
self->cursor->y = MIN(cursor_y, self->lines - 1); S(self->cursor, cursor);
if (cursor_is_beyond_content) { S((&(self->main_savepoint.cursor)), main_saved_cursor);
self->cursor->y = num_content_lines; 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 (self->cursor->y >= self->lines) { self->cursor->y = self->lines - 1; screen_index(self); }
} }
if (is_main && OPT(scrollback_fill_enlarged_window)) { if (is_main && OPT(scrollback_fill_enlarged_window)) {
const unsigned int top = 0, bottom = self->lines-1; 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) { 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; if (!historybuf_pop_line(self->historybuf, self->alt_linebuf->line)) break;
INDEX_DOWN; INDEX_DOWN;
linebuf_copy_line_to(self->main_linebuf, self->alt_linebuf->line, 0); linebuf_copy_line_to(self->main_linebuf, self->alt_linebuf->line, 0);
self->cursor->y++; self->cursor->y++;
sp->cursor.y = MIN(sp->cursor.y + 1, self->lines - 1);
} }
} }
return true; return true;