mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
terminal/new: eraseRows
This commit is contained in:
@ -488,12 +488,26 @@ pub const RowChunkIterator = struct {
|
||||
///
|
||||
/// This is a more efficient way to iterate through the data in a region,
|
||||
/// since you can do simple pointer math and so on.
|
||||
///
|
||||
/// If bl_pt is non-null, iteration will stop at the bottom left point
|
||||
/// (inclusive). If bl_pt is null, the entire region specified by the point
|
||||
/// tag will be iterated over. tl_pt and bl_pt must be the same tag, and
|
||||
/// bl_pt must be greater than or equal to tl_pt.
|
||||
pub fn rowChunkIterator(
|
||||
self: *const PageList,
|
||||
tl_pt: point.Point,
|
||||
bl_pt: ?point.Point,
|
||||
) RowChunkIterator {
|
||||
// TODO: bl_pt assertions
|
||||
|
||||
const tl = self.getTopLeft(tl_pt);
|
||||
const limit: RowChunkIterator.Limit = switch (tl_pt) {
|
||||
const limit: RowChunkIterator.Limit = limit: {
|
||||
if (bl_pt) |pt| {
|
||||
const bl = self.getTopLeft(pt);
|
||||
break :limit .{ .row = bl.forward(pt.coord().y).? };
|
||||
}
|
||||
|
||||
break :limit switch (tl_pt) {
|
||||
// These always go to the end of the screen.
|
||||
.screen, .active => .{ .none = {} },
|
||||
|
||||
@ -504,6 +518,7 @@ pub fn rowChunkIterator(
|
||||
// to calculate but also more rare of a thing to iterate over.
|
||||
.history => .{ .row = self.getTopLeft(.active) },
|
||||
};
|
||||
};
|
||||
|
||||
return .{ .row = tl.forward(tl_pt.coord().y), .limit = limit };
|
||||
}
|
||||
@ -1040,7 +1055,7 @@ test "PageList rowChunkIterator single page" {
|
||||
try testing.expect(s.pages.first.?.next == null);
|
||||
|
||||
// Iterate the active area
|
||||
var it = s.rowChunkIterator(.{ .active = .{} });
|
||||
var it = s.rowChunkIterator(.{ .active = .{} }, null);
|
||||
{
|
||||
const chunk = it.next().?;
|
||||
try testing.expect(chunk.page == s.pages.first.?);
|
||||
@ -1068,7 +1083,7 @@ test "PageList rowChunkIterator two pages" {
|
||||
try testing.expect(try s.grow() != null);
|
||||
|
||||
// Iterate the active area
|
||||
var it = s.rowChunkIterator(.{ .active = .{} });
|
||||
var it = s.rowChunkIterator(.{ .active = .{} }, null);
|
||||
{
|
||||
const chunk = it.next().?;
|
||||
try testing.expect(chunk.page == s.pages.first.?);
|
||||
@ -1102,7 +1117,7 @@ test "PageList rowChunkIterator history two pages" {
|
||||
try testing.expect(try s.grow() != null);
|
||||
|
||||
// Iterate the active area
|
||||
var it = s.rowChunkIterator(.{ .history = .{} });
|
||||
var it = s.rowChunkIterator(.{ .history = .{} }, null);
|
||||
{
|
||||
const active_tl = s.getTopLeft(.active);
|
||||
const chunk = it.next().?;
|
||||
|
@ -277,10 +277,11 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
|
||||
}
|
||||
}
|
||||
|
||||
/// Erase the active area of the screen from y=0 to rows-1. The cells
|
||||
/// are blanked using the given blank cell.
|
||||
pub fn eraseActive(self: *Screen) void {
|
||||
var it = self.pages.rowChunkIterator(.{ .active = .{} });
|
||||
// Erase the region specified by tl and bl, inclusive. Erased cells are
|
||||
// colored with the current style background color. This will erase all
|
||||
// cells in the rows.
|
||||
pub fn eraseRows(self: *Screen, tl: point.Point, bl: ?point.Point) void {
|
||||
var it = self.pages.rowChunkIterator(tl, bl);
|
||||
while (it.next()) |chunk| {
|
||||
for (chunk.rows()) |*row| {
|
||||
const cells_offset = row.cells;
|
||||
@ -345,6 +346,20 @@ pub fn eraseCells(
|
||||
@memset(cells, self.blankCell());
|
||||
}
|
||||
|
||||
/// Erase cells but only if they are not protected.
|
||||
pub fn eraseUnprotectedCells(
|
||||
self: *Screen,
|
||||
page: *Page,
|
||||
row: *Row,
|
||||
cells: []Cell,
|
||||
) void {
|
||||
for (cells) |*cell| {
|
||||
if (cell.protected) continue;
|
||||
const cell_multi: [*]Cell = @ptrCast(cell);
|
||||
self.eraseCells(page, row, cell_multi[0..1]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the blank cell to use when doing terminal operations that
|
||||
/// require preserving the bg color.
|
||||
fn blankCell(self: *const Screen) Cell {
|
||||
@ -743,7 +758,7 @@ test "Screen style reset with unset" {
|
||||
try testing.expectEqual(@as(usize, 0), page.styles.count(page.memory));
|
||||
}
|
||||
|
||||
test "Screen eraseActive one line" {
|
||||
test "Screen eraseRows active one line" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
@ -751,13 +766,13 @@ test "Screen eraseActive one line" {
|
||||
defer s.deinit();
|
||||
|
||||
try s.testWriteString("hello, world");
|
||||
s.eraseActive();
|
||||
s.eraseRows(.{ .active = .{} }, null);
|
||||
const str = try s.dumpStringAlloc(alloc, .{ .screen = .{} });
|
||||
defer alloc.free(str);
|
||||
try testing.expectEqualStrings("", str);
|
||||
}
|
||||
|
||||
test "Screen eraseActive multi line" {
|
||||
test "Screen eraseRows active multi line" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
@ -765,13 +780,13 @@ test "Screen eraseActive multi line" {
|
||||
defer s.deinit();
|
||||
|
||||
try s.testWriteString("hello\nworld");
|
||||
s.eraseActive();
|
||||
s.eraseRows(.{ .active = .{} }, null);
|
||||
const str = try s.dumpStringAlloc(alloc, .{ .screen = .{} });
|
||||
defer alloc.free(str);
|
||||
try testing.expectEqualStrings("", str);
|
||||
}
|
||||
|
||||
test "Screen eraseActive styled line" {
|
||||
test "Screen eraseRows active styled line" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
@ -786,7 +801,7 @@ test "Screen eraseActive styled line" {
|
||||
const page = s.cursor.page_offset.page.data;
|
||||
try testing.expectEqual(@as(usize, 1), page.styles.count(page.memory));
|
||||
|
||||
s.eraseActive();
|
||||
s.eraseRows(.{ .active = .{} }, null);
|
||||
|
||||
// We should have none because active cleared it
|
||||
try testing.expectEqual(@as(usize, 0), page.styles.count(page.memory));
|
||||
|
Reference in New Issue
Block a user