mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-21 23:05:20 +00:00
vt: add style C API
Expose the terminal Style struct to the C API as GhosttyStyle, a sized struct with foreground, background, and underline colors (as tagged unions) plus boolean text decoration flags. Add ghostty_style_default() to obtain the default style and ghostty_style_is_default() to check whether a style has all default values. Wire both through c/style.zig, main.zig, and lib_vt.zig with the corresponding header in vt/style.h.
This commit is contained in:
@@ -169,6 +169,8 @@ comptime {
|
||||
@export(&c.mode_report_encode, .{ .name = "ghostty_mode_report_encode" });
|
||||
@export(&c.paste_is_safe, .{ .name = "ghostty_paste_is_safe" });
|
||||
@export(&c.size_report_encode, .{ .name = "ghostty_size_report_encode" });
|
||||
@export(&c.style_default, .{ .name = "ghostty_style_default" });
|
||||
@export(&c.style_is_default, .{ .name = "ghostty_style_is_default" });
|
||||
@export(&c.color_rgb_get, .{ .name = "ghostty_color_rgb_get" });
|
||||
@export(&c.sgr_new, .{ .name = "ghostty_sgr_new" });
|
||||
@export(&c.sgr_free, .{ .name = "ghostty_sgr_free" });
|
||||
|
||||
@@ -10,6 +10,7 @@ pub const mouse_encode = @import("mouse_encode.zig");
|
||||
pub const paste = @import("paste.zig");
|
||||
pub const sgr = @import("sgr.zig");
|
||||
pub const size_report = @import("size_report.zig");
|
||||
pub const style = @import("style.zig");
|
||||
pub const terminal = @import("terminal.zig");
|
||||
|
||||
// The full C API, unexported.
|
||||
@@ -90,6 +91,9 @@ pub const paste_is_safe = paste.is_safe;
|
||||
|
||||
pub const size_report_encode = size_report.encode;
|
||||
|
||||
pub const style_default = style.default_style;
|
||||
pub const style_is_default = style.style_is_default;
|
||||
|
||||
pub const terminal_new = terminal.new;
|
||||
pub const terminal_free = terminal.free;
|
||||
pub const terminal_reset = terminal.reset;
|
||||
@@ -113,6 +117,7 @@ test {
|
||||
_ = paste;
|
||||
_ = sgr;
|
||||
_ = size_report;
|
||||
_ = style;
|
||||
_ = terminal;
|
||||
|
||||
// We want to make sure we run the tests for the C allocator interface.
|
||||
|
||||
133
src/terminal/c/style.zig
Normal file
133
src/terminal/c/style.zig
Normal file
@@ -0,0 +1,133 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const style = @import("../style.zig");
|
||||
const color = @import("../color.zig");
|
||||
const sgr = @import("../sgr.zig");
|
||||
|
||||
/// C: GhosttyStyleColorTag
|
||||
pub const ColorTag = enum(c_int) {
|
||||
none = 0,
|
||||
palette = 1,
|
||||
rgb = 2,
|
||||
};
|
||||
|
||||
/// C: GhosttyStyleColorValue
|
||||
pub const ColorValue = extern union {
|
||||
palette: u8,
|
||||
rgb: color.RGB.C,
|
||||
_padding: u32,
|
||||
};
|
||||
|
||||
/// C: GhosttyStyleColor
|
||||
pub const Color = extern struct {
|
||||
tag: ColorTag,
|
||||
value: ColorValue,
|
||||
};
|
||||
|
||||
/// C: GhosttyStyle
|
||||
pub const Style = extern struct {
|
||||
size: usize = @sizeOf(Style),
|
||||
fg_color: Color,
|
||||
bg_color: Color,
|
||||
underline_color: Color,
|
||||
bold: bool,
|
||||
italic: bool,
|
||||
faint: bool,
|
||||
blink: bool,
|
||||
inverse: bool,
|
||||
invisible: bool,
|
||||
strikethrough: bool,
|
||||
overline: bool,
|
||||
underline: c_int,
|
||||
};
|
||||
|
||||
fn convertColor(c: style.Style.Color) Color {
|
||||
return switch (c) {
|
||||
.none => .{
|
||||
.tag = .none,
|
||||
.value = .{ ._padding = 0 },
|
||||
},
|
||||
.palette => |idx| .{
|
||||
.tag = .palette,
|
||||
.value = .{ .palette = idx },
|
||||
},
|
||||
.rgb => |rgb| .{
|
||||
.tag = .rgb,
|
||||
.value = .{ .rgb = rgb.cval() },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn convertStyle(s: style.Style) Style {
|
||||
return .{
|
||||
.fg_color = convertColor(s.fg_color),
|
||||
.bg_color = convertColor(s.bg_color),
|
||||
.underline_color = convertColor(s.underline_color),
|
||||
.bold = s.flags.bold,
|
||||
.italic = s.flags.italic,
|
||||
.faint = s.flags.faint,
|
||||
.blink = s.flags.blink,
|
||||
.inverse = s.flags.inverse,
|
||||
.invisible = s.flags.invisible,
|
||||
.strikethrough = s.flags.strikethrough,
|
||||
.overline = s.flags.overline,
|
||||
.underline = @intFromEnum(s.flags.underline),
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the default style.
|
||||
pub fn default_style(result: *Style) callconv(.c) void {
|
||||
result.* = convertStyle(.{});
|
||||
assert(result.size == @sizeOf(Style));
|
||||
}
|
||||
|
||||
/// Returns true if the style is the default style.
|
||||
pub fn style_is_default(s: *const Style) callconv(.c) bool {
|
||||
assert(s.size == @sizeOf(Style));
|
||||
return s.fg_color.tag == .none and
|
||||
s.bg_color.tag == .none and
|
||||
s.underline_color.tag == .none and
|
||||
s.bold == false and
|
||||
s.italic == false and
|
||||
s.faint == false and
|
||||
s.blink == false and
|
||||
s.inverse == false and
|
||||
s.invisible == false and
|
||||
s.strikethrough == false and
|
||||
s.overline == false and
|
||||
s.underline == 0;
|
||||
}
|
||||
|
||||
test "default style" {
|
||||
var s: Style = undefined;
|
||||
default_style(&s);
|
||||
try testing.expect(style_is_default(&s));
|
||||
try testing.expectEqual(ColorTag.none, s.fg_color.tag);
|
||||
try testing.expectEqual(ColorTag.none, s.bg_color.tag);
|
||||
try testing.expectEqual(ColorTag.none, s.underline_color.tag);
|
||||
try testing.expect(!s.bold);
|
||||
try testing.expect(!s.italic);
|
||||
try testing.expectEqual(@as(c_int, 0), s.underline);
|
||||
}
|
||||
|
||||
test "convert style with colors" {
|
||||
const zig_style: style.Style = .{
|
||||
.fg_color = .{ .palette = 42 },
|
||||
.bg_color = .{ .rgb = .{ .r = 255, .g = 128, .b = 64 } },
|
||||
.underline_color = .none,
|
||||
.flags = .{ .bold = true, .underline = .curly },
|
||||
};
|
||||
|
||||
const c_style = convertStyle(zig_style);
|
||||
try testing.expectEqual(ColorTag.palette, c_style.fg_color.tag);
|
||||
try testing.expectEqual(@as(u8, 42), c_style.fg_color.value.palette);
|
||||
try testing.expectEqual(ColorTag.rgb, c_style.bg_color.tag);
|
||||
try testing.expectEqual(@as(u8, 255), c_style.bg_color.value.rgb.r);
|
||||
try testing.expectEqual(@as(u8, 128), c_style.bg_color.value.rgb.g);
|
||||
try testing.expectEqual(@as(u8, 64), c_style.bg_color.value.rgb.b);
|
||||
try testing.expectEqual(ColorTag.none, c_style.underline_color.tag);
|
||||
try testing.expect(c_style.bold);
|
||||
try testing.expectEqual(@as(c_int, 3), c_style.underline);
|
||||
try testing.expect(!style_is_default(&c_style));
|
||||
}
|
||||
Reference in New Issue
Block a user