From a41239fddc9fa24061994e3c777de031b931008e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 25 Feb 2024 22:09:28 -0800 Subject: [PATCH] terminal/new: cursorDown --- src/terminal/Terminal.zig | 4 ++ src/terminal/new/Screen.zig | 8 ++-- src/terminal/new/Terminal.zig | 89 ++++++++++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 53658d1ea..a566eeecf 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -6787,6 +6787,7 @@ test "Terminal: cursorLeft reverse wrap on first row" { try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); } +// X test "Terminal: cursorDown basic" { const alloc = testing.allocator; var t = try init(alloc, 5, 5); @@ -6803,6 +6804,7 @@ test "Terminal: cursorDown basic" { } } +// X test "Terminal: cursorDown above bottom scroll margin" { const alloc = testing.allocator; var t = try init(alloc, 5, 5); @@ -6820,6 +6822,7 @@ test "Terminal: cursorDown above bottom scroll margin" { } } +// X test "Terminal: cursorDown below bottom scroll margin" { const alloc = testing.allocator; var t = try init(alloc, 5, 5); @@ -6838,6 +6841,7 @@ test "Terminal: cursorDown below bottom scroll margin" { } } +// X test "Terminal: cursorDown resets wrap" { const alloc = testing.allocator; var t = try init(alloc, 5, 5); diff --git a/src/terminal/new/Screen.zig b/src/terminal/new/Screen.zig index 8d1484b17..c80db969a 100644 --- a/src/terminal/new/Screen.zig +++ b/src/terminal/new/Screen.zig @@ -145,19 +145,19 @@ pub fn cursorRowUp(self: *Screen, n: size.CellCountInt) *pagepkg.Row { /// Move the cursor down. /// /// Precondition: The cursor is not at the bottom of the screen. -pub fn cursorDown(self: *Screen) void { - assert(self.cursor.y + 1 < self.pages.rows); +pub fn cursorDown(self: *Screen, n: size.CellCountInt) void { + assert(self.cursor.y + n < self.pages.rows); // We move the offset into our page list to the next row and then // get the pointers to the row/cell and set all the cursor state up. - const page_offset = self.cursor.page_offset.forward(1).?; + const page_offset = self.cursor.page_offset.forward(n).?; const page_rac = page_offset.rowAndCell(self.cursor.x); self.cursor.page_offset = page_offset; self.cursor.page_row = page_rac.row; self.cursor.page_cell = page_rac.cell; // Y of course increases - self.cursor.y += 1; + self.cursor.y += n; } /// Move the cursor to some absolute horizontal position. diff --git a/src/terminal/new/Terminal.zig b/src/terminal/new/Terminal.zig index f58815cda..f00655e1b 100644 --- a/src/terminal/new/Terminal.zig +++ b/src/terminal/new/Terminal.zig @@ -603,6 +603,22 @@ pub fn cursorUp(self: *Terminal, count_req: usize) void { self.screen.cursorUp(@intCast(count)); } +/// Move the cursor down amount lines. If amount is greater than the maximum +/// move distance then it is internally adjusted to the maximum. This sequence +/// will not scroll the screen or scroll region. If amount is 0, adjust it to 1. +pub fn cursorDown(self: *Terminal, count_req: usize) void { + // Always resets pending wrap + self.screen.cursor.pending_wrap = false; + + // The max the cursor can move to depends where the cursor currently is + const max = if (self.screen.cursor.y <= self.scrolling_region.bottom) + self.scrolling_region.bottom - self.screen.cursor.y + else + self.rows - self.screen.cursor.y - 1; + const count = @min(max, @max(count_req, 1)); + self.screen.cursorDown(@intCast(count)); +} + /// Move the cursor to the left amount cells. If amount is 0, adjust it to 1. pub fn cursorLeft(self: *Terminal, count_req: usize) void { // Wrapping behavior depends on various terminal modes @@ -775,7 +791,7 @@ pub fn index(self: *Terminal) !void { // We only move down if we're not already at the bottom of // the screen. if (self.screen.cursor.y < self.rows - 1) { - self.screen.cursorDown(); + self.screen.cursorDown(1); } return; @@ -805,7 +821,7 @@ pub fn index(self: *Terminal) !void { // Increase cursor by 1, maximum to bottom of scroll region if (self.screen.cursor.y < self.scrolling_region.bottom) { - self.screen.cursorDown(); + self.screen.cursorDown(1); } } @@ -3576,6 +3592,75 @@ test "Terminal: cursorLeft reverse wrap on first row" { try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); } +test "Terminal: cursorDown basic" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 5); + defer t.deinit(alloc); + + try t.print('A'); + t.cursorDown(10); + try t.print('X'); + + { + const str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("A\n\n\n\n X", str); + } +} + +test "Terminal: cursorDown above bottom scroll margin" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 5); + defer t.deinit(alloc); + + t.setTopAndBottomMargin(1, 3); + try t.print('A'); + t.cursorDown(10); + try t.print('X'); + + { + const str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("A\n\n X", str); + } +} + +test "Terminal: cursorDown below bottom scroll margin" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 5); + defer t.deinit(alloc); + + t.setTopAndBottomMargin(1, 3); + try t.print('A'); + t.setCursorPos(4, 1); + t.cursorDown(10); + try t.print('X'); + + { + const str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("A\n\n\n\nX", str); + } +} + +test "Terminal: cursorDown resets wrap" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 5); + defer t.deinit(alloc); + + for ("ABCDE") |c| try t.print(c); + try testing.expect(t.screen.cursor.pending_wrap); + t.cursorDown(1); + try testing.expect(!t.screen.cursor.pending_wrap); + try t.print('X'); + + { + const str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("ABCDE\n X", str); + } +} + test "Terminal: deleteLines simple" { const alloc = testing.allocator; var t = try init(alloc, 5, 5);