Re: [PATCH] emoji on TUI emacs
Eli Zaretskii <[email protected]> Sun, 09 Aug 2026 08:07:17 +0300
| Newsgroups | gmane.emacs.devel |
|---|---|
| Message-ID | <[email protected]> |
> From: Kai Ma <[email protected]> > Cc: [email protected] > Date: Sat, 08 Aug 2026 20:48:33 +0200 > > string-width returns 2 after the patch for fully-matched composed emoji > sequences on tty terminals: > > (string-width (string #x2665)) ;; ==> 1 > (string-width (string #x2665 #xfe0f)) ;; ==> 2 > (string-width (string #x1f3f4 #x200d #x2620 #xfe0f)) > ;; ==> 2 > > And I can confirm org-table alignment works properly now. > > However, the column number change due to C-f, C-b, etc. is still the > total sum of CHARACTER_WIDTH (not necessarily 2). Do we want to change > it as well? Yes, definitely. current-column and move-to-column should both work correctly in these cases. > --- a/lisp/composite.el > +++ b/lisp/composite.el > @@ -899,11 +899,18 @@ auto-compose-chars > > This function is the default value of `auto-composition-function' (which see)." > (let ((gstring (composition-get-gstring from to font-object string))) > - (if (lgstring-shaped-p gstring) > - gstring > - (or (fontp font-object 'font-object) > - (setq func 'compose-gstring-for-terminal)) > - (funcall func gstring direction)))) > + (cond > + ((lgstring-shaped-p gstring) > + gstring) > + ((and (eq func #'compose-gstring-and-emoji) > + (fontp font-object 'font-object)) > + (compose-gstring-for-graphic gstring direction)) > + ((eq func #'compose-gstring-and-emoji) > + (compose-gstring-and-emoji gstring direction)) > + ((fontp font-object 'font-object) > + (funcall func gstring direction)) > + (t > + (compose-gstring-for-terminal gstring direction))))) I think the above logic could benefit from comments explaining why we dispatch the different cases as we do. > + DEFVAR_LISP ("auto-composition-emoji-tty-eligible-codepoints", Vauto_composition_emoji_tty_eligible_codepoints, > + doc: /* List of codepoints for which auto-composition will check for an emoji font on tty display. This line is too long. Our conventions are not to exceed 79 characters. I suggest to shorten it as follows: List of characters displayed as Emoji on TTY frames when followed by VS-16. > +These are codepoints which have Emoji_Presentation = No, and thus by > +default are not displayed as emoji. When followed by U+FE0F (VS-16), ^^^^^ > +they may be considered as the beginning of an emoji sequence instead. ^^^^^ "Emoji", capitalized. > +This list is auto-generated, you should not need to modify it. */); > + Vauto_composition_emoji_tty_eligible_codepoints = Qnil; > + > + DEFVAR_BOOL ("tty-display-emoji-force-wide", tty_display_emoji_force_wide, > + doc: /* Whether Emoji sequences on TTY frames should always be considered wide. > + > +When nil, emoji sequences whose first character's width is 1 may be ^^^^^ "Emoji" > +considered as a narrow glyph to be compatible with some non-compliant > +terminal emulators. */); > + tty_display_emoji_force_wide = true; I think these two variables are related (basically, the first one controls which sequences will be considered to be wide, right?). So I think they should each mention the other one. > @@ -379,9 +377,8 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, > chars = end - i; > bytes = string_char_to_byte (string, end) - i_byte; > } > -#ifdef HAVE_WINDOW_SYSTEM > else if (auto_comp > - && f && FRAME_WINDOW_P (f) > + && f > && multibyte > && find_automatic_composition (i, -1, i, &ignore, > &end, &val, string) > @@ -396,7 +393,7 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, > > /* The below is somewhat expensive, so compute it only once > for the entire loop, and only if needed. */ > - if (font_width < 0) > + if (FRAME_WINDOW_P (f) && font_width < 0) > { > font_width = FRAME_COLUMN_WIDTH (f); > default_font = Fface_font (Qdefault, Qnil, Qnil); > @@ -417,11 +414,13 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, > } > } > } > - thiswidth = (double) pixelwidth / font_width + 0.5; > + > + thiswidth = FRAME_WINDOW_P (f) > + ? ((double) pixelwidth / font_width + 0.5) > + : pixelwidth; > chars = end - i; > bytes = string_char_to_byte (string, end) - i_byte; > } > -#endif /* HAVE_WINDOW_SYSTEM */ > else > { > int c; This is not quite right: in an Emacs build --without-x some of the functions mentioned in the code fragment which was previously under HAVE_WINDOW_SYSTEM do not exist, so this will fail to link. What you need is to move the HAVE_WINDOW_SYSTEM condition inside this fragment, such that it is still in effect when functions like Ffont_info are called. I think the entire block which starts with if (font_width < 0) should be under the HAVE_WINDOW_SYSTEM condition, since it makes no sense on a TTY frame. Finally, I think these changes and the new variables warrant a NEWS entry. Thanks.