diff --git a/src/animations/ColorMix.zig b/src/animations/ColorMix.zig index 95b454c..3db2e46 100644 --- a/src/animations/ColorMix.zig +++ b/src/animations/ColorMix.zig @@ -1,7 +1,7 @@ const std = @import("std"); const Animation = @import("../tui/Animation.zig"); +const Cell = @import("../tui/Cell.zig"); const TerminalBuffer = @import("../tui/TerminalBuffer.zig"); -const utils = @import("../tui/utils.zig"); const ColorMix = @This(); @@ -19,7 +19,7 @@ terminal_buffer: *TerminalBuffer, frames: u64, pattern_cos_mod: f32, pattern_sin_mod: f32, -palette: [palette_len]utils.Cell, +palette: [palette_len]Cell, pub fn init(terminal_buffer: *TerminalBuffer, col1: u32, col2: u32, col3: u32) ColorMix { return .{ @@ -27,19 +27,19 @@ pub fn init(terminal_buffer: *TerminalBuffer, col1: u32, col2: u32, col3: u32) C .frames = 0, .pattern_cos_mod = terminal_buffer.random.float(f32) * math.pi * 2.0, .pattern_sin_mod = terminal_buffer.random.float(f32) * math.pi * 2.0, - .palette = [palette_len]utils.Cell{ - utils.initCell(0x2588, col1, col2), - utils.initCell(0x2593, col1, col2), - utils.initCell(0x2592, col1, col2), - utils.initCell(0x2591, col1, col2), - utils.initCell(0x2588, col2, col3), - utils.initCell(0x2593, col2, col3), - utils.initCell(0x2592, col2, col3), - utils.initCell(0x2591, col2, col3), - utils.initCell(0x2588, col3, col1), - utils.initCell(0x2593, col3, col1), - utils.initCell(0x2592, col3, col1), - utils.initCell(0x2591, col3, col1), + .palette = [palette_len]Cell{ + Cell.init(0x2588, col1, col2), + Cell.init(0x2593, col1, col2), + Cell.init(0x2592, col1, col2), + Cell.init(0x2591, col1, col2), + Cell.init(0x2588, col2, col3), + Cell.init(0x2593, col2, col3), + Cell.init(0x2592, col2, col3), + Cell.init(0x2591, col2, col3), + Cell.init(0x2588, col3, col1), + Cell.init(0x2593, col3, col1), + Cell.init(0x2592, col3, col1), + Cell.init(0x2591, col3, col1), }, }; } @@ -80,7 +80,7 @@ fn draw(self: *ColorMix) void { } const cell = self.palette[@as(usize, @intFromFloat(math.floor(length(uv) * 5.0))) % palette_len]; - utils.putCell(x, y, cell); + cell.put(x, y); } } } diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index bbc0a86..9e2b24a 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -1,8 +1,8 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const Animation = @import("../tui/Animation.zig"); +const Cell = @import("../tui/Cell.zig"); const TerminalBuffer = @import("../tui/TerminalBuffer.zig"); -const utils = @import("../tui/utils.zig"); const Doom = @This(); @@ -11,7 +11,7 @@ pub const STEPS = 12; allocator: Allocator, terminal_buffer: *TerminalBuffer, buffer: []u8, -fire: [STEPS + 1]utils.Cell, +fire: [STEPS + 1]Cell, pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u32, middle_color: u32, bottom_color: u32) !Doom { const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height); @@ -21,20 +21,20 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u .allocator = allocator, .terminal_buffer = terminal_buffer, .buffer = buffer, - .fire = [_]utils.Cell{ - utils.initCell(' ', 0x00000000, 0), - utils.initCell(0x2591, top_color, 0), - utils.initCell(0x2592, top_color, 0), - utils.initCell(0x2593, top_color, 0), - utils.initCell(0x2588, top_color, 0), - utils.initCell(0x2591, middle_color, 2), - utils.initCell(0x2592, middle_color, 2), - utils.initCell(0x2593, middle_color, 2), - utils.initCell(0x2588, middle_color, 2), - utils.initCell(0x2591, bottom_color, 4), - utils.initCell(0x2592, bottom_color, 4), - utils.initCell(0x2593, bottom_color, 4), - utils.initCell(0x2588, bottom_color, 4), + .fire = [_]Cell{ + Cell.init(' ', 0x00000000, 0), + Cell.init(0x2591, top_color, 0), + Cell.init(0x2592, top_color, 0), + Cell.init(0x2593, top_color, 0), + Cell.init(0x2588, top_color, 0), + Cell.init(0x2591, middle_color, 2), + Cell.init(0x2592, middle_color, 2), + Cell.init(0x2593, middle_color, 2), + Cell.init(0x2588, middle_color, 2), + Cell.init(0x2591, bottom_color, 4), + Cell.init(0x2592, bottom_color, 4), + Cell.init(0x2593, bottom_color, 4), + Cell.init(0x2588, bottom_color, 4), }, }; } @@ -73,11 +73,13 @@ fn draw(self: *Doom) void { const dest_y = dest / self.terminal_buffer.width; const dest_x = dest % self.terminal_buffer.width; - utils.putCell(dest_x, dest_y, self.fire[buffer_dest]); + const dest_cell = self.fire[buffer_dest]; + dest_cell.put(dest_x, dest_y); const source_y = source / self.terminal_buffer.width; const source_x = source % self.terminal_buffer.width; - utils.putCell(source_x, source_y, self.fire[buffer_source]); + const source_cell = self.fire[buffer_source]; + source_cell.put(source_x, source_y); } } } diff --git a/src/animations/Matrix.zig b/src/animations/Matrix.zig index c60aa17..9ebc0fb 100644 --- a/src/animations/Matrix.zig +++ b/src/animations/Matrix.zig @@ -1,11 +1,11 @@ const std = @import("std"); +const interop = @import("../interop.zig"); +const Animation = @import("../tui/Animation.zig"); +const Cell = @import("../tui/Cell.zig"); +const TerminalBuffer = @import("../tui/TerminalBuffer.zig"); + const Allocator = std.mem.Allocator; const Random = std.Random; -const Animation = @import("../tui/Animation.zig"); -const TerminalBuffer = @import("../tui/TerminalBuffer.zig"); -const utils = @import("../tui/utils.zig"); - -const interop = @import("../interop.zig"); const termbox = interop.termbox; pub const FRAME_DELAY: usize = 8; @@ -13,6 +13,8 @@ pub const FRAME_DELAY: usize = 8; // Characters change mid-scroll pub const MID_SCROLL_CHANGE = true; +const DOT_HEAD_COLOR: u32 = @intCast(0x00FFFFFF | termbox.TB_BOLD); // White and bold + const Matrix = @This(); pub const Dot = struct { @@ -35,6 +37,7 @@ count: usize, fg_ini: u32, min_codepoint: u16, max_codepoint: u16, +default_cell: Cell, pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg_ini: u32, min_codepoint: u16, max_codepoint: u16) !Matrix { const dots = try allocator.alloc(Dot, terminal_buffer.width * (terminal_buffer.height + 1)); @@ -52,6 +55,7 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg_ini: u32, .fg_ini = fg_ini, .min_codepoint = min_codepoint, .max_codepoint = max_codepoint - min_codepoint, + .default_cell = .{ .ch = ' ', .fg = fg_ini, .bg = termbox.TB_DEFAULT }, }; } @@ -153,16 +157,13 @@ fn draw(self: *Matrix) void { var y: usize = 1; while (y <= self.terminal_buffer.height) : (y += 1) { const dot = self.dots[buf_width * y + x]; + const cell = if (dot.value == null or dot.value == ' ') self.default_cell else Cell{ + .ch = @intCast(dot.value.?), + .fg = if (dot.is_head) DOT_HEAD_COLOR else self.fg_ini, + .bg = termbox.TB_DEFAULT, + }; - var fg = self.fg_ini; - - if (dot.value == null or dot.value == ' ') { - utils.putCell(x, y - 1, .{ .ch = ' ', .fg = fg, .bg = termbox.TB_DEFAULT }); - continue; - } - - if (dot.is_head) fg = @intCast(0x00FFFFFF | termbox.TB_BOLD); // White and bold - utils.putCell(x, y - 1, .{ .ch = @intCast(dot.value.?), .fg = fg, .bg = termbox.TB_DEFAULT }); + cell.put(x, y - 1); } } } diff --git a/src/bigclock.zig b/src/bigclock.zig index fb4baa7..d63f0fd 100644 --- a/src/bigclock.zig +++ b/src/bigclock.zig @@ -1,36 +1,35 @@ const std = @import("std"); const interop = @import("interop.zig"); -const utils = @import("tui/utils.zig"); const enums = @import("enums.zig"); const Lang = @import("bigclock/Lang.zig"); const en = @import("bigclock/en.zig"); const fa = @import("bigclock/fa.zig"); +const Cell = @import("tui/Cell.zig"); -const termbox = interop.termbox; const Bigclock = enums.Bigclock; pub const WIDTH = Lang.WIDTH; pub const HEIGHT = Lang.HEIGHT; pub const SIZE = Lang.SIZE; -pub fn clockCell(animate: bool, char: u8, fg: u32, bg: u32, bigclock: Bigclock) [SIZE]utils.Cell { - var cells: [SIZE]utils.Cell = undefined; +pub fn clockCell(animate: bool, char: u8, fg: u32, bg: u32, bigclock: Bigclock) [SIZE]Cell { + var cells: [SIZE]Cell = undefined; var tv: interop.system_time.timeval = undefined; _ = interop.system_time.gettimeofday(&tv, null); const clock_chars = toBigNumber(if (animate and char == ':' and @divTrunc(tv.tv_usec, 500000) != 0) ' ' else char, bigclock); - for (0..cells.len) |i| cells[i] = utils.initCell(clock_chars[i], fg, bg); + for (0..cells.len) |i| cells[i] = Cell.init(clock_chars[i], fg, bg); return cells; } -pub fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [SIZE]utils.Cell) void { +pub fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [SIZE]Cell) void { if (x + WIDTH >= tb_width or y + HEIGHT >= tb_height) return; for (0..HEIGHT) |yy| { for (0..WIDTH) |xx| { const cell = cells[yy * WIDTH + xx]; - if (cell.ch != 0) utils.putCell(x + xx, y + yy, cell); + cell.put(x + xx, y + yy); } } } diff --git a/src/main.zig b/src/main.zig index 54e62aa..d187010 100644 --- a/src/main.zig +++ b/src/main.zig @@ -21,7 +21,6 @@ const Lang = @import("config/Lang.zig"); const Save = @import("config/Save.zig"); const migrator = @import("config/migrator.zig"); const SharedError = @import("SharedError.zig"); -const utils = @import("tui/utils.zig"); const Ini = ini.Ini; const DisplayServer = enums.DisplayServer; @@ -358,15 +357,15 @@ pub fn main() !void { const animate = config.animation != .none; const shutdown_key = try std.fmt.parseInt(u8, config.shutdown_key[1..], 10); - const shutdown_len = try utils.strWidth(lang.shutdown); + const shutdown_len = try TerminalBuffer.strWidth(lang.shutdown); const restart_key = try std.fmt.parseInt(u8, config.restart_key[1..], 10); - const restart_len = try utils.strWidth(lang.restart); + const restart_len = try TerminalBuffer.strWidth(lang.restart); const sleep_key = try std.fmt.parseInt(u8, config.sleep_key[1..], 10); - const sleep_len = try utils.strWidth(lang.sleep); + const sleep_len = try TerminalBuffer.strWidth(lang.sleep); const brightness_down_key = if (config.brightness_down_key) |key| try std.fmt.parseInt(u8, key[1..], 10) else null; - const brightness_down_len = try utils.strWidth(lang.brightness_down); + const brightness_down_len = try TerminalBuffer.strWidth(lang.brightness_down); const brightness_up_key = if (config.brightness_down_key) |key| try std.fmt.parseInt(u8, key[1..], 10) else null; - const brightness_up_len = try utils.strWidth(lang.brightness_up); + const brightness_up_len = try TerminalBuffer.strWidth(lang.brightness_up); var event: termbox.tb_event = undefined; var run = true; diff --git a/src/tui/Cell.zig b/src/tui/Cell.zig new file mode 100644 index 0000000..66d06f8 --- /dev/null +++ b/src/tui/Cell.zig @@ -0,0 +1,23 @@ +const interop = @import("../interop.zig"); + +const termbox = interop.termbox; + +const Cell = @This(); + +ch: u32, +fg: u32, +bg: u32, + +pub fn init(ch: u32, fg: u32, bg: u32) Cell { + return .{ + .ch = ch, + .fg = fg, + .bg = bg, + }; +} + +pub fn put(self: Cell, x: usize, y: usize) void { + if (self.ch == 0) return; + + _ = termbox.tb_set_cell(@intCast(x), @intCast(y), self.ch, self.fg, self.bg); +} diff --git a/src/tui/TerminalBuffer.zig b/src/tui/TerminalBuffer.zig index ba75516..4fe2dae 100644 --- a/src/tui/TerminalBuffer.zig +++ b/src/tui/TerminalBuffer.zig @@ -1,7 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); const interop = @import("../interop.zig"); -const utils = @import("utils.zig"); +const Cell = @import("Cell.zig"); const Random = std.Random; @@ -41,6 +41,7 @@ box_width: usize, box_height: usize, margin_box_v: u8, margin_box_h: u8, +blank_cell: Cell, pub fn init(options: InitOptions, labels_max_length: usize, random: Random) TerminalBuffer { return .{ @@ -76,6 +77,7 @@ pub fn init(options: InitOptions, labels_max_length: usize, random: Random) Term .box_height = 7 + (2 * options.margin_box_v), .margin_box_v = options.margin_box_v, .margin_box_h = options.margin_box_h, + .blank_cell = Cell.init(' ', options.fg, options.bg), }; } @@ -125,29 +127,27 @@ pub fn drawBoxCenter(self: *TerminalBuffer, show_borders: bool, blank_box: bool) _ = termbox.tb_set_cell(@intCast(x1 - 1), @intCast(y2), self.box_chars.left_down, self.border_fg, self.bg); _ = termbox.tb_set_cell(@intCast(x2), @intCast(y2), self.box_chars.right_down, self.border_fg, self.bg); - var c1 = utils.initCell(self.box_chars.top, self.border_fg, self.bg); - var c2 = utils.initCell(self.box_chars.bottom, self.border_fg, self.bg); + var c1 = Cell.init(self.box_chars.top, self.border_fg, self.bg); + var c2 = Cell.init(self.box_chars.bottom, self.border_fg, self.bg); for (0..self.box_width) |i| { - utils.putCell(x1 + i, y1 - 1, c1); - utils.putCell(x1 + i, y2, c2); + c1.put(x1 + i, y1 - 1); + c2.put(x1 + i, y2); } c1.ch = self.box_chars.left; c2.ch = self.box_chars.right; for (0..self.box_height) |i| { - utils.putCell(x1 - 1, y1 + i, c1); - utils.putCell(x2, y1 + i, c2); + c1.put(x1 - 1, y1 + i); + c2.put(x2, y1 + i); } } if (blank_box) { - const blank = utils.initCell(' ', self.fg, self.bg); - for (0..self.box_height) |y| { for (0..self.box_width) |x| { - utils.putCell(x1 + x, y1 + y, blank); + self.blank_cell.put(x1 + x, y1 + y); } } } @@ -203,6 +203,16 @@ pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: usize, y: us } pub fn drawCharMultiple(self: TerminalBuffer, char: u32, x: usize, y: usize, length: usize) void { - const cell = utils.initCell(char, self.fg, self.bg); - for (0..length) |xx| utils.putCell(x + xx, y, cell); + const cell = Cell.init(char, self.fg, self.bg); + for (0..length) |xx| cell.put(x + xx, y); +} + +// Every codepoint is assumed to have a width of 1. +// Since Ly is normally running in a TTY, this should be fine. +pub fn strWidth(str: []const u8) !u8 { + const utf8view = try std.unicode.Utf8View.init(str); + var utf8 = utf8view.iterator(); + var i: u8 = 0; + while (utf8.nextCodepoint()) |_| i += 1; + return i; } diff --git a/src/tui/components/InfoLine.zig b/src/tui/components/InfoLine.zig index 05d421c..42436d9 100644 --- a/src/tui/components/InfoLine.zig +++ b/src/tui/components/InfoLine.zig @@ -1,7 +1,6 @@ const std = @import("std"); const TerminalBuffer = @import("../TerminalBuffer.zig"); const generic = @import("generic.zig"); -const utils = @import("../utils.zig"); const Allocator = std.mem.Allocator; @@ -32,7 +31,7 @@ pub fn addMessage(self: *InfoLine, text: []const u8, bg: u32, fg: u32) !void { if (text.len == 0) return; try self.label.addItem(.{ - .width = try utils.strWidth(text), + .width = try TerminalBuffer.strWidth(text), .text = text, .bg = bg, .fg = fg, diff --git a/src/tui/utils.zig b/src/tui/utils.zig deleted file mode 100644 index ace54a6..0000000 --- a/src/tui/utils.zig +++ /dev/null @@ -1,32 +0,0 @@ -const std = @import("std"); -const interop = @import("../interop.zig"); - -const termbox = interop.termbox; - -pub const Cell = struct { - ch: u32, - fg: u32, - bg: u32, -}; - -pub fn initCell(ch: u32, fg: u32, bg: u32) Cell { - return .{ - .ch = ch, - .fg = fg, - .bg = bg, - }; -} - -pub fn putCell(x: usize, y: usize, cell: Cell) void { - _ = termbox.tb_set_cell(@intCast(x), @intCast(y), cell.ch, cell.fg, cell.bg); -} - -// Every codepoint is assumed to have a width of 1. -// Since ly should be running in a tty, this should be fine. -pub fn strWidth(str: []const u8) !u8 { - const utf8view = try std.unicode.Utf8View.init(str); - var utf8 = utf8view.iterator(); - var i: u8 = 0; - while (utf8.nextCodepoint()) |_| i += 1; - return i; -}