diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-16 23:28:05 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-16 23:29:28 +0300 |
| commit | 4a3302d19a2baa3a33e910e0088c24e780905b90 (patch) | |
| tree | dcaf76fae1c82102d933c9225b17ca7ac5d3a847 /vendor/libghostty-vt/src/terminal/c/unicode.zig | |
| parent | 550e9f8cc085f428429f5cf2da0bb2dba897e8b8 (diff) | |
chore: update vendored libghostty-vt
refs #276
Diffstat (limited to 'vendor/libghostty-vt/src/terminal/c/unicode.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/terminal/c/unicode.zig | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/terminal/c/unicode.zig b/vendor/libghostty-vt/src/terminal/c/unicode.zig new file mode 100644 index 00000000..14451338 --- /dev/null +++ b/vendor/libghostty-vt/src/terminal/c/unicode.zig @@ -0,0 +1,85 @@ +const std = @import("std"); +const lib = @import("../lib.zig"); +const unicode_pkg = @import("../../unicode/main.zig"); + +pub fn codepoint_width(cp: u32) callconv(lib.calling_conv) u8 { + if (cp > 0x10FFFF) return 1; + return unicode_pkg.codepointWidth(@intCast(cp)); +} + +pub fn grapheme_width( + cps: ?[*]const u32, + len: usize, + width: ?*u8, +) callconv(lib.calling_conv) usize { + if (len == 0) { + if (width) |ptr| ptr.* = 0; + return 0; + } + + const ptr = cps orelse { + if (width) |out| out.* = 0; + return 0; + }; + const result = unicode_pkg.graphemeWidth(u32, ptr[0..len]); + if (width) |out| out.* = result.width; + return result.len; +} + +test "codepoint_width narrow" { + const testing = std.testing; + try testing.expectEqual(1, codepoint_width('a')); +} + +test "codepoint_width wide" { + const testing = std.testing; + try testing.expectEqual(2, codepoint_width(0x4E00)); +} + +test "codepoint_width zero" { + const testing = std.testing; + try testing.expectEqual(0, codepoint_width(0x0301)); +} + +test "codepoint_width out of range" { + const testing = std.testing; + try testing.expectEqual(1, codepoint_width(0x110000)); + try testing.expectEqual(1, codepoint_width(std.math.maxInt(u32))); +} + +test "grapheme_width empty" { + const testing = std.testing; + + var width: u8 = 42; + try testing.expectEqual(@as(usize, 0), grapheme_width(null, 0, &width)); + try testing.expectEqual(@as(u8, 0), width); +} + +test "grapheme_width null width" { + const testing = std.testing; + + const cps = [_]u32{ 0x2764, 0xFE0F }; + try testing.expectEqual(@as(usize, 2), grapheme_width(cps[0..].ptr, cps.len, null)); +} + +test "grapheme_width out of range" { + const testing = std.testing; + + var width: u8 = 0; + const invalid_first = [_]u32{ 0x110000, 0x0301 }; + try testing.expectEqual(@as(usize, 1), grapheme_width(invalid_first[0..].ptr, invalid_first.len, &width)); + try testing.expectEqual(@as(u8, 1), width); + + const invalid_second = [_]u32{ 'a', 0x110000 }; + try testing.expectEqual(@as(usize, 1), grapheme_width(invalid_second[0..].ptr, invalid_second.len, &width)); + try testing.expectEqual(@as(u8, 1), width); +} + +test "grapheme_width emoji sequence" { + const testing = std.testing; + + var width: u8 = 0; + const cps = [_]u32{ 0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F467 }; + try testing.expectEqual(@as(usize, cps.len), grapheme_width(cps[0..].ptr, cps.len, &width)); + try testing.expectEqual(@as(u8, 2), width); +} |
