Mercurial > emacs
comparison lisp/nxml/nxml-mode.el @ 95598:8c4c0ca00399
nXML: Use font lock
author | Michael Olson <mwolson@gnu.org> |
---|---|
date | Fri, 06 Jun 2008 16:14:49 +0000 |
parents | d495d4d5452f |
children | 8b2ac128dd5b |
comparison
equal
deleted
inserted
replaced
95597:d89ef0f12bd4 | 95598:8c4c0ca00399 |
---|---|
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | 21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
22 | 22 |
23 ;;; Commentary: | 23 ;;; Commentary: |
24 | 24 |
25 ;; See nxml-rap.el for description of parsing strategy. | 25 ;; See nxml-rap.el for description of parsing strategy. |
26 | |
27 ;; The font locking here is independent of font-lock.el. We want to | |
28 ;; do more sophisticated handling of changes and we want to use the | |
29 ;; same xmltok rather than regexps for parsing so that we parse | |
30 ;; consistently and correctly. | |
31 | 26 |
32 ;;; Code: | 27 ;;; Code: |
33 | 28 |
34 (when (featurep 'mucs) | 29 (when (featurep 'mucs) |
35 (error "nxml-mode is not compatible with Mule-UCS")) | 30 (error "nxml-mode is not compatible with Mule-UCS")) |
53 | 48 |
54 (defgroup nxml-faces nil | 49 (defgroup nxml-faces nil |
55 "Faces for XML syntax highlighting." | 50 "Faces for XML syntax highlighting." |
56 :group 'nxml | 51 :group 'nxml |
57 :group 'font-lock-faces) | 52 :group 'font-lock-faces) |
58 | |
59 (defcustom nxml-syntax-highlight-flag t | |
60 "*Non-nil means nxml-mode should perform syntax highlighting." | |
61 :group 'nxml | |
62 :type 'boolean) | |
63 | 53 |
64 (defcustom nxml-char-ref-display-glyph-flag t | 54 (defcustom nxml-char-ref-display-glyph-flag t |
65 "*Non-nil means display glyph following character reference. | 55 "*Non-nil means display glyph following character reference. |
66 The glyph is displayed in face `nxml-glyph'. The hook | 56 The glyph is displayed in face `nxml-glyph'. The hook |
67 `nxml-glyph-set-hook' can be used to customize for which characters | 57 `nxml-glyph-set-hook' can be used to customize for which characters |
97 This only applies when the first attribute of a tag starts a line. In other | 87 This only applies when the first attribute of a tag starts a line. In other |
98 cases, the first attribute on one line is indented the same as the first | 88 cases, the first attribute on one line is indented the same as the first |
99 attribute on the previous line." | 89 attribute on the previous line." |
100 :group 'nxml | 90 :group 'nxml |
101 :type 'integer) | 91 :type 'integer) |
102 | |
103 (defvar nxml-fontify-chunk-size 500) | |
104 | 92 |
105 (defcustom nxml-bind-meta-tab-to-complete-flag (not window-system) | 93 (defcustom nxml-bind-meta-tab-to-complete-flag (not window-system) |
106 "*Non-nil means bind M-TAB in `nxml-mode-map' to `nxml-complete'. | 94 "*Non-nil means bind M-TAB in `nxml-mode-map' to `nxml-complete'. |
107 C-return will be bound to `nxml-complete' in any case. | 95 C-return will be bound to `nxml-complete' in any case. |
108 M-TAB gets swallowed by many window systems/managers, and | 96 M-TAB gets swallowed by many window systems/managers, and |
430 (when nxml-bind-meta-tab-to-complete-flag | 418 (when nxml-bind-meta-tab-to-complete-flag |
431 (define-key map "\M-\t" 'nxml-complete)) | 419 (define-key map "\M-\t" 'nxml-complete)) |
432 map) | 420 map) |
433 "Keymap for nxml-mode.") | 421 "Keymap for nxml-mode.") |
434 | 422 |
423 (defvar nxml-font-lock-keywords | |
424 '(nxml-fontify-matcher) | |
425 "Default font lock keywords for nxml-mode.") | |
426 | |
435 (defsubst nxml-set-face (start end face) | 427 (defsubst nxml-set-face (start end face) |
436 (when (and face (< start end)) | 428 (when (and face (< start end)) |
437 (put-text-property start end 'face face))) | 429 (font-lock-append-text-property start end 'face face))) |
438 | |
439 (defun nxml-clear-face (start end) | |
440 (remove-text-properties start end '(face nil)) | |
441 (nxml-clear-char-ref-extra-display start end)) | |
442 | |
443 (defsubst nxml-set-fontified (start end) | |
444 (put-text-property start end 'fontified t)) | |
445 | |
446 (defsubst nxml-clear-fontified (start end) | |
447 (remove-text-properties start end '(fontified nil))) | |
448 | 430 |
449 ;;;###autoload | 431 ;;;###autoload |
450 (defun nxml-mode () | 432 (defun nxml-mode () |
451 ;; We use C-c C-i instead of \\[nxml-balanced-close-start-tag-inline] | 433 ;; We use C-c C-i instead of \\[nxml-balanced-close-start-tag-inline] |
452 ;; because Emacs turns C-c C-i into C-c TAB which is hard to type and | 434 ;; because Emacs turns C-c C-i into C-c TAB which is hard to type and |
453 ;; not mnemonic. | 435 ;; not mnemonic. |
454 "Major mode for editing XML. | 436 "Major mode for editing XML. |
455 | |
456 Syntax highlighting is performed unless the variable | |
457 `nxml-syntax-highlight-flag' is nil. | |
458 | 437 |
459 \\[nxml-finish-element] finishes the current element by inserting an end-tag. | 438 \\[nxml-finish-element] finishes the current element by inserting an end-tag. |
460 C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag | 439 C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag |
461 leaving point between the start-tag and end-tag. | 440 leaving point between the start-tag and end-tag. |
462 \\[nxml-balanced-close-start-tag-block] is similar but for block rather than inline elements: | 441 \\[nxml-balanced-close-start-tag-block] is similar but for block rather than inline elements: |
538 (save-restriction | 517 (save-restriction |
539 (widen) | 518 (widen) |
540 (nxml-clear-dependent-regions (point-min) (point-max)) | 519 (nxml-clear-dependent-regions (point-min) (point-max)) |
541 (setq nxml-scan-end (copy-marker (point-min) nil)) | 520 (setq nxml-scan-end (copy-marker (point-min) nil)) |
542 (nxml-with-unmodifying-text-property-changes | 521 (nxml-with-unmodifying-text-property-changes |
543 (when nxml-syntax-highlight-flag | 522 (nxml-clear-inside (point-min) (point-max)) |
544 (nxml-clear-fontified (point-min) (point-max))) | |
545 (nxml-clear-inside (point-min) (point-max)) | |
546 (nxml-with-invisible-motion | 523 (nxml-with-invisible-motion |
547 (nxml-scan-prolog))))) | 524 (nxml-scan-prolog))))) |
548 (when nxml-syntax-highlight-flag | |
549 (add-hook 'fontification-functions 'nxml-fontify nil t)) | |
550 (add-hook 'after-change-functions 'nxml-after-change nil t) | 525 (add-hook 'after-change-functions 'nxml-after-change nil t) |
551 (add-hook 'change-major-mode-hook 'nxml-cleanup nil t) | 526 (add-hook 'change-major-mode-hook 'nxml-cleanup nil t) |
552 | 527 |
553 ;; Emacs 23 handles the encoding attribute on the xml declaration | 528 ;; Emacs 23 handles the encoding attribute on the xml declaration |
554 ;; transparently to nxml-mode, so there is no longer a need for the below | 529 ;; transparently to nxml-mode, so there is no longer a need for the below |
559 (when (and nxml-default-buffer-file-coding-system | 534 (when (and nxml-default-buffer-file-coding-system |
560 (not (local-variable-p 'buffer-file-coding-system))) | 535 (not (local-variable-p 'buffer-file-coding-system))) |
561 (setq buffer-file-coding-system nxml-default-buffer-file-coding-system)) | 536 (setq buffer-file-coding-system nxml-default-buffer-file-coding-system)) |
562 (when nxml-auto-insert-xml-declaration-flag | 537 (when nxml-auto-insert-xml-declaration-flag |
563 (nxml-insert-xml-declaration))) | 538 (nxml-insert-xml-declaration))) |
539 | |
540 (setq font-lock-defaults | |
541 '(nxml-font-lock-keywords | |
542 t ; keywords-only; we highlight comments and strings here | |
543 nil ; font-lock-keywords-case-fold-search. XML is case sensitive | |
544 nil ; no special syntax table | |
545 nil ; no automatic syntactic fontification | |
546 (font-lock-extend-after-change-region-function | |
547 . nxml-extend-after-change-region) | |
548 (font-lock-extend-region-functions . (nxml-extend-region)) | |
549 (jit-lock-contextually . t) | |
550 (font-lock-unfontify-region-function . nxml-unfontify-region))) | |
551 | |
564 (rng-nxml-mode-init) | 552 (rng-nxml-mode-init) |
565 (nxml-enable-unicode-char-name-sets) | 553 (nxml-enable-unicode-char-name-sets) |
566 (run-hooks 'nxml-mode-hook)) | 554 (run-hooks 'nxml-mode-hook)) |
567 | 555 |
568 (defun nxml-cleanup () | 556 (defun nxml-cleanup () |
589 (setq nxml-prolog-end 1) | 577 (setq nxml-prolog-end 1) |
590 (save-excursion | 578 (save-excursion |
591 (save-restriction | 579 (save-restriction |
592 (widen) | 580 (widen) |
593 (nxml-with-unmodifying-text-property-changes | 581 (nxml-with-unmodifying-text-property-changes |
594 (nxml-clear-face (point-min) (point-max)) | |
595 (nxml-set-fontified (point-min) (point-max)) | |
596 (nxml-clear-inside (point-min) (point-max)))))) | 582 (nxml-clear-inside (point-min) (point-max)))))) |
597 | 583 |
598 ;;; Change management | 584 ;;; Change management |
599 | 585 |
586 (defun nxml-debug-region (start end) | |
587 (interactive "r") | |
588 (let ((font-lock-beg start) | |
589 (font-lock-end end)) | |
590 (nxml-extend-region) | |
591 (goto-char font-lock-beg) | |
592 (set-mark font-lock-end))) | |
593 | |
600 (defun nxml-after-change (start end pre-change-length) | 594 (defun nxml-after-change (start end pre-change-length) |
601 ;; Work around bug in insert-file-contents. | 595 ; In font-lock mode, nxml-after-change1 is called via |
602 (when (> end (1+ (buffer-size))) | 596 ; nxml-extend-after-change-region instead so that the updated |
603 (setq start 1) | 597 ; book-keeping information is available for fontification. |
604 (setq end (1+ (buffer-size)))) | 598 (unless (or font-lock-mode nxml-degraded) |
605 (unless nxml-degraded | 599 (nxml-with-degradation-on-error 'nxml-after-change |
606 (condition-case err | 600 (save-excursion |
607 (save-excursion | 601 (save-restriction |
608 (save-restriction | 602 (widen) |
609 (widen) | 603 (save-match-data |
610 (save-match-data | 604 (nxml-with-invisible-motion |
611 (nxml-with-invisible-motion | 605 (nxml-with-unmodifying-text-property-changes |
612 (nxml-with-unmodifying-text-property-changes | 606 (nxml-after-change1 |
613 (nxml-after-change1 start end pre-change-length)))))) | 607 start end pre-change-length))))))))) |
614 (error | |
615 (nxml-degrade 'nxml-after-change err))))) | |
616 | 608 |
617 (defun nxml-after-change1 (start end pre-change-length) | 609 (defun nxml-after-change1 (start end pre-change-length) |
618 (setq nxml-last-fontify-end nil) | 610 "After-change bookkeeping. Returns a cons cell containing a |
611 possibly-enlarged change region. You must call | |
612 nxml-extend-region on this expanded region to obtain the full | |
613 extent of the area needing refontification. | |
614 | |
615 For bookkeeping, call this function even when fontification is | |
616 disabled." | |
619 (let ((pre-change-end (+ start pre-change-length))) | 617 (let ((pre-change-end (+ start pre-change-length))) |
620 (setq start | 618 (setq start |
621 (nxml-adjust-start-for-dependent-regions start | 619 (nxml-adjust-start-for-dependent-regions start |
622 end | 620 end |
623 pre-change-length)) | 621 pre-change-length)) |
622 ;; If the prolog might have changed, rescan the prolog | |
624 (when (<= start | 623 (when (<= start |
625 ;; Add 2 so as to include the < and following char | 624 ;; Add 2 so as to include the < and following char that |
626 ;; that start the instance, since changing these | 625 ;; start the instance (document element), since changing |
627 ;; can change where the prolog ends. | 626 ;; these can change where the prolog ends. |
628 (+ nxml-prolog-end 2)) | 627 (+ nxml-prolog-end 2)) |
629 ;; end must be extended to at least the end of the old prolog | 628 ;; end must be extended to at least the end of the old prolog in |
629 ;; case the new prolog is shorter | |
630 (when (< pre-change-end nxml-prolog-end) | 630 (when (< pre-change-end nxml-prolog-end) |
631 (setq end | 631 (setq end |
632 ;; don't let end get out of range even if pre-change-length | 632 ;; don't let end get out of range even if pre-change-length |
633 ;; is bogus | 633 ;; is bogus |
634 (min (point-max) | 634 (min (point-max) |
635 (+ end (- nxml-prolog-end pre-change-end))))) | 635 (+ end (- nxml-prolog-end pre-change-end))))) |
636 (nxml-scan-prolog))) | 636 (nxml-scan-prolog) |
637 (cond ((<= end nxml-prolog-end) | 637 (setq start (point-min)))) |
638 (setq end nxml-prolog-end) | 638 |
639 (goto-char start) | 639 (when (> end nxml-prolog-end) |
640 ;; This is so that Emacs redisplay works | 640 (goto-char start) |
641 (setq start (line-beginning-position))) | 641 (nxml-move-tag-backwards (point-min)) |
642 ((and (<= start nxml-scan-end) | 642 (setq start (point)) |
643 (> start (point-min)) | 643 (setq end (max (nxml-scan-after-change start end) |
644 (nxml-get-inside (1- start))) | 644 end))) |
645 ;; The closing delimiter might have been removed. | 645 |
646 ;; So we may need to redisplay from the beginning | 646 (nxml-debug-change "nxml-after-change1" start end) |
647 ;; of the token. | 647 (cons start end)) |
648 (goto-char (1- start)) | 648 |
649 (nxml-move-outside-backwards) | |
650 ;; This is so that Emacs redisplay works | |
651 (setq start (line-beginning-position)) | |
652 (setq end (max (nxml-scan-after-change (point) end) | |
653 end))) | |
654 (t | |
655 (goto-char start) | |
656 ;; This is both for redisplay and to move back | |
657 ;; past any incomplete opening delimiters | |
658 (setq start (line-beginning-position)) | |
659 (setq end (max (nxml-scan-after-change start end) | |
660 end)))) | |
661 (when nxml-syntax-highlight-flag | |
662 (when (>= start end) | |
663 ;; Must clear at least one char so as to trigger redisplay. | |
664 (cond ((< start (point-max)) | |
665 (setq end (1+ start))) | |
666 (t | |
667 (setq end (point-max)) | |
668 (goto-char end) | |
669 (setq start (line-beginning-position))))) | |
670 (nxml-clear-fontified start end))) | |
671 | |
672 ;;; Encodings | 649 ;;; Encodings |
673 | 650 |
674 (defun nxml-insert-xml-declaration () | 651 (defun nxml-insert-xml-declaration () |
675 "Insert an XML declaration at the beginning of buffer. | 652 "Insert an XML declaration at the beginning of buffer. |
676 The XML declaration will declare an encoding depending on the buffer's | 653 The XML declaration will declare an encoding depending on the buffer's |
852 (setq coding-systems (cdr coding-systems)))) | 829 (setq coding-systems (cdr coding-systems)))) |
853 ret)) | 830 ret)) |
854 | 831 |
855 ;;; Fontification | 832 ;;; Fontification |
856 | 833 |
857 (defun nxml-fontify (start) | 834 (defun nxml-unfontify-region (start end) |
858 (condition-case err | 835 (font-lock-default-unfontify-region start end) |
859 (save-excursion | 836 (nxml-clear-char-ref-extra-display start end)) |
860 (save-restriction | 837 |
861 (widen) | 838 (defvar font-lock-beg) (defvar font-lock-end) |
862 (save-match-data | 839 (defun nxml-extend-region () |
863 (nxml-with-invisible-motion | 840 "Extend the region to hold the minimum area we can fontify with nXML. |
864 (nxml-with-unmodifying-text-property-changes | 841 Called with font-lock-beg and font-lock-end dynamically bound." |
865 (if (or nxml-degraded | 842 (let ((start font-lock-beg) |
866 ;; just in case we get called in the wrong buffer | 843 (end font-lock-end)) |
867 (not nxml-prolog-end)) | 844 |
868 (nxml-set-fontified start (point-max)) | 845 (nxml-debug-change "nxml-extend-region(input)" start end) |
869 (nxml-fontify1 start))))))) | 846 |
870 (error | 847 (when (< start nxml-prolog-end) |
871 (nxml-degrade 'nxml-fontify err)))) | 848 (setq start (point-min))) |
872 | 849 |
873 (defun nxml-fontify1 (start) | 850 (cond ((<= end nxml-prolog-end) |
874 (cond ((< start nxml-prolog-end) | 851 (setq end nxml-prolog-end)) |
875 (nxml-fontify-prolog) | 852 |
876 (nxml-set-fontified (point-min) | 853 (t |
877 nxml-prolog-end)) | 854 (goto-char start) |
878 (t | 855 ;; some font-lock backends (like Emacs 22 jit-lock) snap |
879 (goto-char start) | 856 ;; the region to the beginning of the line no matter what |
880 (when (not (eq nxml-last-fontify-end start)) | 857 ;; we say here. To mitigate the resulting excess |
881 (when (not (equal (char-after) ?\<)) | 858 ;; fontification, ignore leading whitespace. |
882 (search-backward "<" nxml-prolog-end t)) | 859 (skip-syntax-forward " ") |
883 (nxml-ensure-scan-up-to-date) | 860 |
884 (nxml-move-outside-backwards)) | 861 ;; find the beginning of the previous tag |
885 (let ((start (point))) | 862 (when (not (equal (char-after) ?\<)) |
886 (nxml-do-fontify (min (point-max) | 863 (search-backward "<" nxml-prolog-end t)) |
887 (+ start nxml-fontify-chunk-size))) | 864 (nxml-ensure-scan-up-to-date) |
888 (setq nxml-last-fontify-end (point)) | 865 (nxml-move-outside-backwards) |
889 (nxml-set-fontified start nxml-last-fontify-end))))) | 866 (setq start (point)) |
890 | 867 |
891 (defun nxml-fontify-buffer () | 868 (while (< (point) end) |
892 (interactive) | 869 (nxml-tokenize-forward)) |
893 (save-excursion | 870 |
894 (save-restriction | 871 (setq end (point)))) |
895 (widen) | 872 |
896 (nxml-with-invisible-motion | 873 (when (or (< start font-lock-beg) |
897 (goto-char (point-min)) | 874 (> end font-lock-end)) |
898 (nxml-with-unmodifying-text-property-changes | 875 (setq font-lock-beg start |
899 (nxml-fontify-prolog) | 876 font-lock-end end) |
900 (goto-char nxml-prolog-end) | 877 (nxml-debug-change "nxml-extend-region" start end) |
901 (nxml-do-fontify)))))) | 878 t))) |
879 | |
880 (defun nxml-extend-after-change-region (start end pre-change-length) | |
881 (unless nxml-degraded | |
882 (setq nxml-last-fontify-end nil) | |
883 | |
884 (nxml-with-degradation-on-error 'nxml-extend-after-change-region | |
885 (save-excursion | |
886 (save-restriction | |
887 (widen) | |
888 (save-match-data | |
889 (nxml-with-invisible-motion | |
890 (nxml-with-unmodifying-text-property-changes | |
891 (nxml-extend-after-change-region1 | |
892 start end pre-change-length))))))))) | |
893 | |
894 (defun nxml-extend-after-change-region1 (start end pre-change-length) | |
895 (let* ((region (nxml-after-change1 start end pre-change-length)) | |
896 (font-lock-beg (car region)) | |
897 (font-lock-end (cdr region))) | |
898 | |
899 (nxml-extend-region) | |
900 (cons font-lock-beg font-lock-end))) | |
901 | |
902 (defun nxml-fontify-matcher (bound) | |
903 "Called as font-lock keyword matcher." | |
904 | |
905 (unless nxml-degraded | |
906 (nxml-debug-change "nxml-fontify-matcher" (point) bound) | |
907 | |
908 (when (< (point) nxml-prolog-end) | |
909 ;; prolog needs to be fontified in one go, and | |
910 ;; nxml-extend-region makes sure we start at BOB. | |
911 (assert (bobp)) | |
912 (nxml-fontify-prolog) | |
913 (goto-char nxml-prolog-end)) | |
914 | |
915 (let (xmltok-dependent-regions | |
916 xmltok-errors) | |
917 (while (and (nxml-tokenize-forward) | |
918 (<= (point) bound)) ; intervals are open-ended | |
919 (nxml-apply-fontify-rule))) | |
920 | |
921 (setq nxml-last-fontify-end (point))) | |
922 | |
923 ;; Since we did the fontification internally, tell font-lock to not | |
924 ;; do anything itself. | |
925 nil) | |
902 | 926 |
903 (defun nxml-fontify-prolog () | 927 (defun nxml-fontify-prolog () |
904 "Fontify the prolog. | 928 "Fontify the prolog. |
905 The buffer is assumed to be prepared for fontification. | 929 The buffer is assumed to be prepared for fontification. |
906 This does not set the fontified property, but it does clear | 930 This does not set the fontified property, but it does clear |
907 faces appropriately." | 931 faces appropriately." |
908 (let ((regions nxml-prolog-regions)) | 932 (let ((regions nxml-prolog-regions)) |
909 (nxml-clear-face (point-min) nxml-prolog-end) | |
910 (while regions | 933 (while regions |
911 (let ((region (car regions))) | 934 (let ((region (car regions))) |
912 (nxml-apply-fontify-rule (aref region 0) | 935 (nxml-apply-fontify-rule (aref region 0) |
913 (aref region 1) | 936 (aref region 1) |
914 (aref region 2))) | 937 (aref region 2))) |
915 (setq regions (cdr regions))))) | 938 (setq regions (cdr regions))))) |
916 | |
917 (defun nxml-do-fontify (&optional bound) | |
918 "Fontify at least as far as bound. | |
919 Leave point after last fontified position." | |
920 (unless bound (setq bound (point-max))) | |
921 (let (xmltok-dependent-regions | |
922 xmltok-errors) | |
923 (while (and (< (point) bound) | |
924 (nxml-tokenize-forward)) | |
925 (nxml-clear-face xmltok-start (point)) | |
926 (nxml-apply-fontify-rule)))) | |
927 | 939 |
928 ;; Vectors identify a substring of the token to be highlighted in some face. | 940 ;; Vectors identify a substring of the token to be highlighted in some face. |
929 | 941 |
930 ;; Token types returned by xmltok-forward. | 942 ;; Token types returned by xmltok-forward. |
931 | 943 |
2572 (let ((new (if (null arg) | 2584 (let ((new (if (null arg) |
2573 (not nxml-char-ref-extra-display) | 2585 (not nxml-char-ref-extra-display) |
2574 (> (prefix-numeric-value arg) 0)))) | 2586 (> (prefix-numeric-value arg) 0)))) |
2575 (when (not (eq new nxml-char-ref-extra-display)) | 2587 (when (not (eq new nxml-char-ref-extra-display)) |
2576 (setq nxml-char-ref-extra-display new) | 2588 (setq nxml-char-ref-extra-display new) |
2577 (save-excursion | 2589 (font-lock-fontify-buffer)))) |
2578 (save-restriction | |
2579 (widen) | |
2580 (if nxml-char-ref-extra-display | |
2581 (nxml-with-unmodifying-text-property-changes | |
2582 (nxml-clear-fontified (point-min) (point-max))) | |
2583 (nxml-clear-char-ref-extra-display (point-min) (point-max)))))))) | |
2584 | 2590 |
2585 (put 'nxml-char-ref 'evaporate t) | 2591 (put 'nxml-char-ref 'evaporate t) |
2586 | 2592 |
2587 (defun nxml-char-ref-display-extra (start end n) | 2593 (defun nxml-char-ref-display-extra (start end n) |
2588 (when nxml-char-ref-extra-display | 2594 (when nxml-char-ref-extra-display |