From becc4f90684e4586790878166736b784378ab115 Mon Sep 17 00:00:00 2001 From: kofany Date: Wed, 10 Sep 2025 20:55:25 +0200 Subject: [PATCH] Fix emoji variation selector width calculation in string_advance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses issue where emoji with variation selectors (like ❣️, ♥️) were incorrectly calculated as width 1 instead of width 2, causing display overflow in modern terminals. - Add variation selector detection (0xFE0F) in string_advance_with_grapheme_support() - Apply special width handling for base emoji + variation selector combinations - Ensures consistent width calculation with input field processing - Fixes chat window overflow issues in terminals like Ghostty This brings string_advance logic in line with unichar_array_advance_cluster which already had proper variation selector handling. --- src/core/utf8.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/core/utf8.c b/src/core/utf8.c index ca841b4d..cdb272f5 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -42,6 +42,7 @@ static int string_advance_with_grapheme_support(char const **str, int policy) const char *start = *str; const char *pos = *str; int cluster_width = 0; + int has_variation_selector = 0; utf8proc_ssize_t bytes; if (policy != TREAT_STRING_AS_UTF8) { @@ -69,6 +70,11 @@ static int string_advance_with_grapheme_support(char const **str, int policy) break; } + /* Check for variation selector */ + if (codepoint == 0xFE0F) { + has_variation_selector = 1; + } + /* Add this codepoint's width to the cluster */ if (unichar_isprint(codepoint)) { int char_width = i_wcwidth(codepoint); @@ -81,6 +87,12 @@ static int string_advance_with_grapheme_support(char const **str, int policy) pos += bytes; } + /* Special handling for emoji with variation selector */ + if (has_variation_selector && cluster_width == 1) { + /* Base emoji (like ❣ U+2763, ♥ U+2665) + variation selector should have width 2 */ + cluster_width = 2; + } + *str = pos; return cluster_width > 0 ? cluster_width : 1; }