aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/libghostty-vt/src/simd/codepoint_width.zig
diff options
context:
space:
mode:
authorsl0p <sl0p@sl0p.foo>2026-08-13 22:00:03 +0200
committersl0p <sl0p@sl0p.foo>2026-08-13 22:00:03 +0200
commit2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8 (patch)
tree7cd6274303ba1da1f8bd57371aec336dd687fb58 /vendor/libghostty-vt/src/simd/codepoint_width.zig
downloadslosh-2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8.tar.gz
slosh-2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8.tar.xz
slosh-2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8.zip
sl0ptty: M0 — libghostty-vt vendored, one pane, compositor, diff renderer
Design contract in DESIGN.md. libghostty-vt vendored fresh from ghostty main@bedb6f2 (zig 0.16), built to a 14MB static lib. M0: pty spawn (no libutil), a lib-vt terminal per pane, a screen cell buffer, a diff emitter that repaints only what changed, raw mode, SIGWINCH, and a ~120Hz frame cap that coalesces pty reads. Also the seed of the headless harness: --headless dumps the composited screen without a tty, so composition is testable in milliseconds. tests/live_m0.py covers what headless cannot: raw mode, the diff emitter, resize propagation, and the quit path. 6/6 green.
Diffstat (limited to 'vendor/libghostty-vt/src/simd/codepoint_width.zig')
-rw-r--r--vendor/libghostty-vt/src/simd/codepoint_width.zig52
1 files changed, 52 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/simd/codepoint_width.zig b/vendor/libghostty-vt/src/simd/codepoint_width.zig
new file mode 100644
index 0000000..c1767be
--- /dev/null
+++ b/vendor/libghostty-vt/src/simd/codepoint_width.zig
@@ -0,0 +1,52 @@
+const std = @import("std");
+const options = @import("build_options");
+
+// vt.cpp
+extern "c" fn ghostty_simd_codepoint_width(u32) i8;
+
+pub fn codepointWidth(cp: u32) i8 {
+ if (comptime options.simd) return ghostty_simd_codepoint_width(cp);
+ const uucode = @import("uucode");
+ if (cp > uucode.config.max_code_point) return 1;
+ return @import("uucode").get(.width, @intCast(cp));
+}
+
+test "codepointWidth basic" {
+ const testing = std.testing;
+ try testing.expectEqual(@as(i8, 1), codepointWidth('a'));
+ try testing.expectEqual(@as(i8, 1), codepointWidth(0x100)); // Ā
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0x3400)); // 㐀
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0x2E3A)); // ⸺
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0x1F1E6)); // 🇦
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0x4E00)); // 一
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0xF900)); // 豈
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0x20000)); // 𠀀
+ try testing.expectEqual(@as(i8, 2), codepointWidth(0x30000)); // 𠀀
+ // try testing.expectEqual(@as(i8, 1), @import("uucode").get(.width, 0x100));
+}
+
+// This is not very fast in debug modes, so its commented by default.
+// IMPORTANT: UNCOMMENT THIS WHENEVER MAKING CODEPOINTWIDTH CHANGES.
+// test "codepointWidth matches uucode" {
+// const testing = std.testing;
+// const uucode = @import("uucode");
+//
+// const min = 0xFF + 1; // start outside ascii
+// const max = std.math.maxInt(u21) + 1;
+// for (min..max) |cp| {
+// const simd = codepointWidth(@intCast(cp));
+// const uu = if (cp > uucode.config.max_code_point)
+// 1
+// else
+// uucode.get(.width, @intCast(cp));
+// if (simd != uu) mismatch: {
+// if (cp == 0x2E3B) {
+// try testing.expectEqual(@as(i8, 2), simd);
+// break :mismatch;
+// }
+//
+// std.log.warn("mismatch cp=U+{x} simd={} uucode={}", .{ cp, simd, uu });
+// try testing.expect(false);
+// }
+// }
+// }