1

Sometimes a font or a font at a special fontsize does not support a unicode glyph. Then a placeholder (box with character number) is printed, see screenshot with selected line:
enter image description here

How can I programmatically detect such unicode glyphs from within Emacs with elisp?
I intend to overlay|replace them with a printable representation.

I could change general fontset, but this is not an option.

Edit: what-cursor-position states that:

display: no font available

But I can't decode from the source, how it detects that.

1 Answer 1

2

How about this:

char-displayable-p is an autoloaded compiled Lisp function in `mule-util.el'.

(char-displayable-p CHAR)

Return non-nil if we should be able to display CHAR. On a multi-font display, the test is only whether there is an appropriate font from the selected frame's fontset to display CHAR's charset in general. Since fonts may be specified on a per-character basis, this may not be accurate.


Add-on by user Tobias:

The manual says that char-displayable-p would return t if the character is displayable with selected frame's fontset:

— Function: char-displayable-p char

This function returns t if Emacs ought to be able to display char. More precisely, if the selected frame's fontset has a font to display the character set that char belongs to.

Fontsets can specify a font on a per-character basis; when the fontset does that, this function's value may not be accurate.

Tests and an analysis of the source code tell another story. Only the case of a graphical display is discussed in the following.
All fonts can display ASCII characters. There is a shortcut branch in char-displayable-p returning t for that case.
Otherwise, if the font for the default face has a glyph for representing CHAR that font is returned. That is the first component of the return value of internal-char-font. But, pityingly internal-char-font is for internal use only.
The real implementation of char-displayable-p in Emacs 26.1 interprets "displayable" a bit wider.
It may be that CHAR can be encoded by the current coding system (tested with encode-char), but the glyph for CHAR is missing in the font for the default face. In that case char-displayable-p returns the coding system and CHAR is represented by a square containing the code point.

For testing whether there is a glyph for CHAR in the font for the default face you could use the following test:

(or (< CHAR 128) (fontp (char-displayable-p CHAR)))

Side note:

If internal-char-font wasn't internal you could also simply use (internal-char-font nil CHAR).

Maybe internal-char-font is really an alternative since the return value of char-displayable-p is also not specified in the documentation of that function.

8
  • 1
    (char-displayable-p #xE01EF) results in unicode which means true, but this character is displayed with a placeholder only. (as (insert #xE01EF) proves.) Is there anything I'm doing wrong?
    – jue
    Apr 8, 2019 at 13:38
  • 2
    @jue unicode means the unicode box. If it representable by a font then a font object is returned. The right test is (fontp (char-displayable-p CHAR)).
    – Tobias
    Apr 8, 2019 at 14:05
  • Please consider adding @Tobias's info. This is a good Q&A.
    – Drew
    Apr 8, 2019 at 14:25
  • @Tobias can you add your info to the answer as an edit?
    – user12563
    Apr 8, 2019 at 16:24
  • @Tobias I did some more tests and the results where unexpected. Ascii a == 0x61: (char-displayable-p #x61) results in t which means fontp results in nil. So it looks like one have to distinguish between Ascii and Unicode before the test. Could this please be checked and then added to the answer?
    – jue
    Apr 8, 2019 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.