utf8: count Thai spacing marks in widths (#1413)

Thai SARA AM occupies an additional cell within a grapheme. Count
positive-width spacing marks to keep output coordinates aligned with
terminals.

Fix #479
This commit is contained in:
Simon Klee
2026-08-23 09:52:44 +02:00
committed by GitHub
parent 2ba1c36cba
commit a6d993da72
2 changed files with 10 additions and 2 deletions
+7 -2
View File
@@ -4028,9 +4028,14 @@ test "Thai: mixed Thai and emoji" {
try testing.expectEqual(@as(u32, 11), utf8.calculateTextWidth(text, 4, false, .unicode));
}
test "Thai: คำว่า width should be 3" {
test "Thai: คำว่า width should be 4" {
const text = "คำว่า";
try testing.expectEqual(@as(u32, 3), utf8.calculateTextWidth(text, 4, false, .unicode));
try testing.expectEqual(@as(u32, 4), utf8.calculateTextWidth(text, 4, false, .unicode));
}
test "Thai: น้ำ width should be 2" {
const text = "น้ำ";
try testing.expectEqual(@as(u32, 2), utf8.calculateTextWidth(text, 4, false, .unicode));
}
test "Thai: ว่ width should be 1" {
+3
View File
@@ -853,6 +853,7 @@ const GraphemeWidthState = struct {
const gc = uucode.get(.general_category, cp);
const is_virama = gc == .mark_nonspacing;
const is_spacing_mark = uucode.get(.grapheme_break, cp) == .spacing_mark;
const is_devanagari_ra = (cp == 0x0930);
@@ -877,6 +878,8 @@ const GraphemeWidthState = struct {
} else if (!self.has_width and cp_width > 0) {
self.width = cp_width;
self.has_width = true;
} else if (self.has_width and is_spacing_mark and cp_width > 0) {
self.width = @max(self.width, 2);
} else if (self.has_width and self.has_indic_virama and is_devanagari_base and cp_width > 0) {
if (!is_devanagari_ra) {
self.width += cp_width;