terminal/new: pages have a size

This commit is contained in:
Mitchell Hashimoto
2024-02-21 19:26:44 -08:00
parent 01f2a9b39a
commit 06e88a975b
4 changed files with 40 additions and 26 deletions

View File

@ -8,6 +8,7 @@ const Allocator = std.mem.Allocator;
const assert = std.debug.assert; const assert = std.debug.assert;
const point = @import("point.zig"); const point = @import("point.zig");
const pagepkg = @import("page.zig"); const pagepkg = @import("page.zig");
const size = @import("size.zig");
const Page = pagepkg.Page; const Page = pagepkg.Page;
/// The number of PageList.Nodes we preheat the pool with. A node is /// The number of PageList.Nodes we preheat the pool with. A node is
@ -55,13 +56,13 @@ active: RowOffset,
/// The current desired screen dimensions. I say "desired" because individual /// The current desired screen dimensions. I say "desired" because individual
/// pages may still be a different size and not yet reflowed since we lazily /// pages may still be a different size and not yet reflowed since we lazily
/// reflow text. /// reflow text.
cols: usize, cols: size.CellCountInt,
rows: usize, rows: size.CellCountInt,
pub fn init( pub fn init(
alloc: Allocator, alloc: Allocator,
cols: usize, cols: size.CellCountInt,
rows: usize, rows: size.CellCountInt,
max_scrollback: usize, max_scrollback: usize,
) !PageList { ) !PageList {
_ = max_scrollback; _ = max_scrollback;

View File

@ -24,8 +24,8 @@ cursor: Cursor,
/// The cursor position. /// The cursor position.
const Cursor = struct { const Cursor = struct {
// The x/y position within the viewport. // The x/y position within the viewport.
x: usize, x: size.CellCountInt,
y: usize, y: size.CellCountInt,
/// The "last column flag (LCF)" as its called. If this is set then the /// The "last column flag (LCF)" as its called. If this is set then the
/// next character print will force a soft-wrap. /// next character print will force a soft-wrap.
@ -47,8 +47,8 @@ const Cursor = struct {
/// Initialize a new screen. /// Initialize a new screen.
pub fn init( pub fn init(
alloc: Allocator, alloc: Allocator,
cols: usize, cols: size.CellCountInt,
rows: usize, rows: size.CellCountInt,
max_scrollback: usize, max_scrollback: usize,
) !Screen { ) !Screen {
// Initialize our backing pages. This will initialize the viewport. // Initialize our backing pages. This will initialize the viewport.
@ -106,7 +106,7 @@ pub fn cursorDown(self: *Screen) void {
} }
/// Move the cursor to some absolute position. /// Move the cursor to some absolute position.
pub fn cursorHorizontalAbsolute(self: *Screen, x: usize) void { pub fn cursorHorizontalAbsolute(self: *Screen, x: size.CellCountInt) void {
assert(x < self.pages.cols); assert(x < self.pages.cols);
const page_rac = self.cursor.page_offset.rowAndCell(x); const page_rac = self.cursor.page_offset.rowAndCell(x);

View File

@ -20,6 +20,7 @@ const Tabstops = @import("../Tabstops.zig");
const color = @import("../color.zig"); const color = @import("../color.zig");
const mouse_shape = @import("../mouse_shape.zig"); const mouse_shape = @import("../mouse_shape.zig");
const size = @import("size.zig");
const pagepkg = @import("page.zig"); const pagepkg = @import("page.zig");
const style = @import("style.zig"); const style = @import("style.zig");
const Screen = @import("Screen.zig"); const Screen = @import("Screen.zig");
@ -65,8 +66,8 @@ status_display: ansi.StatusDisplay = .main,
tabstops: Tabstops, tabstops: Tabstops,
/// The size of the terminal. /// The size of the terminal.
rows: usize, rows: size.CellCountInt,
cols: usize, cols: size.CellCountInt,
/// The size of the screen in pixels. This is used for pty events and images /// The size of the screen in pixels. This is used for pty events and images
width_px: u32 = 0, width_px: u32 = 0,
@ -155,18 +156,18 @@ pub const MouseFormat = enum(u3) {
pub const ScrollingRegion = struct { pub const ScrollingRegion = struct {
// Top and bottom of the scroll region (0-indexed) // Top and bottom of the scroll region (0-indexed)
// Precondition: top < bottom // Precondition: top < bottom
top: usize, top: size.CellCountInt,
bottom: usize, bottom: size.CellCountInt,
// Left/right scroll regions. // Left/right scroll regions.
// Precondition: right > left // Precondition: right > left
// Precondition: right <= cols - 1 // Precondition: right <= cols - 1
left: usize, left: size.CellCountInt,
right: usize, right: size.CellCountInt,
}; };
/// Initialize a new terminal. /// Initialize a new terminal.
pub fn init(alloc: Allocator, cols: usize, rows: usize) !Terminal { pub fn init(alloc: Allocator, cols: size.CellCountInt, rows: size.CellCountInt) !Terminal {
return Terminal{ return Terminal{
.cols = cols, .cols = cols,
.rows = rows, .rows = rows,

View File

@ -70,7 +70,13 @@ pub const Page = struct {
/// The available set of styles in use on this page. /// The available set of styles in use on this page.
styles: style.Set, styles: style.Set,
/// The capacity of this page. /// The current dimensions of the page. The capacity may be larger
/// than this. This allows us to allocate a larger page than necessary
/// and also to resize a page smaller witout reallocating.
size: Size,
/// The capacity of this page. This is the full size of the backing
/// memory and is fixed at page creation time.
capacity: Capacity, capacity: Capacity,
/// The allocator to use for multi-codepoint grapheme data. We use /// The allocator to use for multi-codepoint grapheme data. We use
@ -85,11 +91,17 @@ pub const Page = struct {
const grapheme_bytes_default = grapheme_count_default * grapheme_chunk; const grapheme_bytes_default = grapheme_count_default * grapheme_chunk;
const GraphemeMap = AutoOffsetHashMap(Offset(Cell), Offset(u21).Slice); const GraphemeMap = AutoOffsetHashMap(Offset(Cell), Offset(u21).Slice);
/// The size of this page.
pub const Size = struct {
cols: size.CellCountInt,
rows: size.CellCountInt,
};
/// Capacity of this page. /// Capacity of this page.
pub const Capacity = struct { pub const Capacity = struct {
/// Number of columns and rows we can know about. /// Number of columns and rows we can know about.
cols: usize, cols: size.CellCountInt,
rows: usize, rows: size.CellCountInt,
/// Number of unique styles that can be used on this page. /// Number of unique styles that can be used on this page.
styles: u16 = 16, styles: u16 = 16,
@ -99,8 +111,7 @@ pub const Page = struct {
}; };
/// Initialize a new page, allocating the required backing memory. /// Initialize a new page, allocating the required backing memory.
/// It is HIGHLY RECOMMENDED you use a page_allocator as the allocator /// The size of the initialized page defaults to the full capacity.
/// but any allocator is allowed.
pub fn init(alloc: Allocator, cap: Capacity) !Page { pub fn init(alloc: Allocator, cap: Capacity) !Page {
const l = layout(cap); const l = layout(cap);
const backing = try alloc.alignedAlloc(u8, std.mem.page_size, l.total_size); const backing = try alloc.alignedAlloc(u8, std.mem.page_size, l.total_size);
@ -138,6 +149,7 @@ pub const Page = struct {
buf.add(l.grapheme_map_start), buf.add(l.grapheme_map_start),
l.grapheme_map_layout, l.grapheme_map_layout,
), ),
.size = .{ .cols = cap.cols, .rows = cap.rows },
.capacity = cap, .capacity = cap,
}; };
} }
@ -149,7 +161,7 @@ pub const Page = struct {
/// Get a single row. y must be valid. /// Get a single row. y must be valid.
pub fn getRow(self: *const Page, y: usize) *Row { pub fn getRow(self: *const Page, y: usize) *Row {
assert(y < self.capacity.rows); assert(y < self.size.rows);
return &self.rows.ptr(self.memory)[y]; return &self.rows.ptr(self.memory)[y];
} }
@ -163,7 +175,7 @@ pub const Page = struct {
} }
const cells = row.cells.ptr(self.memory); const cells = row.cells.ptr(self.memory);
return cells[0..self.capacity.cols]; return cells[0..self.size.cols];
} }
/// Get the row and cell for the given X/Y within this page. /// Get the row and cell for the given X/Y within this page.
@ -171,8 +183,8 @@ pub const Page = struct {
row: *Row, row: *Row,
cell: *Cell, cell: *Cell,
} { } {
assert(y < self.capacity.rows); assert(y < self.size.rows);
assert(x < self.capacity.cols); assert(x < self.size.cols);
const rows = self.rows.ptr(self.memory); const rows = self.rows.ptr(self.memory);
const row = &rows[y]; const row = &rows[y];
@ -199,7 +211,7 @@ pub const Page = struct {
const rows_start = 0; const rows_start = 0;
const rows_end = rows_start + (cap.rows * @sizeOf(Row)); const rows_end = rows_start + (cap.rows * @sizeOf(Row));
const cells_count = cap.cols * cap.rows; const cells_count: usize = @intCast(cap.cols * cap.rows);
const cells_start = alignForward(usize, rows_end, @alignOf(Cell)); const cells_start = alignForward(usize, rows_end, @alignOf(Cell));
const cells_end = cells_start + (cells_count * @sizeOf(Cell)); const cells_end = cells_start + (cells_count * @sizeOf(Cell));