From 56aa52c346d5317a9f228ca12d52d4c860c458b0 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 27 Aug 2022 11:56:00 +0300 Subject: [PATCH] Support "replacement characters" on TTY frames * src/nsterm.m (ns_draw_glyphless_glyph_string_foreground): * src/pgtkterm.c (pgtk_draw_glyphless_glyph_string_foreground): * src/haikuterm.c (haiku_draw_glyphless_glyph_string_foreground): * src/xterm.c (x_draw_glyphless_glyph_string_foreground): * src/w32term.c (w32_draw_glyphless_glyph_string_foreground): * src/xdisp.c (lookup_glyphless_char_display): Handle extra-slot of 'glyphless-char-display' that is a cons cell. (syms_of_xdisp) : Update doc string. * etc/NEWS: * doc/lispref/display.texi (Glyphless Chars): Document the new feature. * lisp/faces.el (glyphless-char): Make the face stand out on TTY frames that don't support the underline attribute. --- doc/lispref/display.texi | 6 +++++- etc/NEWS | 17 +++++++++++++++-- lisp/faces.el | 2 +- src/haikuterm.c | 2 ++ src/nsterm.m | 2 ++ src/pgtkterm.c | 2 ++ src/term.c | 22 +++++++++++++++++----- src/w32term.c | 2 ++ src/xdisp.c | 17 +++++++++-------- src/xterm.c | 2 ++ 10 files changed, 57 insertions(+), 17 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index bb2b2d98a36..a56f467e0b5 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -8542,7 +8542,11 @@ hexadecimal notation. @item an @acronym{ASCII} string Display a box containing that string. The string should contain at -most 6 @acronym{ASCII} characters. +most 6 @acronym{ASCII} characters. As an exception, if the string +includes just one character, on text-mode terminals that character +will be displayed without a box; this allows to handle such +``acronyms'' as a replacement character for characters that cannot be +displayed by the terminal. @item a cons cell @code{(@var{graphical} . @var{text})} Display with @var{graphical} on graphical displays, and with diff --git a/etc/NEWS b/etc/NEWS index 9eeab7bb9a2..a2537235eba 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1512,7 +1512,7 @@ non-nil, the text will now be added to the Isearch instead. *** Changes for values 'no' and 'no-ding' of 'isearch-wrap-pause'. Now with these values the search will wrap around not only on repeating with 'C-s C-s', but also after typing a character. - +1 +++ *** New user option 'char-fold-override'. Non-nil means that the default definitions of equivalent characters @@ -1525,11 +1525,24 @@ command accepts the Unicode name of an Emoji (for example, "smiling face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer completion, and adds the Emoji into the search string. +** Glyphless characters + +++ -** New minor mode 'glyphless-display-mode'. +*** New minor mode 'glyphless-display-mode'. This allows an easy way to toggle seeing all glyphless characters in the current buffer. +*** The extra slot of 'glyphless-char-display' can now have cons values. +The extra slot of the 'glyphless-char-display' char-table can now have +values that are cons cells, specifying separate values for text-mode +and GUI terminals. + +*** "Replacement character" feature for undisplayable characters on TTYs. +The 'acronym' method of displaying glyphless characters on text-mode +frames treats single-character acronyms specially: they are displayed +without the surrounding [..] "box", thus in effect treating such +"acronyms" as replacement characters. + ** Registers +++ diff --git a/lisp/faces.el b/lisp/faces.el index 0246e038dd4..336078b0403 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -2978,7 +2978,7 @@ bindings. See also the face `tooltip'." :group 'help) (defface glyphless-char - '((((type tty)) :inherit underline) + '((((type tty)) :inherit escape-glyph :underline t) (((type pc)) :inherit escape-glyph) (t :height 0.6)) "Face for displaying non-graphic characters (e.g. U+202A (LRE)). diff --git a/src/haikuterm.c b/src/haikuterm.c index c2d4e34ba25..df1c39974f8 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1252,6 +1252,8 @@ haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s) ? CHAR_TABLE_REF (Vglyphless_char_display, glyph->u.glyphless.ch) : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + if (CONSP (acronym)) + acronym = XCAR (acronym); if (STRINGP (acronym)) str = SSDATA (acronym); } diff --git a/src/nsterm.m b/src/nsterm.m index e3f47eb905e..6c6151701b8 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4241,6 +4241,8 @@ Function modeled after x_draw_glyph_string_box (). ? CHAR_TABLE_REF (Vglyphless_char_display, glyph->u.glyphless.ch) : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + if (CONSP (acronym)) + acronym = XCAR (acronym); if (STRINGP (acronym)) str = SSDATA (acronym); } diff --git a/src/pgtkterm.c b/src/pgtkterm.c index b283cef7cde..491ba338821 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1584,6 +1584,8 @@ pgtk_draw_glyphless_glyph_string_foreground (struct glyph_string *s) ? CHAR_TABLE_REF (Vglyphless_char_display, glyph->u.glyphless.ch) : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + if (CONSP (acronym)) + acronym = XCAR (acronym); if (STRINGP (acronym)) str = SSDATA (acronym); } diff --git a/src/term.c b/src/term.c index 3bea621dbda..2e43d89232f 100644 --- a/src/term.c +++ b/src/term.c @@ -1862,12 +1862,24 @@ produce_glyphless_glyph (struct it *it, Lisp_Object acronym) acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c); if (CONSP (acronym)) acronym = XCDR (acronym); - buf[0] = '['; str = STRINGP (acronym) ? SSDATA (acronym) : ""; - for (len = 0; len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++) - buf[1 + len] = str[len]; - buf[1 + len] = ']'; - len += 2; + /* A special kludgey feature for single-character acronyms: + don't put them in a box, effectively treating them as a + replacement character. */ + if (STRINGP (acronym) && SCHARS (acronym) == 1) + { + buf[0] = str[0]; + len = 1; + } + else + { + buf[0] = '['; + for (len = 0; + len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++) + buf[1 + len] = str[len]; + buf[1 + len] = ']'; + len += 2; + } } else { diff --git a/src/w32term.c b/src/w32term.c index d0577efccc1..dff21489e5b 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -1490,6 +1490,8 @@ w32_draw_glyphless_glyph_string_foreground (struct glyph_string *s) ? CHAR_TABLE_REF (Vglyphless_char_display, glyph->u.glyphless.ch) : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + if (CONSP (acronym)) + acronym = XCAR (acronym); if (STRINGP (acronym)) str = SSDATA (acronym); } diff --git a/src/xdisp.c b/src/xdisp.c index 86a119c0f63..70f6936dd0b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -7842,15 +7842,14 @@ lookup_glyphless_char_display (int c, struct it *it) && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1) { if (c >= 0) - { - glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c); - if (CONSP (glyphless_method)) - glyphless_method = FRAME_WINDOW_P (it->f) - ? XCAR (glyphless_method) - : XCDR (glyphless_method); - } + glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c); else glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0]; + + if (CONSP (glyphless_method)) + glyphless_method = FRAME_WINDOW_P (it->f) + ? XCAR (glyphless_method) + : XCDR (glyphless_method); } retry: @@ -37117,7 +37116,9 @@ GRAPHICAL and TEXT should each have one of the values listed above. The char-table has one extra slot to control the display of a character for which no font is found. This slot only takes effect on graphical terminals. Its value should be an ASCII acronym string, `hex-code', `empty-box', or -`thin-space'. The default is `empty-box'. +`thin-space'. It could also be a cons cell of any two of these, to specify +separate values for graphical and text terminals. +The default is `empty-box'. If a character has a non-nil entry in an active display table, the display table takes effect; in this case, Emacs does not consult diff --git a/src/xterm.c b/src/xterm.c index c716d07adaf..e7f55255021 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8316,6 +8316,8 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) ? CHAR_TABLE_REF (Vglyphless_char_display, glyph->u.glyphless.ch) : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + if (CONSP (acronym)) + acronym = XCAR (acronym); if (STRINGP (acronym)) str = SSDATA (acronym); }