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
committed by Nicholas Marriott
parent aa1f0653e9
commit cc87db74c7
2 changed files with 25 additions and 1 deletions

2
tty.c
View File

@@ -2051,6 +2051,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_off(tty); 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_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette, 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); 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? */ /* Should these two characters combine? */
int int
utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add) 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); return (0);
/* Regional indicators. */ /* 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); return (1);
}
/* Emoji skin tone modifiers. */ /* Emoji skin tone modifiers. */
switch (a) { switch (a) {