terminal: style needs to be copied to new page on scroll

This commit is contained in:
Mitchell Hashimoto
2024-03-19 12:52:21 -07:00
parent b8d88fd8a2
commit 631fdf00a8
2 changed files with 56 additions and 2 deletions

View File

@ -20,6 +20,8 @@ const Row = pagepkg.Row;
const Cell = pagepkg.Cell; const Cell = pagepkg.Cell;
const Pin = PageList.Pin; const Pin = PageList.Pin;
const log = std.log.scoped(.screen);
/// The general purpose allocator to use for all memory allocations. /// The general purpose allocator to use for all memory allocations.
/// Unfortunately some screen operations do require allocation. /// Unfortunately some screen operations do require allocation.
alloc: Allocator, alloc: Allocator,
@ -524,9 +526,16 @@ pub fn cursorDownScroll(self: *Screen) !void {
} }
} }
// The newly created line needs to be styled according to the bg color
// if it is set.
if (self.cursor.style_id != style.default_id) { if (self.cursor.style_id != style.default_id) {
// We need to ensure our new page has our style.
self.manualStyleUpdate() catch |err| {
// This should never happen because if we're in a new
// page then we should have space for one style.
log.warn("error updating style on scroll err={}", .{err});
};
// The newly created line needs to be styled according to
// the bg color if it is set.
if (self.cursor.style.bgCell()) |blank_cell| { if (self.cursor.style.bgCell()) |blank_cell| {
const cell_current: [*]pagepkg.Cell = @ptrCast(self.cursor.page_cell); const cell_current: [*]pagepkg.Cell = @ptrCast(self.cursor.page_cell);
const cells = cell_current - self.cursor.x; const cells = cell_current - self.cursor.x;
@ -2505,6 +2514,33 @@ test "Screen: scrolling" {
} }
} }
test "Screen: scrolling across pages preserves style" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 10, 3, 1);
defer s.deinit();
try s.setAttribute(.{ .bold = {} });
try s.testWriteString("1ABCD\n2EFGH\n3IJKL");
const start_page = &s.pages.pages.last.?.data;
// Scroll down enough to go to another page
const rem = start_page.capacity.rows - start_page.size.rows + 1;
for (0..rem) |_| try s.cursorDownScroll();
// We need our page to change for this test o make sense. If this
// assertion fails then the bug is in the test: we should be scrolling
// above enough for a new page to show up.
const page = &s.pages.pages.last.?.data;
try testing.expect(start_page != page);
const styleval = page.styles.lookupId(
page.memory,
s.cursor.style_id,
).?;
try testing.expect(styleval.flags.bold);
}
test "Screen: scroll down from 0" { test "Screen: scroll down from 0" {
const testing = std.testing; const testing = std.testing;
const alloc = testing.allocator; const alloc = testing.allocator;

View File

@ -559,6 +559,24 @@ fn printCell(
.protected = self.screen.cursor.protected, .protected = self.screen.cursor.protected,
}; };
if (comptime std.debug.runtime_safety) {
// We've had bugs around this, so let's add an assertion: every
// style we use should be present in the style table.
if (self.screen.cursor.style_id != style.default_id) {
const page = &self.screen.cursor.page_pin.page.data;
if (page.styles.lookupId(
page.memory,
self.screen.cursor.style_id,
) == null) {
log.err("can't find style page={X} id={}", .{
@intFromPtr(&self.screen.cursor.page_pin.page.data),
self.screen.cursor.style_id,
});
@panic("style not found");
}
}
}
// Handle the style ref count handling // Handle the style ref count handling
style_ref: { style_ref: {
if (prev_style_id != style.default_id) { if (prev_style_id != style.default_id) {