terminal: handles eraseRows that erases our full pagelist

This commit is contained in:
Mitchell Hashimoto
2024-03-20 10:20:25 -07:00
parent 29a9d09bbd
commit e64d8f5304

View File

@ -524,6 +524,13 @@ pub const Resize = struct {
/// Resize /// Resize
/// TODO: docs /// TODO: docs
pub fn resize(self: *PageList, opts: Resize) !void { pub fn resize(self: *PageList, opts: Resize) !void {
if (comptime std.debug.runtime_safety) {
// Resize does not work with 0 values, this should be protected
// upstream
if (opts.cols) |v| assert(v > 0);
if (opts.rows) |v| assert(v > 0);
}
if (!opts.reflow) return try self.resizeWithoutReflow(opts); if (!opts.reflow) return try self.resizeWithoutReflow(opts);
// Recalculate our minimum max size. This allows grow to work properly // Recalculate our minimum max size. This allows grow to work properly
@ -1853,7 +1860,15 @@ pub fn eraseRows(
while (it.next()) |chunk| { while (it.next()) |chunk| {
// If the chunk is a full page, deinit thit page and remove it from // If the chunk is a full page, deinit thit page and remove it from
// the linked list. // the linked list.
if (chunk.fullPage()) { if (chunk.fullPage()) full_page: {
// A rare special case is that we're deleting everything
// in our linked list. erasePage requires at least one other
// page so to handle this we break out of this handling and
// do a normal row by row erase.
if (chunk.page.next == null and chunk.page.prev == null) {
break :full_page;
}
self.erasePage(chunk.page); self.erasePage(chunk.page);
erased += chunk.page.data.size.rows; erased += chunk.page.data.size.rows;
continue; continue;
@ -1876,6 +1891,17 @@ pub fn eraseRows(
chunk.page.data.clearCells(src, 0, chunk.page.data.size.cols); chunk.page.data.clearCells(src, 0, chunk.page.data.size.cols);
} }
// Clear our remaining cells that we didn't shift or swapped
// in case we grow back into them.
for (scroll_amount..chunk.page.data.size.rows) |i| {
const row: *Row = &rows[i];
chunk.page.data.clearCells(
row,
0,
chunk.page.data.size.cols,
);
}
// Update any tracked pins to shift their y. If it was in the erased // Update any tracked pins to shift their y. If it was in the erased
// row then we move it to the top of this page. // row then we move it to the top of this page.
var pin_it = self.tracked_pins.keyIterator(); var pin_it = self.tracked_pins.keyIterator();
@ -3972,6 +3998,34 @@ test "PageList erase active regrows automatically" {
try testing.expect(s.totalRows() == s.rows); try testing.expect(s.totalRows() == s.rows);
} }
test "PageList erase a one-row active" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 10, 1, null);
defer s.deinit();
try testing.expectEqual(@as(usize, 1), s.totalPages());
// Write our letter
const page = &s.pages.first.?.data;
for (0..s.rows) |y| {
const rac = page.getRowAndCell(0, y);
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = 'A' },
};
}
s.eraseRows(.{ .active = .{} }, .{ .active = .{} });
try testing.expectEqual(s.rows, s.totalRows());
// The row should be empty
{
const get = s.getCell(.{ .active = .{ .x = 0, .y = 0 } }).?;
try testing.expectEqual(@as(u21, 0), get.cell.content.codepoint);
}
}
test "PageList clone" { test "PageList clone" {
const testing = std.testing; const testing = std.testing;
const alloc = testing.allocator; const alloc = testing.allocator;
@ -4217,6 +4271,40 @@ test "PageList resize (no reflow) less rows" {
} }
} }
test "PageList resize (no reflow) one rows" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 10, 10, 0);
defer s.deinit();
try testing.expectEqual(@as(usize, 10), s.totalRows());
// This is required for our writing below to work
try testing.expect(s.pages.first == s.pages.last);
const page = &s.pages.first.?.data;
// Write into all rows so we don't get trim behavior
for (0..s.rows) |y| {
const rac = page.getRowAndCell(0, y);
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = 'A' },
};
}
// Resize
try s.resize(.{ .rows = 1, .reflow = false });
try testing.expectEqual(@as(usize, 1), s.rows);
try testing.expectEqual(@as(usize, 10), s.totalRows());
{
const pt = s.getCell(.{ .active = .{} }).?.screenPoint();
try testing.expectEqual(point.Point{ .screen = .{
.x = 0,
.y = 9,
} }, pt);
}
}
test "PageList resize (no reflow) less rows cursor on bottom" { test "PageList resize (no reflow) less rows cursor on bottom" {
const testing = std.testing; const testing = std.testing;
const alloc = testing.allocator; const alloc = testing.allocator;