insertLines with scroll region support

This commit is contained in:
Mitchell Hashimoto
2022-05-15 21:17:27 -07:00
parent 7d2b722066
commit 5d34f171a0

View File

@ -438,40 +438,32 @@ pub fn linefeed(self: *Terminal, alloc: Allocator) void {
/// ///
/// Moves the cursor to the left margin. /// Moves the cursor to the left margin.
pub fn insertLines(self: *Terminal, alloc: Allocator, count: usize) !void { pub fn insertLines(self: *Terminal, alloc: Allocator, count: usize) !void {
// TODO: scroll region bounds
if (self.scrolling_region.bottom != self.rows - 1 or
self.scrolling_region.top != 0) @panic("unimplemented");
// Move the cursor to the left margin // Move the cursor to the left margin
self.cursor.x = 0; self.cursor.x = 0;
// Remaining rows from our cursor // Remaining rows from our cursor
const rem = self.rows - (self.cursor.y + 1); const rem = self.scrolling_region.bottom - self.cursor.y + 1;
// If we're trying to insert more than the remaining number of rows, we just // If count is greater than the amount of rows, adjust down.
// erase below and we're done. const adjusted_count = @minimum(count, rem);
if (count >= rem) {
try self.eraseDisplay(alloc, .below);
return;
}
// The the top `scroll_amount` lines need to move to the bottom // The the top `scroll_amount` lines need to move to the bottom
// scroll area. // scroll area. We may have nothing to scroll if we're clearing.
const scroll_amount = rem - count; const scroll_amount = rem - adjusted_count;
var y: usize = self.rows - 1; var y: usize = self.scrolling_region.bottom;
const top = y - scroll_amount - 1; const top = y - scroll_amount;
// Ensure we have the lines populated to the end // Ensure we have the lines populated to the end
_ = try self.getOrPutCell(alloc, 0, y); _ = try self.getOrPutCell(alloc, 0, y);
while (y > top) : (y -= 1) { while (y > top) : (y -= 1) {
self.screen.items[y].deinit(alloc); self.screen.items[y].deinit(alloc);
self.screen.items[y] = self.screen.items[y - count]; self.screen.items[y] = self.screen.items[y - adjusted_count];
self.screen.items[y - count] = .{}; self.screen.items[y - adjusted_count] = .{};
} }
// Insert count blank lines // Insert count blank lines
y = self.cursor.y; y = self.cursor.y;
while (y < self.cursor.y + count) : (y += 1) { while (y < self.cursor.y + adjusted_count) : (y += 1) {
var x: usize = 0; var x: usize = 0;
while (x < self.cols) : (x += 1) { while (x < self.cols) : (x += 1) {
const cell = try self.getOrPutCell(alloc, x, y); const cell = try self.getOrPutCell(alloc, x, y);
@ -825,6 +817,39 @@ test "Terminal: insertLines" {
} }
} }
test "Terminal: insertLines with scroll region" {
const alloc = testing.allocator;
var t = try init(alloc, 2, 6);
defer t.deinit(alloc);
// Initial value
try t.print(alloc, 'A');
t.carriageReturn();
t.linefeed(alloc);
try t.print(alloc, 'B');
t.carriageReturn();
t.linefeed(alloc);
try t.print(alloc, 'C');
t.carriageReturn();
t.linefeed(alloc);
try t.print(alloc, 'D');
t.carriageReturn();
t.linefeed(alloc);
try t.print(alloc, 'E');
t.setScrollingRegion(1, 2);
t.setCursorPos(1, 1);
try t.insertLines(alloc, 1);
try t.print(alloc, 'X');
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings("X\nA\nC\nD\nE", str);
}
}
test "Terminal: insertLines more than remaining" { test "Terminal: insertLines more than remaining" {
const alloc = testing.allocator; const alloc = testing.allocator;
var t = try init(alloc, 2, 5); var t = try init(alloc, 2, 5);
@ -848,8 +873,8 @@ test "Terminal: insertLines more than remaining" {
// Move to row 2 // Move to row 2
t.setCursorPos(2, 1); t.setCursorPos(2, 1);
// Insert two lines // Insert a bunch of lines
try t.insertLines(alloc, 10); try t.insertLines(alloc, 20);
{ {
var str = try t.plainString(testing.allocator); var str = try t.plainString(testing.allocator);