Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146const std = @import("std");const assert = std.debug.assert;const Style = @import("Cell.zig").Style;const Cell = @import("Cell.zig");const MouseShape = @import("Mouse.zig").Shape;const CursorShape = Cell.CursorShape;
const log = std.log.scoped(.vaxis);
const InternalScreen = @This();
pub const InternalCell = struct { char: std.ArrayListUnmanaged(u8) = .empty, style: Style = .{}, uri: std.ArrayListUnmanaged(u8) = .empty, uri_id: std.ArrayListUnmanaged(u8) = .empty, // if we got skipped because of a wide character skipped: bool = false, default: bool = true,
// If we should skip rendering *this* round due to being printed over previously (from a scaled // cell, for example) skip: bool = false,
scale: Cell.Scale = .{},
pub fn eql(self: InternalCell, cell: Cell) bool {
// fastpath when both cells are default if (self.default and cell.default) return true;
return std.mem.eql(u8, self.char.items, cell.char.grapheme) and Style.eql(self.style, cell.style) and std.mem.eql(u8, self.uri.items, cell.link.uri) and std.mem.eql(u8, self.uri_id.items, cell.link.params); }};
arena: *std.heap.ArenaAllocator,width: u16 = 0,height: u16 = 0,
buf: []InternalCell,
cursor_vis: bool = false,cursor_shape: CursorShape = .default,
mouse_shape: MouseShape = .default,
/// sets each cell to the default cellpub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !InternalScreen { const arena = try alloc.create(std.heap.ArenaAllocator); arena.* = .init(alloc); var screen = InternalScreen{ .arena = arena, .buf = try arena.allocator().alloc(InternalCell, @as(usize, @intCast(w)) * h), }; for (screen.buf, 0..) |_, i| { screen.buf[i] = .{ .char = try std.ArrayListUnmanaged(u8).initCapacity(arena.allocator(), 1), .uri = .empty, .uri_id = .empty, }; screen.buf[i].char.appendAssumeCapacity(' '); } screen.width = w; screen.height = h; return screen;}
pub fn deinit(self: *InternalScreen, alloc: std.mem.Allocator) void { self.arena.deinit(); alloc.destroy(self.arena); self.* = undefined;}
/// writes a cell to a location. 0 indexedpub fn writeCell( self: *InternalScreen, col: u16, row: u16, cell: Cell,) void { if (self.width <= col) { // column out of bounds return; } if (self.height <= row) { // height out of bounds return; } const i = (@as(usize, @intCast(row)) * self.width) + col; assert(i < self.buf.len); self.buf[i].char.clearRetainingCapacity(); self.buf[i].char.appendSlice(self.arena.allocator(), cell.char.grapheme) catch { log.warn("couldn't write grapheme", .{}); }; self.buf[i].uri.clearRetainingCapacity(); self.buf[i].uri.appendSlice(self.arena.allocator(), cell.link.uri) catch { log.warn("couldn't write uri", .{}); }; self.buf[i].uri_id.clearRetainingCapacity(); self.buf[i].uri_id.appendSlice(self.arena.allocator(), cell.link.params) catch { log.warn("couldn't write uri_id", .{}); }; self.buf[i].style = cell.style; self.buf[i].default = cell.default;}
pub fn readCell(self: *InternalScreen, col: u16, row: u16) ?Cell { if (self.width <= col) { // column out of bounds return null; } if (self.height <= row) { // height out of bounds return null; } const i = (row * self.width) + col; assert(i < self.buf.len); const cell = self.buf[i]; return .{ .char = .{ .grapheme = cell.char.items }, .style = cell.style, .link = .{ .uri = cell.uri.items, .params = cell.uri_id.items, }, .default = cell.default, };}
test "InternalScreen: out-of-bounds read/write are ignored" { var screen = try InternalScreen.init(std.testing.allocator, 2, 2); defer screen.deinit(std.testing.allocator);
const sentinel: Cell = .{ .char = .{ .grapheme = "A", .width = 1 } }; screen.writeCell(0, 1, sentinel);
const oob_cell: Cell = .{ .char = .{ .grapheme = "X", .width = 1 } }; screen.writeCell(2, 0, oob_cell); const read_back = screen.readCell(0, 1) orelse return error.TestUnexpectedResult; try std.testing.expect(std.mem.eql(u8, read_back.char.grapheme, "A")); try std.testing.expect(screen.readCell(2, 0) == null);}