diff --git a/src/Surface.zig b/src/Surface.zig index d0c199010..10ecfd8f1 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -3115,7 +3115,7 @@ fn processLinks(self: *Surface, pos: apprt.CursorPos) !bool { /// if there is no hyperlink. fn osc8URI(self: *Surface, pin: terminal.Pin) ?[]const u8 { _ = self; - const page = &pin.page.data; + const page = &pin.node.data; const cell = pin.rowAndCell().cell; const link_id = page.lookupHyperlink(cell) orelse return null; const entry = page.hyperlink_set.get(page.memory, link_id); diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index cb0f5a3de..742dfbcd4 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -1040,7 +1040,7 @@ pub fn updateFrame( null, ); while (it.next()) |chunk| { - var dirty_set = chunk.page.data.dirtyBitSet(); + var dirty_set = chunk.node.data.dirtyBitSet(); dirty_set.unsetAll(); } } @@ -2364,7 +2364,7 @@ fn rebuildCells( // True if this cell is selected const selected: bool = if (screen.selection) |sel| sel.contains(screen, .{ - .page = row.page, + .node = row.node, .y = row.y, .x = @intCast( // Spacer tails should show the selection @@ -2512,12 +2512,7 @@ fn rebuildCells( ); }; - if (style.flags.overline) self.addOverline( - @intCast(x), - @intCast(y), - fg, - alpha - ) catch |err| { + if (style.flags.overline) self.addOverline(@intCast(x), @intCast(y), fg, alpha) catch |err| { log.warn( "error adding overline to cell, will be invalid x={} y={}, err={}", .{ x, y, err }, diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 324fe14b3..5313315b1 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -844,7 +844,7 @@ pub fn updateFrame( null, ); while (it.next()) |chunk| { - var dirty_set = chunk.page.data.dirtyBitSet(); + var dirty_set = chunk.node.data.dirtyBitSet(); dirty_set.unsetAll(); } } @@ -1411,7 +1411,7 @@ pub fn rebuildCells( // True if this cell is selected const selected: bool = if (screen.selection) |sel| sel.contains(screen, .{ - .page = row.page, + .node = row.node, .y = row.y, .x = @intCast( // Spacer tails should show the selection diff --git a/src/renderer/cell.zig b/src/renderer/cell.zig index 1a315a0d8..c84fbcc6f 100644 --- a/src/renderer/cell.zig +++ b/src/renderer/cell.zig @@ -70,7 +70,7 @@ pub fn fgMode( } // If we are at the end of the screen its definitely constrained - if (cell_pin.x == cell_pin.page.data.size.cols - 1) break :text .constrained; + if (cell_pin.x == cell_pin.node.data.size.cols - 1) break :text .constrained; // If we have a previous cell and it was PUA then we need to // also constrain. This is so that multiple PUA glyphs align. diff --git a/src/renderer/link.zig b/src/renderer/link.zig index aa2db2b8d..994190ec8 100644 --- a/src/renderer/link.zig +++ b/src/renderer/link.zig @@ -122,7 +122,7 @@ pub const Set = struct { if (!mouse_cell.hyperlink) return; // Get our hyperlink entry - const page = &mouse_pin.page.data; + const page: *terminal.Page = &mouse_pin.node.data; const link_id = page.lookupHyperlink(mouse_cell) orelse { log.warn("failed to find hyperlink for cell", .{}); return; @@ -165,7 +165,7 @@ pub const Set = struct { for (row_pin.cells(.right), 0..) |*cell, x| { const match = match: { if (cell.hyperlink) { - if (row_pin.page.data.lookupHyperlink(cell)) |cell_link_id| { + if (row_pin.node.data.lookupHyperlink(cell)) |cell_link_id| { break :match cell_link_id == link_id; } } @@ -215,7 +215,7 @@ pub const Set = struct { // Expand it to the left. var it = mouse_pin.cellIterator(.left_up, null); while (it.next()) |cell_pin| { - const page = &cell_pin.page.data; + const page: *terminal.Page = &cell_pin.node.data; const rac = cell_pin.rowAndCell(); const cell = rac.cell; @@ -241,7 +241,7 @@ pub const Set = struct { // Expand it to the right it = mouse_pin.cellIterator(.right_down, null); while (it.next()) |cell_pin| { - const page = &cell_pin.page.data; + const page: *terminal.Page = &cell_pin.node.data; const rac = cell_pin.rowAndCell(); const cell = rac.cell; diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index d86ebc765..f1dbc2561 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -69,15 +69,15 @@ pub const MemoryPool = struct { page_alloc: Allocator, preheat: usize, ) !MemoryPool { - var pool = try NodePool.initPreheated(gen_alloc, preheat); - errdefer pool.deinit(); + var node_pool = try NodePool.initPreheated(gen_alloc, preheat); + errdefer node_pool.deinit(); var page_pool = try PagePool.initPreheated(page_alloc, preheat); errdefer page_pool.deinit(); var pin_pool = try PinPool.initPreheated(gen_alloc, 8); errdefer pin_pool.deinit(); return .{ .alloc = gen_alloc, - .nodes = pool, + .nodes = node_pool, .pages = page_pool, .pins = pin_pool, }; @@ -265,7 +265,7 @@ fn initPages( const cap = try std_capacity.adjust(.{ .cols = cols }); var rem = rows; while (rem > 0) { - const page = try pool.nodes.create(); + const node = try pool.nodes.create(); const page_buf = try pool.pages.create(); // no errdefer because the pool deinit will clean these up @@ -276,17 +276,17 @@ fn initPages( // Initialize the first set of pages to contain our viewport so that // the top of the first page is always the active area. - page.* = .{ + node.* = .{ .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; + node.data.size.rows = @min(rem, node.data.capacity.rows); + rem -= node.data.size.rows; // Add the page to the list - page_list.append(page); + page_list.append(node); page_size += page_buf.len; } @@ -412,23 +412,23 @@ pub fn clone( while (it.next()) |chunk| { // Clone the page. We have to use createPageExt here because // we don't know if the source page has a standard size. - const page = try createPageExt( + const node = try createPageExt( pool, - chunk.page.data.capacity, + chunk.node.data.capacity, &page_size, ); - assert(page.data.capacity.rows >= chunk.end - chunk.start); - defer page.data.assertIntegrity(); - page.data.size.rows = chunk.end - chunk.start; - try page.data.cloneFrom( - &chunk.page.data, + assert(node.data.capacity.rows >= chunk.end - chunk.start); + defer node.data.assertIntegrity(); + node.data.size.rows = chunk.end - chunk.start; + try node.data.cloneFrom( + &chunk.node.data, chunk.start, chunk.end, ); - page_list.append(page); + page_list.append(node); - total_rows += page.data.size.rows; + total_rows += node.data.size.rows; // Remap our tracked pins by changing the page and // offsetting the Y position based on the chunk start. @@ -436,12 +436,12 @@ pub fn clone( const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { // We're only interested in pins that were within the chunk. - if (p.page != chunk.page or + if (p.node != chunk.node or p.y < chunk.start or p.y >= chunk.end) continue; const new_p = try pool.pins.create(); new_p.* = p.*; - new_p.page = page; + new_p.node = node; new_p.y -= chunk.start; try remap.putNoClobber(p, new_p); try tracked_pins.putNoClobber(pool.alloc, new_p, {}); @@ -626,8 +626,8 @@ fn resizeCols( try dst_cursor.reflowRow(self, row); // Once we're done reflowing a page, destroy it. - if (row.y == row.page.data.size.rows - 1) { - self.destroyPage(row.page); + if (row.y == row.node.data.size.rows - 1) { + self.destroyNode(row.node); } } @@ -716,7 +716,7 @@ const ReflowCursor = struct { list: *PageList, row: Pin, ) !void { - const src_page = &row.page.data; + const src_page: *Page = &row.node.data; const src_row = row.rowAndCell().row; const src_y = row.y; @@ -744,7 +744,7 @@ const ReflowCursor = struct { { const pin_keys = list.tracked_pins.keys(); for (pin_keys) |p| { - if (&p.page.data != src_page or + if (&p.node.data != src_page or p.y != src_y) continue; // If this pin is in the blanks on the right and past the end @@ -794,11 +794,11 @@ const ReflowCursor = struct { { const pin_keys = list.tracked_pins.keys(); for (pin_keys) |p| { - if (&p.page.data != src_page or + if (&p.node.data != src_page or p.y != src_y or p.x != x) continue; - p.page = self.node; + p.node = self.node; p.x = self.x; p.y = self.y; } @@ -1036,7 +1036,7 @@ const ReflowCursor = struct { // then we should remove it from the list. if (old_page.size.rows == 0) { list.pages.remove(old_node); - list.destroyPage(old_node); + list.destroyNode(old_node); } } @@ -1187,7 +1187,7 @@ fn resizeWithoutReflow(self: *PageList, opts: Resize) !void { .lt => { var it = self.pageIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |chunk| { - const page = &chunk.page.data; + const page = &chunk.node.data; defer page.assertIntegrity(); const rows = page.rows.ptr(page.memory); for (0..page.size.rows) |i| { @@ -1307,7 +1307,7 @@ fn resizeWithoutReflowGrowCols( chunk: PageIterator.Chunk, ) !void { assert(cols > self.cols); - const page = &chunk.page.data; + const page = &chunk.node.data; const cap = try page.capacity.adjust(.{ .cols = cols }); // Update our col count @@ -1326,14 +1326,14 @@ fn resizeWithoutReflowGrowCols( // to allocate a page, and copy the old data into it. // On error, we need to undo all the pages we've added. - const prev = chunk.page.prev; + const prev = chunk.node.prev; errdefer { - var current = chunk.page.prev; + var current = chunk.node.prev; while (current) |p| { if (current == prev) break; current = p.prev; self.pages.remove(p); - self.destroyPage(p); + self.destroyNode(p); } } @@ -1391,8 +1391,8 @@ fn resizeWithoutReflowGrowCols( // We need to loop because our col growth may force us // to split pages. while (copied < page.size.rows) { - const new_page = try self.createPage(cap); - defer new_page.data.assertIntegrity(); + const new_node = try self.createPage(cap); + defer new_node.data.assertIntegrity(); // The length we can copy into the new page is at most the number // of rows in our cap. But if we can finish our source page we use that. @@ -1402,11 +1402,11 @@ fn resizeWithoutReflowGrowCols( const y_start = copied; const y_end = copied + len; const src_rows = page.rows.ptr(page.memory)[y_start..y_end]; - const dst_rows = new_page.data.rows.ptr(new_page.data.memory)[0..len]; + const dst_rows = new_node.data.rows.ptr(new_node.data.memory)[0..len]; for (dst_rows, src_rows) |*dst_row, *src_row| { - new_page.data.size.rows += 1; - errdefer new_page.data.size.rows -= 1; - try new_page.data.cloneRowFrom( + new_node.data.size.rows += 1; + errdefer new_node.data.size.rows -= 1; + try new_node.data.cloneRowFrom( page, dst_row, src_row, @@ -1415,15 +1415,15 @@ fn resizeWithoutReflowGrowCols( copied = y_end; // Insert our new page - self.pages.insertBefore(chunk.page, new_page); + self.pages.insertBefore(chunk.node, new_node); // Update our tracked pins that pointed to this previous page. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != chunk.page or + if (p.node != chunk.node or p.y < y_start or p.y >= y_end) continue; - p.page = new_page; + p.node = new_node; p.y -= y_start; } } @@ -1431,8 +1431,8 @@ fn resizeWithoutReflowGrowCols( // Remove the old page. // Deallocate the old page. - self.pages.remove(chunk.page); - self.destroyPage(chunk.page); + self.pages.remove(chunk.node); + self.destroyNode(chunk.node); } /// Returns the number of trailing blank lines, not to exceed max. Max @@ -1485,7 +1485,7 @@ fn trimTrailingBlankRows( // we'd invalidate this pin, as well. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != row_pin.page or + if (p.node != row_pin.node or p.y != row_pin.y) continue; return trimmed; } @@ -1493,11 +1493,11 @@ fn trimTrailingBlankRows( // No text, we can trim this row. Because it has // no text we can also be sure it has no styling // so we don't need to worry about memory. - row_pin.page.data.size.rows -= 1; - if (row_pin.page.data.size.rows == 0) { - self.erasePage(row_pin.page); + row_pin.node.data.size.rows -= 1; + if (row_pin.node.data.size.rows == 0) { + self.erasePage(row_pin.node); } else { - row_pin.page.data.assertIntegrity(); + row_pin.node.data.assertIntegrity(); } trimmed += 1; @@ -1723,8 +1723,8 @@ pub fn grow(self: *PageList) !?*List.Node { // new first page to the top-left. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != first) continue; - p.page = self.pages.first.?; + if (p.node != first) continue; + p.node = self.pages.first.?; p.y = 0; p.x = 0; } @@ -1737,17 +1737,17 @@ pub fn grow(self: *PageList) !?*List.Node { } // We need to allocate a new memory buffer. - const next_page = try self.createPage(try std_capacity.adjust(.{ .cols = self.cols })); + const next_node = try self.createPage(try std_capacity.adjust(.{ .cols = self.cols })); // we don't errdefer this because we've added it to the linked // list and its fine to have dangling unused pages. - self.pages.append(next_page); - next_page.data.size.rows = 1; + self.pages.append(next_node); + next_node.data.size.rows = 1; // We should never be more than our max size here because we've // verified the case above. - next_page.data.assertIntegrity(); + next_node.data.assertIntegrity(); - return next_page; + return next_node; } /// Adjust the capacity of the given page in the list. @@ -1787,12 +1787,14 @@ pub const AdjustCapacityError = Allocator.Error || Page.CloneFromError; /// any requests to decrease will be ignored. pub fn adjustCapacity( self: *PageList, - page: *List.Node, + node: *List.Node, adjustment: AdjustCapacity, ) AdjustCapacityError!*List.Node { + const page: *Page = &node.data; + // We always start with the base capacity of the existing page. This // ensures we never shrink from what we need. - var cap = page.data.capacity; + var cap = page.capacity; // All ceilPowerOfTwo is unreachable because we're always same or less // bit width so maxInt is always possible. @@ -1820,26 +1822,27 @@ pub fn adjustCapacity( log.info("adjusting page capacity={}", .{cap}); // Create our new page and clone the old page into it. - const new_page = try self.createPage(cap); - errdefer self.destroyPage(new_page); - assert(new_page.data.capacity.rows >= page.data.capacity.rows); - new_page.data.size.rows = page.data.size.rows; - try new_page.data.cloneFrom(&page.data, 0, page.data.size.rows); + const new_node = try self.createPage(cap); + errdefer self.destroyNode(new_node); + const new_page: *Page = &new_node.data; + assert(new_page.capacity.rows >= page.capacity.rows); + new_page.size.rows = page.size.rows; + try new_page.cloneFrom(page, 0, page.size.rows); // Fix up all our tracked pins to point to the new page. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != page) continue; - p.page = new_page; + if (p.node != node) continue; + p.node = new_node; } // Insert this page and destroy the old page - self.pages.insertBefore(page, new_page); - self.pages.remove(page); - self.destroyPage(page); + self.pages.insertBefore(node, new_node); + self.pages.remove(node); + self.destroyNode(node); - new_page.data.assertIntegrity(); - return new_page; + new_page.assertIntegrity(); + return new_node; } /// Create a new page node. This does not add it to the list and this @@ -1897,30 +1900,33 @@ fn createPageExt( return page; } -/// Destroy the memory of the given page and return it to the pool. The -/// page is assumed to already be removed from the linked list. -fn destroyPage(self: *PageList, page: *List.Node) void { - destroyPageExt(&self.pool, page, &self.page_size); +/// Destroy the memory of the given node in the PageList linked list +/// and return it to the pool. The node is assumed to already be removed +/// from the linked list. +fn destroyNode(self: *PageList, node: *List.Node) void { + destroyNodeExt(&self.pool, node, &self.page_size); } -fn destroyPageExt( +fn destroyNodeExt( pool: *MemoryPool, - page: *List.Node, + node: *List.Node, total_size: ?*usize, ) void { - // Update our accounting for page size - if (total_size) |v| v.* -= page.data.memory.len; + const page: *Page = &node.data; - if (page.data.memory.len <= std_size) { + // Update our accounting for page size + if (total_size) |v| v.* -= page.memory.len; + + if (page.memory.len <= std_size) { // Reset the memory to zero so it can be reused - @memset(page.data.memory, 0); - pool.pages.destroy(@ptrCast(page.data.memory.ptr)); + @memset(page.memory, 0); + pool.pages.destroy(@ptrCast(page.memory.ptr)); } else { const page_alloc = pool.pages.arena.child_allocator; - page_alloc.free(page.data.memory); + page_alloc.free(page.memory); } - pool.nodes.destroy(page); + pool.nodes.destroy(node); } /// Fast-path function to erase exactly 1 row. Erasing means that the row @@ -1936,32 +1942,32 @@ pub fn eraseRow( ) !void { const pn = self.pin(pt).?; - var page = pn.page; - var rows = page.data.rows.ptr(page.data.memory.ptr); + var node = pn.node; + var rows = node.data.rows.ptr(node.data.memory.ptr); // In order to move the following rows up we rotate the rows array by 1. // The rotate operation turns e.g. [ 0 1 2 3 ] in to [ 1 2 3 0 ], which // works perfectly to move all of our elements where they belong. - fastmem.rotateOnce(Row, rows[pn.y..page.data.size.rows]); + fastmem.rotateOnce(Row, rows[pn.y..node.data.size.rows]); // We adjust the tracked pins in this page, moving up any that were below // the removed row. { const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page == page and p.y > pn.y) p.y -= 1; + if (p.node == node and p.y > pn.y) p.y -= 1; } } { // Set all the rows as dirty in this page - var dirty = page.data.dirtyBitSet(); - dirty.setRangeValue(.{ .start = pn.y, .end = page.data.size.rows }, true); + var dirty = node.data.dirtyBitSet(); + dirty.setRangeValue(.{ .start = pn.y, .end = node.data.size.rows }, true); } // We iterate through all of the following pages in order to move their // rows up by 1 as well. - while (page.next) |next| { + while (node.next) |next| { const next_rows = next.data.rows.ptr(next.data.memory.ptr); // We take the top row of the page and clone it in to the bottom @@ -1979,30 +1985,30 @@ pub fn eraseRow( // 5 5 5 | 6 // 6 6 6 | 7 // 7 7 7 <' 4 - try page.data.cloneRowFrom( + try node.data.cloneRowFrom( &next.data, - &rows[page.data.size.rows - 1], + &rows[node.data.size.rows - 1], &next_rows[0], ); - page = next; + node = next; rows = next_rows; - fastmem.rotateOnce(Row, rows[0..page.data.size.rows]); + fastmem.rotateOnce(Row, rows[0..node.data.size.rows]); // Set all the rows as dirty - var dirty = page.data.dirtyBitSet(); - dirty.setRangeValue(.{ .start = 0, .end = page.data.size.rows }, true); + var dirty = node.data.dirtyBitSet(); + dirty.setRangeValue(.{ .start = 0, .end = node.data.size.rows }, true); // Our tracked pins for this page need to be updated. // If the pin is in row 0 that means the corresponding row has // been moved to the previous page. Otherwise, move it up by 1. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != page) continue; + if (p.node != node) continue; if (p.y == 0) { - p.page = page.prev.?; - p.y = p.page.data.size.rows - 1; + p.node = node.prev.?; + p.y = p.node.data.size.rows - 1; continue; } p.y -= 1; @@ -2010,7 +2016,7 @@ pub fn eraseRow( } // Clear the final row which was rotated from the top of the page. - page.data.clearCells(&rows[page.data.size.rows - 1], 0, page.data.size.cols); + node.data.clearCells(&rows[node.data.size.rows - 1], 0, node.data.size.cols); } /// A variant of eraseRow that shifts only a bounded number of following @@ -2031,24 +2037,24 @@ pub fn eraseRowBounded( const pn = self.pin(pt).?; - var page = pn.page; - var rows = page.data.rows.ptr(page.data.memory.ptr); + var node: *List.Node = pn.node; + var rows = node.data.rows.ptr(node.data.memory.ptr); // If the row limit is less than the remaining rows before the end of the // page, then we clear the row, rotate it to the end of the boundary limit // and update our pins. - if (page.data.size.rows - pn.y > limit) { - page.data.clearCells(&rows[pn.y], 0, page.data.size.cols); + if (node.data.size.rows - pn.y > limit) { + node.data.clearCells(&rows[pn.y], 0, node.data.size.cols); fastmem.rotateOnce(Row, rows[pn.y..][0 .. limit + 1]); // Set all the rows as dirty - var dirty = page.data.dirtyBitSet(); + var dirty = node.data.dirtyBitSet(); dirty.setRangeValue(.{ .start = pn.y, .end = pn.y + limit }, true); // Update pins in the shifted region. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page == page and + if (p.node == node and p.y >= pn.y and p.y <= pn.y + limit) { @@ -2063,24 +2069,24 @@ pub fn eraseRowBounded( return; } - fastmem.rotateOnce(Row, rows[pn.y..page.data.size.rows]); + fastmem.rotateOnce(Row, rows[pn.y..node.data.size.rows]); // All the rows in the page are dirty below the erased row. { - var dirty = page.data.dirtyBitSet(); - dirty.setRangeValue(.{ .start = pn.y, .end = page.data.size.rows }, true); + var dirty = node.data.dirtyBitSet(); + dirty.setRangeValue(.{ .start = pn.y, .end = node.data.size.rows }, true); } // We need to keep track of how many rows we've shifted so that we can // determine at what point we need to do a partial shift on subsequent // pages. - var shifted: usize = page.data.size.rows - pn.y; + var shifted: usize = node.data.size.rows - pn.y; // Update tracked pins. { const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page == page and p.y >= pn.y) { + if (p.node == node and p.y >= pn.y) { if (p.y == 0) { p.x = 0; } else { @@ -2090,16 +2096,16 @@ pub fn eraseRowBounded( } } - while (page.next) |next| { + while (node.next) |next| { const next_rows = next.data.rows.ptr(next.data.memory.ptr); - try page.data.cloneRowFrom( + try node.data.cloneRowFrom( &next.data, - &rows[page.data.size.rows - 1], + &rows[node.data.size.rows - 1], &next_rows[0], ); - page = next; + node = next; rows = next_rows; // We check to see if this page contains enough rows to satisfy the @@ -2108,21 +2114,21 @@ pub fn eraseRowBounded( // // The logic here is very similar to the one before the loop. const shifted_limit = limit - shifted; - if (page.data.size.rows > shifted_limit) { - page.data.clearCells(&rows[0], 0, page.data.size.cols); + if (node.data.size.rows > shifted_limit) { + node.data.clearCells(&rows[0], 0, node.data.size.cols); fastmem.rotateOnce(Row, rows[0 .. shifted_limit + 1]); // Set all the rows as dirty - var dirty = page.data.dirtyBitSet(); + var dirty = node.data.dirtyBitSet(); dirty.setRangeValue(.{ .start = 0, .end = shifted_limit }, true); // Update pins in the shifted region. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != page or p.y > shifted_limit) continue; + if (p.node != node or p.y > shifted_limit) continue; if (p.y == 0) { - p.page = page.prev.?; - p.y = p.page.data.size.rows - 1; + p.node = node.prev.?; + p.y = p.node.data.size.rows - 1; continue; } p.y -= 1; @@ -2131,22 +2137,22 @@ pub fn eraseRowBounded( return; } - fastmem.rotateOnce(Row, rows[0..page.data.size.rows]); + fastmem.rotateOnce(Row, rows[0..node.data.size.rows]); // Set all the rows as dirty - var dirty = page.data.dirtyBitSet(); - dirty.setRangeValue(.{ .start = 0, .end = page.data.size.rows }, true); + var dirty = node.data.dirtyBitSet(); + dirty.setRangeValue(.{ .start = 0, .end = node.data.size.rows }, true); - // Account for the rows shifted in this page. - shifted += page.data.size.rows; + // Account for the rows shifted in this node. + shifted += node.data.size.rows; // Update tracked pins. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != page) continue; + if (p.node != node) continue; if (p.y == 0) { - p.page = page.prev.?; - p.y = p.page.data.size.rows - 1; + p.node = node.prev.?; + p.y = p.node.data.size.rows - 1; continue; } p.y -= 1; @@ -2155,7 +2161,7 @@ pub fn eraseRowBounded( // We reached the end of the page list before the limit, so we clear // the final row since it was rotated down from the top of this page. - page.data.clearCells(&rows[page.data.size.rows - 1], 0, page.data.size.cols); + node.data.clearCells(&rows[node.data.size.rows - 1], 0, node.data.size.cols); } /// Erase the rows from the given top to bottom (inclusive). Erasing @@ -2183,28 +2189,28 @@ pub fn eraseRows( // in our linked list. erasePage requires at least one other // page so to handle this we reinit this page, set it to zero // size which will let us grow our active area back. - if (chunk.page.next == null and chunk.page.prev == null) { - const page = &chunk.page.data; + if (chunk.node.next == null and chunk.node.prev == null) { + const page = &chunk.node.data; erased += page.size.rows; page.reinit(); page.size.rows = 0; break; } - self.erasePage(chunk.page); - erased += chunk.page.data.size.rows; + self.erasePage(chunk.node); + erased += chunk.node.data.size.rows; continue; } // We are modifying our chunk so make sure it is in a good state. - defer chunk.page.data.assertIntegrity(); + defer chunk.node.data.assertIntegrity(); // The chunk is not a full page so we need to move the rows. // This is a cheap operation because we're just moving cell offsets, // not the actual cell contents. assert(chunk.start == 0); - const rows = chunk.page.data.rows.ptr(chunk.page.data.memory); - const scroll_amount = chunk.page.data.size.rows - chunk.end; + const rows = chunk.node.data.rows.ptr(chunk.node.data.memory); + const scroll_amount = chunk.node.data.size.rows - chunk.end; for (0..scroll_amount) |i| { const src: *Row = &rows[i + chunk.end]; const dst: *Row = &rows[i]; @@ -2215,12 +2221,12 @@ pub fn eraseRows( // Clear our remaining cells that we didn't shift or swapped // in case we grow back into them. - for (scroll_amount..chunk.page.data.size.rows) |i| { + for (scroll_amount..chunk.node.data.size.rows) |i| { const row: *Row = &rows[i]; - chunk.page.data.clearCells( + chunk.node.data.clearCells( row, 0, - chunk.page.data.size.cols, + chunk.node.data.size.cols, ); } @@ -2228,7 +2234,7 @@ pub fn eraseRows( // row then we move it to the top of this page. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != chunk.page) continue; + if (p.node != chunk.node) continue; if (p.y >= chunk.end) { p.y -= chunk.end; } else { @@ -2238,12 +2244,12 @@ pub fn eraseRows( } // Our new size is the amount we scrolled - chunk.page.data.size.rows = @intCast(scroll_amount); + chunk.node.data.size.rows = @intCast(scroll_amount); erased += chunk.end; // Set all the rows as dirty - var dirty = chunk.page.data.dirtyBitSet(); - dirty.setRangeValue(.{ .start = 0, .end = chunk.page.data.size.rows }, true); + var dirty = chunk.node.data.dirtyBitSet(); + dirty.setRangeValue(.{ .start = 0, .end = chunk.node.data.size.rows }, true); } // If we deleted active, we need to regrow because one of our invariants @@ -2271,7 +2277,7 @@ pub fn eraseRows( // For top, we move back to active if our erasing moved our // top page into the active area. - .top => if (self.pinIsActive(.{ .page = self.pages.first.? })) { + .top => if (self.pinIsActive(.{ .node = self.pages.first.? })) { self.viewport = .{ .active = {} }; }, } @@ -2280,21 +2286,21 @@ pub fn eraseRows( /// Erase a single page, freeing all its resources. The page can be /// anywhere in the linked list but must NOT be the final page in the /// entire list (i.e. must not make the list empty). -fn erasePage(self: *PageList, page: *List.Node) void { - assert(page.next != null or page.prev != null); +fn erasePage(self: *PageList, node: *List.Node) void { + assert(node.next != null or node.prev != null); // Update any tracked pins to move to the next page. const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != page) continue; - p.page = page.next orelse page.prev orelse unreachable; + if (p.node != node) continue; + p.node = node.next orelse node.prev orelse unreachable; p.y = 0; p.x = 0; } // Remove the page from the linked list - self.pages.remove(page); - self.destroyPage(page); + self.pages.remove(node); + self.destroyNode(node); } /// Returns the pin for the given point. The pin is NOT tracked so it @@ -2341,10 +2347,10 @@ pub fn countTrackedPins(self: *const PageList) usize { /// worst case. Only for runtime safety/debug. fn pinIsValid(self: *const PageList, p: Pin) bool { var it = self.pages.first; - while (it) |page| : (it = page.next) { - if (page != p.page) continue; - return p.y < page.data.size.rows and - p.x < page.data.size.cols; + while (it) |node| : (it = node.next) { + if (node != p.node) continue; + return p.y < node.data.size.rows and + p.x < node.data.size.cols; } return false; @@ -2356,19 +2362,19 @@ fn pinIsActive(self: *const PageList, p: Pin) bool { // If the pin is in the active page, then we can quickly determine // if we're beyond the end. const active = self.getTopLeft(.active); - if (p.page == active.page) return p.y >= active.y; + if (p.node == active.node) return p.y >= active.y; - var page_ = active.page.next; - while (page_) |page| { + var node_ = active.node.next; + while (node_) |node| { // This loop is pretty fast because the active area is - // never that large so this is at most one, two pages for + // never that large so this is at most one, two nodes for // reasonable terminals (including very large real world // ones). - // A page forward in the active area is our page, so we're + // A node forward in the active area is our node, so we're // definitely in the active area. - if (page == p.page) return true; - page_ = page.next; + if (node == p.node) return true; + node_ = node.next; } return false; @@ -2388,22 +2394,22 @@ pub fn pointFromPin(self: *const PageList, tag: point.Tag, p: Pin) ?point.Point // Count our first page which is special because it may be partial. var coord: point.Coordinate = .{ .x = p.x }; - if (p.page == tl.page) { + if (p.node == tl.node) { // If our top-left is after our y then we're outside the range. if (tl.y > p.y) return null; coord.y = p.y - tl.y; } else { - coord.y += tl.page.data.size.rows - tl.y; - var page_ = tl.page.next; - while (page_) |page| : (page_ = page.next) { - if (page == p.page) { + coord.y += tl.node.data.size.rows - tl.y; + var node_ = tl.node.next; + while (node_) |node| : (node_ = node.next) { + if (node == p.node) { coord.y += p.y; break; } - coord.y += page.data.size.rows; + coord.y += node.data.size.rows; } else { - // We never saw our page, meaning we're outside the range. + // We never saw our node, meaning we're outside the range. return null; } } @@ -2423,9 +2429,9 @@ pub fn pointFromPin(self: *const PageList, tag: point.Tag, p: Pin) ?point.Point /// Warning: this is slow and should not be used in performance critical paths pub fn getCell(self: *const PageList, pt: point.Point) ?Cell { const pt_pin = self.pin(pt) orelse return null; - const rac = pt_pin.page.data.getRowAndCell(pt_pin.x, pt_pin.y); + const rac = pt_pin.node.data.getRowAndCell(pt_pin.x, pt_pin.y); return .{ - .page = pt_pin.page, + .node = pt_pin.node, .row = rac.row, .cell = rac.cell, .row_idx = pt_pin.y, @@ -2463,16 +2469,16 @@ pub fn diagram(self: *const PageList, writer: anytype) !void { var it = self.pageIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |chunk| : (page_index += 1) { - cols = chunk.page.data.size.cols; + cols = chunk.node.data.size.cols; // Whether we've just skipped some number of rows and drawn // an ellipsis row (this is reset when a row is not skipped). var skipped = false; - for (0..chunk.page.data.size.rows) |y| { + for (0..chunk.node.data.size.rows) |y| { // Active header if (!active and - chunk.page == active_pin.page and + chunk.node == active_pin.node and active_pin.y == y) { active = true; @@ -2494,8 +2500,8 @@ pub fn diagram(self: *const PageList, writer: anytype) !void { // Row contents { - const row = chunk.page.data.getRow(y); - const cells = chunk.page.data.getCells(row)[0..cols]; + const row = chunk.node.data.getRow(y); + const cells = chunk.node.data.getCells(row)[0..cols]; var row_has_content = false; @@ -2544,7 +2550,7 @@ pub fn diagram(self: *const PageList, writer: anytype) !void { } try writer.print("{u}", .{cell.codepoint()}); if (cell.hasGrapheme()) { - const grapheme = chunk.page.data.lookupGrapheme(cell).?; + const grapheme = chunk.node.data.lookupGrapheme(cell).?; for (grapheme) |cp| { try writer.print("{u}", .{cp}); } @@ -2572,7 +2578,7 @@ pub fn diagram(self: *const PageList, writer: anytype) !void { var pin_count: usize = 0; const pin_keys = self.tracked_pins.keys(); for (pin_keys) |p| { - if (p.page != chunk.page) continue; + if (p.node != chunk.node) continue; if (p.y != y) continue; pin_buf[pin_count] = p; pin_count += 1; @@ -2651,7 +2657,7 @@ pub const CellIterator = struct { switch (self.row_it.page_it.direction) { .right_down => { - if (cell.x + 1 < cell.page.data.size.cols) { + if (cell.x + 1 < cell.node.data.size.cols) { // We still have cells in this row, increase x. var copy = cell; copy.x += 1; @@ -2672,7 +2678,7 @@ pub const CellIterator = struct { // We need to move to the previous row and last col if (self.row_it.next()) |next_cell| { var copy = next_cell; - copy.x = next_cell.page.data.size.cols - 1; + copy.x = next_cell.node.data.size.cols - 1; self.cell = copy; } else { self.cell = null; @@ -2711,7 +2717,7 @@ pub const RowIterator = struct { pub fn next(self: *RowIterator) ?Pin { const chunk = self.chunk orelse return null; - const row: Pin = .{ .page = chunk.page, .y = self.offset }; + const row: Pin = .{ .node = chunk.node, .y = self.offset }; switch (self.page_it.direction) { .right_down => { @@ -2798,20 +2804,20 @@ pub const PageIterator = struct { // If we have no limit, then we consume this entire page. Our // next row is the next page. self.row = next: { - const next_page = row.page.next orelse break :next null; - break :next .{ .page = next_page }; + const next_page = row.node.next orelse break :next null; + break :next .{ .node = next_page }; }; break :none .{ - .page = row.page, + .node = row.node, .start = row.y, - .end = row.page.data.size.rows, + .end = row.node.data.size.rows, }; }, .count => |*limit| count: { assert(limit.* > 0); // should be handled already - const len = @min(row.page.data.size.rows - row.y, limit.*); + const len = @min(row.node.data.size.rows - row.y, limit.*); if (len > limit.*) { self.row = row.down(len); limit.* -= len; @@ -2820,7 +2826,7 @@ pub const PageIterator = struct { } break :count .{ - .page = row.page, + .node = row.node, .start = row.y, .end = row.y + len, }; @@ -2829,16 +2835,16 @@ pub const PageIterator = struct { .row => |limit_row| row: { // If this is not the same page as our limit then we // can consume the entire page. - if (limit_row.page != row.page) { + if (limit_row.node != row.node) { self.row = next: { - const next_page = row.page.next orelse break :next null; - break :next .{ .page = next_page }; + const next_page = row.node.next orelse break :next null; + break :next .{ .node = next_page }; }; break :row .{ - .page = row.page, + .node = row.node, .start = row.y, - .end = row.page.data.size.rows, + .end = row.node.data.size.rows, }; } @@ -2847,7 +2853,7 @@ pub const PageIterator = struct { self.row = null; if (row.y > limit_row.y) return null; break :row .{ - .page = row.page, + .node = row.node, .start = row.y, .end = limit_row.y + 1, }; @@ -2864,15 +2870,15 @@ pub const PageIterator = struct { // If we have no limit, then we consume this entire page. Our // next row is the next page. self.row = next: { - const next_page = row.page.prev orelse break :next null; + const next_page = row.node.prev orelse break :next null; break :next .{ - .page = next_page, + .node = next_page, .y = next_page.data.size.rows - 1, }; }; break :none .{ - .page = row.page, + .node = row.node, .start = 0, .end = row.y + 1, }; @@ -2889,7 +2895,7 @@ pub const PageIterator = struct { } break :count .{ - .page = row.page, + .node = row.node, .start = row.y - len, .end = row.y - 1, }; @@ -2898,17 +2904,17 @@ pub const PageIterator = struct { .row => |limit_row| row: { // If this is not the same page as our limit then we // can consume the entire page. - if (limit_row.page != row.page) { + if (limit_row.node != row.node) { self.row = next: { - const next_page = row.page.prev orelse break :next null; + const next_page = row.node.prev orelse break :next null; break :next .{ - .page = next_page, + .node = next_page, .y = next_page.data.size.rows - 1, }; }; break :row .{ - .page = row.page, + .node = row.node, .start = 0, .end = row.y + 1, }; @@ -2919,7 +2925,7 @@ pub const PageIterator = struct { self.row = null; if (row.y < limit_row.y) return null; break :row .{ - .page = row.page, + .node = row.node, .start = limit_row.y, .end = row.y + 1, }; @@ -2928,18 +2934,18 @@ pub const PageIterator = struct { } pub const Chunk = struct { - page: *List.Node, + node: *List.Node, start: size.CellCountInt, end: size.CellCountInt, pub fn rows(self: Chunk) []Row { - const rows_ptr = self.page.data.rows.ptr(self.page.data.memory); + const rows_ptr = self.node.data.rows.ptr(self.node.data.memory); return rows_ptr[self.start..self.end]; } /// Returns true if this chunk represents every row in the page. pub fn fullPage(self: Chunk) bool { - return self.start == 0 and self.end == self.page.data.size.rows; + return self.start == 0 and self.end == self.node.data.size.rows; } }; }; @@ -2986,7 +2992,7 @@ pub fn pageIterator( pub fn getTopLeft(self: *const PageList, tag: point.Tag) Pin { return switch (tag) { // The full screen or history is always just the first page. - .screen, .history => .{ .page = self.pages.first.? }, + .screen, .history => .{ .node = self.pages.first.? }, .viewport => switch (self.viewport) { .active => self.getTopLeft(.active), @@ -3001,13 +3007,13 @@ pub fn getTopLeft(self: *const PageList, tag: point.Tag) Pin { .active => active: { var rem = self.rows; var it = self.pages.last; - while (it) |page| : (it = page.prev) { - if (rem <= page.data.size.rows) break :active .{ - .page = page, - .y = page.data.size.rows - rem, + while (it) |node| : (it = node.prev) { + if (rem <= node.data.size.rows) break :active .{ + .node = node, + .y = node.data.size.rows - rem, }; - rem -= page.data.size.rows; + rem -= node.data.size.rows; } unreachable; // assertion: we always have enough rows for active @@ -3021,11 +3027,11 @@ pub fn getTopLeft(self: *const PageList, tag: point.Tag) Pin { pub fn getBottomRight(self: *const PageList, tag: point.Tag) ?Pin { return switch (tag) { .screen, .active => last: { - const page = self.pages.last.?; + const node = self.pages.last.?; break :last .{ - .page = page, - .y = page.data.size.rows - 1, - .x = page.data.size.cols - 1, + .node = node, + .y = node.data.size.rows - 1, + .x = node.data.size.cols - 1, }; }, @@ -3048,10 +3054,10 @@ pub fn getBottomRight(self: *const PageList, tag: point.Tag) ?Pin { /// rows, so it is not pub. This is only used for testing/debugging. fn totalRows(self: *const PageList) usize { var rows: usize = 0; - var page = self.pages.first; - while (page) |p| { - rows += p.data.size.rows; - page = p.next; + var node_ = self.pages.first; + while (node_) |node| { + rows += node.data.size.rows; + node_ = node.next; } return rows; @@ -3060,10 +3066,10 @@ fn totalRows(self: *const PageList) usize { /// The total number of pages in this list. fn totalPages(self: *const PageList) usize { var pages: usize = 0; - var page = self.pages.first; - while (page) |p| { + var node_ = self.pages.first; + while (node_) |node| { pages += 1; - page = p.next; + node_ = node.next; } return pages; @@ -3126,7 +3132,7 @@ fn markDirty(self: *PageList, pt: point.Point) void { /// all up to date as the pagelist is modified. This isn't cheap so callers /// should limit the number of active pins as much as possible. pub const Pin = struct { - page: *List.Node, + node: *List.Node, y: size.CellCountInt = 0, x: size.CellCountInt = 0, @@ -3134,7 +3140,7 @@ pub const Pin = struct { row: *pagepkg.Row, cell: *pagepkg.Cell, } { - const rac = self.page.data.getRowAndCell(self.x, self.y); + const rac = self.node.data.getRowAndCell(self.x, self.y); return .{ .row = rac.row, .cell = rac.cell }; } @@ -3145,7 +3151,7 @@ pub const Pin = struct { /// inclusive of the x coordinate of the pin. pub fn cells(self: Pin, subset: CellSubset) []pagepkg.Cell { const rac = self.rowAndCell(); - const all = self.page.data.getCells(rac.row); + const all = self.node.data.getCells(rac.row); return switch (subset) { .all => all, .left => all[0 .. self.x + 1], @@ -3156,26 +3162,26 @@ pub const Pin = struct { /// Returns the grapheme codepoints for the given cell. These are only /// the EXTRA codepoints and not the first codepoint. pub fn grapheme(self: Pin, cell: *const pagepkg.Cell) ?[]u21 { - return self.page.data.lookupGrapheme(cell); + return self.node.data.lookupGrapheme(cell); } /// Returns the style for the given cell in this pin. pub fn style(self: Pin, cell: *const pagepkg.Cell) stylepkg.Style { if (cell.style_id == stylepkg.default_id) return .{}; - return self.page.data.styles.get( - self.page.data.memory, + return self.node.data.styles.get( + self.node.data.memory, cell.style_id, ).*; } /// Check if this pin is dirty. pub fn isDirty(self: Pin) bool { - return self.page.data.isRowDirty(self.y); + return self.node.data.isRowDirty(self.y); } /// Mark this pin location as dirty. pub fn markDirty(self: Pin) void { - var set = self.page.data.dirtyBitSet(); + var set = self.node.data.dirtyBitSet(); set.set(self.y); } @@ -3289,7 +3295,7 @@ pub const Pin = struct { // graphics deletion code. pub fn isBetween(self: Pin, top: Pin, bottom: Pin) bool { if (build_config.slow_runtime_safety) { - if (top.page == bottom.page) { + if (top.node == bottom.node) { // If top is bottom, must be ordered. assert(top.y <= bottom.y); if (top.y == bottom.y) { @@ -3297,14 +3303,14 @@ pub const Pin = struct { } } else { // If top is not bottom, top must be before bottom. - var page = top.page.next; - while (page) |p| : (page = p.next) { - if (p == bottom.page) break; + var node_ = top.node.next; + while (node_) |node| : (node_ = node.next) { + if (node == bottom.node) break; } else assert(false); } } - if (self.page == top.page) { + if (self.node == top.node) { // If our pin is the top page and our y is less than the top y // then we can't possibly be between the top and bottom. if (self.y < top.y) return false; @@ -3316,7 +3322,7 @@ pub const Pin = struct { // at least the full top page and since we're the same page // we're in the range. if (self.y > top.y) { - return if (self.page == bottom.page) + return if (self.node == bottom.node) self.y <= bottom.y else true; @@ -3327,7 +3333,7 @@ pub const Pin = struct { assert(self.y == top.y); if (self.x < top.x) return false; } - if (self.page == bottom.page) { + if (self.node == bottom.node) { // Our page is the bottom page so we're between the top and // bottom if our y is less than the bottom y. if (self.y > bottom.y) return false; @@ -3345,11 +3351,11 @@ pub const Pin = struct { // Since our loop starts at top.page.next we need to check that // top != bottom because if they're the same then we can't possibly // be between them. - if (top.page == bottom.page) return false; - var page = top.page.next; - while (page) |p| : (page = p.next) { - if (p == bottom.page) break; - if (p == self.page) return true; + if (top.node == bottom.node) return false; + var node_ = top.node.next; + while (node_) |node| : (node_ = node.next) { + if (node == bottom.node) break; + if (node == self.node) return true; } return false; @@ -3359,22 +3365,22 @@ pub const Pin = struct { /// it requires traversing the linked list of pages. This should not /// be called in performance critical paths. pub fn before(self: Pin, other: Pin) bool { - if (self.page == other.page) { + if (self.node == other.node) { if (self.y < other.y) return true; if (self.y > other.y) return false; return self.x < other.x; } - var page = self.page.next; - while (page) |p| : (page = p.next) { - if (p == other.page) return true; + var node_ = self.node.next; + while (node_) |node| : (node_ = node.next) { + if (node == other.node) return true; } return false; } pub fn eql(self: Pin, other: Pin) bool { - return self.page == other.page and + return self.node == other.node and self.y == other.y and self.x == other.x; } @@ -3389,7 +3395,7 @@ pub const Pin = struct { /// Move the pin right n columns. n must fit within the size. pub fn right(self: Pin, n: usize) Pin { - assert(self.x + n < self.page.data.size.cols); + assert(self.x + n < self.node.data.size.cols); var result = self; result.x +|= std.math.cast(size.CellCountInt, n) orelse std.math.maxInt(size.CellCountInt); @@ -3424,33 +3430,33 @@ pub const Pin = struct { }, } { // Index fits within this page - const rows = self.page.data.size.rows - (self.y + 1); + const rows = self.node.data.size.rows - (self.y + 1); if (n <= rows) return .{ .offset = .{ - .page = self.page, + .node = self.node, .y = std.math.cast(size.CellCountInt, self.y + n) orelse std.math.maxInt(size.CellCountInt), .x = self.x, } }; // Need to traverse page links to find the page - var page: *List.Node = self.page; + var node: *List.Node = self.node; var n_left: usize = n - rows; while (true) { - page = page.next orelse return .{ .overflow = .{ + node = node.next orelse return .{ .overflow = .{ .end = .{ - .page = page, - .y = page.data.size.rows - 1, + .node = node, + .y = node.data.size.rows - 1, .x = self.x, }, .remaining = n_left, } }; - if (n_left <= page.data.size.rows) return .{ .offset = .{ - .page = page, + if (n_left <= node.data.size.rows) return .{ .offset = .{ + .node = node, .y = std.math.cast(size.CellCountInt, n_left - 1) orelse std.math.maxInt(size.CellCountInt), .x = self.x, } }; - n_left -= page.data.size.rows; + n_left -= node.data.size.rows; } } @@ -3465,33 +3471,33 @@ pub const Pin = struct { } { // Index fits within this page if (n <= self.y) return .{ .offset = .{ - .page = self.page, + .node = self.node, .y = std.math.cast(size.CellCountInt, self.y - n) orelse std.math.maxInt(size.CellCountInt), .x = self.x, } }; // Need to traverse page links to find the page - var page: *List.Node = self.page; + var node: *List.Node = self.node; var n_left: usize = n - self.y; while (true) { - page = page.prev orelse return .{ .overflow = .{ - .end = .{ .page = page, .y = 0, .x = self.x }, + node = node.prev orelse return .{ .overflow = .{ + .end = .{ .node = node, .y = 0, .x = self.x }, .remaining = n_left, } }; - if (n_left <= page.data.size.rows) return .{ .offset = .{ - .page = page, - .y = std.math.cast(size.CellCountInt, page.data.size.rows - n_left) orelse + if (n_left <= node.data.size.rows) return .{ .offset = .{ + .node = node, + .y = std.math.cast(size.CellCountInt, node.data.size.rows - n_left) orelse std.math.maxInt(size.CellCountInt), .x = self.x, } }; - n_left -= page.data.size.rows; + n_left -= node.data.size.rows; } } }; const Cell = struct { - page: *List.Node, + node: *List.Node, row: *pagepkg.Row, cell: *pagepkg.Cell, row_idx: size.CellCountInt, @@ -3502,7 +3508,7 @@ const Cell = struct { /// This is not very performant this is primarily used for assertions /// and testing. pub fn isDirty(self: Cell) bool { - return self.page.data.isRowDirty(self.row_idx); + return self.node.data.isRowDirty(self.row_idx); } /// Get the cell style. @@ -3510,8 +3516,8 @@ const Cell = struct { /// Not meant for non-test usage since this is inefficient. pub fn style(self: Cell) stylepkg.Style { if (self.cell.style_id == stylepkg.default_id) return .{}; - return self.page.data.styles.get( - self.page.data.memory, + return self.node.data.styles.get( + self.node.data.memory, self.cell.style_id, ).*; } @@ -3524,10 +3530,10 @@ const Cell = struct { /// carefully if you really need this. pub fn screenPoint(self: Cell) point.Point { var y: size.CellCountInt = self.row_idx; - var page = self.page; - while (page.prev) |prev| { - y += prev.data.size.rows; - page = prev; + var node_ = self.node; + while (node_.prev) |node| { + y += node.data.size.rows; + node_ = node; } return .{ .screen = .{ @@ -3549,7 +3555,7 @@ test "PageList" { // Active area should be the top try testing.expectEqual(Pin{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 0, .x = 0, }, s.getTopLeft(.active)); @@ -3592,7 +3598,7 @@ test "PageList pointFromPin active no history" { .x = 0, }, }, s.pointFromPin(.active, .{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 0, .x = 0, }).?); @@ -3604,7 +3610,7 @@ test "PageList pointFromPin active no history" { .x = 4, }, }, s.pointFromPin(.active, .{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 2, .x = 4, }).?); @@ -3626,7 +3632,7 @@ test "PageList pointFromPin active with history" { .x = 2, }, }, s.pointFromPin(.active, .{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 30, .x = 2, }).?); @@ -3635,7 +3641,7 @@ test "PageList pointFromPin active with history" { // In history, invalid { try testing.expect(s.pointFromPin(.active, .{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 21, .x = 2, }) == null); @@ -3660,7 +3666,7 @@ test "PageList pointFromPin active from prior page" { .x = 2, }, }, s.pointFromPin(.active, .{ - .page = s.pages.last.?, + .node = s.pages.last.?, .y = 0, .x = 2, }).?); @@ -3669,7 +3675,7 @@ test "PageList pointFromPin active from prior page" { // Prior page { try testing.expect(s.pointFromPin(.active, .{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 0, .x = 0, }) == null); @@ -3698,7 +3704,7 @@ test "PageList pointFromPin traverse pages" { .x = 2, }, }, s.pointFromPin(.screen, .{ - .page = s.pages.last.?.prev.?, + .node = s.pages.last.?.prev.?, .y = 5, .x = 2, }).?); @@ -3707,7 +3713,7 @@ test "PageList pointFromPin traverse pages" { // Prior page { try testing.expect(s.pointFromPin(.active, .{ - .page = s.pages.first.?, + .node = s.pages.first.?, .y = 0, .x = 0, }) == null); @@ -4159,7 +4165,7 @@ test "PageList grow allocate" { try testing.expect(last_node.next.? == new); { const cell = s.getCell(.{ .active = .{ .y = s.rows - 1 } }).?; - try testing.expect(cell.page == new); + try testing.expect(cell.node == new); try testing.expectEqual(point.Point{ .screen = .{ .x = 0, .y = last.capacity.rows, @@ -4195,7 +4201,7 @@ test "PageList grow prune scrollback" { // Create a tracked pin in the first page const p = try s.trackPin(s.pin(.{ .screen = .{} }).?); defer s.untrackPin(p); - try testing.expect(p.page == s.pages.first.?); + try testing.expect(p.node == s.pages.first.?); // Next should create a new page, but it should reuse our first // page since we're at max size. @@ -4208,7 +4214,7 @@ test "PageList grow prune scrollback" { try testing.expectEqual(page1_node, s.pages.last.?); // Our tracked pin should point to the top-left of the first page - try testing.expect(p.page == s.pages.first.?); + try testing.expect(p.node == s.pages.first.?); try testing.expect(p.x == 0); try testing.expect(p.y == 0); } @@ -4356,7 +4362,7 @@ test "PageList pageIterator single page" { var it = s.pageIterator(.right_down, .{ .active = .{} }, null); { const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.first.?); + try testing.expect(chunk.node == s.pages.first.?); try testing.expectEqual(@as(usize, 0), chunk.start); try testing.expectEqual(@as(usize, s.rows), chunk.end); } @@ -4384,14 +4390,14 @@ test "PageList pageIterator two pages" { var it = s.pageIterator(.right_down, .{ .active = .{} }, null); { const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.first.?); - const start = chunk.page.data.size.rows - s.rows + 1; + try testing.expect(chunk.node == s.pages.first.?); + const start = chunk.node.data.size.rows - s.rows + 1; try testing.expectEqual(start, chunk.start); - try testing.expectEqual(chunk.page.data.size.rows, chunk.end); + try testing.expectEqual(chunk.node.data.size.rows, chunk.end); } { const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.last.?); + try testing.expect(chunk.node == s.pages.last.?); const start: usize = 0; try testing.expectEqual(start, chunk.start); try testing.expectEqual(start + 1, chunk.end); @@ -4419,7 +4425,7 @@ test "PageList pageIterator history two pages" { { const active_tl = s.getTopLeft(.active); const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.first.?); + try testing.expect(chunk.node == s.pages.first.?); const start: usize = 0; try testing.expectEqual(start, chunk.start); try testing.expectEqual(active_tl.y, chunk.end); @@ -4441,7 +4447,7 @@ test "PageList pageIterator reverse single page" { var it = s.pageIterator(.left_up, .{ .active = .{} }, null); { const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.first.?); + try testing.expect(chunk.node == s.pages.first.?); try testing.expectEqual(@as(usize, 0), chunk.start); try testing.expectEqual(@as(usize, s.rows), chunk.end); } @@ -4470,7 +4476,7 @@ test "PageList pageIterator reverse two pages" { var count: usize = 0; { const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.last.?); + try testing.expect(chunk.node == s.pages.last.?); const start: usize = 0; try testing.expectEqual(start, chunk.start); try testing.expectEqual(start + 1, chunk.end); @@ -4478,10 +4484,10 @@ test "PageList pageIterator reverse two pages" { } { const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.first.?); - const start = chunk.page.data.size.rows - s.rows + 1; + try testing.expect(chunk.node == s.pages.first.?); + const start = chunk.node.data.size.rows - s.rows + 1; try testing.expectEqual(start, chunk.start); - try testing.expectEqual(chunk.page.data.size.rows, chunk.end); + try testing.expectEqual(chunk.node.data.size.rows, chunk.end); count += chunk.end - chunk.start; } try testing.expect(it.next() == null); @@ -4508,7 +4514,7 @@ test "PageList pageIterator reverse history two pages" { { const active_tl = s.getTopLeft(.active); const chunk = it.next().?; - try testing.expect(chunk.page == s.pages.first.?); + try testing.expect(chunk.node == s.pages.first.?); const start: usize = 0; try testing.expectEqual(start, chunk.start); try testing.expectEqual(active_tl.y, chunk.end); @@ -4688,7 +4694,7 @@ test "PageList erase row with tracked pin resets to top-left" { try testing.expectEqual(s.rows, s.totalRows()); // Our pin should move to the first page - try testing.expectEqual(s.pages.first.?, p.page); + try testing.expectEqual(s.pages.first.?, p.node); try testing.expectEqual(@as(usize, 0), p.y); try testing.expectEqual(@as(usize, 0), p.x); } @@ -4709,7 +4715,7 @@ test "PageList erase row with tracked pin shifts" { try testing.expectEqual(s.rows, s.totalRows()); // Our pin should move to the first page - try testing.expectEqual(s.pages.first.?, p.page); + try testing.expectEqual(s.pages.first.?, p.node); try testing.expectEqual(@as(usize, 0), p.y); try testing.expectEqual(@as(usize, 2), p.x); } @@ -4730,7 +4736,7 @@ test "PageList erase row with tracked pin is erased" { try testing.expectEqual(s.rows, s.totalRows()); // Our pin should move to the first page - try testing.expectEqual(s.pages.first.?, p.page); + try testing.expectEqual(s.pages.first.?, p.node); try testing.expectEqual(@as(usize, 0), p.y); try testing.expectEqual(@as(usize, 0), p.x); } @@ -4751,7 +4757,7 @@ test "PageList erase resets viewport to active if moves within active" { // Move our viewport to the top s.scroll(.{ .delta_row = -@as(isize, @intCast(s.totalRows())) }); try testing.expect(s.viewport == .pin); - try testing.expect(s.viewport_pin.page == s.pages.first.?); + try testing.expect(s.viewport_pin.node == s.pages.first.?); // Erase the entire history, we should be back to just our active set. s.eraseRows(.{ .history = .{} }, null); @@ -4774,12 +4780,12 @@ test "PageList erase resets viewport if inside erased page but not active" { // Move our viewport to the top s.scroll(.{ .delta_row = -@as(isize, @intCast(s.totalRows())) }); try testing.expect(s.viewport == .pin); - try testing.expect(s.viewport_pin.page == s.pages.first.?); + try testing.expect(s.viewport_pin.node == s.pages.first.?); // Erase the entire history, we should be back to just our active set. s.eraseRows(.{ .history = .{} }, .{ .history = .{ .y = 2 } }); try testing.expect(s.viewport == .pin); - try testing.expect(s.viewport_pin.page == s.pages.first.?); + try testing.expect(s.viewport_pin.node == s.pages.first.?); } test "PageList erase resets viewport to active if top is inside active" { @@ -4868,15 +4874,15 @@ test "PageList eraseRowBounded less than full row" { try testing.expect(s.isDirty(.{ .active = .{ .x = 0, .y = 7 } })); try testing.expect(!s.isDirty(.{ .active = .{ .x = 0, .y = 8 } })); - try testing.expectEqual(s.pages.first.?, p_top.page); + try testing.expectEqual(s.pages.first.?, p_top.node); try testing.expectEqual(@as(usize, 4), p_top.y); try testing.expectEqual(@as(usize, 0), p_top.x); - try testing.expectEqual(s.pages.first.?, p_bot.page); + try testing.expectEqual(s.pages.first.?, p_bot.node); try testing.expectEqual(@as(usize, 7), p_bot.y); try testing.expectEqual(@as(usize, 0), p_bot.x); - try testing.expectEqual(s.pages.first.?, p_out.page); + try testing.expectEqual(s.pages.first.?, p_out.node); try testing.expectEqual(@as(usize, 9), p_out.y); try testing.expectEqual(@as(usize, 0), p_out.x); } @@ -4902,7 +4908,7 @@ test "PageList eraseRowBounded with pin at top" { try testing.expect(s.isDirty(.{ .active = .{ .x = 0, .y = 2 } })); try testing.expect(!s.isDirty(.{ .active = .{ .x = 0, .y = 3 } })); - try testing.expectEqual(s.pages.first.?, p_top.page); + try testing.expectEqual(s.pages.first.?, p_top.node); try testing.expectEqual(@as(usize, 0), p_top.y); try testing.expectEqual(@as(usize, 0), p_top.x); } @@ -4932,11 +4938,11 @@ test "PageList eraseRowBounded full rows single page" { } })); // Our pin should move to the first page - try testing.expectEqual(s.pages.first.?, p_in.page); + try testing.expectEqual(s.pages.first.?, p_in.node); try testing.expectEqual(@as(usize, 6), p_in.y); try testing.expectEqual(@as(usize, 0), p_in.x); - try testing.expectEqual(s.pages.first.?, p_out.page); + try testing.expectEqual(s.pages.first.?, p_out.node); try testing.expectEqual(@as(usize, 8), p_out.y); try testing.expectEqual(@as(usize, 0), p_out.x); } @@ -4968,19 +4974,19 @@ test "PageList eraseRowBounded full rows two pages" { defer s.untrackPin(p_out); { - try testing.expectEqual(s.pages.last.?.prev.?, p_first.page); - try testing.expectEqual(@as(usize, p_first.page.data.size.rows - 1), p_first.y); + try testing.expectEqual(s.pages.last.?.prev.?, p_first.node); + try testing.expectEqual(@as(usize, p_first.node.data.size.rows - 1), p_first.y); try testing.expectEqual(@as(usize, 0), p_first.x); - try testing.expectEqual(s.pages.last.?.prev.?, p_first_out.page); - try testing.expectEqual(@as(usize, p_first_out.page.data.size.rows - 2), p_first_out.y); + try testing.expectEqual(s.pages.last.?.prev.?, p_first_out.node); + try testing.expectEqual(@as(usize, p_first_out.node.data.size.rows - 2), p_first_out.y); try testing.expectEqual(@as(usize, 0), p_first_out.x); - try testing.expectEqual(s.pages.last.?, p_in.page); + try testing.expectEqual(s.pages.last.?, p_in.node); try testing.expectEqual(@as(usize, 3), p_in.y); try testing.expectEqual(@as(usize, 0), p_in.x); - try testing.expectEqual(s.pages.last.?, p_out.page); + try testing.expectEqual(s.pages.last.?, p_out.node); try testing.expectEqual(@as(usize, 4), p_out.y); try testing.expectEqual(@as(usize, 0), p_out.x); } @@ -4996,22 +5002,22 @@ test "PageList eraseRowBounded full rows two pages" { } })); // In page in first page is shifted - try testing.expectEqual(s.pages.last.?.prev.?, p_first.page); - try testing.expectEqual(@as(usize, p_first.page.data.size.rows - 2), p_first.y); + try testing.expectEqual(s.pages.last.?.prev.?, p_first.node); + try testing.expectEqual(@as(usize, p_first.node.data.size.rows - 2), p_first.y); try testing.expectEqual(@as(usize, 0), p_first.x); // Out page in first page should not be shifted - try testing.expectEqual(s.pages.last.?.prev.?, p_first_out.page); - try testing.expectEqual(@as(usize, p_first_out.page.data.size.rows - 2), p_first_out.y); + try testing.expectEqual(s.pages.last.?.prev.?, p_first_out.node); + try testing.expectEqual(@as(usize, p_first_out.node.data.size.rows - 2), p_first_out.y); try testing.expectEqual(@as(usize, 0), p_first_out.x); // In page is shifted - try testing.expectEqual(s.pages.last.?, p_in.page); + try testing.expectEqual(s.pages.last.?, p_in.node); try testing.expectEqual(@as(usize, 2), p_in.y); try testing.expectEqual(@as(usize, 0), p_in.x); // Out page is not shifted - try testing.expectEqual(s.pages.last.?, p_out.page); + try testing.expectEqual(s.pages.last.?, p_out.node); try testing.expectEqual(@as(usize, 4), p_out.y); try testing.expectEqual(@as(usize, 0), p_out.x); } @@ -5669,7 +5675,7 @@ test "PageList resize (no reflow) less cols" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 5), cells.len); } } @@ -5693,7 +5699,7 @@ test "PageList resize (no reflow) less cols pin in trimmed cols" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 5), cells.len); } @@ -5729,7 +5735,7 @@ test "PageList resize (no reflow) less cols clears graphemes" { var it = s.pageIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |chunk| { - try testing.expectEqual(@as(usize, 0), chunk.page.data.graphemeCount()); + try testing.expectEqual(@as(usize, 0), chunk.node.data.graphemeCount()); } } @@ -5748,7 +5754,7 @@ test "PageList resize (no reflow) more cols" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 10), cells.len); } } @@ -5921,7 +5927,7 @@ test "PageList resize (no reflow) less cols then more cols" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 5), cells.len); } } @@ -5941,7 +5947,7 @@ test "PageList resize (no reflow) less rows and cols" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 5), cells.len); } } @@ -5962,7 +5968,7 @@ test "PageList resize (no reflow) more rows and less cols" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 5), cells.len); } } @@ -6002,7 +6008,7 @@ test "PageList resize (no reflow) empty screen" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 10), cells.len); } } @@ -6041,7 +6047,7 @@ test "PageList resize (no reflow) more cols forces smaller cap" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, cap2.cols), cells.len); try testing.expectEqual(@as(u21, 'A'), cells[0].content.codepoint); } @@ -6146,7 +6152,7 @@ test "PageList resize reflow more cols no wrapped rows" { var it = s.rowIterator(.right_down, .{ .screen = .{} }, null); while (it.next()) |offset| { const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 10), cells.len); try testing.expectEqual(@as(u21, 'A'), cells[0].content.codepoint); } @@ -6197,7 +6203,7 @@ test "PageList resize reflow more cols wrapped rows" { // First row should be unwrapped const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 4), cells.len); try testing.expectEqual(@as(u21, 'A'), cells[0].content.codepoint); @@ -6453,7 +6459,7 @@ test "PageList resize reflow more cols wrap across page boundary cursor in secon // Put a tracked pin in wrapped row on the last page const p = try s.trackPin(s.pin(.{ .active = .{ .x = 1, .y = 9 } }).?); defer s.untrackPin(p); - try testing.expect(p.page == s.pages.last.?); + try testing.expect(p.node == s.pages.last.?); // We expect one fewer rows since we unwrapped a row. const end_rows = s.totalRows() - 1; @@ -6537,7 +6543,7 @@ test "PageList resize reflow less cols wrap across page boundary cursor in secon // Put a tracked pin in wrapped row on the last page const p = try s.trackPin(s.pin(.{ .active = .{ .x = 2, .y = 5 } }).?); defer s.untrackPin(p); - try testing.expect(p.page == s.pages.last.?); + try testing.expect(p.node == s.pages.last.?); try testing.expect(p.y == 0); // PageList.diagram -> @@ -7235,7 +7241,7 @@ test "PageList resize reflow less cols no wrapped rows" { var offset_copy = offset; offset_copy.x = @intCast(x); const rac = offset_copy.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(usize, 5), cells.len); try testing.expectEqual(@as(u21, @intCast(x)), cells[x].content.codepoint); } @@ -7279,7 +7285,7 @@ test "PageList resize reflow less cols wrapped rows" { // First row should be wrapped const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); @@ -7287,7 +7293,7 @@ test "PageList resize reflow less cols wrapped rows" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 2), cells[0].content.codepoint); @@ -7296,7 +7302,7 @@ test "PageList resize reflow less cols wrapped rows" { // First row should be wrapped const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); @@ -7304,7 +7310,7 @@ test "PageList resize reflow less cols wrapped rows" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 2), cells[0].content.codepoint); @@ -7355,7 +7361,7 @@ test "PageList resize reflow less cols wrapped rows with graphemes" { // First row should be wrapped const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); @@ -7363,7 +7369,7 @@ test "PageList resize reflow less cols wrapped rows with graphemes" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expect(rac.row.grapheme); try testing.expectEqual(@as(usize, 2), cells.len); @@ -7377,7 +7383,7 @@ test "PageList resize reflow less cols wrapped rows with graphemes" { // First row should be wrapped const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); @@ -7385,7 +7391,7 @@ test "PageList resize reflow less cols wrapped rows with graphemes" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expect(rac.row.grapheme); try testing.expectEqual(@as(usize, 2), cells.len); @@ -7721,7 +7727,7 @@ test "PageList resize reflow less cols blank lines" { // First row should be wrapped const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); @@ -7729,7 +7735,7 @@ test "PageList resize reflow less cols blank lines" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 2), cells[0].content.codepoint); @@ -7777,7 +7783,7 @@ test "PageList resize reflow less cols blank lines between" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); @@ -7785,7 +7791,7 @@ test "PageList resize reflow less cols blank lines between" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 2), cells[0].content.codepoint); @@ -7824,7 +7830,7 @@ test "PageList resize reflow less cols blank lines between no scrollback" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 'A'), cells[0].content.codepoint); @@ -7832,13 +7838,13 @@ test "PageList resize reflow less cols blank lines between no scrollback" { { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint); } { const offset = it.next().?; const rac = offset.rowAndCell(); - const cells = offset.page.data.getCells(rac.row); + const cells = offset.node.data.getCells(rac.row); try testing.expect(!rac.row.wrap); try testing.expectEqual(@as(usize, 2), cells.len); try testing.expectEqual(@as(u21, 'C'), cells[0].content.codepoint); @@ -7931,8 +7937,8 @@ test "PageList resize reflow less cols copy style" { const style_id = rac.cell.style_id; try testing.expect(style_id != 0); - const style = offset.page.data.styles.get( - offset.page.data.memory, + const style = offset.node.data.styles.get( + offset.node.data.memory, style_id, ); try testing.expect(style.flags.bold); diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index e9d2fccd8..4f3fe270e 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -203,7 +203,7 @@ pub fn init( errdefer pages.deinit(); // Create our tracked pin for the cursor. - const page_pin = try pages.trackPin(.{ .page = pages.pages.first.? }); + const page_pin = try pages.trackPin(.{ .node = pages.pages.first.? }); errdefer pages.untrackPin(page_pin); const page_rac = page_pin.rowAndCell(); @@ -331,7 +331,7 @@ pub fn clonePool( }; } - const page_pin = try pages.trackPin(.{ .page = pages.pages.first.? }); + const page_pin = try pages.trackPin(.{ .node = pages.pages.first.? }); const page_rac = page_pin.rowAndCell(); break :cursor .{ .x = 0, @@ -376,7 +376,7 @@ pub fn clonePool( if (!sel.contains(self, clone_top)) break :sel null; } - break :start try pages.trackPin(.{ .page = pages.pages.first.? }); + break :start try pages.trackPin(.{ .node = pages.pages.first.? }); }; const end_pin = pin_remap.get(ordered.br) orelse end: { @@ -414,21 +414,21 @@ pub fn clonePool( /// cursor page. pub fn adjustCapacity( self: *Screen, - page: *PageList.List.Node, + node: *PageList.List.Node, adjustment: PageList.AdjustCapacity, ) PageList.AdjustCapacityError!*PageList.List.Node { // If the page being modified isn't our cursor page then // this is a quick operation because we have no additional // accounting. - if (page != self.cursor.page_pin.page) { - return try self.pages.adjustCapacity(page, adjustment); + if (node != self.cursor.page_pin.node) { + return try self.pages.adjustCapacity(node, adjustment); } // We're modifying the cursor page. When we adjust the // capacity below it will be short the ref count on our // current style and hyperlink, so we need to init those. - const node = try self.pages.adjustCapacity(page, adjustment); - const new_page = &node.data; + const new_node = try self.pages.adjustCapacity(node, adjustment); + const new_page: *Page = &new_node.data; // All additions below have unreachable catches because when // we adjust cap we should have enough memory to fit the @@ -460,7 +460,7 @@ pub fn adjustCapacity( // So our page row/cell and so on are all off. self.cursorReload(); - return node; + return new_node; } pub fn cursorCellRight(self: *Screen, n: size.CellCountInt) *pagepkg.Cell { @@ -636,13 +636,14 @@ pub fn cursorDownScroll(self: *Screen) !void { // so our cursor is in the correct place we just have to clear // the cells. if (self.pages.rows == 1) { + const page: *Page = &self.cursor.page_pin.node.data; self.clearCells( - &self.cursor.page_pin.page.data, + page, self.cursor.page_row, - self.cursor.page_pin.page.data.getCells(self.cursor.page_row), + page.getCells(self.cursor.page_row), ); - var dirty = self.cursor.page_pin.page.data.dirtyBitSet(); + var dirty = page.dirtyBitSet(); dirty.set(0); } else { // eraseRow will shift everything below it up. @@ -684,7 +685,7 @@ pub fn cursorDownScroll(self: *Screen) !void { // was on was pruned. In this case, grow() moves the pin to // the top-left of the new page. This effectively moves it by // one already, we just need to fix up the x value. - const page_pin = if (old_pin.page == self.cursor.page_pin.page) + const page_pin = if (old_pin.node == self.cursor.page_pin.node) self.cursor.page_pin.down(1).? else reuse: { var pin = self.cursor.page_pin.*; @@ -714,10 +715,11 @@ pub fn cursorDownScroll(self: *Screen) !void { // Clear the new row so it gets our bg color. We only do this // if we have a bg color at all. if (self.cursor.style.bg_color != .none) { + const page: *Page = &page_pin.node.data; self.clearCells( - &page_pin.page.data, + page, self.cursor.page_row, - page_pin.page.data.getCells(self.cursor.page_row), + page.getCells(self.cursor.page_row), ); } } @@ -753,15 +755,15 @@ pub fn cursorScrollAbove(self: *Screen) !void { } else { // In this case, it means grow() didn't allocate a new page. - if (self.cursor.page_pin.page == self.pages.pages.last) { + if (self.cursor.page_pin.node == self.pages.pages.last) { // If we're on the last page we can do a very fast path because // all the rows we need to move around are within a single page. - assert(old_pin.page == self.cursor.page_pin.page); + assert(old_pin.node == self.cursor.page_pin.node); self.cursor.page_pin.* = self.cursor.page_pin.down(1).?; const pin = self.cursor.page_pin; - const page = &self.cursor.page_pin.page.data; + const page: *Page = &self.cursor.page_pin.node.data; // Rotate the rows so that the newly created empty row is at the // beginning. e.g. [ 0 1 2 3 ] in to [ 3 0 1 2 ]. @@ -822,7 +824,7 @@ fn cursorScrollAboveRotate(self: *Screen) !void { // Go through each of the pages following our pin, shift all rows // down by one, and copy the last row of the previous page. var current = self.pages.pages.last.?; - while (current != self.cursor.page_pin.page) : (current = current.prev.?) { + while (current != self.cursor.page_pin.node) : (current = current.prev.?) { const prev = current.prev.?; const prev_page = &prev.data; const cur_page = ¤t.data; @@ -846,7 +848,7 @@ fn cursorScrollAboveRotate(self: *Screen) !void { // Our current is our cursor page, we need to rotate down from // our cursor and clear our row. - assert(current == self.cursor.page_pin.page); + assert(current == self.cursor.page_pin.node); const cur_page = ¤t.data; const cur_rows = cur_page.rows.ptr(cur_page.memory.ptr); fastmem.rotateOnceR(Row, cur_rows[self.cursor.page_pin.y..cur_page.size.rows]); @@ -922,7 +924,7 @@ pub fn cursorCopy(self: *Screen, other: Cursor, opts: struct { // If the other cursor had a hyperlink, add it to ours. if (opts.hyperlink and other.hyperlink_id != 0) { // Get the hyperlink from the other cursor's page. - const other_page = &other.page_pin.page.data; + const other_page = &other.page_pin.node.data; const other_link = other_page.hyperlink_set.get(other_page.memory, other.hyperlink_id); const uri = other_link.uri.offset.ptr(other_page.memory)[0..other_link.uri.len]; @@ -957,7 +959,7 @@ fn cursorChangePin(self: *Screen, new: Pin) void { // If our pin is on the same page, then we can just update the pin. // We don't need to migrate any state. - if (self.cursor.page_pin.page == new.page) { + if (self.cursor.page_pin.node == new.node) { self.cursor.page_pin.* = new; return; } @@ -974,7 +976,7 @@ fn cursorChangePin(self: *Screen, new: Pin) void { // If we have a hyperlink then we need to release it from the old page. if (self.cursor.hyperlink != null) { - const old_page = &self.cursor.page_pin.page.data; + const old_page: *Page = &self.cursor.page_pin.node.data; old_page.hyperlink_set.release(old_page.memory, self.cursor.hyperlink_id); } @@ -1049,12 +1051,12 @@ pub fn cursorResetWrap(self: *Screen) void { // If the last cell in the row is a spacer head we need to clear it. const cells = self.cursor.page_pin.cells(.all); - const cell = cells[self.cursor.page_pin.page.data.size.cols - 1]; + const cell = cells[self.cursor.page_pin.node.data.size.cols - 1]; if (cell.wide == .spacer_head) { self.clearCells( - &self.cursor.page_pin.page.data, + &self.cursor.page_pin.node.data, page_row, - cells[self.cursor.page_pin.page.data.size.cols - 1 ..][0..1], + cells[self.cursor.page_pin.node.data.size.cols - 1 ..][0..1], ); } } @@ -1144,22 +1146,22 @@ pub fn clearRows( var it = self.pages.pageIterator(.right_down, tl, bl); while (it.next()) |chunk| { // Mark everything in this chunk as dirty - var dirty = chunk.page.data.dirtyBitSet(); + var dirty = chunk.node.data.dirtyBitSet(); dirty.setRangeValue(.{ .start = chunk.start, .end = chunk.end }, true); for (chunk.rows()) |*row| { const cells_offset = row.cells; - const cells_multi: [*]Cell = row.cells.ptr(chunk.page.data.memory); + const cells_multi: [*]Cell = row.cells.ptr(chunk.node.data.memory); const cells = cells_multi[0..self.pages.cols]; // Clear all cells if (protected) { - self.clearUnprotectedCells(&chunk.page.data, row, cells); + self.clearUnprotectedCells(&chunk.node.data, row, cells); // We need to preserve other row attributes since we only // cleared unprotected cells. row.cells = cells_offset; } else { - self.clearCells(&chunk.page.data, row, cells); + self.clearCells(&chunk.node.data, row, cells); row.* = .{ .cells = cells_offset }; } } @@ -1294,8 +1296,8 @@ pub fn clearPrompt(self: *Screen) void { var clear_it = top.rowIterator(.right_down, null); while (clear_it.next()) |p| { const row = p.rowAndCell().row; - p.page.data.clearCells(row, 0, p.page.data.size.cols); - p.page.data.assertIntegrity(); + p.node.data.clearCells(row, 0, p.node.data.size.cols); + p.node.data.assertIntegrity(); } } } @@ -1336,12 +1338,12 @@ pub fn splitCellBoundary( self: *Screen, x: size.CellCountInt, ) void { - const page = &self.cursor.page_pin.page.data; + const page = &self.cursor.page_pin.node.data; page.pauseIntegrityChecks(true); defer page.pauseIntegrityChecks(false); - const cols = self.cursor.page_pin.page.data.size.cols; + const cols = self.cursor.page_pin.node.data.size.cols; // `x` may be up to an INCLUDING `cols`, since that signifies splitting // the boundary to the right of the final cell in the row. @@ -1385,12 +1387,12 @@ pub fn splitCellBoundary( if (self.cursor.page_pin.up(1)) |p_row| { const p_rac = p_row.rowAndCell(); const p_cells = p_row.cells(.all); - const p_cell = p_cells[p_row.page.data.size.cols - 1]; + const p_cell = p_cells[p_row.node.data.size.cols - 1]; if (p_cell.wide == .spacer_head) { self.clearCells( - &p_row.page.data, + &p_row.node.data, p_rac.row, - p_cells[p_row.page.data.size.cols - 1 ..][0..1], + p_cells[p_row.node.data.size.cols - 1 ..][0..1], ); } } @@ -1506,7 +1508,7 @@ fn resizeInternal( if (self.cursor.hyperlink_id != 0) { // Note we do NOT use endHyperlink because we want to keep // our allocated self.cursor.hyperlink valid. - var page = &self.cursor.page_pin.page.data; + var page = &self.cursor.page_pin.node.data; page.hyperlink_set.release(page.memory, self.cursor.hyperlink_id); self.cursor.hyperlink_id = 0; self.cursor.hyperlink = null; @@ -1701,7 +1703,7 @@ pub fn setAttribute(self: *Screen, attr: sgr.Attribute) !void { /// Call this whenever you manually change the cursor style. pub fn manualStyleUpdate(self: *Screen) !void { - var page = &self.cursor.page_pin.page.data; + var page: *Page = &self.cursor.page_pin.node.data; // std.log.warn("active styles={}", .{page.styles.count()}); @@ -1730,7 +1732,7 @@ pub fn manualStyleUpdate(self: *Screen) !void { // and double the style capacity for it if it was // full. const node = try self.adjustCapacity( - self.cursor.page_pin.page, + self.cursor.page_pin.node, switch (err) { error.OutOfMemory => .{ .styles = page.capacity.styles * 2 }, error.NeedsRehash => .{}, @@ -1749,8 +1751,8 @@ pub fn manualStyleUpdate(self: *Screen) !void { /// Append a grapheme to the given cell within the current cursor row. pub fn appendGrapheme(self: *Screen, cell: *Cell, cp: u21) !void { - defer self.cursor.page_pin.page.data.assertIntegrity(); - self.cursor.page_pin.page.data.appendGrapheme( + defer self.cursor.page_pin.node.data.assertIntegrity(); + self.cursor.page_pin.node.data.appendGrapheme( self.cursor.page_row, cell, cp, @@ -1768,7 +1770,7 @@ pub fn appendGrapheme(self: *Screen, cell: *Cell, cp: u21) !void { // Adjust our capacity. This will update our cursor page pin and // force us to reload. - const original_node = self.cursor.page_pin.page; + const original_node = self.cursor.page_pin.node; const new_bytes = original_node.data.capacity.grapheme_bytes * 2; _ = try self.adjustCapacity( original_node, @@ -1783,7 +1785,7 @@ pub fn appendGrapheme(self: *Screen, cell: *Cell, cp: u21) !void { .gt => self.cursorCellRight(@intCast(cell_idx - self.cursor.x)), }; - try self.cursor.page_pin.page.data.appendGrapheme( + try self.cursor.page_pin.node.data.appendGrapheme( self.cursor.page_row, reloaded_cell, cp, @@ -1827,19 +1829,19 @@ pub fn startHyperlink( // strings table is out of memory, adjust it up error.StringsOutOfMemory => _ = try self.adjustCapacity( - self.cursor.page_pin.page, - .{ .string_bytes = self.cursor.page_pin.page.data.capacity.string_bytes * 2 }, + self.cursor.page_pin.node, + .{ .string_bytes = self.cursor.page_pin.node.data.capacity.string_bytes * 2 }, ), // hyperlink set is out of memory, adjust it up error.SetOutOfMemory => _ = try self.adjustCapacity( - self.cursor.page_pin.page, - .{ .hyperlink_bytes = self.cursor.page_pin.page.data.capacity.hyperlink_bytes * 2 }, + self.cursor.page_pin.node, + .{ .hyperlink_bytes = self.cursor.page_pin.node.data.capacity.hyperlink_bytes * 2 }, ), // hyperlink set is too full, rehash it error.SetNeedsRehash => _ = try self.adjustCapacity( - self.cursor.page_pin.page, + self.cursor.page_pin.node, .{}, ), } @@ -1866,7 +1868,7 @@ fn startHyperlinkOnce( errdefer link.deinit(self.alloc); // Insert the hyperlink into page memory - var page = &self.cursor.page_pin.page.data; + var page = &self.cursor.page_pin.node.data; const id: hyperlink.Id = try page.insertHyperlink(link.*); // Save it all @@ -1893,7 +1895,7 @@ pub fn endHyperlink(self: *Screen) void { // how RefCountedSet works). This causes some memory fragmentation but // is fine because if it is ever pruned the context deleted callback // will be called. - var page = &self.cursor.page_pin.page.data; + var page: *Page = &self.cursor.page_pin.node.data; page.hyperlink_set.release(page.memory, self.cursor.hyperlink_id); self.cursor.hyperlink.?.deinit(self.alloc); self.alloc.destroy(self.cursor.hyperlink.?); @@ -1905,7 +1907,7 @@ pub fn endHyperlink(self: *Screen) void { pub fn cursorSetHyperlink(self: *Screen) !void { assert(self.cursor.hyperlink_id != 0); - var page = &self.cursor.page_pin.page.data; + var page = &self.cursor.page_pin.node.data; if (page.setHyperlink( self.cursor.page_row, self.cursor.page_cell, @@ -1918,7 +1920,7 @@ pub fn cursorSetHyperlink(self: *Screen) !void { // hyperlink_map is out of space, realloc the page to be larger error.HyperlinkMapOutOfMemory => { _ = try self.adjustCapacity( - self.cursor.page_pin.page, + self.cursor.page_pin.node, .{ .hyperlink_bytes = page.capacity.hyperlink_bytes * 2 }, ); @@ -2021,7 +2023,7 @@ pub fn selectionString(self: *Screen, alloc: Allocator, opts: SelectionString) ! while (page_it.next()) |chunk| { const rows = chunk.rows(); for (rows, chunk.start..) |row, y| { - const cells_ptr = row.cells.ptr(chunk.page.data.memory); + const cells_ptr = row.cells.ptr(chunk.node.data.memory); const start_x = if (row_count == 0 or sel_ordered.rectangle) sel_start.x @@ -2048,20 +2050,20 @@ pub fn selectionString(self: *Screen, alloc: Allocator, opts: SelectionString) ! try strbuilder.appendSlice(buf[0..encode_len]); if (mapbuilder) |*b| { for (0..encode_len) |_| try b.append(.{ - .page = chunk.page, + .node = chunk.node, .y = @intCast(y), .x = @intCast(x), }); } } if (cell.hasGrapheme()) { - const cps = chunk.page.data.lookupGrapheme(cell).?; + const cps = chunk.node.data.lookupGrapheme(cell).?; for (cps) |cp| { const encode_len = try std.unicode.utf8Encode(cp, &buf); try strbuilder.appendSlice(buf[0..encode_len]); if (mapbuilder) |*b| { for (0..encode_len) |_| try b.append(.{ - .page = chunk.page, + .node = chunk.node, .y = @intCast(y), .x = @intCast(x), }); @@ -2070,16 +2072,16 @@ pub fn selectionString(self: *Screen, alloc: Allocator, opts: SelectionString) ! } } - const is_final_row = chunk.page == sel_end.page and y == sel_end.y; + const is_final_row = chunk.node == sel_end.node and y == sel_end.y; if (!is_final_row and (!row.wrap or sel_ordered.rectangle)) { try strbuilder.append('\n'); if (mapbuilder) |*b| try b.append(.{ - .page = chunk.page, + .node = chunk.node, .y = @intCast(y), - .x = chunk.page.data.size.cols - 1, + .x = chunk.node.data.size.cols - 1, }); } @@ -2209,14 +2211,14 @@ pub fn selectLine(self: *const Screen, opts: SelectLine) ?Selection { const current_prompt = row.semantic_prompt.promptOrInput(); if (current_prompt != v) { var prev = p.up(1).?; - prev.x = p.page.data.size.cols - 1; + prev.x = p.node.data.size.cols - 1; break :end_pin prev; } } if (!row.wrap) { var copy = p; - copy.x = p.page.data.size.cols - 1; + copy.x = p.node.data.size.cols - 1; break :end_pin copy; } } @@ -2417,7 +2419,7 @@ pub fn selectWord(self: *Screen, pin: Pin) ?Selection { // If we are going to the next row and it isn't wrapped, we // return the previous. - if (p.x == p.page.data.size.cols - 1 and !rac.row.wrap) { + if (p.x == p.node.data.size.cols - 1 and !rac.row.wrap) { break :end p; } @@ -2437,7 +2439,7 @@ pub fn selectWord(self: *Screen, pin: Pin) ?Selection { // If we are going to the next row and it isn't wrapped, we // return the previous. - if (p.x == p.page.data.size.cols - 1 and !rac.row.wrap) { + if (p.x == p.node.data.size.cols - 1 and !rac.row.wrap) { break :start prev; } @@ -2491,7 +2493,7 @@ pub fn selectOutput(self: *Screen, pin: Pin) ?Selection { switch (row.semantic_prompt) { .input, .prompt_continuation, .prompt => { var copy = it_prev; - copy.x = it_prev.page.data.size.cols - 1; + copy.x = it_prev.node.data.size.cols - 1; break :boundary copy; }, else => {}, @@ -2504,10 +2506,10 @@ pub fn selectOutput(self: *Screen, pin: Pin) ?Selection { it = it_prev.rowIterator(.left_up, null); while (it.next()) |p| { const row = p.rowAndCell().row; - const cells = p.page.data.getCells(row); + const cells = p.node.data.getCells(row); if (Cell.hasTextAny(cells)) { var copy = p; - copy.x = p.page.data.size.cols - 1; + copy.x = p.node.data.size.cols - 1; break :boundary copy; } } @@ -2598,7 +2600,7 @@ pub fn selectPrompt(self: *Screen, pin: Pin) ?Selection { const end: Pin = end: { var it = pin.rowIterator(.right_down, null); var it_prev = it.next().?; - it_prev.x = it_prev.page.data.size.cols - 1; + it_prev.x = it_prev.node.data.size.cols - 1; while (it.next()) |p| { const row = p.rowAndCell().row; switch (row.semantic_prompt) { @@ -2610,7 +2612,7 @@ pub fn selectPrompt(self: *Screen, pin: Pin) ?Selection { } it_prev = p; - it_prev.x = it_prev.page.data.size.cols - 1; + it_prev.x = it_prev.node.data.size.cols - 1; } break :end it_prev; @@ -2764,7 +2766,7 @@ pub fn dumpString( .codepoint_grapheme => { try writer.print("{u}", .{cell.content.codepoint}); - const cps = row_offset.page.data.lookupGrapheme(cell).?; + const cps = row_offset.node.data.lookupGrapheme(cell).?; for (cps) |cp| { try writer.print("{u}", .{cp}); } @@ -2843,7 +2845,7 @@ pub fn testWriteString(self: *Screen, text: []const u8) !void { break :cell cell; }; - try self.cursor.page_pin.page.data.appendGrapheme( + try self.cursor.page_pin.node.data.appendGrapheme( self.cursor.page_row, cell, c, @@ -2872,7 +2874,7 @@ pub fn testWriteString(self: *Screen, text: []const u8) !void { // If we have a ref-counted style, increase. if (self.cursor.style_id != style.default_id) { - const page = self.cursor.page_pin.page.data; + const page = self.cursor.page_pin.node.data; page.styles.use(page.memory, self.cursor.style_id); self.cursor.page_row.styled = true; } @@ -2914,7 +2916,7 @@ pub fn testWriteString(self: *Screen, text: []const u8) !void { // If we have a ref-counted style, increase twice. if (self.cursor.style_id != style.default_id) { - const page = self.cursor.page_pin.page.data; + const page = self.cursor.page_pin.node.data; page.styles.use(page.memory, self.cursor.style_id); page.styles.use(page.memory, self.cursor.style_id); self.cursor.page_row.styled = true; @@ -3054,7 +3056,7 @@ test "Screen cursorCopy style deref" { var s2 = try Screen.init(alloc, 10, 10, 0); defer s2.deinit(); - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; // Bold should create our style try s2.setAttribute(.{ .bold = {} }); @@ -3110,12 +3112,12 @@ test "Screen cursorCopy style deref new page" { // +-------------+ // This should be PAGE 1 - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; // It should be the last page in the list. try testing.expectEqual(&s2.pages.pages.last.?.data, page); // It should have a previous page. - try testing.expect(s2.cursor.page_pin.page.prev != null); + try testing.expect(s2.cursor.page_pin.node.prev != null); // The cursor should be at 2, 9 try testing.expect(s2.cursor.x == 2); @@ -3132,7 +3134,7 @@ test "Screen cursorCopy style deref new page" { try testing.expect(!s2.cursor.style.flags.bold); try testing.expectEqual(@as(usize, 0), page.styles.count()); // The page after the page the cursor is now in should be page 1. - try testing.expectEqual(page, &s2.cursor.page_pin.page.next.?.data); + try testing.expectEqual(page, &s2.cursor.page_pin.node.next.?.data); // The cursor should be at 0, 0 try testing.expect(s2.cursor.x == 0); try testing.expect(s2.cursor.y == 0); @@ -3148,7 +3150,7 @@ test "Screen cursorCopy style copy" { var s2 = try Screen.init(alloc, 10, 10, 0); defer s2.deinit(); - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; try s2.cursorCopy(s.cursor, .{}); try testing.expect(s2.cursor.style.flags.bold); try testing.expectEqual(@as(usize, 1), page.styles.count()); @@ -3163,7 +3165,7 @@ test "Screen cursorCopy hyperlink deref" { var s2 = try Screen.init(alloc, 10, 10, 0); defer s2.deinit(); - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; // Create a hyperlink for the cursor. try s2.startHyperlink("https://example.com/", null); @@ -3219,12 +3221,12 @@ test "Screen cursorCopy hyperlink deref new page" { // +-------------+ // This should be PAGE 1 - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; // It should be the last page in the list. try testing.expectEqual(&s2.pages.pages.last.?.data, page); // It should have a previous page. - try testing.expect(s2.cursor.page_pin.page.prev != null); + try testing.expect(s2.cursor.page_pin.node.prev != null); // The cursor should be at 2, 9 try testing.expect(s2.cursor.x == 2); @@ -3241,7 +3243,7 @@ test "Screen cursorCopy hyperlink deref new page" { try testing.expectEqual(@as(usize, 0), page.hyperlink_set.count()); try testing.expect(s2.cursor.hyperlink_id == 0); // The page after the page the cursor is now in should be page 1. - try testing.expectEqual(page, &s2.cursor.page_pin.page.next.?.data); + try testing.expectEqual(page, &s2.cursor.page_pin.node.next.?.data); // The cursor should be at 0, 0 try testing.expect(s2.cursor.x == 0); try testing.expect(s2.cursor.y == 0); @@ -3256,12 +3258,12 @@ test "Screen cursorCopy hyperlink copy" { // Create a hyperlink for the cursor. try s.startHyperlink("https://example.com/", null); - try testing.expectEqual(@as(usize, 1), s.cursor.page_pin.page.data.hyperlink_set.count()); + try testing.expectEqual(@as(usize, 1), s.cursor.page_pin.node.data.hyperlink_set.count()); try testing.expect(s.cursor.hyperlink_id != 0); var s2 = try Screen.init(alloc, 10, 10, 0); defer s2.deinit(); - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.hyperlink_set.count()); try testing.expect(s2.cursor.hyperlink_id == 0); @@ -3281,12 +3283,12 @@ test "Screen cursorCopy hyperlink copy disabled" { // Create a hyperlink for the cursor. try s.startHyperlink("https://example.com/", null); - try testing.expectEqual(@as(usize, 1), s.cursor.page_pin.page.data.hyperlink_set.count()); + try testing.expectEqual(@as(usize, 1), s.cursor.page_pin.node.data.hyperlink_set.count()); try testing.expect(s.cursor.hyperlink_id != 0); var s2 = try Screen.init(alloc, 10, 10, 0); defer s2.deinit(); - const page = &s2.cursor.page_pin.page.data; + const page = &s2.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.hyperlink_set.count()); try testing.expect(s2.cursor.hyperlink_id == 0); @@ -3303,7 +3305,7 @@ test "Screen style basics" { var s = try Screen.init(alloc, 80, 24, 1000); defer s.deinit(); - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.styles.count()); // Set a new style @@ -3325,7 +3327,7 @@ test "Screen style reset to default" { var s = try Screen.init(alloc, 80, 24, 1000); defer s.deinit(); - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.styles.count()); // Set a new style @@ -3345,7 +3347,7 @@ test "Screen style reset with unset" { var s = try Screen.init(alloc, 80, 24, 1000); defer s.deinit(); - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.styles.count()); // Set a new style @@ -3402,7 +3404,7 @@ test "Screen clearRows active styled line" { try s.setAttribute(.{ .unset = {} }); // We should have one style - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.styles.count()); s.clearRows(.{ .active = .{} }, null, false); @@ -3628,21 +3630,21 @@ test "Screen: cursorDown across pages preserves style" { // assertion fails then the bug is in the test: we should be scrolling // above enough for a new page to show up. { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expect(start_page != page); } // Scroll back to the previous page s.cursorUp(1); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expect(start_page == page); } // Go back up, set a style try s.setAttribute(.{ .bold = {} }); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; const styleval = page.styles.get( page.memory, s.cursor.style_id, @@ -3653,7 +3655,7 @@ test "Screen: cursorDown across pages preserves style" { // Go back down into the next page and we should have that style s.cursorDown(1); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; const styleval = page.styles.get( page.memory, s.cursor.style_id, @@ -3678,14 +3680,14 @@ test "Screen: cursorUp across pages preserves style" { // assertion fails then the bug is in the test: we should be scrolling // above enough for a new page to show up. { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expect(start_page != page); } // Go back up, set a style try s.setAttribute(.{ .bold = {} }); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; const styleval = page.styles.get( page.memory, s.cursor.style_id, @@ -3696,7 +3698,7 @@ test "Screen: cursorUp across pages preserves style" { // Go back down into the prev page and we should have that style s.cursorUp(1); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expect(start_page == page); const styleval = page.styles.get( @@ -3723,14 +3725,14 @@ test "Screen: cursorAbsolute across pages preserves style" { // assertion fails then the bug is in the test: we should be scrolling // above enough for a new page to show up. { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expect(start_page != page); } // Go back up, set a style try s.setAttribute(.{ .bold = {} }); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; const styleval = page.styles.get( page.memory, s.cursor.style_id, @@ -3741,7 +3743,7 @@ test "Screen: cursorAbsolute across pages preserves style" { // Go back down into the prev page and we should have that style s.cursorAbsolute(1, 1); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expect(start_page == page); const styleval = page.styles.get( @@ -4345,7 +4347,7 @@ test "Screen: scroll above same page but cursor on previous page" { s.pages.clearDirty(); // Ensure we're still on the first page and have a second - try testing.expect(s.cursor.page_pin.page == s.pages.pages.first.?); + try testing.expect(s.cursor.page_pin.node == s.pages.pages.first.?); try testing.expect(s.pages.pages.first.?.next != null); // At this point: @@ -4403,7 +4405,7 @@ test "Screen: scroll above same page but cursor on previous page last row" { s.pages.clearDirty(); // Ensure we're still on the first page and have a second - try testing.expect(s.cursor.page_pin.page == s.pages.pages.first.?); + try testing.expect(s.cursor.page_pin.node == s.pages.pages.first.?); try testing.expect(s.pages.pages.first.?.next != null); // At this point: @@ -4478,7 +4480,7 @@ test "Screen: scroll above creates new page" { s.pages.clearDirty(); // Ensure we're still on the first page - try testing.expect(s.cursor.page_pin.page == s.pages.pages.first.?); + try testing.expect(s.cursor.page_pin.node == s.pages.pages.first.?); try s.cursorScrollAbove(); { @@ -8150,7 +8152,7 @@ test "Screen: selectionString with zero width joiner" { const cell = pin.rowAndCell().cell; try testing.expectEqual(@as(u21, 0x1F468), cell.content.codepoint); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = pin.page.data.lookupGrapheme(cell).?; + const cps = pin.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } @@ -8381,21 +8383,21 @@ test "Screen: hyperlink start/end" { defer s.deinit(); try testing.expect(s.cursor.hyperlink_id == 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(0, page.hyperlink_set.count()); } try s.startHyperlink("http://example.com", null); try testing.expect(s.cursor.hyperlink_id != 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } s.endHyperlink(); try testing.expect(s.cursor.hyperlink_id == 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(0, page.hyperlink_set.count()); } } @@ -8409,7 +8411,7 @@ test "Screen: hyperlink reuse" { try testing.expect(s.cursor.hyperlink_id == 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(0, page.hyperlink_set.count()); } @@ -8422,14 +8424,14 @@ test "Screen: hyperlink reuse" { try s.startHyperlink("http://example.com", null); try testing.expectEqual(id, s.cursor.hyperlink_id); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } s.endHyperlink(); try testing.expect(s.cursor.hyperlink_id == 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(0, page.hyperlink_set.count()); } } @@ -8449,7 +8451,7 @@ test "Screen: hyperlink cursor state on resize" { try s.startHyperlink("http://example.com", null); try testing.expect(s.cursor.hyperlink_id != 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } @@ -8457,14 +8459,14 @@ test "Screen: hyperlink cursor state on resize" { try s.resize(10, 10); try testing.expect(s.cursor.hyperlink_id != 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } s.endHyperlink(); try testing.expect(s.cursor.hyperlink_id == 0); { - const page = &s.cursor.page_pin.page.data; + const page = &s.cursor.page_pin.node.data; try testing.expectEqual(0, page.hyperlink_set.count()); } } @@ -8489,8 +8491,8 @@ test "Screen: adjustCapacity cursor style ref count" { // This forces the page to change. _ = try s.adjustCapacity( - s.cursor.page_pin.page, - .{ .grapheme_bytes = s.cursor.page_pin.page.data.capacity.grapheme_bytes * 2 }, + s.cursor.page_pin.node, + .{ .grapheme_bytes = s.cursor.page_pin.node.data.capacity.grapheme_bytes * 2 }, ); // Our ref counts should still be the same diff --git a/src/terminal/Selection.zig b/src/terminal/Selection.zig index 452643f92..6fdb921e7 100644 --- a/src/terminal/Selection.zig +++ b/src/terminal/Selection.zig @@ -372,7 +372,7 @@ pub fn adjust( var current = end_pin.*; while (current.down(1)) |next| : (current = next) { const rac = next.rowAndCell(); - const cells = next.page.data.getCells(rac.row); + const cells = next.node.data.getCells(rac.row); if (page.Cell.hasTextAny(cells)) { end_pin.* = next; break; @@ -434,7 +434,7 @@ pub fn adjust( ); while (it.next()) |next| { const rac = next.rowAndCell(); - const cells = next.page.data.getCells(rac.row); + const cells = next.node.data.getCells(rac.row); if (page.Cell.hasTextAny(cells)) { end_pin.* = next; end_pin.x = @intCast(cells.len - 1); @@ -445,7 +445,7 @@ pub fn adjust( .beginning_of_line => end_pin.x = 0, - .end_of_line => end_pin.x = end_pin.page.data.size.cols - 1, + .end_of_line => end_pin.x = end_pin.node.data.size.cols - 1, } } diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index a2bf6d50e..f5784b6ab 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -313,7 +313,7 @@ pub fn print(self: *Terminal, c: u21) !void { var state: unicode.GraphemeBreakState = .{}; var cp1: u21 = prev.cell.content.codepoint; if (prev.cell.hasGrapheme()) { - const cps = self.screen.cursor.page_pin.page.data.lookupGrapheme(prev.cell).?; + const cps = self.screen.cursor.page_pin.node.data.lookupGrapheme(prev.cell).?; for (cps) |cp2| { // log.debug("cp1={x} cp2={x}", .{ cp1, cp2 }); assert(!unicode.graphemeBreak(cp1, cp2, &state)); @@ -567,7 +567,7 @@ fn printCell( const spacer_cell = self.screen.cursorCellRight(1); self.screen.clearCells( - &self.screen.cursor.page_pin.page.data, + &self.screen.cursor.page_pin.node.data, self.screen.cursor.page_row, spacer_cell[0..1], ); @@ -588,7 +588,7 @@ fn printCell( const wide_cell = self.screen.cursorCellLeft(1); self.screen.clearCells( - &self.screen.cursor.page_pin.page.data, + &self.screen.cursor.page_pin.node.data, self.screen.cursor.page_row, wide_cell[0..1], ); @@ -607,7 +607,7 @@ fn printCell( // If the prior value had graphemes, clear those if (cell.hasGrapheme()) { - self.screen.cursor.page_pin.page.data.clearGrapheme( + self.screen.cursor.page_pin.node.data.clearGrapheme( self.screen.cursor.page_row, cell, ); @@ -617,7 +617,7 @@ fn printCell( // cell's new style will be different after writing. const style_changed = cell.style_id != self.screen.cursor.style_id; if (style_changed) { - var page = &self.screen.cursor.page_pin.page.data; + var page = &self.screen.cursor.page_pin.node.data; // Release the old style. if (cell.style_id != style.default_id) { @@ -639,7 +639,7 @@ fn printCell( }; if (style_changed) { - var page = &self.screen.cursor.page_pin.page.data; + var page = &self.screen.cursor.page_pin.node.data; // Use the new style. if (cell.style_id != style.default_id) { @@ -664,7 +664,7 @@ fn printCell( }; } else if (had_hyperlink) { // If the previous cell had a hyperlink then we need to clear it. - var page = &self.screen.cursor.page_pin.page.data; + var page = &self.screen.cursor.page_pin.node.data; page.clearHyperlink(self.screen.cursor.page_row, cell); } } @@ -1500,8 +1500,8 @@ pub fn insertLines(self: *Terminal, count: usize) void { const off_rac = off_p.rowAndCell(); const off_row: *Row = off_rac.row; - self.rowWillBeShifted(&cur_p.page.data, cur_row); - self.rowWillBeShifted(&off_p.page.data, off_row); + self.rowWillBeShifted(&cur_p.node.data, cur_row); + self.rowWillBeShifted(&off_p.node.data, off_row); // If our scrolling region is full width, then we unset wrap. if (!left_right) { @@ -1518,19 +1518,19 @@ pub fn insertLines(self: *Terminal, count: usize) void { // If our page doesn't match, then we need to do a copy from // one page to another. This is the slow path. - if (src_p.page != dst_p.page) { - dst_p.page.data.clonePartialRowFrom( - &src_p.page.data, + if (src_p.node != dst_p.node) { + dst_p.node.data.clonePartialRowFrom( + &src_p.node.data, dst_row, src_row, self.scrolling_region.left, self.scrolling_region.right + 1, ) catch |err| { - const cap = dst_p.page.data.capacity; + const cap = dst_p.node.data.capacity; // Adjust our page capacity to make // room for we didn't have space for _ = self.screen.adjustCapacity( - dst_p.page, + dst_p.node, switch (err) { // Rehash the sets error.StyleSetNeedsRehash, @@ -1589,11 +1589,11 @@ pub fn insertLines(self: *Terminal, count: usize) void { src_row.* = dst; // Ensure what we did didn't corrupt the page - cur_p.page.data.assertIntegrity(); + cur_p.node.data.assertIntegrity(); } else { // Left/right scroll margins we have to // copy cells, which is much slower... - const page = &cur_p.page.data; + const page = &cur_p.node.data; page.moveCells( src_row, self.scrolling_region.left, @@ -1605,7 +1605,7 @@ pub fn insertLines(self: *Terminal, count: usize) void { } } else { // Clear the cells for this row, it has been shifted. - const page = &cur_p.page.data; + const page = &cur_p.node.data; const cells = page.getCells(cur_row); self.screen.clearCells( page, @@ -1698,8 +1698,8 @@ pub fn deleteLines(self: *Terminal, count: usize) void { const off_rac = off_p.rowAndCell(); const off_row: *Row = off_rac.row; - self.rowWillBeShifted(&cur_p.page.data, cur_row); - self.rowWillBeShifted(&off_p.page.data, off_row); + self.rowWillBeShifted(&cur_p.node.data, cur_row); + self.rowWillBeShifted(&off_p.node.data, off_row); // If our scrolling region is full width, then we unset wrap. if (!left_right) { @@ -1716,19 +1716,19 @@ pub fn deleteLines(self: *Terminal, count: usize) void { // If our page doesn't match, then we need to do a copy from // one page to another. This is the slow path. - if (src_p.page != dst_p.page) { - dst_p.page.data.clonePartialRowFrom( - &src_p.page.data, + if (src_p.node != dst_p.node) { + dst_p.node.data.clonePartialRowFrom( + &src_p.node.data, dst_row, src_row, self.scrolling_region.left, self.scrolling_region.right + 1, ) catch |err| { - const cap = dst_p.page.data.capacity; + const cap = dst_p.node.data.capacity; // Adjust our page capacity to make // room for we didn't have space for _ = self.screen.adjustCapacity( - dst_p.page, + dst_p.node, switch (err) { // Rehash the sets error.StyleSetNeedsRehash, @@ -1782,11 +1782,11 @@ pub fn deleteLines(self: *Terminal, count: usize) void { src_row.* = dst; // Ensure what we did didn't corrupt the page - cur_p.page.data.assertIntegrity(); + cur_p.node.data.assertIntegrity(); } else { // Left/right scroll margins we have to // copy cells, which is much slower... - const page = &cur_p.page.data; + const page = &cur_p.node.data; page.moveCells( src_row, self.scrolling_region.left, @@ -1798,7 +1798,7 @@ pub fn deleteLines(self: *Terminal, count: usize) void { } } else { // Clear the cells for this row, it's from out of bounds. - const page = &cur_p.page.data; + const page = &cur_p.node.data; const cells = page.getCells(cur_row); self.screen.clearCells( page, @@ -1843,7 +1843,7 @@ pub fn insertBlanks(self: *Terminal, count: usize) void { // left is just the cursor position but as a multi-pointer const left: [*]Cell = @ptrCast(self.screen.cursor.page_cell); - var page = &self.screen.cursor.page_pin.page.data; + var page = &self.screen.cursor.page_pin.node.data; // If our X is a wide spacer tail then we need to erase the // previous cell too so we don't split a multi-cell character. @@ -1914,7 +1914,7 @@ pub fn deleteChars(self: *Terminal, count_req: usize) void { // left is just the cursor position but as a multi-pointer const left: [*]Cell = @ptrCast(self.screen.cursor.page_cell); - var page = &self.screen.cursor.page_pin.page.data; + var page = &self.screen.cursor.page_pin.node.data; // Remaining cols from our cursor to the right margin. const rem = self.scrolling_region.right - self.screen.cursor.x + 1; @@ -1995,7 +1995,7 @@ pub fn eraseChars(self: *Terminal, count_req: usize) void { // mode was not ISO we also always ignore protection attributes. if (self.screen.protected_mode != .iso) { self.screen.clearCells( - &self.screen.cursor.page_pin.page.data, + &self.screen.cursor.page_pin.node.data, self.screen.cursor.page_row, cells[0..end], ); @@ -2003,7 +2003,7 @@ pub fn eraseChars(self: *Terminal, count_req: usize) void { } self.screen.clearUnprotectedCells( - &self.screen.cursor.page_pin.page.data, + &self.screen.cursor.page_pin.node.data, self.screen.cursor.page_row, cells[0..end], ); @@ -2075,7 +2075,7 @@ pub fn eraseLine( // to fill the entire line. if (!protected) { self.screen.clearCells( - &self.screen.cursor.page_pin.page.data, + &self.screen.cursor.page_pin.node.data, self.screen.cursor.page_row, cells[start..end], ); @@ -2083,7 +2083,7 @@ pub fn eraseLine( } self.screen.clearUnprotectedCells( - &self.screen.cursor.page_pin.page.data, + &self.screen.cursor.page_pin.node.data, self.screen.cursor.page_row, cells[start..end], ); @@ -2257,7 +2257,7 @@ pub fn decaln(self: *Terminal) !void { // Fill with Es by moving the cursor but reset it after. while (true) { - const page = &self.screen.cursor.page_pin.page.data; + const page = &self.screen.cursor.page_pin.node.data; const row = self.screen.cursor.page_row; const cells_multi: [*]Cell = row.cells.ptr(page.memory); const cells = cells_multi[0..page.size.cols]; @@ -2986,7 +2986,7 @@ test "Terminal: print over wide char with bold" { try t.print(0x1F600); // Smiley face // verify we have styles in our style map { - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.styles.count()); } @@ -2997,7 +2997,7 @@ test "Terminal: print over wide char with bold" { // verify our style is gone { - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.styles.count()); } @@ -3016,7 +3016,7 @@ test "Terminal: print over wide char with bg color" { try t.print(0x1F600); // Smiley face // verify we have styles in our style map { - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.styles.count()); } @@ -3027,7 +3027,7 @@ test "Terminal: print over wide char with bg color" { // verify our style is gone { - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.styles.count()); } @@ -3058,7 +3058,7 @@ test "Terminal: print multicodepoint grapheme, disabled mode 2027" { try testing.expectEqual(@as(u21, 0x1F468), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } { @@ -3067,7 +3067,7 @@ test "Terminal: print multicodepoint grapheme, disabled mode 2027" { try testing.expectEqual(@as(u21, 0), cell.content.codepoint); try testing.expect(!cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.spacer_tail, cell.wide); - try testing.expect(list_cell.page.data.lookupGrapheme(cell) == null); + try testing.expect(list_cell.node.data.lookupGrapheme(cell) == null); } { const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 2, .y = 0 } }).?; @@ -3075,7 +3075,7 @@ test "Terminal: print multicodepoint grapheme, disabled mode 2027" { try testing.expectEqual(@as(u21, 0x1F469), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } { @@ -3084,7 +3084,7 @@ test "Terminal: print multicodepoint grapheme, disabled mode 2027" { try testing.expectEqual(@as(u21, 0), cell.content.codepoint); try testing.expect(!cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.spacer_tail, cell.wide); - try testing.expect(list_cell.page.data.lookupGrapheme(cell) == null); + try testing.expect(list_cell.node.data.lookupGrapheme(cell) == null); } { const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 4, .y = 0 } }).?; @@ -3092,7 +3092,7 @@ test "Terminal: print multicodepoint grapheme, disabled mode 2027" { try testing.expectEqual(@as(u21, 0x1F467), cell.content.codepoint); try testing.expect(!cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - try testing.expect(list_cell.page.data.lookupGrapheme(cell) == null); + try testing.expect(list_cell.node.data.lookupGrapheme(cell) == null); } { const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 5, .y = 0 } }).?; @@ -3100,7 +3100,7 @@ test "Terminal: print multicodepoint grapheme, disabled mode 2027" { try testing.expectEqual(@as(u21, 0), cell.content.codepoint); try testing.expect(!cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.spacer_tail, cell.wide); - try testing.expect(list_cell.page.data.lookupGrapheme(cell) == null); + try testing.expect(list_cell.node.data.lookupGrapheme(cell) == null); } try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); @@ -3128,7 +3128,7 @@ test "Terminal: VS16 doesn't make character with 2027 disabled" { try testing.expectEqual(@as(u21, 0x2764), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.narrow, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } } @@ -3221,7 +3221,7 @@ test "Terminal: print multicodepoint grapheme, mode 2027" { try testing.expectEqual(@as(u21, 0x1F468), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 4), cps.len); } { @@ -3288,7 +3288,7 @@ test "Terminal: VS15 to make narrow character" { try testing.expectEqual(@as(u21, 0x26C8), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.narrow, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } } @@ -3319,7 +3319,7 @@ test "Terminal: VS16 to make wide character with mode 2027" { try testing.expectEqual(@as(u21, 0x2764), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } } @@ -3350,7 +3350,7 @@ test "Terminal: VS16 repeated with mode 2027" { try testing.expectEqual(@as(u21, 0x2764), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } { @@ -3359,7 +3359,7 @@ test "Terminal: VS16 repeated with mode 2027" { try testing.expectEqual(@as(u21, 0x2764), cell.content.codepoint); try testing.expect(cell.hasGrapheme()); try testing.expectEqual(Cell.Wide.wide, cell.wide); - const cps = list_cell.page.data.lookupGrapheme(cell).?; + const cps = list_cell.node.data.lookupGrapheme(cell).?; try testing.expectEqual(@as(usize, 1), cps.len); } } @@ -3482,7 +3482,7 @@ test "Terminal: overwrite multicodepoint grapheme clears grapheme data" { try testing.expectEqual(@as(usize, 2), t.screen.cursor.x); // We should have one cell with graphemes - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.graphemeCount()); // Move back and overwrite wide @@ -3522,7 +3522,7 @@ test "Terminal: overwrite multicodepoint grapheme tail clears grapheme data" { try testing.expectEqual(@as(usize, 2), t.screen.cursor.x); // We should have one cell with graphemes - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.graphemeCount()); // Move back and overwrite wide @@ -3971,7 +3971,7 @@ test "Terminal: print with hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } @@ -3998,7 +3998,7 @@ test "Terminal: print over cell with same hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } @@ -4025,7 +4025,7 @@ test "Terminal: print and end hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } for (3..6) |x| { @@ -4060,7 +4060,7 @@ test "Terminal: print and change hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } for (3..6) |x| { @@ -4070,7 +4070,7 @@ test "Terminal: print and change hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 2), id); } @@ -4094,7 +4094,7 @@ test "Terminal: overwrite hyperlink" { .x = @intCast(x), .y = 0, } }).?; - const page = &list_cell.page.data; + const page = &list_cell.node.data; const row = list_cell.row; try testing.expect(!row.hyperlink); const cell = list_cell.cell; @@ -4865,7 +4865,7 @@ test "Terminal: insertLines handles style refs" { try t.setAttribute(.{ .unset = {} }); // verify we have styles in our style map - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.styles.count()); t.setCursorPos(2, 2); @@ -5233,9 +5233,9 @@ test "Terminal: scrollUp moves hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } for (0..3) |x| { @@ -5247,7 +5247,7 @@ test "Terminal: scrollUp moves hyperlink" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -5284,7 +5284,7 @@ test "Terminal: scrollUp clears hyperlink" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -5386,7 +5386,7 @@ test "Terminal: scrollUp left/right scroll region hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } for (1..4) |x| { @@ -5398,9 +5398,9 @@ test "Terminal: scrollUp left/right scroll region hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } for (4..6) |x| { @@ -5410,7 +5410,7 @@ test "Terminal: scrollUp left/right scroll region hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -5426,9 +5426,9 @@ test "Terminal: scrollUp left/right scroll region hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } for (1..4) |x| { @@ -5438,7 +5438,7 @@ test "Terminal: scrollUp left/right scroll region hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } for (4..6) |x| { @@ -5450,9 +5450,9 @@ test "Terminal: scrollUp left/right scroll region hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } } @@ -5596,9 +5596,9 @@ test "Terminal: scrollDown hyperlink moves" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } for (0..3) |x| { @@ -5610,7 +5610,7 @@ test "Terminal: scrollDown hyperlink moves" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -5720,9 +5720,9 @@ test "Terminal: scrollDown left/right scroll region hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } for (1..4) |x| { @@ -5732,7 +5732,7 @@ test "Terminal: scrollDown left/right scroll region hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } for (4..6) |x| { @@ -5744,9 +5744,9 @@ test "Terminal: scrollDown left/right scroll region hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } } @@ -5760,7 +5760,7 @@ test "Terminal: scrollDown left/right scroll region hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } for (1..4) |x| { @@ -5772,9 +5772,9 @@ test "Terminal: scrollDown left/right scroll region hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(1, page.hyperlink_set.count()); } for (4..6) |x| { @@ -5784,7 +5784,7 @@ test "Terminal: scrollDown left/right scroll region hyperlink" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -6018,7 +6018,7 @@ test "Terminal: eraseChars handles refcounted styles" { try t.print('C'); // verify we have styles in our style map - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.styles.count()); t.setCursorPos(1, 1); @@ -6095,7 +6095,7 @@ test "Terminal: eraseChars wide char boundary conditions" { t.setCursorPos(1, 2); t.eraseChars(3); - t.screen.cursor.page_pin.page.data.assertIntegrity(); + t.screen.cursor.page_pin.node.data.assertIntegrity(); { const str = try t.plainString(alloc); @@ -6122,7 +6122,7 @@ test "Terminal: eraseChars wide char wrap boundary conditions" { t.setCursorPos(2, 2); t.eraseChars(3); - t.screen.cursor.page_pin.page.data.assertIntegrity(); + t.screen.cursor.page_pin.node.data.assertIntegrity(); { const str = try t.plainString(alloc); @@ -6425,7 +6425,7 @@ test "Terminal: index scrolling with hyperlink" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } { @@ -6437,7 +6437,7 @@ test "Terminal: index scrolling with hyperlink" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -6599,7 +6599,7 @@ test "Terminal: index bottom of scroll region with hyperlinks" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } { @@ -6611,7 +6611,7 @@ test "Terminal: index bottom of scroll region with hyperlinks" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -6648,9 +6648,9 @@ test "Terminal: index bottom of scroll region clear hyperlinks" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); - const page = &list_cell.page.data; + const page = &list_cell.node.data; try testing.expectEqual(0, page.hyperlink_set.count()); } } @@ -7972,7 +7972,7 @@ test "Terminal: bold style" { const cell = list_cell.cell; try testing.expectEqual(@as(u21, 'A'), cell.content.codepoint); try testing.expect(cell.style_id != 0); - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expect(page.styles.refCount(page.memory, t.screen.cursor.style_id) > 1); } } @@ -7996,7 +7996,7 @@ test "Terminal: garbage collect overwritten" { } // verify we have no styles in our style map - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 0), page.styles.count()); } @@ -8018,7 +8018,7 @@ test "Terminal: do not garbage collect old styles in use" { } // verify we have no styles in our style map - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.styles.count()); } @@ -8390,7 +8390,7 @@ test "Terminal: insertBlanks deleting graphemes" { try t.print(0x1F467); // We should have one cell with graphemes - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.graphemeCount()); t.setCursorPos(1, 1); @@ -8426,7 +8426,7 @@ test "Terminal: insertBlanks shift graphemes" { try t.print(0x1F467); // We should have one cell with graphemes - const page = &t.screen.cursor.page_pin.page.data; + const page = &t.screen.cursor.page_pin.node.data; try testing.expectEqual(@as(usize, 1), page.graphemeCount()); t.setCursorPos(1, 1); @@ -8494,7 +8494,7 @@ test "Terminal: insertBlanks shifts hyperlinks" { try testing.expect(row.hyperlink); const cell = list_cell.cell; try testing.expect(cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell).?; + const id = list_cell.node.data.lookupHyperlink(cell).?; try testing.expectEqual(@as(hyperlink.Id, 1), id); } for (0..2) |x| { @@ -8504,7 +8504,7 @@ test "Terminal: insertBlanks shifts hyperlinks" { } }).?; const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -8534,7 +8534,7 @@ test "Terminal: insertBlanks pushes hyperlink off end completely" { try testing.expect(!row.hyperlink); const cell = list_cell.cell; try testing.expect(!cell.hyperlink); - const id = list_cell.page.data.lookupHyperlink(cell); + const id = list_cell.node.data.lookupHyperlink(cell); try testing.expect(id == null); } } @@ -9036,7 +9036,7 @@ test "Terminal: deleteChars wide char boundary conditions" { t.setCursorPos(1, 2); t.deleteChars(3); - t.screen.cursor.page_pin.page.data.assertIntegrity(); + t.screen.cursor.page_pin.node.data.assertIntegrity(); { const str = try t.plainString(alloc); @@ -9088,7 +9088,7 @@ test "Terminal: deleteChars wide char wrap boundary conditions" { t.setCursorPos(2, 2); t.deleteChars(3); - t.screen.cursor.page_pin.page.data.assertIntegrity(); + t.screen.cursor.page_pin.node.data.assertIntegrity(); { const str = try t.plainString(alloc); @@ -9127,7 +9127,7 @@ test "Terminal: deleteChars wide char across right margin" { t.setCursorPos(1, 2); t.deleteChars(1); - t.screen.cursor.page_pin.page.data.assertIntegrity(); + t.screen.cursor.page_pin.node.data.assertIntegrity(); // NOTE: This behavior is slightly inconsistent with xterm. xterm // _visually_ splits the wide character (half the wide character shows