diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index 9590f2fbb..403fe7e5a 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -7,6 +7,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; const fastmem = @import("../fastmem.zig"); +const kitty = @import("kitty.zig"); const point = @import("point.zig"); const pagepkg = @import("page.zig"); const stylepkg = @import("style.zig"); @@ -1056,6 +1057,11 @@ const ReflowCursor = struct { self.page_cell.style_id = id; } + // Copy Kitty virtual placeholder status + if (cell.codepoint() == kitty.graphics.unicode.placeholder) { + self.page_row.kitty_virtual_placeholder = true; + } + self.cursorForward(); } diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index 12bdaa73c..30ffc39e3 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -984,6 +984,16 @@ pub fn clearCells( if (cells.len == self.pages.cols) row.styled = false; } + if (row.kitty_virtual_placeholder and + cells.len == self.pages.cols) + { + for (cells) |c| { + if (c.codepoint() == kitty.graphics.unicode.placeholder) { + break; + } + } else row.kitty_virtual_placeholder = false; + } + @memset(cells, self.blankCell()); } diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 013325c3a..d6b8a7376 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -640,6 +640,12 @@ fn printCell( } } + // If this is a Kitty unicode placeholder then we need to mark the + // row so that the renderer can lookup rows with these much faster. + if (c == kitty.graphics.unicode.placeholder) { + self.screen.cursor.page_row.kitty_virtual_placeholder = true; + } + // We check for an active hyperlink first because setHyperlink // handles clearing the old hyperlink and an optimization if we're // overwriting the same hyperlink. diff --git a/src/terminal/page.zig b/src/terminal/page.zig index 18b63f126..9d149270e 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -826,6 +826,9 @@ pub const Page = struct { src_cell.style_id, ) orelse src_cell.style_id; } + if (src_cell.codepoint() == kitty.graphics.unicode.placeholder) { + dst_row.kitty_virtual_placeholder = true; + } } } @@ -913,6 +916,9 @@ pub const Page = struct { dst.hyperlink = true; dst_row.hyperlink = true; } + if (src.codepoint() == kitty.graphics.unicode.placeholder) { + dst_row.kitty_virtual_placeholder = true; + } } } @@ -932,6 +938,7 @@ pub const Page = struct { src_row.grapheme = false; src_row.hyperlink = false; src_row.styled = false; + src_row.kitty_virtual_placeholder = false; } } @@ -1029,6 +1036,16 @@ pub const Page = struct { if (cells.len == self.size.cols) row.styled = false; } + if (row.kitty_virtual_placeholder and + cells.len == self.size.cols) + { + for (cells) |c| { + if (c.codepoint() == kitty.graphics.unicode.placeholder) { + break; + } + } else row.kitty_virtual_placeholder = false; + } + // Zero the cells as u64s since empirically this seems // to be a bit faster than using @memset(cells, .{}) @memset(@as([]u64, @ptrCast(cells)), 0); @@ -1552,7 +1569,11 @@ pub const Row = packed struct(u64) { /// running program, or "unknown" if it was never set. semantic_prompt: SemanticPrompt = .unknown, - _padding: u24 = 0, + /// True if this row contains a virtual placeholder for the Kitty + /// graphics protocol. (U+10EEEE) + kitty_virtual_placeholder: bool = false, + + _padding: u23 = 0, /// Semantic prompt type. pub const SemanticPrompt = enum(u3) {