Two fixes for RI codepoints. Firstly, do not combine more than two of

them - previously we were ending up with four codepoints in one cell
which tmux believed to be width 2, but terminals considered width 4.
Secondly, invalidate cursor position before redrawing the cell when the
second codepoint is received, terminals vary in how they manage
backspace and cursor movement across these characters, so it is better
to use absolute rather than relative positioning. GitHub issue 4853.
This commit is contained in:
nicm
2026-06-09 11:49:36 +00:00
parent d5c9196348
commit a42e425d44
2 changed files with 25 additions and 1 deletions

2
tty.c
View File

@@ -1979,6 +1979,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_off(tty);
if (ctx->flags & TTY_CTX_CELL_INVALIDATE)
tty_invalidate(tty);
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,

View File

@@ -82,6 +82,23 @@ utf8_is_hangul_filler(const struct utf8_data *ud)
return (memcmp(ud->data, "\343\205\244", 3) == 0);
}
/* Count regional indicator characters. */
static u_int
utf8_regional_count(const struct utf8_data *ud)
{
u_int count = 0, i;
for (i = 0; i + 4 <= ud->size; i++) {
if (ud->data[i] == 0xf0 &&
ud->data[i + 1] == 0x9f &&
ud->data[i + 2] == 0x87 &&
ud->data[i + 3] >= 0xa6 &&
ud->data[i + 3] <= 0xbf)
count++;
}
return (count);
}
/* Should these two characters combine? */
int
utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add)
@@ -94,8 +111,13 @@ utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add)
return (0);
/* Regional indicators. */
if ((a >= 0x1F1E6 && a <= 0x1F1FF) && (w >= 0x1F1E6 && w <= 0x1F1FF))
if ((a >= 0x1F1E6 && a <= 0x1F1FF) && (w >= 0x1F1E6 && w <= 0x1F1FF)) {
if (utf8_regional_count(with) != 1)
return (0);
if (utf8_regional_count(add) != 1)
return (0);
return (1);
}
/* Emoji skin tone modifiers. */
switch (a) {