From 802f230fa2d2c879eeb7754e21080a86c956f2d1 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Sep 2022 10:35:22 -0700 Subject: [PATCH] handle graphemes with more than 1 joiner --- src/terminal/Screen.zig | 1 + src/terminal/Terminal.zig | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index d50c67d33..158b5b18c 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -1497,6 +1497,7 @@ pub fn testWriteString(self: *Screen, text: []const u8) !void { // Get our row var row = self.getRow(.{ .active = y }); + // If we have a previous cell, we check if we're part of a grapheme. if (grapheme.cell) |prev_cell| { const grapheme_break = brk: { var state: i32 = 0; diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index c5e7b6803..d42fb1d29 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -474,22 +474,21 @@ pub fn print(self: *Terminal, c: u21) !void { }; }; - var state: i32 = 0; - const grapheme_break = if (!prev.cell.attrs.grapheme) - utf8proc.graphemeBreakStateful(@intCast(u21, prev.cell.char), c, &state) - else brk: { - // We need to rebuild the state by processing the grapheme breaks - // for all the codepoints up to this point. This MUST exist because - // grapheme is only true iff this exists. - const points = self.screen.graphemes.getEntry(row.getId() + prev.x + 1).?; - const cp1 = switch (points.value_ptr.*) { - .one => |v| one: { - assert(!utf8proc.graphemeBreakStateful(@intCast(u21, prev.cell.char), v, &state)); - break :one v; - }, + const grapheme_break = brk: { + var state: i32 = 0; + var cp1 = @intCast(u21, prev.cell.char); + if (prev.cell.attrs.grapheme) { + var it = row.codepointIterator(prev.x); + while (it.next()) |cp2| { + assert(!utf8proc.graphemeBreakStateful( + cp1, + cp2, + &state, + )); - else => @panic("NO"), - }; + cp1 = cp2; + } + } break :brk utf8proc.graphemeBreakStateful(cp1, c, &state); };