diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index dd1543202..def46ee01 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -1976,13 +1976,17 @@ pub fn eraseRows( while (it.next()) |chunk| { // If the chunk is a full page, deinit thit page and remove it from // the linked list. - if (chunk.fullPage()) full_page: { + if (chunk.fullPage()) { // 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. + // page so to handle this we reinit this page, set it to zero + // size which will let us grow our active area back. if (chunk.page.next == null and chunk.page.prev == null) { - break :full_page; + const page = &chunk.page.data; + erased += page.size.rows; + page.reinit(); + page.size.rows = 0; + break; } self.erasePage(chunk.page); diff --git a/src/terminal/page.zig b/src/terminal/page.zig index 3fee11a0a..ea0192b33 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -175,7 +175,15 @@ pub const Page = struct { self.* = undefined; } + /// Reinitialize the page with the same capacity. + pub fn reinit(self: *Page) void { + @memset(self.memory, 0); + self.* = initBuf(OffsetBuf.init(self.memory), layout(self.capacity)); + } + pub const IntegrityError = error{ + ZeroRowCount, + ZeroColCount, UnmarkedGraphemeRow, MissingGraphemeData, InvalidGraphemeCount, @@ -212,6 +220,15 @@ pub const Page = struct { // used for the same reason as styles above. // + if (self.size.rows == 0) { + log.warn("page integrity violation zero row count", .{}); + return IntegrityError.ZeroRowCount; + } + if (self.size.cols == 0) { + log.warn("page integrity violation zero col count", .{}); + return IntegrityError.ZeroColCount; + } + var arena = ArenaAllocator.init(alloc_gpa); defer arena.deinit(); const alloc = arena.allocator(); @@ -1742,3 +1759,31 @@ test "Page verifyIntegrity styles ref count mismatch" { page.verifyIntegrity(testing.allocator), ); } + +test "Page verifyIntegrity zero rows" { + var page = try Page.init(.{ + .cols = 10, + .rows = 10, + .styles = 8, + }); + defer page.deinit(); + page.size.rows = 0; + try testing.expectError( + Page.IntegrityError.ZeroRowCount, + page.verifyIntegrity(testing.allocator), + ); +} + +test "Page verifyIntegrity zero cols" { + var page = try Page.init(.{ + .cols = 10, + .rows = 10, + .styles = 8, + }); + defer page.deinit(); + page.size.cols = 0; + try testing.expectError( + Page.IntegrityError.ZeroColCount, + page.verifyIntegrity(testing.allocator), + ); +}