From 8c9338ddd2c60f3dc8ff358397079b9cec18895c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Sat, 18 May 2024 16:49:01 +0200 Subject: [PATCH] feat: add support for scrolling and transparent windows in vaxis backend --- src/renderer/vaxis/Plane.zig | 43 ++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/renderer/vaxis/Plane.zig b/src/renderer/vaxis/Plane.zig index b1a46a1..fe5ad76 100644 --- a/src/renderer/vaxis/Plane.zig +++ b/src/renderer/vaxis/Plane.zig @@ -15,6 +15,8 @@ name_len: usize, cache: GraphemeCache = .{}, style: vaxis.Cell.Style = .{}, style_base: vaxis.Cell.Style = .{}, +scrolling: bool = false, +transparent: bool = false, pub const Options = struct { y: usize = 0, @@ -42,6 +44,7 @@ pub fn init(nopts: *const Options, parent_: Plane) !Plane { .window = parent_.window.child(opts), .name_buf = undefined, .name_len = std.mem.span(nopts.name).len, + .scrolling = nopts.flags == .VSCROLL, }; @memcpy(plane.name_buf[0..plane.name_len], nopts.name); return plane; @@ -135,6 +138,7 @@ pub fn print_aligned_center(self: *Plane, y: c_int, comptime fmt: anytype, args: pub fn putstr(self: *Plane, text: []const u8) !usize { var result: usize = 0; + const height = self.window.height; const width = self.window.width; var iter = self.window.screen.unicode.graphemeIterator(text); while (iter.next()) |grapheme| { @@ -142,21 +146,15 @@ pub fn putstr(self: *Plane, text: []const u8) !usize { return result; const s = grapheme.bytes(text); if (std.mem.eql(u8, s, "\n")) { - self.row += 1; + if (self.scrolling and self.row == height - 1) + self.window.scroll(1) + else + self.row += 1; self.col = 0; result += 1; continue; } - const w = self.window.gwidth(s); - if (w == 0) continue; - self.window.writeCell(@intCast(self.col), @intCast(self.row), .{ - .char = .{ - .grapheme = self.cache.put(s), - .width = w, - }, - .style = self.style, - }); - self.col += @intCast(w); + self.write_cell(@intCast(self.col), @intCast(self.row), s); result += 1; } return result; @@ -175,6 +173,20 @@ pub fn putc_yx(self: *Plane, y: c_int, x: c_int, cell: *const Cell) !usize { return w; } +fn write_cell(self: *Plane, col: usize, row: usize, egc: []const u8) void { + var cell: vaxis.Cell = self.window.readCell(col, row) orelse .{ .style = self.style }; + const w = self.window.gwidth(egc); + cell.char.grapheme = self.cache.put(egc); + cell.char.width = w; + if (self.transparent) { + cell.style.fg = self.style.fg; + } else { + cell.style = self.style; + } + self.window.writeCell(col, row, cell); + self.col += @intCast(w); +} + pub fn cursor_yx(self: Plane, y: *c_uint, x: *c_uint) void { y.* = @intCast(self.row); x.* = @intCast(self.col); @@ -212,7 +224,6 @@ pub fn cell_init(self: Plane) Cell { } pub fn cell_load(self: *Plane, cell: *Cell, gcluster: [:0]const u8) !usize { - cell.* = .{ .cell = .{ .style = self.style } }; var cols: c_int = 0; const bytes = self.egc_length(gcluster, &cols, 0); cell.cell.char.grapheme = self.cache.put(gcluster[0..bytes]); @@ -275,28 +286,32 @@ pub inline fn set_base_style(self: *Plane, _: [*c]const u8, style_: Style) void pub fn set_base_style_transparent(self: *Plane, _: [*:0]const u8, style_: Style) void { self.style_base.fg = if (style_.fg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default; - self.style_base.bg = if (style_.bg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default; + self.style.bg = .default; if (style_.fs) |fs| set_font_style(&self.style, fs); self.set_style(style_); + self.transparent = true; } pub fn set_base_style_bg_transparent(self: *Plane, _: [*:0]const u8, style_: Style) void { self.style_base.fg = if (style_.fg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default; - self.style_base.bg = if (style_.bg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default; + self.style.bg = .default; if (style_.fs) |fs| set_font_style(&self.style, fs); self.set_style(style_); + self.transparent = true; } pub inline fn set_style(self: *Plane, style_: Style) void { if (style_.fg) |color| self.style.fg = vaxis.Cell.Color.rgbFromUint(@intCast(color)); if (style_.bg) |color| self.style.bg = vaxis.Cell.Color.rgbFromUint(@intCast(color)); if (style_.fs) |fs| set_font_style(&self.style, fs); + self.transparent = false; } pub inline fn set_style_bg_transparent(self: *Plane, style_: Style) void { if (style_.fg) |color| self.style.fg = vaxis.Cell.Color.rgbFromUint(@intCast(color)); self.style.bg = .default; if (style_.fs) |fs| set_font_style(&self.style, fs); + self.transparent = true; } inline fn set_font_style(style: *vaxis.Cell.Style, fs: FontStyle) void {