terminal: clear spacer heads on growing cols w/o reflow

This commit is contained in:
Mitchell Hashimoto
2024-03-25 09:42:05 -07:00
parent 33ede13072
commit 9ee0b23ef7
2 changed files with 98 additions and 18 deletions

View File

@ -4826,6 +4826,78 @@ test "PageList resize (no reflow) more cols" {
} }
} }
test "PageList resize (no reflow) more cols with spacer head" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 2, 3, 0);
defer s.deinit();
{
try testing.expect(s.pages.first == s.pages.last);
const page = &s.pages.first.?.data;
{
const rac = page.getRowAndCell(0, 0);
rac.row.wrap = true;
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = 'x' },
};
}
{
const rac = page.getRowAndCell(1, 0);
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = ' ' },
.wide = .spacer_head,
};
}
{
const rac = page.getRowAndCell(0, 1);
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = '😀' },
.wide = .wide,
};
}
{
const rac = page.getRowAndCell(1, 1);
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = ' ' },
.wide = .spacer_tail,
};
}
}
// Resize
try s.resize(.{ .cols = 3, .reflow = false });
try testing.expectEqual(@as(usize, 3), s.cols);
try testing.expectEqual(@as(usize, 3), s.totalRows());
{
try testing.expect(s.pages.first == s.pages.last);
const page = &s.pages.first.?.data;
{
const rac = page.getRowAndCell(0, 0);
try testing.expectEqual(@as(u21, 'x'), rac.cell.content.codepoint);
try testing.expectEqual(pagepkg.Cell.Wide.narrow, rac.cell.wide);
// try testing.expect(!rac.row.wrap);
}
{
const rac = page.getRowAndCell(1, 0);
try testing.expectEqual(@as(u21, ' '), rac.cell.content.codepoint);
try testing.expectEqual(pagepkg.Cell.Wide.narrow, rac.cell.wide);
}
{
const rac = page.getRowAndCell(2, 0);
try testing.expectEqual(@as(u21, 0), rac.cell.content.codepoint);
try testing.expectEqual(pagepkg.Cell.Wide.narrow, rac.cell.wide);
}
}
}
// This test is a bit convoluted so I want to explain: what we are trying // This test is a bit convoluted so I want to explain: what we are trying
// to verify here is that when we increase cols such that our rows per page // to verify here is that when we increase cols such that our rows per page
// shrinks, we don't fragment our rows across many pages because this ends // shrinks, we don't fragment our rows across many pages because this ends

View File

@ -494,26 +494,34 @@ pub const Page = struct {
// If we have no managed memory in the row, we can just copy. // If we have no managed memory in the row, we can just copy.
if (!dst_row.grapheme and !dst_row.styled) { if (!dst_row.grapheme and !dst_row.styled) {
fastmem.copy(Cell, cells, other_cells); fastmem.copy(Cell, cells, other_cells);
return; } else {
// We have managed memory, so we have to do a slower copy to
// get all of that right.
for (cells, other_cells) |*dst_cell, *src_cell| {
dst_cell.* = src_cell.*;
if (src_cell.hasGrapheme()) {
// To prevent integrity checks flipping
if (comptime std.debug.runtime_safety) dst_cell.style_id = style.default_id;
dst_cell.content_tag = .codepoint; // required for appendGrapheme
const cps = other.lookupGrapheme(src_cell).?;
for (cps) |cp| try self.appendGrapheme(dst_row, dst_cell, cp);
}
if (src_cell.style_id != style.default_id) {
const other_style = other.styles.lookupId(other.memory, src_cell.style_id).?.*;
const md = try self.styles.upsert(self.memory, other_style);
md.ref += 1;
dst_cell.style_id = md.id;
}
}
} }
// We have managed memory, so we have to do a slower copy to // If we are growing columns, then we need to ensure spacer heads
// get all of that right. // are cleared.
for (cells, other_cells) |*dst_cell, *src_cell| { if (self.size.cols > other.size.cols) {
dst_cell.* = src_cell.*; const last = &cells[other.size.cols - 1];
if (src_cell.hasGrapheme()) { if (last.wide == .spacer_head) {
// To prevent integrity checks flipping last.wide = .narrow;
if (comptime std.debug.runtime_safety) dst_cell.style_id = style.default_id;
dst_cell.content_tag = .codepoint; // required for appendGrapheme
const cps = other.lookupGrapheme(src_cell).?;
for (cps) |cp| try self.appendGrapheme(dst_row, dst_cell, cp);
}
if (src_cell.style_id != style.default_id) {
const other_style = other.styles.lookupId(other.memory, src_cell.style_id).?.*;
const md = try self.styles.upsert(self.memory, other_style);
md.ref += 1;
dst_cell.style_id = md.id;
} }
} }