diff --git a/examples/cli.zig b/examples/cli.zig index 9a19541..0ec8547 100644 --- a/examples/cli.zig +++ b/examples/cli.zig @@ -92,7 +92,7 @@ pub fn main() !void { .text = opt, .style = if (j == i) .{ .reverse = true } else .{}, }}; - _ = win.print(&seg, .{ .row_offset = j + 1 }); + _ = win.print(&seg, .{ .row_offset = @intCast(j + 1) }); } } try vx.render(tty.anyWriter()); diff --git a/examples/image.zig b/examples/image.zig index 0b05b68..6015457 100644 --- a/examples/image.zig +++ b/examples/image.zig @@ -47,7 +47,7 @@ pub fn main() !void { var n: usize = 0; - var clip_y: usize = 0; + var clip_y: u16 = 0; while (true) { const event = loop.nextEvent(); diff --git a/examples/main.zig b/examples/main.zig index 4cfeb13..fbf116f 100644 --- a/examples/main.zig +++ b/examples/main.zig @@ -67,12 +67,13 @@ pub fn main() !void { // the old and only updated cells will be drawn win.clear(); + const msg_len: u16 = @intCast(msg.len); // Create some child window. .expand means the height and width will // fill the remaining space of the parent. Child windows do not store a // reference to their parent: this is true immediate mode. Do not store // windows, always create new windows each render cycle const child = win.child( - .{ .x_off = win.width / 2 - msg.len / 2, .y_off = win.height / 2 }, + .{ .x_off = win.width / 2 - msg_len / 2, .y_off = win.height / 2 }, ); // Loop through the message and print the cells to the screen for (msg, 0..) |_, i| { @@ -86,7 +87,7 @@ pub fn main() !void { .fg = .{ .index = color_idx }, }, }; - child.writeCell(i, 0, cell); + child.writeCell(@intCast(i), 0, cell); } // Render the screen try vx.render(tty.anyWriter()); diff --git a/examples/table.zig b/examples/table.zig index 3259f33..25e623f 100644 --- a/examples/table.zig +++ b/examples/table.zig @@ -155,10 +155,10 @@ pub fn main() !void { // Select/Unselect Row if (key.matches(vaxis.Key.space, .{})) { const rows = demo_tbl.sel_rows orelse createRows: { - demo_tbl.sel_rows = try alloc.alloc(usize, 1); + demo_tbl.sel_rows = try alloc.alloc(u16, 1); break :createRows demo_tbl.sel_rows.?; }; - var rows_list = std.ArrayList(usize).fromOwnedSlice(alloc, rows); + var rows_list = std.ArrayList(u16).fromOwnedSlice(alloc, rows); for (rows_list.items, 0..) |row, idx| { if (row != demo_tbl.row) continue; _ = rows_list.orderedRemove(idx); @@ -179,11 +179,11 @@ pub fn main() !void { mem.eql(u8, ":quit", cmd) or mem.eql(u8, ":exit", cmd)) return; if (mem.eql(u8, "G", cmd)) { - demo_tbl.row = user_list.items.len - 1; + demo_tbl.row = @intCast(user_list.items.len - 1); active = .mid; } if (cmd.len >= 2 and mem.eql(u8, "gg", cmd[0..2])) { - const goto_row = fmt.parseInt(usize, cmd[2..], 0) catch 0; + const goto_row = fmt.parseInt(u16, cmd[2..], 0) catch 0; demo_tbl.row = goto_row; active = .mid; } @@ -213,7 +213,7 @@ pub fn main() !void { }; demo_tbl.active_ctx = &row_ctx; demo_tbl.active_content_fn = struct { - fn see(win: *vaxis.Window, ctx_raw: *const anyopaque) !usize { + fn see(win: *vaxis.Window, ctx_raw: *const anyopaque) !u16 { const ctx: *const RowContext = @alignCast(@ptrCast(ctx_raw)); win.height = 5; const see_win = win.child(.{ diff --git a/examples/view.zig b/examples/view.zig index bb85687..89a29da 100644 --- a/examples/view.zig +++ b/examples/view.zig @@ -29,10 +29,10 @@ pub fn main() !void { var use_sm_map = false; var use_mini_view = false; - var x: usize = 0; - var y: usize = 0; - var h: usize = 0; - var w: usize = 0; + var x: u16 = 0; + var y: u16 = 0; + var h: u16 = 0; + var w: u16 = 0; defer log.info( \\Results: \\ - Map Size: {d}x{d} @@ -351,11 +351,11 @@ const lg_world_map = \\ +SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS+ \\ ; -const lg_map_width = mapWidth: { +const lg_map_width: u16 = mapWidth: { @setEvalBranchQuota(100_000); - break :mapWidth mem.indexOfScalar(u8, lg_world_map, '\n').?; + break :mapWidth @intCast(mem.indexOfScalar(u8, lg_world_map, '\n').?); }; -const lg_map_height = mapHeight: { +const lg_map_height: u16 = mapHeight: { @setEvalBranchQuota(100_000); - break :mapHeight mem.count(u8, lg_world_map, "\n"); + break :mapHeight @intCast(mem.count(u8, lg_world_map, "\n")); }; diff --git a/src/Image.zig b/src/Image.zig index 97b1042..85cc711 100644 --- a/src/Image.zig +++ b/src/Image.zig @@ -33,8 +33,8 @@ pub const Placement = struct { }; pub const CellSize = struct { - rows: usize, - cols: usize, + rows: u16, + cols: u16, }; pub const DrawOptions = struct { @@ -42,8 +42,8 @@ pub const DrawOptions = struct { /// origin of the image. These must be less than the pixel size of a single /// cell pixel_offset: ?struct { - x: usize, - y: usize, + x: u16, + y: u16, } = null, /// the vertical stacking order /// < 0: Drawn beneath text @@ -51,10 +51,10 @@ pub const DrawOptions = struct { z_index: ?i32 = null, /// A clip region of the source image to draw. clip_region: ?struct { - x: ?usize = null, - y: ?usize = null, - width: ?usize = null, - height: ?usize = null, + x: ?u16 = null, + y: ?u16 = null, + width: ?u16 = null, + height: ?u16 = null, } = null, /// Scaling to apply to the Image scale: enum { @@ -71,8 +71,8 @@ pub const DrawOptions = struct { /// field, and should prefer to use scale. `draw` will fill in this field with /// the correct values if a scale method is applied. size: ?struct { - rows: ?usize = null, - cols: ?usize = null, + rows: ?u16 = null, + cols: ?u16 = null, } = null, }; @@ -80,9 +80,9 @@ pub const DrawOptions = struct { id: u32, /// width in pixels -width: usize, +width: u16, /// height in pixels -height: usize, +height: u16, pub fn draw(self: Image, win: Window, opts: DrawOptions) !void { var p_opts = opts; @@ -176,11 +176,11 @@ pub fn cellSize(self: Image, win: Window) !CellSize { const w = win.screen.width; const h = win.screen.height; - const pix_per_col = try std.math.divCeil(usize, x_pix, w); - const pix_per_row = try std.math.divCeil(usize, y_pix, h); + const pix_per_col = try std.math.divCeil(u16, x_pix, w); + const pix_per_row = try std.math.divCeil(u16, y_pix, h); - const cell_width = std.math.divCeil(usize, self.width, pix_per_col) catch 0; - const cell_height = std.math.divCeil(usize, self.height, pix_per_row) catch 0; + const cell_width = std.math.divCeil(u16, self.width, pix_per_col) catch 0; + const cell_height = std.math.divCeil(u16, self.height, pix_per_row) catch 0; return .{ .rows = cell_height, .cols = cell_width, diff --git a/src/InternalScreen.zig b/src/InternalScreen.zig index 5d41940..a6e11ee 100644 --- a/src/InternalScreen.zig +++ b/src/InternalScreen.zig @@ -32,20 +32,20 @@ pub const InternalCell = struct { } }; -width: usize = 0, -height: usize = 0, +width: u16 = 0, +height: u16 = 0, buf: []InternalCell = undefined, -cursor_row: usize = 0, -cursor_col: usize = 0, +cursor_row: u16 = 0, +cursor_col: u16 = 0, cursor_vis: bool = false, cursor_shape: CursorShape = .default, mouse_shape: MouseShape = .default, /// sets each cell to the default cell -pub fn init(alloc: std.mem.Allocator, w: usize, h: usize) !InternalScreen { +pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !InternalScreen { var screen = InternalScreen{ .buf = try alloc.alloc(InternalCell, w * h), }; @@ -75,8 +75,8 @@ pub fn deinit(self: *InternalScreen, alloc: std.mem.Allocator) void { /// writes a cell to a location. 0 indexed pub fn writeCell( self: *InternalScreen, - col: usize, - row: usize, + col: u16, + row: u16, cell: Cell, ) void { if (self.width < col) { @@ -105,7 +105,7 @@ pub fn writeCell( self.buf[i].default = cell.default; } -pub fn readCell(self: *InternalScreen, col: usize, row: usize) ?Cell { +pub fn readCell(self: *InternalScreen, col: u16, row: u16) ?Cell { if (self.width < col) { // column out of bounds return null; diff --git a/src/Mouse.zig b/src/Mouse.zig index ca4ac6b..0f62cbf 100644 --- a/src/Mouse.zig +++ b/src/Mouse.zig @@ -41,10 +41,10 @@ pub const Type = enum { drag, }; -col: usize, -row: usize, -xoffset: usize = 0, -yoffset: usize = 0, +col: u16, +row: u16, +xoffset: u16 = 0, +yoffset: u16 = 0, button: Button, mods: Modifiers, type: Type, diff --git a/src/Parser.zig b/src/Parser.zig index 767985f..6a481fb 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -522,10 +522,10 @@ inline fn parseCsi(input: []const u8, text_buf: []u8) Result { const width_pix = iter.next() orelse "0"; const winsize: Winsize = .{ - .rows = std.fmt.parseUnsigned(usize, height_char, 10) catch return null_event, - .cols = std.fmt.parseUnsigned(usize, width_char, 10) catch return null_event, - .x_pixel = std.fmt.parseUnsigned(usize, width_pix, 10) catch return null_event, - .y_pixel = std.fmt.parseUnsigned(usize, height_pix, 10) catch return null_event, + .rows = std.fmt.parseUnsigned(u16, height_char, 10) catch return null_event, + .cols = std.fmt.parseUnsigned(u16, width_char, 10) catch return null_event, + .x_pixel = std.fmt.parseUnsigned(u16, width_pix, 10) catch return null_event, + .y_pixel = std.fmt.parseUnsigned(u16, height_pix, 10) catch return null_event, }; return .{ .event = .{ .winsize = winsize }, diff --git a/src/Screen.zig b/src/Screen.zig index 9282226..6eea1a8 100644 --- a/src/Screen.zig +++ b/src/Screen.zig @@ -10,16 +10,16 @@ const Method = @import("gwidth.zig").Method; const Screen = @This(); -width: usize = 0, -height: usize = 0, +width: u16 = 0, +height: u16 = 0, -width_pix: usize = 0, -height_pix: usize = 0, +width_pix: u16 = 0, +height_pix: u16 = 0, buf: []Cell = undefined, -cursor_row: usize = 0, -cursor_col: usize = 0, +cursor_row: u16 = 0, +cursor_col: u16 = 0, cursor_vis: bool = false, unicode: *const Unicode = undefined, @@ -49,7 +49,7 @@ pub fn deinit(self: *Screen, alloc: std.mem.Allocator) void { } /// writes a cell to a location. 0 indexed -pub fn writeCell(self: *Screen, col: usize, row: usize, cell: Cell) void { +pub fn writeCell(self: *Screen, col: u16, row: u16, cell: Cell) void { if (self.width <= col) { // column out of bounds return; @@ -63,7 +63,7 @@ pub fn writeCell(self: *Screen, col: usize, row: usize, cell: Cell) void { self.buf[i] = cell; } -pub fn readCell(self: *const Screen, col: usize, row: usize) ?Cell { +pub fn readCell(self: *const Screen, col: u16, row: u16) ?Cell { if (self.width <= col) { // column out of bounds return null; diff --git a/src/Vaxis.zig b/src/Vaxis.zig index 5a31945..14b77d8 100644 --- a/src/Vaxis.zig +++ b/src/Vaxis.zig @@ -23,6 +23,8 @@ const Winsize = @import("main.zig").Winsize; const ctlseqs = @import("ctlseqs.zig"); const gwidth = @import("gwidth.zig"); +const assert = std.debug.assert; + const Vaxis = @This(); const log = std.log.scoped(.vaxis); @@ -84,8 +86,8 @@ state: struct { changed_default_fg: bool = false, changed_default_bg: bool = false, cursor: struct { - row: usize = 0, - col: usize = 0, + row: u16 = 0, + col: u16 = 0, } = .{}, } = .{}, @@ -139,7 +141,7 @@ pub fn resetState(self: *Vaxis, tty: AnyWriter) !void { try self.exitAltScreen(tty); } else { try tty.writeByte('\r'); - var i: usize = 0; + var i: u16 = 0; while (i < self.state.cursor.row) : (i += 1) { try tty.writeAll(ctlseqs.ri); } @@ -308,6 +310,8 @@ pub fn queueRefresh(self: *Vaxis) void { /// draws the screen to the terminal pub fn render(self: *Vaxis, tty: AnyWriter) !void { defer self.refresh = false; + assert(self.screen.buf.len == self.screen.width * self.screen.height); // correct size + assert(self.screen.buf.len == self.screen_last.buf.len); // same size // Set up sync before we write anything // TODO: optimize sync so we only sync _when we have changes_. This @@ -331,27 +335,27 @@ pub fn render(self: *Vaxis, tty: AnyWriter) !void { // initialize some variables var reposition: bool = false; - var row: usize = 0; - var col: usize = 0; + var row: u16 = 0; + var col: u16 = 0; var cursor: Style = .{}; var link: Hyperlink = .{}; var cursor_pos: struct { - row: usize = 0, - col: usize = 0, + row: u16 = 0, + col: u16 = 0, } = .{}; // Clear all images if (self.caps.kitty_graphics) try tty.writeAll(ctlseqs.kitty_graphics_clear); - var i: usize = 0; + var i: u16 = 0; while (i < self.screen.buf.len) { const cell = self.screen.buf[i]; - const w = blk: { + const w: u16 = blk: { if (cell.char.width != 0) break :blk cell.char.width; const method: gwidth.Method = self.caps.unicode; - const width = gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data); + const width: u16 = @intCast(gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data)); break :blk @max(1, width); }; defer { @@ -726,8 +730,8 @@ pub fn transmitLocalImagePath( allocator: std.mem.Allocator, tty: AnyWriter, payload: []const u8, - width: usize, - height: usize, + width: u16, + height: u16, medium: Image.TransmitMedium, format: Image.TransmitFormat, ) !Image { @@ -780,8 +784,8 @@ pub fn transmitPreEncodedImage( self: *Vaxis, tty: AnyWriter, bytes: []const u8, - width: usize, - height: usize, + width: u16, + height: u16, format: Image.TransmitFormat, ) !Image { defer self.next_img_id += 1; @@ -861,7 +865,7 @@ pub fn transmitImage( const b64_buf = try arena.allocator().alloc(u8, base64Encoder.calcSize(buf.len)); const encoded = base64Encoder.encode(b64_buf, buf); - return self.transmitPreEncodedImage(tty, encoded, img.width, img.height, format); + return self.transmitPreEncodedImage(tty, encoded, @intCast(img.width), @intCast(img.height), format); } pub fn loadImage( @@ -961,16 +965,16 @@ pub fn prettyPrint(self: *Vaxis, tty: AnyWriter) !void { defer tty.writeAll(ctlseqs.sgr_reset) catch {}; var reposition: bool = false; - var row: usize = 0; - var col: usize = 0; + var row: u16 = 0; + var col: u16 = 0; var cursor: Style = .{}; var link: Hyperlink = .{}; var cursor_pos: struct { - row: usize = 0, - col: usize = 0, + row: u16 = 0, + col: u16 = 0, } = .{}; - var i: usize = 0; + var i: u16 = 0; while (i < self.screen.buf.len) { const cell = self.screen.buf[i]; const w = blk: { diff --git a/src/Window.zig b/src/Window.zig index ab81fee..dd3d628 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -11,17 +11,17 @@ const Window = @This(); pub const Size = union(enum) { expand, - limit: usize, + limit: u16, }; /// horizontal offset from the screen -x_off: usize, +x_off: u16, /// vertical offset from the screen -y_off: usize, +y_off: u16, /// width of the window. This can't be larger than the terminal screen -width: usize, +width: u16, /// height of the window. This can't be larger than the terminal screen -height: usize, +height: u16, screen: *Screen, @@ -30,12 +30,12 @@ screen: *Screen, /// unaware of resizes. fn initChild( self: Window, - x_off: usize, - y_off: usize, + x_off: u16, + y_off: u16, width: Size, height: Size, ) Window { - const resolved_width = switch (width) { + const resolved_width: u16 = switch (width) { .expand => self.width -| x_off, .limit => |w| blk: { if (w + x_off > self.width) { @@ -44,7 +44,7 @@ fn initChild( break :blk w; }, }; - const resolved_height = switch (height) { + const resolved_height: u16 = switch (height) { .expand => self.height -| y_off, .limit => |h| blk: { if (h + y_off > self.height) { @@ -63,8 +63,8 @@ fn initChild( } pub const ChildOptions = struct { - x_off: usize = 0, - y_off: usize = 0, + x_off: u16 = 0, + y_off: u16 = 0, /// the width of the resulting child, including any borders width: Size = .expand, /// the height of the resulting child, including any borders @@ -141,25 +141,25 @@ pub fn child(self: Window, opts: ChildOptions) Window { .other => |loc| loc, }; if (loc.top) { - var i: usize = 0; + var i: u16 = 0; while (i < w) : (i += 1) { result.writeCell(i, 0, .{ .char = horizontal, .style = style }); } } if (loc.bottom) { - var i: usize = 0; + var i: u16 = 0; while (i < w) : (i += 1) { result.writeCell(i, h -| 1, .{ .char = horizontal, .style = style }); } } if (loc.left) { - var i: usize = 0; + var i: u16 = 0; while (i < h) : (i += 1) { result.writeCell(0, i, .{ .char = vertical, .style = style }); } } if (loc.right) { - var i: usize = 0; + var i: u16 = 0; while (i < h) : (i += 1) { result.writeCell(w -| 1, i, .{ .char = vertical, .style = style }); } @@ -174,24 +174,24 @@ pub fn child(self: Window, opts: ChildOptions) Window { if (loc.bottom and loc.right) result.writeCell(w -| 1, h -| 1, .{ .char = bottom_right, .style = style }); - const x_off: usize = if (loc.left) 1 else 0; - const y_off: usize = if (loc.top) 1 else 0; - const h_delt: usize = if (loc.bottom) 1 else 0; - const w_delt: usize = if (loc.right) 1 else 0; - const h_ch: usize = h -| y_off -| h_delt; - const w_ch: usize = w -| x_off -| w_delt; + const x_off: u16 = if (loc.left) 1 else 0; + const y_off: u16 = if (loc.top) 1 else 0; + const h_delt: u16 = if (loc.bottom) 1 else 0; + const w_delt: u16 = if (loc.right) 1 else 0; + const h_ch: u16 = h -| y_off -| h_delt; + const w_ch: u16 = w -| x_off -| w_delt; return result.initChild(x_off, y_off, .{ .limit = w_ch }, .{ .limit = h_ch }); } /// writes a cell to the location in the window -pub fn writeCell(self: Window, col: usize, row: usize, cell: Cell) void { +pub fn writeCell(self: Window, col: u16, row: u16, cell: Cell) void { if (self.height == 0 or self.width == 0) return; if (self.height <= row or self.width <= col) return; self.screen.writeCell(col + self.x_off, row + self.y_off, cell); } /// reads a cell at the location in the window -pub fn readCell(self: Window, col: usize, row: usize) ?Cell { +pub fn readCell(self: Window, col: u16, row: u16) ?Cell { if (self.height == 0 or self.width == 0) return null; if (self.height <= row or self.width <= col) return null; return self.screen.readCell(col + self.x_off, row + self.y_off); @@ -203,7 +203,7 @@ pub fn clear(self: Window) void { } /// returns the width of the grapheme. This depends on the terminal capabilities -pub fn gwidth(self: Window, str: []const u8) usize { +pub fn gwidth(self: Window, str: []const u8) u16 { return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data); } @@ -220,7 +220,7 @@ pub fn fill(self: Window, cell: Cell) void { @memset(self.screen.buf[start..end], cell); } else { // Non-contiguous. Iterate over rows an memset - var row: usize = self.y_off; + var row: u16 = self.y_off; const last_row = @min(self.height + self.y_off, self.screen.height); while (row < last_row) : (row += 1) { const start = @min(self.x_off + (row * self.screen.width), self.screen.buf.len); @@ -237,7 +237,7 @@ pub fn hideCursor(self: Window) void { } /// show the cursor at the given coordinates, 0 indexed -pub fn showCursor(self: Window, col: usize, row: usize) void { +pub fn showCursor(self: Window, col: u16, row: u16) void { if (self.height == 0 or self.width == 0) return; if (self.height <= row or self.width <= col) return; self.screen.cursor_vis = true; @@ -252,9 +252,9 @@ pub fn setCursorShape(self: Window, shape: Cell.CursorShape) void { /// Options to use when printing Segments to a window pub const PrintOptions = struct { /// vertical offset to start printing at - row_offset: usize = 0, + row_offset: u16 = 0, /// horizontal offset to start printing at - col_offset: usize = 0, + col_offset: u16 = 0, /// wrap behavior for printing wrap: enum { @@ -273,8 +273,8 @@ pub const PrintOptions = struct { }; pub const PrintResult = struct { - col: usize, - row: usize, + col: u16, + row: u16, overflow: bool, }; @@ -284,7 +284,7 @@ pub fn print(self: Window, segments: []const Segment, opts: PrintOptions) PrintR var row = opts.row_offset; switch (opts.wrap) { .grapheme => { - var col: usize = opts.col_offset; + var col: u16 = opts.col_offset; const overflow: bool = blk: for (segments) |segment| { var iter = self.screen.unicode.graphemeIterator(segment.text); while (iter.next()) |grapheme| { @@ -324,7 +324,7 @@ pub fn print(self: Window, segments: []const Segment, opts: PrintOptions) PrintR }; }, .word => { - var col: usize = opts.col_offset; + var col: u16 = opts.col_offset; var overflow: bool = false; var soft_wrapped: bool = false; outer: for (segments) |segment| { @@ -406,7 +406,7 @@ pub fn print(self: Window, segments: []const Segment, opts: PrintOptions) PrintR }; }, .none => { - var col: usize = opts.col_offset; + var col: u16 = opts.col_offset; const overflow: bool = blk: for (segments) |segment| { var iter = self.screen.unicode.graphemeIterator(segment.text); while (iter.next()) |grapheme| { @@ -443,7 +443,7 @@ pub fn printSegment(self: Window, segment: Segment, opts: PrintOptions) PrintRes /// scrolls the window down one row (IE inserts a blank row at the bottom of the /// screen and shifts all rows up one) -pub fn scroll(self: Window, n: usize) void { +pub fn scroll(self: Window, n: u16) void { if (n > self.height) return; var row = self.y_off; while (row < self.height - n) : (row += 1) { diff --git a/src/gwidth.zig b/src/gwidth.zig index 2e3ca7d..5f7ffdd 100644 --- a/src/gwidth.zig +++ b/src/gwidth.zig @@ -12,30 +12,29 @@ pub const Method = enum { }; /// returns the width of the provided string, as measured by the method chosen -pub fn gwidth(str: []const u8, method: Method, data: *const DisplayWidth.DisplayWidthData) usize { +pub fn gwidth(str: []const u8, method: Method, data: *const DisplayWidth.DisplayWidthData) u16 { switch (method) { .unicode => { const dw: DisplayWidth = .{ .data = data }; - return dw.strWidth(str); + return @intCast(dw.strWidth(str)); }, .wcwidth => { - var total: usize = 0; + var total: u16 = 0; var iter: code_point.Iterator = .{ .bytes = str }; while (iter.next()) |cp| { - const w = switch (cp.code) { + const w: u16 = switch (cp.code) { // undo an override in zg for emoji skintone selectors 0x1f3fb...0x1f3ff, => 2, - else => data.codePointWidth(cp.code), + else => @max(0, data.codePointWidth(cp.code)), }; - if (w < 0) continue; - total += @intCast(w); + total += w; } return total; }, .no_zwj => { var iter = std.mem.split(u8, str, "\u{200D}"); - var result: usize = 0; + var result: u16 = 0; while (iter.next()) |s| { result += gwidth(s, .unicode, data); } diff --git a/src/main.zig b/src/main.zig index 855bd91..c3bfa35 100644 --- a/src/main.zig +++ b/src/main.zig @@ -39,10 +39,10 @@ pub const Tty = switch (builtin.os.tag) { /// The size of the terminal screen pub const Winsize = struct { - rows: usize, - cols: usize, - x_pixel: usize, - y_pixel: usize, + rows: u16, + cols: u16, + x_pixel: u16, + y_pixel: u16, }; /// Initialize a Vaxis application. diff --git a/src/widgets/CodeView.zig b/src/widgets/CodeView.zig index ce7d07b..bb6bbbb 100644 --- a/src/widgets/CodeView.zig +++ b/src/widgets/CodeView.zig @@ -4,9 +4,9 @@ const ScrollView = vaxis.widgets.ScrollView; const LineNumbers = vaxis.widgets.LineNumbers; pub const DrawOptions = struct { - highlighted_line: usize = 0, + highlighted_line: u16 = 0, draw_line_numbers: bool = true, - indentation: usize = 0, + indentation: u16 = 0, }; pub const Buffer = vaxis.widgets.TextView.Buffer; diff --git a/src/widgets/LineNumbers.zig b/src/widgets/LineNumbers.zig index d076f12..1258d38 100644 --- a/src/widgets/LineNumbers.zig +++ b/src/widgets/LineNumbers.zig @@ -12,7 +12,7 @@ pub fn extractDigit(v: usize, n: usize) usize { return (v / (std.math.powi(usize, 10, n) catch unreachable)) % 10; } -pub fn numDigits(v: usize) usize { +pub fn numDigits(v: usize) u8 { return switch (v) { 0...9 => 1, 10...99 => 2, diff --git a/src/widgets/Table.zig b/src/widgets/Table.zig index 47df018..5fdcfdb 100644 --- a/src/widgets/Table.zig +++ b/src/widgets/Table.zig @@ -9,25 +9,25 @@ const vaxis = @import("../main.zig"); /// Table Context for maintaining state and drawing Tables with `drawTable()`. pub const TableContext = struct { /// Current active Row of the Table. - row: usize = 0, + row: u16 = 0, /// Current active Column of the Table. - col: usize = 0, + col: u16 = 0, /// Starting point within the Data List. - start: usize = 0, + start: u16 = 0, /// Selected Rows. - sel_rows: ?[]usize = null, + sel_rows: ?[]u16 = null, /// Active status of the Table. active: bool = false, /// Active Content Callback Function. /// If available, this will be called to vertically expand the active row with additional info. - active_content_fn: ?*const fn (*vaxis.Window, *const anyopaque) anyerror!usize = null, + active_content_fn: ?*const fn (*vaxis.Window, *const anyopaque) anyerror!u16 = null, /// Active Content Context /// This will be provided to the `active_content` callback when called. active_ctx: *const anyopaque = &{}, /// Y Offset for rows beyond the Active Content. /// (This will be calculated automatically) - active_y_off: usize = 0, + active_y_off: u16 = 0, /// The Background Color for Selected Rows. selected_bg: vaxis.Cell.Color, @@ -47,9 +47,9 @@ pub const TableContext = struct { row_bg_2: vaxis.Cell.Color = .{ .rgb = [_]u8{ 8, 8, 8 } }, /// Y Offset for drawing to the parent Window. - y_off: usize = 0, + y_off: u16 = 0, /// X Offset for printing each Cell/Item. - cell_x_off: usize = 1, + cell_x_off: u16 = 1, /// Column Width /// Note, if this is left `null` the Column Width will be dynamically calculated during `drawTable()`. @@ -78,11 +78,11 @@ pub const WidthStyle = union(enum) { /// Dynamically calculate Column Widths such that the entire (or most) of the screen is filled horizontally. dynamic_fill, /// Dynamically calculate the Column Width for each Column based on its Header Length and the provided Padding length. - dynamic_header_len: usize, + dynamic_header_len: u16, /// Statically set all Column Widths to the same value. - static_all: usize, + static_all: u16, /// Statically set individual Column Widths to specific values. - static_individual: []const usize, + static_individual: []const u16, }; /// Column Indexes @@ -216,11 +216,11 @@ pub fn drawTable( }); // Headers - if (table_ctx.col > headers.len - 1) table_ctx.col = headers.len - 1; - var col_start: usize = 0; + if (table_ctx.col > headers.len - 1) table_ctx.col = @intCast(headers.len - 1); + var col_start: u16 = 0; for (headers[0..], 0..) |hdr_txt, idx| { const col_width = try calcColWidth( - idx, + @intCast(idx), headers, table_ctx.col_width, table_win, @@ -260,19 +260,19 @@ pub fn drawTable( // Rows if (table_ctx.active_content_fn == null) table_ctx.active_y_off = 0; - const max_items = - if (data_items.len > table_win.height -| 1) table_win.height -| 1 else data_items.len; + const max_items: u16 = + if (data_items.len > table_win.height -| 1) table_win.height -| 1 else @intCast(data_items.len); var end = table_ctx.start + max_items; if (table_ctx.row + table_ctx.active_y_off >= win.height -| 2) end -|= table_ctx.active_y_off; - if (end > data_items.len) end = data_items.len; + if (end > data_items.len) end = @intCast(data_items.len); table_ctx.start = tableStart: { if (table_ctx.row == 0) break :tableStart 0; if (table_ctx.row < table_ctx.start) break :tableStart table_ctx.start - (table_ctx.start - table_ctx.row); if (table_ctx.row >= data_items.len - 1) - table_ctx.row = data_items.len - 1; + table_ctx.row = @intCast(data_items.len - 1); if (table_ctx.row >= end) break :tableStart table_ctx.start + (table_ctx.row - end + 1); break :tableStart table_ctx.start; @@ -280,7 +280,7 @@ pub fn drawTable( end = table_ctx.start + max_items; if (table_ctx.row + table_ctx.active_y_off >= win.height -| 2) end -|= table_ctx.active_y_off; - if (end > data_items.len) end = data_items.len; + if (end > data_items.len) end = @intCast(data_items.len); table_ctx.start = @min(table_ctx.start, end); table_ctx.active_y_off = 0; for (data_items[table_ctx.start..end], 0..) |data, row| { @@ -288,7 +288,7 @@ pub fn drawTable( if (table_ctx.active and table_ctx.start + row == table_ctx.row) break :rowColors .{ table_ctx.active_fg, table_ctx.active_bg }; if (table_ctx.sel_rows) |rows| { - if (mem.indexOfScalar(usize, rows, table_ctx.start + row) != null) + if (mem.indexOfScalar(u16, rows, @intCast(table_ctx.start + row)) != null) break :rowColors .{ table_ctx.selected_fg, table_ctx.selected_bg }; } if (row % 2 == 0) break :rowColors .{ .default, table_ctx.row_bg_1 }; @@ -296,7 +296,7 @@ pub fn drawTable( }; var row_win = table_win.child(.{ .x_off = 0, - .y_off = 1 + row + table_ctx.active_y_off, + .y_off = @intCast(1 + row + table_ctx.active_y_off), .width = .{ .limit = table_win.width }, .height = .{ .limit = 1 }, //.border = .{ .where = if (table_ctx.row_borders) .top else .none }, @@ -386,21 +386,21 @@ pub fn drawTable( /// Calculate the Column Width of `col` using the provided Number of Headers (`num_hdrs`), Width Style (`style`), and Table Window (`table_win`). pub fn calcColWidth( - col: usize, + col: u16, headers: []const []const u8, style: WidthStyle, table_win: vaxis.Window, -) !usize { +) !u16 { return switch (style) { .dynamic_fill => dynFill: { - var cw = table_win.width / headers.len; + var cw: u16 = table_win.width / @as(u16, @intCast(headers.len)); if (cw % 2 != 0) cw +|= 1; while (cw * headers.len < table_win.width - 1) cw +|= 1; break :dynFill cw; }, .dynamic_header_len => dynHdrs: { if (col >= headers.len) break :dynHdrs error.NotEnoughStaticWidthsProvided; - break :dynHdrs headers[col].len + (style.dynamic_header_len * 2); + break :dynHdrs @as(u16, @intCast(headers[col].len)) + (style.dynamic_header_len * 2); }, .static_all => style.static_all, .static_individual => statInd: { diff --git a/src/widgets/TextInput.zig b/src/widgets/TextInput.zig index c94d86f..ad67c66 100644 --- a/src/widgets/TextInput.zig +++ b/src/widgets/TextInput.zig @@ -18,13 +18,13 @@ const ellipsis: Cell.Character = .{ .grapheme = "…", .width = 1 }; buf: Buffer, /// the number of graphemes to skip when drawing. Used for horizontal scrolling -draw_offset: usize = 0, +draw_offset: u16 = 0, /// the column we placed the cursor the last time we drew -prev_cursor_col: usize = 0, +prev_cursor_col: u16 = 0, /// the grapheme index of the cursor the last time we drew -prev_cursor_idx: usize = 0, +prev_cursor_idx: u16 = 0, /// approximate distance from an edge before we scroll -scroll_offset: usize = 4, +scroll_offset: u16 = 4, unicode: *const Unicode, @@ -88,8 +88,8 @@ pub fn sliceToCursor(self: *TextInput, buf: []u8) []const u8 { } /// calculates the display width from the draw_offset to the cursor -pub fn widthToCursor(self: *TextInput, win: Window) usize { - var width: usize = 0; +pub fn widthToCursor(self: *TextInput, win: Window) u16 { + var width: u16 = 0; const first_half = self.buf.firstHalf(); var first_iter = self.unicode.graphemeIterator(first_half); var i: usize = 0; @@ -120,10 +120,10 @@ pub fn cursorRight(self: *TextInput) void { self.buf.moveGapRight(grapheme.len); } -pub fn graphemesBeforeCursor(self: *const TextInput) usize { +pub fn graphemesBeforeCursor(self: *const TextInput) u16 { const first_half = self.buf.firstHalf(); var first_iter = self.unicode.graphemeIterator(first_half); - var i: usize = 0; + var i: u16 = 0; while (first_iter.next()) |_| { i += 1; } @@ -153,8 +153,8 @@ pub fn drawWithStyle(self: *TextInput, win: Window, style: Cell.Style) void { // one way to _ensure_ this is to move the gap... but that's a cost we probably don't want to pay. const first_half = self.buf.firstHalf(); var first_iter = self.unicode.graphemeIterator(first_half); - var col: usize = 0; - var i: usize = 0; + var col: u16 = 0; + var i: u16 = 0; while (first_iter.next()) |grapheme| { if (i < self.draw_offset) { i += 1; diff --git a/src/widgets/View.zig b/src/widgets/View.zig index 7ecb6fc..e068ef6 100644 --- a/src/widgets/View.zig +++ b/src/widgets/View.zig @@ -20,8 +20,8 @@ screen: Screen, /// View Initialization Config pub const Config = struct { - width: usize, - height: usize, + width: u16, + height: u16, }; /// Initialize a new View @@ -58,8 +58,8 @@ pub fn deinit(self: *View) void { } pub const DrawOptions = struct { - x_off: usize = 0, - y_off: usize = 0, + x_off: u16 = 0, + y_off: u16 = 0, }; pub fn draw(self: *View, win: Window, opts: DrawOptions) void { @@ -80,20 +80,20 @@ pub fn draw(self: *View, win: Window, opts: DrawOptions) void { /// Render Config for `toWin()` pub const RenderConfig = struct { - x: usize = 0, - y: usize = 0, + x: u16 = 0, + y: u16 = 0, width: Extent = .fit, height: Extent = .fit, pub const Extent = union(enum) { fit, - max: usize, + max: u16, }; }; /// Render a portion of this View to the provided Window (`win`). /// This will return the bounded X (col), Y (row) coordinates based on the rendering. -pub fn toWin(self: *View, win: Window, config: RenderConfig) !struct { usize, usize } { +pub fn toWin(self: *View, win: Window, config: RenderConfig) !struct { u16, u16 } { var x = @min(self.screen.width - 1, config.x); var y = @min(self.screen.height - 1, config.y); const width = width: { @@ -123,12 +123,12 @@ pub fn toWin(self: *View, win: Window, config: RenderConfig) !struct { usize, us } /// Writes a cell to the location in the View -pub fn writeCell(self: *View, col: usize, row: usize, cell: Cell) void { +pub fn writeCell(self: *View, col: u16, row: u16, cell: Cell) void { self.screen.writeCell(col, row, cell); } /// Reads a cell at the location in the View -pub fn readCell(self: *const View, col: usize, row: usize) ?Cell { +pub fn readCell(self: *const View, col: u16, row: u16) ?Cell { return self.screen.readCell(col, row); } @@ -138,7 +138,7 @@ pub fn clear(self: View) void { } /// Returns the width of the grapheme. This depends on the terminal capabilities -pub fn gwidth(self: View, str: []const u8) usize { +pub fn gwidth(self: View, str: []const u8) u16 { return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data); } diff --git a/src/widgets/alignment.zig b/src/widgets/alignment.zig index 0aa7de0..f3c90e9 100644 --- a/src/widgets/alignment.zig +++ b/src/widgets/alignment.zig @@ -1,6 +1,6 @@ const Window = @import("../Window.zig"); -pub fn center(parent: Window, cols: usize, rows: usize) Window { +pub fn center(parent: Window, cols: u16, rows: u16) Window { const y_off = (parent.height / 2) -| (rows / 2); const x_off = (parent.width / 2) -| (cols / 2); return parent.child(.{ diff --git a/src/widgets/terminal/Screen.zig b/src/widgets/terminal/Screen.zig index 6afdbb2..9bc0aeb 100644 --- a/src/widgets/terminal/Screen.zig +++ b/src/widgets/terminal/Screen.zig @@ -49,8 +49,8 @@ pub const Cursor = struct { style: vaxis.Style = .{}, uri: std.ArrayList(u8) = undefined, uri_id: std.ArrayList(u8) = undefined, - col: usize = 0, - row: usize = 0, + col: u16 = 0, + row: u16 = 0, pending_wrap: bool = false, shape: vaxis.Cell.CursorShape = .default, visible: bool = true, @@ -68,10 +68,10 @@ pub const Cursor = struct { }; pub const ScrollingRegion = struct { - top: usize, - bottom: usize, - left: usize, - right: usize, + top: u16, + bottom: u16, + left: u16, + right: u16, pub fn contains(self: ScrollingRegion, col: usize, row: usize) bool { return col >= self.left and @@ -81,8 +81,8 @@ pub const ScrollingRegion = struct { } }; -width: usize = 0, -height: usize = 0, +width: u16 = 0, +height: u16 = 0, scrolling_region: ScrollingRegion, @@ -93,7 +93,7 @@ cursor: Cursor = .{}, csi_u_flags: vaxis.Key.KittyFlags = @bitCast(@as(u5, 0)), /// sets each cell to the default cell -pub fn init(alloc: std.mem.Allocator, w: usize, h: usize) !Screen { +pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !Screen { var screen = Screen{ .buf = try alloc.alloc(Cell, w * h), .scrolling_region = .{ @@ -313,7 +313,7 @@ pub fn sgr(self: *Screen, seq: ansi.CSI) void { } } -pub fn cursorUp(self: *Screen, n: usize) void { +pub fn cursorUp(self: *Screen, n: u16) void { self.cursor.pending_wrap = false; if (self.withinScrollingRegion()) self.cursor.row = @max( @@ -324,7 +324,7 @@ pub fn cursorUp(self: *Screen, n: usize) void { self.cursor.row -|= n; } -pub fn cursorLeft(self: *Screen, n: usize) void { +pub fn cursorLeft(self: *Screen, n: u16) void { self.cursor.pending_wrap = false; if (self.withinScrollingRegion()) self.cursor.col = @max( @@ -335,7 +335,7 @@ pub fn cursorLeft(self: *Screen, n: usize) void { self.cursor.col = self.cursor.col -| n; } -pub fn cursorRight(self: *Screen, n: usize) void { +pub fn cursorRight(self: *Screen, n: u16) void { self.cursor.pending_wrap = false; if (self.withinScrollingRegion()) self.cursor.col = @min( diff --git a/src/widgets/terminal/Terminal.zig b/src/widgets/terminal/Terminal.zig index 67c40fe..07d9ba9 100644 --- a/src/widgets/terminal/Terminal.zig +++ b/src/widgets/terminal/Terminal.zig @@ -31,7 +31,7 @@ const posix = std.posix; const log = std.log.scoped(.terminal); pub const Options = struct { - scrollback_size: usize = 500, + scrollback_size: u16 = 500, winsize: Winsize = .{ .rows = 24, .cols = 80, .x_pixel = 0, .y_pixel = 0 }, initial_working_directory: ?[]const u8 = null, }; @@ -52,7 +52,7 @@ pub var global_vts: ?std.AutoHashMap(i32, *Terminal) = null; pub var global_sigchild_installed: bool = false; allocator: std.mem.Allocator, -scrollback_size: usize, +scrollback_size: u16, pty: Pty, cmd: Command, @@ -221,9 +221,9 @@ pub fn draw(self: *Terminal, win: vaxis.Window) !void { } } - var row: usize = 0; + var row: u16 = 0; while (row < self.front_screen.height) : (row += 1) { - var col: usize = 0; + var col: u16 = 0; while (col < self.front_screen.width) { const cell = self.front_screen.readCell(col, row) orelse continue; win.writeCell(col, row, cell);