mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
Screen.region to get a region of contiguous memory for a tag
This commit is contained in:
@ -86,7 +86,7 @@ pub const RowIterator = struct {
|
||||
value: usize = 0,
|
||||
|
||||
pub fn next(self: *RowIterator) ?Row {
|
||||
if (self.value >= self.tag.max(self.screen)) return null;
|
||||
if (self.value > self.tag.max(self.screen)) return null;
|
||||
const idx = self.tag.index(self.value);
|
||||
const res = self.screen.getRow(idx);
|
||||
self.value += 1;
|
||||
@ -129,7 +129,7 @@ pub const RowIndexTag = enum {
|
||||
.screen => screen.totalRows(),
|
||||
.viewport => screen.rows,
|
||||
.active => screen.rows,
|
||||
};
|
||||
} - 1;
|
||||
}
|
||||
|
||||
/// Construct a RowIndex from a tag.
|
||||
@ -216,9 +216,31 @@ pub fn rowIterator(self: *const Screen, tag: RowIndexTag) RowIterator {
|
||||
return .{ .screen = self, .tag = tag };
|
||||
}
|
||||
|
||||
/// Get the visible portion of the screen.
|
||||
pub fn getVisible(self: Screen) []Cell {
|
||||
return self.storage;
|
||||
/// Region gets the contiguous portions of memory that constitute an
|
||||
/// entire region. This is an efficient way to clear regions, for example
|
||||
/// since you can memcpy directly into it.
|
||||
///
|
||||
/// This has two elements because internally we use a ring buffer and
|
||||
/// so any region can be split into two if it crosses the ring buffer
|
||||
/// boundary.
|
||||
pub fn region(self: *const Screen, tag: RowIndexTag) [2][]Cell {
|
||||
const top = self.rowIndex(tag.index(0));
|
||||
const bot = self.rowIndex(tag.index(tag.max(self)));
|
||||
|
||||
// The bottom and top are available in one contiguous slice.
|
||||
if (bot >= top) {
|
||||
return .{
|
||||
self.storage[top .. bot + self.cols],
|
||||
self.storage[0..0], // just so its a valid slice, but zero length
|
||||
};
|
||||
}
|
||||
|
||||
// The bottom and top are split into two slices, so we slice to the
|
||||
// bottom of the storage, then from the top.
|
||||
return .{
|
||||
self.storage[top..self.storage.len],
|
||||
self.storage[0 .. bot + self.cols],
|
||||
};
|
||||
}
|
||||
|
||||
/// Get a single row in the active area by index (0-indexed).
|
||||
@ -649,9 +671,11 @@ test "Screen" {
|
||||
// Sanity check that our test helpers work
|
||||
const str = "1ABCD\n2EFGH\n3IJKL";
|
||||
s.testWriteString(str);
|
||||
var contents = try s.testString(alloc);
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings(str, contents);
|
||||
{
|
||||
var contents = try s.testString(alloc);
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings(str, contents);
|
||||
}
|
||||
|
||||
// Test the row iterator
|
||||
var count: usize = 0;
|
||||
@ -665,6 +689,16 @@ test "Screen" {
|
||||
|
||||
// Should go through all rows
|
||||
try testing.expectEqual(@as(usize, 3), count);
|
||||
|
||||
// Should be able to easily clear screen
|
||||
const reg = s.region(.viewport);
|
||||
std.mem.set(Cell, reg[0], .{ .char = 'A' });
|
||||
std.mem.set(Cell, reg[1], .{ .char = 'A' });
|
||||
{
|
||||
var contents = try s.testString(alloc);
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings("AAAAA\nAAAAA\nAAAAA", contents);
|
||||
}
|
||||
}
|
||||
|
||||
test "Screen: scrolling" {
|
||||
@ -825,6 +859,26 @@ test "Screen: scrollback" {
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings("1ABCD\n2EFGH\n3IJKL", contents);
|
||||
}
|
||||
|
||||
// Should be able to easily clear active area only
|
||||
const reg = s.region(.active);
|
||||
std.mem.set(Cell, reg[0], .{ .char = 0 });
|
||||
std.mem.set(Cell, reg[1], .{ .char = 0 });
|
||||
{
|
||||
var contents = try s.testString(alloc);
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings("1ABCD", contents);
|
||||
}
|
||||
|
||||
// Scrolling to the bottom
|
||||
s.scroll(.{ .bottom = {} });
|
||||
|
||||
{
|
||||
// Test our contents rotated
|
||||
var contents = try s.testString(alloc);
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings("", contents);
|
||||
}
|
||||
}
|
||||
|
||||
test "Screen: scrollback empty" {
|
||||
|
@ -539,8 +539,9 @@ pub fn eraseDisplay(
|
||||
|
||||
switch (mode) {
|
||||
.complete => {
|
||||
const all = self.screen.getVisible();
|
||||
std.mem.set(Screen.Cell, all, self.screen.cursor.pen);
|
||||
const region = self.screen.region(.active);
|
||||
std.mem.set(Screen.Cell, region[0], self.screen.cursor.pen);
|
||||
std.mem.set(Screen.Cell, region[1], self.screen.cursor.pen);
|
||||
|
||||
// Unsets pending wrap state
|
||||
self.screen.cursor.pending_wrap = false;
|
||||
|
Reference in New Issue
Block a user