diff --git a/kitty/screen.c b/kitty/screen.c index 30c03d5ae..72c20f13f 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1892,7 +1892,7 @@ screen_is_cursor_visible(const Screen *self) { void screen_backspace(Screen *self) { - screen_cursor_move(self, 1, -1); + screen_cursor_move(self, 1, -1, true); } void @@ -1963,7 +1963,7 @@ screen_set_tab_stop(Screen *self) { } void -screen_cursor_move(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/) { +screen_cursor_move(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/, bool allow_move_to_previous_line) { if (count == 0) count = 1; bool in_margins = cursor_within_margins(self); if (move_direction > 0) { @@ -1980,7 +1980,7 @@ screen_cursor_move(Screen *self, unsigned int count/*=1*/, int move_direction/*= count -= self->cursor->x; self->cursor->x = 0; } else { - if (self->cursor->y == top) count = 0; + if (self->cursor->y == top || !allow_move_to_previous_line) count = 0; else { count--; self->cursor->y--; self->cursor->x = self->columns-1; @@ -1993,7 +1993,7 @@ screen_cursor_move(Screen *self, unsigned int count/*=1*/, int move_direction/*= void screen_cursor_forward(Screen *self, unsigned int count/*=1*/) { - screen_cursor_move(self, count, 1); + screen_cursor_move(self, count, 1, false); } void @@ -4492,7 +4492,7 @@ is_using_alternate_linebuf(Screen *self, PyObject *a UNUSED) { Py_RETURN_FALSE; } -WRAP1E(cursor_move, 1, -1) +WRAP1E(cursor_move, 1, -1, true) WRAP1B(erase_in_line, 0) WRAP1B(erase_in_display, 0) static PyObject* scroll_until_cursor_prompt(Screen *self, PyObject *args) { int b=false; if(!PyArg_ParseTuple(args, "|p", &b)) return NULL; screen_scroll_until_cursor_prompt(self, b); Py_RETURN_NONE; } diff --git a/kitty/screen.h b/kitty/screen.h index 3edebcabd..f9083fa6d 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -187,7 +187,7 @@ void screen_save_modes(Screen *); void screen_save_mode(Screen *, unsigned int); bool write_escape_code_to_child(Screen *self, unsigned char which, const char *data); void screen_cursor_position(Screen*, unsigned int, unsigned int); -void screen_cursor_move(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/); +void screen_cursor_move(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/, bool allow_move_to_previous_line); void screen_erase_in_line(Screen *, unsigned int, bool); void screen_erase_in_display(Screen *, unsigned int, bool); void screen_draw_text(Screen *self, const uint32_t *chars, size_t num_chars); diff --git a/kitty/vt-parser.c b/kitty/vt-parser.c index 3a18fbc80..8a0640297 100644 --- a/kitty/vt-parser.c +++ b/kitty/vt-parser.c @@ -1009,7 +1009,7 @@ parse_sgr(Screen *screen, const uint8_t *buf, unsigned int num, const char *repo static void screen_cursor_up2(Screen *s, unsigned int count) { screen_cursor_up(s, count, false, -1); } static void -screen_cursor_back1(Screen *s, unsigned int count) { screen_cursor_move(s, count, -1); } +screen_cursor_back1(Screen *s, unsigned int count) { screen_cursor_move(s, count, -1, false); } static void screen_tabn(Screen *s, unsigned int count) { for (index_type i=0; i < MAX(1u, count); i++) screen_tab(s); } diff --git a/kitty_tests/screen.py b/kitty_tests/screen.py index aa8c61add..8157d764a 100644 --- a/kitty_tests/screen.py +++ b/kitty_tests/screen.py @@ -555,6 +555,12 @@ class TestScreen(BaseTest): backspace(use_bs) self.ae(str(s.line(0)), q[:-1] + ' ') self.ae(str(s.line(1)), ' ') + # Test that CUB does not move cursor onto previous line + s.reset() + s.draw('a'*s.columns + 'b') + self.ae((s.cursor.x, s.cursor.y), (1, 1)) + parse_bytes(s, b'\x1b[100D') + self.ae((s.cursor.x, s.cursor.y), (0, 1)) def test_margins(self): # Taken from vttest/main.c