Re: [PATCH] emoji on TUI emacs
Kai Ma <[email protected]> Fri, 31 Jul 2026 11:23:37 +0200
| Newsgroups | gmane.emacs.devel |
|---|---|
| Message-ID | <[email protected]> |
On 7/31/2026 9:22 AM, Eli Zaretskii wrote: >>>> Previous discussions are usually about the width of a grapheme >>>> cluster. But to my surprise, I found that the problem occurs even if >>>> the width is correct. For example, ⚡ (#x26a1) composed with #fe0f >>>> has width 2, >>>> >>>> (string-width "\x26a1\xfe0f") ;; ==> 2 >>> Yes, Emoji sequences which end in Variation Selector controls are one >>> of a couple of cases which currently cannot be correctly displayed on >>> text-only frames when auto-composition-mode is enabled. Please try >>> disabling auto-composition-mode. >> That's why I think there's something wrong with the current handling of >> the composition. > Not generally with compositions, but specifically with Emoji sequences > that have VS controls or several Emoji codepoints that the terminal > shows as a single glyph. The composite glyph is not only about emoji, (though personally my only use is emoji). E.g. CJK characters can be composed as well: CJK Ideographic Variation Selector: "龜\xE0100" "龜\xE0103" (auto composed, width = 2, which is correct) Korean Jamo: "\x1100\x1161\x11A8" (auto composed, width = 2, which is correct) There are some cases that are not auto composed by emacs as well, (though I think they should): CJK tone modifier: "一\x302A" (width = 4, should be 2) Ainu katakana: "\x31F7\x309A" (width = 4, should be 2) >> I'm talking about the composition. The impression I got from previous >> discussions and etc/PROBLEMS are that the problem is *solely* about >> width calculation. That is not true! > Not IME, no. The only problem I'm aware of is due to a mismatch > between the width of the composed Emoji as Emacs computes it and the > width the terminal actually draws on display. (See below since they have the same width.) > What do you see if you insert only "\x26a1" ? It has the same width. \x26a1 without \xfe0f is displayed and rendered correctly. > And yet when '⚡', i.e. the single codepoint #x26a1, is displayed, > there are no display problems and no artifacts, the cursor is shown in > double width, and the cursor motion works correctly. I tested this on > 2 different systems (GNU/Linux and Windows) and with 2 different > terminal emulators. Do you see something different? If this simpler > case works for you, how do you explain it? Yes, this case works for me and this is one of the observations that lead me to the append_composite_glyph in the first place. (And disabling auto-composition-mode wouldn't work if this is incorrect.) My understanding of the implementation is that, if a CHAR_GLYPH has pixel_width > 1, append_glyph in term.c will add padding glyphs to make room in the glyph matrix. So the proposed patch makes append_composite_glyph do the same thing as append_glyph. > The problem is with the value of N. How can Emacs know what is the > width N of a composed sequence of codepoints? It's the terminal > emulator that decides how to display them and with what font glyphs, > and Emacs has no access to that information when it displays on a > text-only terminal. On GUI frames, we access the font information and > determine the metrics of the glyphs that are displayed as result of > the composition, but on text-only frames we cannot do that. > > Try the Emoji sequence "\x1faf6\x1f3fc", for example. On terminals > that support Emoji, it displays as a single glyph whose width is 2, > but Emacs thinks there are 2 separate glyphs there whose combined > pixel_width is 2 + 2 = 4. And sure enough, (string-width "\x1faf6\x1f3fc") > returns 4 on a text-only frame, because Emacs doesn't think these two > codepoints will be combined into one on display. How do you suggest > to resolve these problems? The proposed patch does not fix this problem, and I think this is orthogonal to the width calculation. That's why I mentioned the case of correct widths. My analysis of the situation is that there are two problems. One is the width calculation, and another is the rendering of composite glyphs. Both problems are not emoji-specific. I haven't looked into the first problem at the moment, because fixing the second one alone makes emacs good enough for me for most cases. I can spend some time improving that part later. >> Do you have other acceptable alternative solutions in mind? > Not at the moment, no. But I'm open to ideas. For example, we could > perhaps do better for Emoji sequences whose first codepoint has a > width of 2, by adding a padding glyphs. But that's a partial solution > in any case. And adding padding glyphs according to pixel_width of a > composite glyph is incorrect in general, because on text-mode frames > that value is in many cases incorrect. I'm following the case of append_glyph. Does it mean CHAR_GLYPHs always have pixel_width no more than 2? If so, do you think it's acceptable to add only one padding glyph? That could bring it closer to append_glyph. add_one_composite_glyph(); if (pixel_width >= 2) add_one_padding_glyph(); nglyphs = 1 + (pixel_width >= 2); I tested this approach just now and it does feel like an improvement.