terminal: copy grapheme map when resizing and ensure proper cleanup

This commit is contained in:
Mitchell Hashimoto
2022-11-26 17:33:52 -08:00
parent e877dbf861
commit d64b0e371e

View File

@ -774,7 +774,10 @@ pub fn init(
pub fn deinit(self: *Screen) void {
self.storage.deinit(self.alloc);
self.deinitGraphemes();
}
fn deinitGraphemes(self: *Screen) void {
var grapheme_it = self.graphemes.valueIterator();
while (grapheme_it.next()) |data| data.deinit(self.alloc);
self.graphemes.deinit(self.alloc);
@ -1684,6 +1687,12 @@ pub fn resizeWithoutReflow(self: *Screen, rows: usize, cols: usize) !void {
self.viewport = 0;
self.history = 0;
// Reset our grapheme map and ensure the old one is deallocated
// on success.
self.graphemes = .{};
errdefer self.deinitGraphemes();
defer old.deinitGraphemes();
// Rewrite all our rows
var y: usize = 0;
var row_it = old.rowIterator(.screen);
@ -3567,6 +3576,47 @@ test "Screen: resize (no reflow) empty screen" {
try testing.expectEqual(@as(usize, 10), s.rowsCapacity());
}
test "Screen: resize (no reflow) grapheme copy" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 3, 5, 0);
defer s.deinit();
const str = "1ABCD\n2EFGH\n3IJKL";
try s.testWriteString(str);
// Attach graphemes to all the columns
{
var iter = s.rowIterator(.viewport);
while (iter.next()) |row| {
var col: usize = 0;
while (col < s.cols) : (col += 1) {
try row.attachGrapheme(col, 0xFE0F);
}
}
}
// Clear dirty rows
{
var iter = s.rowIterator(.viewport);
while (iter.next()) |row| row.setDirty(false);
}
// Resize
try s.resizeWithoutReflow(10, 5);
{
var contents = try s.testString(alloc, .viewport);
defer alloc.free(contents);
try testing.expectEqualStrings(str, contents);
}
// Everything should be dirty
{
var iter = s.rowIterator(.viewport);
while (iter.next()) |row| try testing.expect(row.isDirty());
}
}
test "Screen: resize more rows no scrollback" {
const testing = std.testing;
const alloc = testing.allocator;