core: fix PageList.scroll using wrong type for row offset (#13048)

Changes `PageList.scroll` to use `usize` as the type for the number of
remaining rows when trying to find a specific row in the list of pages.
Previously `CellCountInt=u16` was used, but the row offset can be larger
than `maxInt(u16)=65535`, in which case the scroll operation would fail.

Fixes #13000 where scrolling does not work correctly in the GTK app with
a large scrollback history. E.g. nothing happens when you click in the
middle of the scrollbar. Note that this problem only manifests at
millions of lines of history instead of already when the row offset
overflows `u16`. The reason for that is that GTK often emits multiple
scroll adjustments, the first of which is usually close enough to the
current position to not overflow `u16`. The other scroll adjustments are
then handled by the fast path in `PageList.scroll` that works correctly.

#### AI Disclosure
No AI was used.
This commit is contained in:
Mitchell Hashimoto
2026-06-22 13:29:12 -07:00
committed by GitHub

View File

@@ -2582,18 +2582,15 @@ pub fn scroll(self: *PageList, behavior: Scroll) void {
if (n < midpoint) {
// Iterate forward from the first node.
var node_it = self.pages.first;
var rem: size.CellCountInt = std.math.cast(
size.CellCountInt,
n,
) orelse {
self.viewport = .active;
break :row;
};
var rem: usize = n;
while (node_it) |node| : (node_it = node.next) {
if (rem < node.data.size.rows) {
self.viewport_pin.* = .{
.node = node,
.y = rem,
.y = std.math.cast(size.CellCountInt, rem) orelse {
self.viewport = .active;
break :row;
},
};
break :row;
}
@@ -2603,18 +2600,15 @@ pub fn scroll(self: *PageList, behavior: Scroll) void {
} else {
// Iterate backwards from the last node.
var node_it = self.pages.last;
var rem: size.CellCountInt = std.math.cast(
size.CellCountInt,
self.total_rows - n,
) orelse {
self.viewport = .active;
break :row;
};
var rem: usize = self.total_rows - n;
while (node_it) |node| : (node_it = node.prev) {
if (rem <= node.data.size.rows) {
self.viewport_pin.* = .{
.node = node,
.y = node.data.size.rows - rem,
.y = std.math.cast(size.CellCountInt, node.data.size.rows - rem) orelse {
self.viewport = .active;
break :row;
},
};
break :row;
}