From 3bd10e106d61ddb3c787d0b9a9669a65999e9b74 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 5 Jun 2024 22:02:26 +0200 Subject: [PATCH] refactor: remove notcurses renderer --- src/renderer/notcurses/Cell.zig | 38 -- src/renderer/notcurses/Plane.zig | 277 --------------- src/renderer/notcurses/channels.zig | 40 --- src/renderer/notcurses/input.zig | 15 - src/renderer/notcurses/renderer.zig | 525 ---------------------------- src/renderer/notcurses/style.zig | 14 - 6 files changed, 909 deletions(-) delete mode 100644 src/renderer/notcurses/Cell.zig delete mode 100644 src/renderer/notcurses/Plane.zig delete mode 100644 src/renderer/notcurses/channels.zig delete mode 100644 src/renderer/notcurses/input.zig delete mode 100644 src/renderer/notcurses/renderer.zig delete mode 100644 src/renderer/notcurses/style.zig diff --git a/src/renderer/notcurses/Cell.zig b/src/renderer/notcurses/Cell.zig deleted file mode 100644 index f6f913c..0000000 --- a/src/renderer/notcurses/Cell.zig +++ /dev/null @@ -1,38 +0,0 @@ -const nc = @import("notcurses"); -const Style = @import("theme").Style; -const channels = @import("channels.zig"); - -pub const Cell = struct { - cell: nc.Cell, - - pub inline fn set_style(cell: *Cell, style_: Style) void { - channels.from_style(&cell.cell.channels, style_); - if (style_.fs) |fs| switch (fs) { - .normal => nc.cell_set_styles(&cell.cell, nc.style.none), - .bold => nc.cell_set_styles(&cell.cell, nc.style.bold), - .italic => nc.cell_set_styles(&cell.cell, nc.style.italic), - .underline => nc.cell_set_styles(&cell.cell, nc.style.underline), - .undercurl => nc.cell_set_styles(&cell.cell, nc.style.undercurl), - .strikethrough => nc.cell_set_styles(&cell.cell, nc.style.struck), - }; - } - - pub inline fn set_style_fg(cell: *Cell, style_: Style) void { - channels.fg_from_style(&cell.cell.channels, style_); - } - - pub inline fn set_style_bg(cell: *Cell, style_: Style) void { - channels.bg_from_style(&cell.cell.channels, style_); - } - - pub inline fn set_fg_rgb(cell: *Cell, arg_rgb: c_uint) !void { - return channels.set_fg_rgb(&cell.cell.channels, arg_rgb); - } - pub inline fn set_bg_rgb(cell: *Cell, arg_rgb: c_uint) !void { - return channels.set_bg_rgb(&cell.cell.channels, arg_rgb); - } - - pub fn columns(cell: *const Cell) usize { - return nc.cell_cols(&cell.cell); - } -}; diff --git a/src/renderer/notcurses/Plane.zig b/src/renderer/notcurses/Plane.zig deleted file mode 100644 index c6aca43..0000000 --- a/src/renderer/notcurses/Plane.zig +++ /dev/null @@ -1,277 +0,0 @@ -const nc = @import("notcurses"); -const Style = @import("theme").Style; -const channels = @import("channels.zig"); -const StyleBits = @import("style.zig").StyleBits; -const Cell = @import("Cell.zig").Cell; - -pub const Plane = struct { - plane: nc.Plane, - - pub const Options = struct { - y: usize = 0, - x: usize = 0, - rows: usize = 0, - cols: usize = 0, - name: [*:0]const u8, - flags: option = .none, - }; - - pub const option = enum { - none, - VSCROLL, - }; - - pub fn init(nopts: *const Options, parent_: Plane) !Plane { - var nopts_: nc.Plane.Options = .{ - .y = @intCast(nopts.y), - .x = @intCast(nopts.x), - .rows = @intCast(nopts.rows), - .cols = @intCast(nopts.cols), - .name = nopts.name, - }; - switch (nopts.flags) { - .none => {}, - .VSCROLL => nopts_.flags = nc.Plane.option.VSCROLL, - } - - return .{ .plane = nc.Plane.init(&nopts_, parent_.plane) catch |e| return e }; - } - - pub fn deinit(self: *Plane) void { - self.plane.deinit(); - } - - pub fn name(self: Plane, buf: []u8) []u8 { - return self.plane.name(buf); - } - - pub fn parent(self: Plane) Plane { - return .{ .plane = self.plane.parent() }; - } - - pub fn above(self: Plane) ?Plane { - return .{ .plane = self.plane.above() orelse return null }; - } - - pub fn below(self: Plane) ?Plane { - return .{ .plane = self.plane.below() orelse return null }; - } - - pub fn erase(self: Plane) void { - return self.plane.erase(); - } - - pub fn abs_y(self: Plane) c_int { - return self.plane.abs_y(); - } - - pub fn abs_x(self: Plane) c_int { - return self.plane.abs_x(); - } - - pub fn dim_y(self: Plane) c_uint { - return self.plane.dim_y(); - } - - pub fn dim_x(self: Plane) c_uint { - return self.plane.dim_x(); - } - - pub fn abs_yx_to_rel(self: Plane, y: c_int, x: c_int) struct { c_int, c_int } { - var y_, var x_ = .{ y, x }; - self.plane.abs_yx_to_rel(&y_, &x_); - return .{ y_, x_ }; - } - - pub fn rel_yx_to_abs(self: Plane, y: c_int, x: c_int) struct { c_int, c_int } { - var y_, var x_ = .{ y, x }; - self.plane.rel_yx_to_abs(&y_, &x_); - return .{ y_, x_ }; - } - - pub fn hide(self: Plane) void { - self.plane.move_bottom(); - } - - pub fn move_yx(self: Plane, y: c_int, x: c_int) !void { - return self.plane.move_yx(y, x); - } - - pub fn resize_simple(self: Plane, ylen: c_uint, xlen: c_uint) !void { - return self.plane.resize_simple(ylen, xlen); - } - - pub fn home(self: Plane) void { - return self.plane.home(); - } - - pub fn print(self: Plane, comptime fmt: anytype, args: anytype) !usize { - return self.plane.print(fmt, args); - } - - pub fn print_aligned_right(self: Plane, y: c_int, comptime fmt: anytype, args: anytype) !usize { - return self.plane.print_aligned(y, .right, fmt, args); - } - - pub fn print_aligned_center(self: Plane, y: c_int, comptime fmt: anytype, args: anytype) !usize { - return self.plane.print_aligned(y, .center, fmt, args); - } - - pub fn putstr(self: Plane, gclustarr: [*:0]const u8) !usize { - return self.plane.putstr(gclustarr); - } - - pub fn putc(self: Plane, cell: *const Cell) !usize { - return self.plane.putc(&cell.cell); - } - - pub fn putc_yx(self: Plane, y: c_int, x: c_int, cell: *const Cell) !usize { - return self.plane.put_yx(y, x, &cell.cell); - } - - pub fn cursor_yx(self: Plane, y: *c_uint, x: *c_uint) void { - self.plane.cursor_yx(y, x); - } - - pub fn cursor_y(self: Plane) c_uint { - return self.plane.cursor_y(); - } - - pub fn cursor_x(self: Plane) c_uint { - return self.plane.cursor_x(); - } - - pub fn cursor_move_yx(self: Plane, y: c_int, x: c_int) !void { - return self.plane.cursor_move_yx(y, x); - } - - pub fn cursor_move_rel(self: Plane, y: c_int, x: c_int) !void { - return self.plane.cursor_move_rel(y, x); - } - - pub fn cell_init(self: Plane) Cell { - return .{ .cell = self.plane.cell_init() }; - } - - pub fn cell_load(self: Plane, cell: *Cell, gcluster: [:0]const u8) !usize { - return self.plane.cell_load(&cell.cell, gcluster); - } - - pub fn at_cursor_cell(self: Plane, cell: *Cell) !usize { - return self.plane.at_cursor_cell(&cell.cell); - } - - pub fn set_styles(self: Plane, stylebits: StyleBits) void { - return self.plane.set_styles(@intCast(@as(u5, @bitCast(stylebits)))); - } - - pub fn on_styles(self: Plane, stylebits: StyleBits) void { - return self.plane.on_styles(@intCast(@as(u5, @bitCast(stylebits)))); - } - - pub fn off_styles(self: Plane, stylebits: StyleBits) void { - return self.plane.off_styles(@intCast(@as(u5, @bitCast(stylebits)))); - } - - pub fn set_fg_rgb(self: Plane, channel: u32) !void { - return self.plane.set_fg_rgb(channel); - } - - pub fn set_bg_rgb(self: Plane, channel: u32) !void { - return self.plane.set_bg_rgb(channel); - } - - pub fn set_fg_palindex(self: Plane, idx: c_uint) !void { - return self.plane.set_fg_palindex(idx); - } - - pub fn set_bg_palindex(self: Plane, idx: c_uint) !void { - return self.plane.set_bg_palindex(idx); - } - - pub fn set_channels(self: Plane, channels_: u64) void { - return self.plane.set_channels(channels_); - } - - pub inline fn set_base_style(plane: *const Plane, egc_: [*c]const u8, style_: Style) void { - var channels_: u64 = 0; - channels.from_style(&channels_, style_); - if (style_.fg) |fg| plane.plane.set_fg_rgb(fg) catch {}; - if (style_.bg) |bg| plane.plane.set_bg_rgb(bg) catch {}; - _ = plane.plane.set_base(egc_, 0, channels_) catch {}; - } - - pub fn set_base_style_transparent(plane: Plane, egc_: [*:0]const u8, style_: Style) void { - var channels_: u64 = 0; - channels.from_style(&channels_, style_); - if (style_.fg) |fg| plane.plane.set_fg_rgb(fg) catch {}; - if (style_.bg) |bg| plane.plane.set_bg_rgb(bg) catch {}; - channels.set_fg_transparent(&channels_); - channels.set_bg_transparent(&channels_); - _ = plane.plane.set_base(egc_, 0, channels_) catch {}; - } - - pub fn set_base_style_bg_transparent(plane: Plane, egc_: [*:0]const u8, style_: Style) void { - var channels_: u64 = 0; - channels.from_style(&channels_, style_); - if (style_.fg) |fg| plane.plane.set_fg_rgb(fg) catch {}; - if (style_.bg) |bg| plane.plane.set_bg_rgb(bg) catch {}; - channels.set_bg_transparent(&channels_); - _ = plane.plane.set_base(egc_, 0, channels_) catch {}; - } - - pub inline fn set_style(plane: *const Plane, style_: Style) void { - var channels_: u64 = 0; - channels.from_style(&channels_, style_); - plane.plane.set_channels(channels_); - if (style_.fs) |fs| switch (fs) { - .normal => plane.plane.set_styles(nc.style.none), - .bold => plane.plane.set_styles(nc.style.bold), - .italic => plane.plane.set_styles(nc.style.italic), - .underline => plane.plane.set_styles(nc.style.underline), - .undercurl => plane.plane.set_styles(nc.style.undercurl), - .strikethrough => plane.plane.set_styles(nc.style.struck), - }; - } - - pub inline fn set_style_bg_transparent(plane: *const Plane, style_: Style) void { - var channels_: u64 = 0; - channels.from_style(&channels_, style_); - channels.set_bg_transparent(&channels_); - plane.plane.set_channels(channels_); - if (style_.fs) |fs| switch (fs) { - .normal => plane.plane.set_styles(nc.style.none), - .bold => plane.plane.set_styles(nc.style.bold), - .italic => plane.plane.set_styles(nc.style.italic), - .underline => plane.plane.set_styles(nc.style.underline), - .undercurl => plane.plane.set_styles(nc.style.undercurl), - .strikethrough => plane.plane.set_styles(nc.style.struck), - }; - } - - pub fn egc_length(_: Plane, egcs: []const u8, colcount: *c_int, abs_col: usize) usize { - if (egcs[0] == '\t') { - colcount.* = @intCast(8 - abs_col % 8); - return 1; - } - return nc.ncegc_len(egcs, colcount) catch ret: { - colcount.* = 1; - break :ret 1; - }; - } - - pub fn egc_chunk_width(plane: Plane, chunk_: []const u8, abs_col_: usize) usize { - var abs_col = abs_col_; - var chunk = chunk_; - var colcount: usize = 0; - var cols: c_int = 0; - while (chunk.len > 0) { - const bytes = plane.egc_length(chunk, &cols, abs_col); - colcount += @intCast(cols); - abs_col += @intCast(cols); - if (chunk.len < bytes) break; - chunk = chunk[bytes..]; - } - return colcount; - } -}; diff --git a/src/renderer/notcurses/channels.zig b/src/renderer/notcurses/channels.zig deleted file mode 100644 index 5115023..0000000 --- a/src/renderer/notcurses/channels.zig +++ /dev/null @@ -1,40 +0,0 @@ -const Style = @import("theme").Style; -const nc = @import("notcurses"); - -pub const set_fg_rgb = nc.channels_set_fg_rgb; -pub const set_bg_rgb = nc.channels_set_bg_rgb; - -pub fn set_fg_opaque(channels_: *u64) void { - nc.channels_set_fg_alpha(channels_, nc.ALPHA_OPAQUE) catch {}; -} - -pub fn set_bg_opaque(channels_: *u64) void { - nc.channels_set_bg_alpha(channels_, nc.ALPHA_OPAQUE) catch {}; -} - -pub fn set_fg_transparent(channels_: *u64) void { - nc.channels_set_fg_alpha(channels_, nc.ALPHA_TRANSPARENT) catch {}; -} - -pub fn set_bg_transparent(channels_: *u64) void { - nc.channels_set_bg_alpha(channels_, nc.ALPHA_TRANSPARENT) catch {}; -} - -pub inline fn fg_from_style(channels_: *u64, style_: Style) void { - if (style_.fg) |fg| { - set_fg_rgb(channels_, fg) catch {}; - set_fg_opaque(channels_); - } -} - -pub inline fn bg_from_style(channels_: *u64, style_: Style) void { - if (style_.bg) |bg| { - set_bg_rgb(channels_, bg) catch {}; - set_bg_opaque(channels_); - } -} - -pub inline fn from_style(channels_: *u64, style_: Style) void { - fg_from_style(channels_, style_); - bg_from_style(channels_, style_); -} diff --git a/src/renderer/notcurses/input.zig b/src/renderer/notcurses/input.zig deleted file mode 100644 index b50c8fa..0000000 --- a/src/renderer/notcurses/input.zig +++ /dev/null @@ -1,15 +0,0 @@ -const nc = @import("notcurses"); - -pub const key = nc.key; -pub const key_type = u32; -pub const modifier = nc.mod; -pub const event_type = nc.event_type; - -pub const utils = struct { - pub const isSuper = nc.isSuper; - pub const isCtrl = nc.isCtrl; - pub const isShift = nc.isShift; - pub const isAlt = nc.isAlt; - pub const key_id_string = nc.key_id_string; - pub const key_string = nc.key_string; -}; diff --git a/src/renderer/notcurses/renderer.zig b/src/renderer/notcurses/renderer.zig deleted file mode 100644 index 5b7b4ec..0000000 --- a/src/renderer/notcurses/renderer.zig +++ /dev/null @@ -1,525 +0,0 @@ -const std = @import("std"); -const cbor = @import("cbor"); -const log = @import("log"); -const nc = @import("notcurses"); -const Style = @import("theme").Style; - -pub const input = @import("input.zig"); - -pub const Plane = @import("Plane.zig").Plane; -pub const Cell = @import("Cell.zig").Cell; -pub const channels = @import("channels.zig"); - -pub const style = @import("style.zig").StyleBits; - -const mod = input.modifier; -const key = input.key; -const event_type = input.event_type; - -const Self = @This(); -pub const log_name = "notcurses"; - -a: std.mem.Allocator, -ctx: nc.Context, - -escape_state: EscapeState = .none, -escape_initial: ?nc.Input = null, -escape_code: std.ArrayList(u8), - -event_buffer: std.ArrayList(u8), -mods: ModState = .{}, -drag: bool = false, -drag_event: nc.Input = nc.input(), -bracketed_paste: bool = false, -bracketed_paste_buffer: std.ArrayList(u8), - -handler_ctx: *anyopaque, -dispatch_input: ?*const fn (ctx: *anyopaque, cbor_msg: []const u8) void = null, -dispatch_mouse: ?*const fn (ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) void = null, -dispatch_mouse_drag: ?*const fn (ctx: *anyopaque, y: c_int, x: c_int, dragging: bool, cbor_msg: []const u8) void = null, -dispatch_event: ?*const fn (ctx: *anyopaque, cbor_msg: []const u8) void = null, - -logger: log.Logger, - -const EscapeState = enum { none, init, OSC, st, CSI }; -const ModState = struct { ctrl: bool = false, shift: bool = false, alt: bool = false }; - -pub fn init(a: std.mem.Allocator, handler_ctx: *anyopaque, no_alternate: bool) !Self { - var opts = nc.Context.Options{ - .termtype = null, - .loglevel = @intFromEnum(nc.LogLevel.silent), - .margin_t = 0, - .margin_r = 0, - .margin_b = 0, - .margin_l = 0, - .flags = nc.Context.option.SUPPRESS_BANNERS | nc.Context.option.INHIBIT_SETLOCALE | nc.Context.option.NO_WINCH_SIGHANDLER, - }; - if (no_alternate) - opts.flags |= nc.Context.option.NO_ALTERNATE_SCREEN; - const nc_ = try nc.Context.core_init(&opts, null); - nc_.mice_enable(nc.mice.ALL_EVENTS) catch {}; - try nc_.linesigs_disable(); - bracketed_paste_enable(); - - return .{ - .a = a, - .ctx = nc_, - .escape_code = std.ArrayList(u8).init(a), - .event_buffer = std.ArrayList(u8).init(a), - .bracketed_paste_buffer = std.ArrayList(u8).init(a), - .handler_ctx = handler_ctx, - .logger = log.logger(log_name), - }; -} - -pub fn deinit(self: *Self) void { - self.escape_code.deinit(); - self.event_buffer.deinit(); - self.bracketed_paste_buffer.deinit(); -} - -pub fn run(_: *Self) !void {} - -pub fn render(self: Self) !void { - return self.ctx.render(); -} - -pub fn refresh(self: Self) !void { - return self.ctx.refresh(); -} - -pub fn stop(self: Self) void { - return self.ctx.stop(); -} - -pub fn stdplane(self: Self) Plane { - return .{ .plane = self.ctx.stdplane() }; -} - -pub fn input_fd(self: Self) i32 { - return self.ctx.inputready_fd(); -} - -pub fn leave_alternate_screen(self: Self) void { - return self.ctx.leave_alternate_screen(); -} - -const InputError = error{ - OutOfMemory, - InvalidCharacter, - NoSpaceLeft, - CborIntegerTooLarge, - CborIntegerTooSmall, - CborInvalidType, - CborTooShort, - Ucs32toUtf8Error, - InvalidPadding, - ReadInputError, - WouldBlock, -}; - -pub fn process_input(self: *Self) InputError!void { - var input_buffer: [256]nc.Input = undefined; - - while (true) { - const nivec = self.ctx.getvec_nblock(&input_buffer) catch return error.ReadInputError; - if (nivec.len == 0) - break; - for (nivec) |*ni| { - if (ni.id == 27 or self.escape_state != .none) { - try self.handle_escape(ni); - continue; - } - self.dispatch_input_event(ni) catch |e| - self.logger.err("input dispatch", e); - } - } - if (self.escape_state == .init) - try self.handle_escape_short(); -} - -fn fmtmsg(self: *Self, value: anytype) ![]const u8 { - self.event_buffer.clearRetainingCapacity(); - try cbor.writeValue(self.event_buffer.writer(), value); - return self.event_buffer.items; -} - -fn dispatch_input_event(self: *Self, ni: *nc.Input) !void { - const keypress: u32 = ni.id; - ni.modifiers &= mod.CTRL | mod.SHIFT | mod.ALT | mod.SUPER | mod.META | mod.HYPER; - if (keypress == key.RESIZE) return; - try self.sync_mod_state(keypress, ni.modifiers); - if (keypress == key.MOTION) { - if (ni.y == 0 and ni.x == 0 and ni.ypx == -1 and ni.xpx == -1) return; - if (self.dispatch_mouse) |f| f( - self.handler_ctx, - ni.y, - ni.x, - try self.fmtmsg(.{ - "M", - ni.x, - ni.y, - ni.xpx, - ni.ypx, - }), - ); - } else if (keypress > key.MOTION and keypress <= key.BUTTON11) { - if (ni.y == 0 and ni.x == 0 and ni.ypx == -1 and ni.xpx == -1) return; - if (try self.detect_drag(ni)) return; - if (self.dispatch_mouse) |f| f( - self.handler_ctx, - ni.y, - ni.x, - try self.fmtmsg(.{ - "B", - ni.evtype, - keypress, - input.utils.key_string(ni), - ni.x, - ni.y, - ni.xpx, - ni.ypx, - }), - ); - } else { - const cbor_msg = try self.fmtmsg(.{ - "I", - normalized_evtype(ni.evtype), - keypress, - if (@hasField(nc.Input, "eff_text")) ni.eff_text[0] else keypress, - input.utils.key_string(ni), - ni.modifiers, - }); - if (self.bracketed_paste and self.handle_bracketed_paste_input(cbor_msg) catch |e| { - self.bracketed_paste_buffer.clearAndFree(); - self.bracketed_paste = false; - return e; - }) {} else if (self.dispatch_input) |f| f(self.handler_ctx, cbor_msg); - } -} - -fn handle_bracketed_paste_input(self: *Self, cbor_msg: []const u8) !bool { - var keypress: u32 = undefined; - var egc_: u32 = undefined; - if (try cbor.match(cbor_msg, .{ "I", cbor.number, cbor.extract(&keypress), cbor.extract(&egc_), cbor.string, 0 })) { - switch (keypress) { - key.ENTER => try self.bracketed_paste_buffer.appendSlice("\n"), - else => if (!key.synthesized_p(keypress)) { - var buf: [6]u8 = undefined; - const bytes = try ucs32_to_utf8(&[_]u32{egc_}, &buf); - try self.bracketed_paste_buffer.appendSlice(buf[0..bytes]); - } else { - try self.handle_bracketed_paste_end(); - return false; - }, - } - return true; - } - return false; -} - -fn normalized_evtype(evtype: c_uint) c_uint { - return if (evtype == event_type.UNKNOWN) @as(c_uint, @intCast(event_type.PRESS)) else evtype; -} - -fn sync_mod_state(self: *Self, keypress: u32, modifiers: u32) !void { - if (input.utils.isCtrl(modifiers) and !self.mods.ctrl and !(keypress == key.LCTRL or keypress == key.RCTRL)) - try self.send_sync_key(event_type.PRESS, key.LCTRL, "lctrl", modifiers); - if (!input.utils.isCtrl(modifiers) and self.mods.ctrl and !(keypress == key.LCTRL or keypress == key.RCTRL)) - try self.send_sync_key(event_type.RELEASE, key.LCTRL, "lctrl", modifiers); - if (input.utils.isAlt(modifiers) and !self.mods.alt and !(keypress == key.LALT or keypress == key.RALT)) - try self.send_sync_key(event_type.PRESS, key.LALT, "lalt", modifiers); - if (!input.utils.isAlt(modifiers) and self.mods.alt and !(keypress == key.LALT or keypress == key.RALT)) - try self.send_sync_key(event_type.RELEASE, key.LALT, "lalt", modifiers); - if (input.utils.isShift(modifiers) and !self.mods.shift and !(keypress == key.LSHIFT or keypress == key.RSHIFT)) - try self.send_sync_key(event_type.PRESS, key.LSHIFT, "lshift", modifiers); - if (!input.utils.isShift(modifiers) and self.mods.shift and !(keypress == key.LSHIFT or keypress == key.RSHIFT)) - try self.send_sync_key(event_type.RELEASE, key.LSHIFT, "lshift", modifiers); - self.mods = .{ - .ctrl = input.utils.isCtrl(modifiers), - .alt = input.utils.isAlt(modifiers), - .shift = input.utils.isShift(modifiers), - }; -} - -fn send_sync_key(self: *Self, event_type_: c_int, keypress: u32, key_string: []const u8, modifiers: u32) !void { - if (self.dispatch_input) |f| f( - self.handler_ctx, - try self.fmtmsg(.{ - "I", - event_type_, - keypress, - keypress, - key_string, - modifiers, - }), - ); -} - -fn detect_drag(self: *Self, ni: *nc.Input) !bool { - return switch (ni.id) { - key.BUTTON1...key.BUTTON3, key.BUTTON6...key.BUTTON9 => if (self.drag) self.detect_drag_end(ni) else self.detect_drag_begin(ni), - else => false, - }; -} - -fn detect_drag_begin(self: *Self, ni: *nc.Input) !bool { - if (ni.evtype == event_type.PRESS and self.drag_event.id == ni.id) { - self.drag_event = ni.*; - self.drag = true; - if (self.dispatch_mouse_drag) |f| f( - self.handler_ctx, - ni.y, - ni.x, - true, - try self.fmtmsg(.{ - "D", - event_type.PRESS, - ni.id, - input.utils.key_string(ni), - ni.x, - ni.y, - ni.xpx, - ni.ypx, - }), - ); - return true; - } - if (ni.evtype == event_type.PRESS) - self.drag_event = ni.* - else - self.drag_event = nc.input(); - return false; -} - -fn detect_drag_end(self: *Self, ni: *nc.Input) !bool { - if (ni.id == self.drag_event.id and ni.evtype != event_type.PRESS) { - if (self.dispatch_mouse_drag) |f| f( - self.handler_ctx, - ni.y, - ni.x, - false, - try self.fmtmsg(.{ - "D", - event_type.RELEASE, - ni.id, - input.utils.key_string(ni), - ni.x, - ni.y, - ni.xpx, - ni.ypx, - }), - ); - self.drag = false; - self.drag_event = nc.input(); - } else if (self.dispatch_mouse_drag) |f| f( - self.handler_ctx, - ni.y, - ni.x, - true, - try self.fmtmsg(.{ - "D", - ni.evtype, - ni.id, - input.utils.key_string(ni), - ni.x, - ni.y, - ni.xpx, - ni.ypx, - }), - ); - return true; -} - -fn handle_escape(self: *Self, ni: *nc.Input) !void { - switch (self.escape_state) { - .none => switch (ni.id) { - '\x1B' => { - self.escape_state = .init; - self.escape_initial = ni.*; - }, - else => unreachable, - }, - .init => switch (ni.id) { - ']' => self.escape_state = .OSC, - '[' => self.escape_state = .CSI, - else => { - try self.handle_escape_short(); - _ = try self.dispatch_input_event(ni); - }, - }, - .OSC => switch (ni.id) { - '\x1B' => self.escape_state = .st, - '\\' => try self.handle_OSC_escape_code(), - ' '...'\\' - 1, '\\' + 1...127 => { - const p = try self.escape_code.addOne(); - p.* = @intCast(ni.id); - }, - else => try self.handle_OSC_escape_code(), - }, - .st => switch (ni.id) { - '\\' => try self.handle_OSC_escape_code(), - else => try self.handle_OSC_escape_code(), - }, - .CSI => switch (ni.id) { - '0'...'9', ';', ' ', '-', '?' => { - const p = try self.escape_code.addOne(); - p.* = @intCast(ni.id); - }, - else => { - const p = try self.escape_code.addOne(); - p.* = @intCast(ni.id); - try self.handle_CSI_escape_code(); - }, - }, - } -} - -fn handle_escape_short(self: *Self) !void { - self.escape_code.clearAndFree(); - self.escape_state = .none; - defer self.escape_initial = null; - if (self.escape_initial) |*ni| - _ = try self.dispatch_input_event(ni); -} - -fn match_code(self: Self, match: []const u8, skip: usize) bool { - const code = self.escape_code.items; - if (!(code.len >= match.len - skip)) return false; - const code_prefix = code[0 .. match.len - skip]; - return std.mem.eql(u8, match[skip..], code_prefix); -} - -const OSC = "\x1B]"; // Operating System Command -const ST = "\x1B\\"; // String Terminator -const BEL = "\x07"; -const OSC0_title = OSC ++ "0;"; -const OSC52_clipboard = OSC ++ "52;c;"; -const OSC52_clipboard_paste = OSC ++ "52;p;"; -const OSC22_cursor = OSC ++ "22;"; -const OSC22_cursor_reply = OSC ++ "22:"; - -fn handle_OSC_escape_code(self: *Self) !void { - self.escape_state = .none; - self.escape_initial = null; - defer self.escape_code.clearAndFree(); - const code = self.escape_code.items; - if (self.match_code(OSC52_clipboard, OSC.len)) - return self.handle_system_clipboard(code[OSC52_clipboard.len - OSC.len ..]); - if (self.match_code(OSC52_clipboard_paste, OSC.len)) - return self.handle_system_clipboard(code[OSC52_clipboard_paste.len - OSC.len ..]); - if (self.match_code(OSC22_cursor_reply, OSC.len)) - return self.handle_mouse_cursor(code[OSC22_cursor_reply.len - OSC.len ..]); - self.logger.print("ignored escape code: OSC {s}", .{std.fmt.fmtSliceEscapeLower(code)}); -} - -fn handle_system_clipboard(self: *Self, base64: []const u8) !void { - const decoder = std.base64.standard.Decoder; - const text = try self.a.alloc(u8, try decoder.calcSizeForSlice(base64)); - defer self.a.free(text); - try decoder.decode(text, base64); - if (self.dispatch_event) |f| f(self.handler_ctx, try self.fmtmsg(.{ "system_clipboard", text })); -} - -fn handle_mouse_cursor(self: Self, text: []const u8) !void { - self.logger.print("mouse cursor report: {s}", .{text}); -} - -const CSI = "\x1B["; // Control Sequence Introducer -const CSI_bracketed_paste_enable = CSI ++ "?2004h"; -const CSI_bracketed_paste_disable = CSI ++ "?2004h"; -const CIS_bracketed_paste_begin = CSI ++ "200~"; -const CIS_bracketed_paste_end = CSI ++ "201~"; - -fn bracketed_paste_enable() void { - write_stdout(CSI_bracketed_paste_enable); -} - -fn bracketed_paste_disable() void { - write_stdout(CSI_bracketed_paste_disable); -} - -fn handle_CSI_escape_code(self: *Self) !void { - self.escape_state = .none; - self.escape_initial = null; - defer self.escape_code.clearAndFree(); - const code = self.escape_code.items; - if (self.match_code(CIS_bracketed_paste_begin, CSI.len)) - return self.handle_bracketed_paste_begin(); - if (self.match_code(CIS_bracketed_paste_end, CSI.len)) - return self.handle_bracketed_paste_end(); - self.logger.print("ignored escape code: CSI {s}", .{std.fmt.fmtSliceEscapeLower(code)}); -} - -fn handle_bracketed_paste_begin(self: *Self) !void { - self.bracketed_paste_buffer.clearAndFree(); - self.bracketed_paste = true; -} - -fn handle_bracketed_paste_end(self: *Self) !void { - defer self.bracketed_paste_buffer.clearAndFree(); - if (!self.bracketed_paste) return; - self.bracketed_paste = false; - if (self.dispatch_event) |f| f(self.handler_ctx, try self.fmtmsg(.{ "system_clipboard", self.bracketed_paste_buffer.items })); -} - -pub fn set_terminal_title(_: *Self, text: []const u8) void { - var writer = std.io.getStdOut().writer(); - var buf: [std.posix.PATH_MAX]u8 = undefined; - const term_cmd = std.fmt.bufPrint(&buf, OSC0_title ++ "{s}" ++ BEL, .{text}) catch return; - _ = writer.write(term_cmd) catch return; -} - -pub fn copy_to_system_clipboard(self: *Self, text: []const u8) void { - self.copy_to_system_clipboard_with_errors(text) catch |e| log.logger(log_name).err("copy_to_system_clipboard", e); -} - -fn copy_to_system_clipboard_with_errors(self: *Self, text: []const u8) !void { - var writer = std.io.getStdOut().writer(); - const encoder = std.base64.standard.Encoder; - const size = OSC52_clipboard.len + encoder.calcSize(text.len) + ST.len; - const buf = try self.a.alloc(u8, size); - defer self.a.free(buf); - @memcpy(buf[0..OSC52_clipboard.len], OSC52_clipboard); - const b64 = encoder.encode(buf[OSC52_clipboard.len..], text); - @memcpy(buf[OSC52_clipboard.len + b64.len ..], ST); - _ = try writer.write(buf); -} - -pub fn request_system_clipboard(_: *Self) void { - write_stdout(OSC52_clipboard ++ "?" ++ ST); -} - -pub fn request_mouse_cursor_text(_: *Self, push_or_pop: bool) void { - if (push_or_pop) mouse_cursor_push("text") else mouse_cursor_pop(); -} - -pub fn request_mouse_cursor_pointer(_: *Self, push_or_pop: bool) void { - if (push_or_pop) mouse_cursor_push("pointer") else mouse_cursor_pop(); -} - -pub fn request_mouse_cursor_default(_: *Self, push_or_pop: bool) void { - if (push_or_pop) mouse_cursor_push("default") else mouse_cursor_pop(); -} - -fn mouse_cursor_push(comptime name: []const u8) void { - write_stdout(OSC22_cursor ++ name ++ ST); -} - -fn mouse_cursor_pop() void { - write_stdout(OSC22_cursor ++ "default" ++ ST); -} - -fn write_stdout(bytes: []const u8) void { - _ = std.io.getStdOut().writer().write(bytes) catch |e| log.logger(log_name).err("stdout", e); -} - -pub fn cursor_enable(self: Self, y: c_int, x: c_int) !void { - return self.ctx.cursor_enable(y, x); -} - -pub fn cursor_disable(self: Self) void { - self.ctx.cursor_disable() catch {}; -} - -pub const ucs32_to_utf8 = nc.ucs32_to_utf8; diff --git a/src/renderer/notcurses/style.zig b/src/renderer/notcurses/style.zig deleted file mode 100644 index 4420bd5..0000000 --- a/src/renderer/notcurses/style.zig +++ /dev/null @@ -1,14 +0,0 @@ -pub const StyleBits = packed struct(u5) { - struck: bool = false, - bold: bool = false, - undercurl: bool = false, - underline: bool = false, - italic: bool = false, - - pub const struck: StyleBits = .{ .struck = true }; - pub const bold: StyleBits = .{ .bold = true }; - pub const undercurl: StyleBits = .{ .undercurl = true }; - pub const underline: StyleBits = .{ .underline = true }; - pub const italic: StyleBits = .{ .italic = true }; - pub const normal: StyleBits = .{}; -};