mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-04-20 00:18:53 +03:00
169 lines
5.0 KiB
Zig
169 lines
5.0 KiB
Zig
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const c = @import("c.zig").c;
|
|
const Error = @import("main.zig").Error;
|
|
const ObjectSet = @import("main.zig").ObjectSet;
|
|
const Property = @import("main.zig").Property;
|
|
const Result = @import("main.zig").Result;
|
|
const Value = @import("main.zig").Value;
|
|
const ValueBinding = @import("main.zig").ValueBinding;
|
|
const Weight = @import("main.zig").Weight;
|
|
|
|
pub const Pattern = opaque {
|
|
pub fn create() *Pattern {
|
|
return @ptrCast(c.FcPatternCreate());
|
|
}
|
|
|
|
pub fn parse(str: [:0]const u8) *Pattern {
|
|
return @ptrCast(c.FcNameParse(str.ptr));
|
|
}
|
|
|
|
pub fn destroy(self: *Pattern) void {
|
|
c.FcPatternDestroy(self.cval());
|
|
}
|
|
|
|
pub fn defaultSubstitute(self: *Pattern) void {
|
|
c.FcDefaultSubstitute(self.cval());
|
|
}
|
|
|
|
pub fn add(self: *Pattern, prop: Property, value: Value, append: bool) bool {
|
|
return c.FcPatternAdd(
|
|
self.cval(),
|
|
prop.cval().ptr,
|
|
value.cval(),
|
|
if (append) c.FcTrue else c.FcFalse,
|
|
) == c.FcTrue;
|
|
}
|
|
|
|
pub fn get(self: *Pattern, prop: Property, id: u32) Error!Value {
|
|
var val: c.struct__FcValue = undefined;
|
|
try @as(Result, @enumFromInt(c.FcPatternGet(
|
|
self.cval(),
|
|
prop.cval().ptr,
|
|
@intCast(id),
|
|
&val,
|
|
))).toError();
|
|
|
|
return Value.init(&val);
|
|
}
|
|
|
|
pub fn delete(self: *Pattern, prop: Property) bool {
|
|
return c.FcPatternDel(self.cval(), prop.cval()) == c.FcTrue;
|
|
}
|
|
|
|
pub fn filter(self: *Pattern, os: *const ObjectSet) *Pattern {
|
|
return @ptrCast(c.FcPatternFilter(self.cval(), os.cval()));
|
|
}
|
|
|
|
pub fn objectIterator(self: *Pattern) ObjectIterator {
|
|
return .{ .pat = self.cval(), .iter = null };
|
|
}
|
|
|
|
pub fn print(self: *Pattern) void {
|
|
c.FcPatternPrint(self.cval());
|
|
}
|
|
|
|
pub inline fn cval(self: *Pattern) *c.struct__FcPattern {
|
|
return @ptrCast(self);
|
|
}
|
|
|
|
pub const ObjectIterator = struct {
|
|
pat: *c.struct__FcPattern,
|
|
iter: ?c.struct__FcPatternIter,
|
|
|
|
/// Move to the next object, returns true if there is another
|
|
/// object and false otherwise. If this is the first call, this
|
|
/// will be the first object.
|
|
pub fn next(self: *ObjectIterator) bool {
|
|
// Null means our first iterator
|
|
if (self.iter == null) {
|
|
// If we have no objects, do not create iterator
|
|
if (c.FcPatternObjectCount(self.pat) == 0) return false;
|
|
|
|
var iter: c.struct__FcPatternIter = undefined;
|
|
c.FcPatternIterStart(
|
|
self.pat,
|
|
&iter,
|
|
);
|
|
assert(c.FcPatternIterIsValid(self.pat, &iter) == c.FcTrue);
|
|
self.iter = iter;
|
|
|
|
// Return right away because the fontconfig iterator pattern
|
|
// is do/while.
|
|
return true;
|
|
}
|
|
|
|
return c.FcPatternIterNext(self.pat, @ptrCast(&self.iter)) == c.FcTrue;
|
|
}
|
|
|
|
pub fn object(self: *ObjectIterator) []const u8 {
|
|
return std.mem.sliceTo(c.FcPatternIterGetObject(
|
|
self.pat,
|
|
&self.iter.?,
|
|
), 0);
|
|
}
|
|
|
|
pub fn valueLen(self: *ObjectIterator) usize {
|
|
return @intCast(c.FcPatternIterValueCount(self.pat, &self.iter.?));
|
|
}
|
|
|
|
pub fn valueIterator(self: *ObjectIterator) ValueIterator {
|
|
return .{
|
|
.pat = self.pat,
|
|
.iter = &self.iter.?,
|
|
.max = c.FcPatternIterValueCount(self.pat, &self.iter.?),
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const ValueIterator = struct {
|
|
pat: *c.struct__FcPattern,
|
|
iter: *c.struct__FcPatternIter,
|
|
max: c_int,
|
|
id: c_int = 0,
|
|
|
|
pub const Entry = struct {
|
|
result: Result,
|
|
value: Value,
|
|
binding: ValueBinding,
|
|
};
|
|
|
|
pub fn next(self: *ValueIterator) ?Entry {
|
|
if (self.id >= self.max) return null;
|
|
var value: c.struct__FcValue = undefined;
|
|
var binding: c.FcValueBinding = undefined;
|
|
const result = c.FcPatternIterGetValue(self.pat, self.iter, self.id, &value, &binding);
|
|
self.id += 1;
|
|
|
|
return Entry{
|
|
.result = @enumFromInt(result),
|
|
.binding = @enumFromInt(binding),
|
|
.value = Value.init(&value),
|
|
};
|
|
}
|
|
};
|
|
};
|
|
|
|
test "create" {
|
|
const testing = std.testing;
|
|
|
|
var pat = Pattern.create();
|
|
defer pat.destroy();
|
|
|
|
try testing.expect(pat.add(.family, .{ .string = "monospace" }, false));
|
|
try testing.expect(pat.add(.weight, .{ .integer = @intFromEnum(Weight.bold) }, false));
|
|
|
|
{
|
|
const val = try pat.get(.family, 0);
|
|
try testing.expect(val == .string);
|
|
try testing.expectEqualStrings("monospace", val.string);
|
|
}
|
|
}
|
|
|
|
test "name parse" {
|
|
var pat = Pattern.parse(":monospace");
|
|
defer pat.destroy();
|
|
|
|
pat.defaultSubstitute();
|
|
}
|