diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-09-10 21:51:57 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-10 21:51:57 +0300 |
| commit | 425c86179791cd32e2d4ce0ae7f269940b4b0663 (patch) | |
| tree | e52c4383a6d69216cbe2a32638bf90841d7e2189 /vendor/libghostty-vt/src/terminal/c/selection.zig | |
| parent | 90e947a6e26e02f10ec7f1694c4eb5b78a86406b (diff) | |
chore: upgrade libghostty and preserve terminal behavior (#3906)
Diffstat (limited to 'vendor/libghostty-vt/src/terminal/c/selection.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/terminal/c/selection.zig | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/vendor/libghostty-vt/src/terminal/c/selection.zig b/vendor/libghostty-vt/src/terminal/c/selection.zig index cb574ecc..2830149f 100644 --- a/vendor/libghostty-vt/src/terminal/c/selection.zig +++ b/vendor/libghostty-vt/src/terminal/c/selection.zig @@ -38,6 +38,18 @@ pub const CSelection = extern struct { } }; +/// C: GhosttySelectionBuffer +/// +/// A caller-provided buffer of selections. This follows the same +/// conventions as GhosttyBuffer: ptr may be NULL with cap 0 to query +/// the required capacity, and len is set to the entries written on +/// success or to the required capacity on GHOSTTY_OUT_OF_SPACE. +pub const CSelectionBuffer = extern struct { + ptr: ?[*]CSelection = null, + cap: usize = 0, + len: usize = 0, +}; + /// C: GhosttyTerminalSelectWordOptions pub const SelectWordOptions = extern struct { size: usize = @sizeOf(SelectWordOptions), @@ -234,7 +246,8 @@ pub fn format_alloc( }; const buf = aw.toOwnedSlice() catch return .out_of_memory; - out_ptr.* = buf.ptr; + // Do not expose Zig's empty slice sentinel through the C ABI. + out_ptr.* = if (buf.len == 0) null else buf.ptr; out_len.* = buf.len; return .success; } @@ -253,7 +266,7 @@ fn selectionFormatter( opts: FormatOptions, ) error{ InvalidValue, NoValue }!formatterpkg.TerminalFormatter { if (opts.size < @sizeOf(FormatOptions)) return error.InvalidValue; - _ = std.meta.intToEnum(Format, @intFromEnum(opts.emit)) catch + _ = std.enums.fromInt(Format, @intFromEnum(opts.emit)) orelse return error.InvalidValue; const sel = if (opts.selection) |sel| @@ -308,7 +321,7 @@ pub fn adjust( adjustment: Selection.Adjustment, ) callconv(lib.calling_conv) Result { if (comptime std.debug.runtime_safety) { - _ = std.meta.intToEnum(Selection.Adjustment, @intFromEnum(adjustment)) catch { + _ = std.enums.fromInt(Selection.Adjustment, @intFromEnum(adjustment)) orelse { log.warn("terminal_selection_adjust invalid adjustment value={d}", .{@intFromEnum(adjustment)}); return .invalid_value; }; @@ -343,7 +356,7 @@ pub fn ordered( out_selection: ?*CSelection, ) callconv(lib.calling_conv) Result { if (comptime std.debug.runtime_safety) { - _ = std.meta.intToEnum(Selection.Order, @intFromEnum(desired)) catch { + _ = std.enums.fromInt(Selection.Order, @intFromEnum(desired)) orelse { log.warn("terminal_selection_ordered invalid desired value={d}", .{@intFromEnum(desired)}); return .invalid_value; }; @@ -392,12 +405,44 @@ pub fn equal( return .success; } +test "selection_format_alloc empty output" { + const failing: CAllocator = .fromZig(&std.mem.Allocator.failing); + var t: terminal_c.Terminal = null; + try testing.expectEqual(Result.success, terminal_c.new( + &lib.alloc.test_allocator, + &t, + 80, + 24, + )); + defer terminal_c.free(t); + + var ref: grid_ref.CGridRef = .{}; + try testing.expectEqual(Result.success, terminal_c.grid_ref(t, .{ + .tag = .active, + .value = .{ .active = .{ .x = 0, .y = 0 } }, + }, &ref)); + const sel: CSelection = .{ .start = ref, .end = ref }; + try testing.expectEqual(Result.success, terminal_c.set(t, .selection, &sel)); + + var ptr: ?[*]u8 = null; + var len: usize = 123; + try testing.expectEqual(Result.success, format_alloc(t, &failing, .{ + .emit = .plain, + .unwrap = true, + .trim = true, + }, &ptr, &len)); + defer @import("allocator.zig").free(&failing, ptr, len); + try testing.expectEqual(@as(usize, 0), len); + try testing.expectEqual(null, ptr); +} + test "selection_format_alloc uses active selection" { var t: terminal_c.Terminal = null; try testing.expectEqual(Result.success, terminal_c.new( &lib.alloc.test_allocator, &t, - .{ .cols = 80, .rows = 24, .max_scrollback = 10_000 }, + 80, + 24, )); defer terminal_c.free(t); @@ -457,7 +502,8 @@ test "selection_format_buf uses provided selection" { try testing.expectEqual(Result.success, terminal_c.new( &lib.alloc.test_allocator, &t, - .{ .cols = 80, .rows = 24, .max_scrollback = 10_000 }, + 80, + 24, )); defer terminal_c.free(t); @@ -513,7 +559,8 @@ test "selection_format_alloc returns no_value without active selection" { try testing.expectEqual(Result.success, terminal_c.new( &lib.alloc.test_allocator, &t, - .{ .cols = 80, .rows = 24, .max_scrollback = 10_000 }, + 80, + 24, )); defer terminal_c.free(t); |
