mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-20 02:36:22 +03:00
terminal: PageList support initialization of multi-page viewports
This commit is contained in:
@ -223,30 +223,7 @@ pub fn init(
|
|||||||
// necessary.
|
// necessary.
|
||||||
var pool = try MemoryPool.init(alloc, std.heap.page_allocator, page_preheat);
|
var pool = try MemoryPool.init(alloc, std.heap.page_allocator, page_preheat);
|
||||||
errdefer pool.deinit();
|
errdefer pool.deinit();
|
||||||
|
const page_list, const page_size = try initPages(&pool, cols, rows);
|
||||||
var page = try pool.nodes.create();
|
|
||||||
const page_buf = try pool.pages.create();
|
|
||||||
// no errdefer because the pool deinit will clean these up
|
|
||||||
|
|
||||||
// In runtime safety modes we have to memset because the Zig allocator
|
|
||||||
// interface will always memset to 0xAA for undefined. In non-safe modes
|
|
||||||
// we use a page allocator and the OS guarantees zeroed memory.
|
|
||||||
if (comptime std.debug.runtime_safety) @memset(page_buf, 0);
|
|
||||||
|
|
||||||
// Initialize the first set of pages to contain our viewport so that
|
|
||||||
// the top of the first page is always the active area.
|
|
||||||
page.* = .{
|
|
||||||
.data = Page.initBuf(
|
|
||||||
OffsetBuf.init(page_buf),
|
|
||||||
Page.layout(try std_capacity.adjust(.{ .cols = cols })),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
assert(page.data.capacity.rows >= rows); // todo: handle this
|
|
||||||
page.data.size.rows = rows;
|
|
||||||
|
|
||||||
var page_list: List = .{};
|
|
||||||
page_list.prepend(page);
|
|
||||||
const page_size = page_buf.len;
|
|
||||||
|
|
||||||
// Get our minimum max size, see doc comments for more details.
|
// Get our minimum max size, see doc comments for more details.
|
||||||
const min_max_size = try minMaxSize(cols, rows);
|
const min_max_size = try minMaxSize(cols, rows);
|
||||||
@ -272,6 +249,48 @@ pub fn init(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initPages(
|
||||||
|
pool: *MemoryPool,
|
||||||
|
cols: size.CellCountInt,
|
||||||
|
rows: size.CellCountInt,
|
||||||
|
) !struct { List, usize } {
|
||||||
|
var page_list: List = .{};
|
||||||
|
var page_size: usize = 0;
|
||||||
|
|
||||||
|
// Add pages as needed to create our initial viewport.
|
||||||
|
const cap = try std_capacity.adjust(.{ .cols = cols });
|
||||||
|
var rem = rows;
|
||||||
|
while (rem > 0) {
|
||||||
|
const page = try pool.nodes.create();
|
||||||
|
const page_buf = try pool.pages.create();
|
||||||
|
// no errdefer because the pool deinit will clean these up
|
||||||
|
|
||||||
|
// In runtime safety modes we have to memset because the Zig allocator
|
||||||
|
// interface will always memset to 0xAA for undefined. In non-safe modes
|
||||||
|
// we use a page allocator and the OS guarantees zeroed memory.
|
||||||
|
if (comptime std.debug.runtime_safety) @memset(page_buf, 0);
|
||||||
|
|
||||||
|
// Initialize the first set of pages to contain our viewport so that
|
||||||
|
// the top of the first page is always the active area.
|
||||||
|
page.* = .{
|
||||||
|
.data = Page.initBuf(
|
||||||
|
OffsetBuf.init(page_buf),
|
||||||
|
Page.layout(cap),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
page.data.size.rows = @min(rem, page.data.capacity.rows);
|
||||||
|
rem -= page.data.size.rows;
|
||||||
|
|
||||||
|
// Add the page to the list
|
||||||
|
page_list.append(page);
|
||||||
|
page_size += page_buf.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(page_list.first != null);
|
||||||
|
|
||||||
|
return .{ page_list, page_size };
|
||||||
|
}
|
||||||
|
|
||||||
/// Deinit the pagelist. If you own the memory pool (used clonePool) then
|
/// Deinit the pagelist. If you own the memory pool (used clonePool) then
|
||||||
/// this will reset the pool and retain capacity.
|
/// this will reset the pool and retain capacity.
|
||||||
pub fn deinit(self: *PageList) void {
|
pub fn deinit(self: *PageList) void {
|
||||||
@ -3029,6 +3048,29 @@ test "PageList" {
|
|||||||
}, s.getTopLeft(.active));
|
}, s.getTopLeft(.active));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "PageList init rows across two pages" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
// Find a cap that makes it so that rows don't fit on one page.
|
||||||
|
const rows = 100;
|
||||||
|
const cap = cap: {
|
||||||
|
var cap = try std_capacity.adjust(.{ .cols = 50 });
|
||||||
|
while (cap.rows >= rows) cap = try std_capacity.adjust(.{
|
||||||
|
.cols = cap.cols + 50,
|
||||||
|
});
|
||||||
|
|
||||||
|
break :cap cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Init
|
||||||
|
var s = try init(alloc, cap.cols, rows, null);
|
||||||
|
defer s.deinit();
|
||||||
|
try testing.expect(s.viewport == .active);
|
||||||
|
try testing.expect(s.pages.first != null);
|
||||||
|
try testing.expectEqual(@as(usize, s.rows), s.totalRows());
|
||||||
|
}
|
||||||
|
|
||||||
test "PageList pointFromPin active no history" {
|
test "PageList pointFromPin active no history" {
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
Reference in New Issue
Block a user