terminal: resize page on unique style per cell

This commit is contained in:
Mitchell Hashimoto
2024-03-11 19:18:27 -07:00
parent 98b16930c3
commit 5e68bc60e0
2 changed files with 50 additions and 3 deletions

View File

@ -646,9 +646,15 @@ pub fn clearCells(
// Slow path: we need to lookup this style so we can decrement
// the ref count. Since we've already loaded everything, we also
// just go ahead and GC it if it reaches zero, too.
if (page.styles.lookupId(page.memory, cell.style_id)) |prev_style| {
if (page.styles.lookupId(
page.memory,
cell.style_id,
)) |prev_style| {
// Below upsert can't fail because it should already be present
const md = page.styles.upsert(page.memory, prev_style.*) catch unreachable;
const md = page.styles.upsert(
page.memory,
prev_style.*,
) catch unreachable;
assert(md.ref > 0);
md.ref -= 1;
if (md.ref == 0) page.styles.remove(page.memory, cell.style_id);
@ -962,7 +968,30 @@ pub fn manualStyleUpdate(self: *Screen) !void {
// if that makes a meaningful difference. Our priority is to keep print
// fast because setting a ton of styles that do nothing is uncommon
// and weird.
const md = try page.styles.upsert(page.memory, self.cursor.style);
const md = page.styles.upsert(
page.memory,
self.cursor.style,
) catch |err| switch (err) {
// Our style map is full. Let's allocate a new page by doubling
// the size and then try again.
error.OutOfMemory => md: {
const node = try self.pages.adjustCapacity(
self.cursor.page_pin.page,
.{ .styles = page.capacity.styles * 2 },
);
// Since this modifies our cursor page, we need to reload
self.cursorReload();
page = &node.data;
break :md try page.styles.upsert(
page.memory,
self.cursor.style,
);
},
error.Overflow => return err, // TODO
};
self.cursor.style_id = md.id;
self.cursor.style_ref = &md.ref;
}

View File

@ -2264,6 +2264,24 @@ test "Terminal: input that forces scroll" {
}
}
test "Terminal: input unique style per cell" {
const alloc = testing.allocator;
var t = try init(alloc, 30, 30);
defer t.deinit(alloc);
for (0..t.rows) |y| {
for (0..t.cols) |x| {
t.setCursorPos(y, x);
try t.setAttribute(.{ .direct_color_bg = .{
.r = @intCast(x),
.g = @intCast(y),
.b = 0,
} });
try t.print('x');
}
}
}
test "Terminal: zero-width character at start" {
var t = try init(testing.allocator, 80, 80);
defer t.deinit(testing.allocator);