diff --git a/kitty/screen.c b/kitty/screen.c index a10b46cb0..9a97f71f8 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -674,6 +674,7 @@ draw_combining_char(Screen *self, text_loop_state *s, char_type ch) { if (has_prev_char) { CPUCell *cp; GPUCell *gp; linebuf_init_cells(self->linebuf, ypos, &cp, &gp); + if (xpos > 0 && gp[xpos].attrs.width == 0 && gp[xpos-1].attrs.width == 2) xpos--; bool added = line_add_combining_char(cp, gp, self->text_cache, self->lc, ch, xpos); unsigned base_pos = self->lc->count - (added ? 2 : 1); if (ch == VS16) { // emoji presentation variation marker makes default text presentation emoji (narrow emoji) into wide emoji diff --git a/kitty_tests/screen.py b/kitty_tests/screen.py index 3b3bcbe1a..1a18d918f 100644 --- a/kitty_tests/screen.py +++ b/kitty_tests/screen.py @@ -657,6 +657,7 @@ class TestScreen(BaseTest): self.ae(s.text_for_selection(), ('abc ', 'xy')) self.ae(s.text_for_selection(True), ('a\x1b[32mb\x1b[39mc ', 'xy', '\x1b[m')) self.ae(s.text_for_selection(True, True), ('a\x1b[32mb\x1b[39mc', 'xy', '\x1b[m')) + # ]]]]]]]]]]]]]]]]]]]] def test_soft_hyphen(self): s = self.create_screen() @@ -668,17 +669,24 @@ class TestScreen(BaseTest): def test_variation_selectors(self): s = self.create_screen() - s.draw('\U0001f610') - self.ae(s.cursor.x, 2) - s.carriage_return(), s.linefeed() - s.draw('\U0001f610\ufe0e') - self.ae(s.cursor.x, 1) - s.carriage_return(), s.linefeed() - s.draw('\u25b6') - self.ae(s.cursor.x, 1) - s.carriage_return(), s.linefeed() - s.draw('\u25b6\ufe0f') - self.ae(s.cursor.x, 2) + def t(*a): + s.reset() + for i in range(0, len(a), 2): + char, x = a[i], a[i+1] + s.draw(char) + self.ae(s.cursor.x, x, f'after char: {char!r}') + # already wide + VS15 + t('\U0001f610', 2, '\ufe0e', 1, '\ufe0e', 1) + t('\U0001f610\ufe0e', 1, '\ufe0e', 1) + # narrow + VS16 + t('\u25b6', 1, '\ufe0f', 2) + t('\u25b6\ufe0f', 2) + # wide + VS16 + t('\u26d4\ufe0f', 2, '\ufe0f', 2) + t('\u26d4', 2, '\ufe0f', 2) + # narrow + VS15 + t('\u25b6', 1, '\ufe0e', 1) + t('\u25b6\ufe0e', 1) def test_writing_with_cursor_on_trailer_of_wide_character(self): s = self.create_screen()