diff --git a/pkg/macos/foundation.zig b/pkg/macos/foundation.zig index 309da9675..3471c1757 100644 --- a/pkg/macos/foundation.zig +++ b/pkg/macos/foundation.zig @@ -1,5 +1,6 @@ pub const c = @import("foundation/c.zig"); pub usingnamespace @import("foundation/array.zig"); +pub usingnamespace @import("foundation/attributed_string.zig"); pub usingnamespace @import("foundation/base.zig"); pub usingnamespace @import("foundation/data.zig"); pub usingnamespace @import("foundation/dictionary.zig"); diff --git a/pkg/macos/foundation/attributed_string.zig b/pkg/macos/foundation/attributed_string.zig new file mode 100644 index 000000000..1194924af --- /dev/null +++ b/pkg/macos/foundation/attributed_string.zig @@ -0,0 +1,72 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const foundation = @import("../foundation.zig"); +const text = @import("../text.zig"); +const c = @import("c.zig"); + +pub const MutableAttributedString = opaque { + pub fn create(cap: usize) Allocator.Error!*MutableAttributedString { + return @intToPtr( + ?*MutableAttributedString, + @ptrToInt(c.CFAttributedStringCreateMutable( + null, + @intCast(c.CFIndex, cap), + )), + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn release(self: *MutableAttributedString) void { + foundation.CFRelease(self); + } + + pub fn replaceString( + self: *MutableAttributedString, + range: foundation.Range, + replacement: *foundation.String, + ) void { + c.CFAttributedStringReplaceString( + @ptrCast(c.CFMutableAttributedStringRef, self), + range.cval(), + @ptrCast(c.CFStringRef, replacement), + ); + } + + pub fn setAttribute( + self: *MutableAttributedString, + range: foundation.Range, + key: anytype, + value: ?*anyopaque, + ) void { + const T = @TypeOf(key); + const info = @typeInfo(T); + const Key = if (info != .Pointer) T else info.Pointer.child; + const key_arg = if (@hasDecl(Key, "key")) + key.key() + else + key; + + c.CFAttributedStringSetAttribute( + @ptrCast(c.CFMutableAttributedStringRef, self), + range.cval(), + @ptrCast(c.CFStringRef, key_arg), + value, + ); + } +}; + +test "mutable attributed string" { + //const testing = std.testing; + + const str = try MutableAttributedString.create(0); + defer str.release(); + + { + const rep = try foundation.String.createWithBytes("hello", .utf8, false); + defer rep.release(); + str.replaceString(foundation.Range.init(0, 0), rep); + } + + str.setAttribute(foundation.Range.init(0, 0), text.FontAttribute.url, null); + str.setAttribute(foundation.Range.init(0, 0), text.FontAttribute.name.key(), null); +} diff --git a/pkg/macos/foundation/base.zig b/pkg/macos/foundation/base.zig index b48d6df38..1b8f75661 100644 --- a/pkg/macos/foundation/base.zig +++ b/pkg/macos/foundation/base.zig @@ -1,5 +1,20 @@ +const c = @import("c.zig"); + pub const ComparisonResult = enum(c_int) { less = -1, equal = 0, greater = 1, }; + +pub const Range = extern struct { + location: c.CFIndex, + length: c.CFIndex, + + pub fn init(loc: usize, len: usize) Range { + return @bitCast(Range, c.CFRangeMake(@intCast(c_long, loc), @intCast(c_long, len))); + } + + pub fn cval(self: Range) c.CFRange { + return @bitCast(c.CFRange, self); + } +};