term: insert-mode: handle combining characters correctly

When the client application emits combining characters, for example
multi-codepoint emojis, in insert-mode, we ended up pushing partial
graphemes to the right, for each codepoint, resulting in too many
cells (and with the wrong content) being inserted.

The fix is fairly simple; don't "insert" when appending characters to
an existing grapheme cluster.

This isn't something we can detect easily in print_insert() (it would
require us to do grapheme clustering again). Fortunately, we do have
the required information in action_utf8_print(). So, pass this
information as a boolean to term_print().

Closes #1947
This commit is contained in:
Daniel Eklöf 2025-02-06 07:31:30 +01:00
parent dd01783f88
commit 88dcde3ed8
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 14 additions and 6 deletions

4
vt.c
View file

@ -703,6 +703,7 @@ static void
action_utf8_print(struct terminal *term, char32_t wc)
{
int width = c32width(wc);
bool insert_mode_disable = false;
const bool grapheme_clustering = term->grapheme_shaping;
#if !defined(FOOT_GRAPHEME_CLUSTERING)
@ -757,6 +758,7 @@ action_utf8_print(struct terminal *term, char32_t wc)
if (base_width > 0) {
term->grid->cursor.point.col = col;
term->grid->cursor.lcf = false;
insert_mode_disable = true;
if (composed == NULL) {
bool base_from_primary;
@ -954,7 +956,7 @@ action_utf8_print(struct terminal *term, char32_t wc)
out:
if (width > 0)
term_print(term, wc, width);
term_print(term, wc, width, insert_mode_disable);
}
static void