diff --git a/ly-ui/src/Cell.zig b/ly-ui/src/Cell.zig index 35d0cf0..59eb4aa 100644 --- a/ly-ui/src/Cell.zig +++ b/ly-ui/src/Cell.zig @@ -14,8 +14,8 @@ pub fn init(ch: u32, fg: u32, bg: u32) Cell { }; } -pub fn put(self: Cell, x: usize, y: usize) void { +pub fn put(self: Cell, x: usize, y: usize) !void { if (self.ch == 0) return; - TerminalBuffer.setCell(x, y, self); + try TerminalBuffer.setCell(x, y, self); } diff --git a/ly-ui/src/TerminalBuffer.zig b/ly-ui/src/TerminalBuffer.zig index 1fd9999..d0b3e3d 100644 --- a/ly-ui/src/TerminalBuffer.zig +++ b/ly-ui/src/TerminalBuffer.zig @@ -103,24 +103,39 @@ pub fn init( random: Random, ) !TerminalBuffer { // Initialize termbox - _ = termbox.tb_init(); + if (termbox.tb_init() != 0) return error.TermboxInitFailed; if (options.full_color) { - _ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_TRUECOLOR); - try log_file.info(io, "tui", "termbox2 set to 24-bit color output mode", .{}); + if (termbox.tb_set_output_mode(termbox.TB_OUTPUT_TRUECOLOR) != 0) { + return error.TermboxSetOutputModeFailed; + } + try log_file.info( + io, + "tui", + "termbox2 set to 24-bit color output mode", + .{}, + ); } else { - try log_file.info(io, "tui", "termbox2 set to eight-color output mode", .{}); + try log_file.info( + io, + "tui", + "termbox2 set to eight-color output mode", + .{}, + ); } - _ = termbox.tb_clear(); - // Let's take some precautions here and clear the back buffer as well - try clearBackBuffer(); + try clearScreen(true); - const width: usize = @intCast(termbox.tb_width()); - const height: usize = @intCast(termbox.tb_height()); + const width = getWidth(); + const height = getHeight(); - try log_file.info(io, "tui", "screen resolution is {d}x{d}", .{ width, height }); + try log_file.info( + io, + "tui", + "screen resolution is {d}x{d}", + .{ width, height }, + ); return .{ .log_file = log_file, @@ -163,7 +178,7 @@ pub fn init( pub fn deinit(self: *TerminalBuffer) void { self.keybinds.deinit(); - TerminalBuffer.shutdown(); + TerminalBuffer.shutdown() catch {}; } pub fn runEventLoop( @@ -238,7 +253,7 @@ pub fn runEventLoop( } } - TerminalBuffer.presentBuffer(); + try TerminalBuffer.presentBuffer(); } if (inactivity_event_fn) |inactivity_fn| { @@ -338,31 +353,35 @@ pub fn getHeight() usize { return @intCast(termbox.tb_height()); } -pub fn setCursor(x: usize, y: usize) void { - _ = termbox.tb_set_cursor(@intCast(x), @intCast(y)); +pub fn setCursor(x: usize, y: usize) !void { + if (termbox.tb_set_cursor(@intCast(x), @intCast(y)) != 0) { + return error.TermboxSetCursorFailed; + } } pub fn clearScreen(clear_back_buffer: bool) !void { - _ = termbox.tb_clear(); + if (termbox.tb_clear() != 0) return error.TermboxClearFailed; if (clear_back_buffer) try clearBackBuffer(); } -pub fn shutdown() void { - _ = termbox.tb_shutdown(); +pub fn shutdown() !void { + if (termbox.tb_shutdown() != 0) return error.TermboxShutdownFailed; } -pub fn presentBuffer() void { - _ = termbox.tb_present(); +pub fn presentBuffer() !void { + if (termbox.tb_present() != 0) return error.TermboxPresentFailed; } pub fn getCell(x: usize, y: usize) ?Cell { var maybe_cell: ?*termbox.tb_cell = undefined; - _ = termbox.tb_get_cell( + if (termbox.tb_get_cell( @intCast(x), @intCast(y), 1, &maybe_cell, - ); + ) != 0) { + return null; + } if (maybe_cell) |cell| { return Cell.init(cell.ch, cell.fg, cell.bg); @@ -371,29 +390,31 @@ pub fn getCell(x: usize, y: usize) ?Cell { return null; } -pub fn setCell(x: usize, y: usize, cell: Cell) void { - _ = termbox.tb_set_cell( +pub fn setCell(x: usize, y: usize, cell: Cell) !void { + if (termbox.tb_set_cell( @intCast(x), @intCast(y), cell.ch, cell.fg, cell.bg, - ); + ) != 0) { + return error.TermboxSetCellFailed; + } } -pub fn setCellBoundsChecked(self: *TerminalBuffer, x: isize, y: isize, cell: Cell) void { +pub fn setCellBoundsChecked(self: *TerminalBuffer, x: isize, y: isize, cell: Cell) !void { if (0 <= x and x < self.width and 0 <= y and y < self.height) { - cell.put(@intCast(x), @intCast(y)); + try cell.put(@intCast(x), @intCast(y)); } } pub fn reclaim(self: TerminalBuffer) !void { if (self.termios) |termios| { // Take back control of the TTY - _ = termbox.tb_init(); + if (termbox.tb_init() != 0) return error.TermboxReinitFailed; - if (self.full_color) { - _ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_TRUECOLOR); + if (self.full_color and termbox.tb_set_output_mode(termbox.TB_OUTPUT_TRUECOLOR) != 0) { + return error.TermboxSetOutputModeFailed; } try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, termios); @@ -464,14 +485,14 @@ pub fn drawText( y: usize, fg: u32, bg: u32, -) void { - const yc: c_int = @intCast(y); +) !void { const utf8view = std.unicode.Utf8View.init(text) catch return; var utf8 = utf8view.iterator(); - var i: c_int = @intCast(x); - while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) { - _ = termbox.tb_set_cell(i, yc, codepoint, fg, bg); + var i = x; + while (utf8.nextCodepoint()) |codepoint| : (i += @intCast(termbox.tb_wcwidth(codepoint))) { + const cell = Cell.init(codepoint, fg, bg); + try cell.put(i, y); } } @@ -482,15 +503,16 @@ pub fn drawConfinedText( max_length: usize, fg: u32, bg: u32, -) void { - const yc: c_int = @intCast(y); +) !void { const utf8view = std.unicode.Utf8View.init(text) catch return; var utf8 = utf8view.iterator(); - var i: c_int = @intCast(x); - while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) { - if (i - @as(c_int, @intCast(x)) >= max_length) break; - _ = termbox.tb_set_cell(i, yc, codepoint, fg, bg); + var i = x; + while (utf8.nextCodepoint()) |codepoint| : (i += @intCast(termbox.tb_wcwidth(codepoint))) { + if (i - x >= max_length) break; + + const cell = Cell.init(codepoint, fg, bg); + try cell.put(i, y); } } @@ -501,9 +523,9 @@ pub fn drawCharMultiple( length: usize, fg: u32, bg: u32, -) void { +) !void { const cell = Cell.init(char, fg, bg); - for (0..length) |xx| cell.put(x + xx, y); + for (0..length) |xx| try cell.put(x + xx, y); } // Every codepoint is assumed to have a width of 1. @@ -521,6 +543,8 @@ pub fn strWidth(str: []const u8) usize { } fn clearBackBuffer() !void { + if (termbox.global.initialized == 0) return; + // Clear the TTY because termbox2 doesn't seem to do it properly const capability = termbox.global.caps[termbox.TB_CAP_CLEAR_SCREEN]; const capability_slice = std.mem.span(capability); diff --git a/ly-ui/src/components/BigLabel.zig b/ly-ui/src/components/BigLabel.zig index bd9af6e..cb2f6b5 100644 --- a/ly-ui/src/components/BigLabel.zig +++ b/ly-ui/src/components/BigLabel.zig @@ -207,7 +207,7 @@ fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [CHAR for (0..CHAR_HEIGHT) |yy| { for (0..CHAR_WIDTH) |xx| { const cell = cells[yy * CHAR_WIDTH + xx]; - cell.put(x + xx, y + yy); + cell.put(x + xx, y + yy) catch {}; } } } diff --git a/ly-ui/src/components/Box.zig b/ly-ui/src/components/Box.zig index 7c753ae..af3a687 100644 --- a/ly-ui/src/components/Box.zig +++ b/ly-ui/src/components/Box.zig @@ -129,29 +129,29 @@ fn draw(self: *Box) void { self.bg, ); - left_up.put(self.left_pos.x - 1, self.left_pos.y - 1); - right_up.put(self.right_pos.x, self.left_pos.y - 1); - left_down.put(self.left_pos.x - 1, self.right_pos.y); - right_down.put(self.right_pos.x, self.right_pos.y); + left_up.put(self.left_pos.x - 1, self.left_pos.y - 1) catch {}; + right_up.put(self.right_pos.x, self.left_pos.y - 1) catch {}; + left_down.put(self.left_pos.x - 1, self.right_pos.y) catch {}; + right_down.put(self.right_pos.x, self.right_pos.y) catch {}; for (0..self.width) |i| { - top.put(self.left_pos.x + i, self.left_pos.y - 1); - bottom.put(self.left_pos.x + i, self.right_pos.y); + top.put(self.left_pos.x + i, self.left_pos.y - 1) catch {}; + bottom.put(self.left_pos.x + i, self.right_pos.y) catch {}; } top.ch = self.buffer.box_chars.left; bottom.ch = self.buffer.box_chars.right; for (0..self.height) |i| { - top.put(self.left_pos.x - 1, self.left_pos.y + i); - bottom.put(self.right_pos.x, self.left_pos.y + i); + top.put(self.left_pos.x - 1, self.left_pos.y + i) catch {}; + bottom.put(self.right_pos.x, self.left_pos.y + i) catch {}; } } if (self.blank_box) { for (0..self.height) |y| { for (0..self.width) |x| { - self.buffer.blank_cell.put(self.left_pos.x + x, self.left_pos.y + y); + self.buffer.blank_cell.put(self.left_pos.x + x, self.left_pos.y + y) catch {}; } } } @@ -164,7 +164,7 @@ fn draw(self: *Box) void { self.width, self.title_fg, self.bg, - ); + ) catch {}; } if (self.bottom_title) |title| { @@ -175,7 +175,7 @@ fn draw(self: *Box) void { self.width, self.title_fg, self.bg, - ); + ) catch {}; } } diff --git a/ly-ui/src/components/Label.zig b/ly-ui/src/components/Label.zig index 9874fcb..d54cb9c 100644 --- a/ly-ui/src/components/Label.zig +++ b/ly-ui/src/components/Label.zig @@ -117,7 +117,7 @@ fn draw(self: *Label) void { width, self.fg, self.bg, - ); + ) catch {}; return; } @@ -127,7 +127,7 @@ fn draw(self: *Label) void { self.component_pos.y, self.fg, self.bg, - ); + ) catch {}; } fn update(self: *Label, ctx: *anyopaque) !void { diff --git a/ly-ui/src/components/Text.zig b/ly-ui/src/components/Text.zig index 4fc35bf..0ca5312 100644 --- a/ly-ui/src/components/Text.zig +++ b/ly-ui/src/components/Text.zig @@ -131,14 +131,14 @@ pub fn handle(self: *Text, maybe_key: ?keyboard.Key) !void { } if (self.masked and self.maybe_mask == null) { - TerminalBuffer.setCursor( + try TerminalBuffer.setCursor( self.component_pos.x, self.component_pos.y, ); return; } - TerminalBuffer.setCursor( + try TerminalBuffer.setCursor( self.component_pos.x + (self.cursor - self.visible_start), self.component_pos.y, ); @@ -159,7 +159,7 @@ fn draw(self: *Text) void { length, self.fg, self.bg, - ); + ) catch {}; } return; } @@ -182,7 +182,7 @@ fn draw(self: *Text) void { self.component_pos.y, self.fg, self.bg, - ); + ) catch {}; } fn goLeft(ptr: *anyopaque) !bool { diff --git a/ly-ui/src/components/generic.zig b/ly-ui/src/components/generic.zig index 0a76c4f..572fe3f 100644 --- a/ly-ui/src/components/generic.zig +++ b/ly-ui/src/components/generic.zig @@ -105,8 +105,8 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ self.current = self.list.items.len - 1; } - pub fn handle(self: *Self, _: ?keyboard.Key) void { - TerminalBuffer.setCursor( + pub fn handle(self: *Self, _: ?keyboard.Key) !void { + try TerminalBuffer.setCursor( self.component_pos.x + self.cursor + 2, self.component_pos.y, ); @@ -119,11 +119,11 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ var left_arrow = Cell.init('<', self.fg, self.bg); var right_arrow = Cell.init('>', self.fg, self.bg); - left_arrow.put(self.component_pos.x, self.component_pos.y); + left_arrow.put(self.component_pos.x, self.component_pos.y) catch {}; right_arrow.put( self.component_pos.x + self.width - 1, self.component_pos.y, - ); + ) catch {}; const current_item = self.list.items[self.current]; const x = self.component_pos.x + 2; diff --git a/src/animations/Cascade.zig b/src/animations/Cascade.zig index 587cd37..c9b7769 100644 --- a/src/animations/Cascade.zig +++ b/src/animations/Cascade.zig @@ -71,14 +71,14 @@ fn draw(self: *Cascade) void { if ((self.buffer.random.int(u16) % 10) > 7) continue; - cell.?.put(x, y); + cell.?.put(x, y) catch {}; var space = Cell.init( ' ', cell_under.?.fg, cell_under.?.bg, ); - space.put(x, y - 1); + space.put(x, y - 1) catch {}; } } @@ -87,6 +87,6 @@ fn draw(self: *Cascade) void { self.current_auth_fails.* = 0; } - TerminalBuffer.presentBuffer(); + TerminalBuffer.presentBuffer() catch {}; } } diff --git a/src/animations/ColorMix.zig b/src/animations/ColorMix.zig index 49c6238..e9063a3 100644 --- a/src/animations/ColorMix.zig +++ b/src/animations/ColorMix.zig @@ -114,7 +114,7 @@ fn draw(self: *ColorMix) void { } const cell = self.palette[@as(usize, @trunc(math.floor(length(uv) * 5.0))) % palette_len]; - cell.put(x, y); + cell.put(x, y) catch {}; } } } diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 9b0abae..504831a 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -129,13 +129,13 @@ fn draw(self: *Doom) void { // Send known fire levels to terminal buffer const from_cell = self.fire[level_buf_from]; const to_cell = self.fire[level_buf_to]; - from_cell.put(x, y); - to_cell.put(to_x, to_y); + from_cell.put(x, y) catch {}; + to_cell.put(to_x, to_y) catch {}; } // Draw bottom line (fire source) const src_cell = self.fire[STEPS]; - src_cell.put(x, self.terminal_buffer.height - 1); + src_cell.put(x, self.terminal_buffer.height - 1) catch {}; } } diff --git a/src/animations/DurFile.zig b/src/animations/DurFile.zig index ca3922c..95677f8 100644 --- a/src/animations/DurFile.zig +++ b/src/animations/DurFile.zig @@ -535,7 +535,7 @@ fn draw(self: *DurFile) void { const cell = Cell{ .ch = @intCast(codepoint), .fg = fg_color, .bg = bg_color }; - self.terminal_buffer.setCellBoundsChecked(cell_x, cell_y, cell); + self.terminal_buffer.setCellBoundsChecked(cell_x, cell_y, cell) catch {}; } } diff --git a/src/animations/GameOfLife.zig b/src/animations/GameOfLife.zig index c100c52..6e9a16c 100644 --- a/src/animations/GameOfLife.zig +++ b/src/animations/GameOfLife.zig @@ -146,7 +146,7 @@ fn draw(self: *GameOfLife) void { const row_offset = y * self.width; for (0..self.width) |x| { const cell = if (self.current_grid[row_offset + x]) alive_cell else self.dead_cell; - cell.put(x, y); + cell.put(x, y) catch {}; } } } diff --git a/src/animations/Matrix.zig b/src/animations/Matrix.zig index e7af489..3d43118 100644 --- a/src/animations/Matrix.zig +++ b/src/animations/Matrix.zig @@ -200,9 +200,9 @@ fn draw(self: *Matrix) void { .bg = self.terminal_buffer.bg, }; - cell.put(x, y - 1); + cell.put(x, y - 1) catch {}; // Fill background in between columns - self.default_cell.put(x + 1, y - 1); + self.default_cell.put(x + 1, y - 1) catch {}; } } } diff --git a/src/components/InfoLine.zig b/src/components/InfoLine.zig index 97a8a73..45b5da3 100644 --- a/src/components/InfoLine.zig +++ b/src/components/InfoLine.zig @@ -84,7 +84,7 @@ pub fn clearRendered(self: InfoLine, allocator: Allocator) !void { @memset(spaces, ' '); - TerminalBuffer.drawText( + try TerminalBuffer.drawText( spaces, self.label.component_pos.x + 2, self.label.component_pos.y, @@ -98,7 +98,7 @@ fn draw(self: *InfoLine) void { } fn handle(self: *InfoLine, maybe_key: ?keyboard.Key) !void { - self.label.handle(maybe_key); + try self.label.handle(maybe_key); } fn drawItem(label: *MessageLabel, message: Message, x: usize, y: usize, width: usize) void { @@ -114,5 +114,5 @@ fn drawItem(label: *MessageLabel, message: Message, x: usize, y: usize, width: u width, message.fg, message.bg, - ); + ) catch {}; } diff --git a/src/components/Session.zig b/src/components/Session.zig index 1e975c6..6cb252a 100644 --- a/src/components/Session.zig +++ b/src/components/Session.zig @@ -87,7 +87,7 @@ fn draw(self: *Session) void { } fn handle(self: *Session, maybe_key: ?keyboard.Key) !void { - self.label.handle(maybe_key); + try self.label.handle(maybe_key); } fn addedSession(env: Env, user_list: *UserList) void { @@ -119,5 +119,5 @@ fn drawItem(label: *EnvironmentLabel, env: Env, x: usize, y: usize, width: usize width, label.fg, label.bg, - ); + ) catch {}; } diff --git a/src/components/UserList.zig b/src/components/UserList.zig index c407173..9f01bc5 100644 --- a/src/components/UserList.zig +++ b/src/components/UserList.zig @@ -118,7 +118,7 @@ fn draw(self: *UserList) void { } fn handle(self: *UserList, maybe_key: ?keyboard.Key) !void { - self.label.handle(maybe_key); + try self.label.handle(maybe_key); } fn usernameChanged(user: User, maybe_session: ?*Session) void { @@ -143,5 +143,5 @@ fn drawItem(label: *UserLabel, user: User, x: usize, y: usize, width: usize) voi width, label.fg, label.bg, - ); + ) catch {}; } diff --git a/src/main.zig b/src/main.zig index a2a8512..0f6f1e0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -56,12 +56,12 @@ fn signalHandler(sig: std.posix.SIG) callconv(.c) void { _ = std.c.waitpid(session_pid, &status, 0); } - TerminalBuffer.shutdown(); + TerminalBuffer.shutdown() catch {}; std.c.exit(@intCast(@intFromEnum(sig))); } fn ttyControlTransferSignalHandler(_: std.posix.SIG) callconv(.c) void { - TerminalBuffer.shutdown(); + TerminalBuffer.shutdown() catch {}; } const CustomBindLabel = struct { @@ -1484,7 +1484,7 @@ fn authenticate(ptr: *anyopaque) !bool { ); }; state.info_line.label.draw(); - TerminalBuffer.presentBuffer(); + try TerminalBuffer.presentBuffer(); return false; } @@ -1507,7 +1507,7 @@ fn authenticate(ptr: *anyopaque) !bool { ); }; state.info_line.label.draw(); - TerminalBuffer.presentBuffer(); + try TerminalBuffer.presentBuffer(); if (state.config.save) save_last_settings: { // It isn't worth cluttering the code with precise error @@ -1660,8 +1660,8 @@ fn authenticate(ptr: *anyopaque) !bool { } // Restore the cursor - TerminalBuffer.setCursor(0, 0); - TerminalBuffer.presentBuffer(); + try TerminalBuffer.setCursor(0, 0); + try TerminalBuffer.presentBuffer(); return false; }