this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

at bf4e6ae3d396e62f1be2c1fde61dae1cbbd2aa57 127 lines 3.7 kB view raw
1const std = @import("std"); 2const assert = std.debug.assert; 3const Style = @import("Cell.zig").Style; 4const Cell = @import("Cell.zig"); 5const MouseShape = @import("Mouse.zig").Shape; 6const CursorShape = Cell.CursorShape; 7 8const log = std.log.scoped(.vaxis); 9 10const InternalScreen = @This(); 11 12pub const InternalCell = struct { 13 char: std.ArrayListUnmanaged(u8) = .empty, 14 style: Style = .{}, 15 uri: std.ArrayListUnmanaged(u8) = .empty, 16 uri_id: std.ArrayListUnmanaged(u8) = .empty, 17 // if we got skipped because of a wide character 18 skipped: bool = false, 19 default: bool = true, 20 21 pub fn eql(self: InternalCell, cell: Cell) bool { 22 23 // fastpath when both cells are default 24 if (self.default and cell.default) return true; 25 26 return std.mem.eql(u8, self.char.items, cell.char.grapheme) and 27 Style.eql(self.style, cell.style) and 28 std.mem.eql(u8, self.uri.items, cell.link.uri) and 29 std.mem.eql(u8, self.uri_id.items, cell.link.params); 30 } 31}; 32 33arena: *std.heap.ArenaAllocator = undefined, 34width: u16 = 0, 35height: u16 = 0, 36 37buf: []InternalCell = undefined, 38 39cursor_row: u16 = 0, 40cursor_col: u16 = 0, 41cursor_vis: bool = false, 42cursor_shape: CursorShape = .default, 43 44mouse_shape: MouseShape = .default, 45 46/// sets each cell to the default cell 47pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !InternalScreen { 48 const arena = try alloc.create(std.heap.ArenaAllocator); 49 arena.* = .init(alloc); 50 var screen = InternalScreen{ 51 .arena = arena, 52 .buf = try arena.allocator().alloc(InternalCell, @as(usize, @intCast(w)) * h), 53 }; 54 for (screen.buf, 0..) |_, i| { 55 screen.buf[i] = .{ 56 .char = try std.ArrayListUnmanaged(u8).initCapacity(arena.allocator(), 1), 57 .uri = .empty, 58 .uri_id = .empty, 59 }; 60 screen.buf[i].char.appendAssumeCapacity(' '); 61 } 62 screen.width = w; 63 screen.height = h; 64 return screen; 65} 66 67pub fn deinit(self: *InternalScreen, alloc: std.mem.Allocator) void { 68 self.arena.deinit(); 69 alloc.destroy(self.arena); 70 self.* = undefined; 71} 72 73/// writes a cell to a location. 0 indexed 74pub fn writeCell( 75 self: *InternalScreen, 76 col: u16, 77 row: u16, 78 cell: Cell, 79) void { 80 if (self.width < col) { 81 // column out of bounds 82 return; 83 } 84 if (self.height < row) { 85 // height out of bounds 86 return; 87 } 88 const i = (@as(usize, @intCast(row)) * self.width) + col; 89 assert(i < self.buf.len); 90 self.buf[i].char.clearRetainingCapacity(); 91 self.buf[i].char.appendSlice(self.arena.allocator(), cell.char.grapheme) catch { 92 log.warn("couldn't write grapheme", .{}); 93 }; 94 self.buf[i].uri.clearRetainingCapacity(); 95 self.buf[i].uri.appendSlice(self.arena.allocator(), cell.link.uri) catch { 96 log.warn("couldn't write uri", .{}); 97 }; 98 self.buf[i].uri_id.clearRetainingCapacity(); 99 self.buf[i].uri_id.appendSlice(self.arena.allocator(), cell.link.params) catch { 100 log.warn("couldn't write uri_id", .{}); 101 }; 102 self.buf[i].style = cell.style; 103 self.buf[i].default = cell.default; 104} 105 106pub fn readCell(self: *InternalScreen, col: u16, row: u16) ?Cell { 107 if (self.width < col) { 108 // column out of bounds 109 return null; 110 } 111 if (self.height < row) { 112 // height out of bounds 113 return null; 114 } 115 const i = (row * self.width) + col; 116 assert(i < self.buf.len); 117 const cell = self.buf[i]; 118 return .{ 119 .char = .{ .grapheme = cell.char.items }, 120 .style = cell.style, 121 .link = .{ 122 .uri = cell.uri.items, 123 .params = cell.uri_id.items, 124 }, 125 .default = cell.default, 126 }; 127}