From c27b597951820961e65d01a0651469568aad2a12 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 19 May 2017 19:25:41 +0530 Subject: [PATCH] Fix incorrect implementation of the CSI scroll commands I was lazy and just assumed they were n indexes, but they actually scroll the screen without moving the cursor. Fixes #76 --- kitty/data-types.h | 2 ++ kitty/parser.c | 8 ++----- kitty/screen.c | 56 ++++++++++++++++++++++++++++++++++------------ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/kitty/data-types.h b/kitty/data-types.h index 1306b6b8a..0f6137ef4 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -376,6 +376,8 @@ void screen_change_default_color(Screen *self, unsigned int which, uint32_t col) void screen_alignment_display(Screen *self); void screen_reverse_index(Screen *self); void screen_index(Screen *self); +void screen_scroll(Screen *self, unsigned int count); +void screen_reverse_scroll(Screen *self, unsigned int count); void screen_reset(Screen *self); void screen_set_tab_stop(Screen *self); void screen_tab(Screen *self); diff --git a/kitty/parser.c b/kitty/parser.c index b3530a182..ca6195535 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -335,11 +335,7 @@ screen_cursor_up2(Screen *s, unsigned int count) { screen_cursor_up(s, count, fa static inline void screen_cursor_back1(Screen *s, unsigned int count) { screen_cursor_back(s, count, -1); } static inline void -screen_indexn(Screen *s, unsigned int count) { for (index_type i=0; i < MAX(1, count); i++) screen_index(s); } -static inline void screen_tabn(Screen *s, unsigned int count) { for (index_type i=0; i < MAX(1, count); i++) screen_tab(s); } -static inline void -screen_reverse_indexn(Screen *s, unsigned int count) { for (index_type i=0; i < count; i++) screen_reverse_index(s); } static inline void save_cursor(Screen *s, unsigned int UNUSED param, bool private) { if (private) fprintf(stderr, "%s %s", ERROR_PREFIX, "CSI s in private mode not supported"); @@ -488,9 +484,9 @@ dispatch_csi(Screen *screen, PyObject DUMP_UNUSED *dump_callback) { case DECSCUSR: CALL_CSI_HANDLER1M(screen_set_cursor, 1); case SU: - CALL_CSI_HANDLER1(screen_indexn, 1); + CALL_CSI_HANDLER1(screen_scroll, 1); case SD: - CALL_CSI_HANDLER1(screen_reverse_indexn, 1); + CALL_CSI_HANDLER1(screen_reverse_scroll, 1); case DECSTR: if (end_modifier == '$') { // DECRQM diff --git a/kitty/screen.c b/kitty/screen.c index 4af72edcd..a71880eb5 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -582,36 +582,64 @@ screen_cursor_to_column(Screen *self, unsigned int column) { } } +#define INDEX_UP \ + linebuf_index(self->linebuf, top, bottom); \ + if (self->linebuf == self->main_linebuf && bottom == self->lines - 1) { \ + /* Only add to history when no page margins have been set */ \ + linebuf_init_line(self->linebuf, bottom); \ + historybuf_add_line(self->historybuf, self->linebuf->line); \ + tracker_line_added_to_history(self->change_tracker); \ + } \ + linebuf_clear_line(self->linebuf, bottom); \ + if (bottom - top > self->lines - 1) tracker_update_screen(self->change_tracker); \ + else tracker_update_line_range(self->change_tracker, top, bottom); + void screen_index(Screen *self) { // Move cursor down one line, scrolling screen if needed unsigned int top = self->margin_top, bottom = self->margin_bottom; if (self->cursor->y == bottom) { - linebuf_index(self->linebuf, top, bottom); - if (self->linebuf == self->main_linebuf && bottom == self->lines - 1) { - // Only add to history when no page margins have been set - linebuf_init_line(self->linebuf, bottom); - historybuf_add_line(self->historybuf, self->linebuf->line); - tracker_line_added_to_history(self->change_tracker); - } - linebuf_clear_line(self->linebuf, bottom); - if (bottom - top > self->lines - 1) tracker_update_screen(self->change_tracker); - else tracker_update_line_range(self->change_tracker, top, bottom); + INDEX_UP; } else screen_cursor_down(self, 1); } +void +screen_scroll(Screen *self, unsigned int count) { + // Scroll the screen up by count lines, not moving the cursor + count = MIN(self->lines, count); + unsigned int top = self->margin_top, bottom = self->margin_bottom; + while (count > 0) { + count--; + INDEX_UP; + } +} + +#define INDEX_DOWN \ + linebuf_reverse_index(self->linebuf, top, bottom); \ + linebuf_clear_line(self->linebuf, top); \ + if (bottom - top > self->lines - 1) tracker_update_screen(self->change_tracker); \ + else tracker_update_line_range(self->change_tracker, top, bottom); + void screen_reverse_index(Screen *self) { // Move cursor up one line, scrolling screen if needed unsigned int top = self->margin_top, bottom = self->margin_bottom; if (self->cursor->y == top) { - linebuf_reverse_index(self->linebuf, top, bottom); - linebuf_clear_line(self->linebuf, top); - if (bottom - top > self->lines - 1) tracker_update_screen(self->change_tracker); - else tracker_update_line_range(self->change_tracker, top, bottom); + INDEX_DOWN; } else screen_cursor_up(self, 1, false, -1); } +void +screen_reverse_scroll(Screen *self, unsigned int count) { + // Scroll the screen down by count lines, not moving the cursor + count = MIN(self->lines, count); + unsigned int top = self->margin_top, bottom = self->margin_bottom; + while (count > 0) { + count--; + INDEX_DOWN; + } +} + void screen_carriage_return(Screen *self) {