mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-18 14:34:52 +02:00
Scrollback filling should happen after cursor position is finalized
This commit is contained in:
@@ -212,6 +212,33 @@ realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *n
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
is_selection_empty(const Selection *s) {
|
||||||
|
int start_y = (int)s->start.y - (int)s->start_scrolled_by, end_y = (int)s->end.y - (int)s->end_scrolled_by;
|
||||||
|
return s->start.x == s->end.x && s->start.in_left_half_of_cell == s->end.in_left_half_of_cell && start_y == end_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
index_selection(const Screen *self, Selections *selections, bool up) {
|
||||||
|
for (size_t i = 0; i < selections->count; i++) {
|
||||||
|
Selection *s = selections->items + i;
|
||||||
|
if (!is_selection_empty(s)) {
|
||||||
|
if (up) {
|
||||||
|
if (s->start.y == 0) s->start_scrolled_by += 1;
|
||||||
|
else s->start.y--;
|
||||||
|
if (s->end.y == 0) s->end_scrolled_by += 1;
|
||||||
|
else s->end.y--;
|
||||||
|
} else {
|
||||||
|
if (s->start.y >= self->lines - 1) s->start_scrolled_by -= 1;
|
||||||
|
else s->start.y++;
|
||||||
|
if (s->end.y >= self->lines - 1) s->end_scrolled_by -= 1;
|
||||||
|
else s->end.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define INDEX_GRAPHICS(amtv) { \
|
#define INDEX_GRAPHICS(amtv) { \
|
||||||
bool is_main = self->linebuf == self->main_linebuf; \
|
bool is_main = self->linebuf == self->main_linebuf; \
|
||||||
static ScrollData s; \
|
static ScrollData s; \
|
||||||
@@ -221,6 +248,16 @@ realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *n
|
|||||||
grman_scroll_images(self->grman, &s, self->cell_size); \
|
grman_scroll_images(self->grman, &s, self->cell_size); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define INDEX_DOWN \
|
||||||
|
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
|
||||||
|
linebuf_reverse_index(self->linebuf, top, bottom); \
|
||||||
|
linebuf_clear_line(self->linebuf, top); \
|
||||||
|
INDEX_GRAPHICS(1) \
|
||||||
|
self->is_dirty = true; \
|
||||||
|
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);
|
||||||
@@ -247,19 +284,11 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
|||||||
if (n == NULL) return false;
|
if (n == NULL) return false;
|
||||||
|
|
||||||
|
|
||||||
|
int lines_to_fill = -1;
|
||||||
if (is_main && OPT(scrollback_fill_enlarged_window)) {
|
if (is_main && OPT(scrollback_fill_enlarged_window)) {
|
||||||
int lines_to_fill = (lines - self->main_linebuf->ynum) + (
|
lines_to_fill = (lines - self->main_linebuf->ynum) + (
|
||||||
linebuf_continued_lines_count(self->main_linebuf, self->cursor->y) - linebuf_continued_lines_count(n, y));
|
linebuf_continued_lines_count(self->main_linebuf, self->cursor->y) - linebuf_continued_lines_count(n, y));
|
||||||
const unsigned int top = 0, bottom = lines-1;
|
|
||||||
Line last_history_line = {.xnum=self->historybuf->xnum};
|
|
||||||
while (lines_to_fill-- > 0) {
|
|
||||||
if (!historybuf_pop_line(self->historybuf, &last_history_line)) break;
|
|
||||||
linebuf_reverse_index(n, top, bottom);
|
|
||||||
INDEX_GRAPHICS(1);
|
|
||||||
linebuf_add_line_to_top(n, &last_history_line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
grman_resize(self->main_grman, self->lines, lines, self->columns, columns);
|
grman_resize(self->main_grman, self->lines, lines, self->columns, columns);
|
||||||
@@ -295,6 +324,14 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
|||||||
self->cursor->y = num_content_lines;
|
self->cursor->y = 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 (lines_to_fill > 0) {
|
||||||
|
const unsigned int top = 0, bottom = self->lines-1;
|
||||||
|
while (lines_to_fill-- > 0) {
|
||||||
|
if (!historybuf_pop_line(self->historybuf, self->alt_linebuf->line)) break;
|
||||||
|
INDEX_DOWN;
|
||||||
|
linebuf_add_line_to_top(self->main_linebuf, self->alt_linebuf->line);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,12 +431,6 @@ move_widened_char(Screen *self, CPUCell* cpu_cell, GPUCell *gpu_cell, index_type
|
|||||||
*dest_gpu = src_gpu;
|
*dest_gpu = src_gpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
is_selection_empty(const Selection *s) {
|
|
||||||
int start_y = (int)s->start.y - (int)s->start_scrolled_by, end_y = (int)s->end.y - (int)s->end_scrolled_by;
|
|
||||||
return s->start.x == s->end.x && s->start.in_left_half_of_cell == s->end.in_left_half_of_cell && start_y == end_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
selection_has_screen_line(const Selections *selections, const int y) {
|
selection_has_screen_line(const Selections *selections, const int y) {
|
||||||
for (size_t i = 0; i < selections->count; i++) {
|
for (size_t i = 0; i < selections->count; i++) {
|
||||||
@@ -1058,26 +1089,6 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
index_selection(const Screen *self, Selections *selections, bool up) {
|
|
||||||
for (size_t i = 0; i < selections->count; i++) {
|
|
||||||
Selection *s = selections->items + i;
|
|
||||||
if (!is_selection_empty(s)) {
|
|
||||||
if (up) {
|
|
||||||
if (s->start.y == 0) s->start_scrolled_by += 1;
|
|
||||||
else s->start.y--;
|
|
||||||
if (s->end.y == 0) s->end_scrolled_by += 1;
|
|
||||||
else s->end.y--;
|
|
||||||
} else {
|
|
||||||
if (s->start.y >= self->lines - 1) s->start_scrolled_by -= 1;
|
|
||||||
else s->start.y++;
|
|
||||||
if (s->end.y >= self->lines - 1) s->end_scrolled_by -= 1;
|
|
||||||
else s->end.y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INDEX_UP \
|
#define INDEX_UP \
|
||||||
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
|
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
|
||||||
linebuf_index(self->linebuf, top, bottom); \
|
linebuf_index(self->linebuf, top, bottom); \
|
||||||
@@ -1111,14 +1122,6 @@ screen_scroll(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INDEX_DOWN \
|
|
||||||
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
|
|
||||||
linebuf_reverse_index(self->linebuf, top, bottom); \
|
|
||||||
linebuf_clear_line(self->linebuf, top); \
|
|
||||||
INDEX_GRAPHICS(1) \
|
|
||||||
self->is_dirty = true; \
|
|
||||||
index_selection(self, &self->selections, false);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_reverse_index(Screen *self) {
|
screen_reverse_index(Screen *self) {
|
||||||
// Move cursor up one line, scrolling screen if needed
|
// Move cursor up one line, scrolling screen if needed
|
||||||
|
|||||||
@@ -91,14 +91,10 @@ class BaseTest(TestCase):
|
|||||||
options = Options(merge_configs(defaults._asdict(), final_options))
|
options = Options(merge_configs(defaults._asdict(), final_options))
|
||||||
set_options(options)
|
set_options(options)
|
||||||
|
|
||||||
def create_screen(self, cols=5, lines=5, scrollback=5, cell_width=10, cell_height=20, options=None, content=()):
|
def create_screen(self, cols=5, lines=5, scrollback=5, cell_width=10, cell_height=20, options=None):
|
||||||
self.set_options(options)
|
self.set_options(options)
|
||||||
c = Callbacks()
|
c = Callbacks()
|
||||||
s = Screen(c, lines, cols, scrollback, cell_width, cell_height, 0, c)
|
s = Screen(c, lines, cols, scrollback, cell_width, cell_height, 0, c)
|
||||||
for content_line in content:
|
|
||||||
s.draw(content_line)
|
|
||||||
s.linefeed()
|
|
||||||
s.carriage_return()
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def assertEqualAttributes(self, c1, c2):
|
def assertEqualAttributes(self, c1, c2):
|
||||||
|
|||||||
@@ -305,45 +305,45 @@ class TestScreen(BaseTest):
|
|||||||
|
|
||||||
def test_scrollback_fill_after_resize(self):
|
def test_scrollback_fill_after_resize(self):
|
||||||
def prepare_screen(content=()):
|
def prepare_screen(content=()):
|
||||||
return self.create_screen(
|
ans = self.create_screen(options={'scrollback_fill_enlarged_window': True})
|
||||||
lines=5,
|
for line in content:
|
||||||
cols=5,
|
ans.draw(line)
|
||||||
options={'scrollback_fill_enlarged_window': True},
|
ans.linefeed()
|
||||||
content=content,
|
ans.carriage_return()
|
||||||
)
|
return ans
|
||||||
|
|
||||||
def assert_lines(lines, s):
|
def assert_lines(*lines):
|
||||||
return self.ae(lines, str(s.linebuf).split("\n"))
|
return self.ae(lines, tuple(str(s.line(i)) for i in range(s.lines)))
|
||||||
|
|
||||||
# Height increased, width unchanged → pull down lines to fill new space at the top
|
# Height increased, width unchanged → pull down lines to fill new space at the top
|
||||||
s = prepare_screen([str(i) for i in range(0, 6)])
|
s = prepare_screen(map(str, range(6)))
|
||||||
assert_lines(['2', '3', '4', '5', ''], s)
|
assert_lines('2', '3', '4', '5', '')
|
||||||
s.resize(7, s.columns)
|
s.resize(7, s.columns)
|
||||||
assert_lines(['0', '1', '2', '3', '4', '5', ''], s)
|
assert_lines('0', '1', '2', '3', '4', '5', '')
|
||||||
|
|
||||||
# Height increased, width increased → rewrap, pull down
|
# Height increased, width increased → rewrap, pull down
|
||||||
s = prepare_screen(['0', '1', '2', '3' * 15])
|
s = prepare_screen(['0', '1', '2', '3' * 15])
|
||||||
assert_lines(['2', '33333', '33333', '33333', ''], s)
|
assert_lines('2', '33333', '33333', '33333', '')
|
||||||
s.resize(7, 12)
|
s.resize(7, 12)
|
||||||
assert_lines(['0', '1', '2', '333333333333', '333', '', ''], s)
|
assert_lines('0', '1', '2', '333333333333', '333', '', '')
|
||||||
|
|
||||||
# Height increased, width decreased → rewrap, pull down if possible
|
# Height increased, width decreased → rewrap, pull down if possible
|
||||||
s = prepare_screen(['0', '1', '2', '3' * 5])
|
s = prepare_screen(['0', '1', '2', '3' * 5])
|
||||||
assert_lines(['0', '1', '2', '33333', ''], s)
|
assert_lines('0', '1', '2', '33333', '')
|
||||||
s.resize(6, 4)
|
s.resize(6, 4)
|
||||||
assert_lines(['0', '1', '2', '3333', '3', ''], s)
|
assert_lines('0', '1', '2', '3333', '3', '')
|
||||||
|
|
||||||
# Height unchanged, width increased → rewrap, pull down if possible
|
# Height unchanged, width increased → rewrap, pull down if possible
|
||||||
s = prepare_screen(['0', '1', '2', '3' * 15])
|
s = prepare_screen(['0', '1', '2', '3' * 15])
|
||||||
assert_lines(['2', '33333', '33333', '33333', ''], s)
|
assert_lines('2', '33333', '33333', '33333', '')
|
||||||
s.resize(s.lines, 12)
|
s.resize(s.lines, 12)
|
||||||
assert_lines(['1', '2', '333333333333', '333', ''], s)
|
assert_lines('1', '2', '333333333333', '333', '')
|
||||||
|
|
||||||
# Height decreased, width increased → rewrap, pull down if possible
|
# Height decreased, width increased → rewrap, pull down if possible
|
||||||
s = prepare_screen(['0', '1', '2', '3' * 15])
|
s = prepare_screen(['0', '1', '2', '3' * 15])
|
||||||
assert_lines(['2', '33333', '33333', '33333', ''], s)
|
assert_lines('2', '33333', '33333', '33333', '')
|
||||||
s.resize(4, 12)
|
s.resize(4, 12)
|
||||||
assert_lines(['2', '333333333333', '333', ''], s)
|
assert_lines('2', '333333333333', '333', '')
|
||||||
|
|
||||||
def test_tab_stops(self):
|
def test_tab_stops(self):
|
||||||
# Taken from vttest/main.c
|
# Taken from vttest/main.c
|
||||||
|
|||||||
Reference in New Issue
Block a user