diff --git a/src/datastruct/intrusive_linked_list.zig b/src/datastruct/intrusive_linked_list.zig index 02279457f..61bf8157c 100644 --- a/src/datastruct/intrusive_linked_list.zig +++ b/src/datastruct/intrusive_linked_list.zig @@ -11,15 +11,19 @@ pub fn DoublyLinkedList(comptime T: type) type { return struct { const Self = @This(); - first: ?*T = null, - last: ?*T = null, + /// The type of the node in the list. This makes it easy to get the + /// node type from the list type. + pub const Node = T; + + first: ?*Node = null, + last: ?*Node = null, /// Insert a new node after an existing one. /// /// Arguments: /// node: Pointer to a node in the list. /// new_node: Pointer to the new node to insert. - pub fn insertAfter(list: *Self, node: *T, new_node: *T) void { + pub fn insertAfter(list: *Self, node: *Node, new_node: *Node) void { new_node.prev = node; if (node.next) |next_node| { // Intermediate node. @@ -38,7 +42,7 @@ pub fn DoublyLinkedList(comptime T: type) type { /// Arguments: /// node: Pointer to a node in the list. /// new_node: Pointer to the new node to insert. - pub fn insertBefore(list: *Self, node: *T, new_node: *T) void { + pub fn insertBefore(list: *Self, node: *Node, new_node: *Node) void { new_node.next = node; if (node.prev) |prev_node| { // Intermediate node. @@ -56,7 +60,7 @@ pub fn DoublyLinkedList(comptime T: type) type { /// /// Arguments: /// new_node: Pointer to the new node to insert. - pub fn append(list: *Self, new_node: *T) void { + pub fn append(list: *Self, new_node: *Node) void { if (list.last) |last| { // Insert after last. list.insertAfter(last, new_node); @@ -70,7 +74,7 @@ pub fn DoublyLinkedList(comptime T: type) type { /// /// Arguments: /// new_node: Pointer to the new node to insert. - pub fn prepend(list: *Self, new_node: *T) void { + pub fn prepend(list: *Self, new_node: *Node) void { if (list.first) |first| { // Insert before first. list.insertBefore(first, new_node); @@ -87,7 +91,7 @@ pub fn DoublyLinkedList(comptime T: type) type { /// /// Arguments: /// node: Pointer to the node to be removed. - pub fn remove(list: *Self, node: *T) void { + pub fn remove(list: *Self, node: *Node) void { if (node.prev) |prev_node| { // Intermediate node. prev_node.next = node.next; @@ -109,7 +113,7 @@ pub fn DoublyLinkedList(comptime T: type) type { /// /// Returns: /// A pointer to the last node in the list. - pub fn pop(list: *Self) ?*T { + pub fn pop(list: *Self) ?*Node { const last = list.last orelse return null; list.remove(last); return last; @@ -119,7 +123,7 @@ pub fn DoublyLinkedList(comptime T: type) type { /// /// Returns: /// A pointer to the first node in the list. - pub fn popFirst(list: *Self) ?*T { + pub fn popFirst(list: *Self) ?*Node { const first = list.first orelse return null; list.remove(first); return first; diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index f1dbc2561..70f972ebe 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -7,8 +7,9 @@ const std = @import("std"); const build_config = @import("../build_config.zig"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const color = @import("color.zig"); const fastmem = @import("../fastmem.zig"); +const DoublyLinkedList = @import("../datastruct/main.zig").IntrusiveDoublyLinkedList; +const color = @import("color.zig"); const kitty = @import("kitty.zig"); const point = @import("point.zig"); const pagepkg = @import("page.zig"); @@ -33,7 +34,16 @@ const page_preheat = 4; /// The list of pages in the screen. These are expected to be in order /// where the first page is the topmost page (scrollback) and the last is /// the bottommost page (the current active page). -pub const List = std.DoublyLinkedList(Page); +pub const List = DoublyLinkedList(Node); + +/// A single node within the PageList linked list. +/// +/// This isn't pub because you can access the type via List.Node. +const Node = struct { + prev: ?*Node = null, + next: ?*Node = null, + data: Page, +}; /// The memory pool we get page nodes from. const NodePool = std.heap.MemoryPool(List.Node); @@ -1699,7 +1709,8 @@ pub fn grow(self: *PageList) !?*List.Node { // reuses the popped page. It is possible to have a single page and // exceed the max size if that page was adjusted to be larger after // initial allocation. - if (self.pages.len > 1 and + if (self.pages.first != null and + self.pages.first != self.pages.last and self.page_size + PagePool.item_size > self.maxSize()) prune: { // If we need to add more memory to ensure our active area is