* lisp/international/mule.el (char-displayable-on-frame-p): New
function used to determine whether a character can be
meaningfully displayed on a given frame.
* doc/lispref/display.texi (Fontsets): Document it.
* lisp/progmodes/prog-mode.el
(prettify-symbols--composition-displayable-p): New function used
to restrict to displayable prettification symbols. This
prevents issues with missing characters appearing as boxes.
(prettify-symbols--make-keywords): Use it. (Bug#77381)
(cherry picked from commit
2d0b5f34a008979d34f337c872bcf93a296c6ec2)
terminal can encode the character (@pxref{Terminal I/O Encoding}).
@end defun
+@defun char-displayable-on-frame-p char frame
+This function behaves like @code{char-displayable-p} does (relative to
+@var{frame}), but in the graphical case, it does not perform the final
+check of whether the underlying text terminal can encode the character.
+It thus provides a displayability check for @var{char} more specific to
+@var{frame}.
+@end defun
+
@node Low-Level Font
@subsection Low-Level Font Representation
@cindex font property
(throw 'tag3 charset)))
charset-list)
nil)))))))))))
+
+(defun char-displayable-on-frame-p (char &optional frame)
+ "Return non-nil if CHAR can be displayed in FRAME.
+FRAME nil means the selected frame.
+
+This function provides a stricter test than `char-displayable-p' does
+for determining if a character will display properly: in the graphical
+case, it does not check whether the underlying terminal can encode the
+character.
+
+Specifically, this function returns non-nil:
+
+- for a text terminal, if `char-displayable-p' returns non-nil.
+
+- for a graphical terminal, if `char-displayable-p' returns either t or
+ a font object.
+
+The two functions differ in behavior (i.e., `char-displayable-strict-p'
+returns nil but `char-displayable-p' does not) if the underlying
+terminal is graphical and can encode the character, but FRAME cannot."
+ (let ((display-capability (with-selected-frame (or frame (selected-frame))
+ (char-displayable-p char))))
+ (if (display-graphic-p frame)
+ (or (eq display-capability t)
+ (fontp display-capability))
+ display-capability)))
\f
;; Save the ASCII case table in case we need it later. Some locales
;; (such as Turkish) modify the case behavior of ASCII characters,
;; Return nil because we're not adding any face property.
nil)
+(defun prettify-symbols--composition-displayable-p (composition)
+ "Return non-nil if COMPOSITION can be displayed with the current fonts.
+COMPOSITION can be a single character, a string, or a sequence (vector or
+list) of characters and composition rules as described in the documentation
+of `prettify-symbols-alist' and `compose-region'."
+ (cond
+ ((characterp composition)
+ (char-displayable-on-frame-p composition))
+ ((stringp composition)
+ (seq-every-p #'char-displayable-on-frame-p composition))
+ ((seqp composition)
+ ;; check that every even-indexed element is displayable
+ (seq-every-p
+ (lambda (idx-elt)
+ (if (evenp (car idx-elt))
+ (char-displayable-on-frame-p (cdr idx-elt))
+ t))
+ (seq-map-indexed #'cons composition)))
+ (t
+ ;; silently ignore invalid compositions
+ t)))
+
(defun prettify-symbols--make-keywords ()
(if prettify-symbols-alist
- `((,(regexp-opt (mapcar 'car prettify-symbols-alist) t)
- (0 (prettify-symbols--compose-symbol ',prettify-symbols-alist))))
+ (let ((filtered-alist
+ (seq-filter
+ (lambda (elt)
+ (prettify-symbols--composition-displayable-p (cdr elt)))
+ prettify-symbols-alist)))
+ `((,(regexp-opt (mapcar 'car filtered-alist) t)
+ (0 (prettify-symbols--compose-symbol ',filtered-alist)))))
nil))
(defvar-local prettify-symbols--keywords nil)