scroll with delta no grow

This commit is contained in:
Mitchell Hashimoto
2022-07-10 15:54:32 -07:00
parent 9f3e6344cc
commit a09b87bc9e

View File

@ -161,6 +161,11 @@ pub const Scroll = union(enum) {
/// moves, not the direction text moves. This is the colloquial way that /// moves, not the direction text moves. This is the colloquial way that
/// scrolling is described: "scroll the page down". /// scrolling is described: "scroll the page down".
delta: isize, delta: isize,
/// Same as delta but scrolling down will not grow the scrollback.
/// Scrolling down at the bottom will do nothing (similar to how
/// delta at the top does nothing).
delta_no_grow: isize,
}; };
/// Scroll the screen by the given behavior. Note that this will always /// Scroll the screen by the given behavior. Note that this will always
@ -174,11 +179,18 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
.top => self.visible_offset = 0, .top => self.visible_offset = 0,
// TODO: deltas greater than the entire scrollback // TODO: deltas greater than the entire scrollback
.delta => |delta| delta: { .delta => |delta| self.scrollDown(delta, true),
.delta_no_grow => |delta| self.scrollDown(delta, false),
else => @panic("unimplemented"),
}
}
fn scrollDown(self: *Screen, delta: isize, grow: bool) void {
// If we're scrolling up, then we just subtract and we're done. // If we're scrolling up, then we just subtract and we're done.
if (delta < 0) { if (delta < 0) {
self.visible_offset -|= @intCast(usize, -delta); self.visible_offset -|= @intCast(usize, -delta);
break :delta; return;
} }
// If we're scrolling down, we have more work to do beacuse we // If we're scrolling down, we have more work to do beacuse we
@ -197,7 +209,7 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
// our true visible top to zero. // our true visible top to zero.
const visible_top = visible_zero - storage_rows; const visible_top = visible_zero - storage_rows;
const rows_available = self.zero - visible_top; const rows_available = self.zero - visible_top;
if (rows_available >= self.rows) break :delta; if (rows_available >= self.rows) return;
// We overlap our missing rows // We overlap our missing rows
break :overlap self.rows - rows_available; break :overlap self.rows - rows_available;
@ -205,18 +217,21 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
// First check: if we have enough space in the storage buffer // First check: if we have enough space in the storage buffer
// FORWARD to accomodate all our rows, then we're fine. // FORWARD to accomodate all our rows, then we're fine.
const rows_forward = storage_rows - (self.zero + self.visible_offset); const rows_forward = storage_rows - (self.zero + self.visible_offset);
if (rows_forward >= self.rows) break :delta; if (rows_forward >= self.rows) return;
// Second check: if we have enough space PRIOR to zero when // Second check: if we have enough space PRIOR to zero when
// wrapped, then we're fine. // wrapped, then we're fine.
const rows_wrapped = self.rows - rows_forward; const rows_wrapped = self.rows - rows_forward;
if (rows_wrapped < self.zero) break :delta; if (rows_wrapped < self.zero) return;
// We need to clear the rows in the overlap and move the top // We need to clear the rows in the overlap and move the top
// of the scrollback buffer. // of the scrollback buffer.
break :overlap rows_wrapped - self.zero; break :overlap rows_wrapped - self.zero;
}; };
// If we are growing, then we clear the overlap and reset zero
if (grow) {
// Clear our overlap // Clear our overlap
const clear_start = self.zero * self.cols; const clear_start = self.zero * self.cols;
const clear_end = clear_start + (rows_overlapped * self.cols); const clear_end = clear_start + (rows_overlapped * self.cols);
@ -224,11 +239,10 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
// Move to accomodate overlap. This deletes scrollback. // Move to accomodate overlap. This deletes scrollback.
self.zero = @mod(self.zero + rows_overlapped, storage_rows); self.zero = @mod(self.zero + rows_overlapped, storage_rows);
self.visible_offset -= rows_overlapped;
},
else => @panic("unimplemented"),
} }
// Move back the number of overlapped
self.visible_offset -= rows_overlapped;
} }
/// Scroll the screen up (positive) or down (negative). Scrolling direction /// Scroll the screen up (positive) or down (negative). Scrolling direction
@ -466,6 +480,16 @@ test "Screen: scrollback" {
try testing.expectEqualStrings("2EFGH\n3IJKL", contents); try testing.expectEqualStrings("2EFGH\n3IJKL", contents);
} }
// Scrolling forward with no grow should do nothing
s.scroll(.{ .delta_no_grow = 1 });
{
// Test our contents rotated
var contents = try s.testString(alloc);
defer alloc.free(contents);
try testing.expectEqualStrings("2EFGH\n3IJKL", contents);
}
// Scrolling to the top should work // Scrolling to the top should work
s.scroll(.{ .top = {} }); s.scroll(.{ .top = {} });