]> code.delx.au - gnu-emacs/blobdiff - lisp/nxml/nxml-mode.el
Merge from mainline.
[gnu-emacs] / lisp / nxml / nxml-mode.el
index 824d52a0102e154474bdaeccd85b0102916e108f..5eb9840a4ca2b6a480457e617c7738b1d1d1bb0a 100644 (file)
@@ -1,16 +1,16 @@
 ;;; nxml-mode.el --- a new XML mode
 
-;; Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: James Clark
 ;; Keywords: XML
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
-;; To use this include rng-auto.el in your .emacs.
-
 ;; See nxml-rap.el for description of parsing strategy.
 
-;; The font locking here is independent of font-lock.el.  We want to
-;; do more sophisticated handling of changes and we want to use the
-;; same xmltok rather than regexps for parsing so that we parse
-;; consistently and correctly.
-
 ;;; Code:
 
 (when (featurep 'mucs)
   (error "nxml-mode is not compatible with Mule-UCS"))
 
+(eval-when-compile (require 'cl))      ; for assert
+
 (require 'xmltok)
 (require 'nxml-enc)
 (require 'nxml-glyph)
 (require 'nxml-rap)
 (require 'nxml-outln)
 
+(declare-function rng-nxml-mode-init "rng-nxml")
+(declare-function nxml-enable-unicode-char-name-sets "nxml-uchnm")
+
 ;;; Customization
 
 (defgroup nxml nil
-  "New XML editing mode"
-  :group 'languages
-  :group 'wp)
+  "New XML editing mode."
+  :group 'languages)
 
 (defgroup nxml-faces nil
   "Faces for XML syntax highlighting."
-  :group 'nxml
-  :group 'font-lock-faces)
-
-(defcustom nxml-syntax-highlight-flag t
-  "*Non-nil means nxml-mode should perform syntax highlighting."
-  :group 'nxml
-  :type 'boolean)
+  :group 'nxml)
 
 (defcustom nxml-char-ref-display-glyph-flag t
   "*Non-nil means display glyph following character reference.
@@ -95,20 +84,18 @@ nothing else other than that start-tag."
 
 (defcustom nxml-attribute-indent 4
   "*Indentation for the attributes of an element relative to the start-tag.
-This only applies when the first attribute of a tag starts a line. In other
-cases, the first attribute on one line is indented the same as the first
-attribute on the previous line."
+This only applies when the first attribute of a tag starts a line.
+In other cases, the first attribute on one line is indented the same
+as the first attribute on the previous line."
   :group 'nxml
   :type 'integer)
 
-(defvar nxml-fontify-chunk-size 500)
-
 (defcustom nxml-bind-meta-tab-to-complete-flag (not window-system)
   "*Non-nil means bind M-TAB in `nxml-mode-map' to `nxml-complete'.
 C-return will be bound to `nxml-complete' in any case.
 M-TAB gets swallowed by many window systems/managers, and
 `documentation' will show M-TAB rather than C-return as the
-binding `rng-complete' when both are bound.  So it's better
+binding for `nxml-complete' when both are bound.  So it's better
 to bind M-TAB only when it will work."
   :group 'nxml
   :set (lambda (sym flag)
@@ -136,7 +123,7 @@ and when the encoding declaration specifies `UTF-16'."
 
 (defcustom nxml-default-buffer-file-coding-system nil
   "*Default value for `buffer-file-coding-system' for a buffer for a new file.
-Nil means use the default value of `buffer-file-coding-system' as normal.
+A value of nil means use the default value of `buffer-file-coding-system' as normal.
 A buffer's `buffer-file-coding-system' affects what \\[nxml-insert-xml-declaration] inserts."
   :group 'nxml
   :type 'coding-system)
@@ -274,7 +261,7 @@ This includes ths `x' in hex references."
   '((t (:inherit nxml-delimiter)))
   "Face used for the colon in attribute names."
   :group 'nxml-faces)
-  
+
 (defface nxml-attribute-local-name
   '((t (:inherit font-lock-variable-name-face)))
   "Face used for the local name of attributes."
@@ -350,7 +337,7 @@ The delimiters are <! and >."
       :foreground
       "black"
       :weight
-      normal 
+      normal
       :slant
       normal))
     (t
@@ -359,7 +346,7 @@ The delimiters are <! and >."
       :foreground
       "black"
       :weight
-      normal 
+      normal
       :slant
       normal)))
   "Face used for glyph for char references."
@@ -374,7 +361,7 @@ See the function `xmltok-forward-prolog' for more information.")
 
 (defvar nxml-last-fontify-end nil
   "Position where fontification last ended.
-Nil if the buffer changed since the last fontification.")
+It is nil if the buffer changed since the last fontification.")
 (make-variable-buffer-local 'nxml-last-fontify-end)
 
 (defvar nxml-degraded nil
@@ -427,25 +414,19 @@ reference.")
     (define-key map "\C-c\C-o" nxml-outline-prefix-map)
     (define-key map [S-mouse-2] 'nxml-mouse-hide-direct-text-content)
     (define-key map "/" 'nxml-electric-slash)
-    (define-key map [C-return] 'nxml-complete) 
+    (define-key map [C-return] 'nxml-complete)
     (when nxml-bind-meta-tab-to-complete-flag
       (define-key map "\M-\t" 'nxml-complete))
     map)
   "Keymap for nxml-mode.")
 
+(defvar nxml-font-lock-keywords
+  '(nxml-fontify-matcher)
+  "Default font lock keywords for nxml-mode.")
+
 (defsubst nxml-set-face (start end face)
   (when (and face (< start end))
-    (put-text-property start end 'face face)))
-
-(defun nxml-clear-face (start end)
-  (remove-text-properties start end '(face nil))
-  (nxml-clear-char-ref-extra-display start end))
-
-(defsubst nxml-set-fontified (start end)
-  (put-text-property start end 'fontified t))
-
-(defsubst nxml-clear-fontified (start end)
-  (remove-text-properties start end '(fontified nil)))
+    (font-lock-append-text-property start end 'face face)))
 
 ;;;###autoload
 (defun nxml-mode ()
@@ -454,12 +435,9 @@ reference.")
   ;; not mnemonic.
   "Major mode for editing XML.
 
-Syntax highlighting is performed unless the variable
-`nxml-syntax-highlight-flag' is nil.
-
 \\[nxml-finish-element] finishes the current element by inserting an end-tag.
 C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag
-leaving point between the start-tag and end-tag. 
+leaving point between the start-tag and end-tag.
 \\[nxml-balanced-close-start-tag-block] is similar but for block rather than inline elements:
 the start-tag, point, and end-tag are all left on separate lines.
 If `nxml-slash-auto-complete-flag' is non-nil, then inserting a `</'
@@ -479,17 +457,17 @@ instead of C-c.
 Validation is provided by the related minor-mode `rng-validate-mode'.
 This also makes completion schema- and context- sensitive.  Element
 names, attribute names, attribute values and namespace URIs can all be
-completed. By default, `rng-validate-mode' is automatically enabled by
-`rng-nxml-mode-init' which is normally added to `nxml-mode-hook'. You
-can toggle it using \\[rng-validate-mode].
+completed. By default, `rng-validate-mode' is automatically enabled.
+You can toggle it using \\[rng-validate-mode] or change the default by
+customizing `rng-nxml-auto-validate-flag'.
 
 \\[indent-for-tab-command] indents the current line appropriately.
 This can be customized using the variable `nxml-child-indent'
 and the variable `nxml-attribute-indent'.
 
 \\[nxml-insert-named-char] inserts a character reference using
-the character's name (by default, the Unicode name). \\[universal-argument] \\[nxml-insert-named-char]
-inserts the character directly.
+the character's name (by default, the Unicode name).
+\\[universal-argument] \\[nxml-insert-named-char] inserts the character directly.
 
 The Emacs commands that normally operate on balanced expressions will
 operate on XML markup items.  Thus \\[forward-sexp] will move forward
@@ -509,6 +487,7 @@ Many aspects this mode can be customized using
   (kill-all-local-variables)
   (setq major-mode 'nxml-mode)
   (setq mode-name "nXML")
+  (set (make-local-variable 'mode-line-process) '((nxml-degraded "/degraded")))
   ;; We'll determine the fill prefix ourselves
   (make-local-variable 'adaptive-fill-mode)
   (setq adaptive-fill-mode nil)
@@ -540,22 +519,54 @@ Many aspects this mode can be customized using
       (nxml-clear-dependent-regions (point-min) (point-max))
       (setq nxml-scan-end (copy-marker (point-min) nil))
       (nxml-with-unmodifying-text-property-changes
-       (when nxml-syntax-highlight-flag
-         (nxml-clear-fontified (point-min) (point-max)))
-       (nxml-clear-inside (point-min) (point-max))
+        (nxml-clear-inside (point-min) (point-max))
        (nxml-with-invisible-motion
          (nxml-scan-prolog)))))
-  (when nxml-syntax-highlight-flag
-    (add-hook 'fontification-functions 'nxml-fontify nil t))
   (add-hook 'after-change-functions 'nxml-after-change nil t)
-  (add-hook 'write-contents-hooks 'nxml-prepare-to-save)
+  (add-hook 'change-major-mode-hook 'nxml-cleanup nil t)
+
+  ;; Emacs 23 handles the encoding attribute on the xml declaration
+  ;; transparently to nxml-mode, so there is no longer a need for the below
+  ;; hook. The hook also had the drawback of overriding explicit user
+  ;; instruction to save as some encoding other than utf-8.
+;;;   (add-hook 'write-contents-hooks 'nxml-prepare-to-save)
   (when (not (and (buffer-file-name) (file-exists-p (buffer-file-name))))
     (when (and nxml-default-buffer-file-coding-system
               (not (local-variable-p 'buffer-file-coding-system)))
       (setq buffer-file-coding-system nxml-default-buffer-file-coding-system))
     (when nxml-auto-insert-xml-declaration-flag
       (nxml-insert-xml-declaration)))
-  (run-hooks 'nxml-mode-hook))
+
+  (setq font-lock-defaults
+        '(nxml-font-lock-keywords
+          t    ; keywords-only; we highlight comments and strings here
+          nil  ; font-lock-keywords-case-fold-search. XML is case sensitive
+          nil  ; no special syntax table
+          nil  ; no automatic syntactic fontification
+          (font-lock-extend-after-change-region-function
+           . nxml-extend-after-change-region)
+          (font-lock-extend-region-functions . (nxml-extend-region))
+          (jit-lock-contextually . t)
+          (font-lock-unfontify-region-function . nxml-unfontify-region)))
+
+  (rng-nxml-mode-init)
+  (nxml-enable-unicode-char-name-sets)
+  (run-mode-hooks 'nxml-mode-hook))
+
+(defun nxml-cleanup ()
+  "Clean up after nxml-mode."
+  ;; Disable associated minor modes.
+  (rng-validate-mode -1)
+  ;; Clean up fontification.
+  (save-excursion
+    (widen)
+    (let ((inhibit-read-only t)
+         (buffer-undo-list t)
+         (modified (buffer-modified-p)))
+      (nxml-with-invisible-motion
+       (remove-text-properties (point-min) (point-max) '(face)))
+      (set-buffer-modified-p modified)))
+  (remove-hook 'change-major-mode-hook 'nxml-cleanup t))
 
 (defun nxml-degrade (context err)
   (message "Internal nXML mode error in %s (%s), degrading"
@@ -568,85 +579,73 @@ Many aspects this mode can be customized using
     (save-restriction
       (widen)
       (nxml-with-unmodifying-text-property-changes
-       (nxml-clear-face (point-min) (point-max))
-       (nxml-set-fontified (point-min) (point-max))
-       (nxml-clear-inside (point-min) (point-max)))
-      (setq mode-name "nXML/degraded"))))
+       (nxml-clear-inside (point-min) (point-max))))))
 
 ;;; Change management
 
+(defun nxml-debug-region (start end)
+  (interactive "r")
+  (let ((font-lock-beg start)
+        (font-lock-end end))
+    (nxml-extend-region)
+    (goto-char font-lock-beg)
+    (set-mark font-lock-end)))
+
 (defun nxml-after-change (start end pre-change-length)
-  ;; Work around bug in insert-file-contents.
-  (when (> end (1+ (buffer-size)))
-    (setq start 1)
-    (setq end (1+ (buffer-size))))
-  (unless nxml-degraded
-    (condition-case err
-       (save-excursion
-         (save-restriction
-           (widen)
-           (save-match-data
-             (nxml-with-invisible-motion
-               (nxml-with-unmodifying-text-property-changes
-                 (nxml-after-change1 start end pre-change-length))))))
-      (error
-       (nxml-degrade 'nxml-after-change err)))))
+  ; In font-lock mode, nxml-after-change1 is called via
+  ; nxml-extend-after-change-region instead so that the updated
+  ; book-keeping information is available for fontification.
+  (unless (or font-lock-mode nxml-degraded)
+    (nxml-with-degradation-on-error 'nxml-after-change
+        (save-excursion
+          (save-restriction
+            (widen)
+            (save-match-data
+              (nxml-with-invisible-motion
+                (nxml-with-unmodifying-text-property-changes
+                  (nxml-after-change1
+                   start end pre-change-length)))))))))
 
 (defun nxml-after-change1 (start end pre-change-length)
-  (setq nxml-last-fontify-end nil)
+  "After-change bookkeeping.
+Returns a cons cell containing a possibly-enlarged change region.
+You must call `nxml-extend-region' on this expanded region to obtain
+the full extent of the area needing refontification.
+
+For bookkeeping, call this function even when fontification is
+disabled."
   (let ((pre-change-end (+ start pre-change-length)))
     (setq start
          (nxml-adjust-start-for-dependent-regions start
                                                   end
                                                   pre-change-length))
+    ;; If the prolog might have changed, rescan the prolog
     (when (<= start
-             ;; Add 2 so as to include the < and following char
-             ;; that start the instance, since changing these
-             ;; can change where the prolog ends.
+             ;; Add 2 so as to include the < and following char that
+             ;; start the instance (document element), since changing
+             ;; these can change where the prolog ends.
              (+ nxml-prolog-end 2))
-      ;; end must be extended to at least the end of the old prolog
+      ;; end must be extended to at least the end of the old prolog in
+      ;; case the new prolog is shorter
       (when (< pre-change-end nxml-prolog-end)
        (setq end
              ;; don't let end get out of range even if pre-change-length
              ;; is bogus
              (min (point-max)
                   (+ end (- nxml-prolog-end pre-change-end)))))
-      (nxml-scan-prolog)))
-  (cond ((<= end nxml-prolog-end)
-        (setq end nxml-prolog-end)
-        (goto-char start)
-        ;; This is so that Emacs redisplay works
-        (setq start (line-beginning-position)))
-       ((and (<= start nxml-scan-end)
-             (> start (point-min))
-             (nxml-get-inside (1- start)))
-        ;; The closing delimiter might have been removed.
-        ;; So we may need to redisplay from the beginning
-        ;; of the token.
-        (goto-char (1- start))
-        (nxml-move-outside-backwards)
-        ;; This is so that Emacs redisplay works
-        (setq start (line-beginning-position))
-        (setq end (max (nxml-scan-after-change (point) end)
-                       end)))
-       (t
-        (goto-char start)
-        ;; This is both for redisplay and to move back
-        ;; past any incomplete opening delimiters
-        (setq start (line-beginning-position))
-        (setq end (max (nxml-scan-after-change start end)
-                       end))))
-  (when nxml-syntax-highlight-flag
-    (when (>= start end)
-      ;; Must clear at least one char so as to trigger redisplay.
-      (cond ((< start (point-max))
-            (setq end (1+ start)))
-           (t
-            (setq end (point-max))
-            (goto-char end)
-            (setq start (line-beginning-position)))))
-    (nxml-clear-fontified start end)))
-  
+      (nxml-scan-prolog)
+      (setq start (point-min))))
+
+  (when (> end nxml-prolog-end)
+    (goto-char start)
+    (nxml-move-tag-backwards (point-min))
+    (setq start (point))
+    (setq end (max (nxml-scan-after-change start end)
+                   end)))
+
+  (nxml-debug-change "nxml-after-change1" start end)
+  (cons start end))
+
 ;;; Encodings
 
 (defun nxml-insert-xml-declaration ()
@@ -799,7 +798,7 @@ The XML declaration will declare an encoding depending on the buffer's
          (setq suitable-coding-systems (cdr suitable-coding-systems))))
       ret)))
 
-(defun nxml-choose-utf-coding-system ()             
+(defun nxml-choose-utf-coding-system ()
   (let ((cur (and (local-variable-p 'buffer-file-coding-system)
                  buffer-file-coding-system
                  (coding-system-base buffer-file-coding-system))))
@@ -832,51 +831,99 @@ The XML declaration will declare an encoding depending on the buffer's
 
 ;;; Fontification
 
-(defun nxml-fontify (start)
-  (condition-case err
-      (save-excursion
-       (save-restriction
-         (widen)
-         (save-match-data
-           (nxml-with-invisible-motion
-             (nxml-with-unmodifying-text-property-changes
-               (if (or nxml-degraded
-                       ;; just in case we get called in the wrong buffer
-                       (not nxml-prolog-end))
-                   (nxml-set-fontified start (point-max))
-                 (nxml-fontify1 start)))))))
-    (error
-     (nxml-degrade 'nxml-fontify err))))
-
-(defun nxml-fontify1 (start)
-  (cond ((< start nxml-prolog-end)
-        (nxml-fontify-prolog)
-        (nxml-set-fontified (point-min)
-                            nxml-prolog-end))
-       (t
-        (goto-char start)
-        (when (not (eq nxml-last-fontify-end start))
-          (when (not (equal (char-after) ?\<))
-            (search-backward "<" nxml-prolog-end t))
-          (nxml-ensure-scan-up-to-date)
-          (nxml-move-outside-backwards))
-        (let ((start (point)))
-          (nxml-do-fontify (min (point-max)
-                                (+ start nxml-fontify-chunk-size)))
-          (setq nxml-last-fontify-end (point))
-          (nxml-set-fontified start nxml-last-fontify-end)))))
-
-(defun nxml-fontify-buffer ()
-  (interactive)
-  (save-excursion
-    (save-restriction
-      (widen)
-      (nxml-with-invisible-motion
-       (goto-char (point-min))
-       (nxml-with-unmodifying-text-property-changes
-         (nxml-fontify-prolog)
-         (goto-char nxml-prolog-end)
-         (nxml-do-fontify))))))
+(defun nxml-unfontify-region (start end)
+  (font-lock-default-unfontify-region start end)
+  (nxml-clear-char-ref-extra-display start end))
+
+(defvar font-lock-beg) (defvar font-lock-end)
+(defun nxml-extend-region ()
+  "Extend the region to hold the minimum area we can fontify with nXML.
+Called with `font-lock-beg' and `font-lock-end' dynamically bound."
+  (let ((start font-lock-beg)
+        (end font-lock-end))
+
+    (nxml-debug-change "nxml-extend-region(input)" start end)
+
+    (when (< start nxml-prolog-end)
+      (setq start (point-min)))
+
+    (cond ((<= end nxml-prolog-end)
+           (setq end nxml-prolog-end))
+
+          (t
+           (goto-char start)
+           ;; some font-lock backends (like Emacs 22 jit-lock) snap
+           ;; the region to the beginning of the line no matter what
+           ;; we say here. To mitigate the resulting excess
+           ;; fontification, ignore leading whitespace.
+           (skip-syntax-forward " ")
+
+           ;; find the beginning of the previous tag
+           (when (not (equal (char-after) ?\<))
+             (search-backward "<" nxml-prolog-end t))
+           (nxml-ensure-scan-up-to-date)
+           (nxml-move-outside-backwards)
+           (setq start (point))
+
+           (while (< (point) end)
+             (nxml-tokenize-forward))
+
+           (setq end (point))))
+
+    (when (or (< start font-lock-beg)
+              (> end font-lock-end))
+      (setq font-lock-beg start
+            font-lock-end end)
+      (nxml-debug-change "nxml-extend-region" start end)
+      t)))
+
+(defun nxml-extend-after-change-region (start end pre-change-length)
+  (unless nxml-degraded
+    (setq nxml-last-fontify-end nil)
+    (let ((region (nxml-with-degradation-on-error
+                  'nxml-extend-after-change-region
+                  (save-excursion
+                    (save-restriction
+                      (widen)
+                      (save-match-data
+                        (nxml-with-invisible-motion
+                          (nxml-with-unmodifying-text-property-changes
+                            (nxml-extend-after-change-region1
+                             start end pre-change-length)))))))))
+      (if (consp region) region))))
+
+(defun nxml-extend-after-change-region1 (start end pre-change-length)
+  (let* ((region (nxml-after-change1 start end pre-change-length))
+         (font-lock-beg (car region))
+         (font-lock-end (cdr region)))
+
+    (nxml-extend-region)
+    (cons font-lock-beg font-lock-end)))
+
+(defun nxml-fontify-matcher (bound)
+  "Called as font-lock keyword matcher."
+
+  (unless nxml-degraded
+    (nxml-debug-change "nxml-fontify-matcher" (point) bound)
+
+    (when (< (point) nxml-prolog-end)
+      ;; prolog needs to be fontified in one go, and
+      ;; nxml-extend-region makes sure we start at BOB.
+      (assert (bobp))
+      (nxml-fontify-prolog)
+      (goto-char nxml-prolog-end))
+
+    (let (xmltok-dependent-regions
+          xmltok-errors)
+      (while (and (nxml-tokenize-forward)
+                  (<= (point) bound)) ; intervals are open-ended
+        (nxml-apply-fontify-rule)))
+
+    (setq nxml-last-fontify-end (point)))
+
+  ;; Since we did the fontification internally, tell font-lock to not
+  ;; do anything itself.
+  nil)
 
 (defun nxml-fontify-prolog ()
   "Fontify the prolog.
@@ -884,7 +931,6 @@ The buffer is assumed to be prepared for fontification.
 This does not set the fontified property, but it does clear
 faces appropriately."
   (let ((regions nxml-prolog-regions))
-    (nxml-clear-face (point-min) nxml-prolog-end)
     (while regions
       (let ((region (car regions)))
        (nxml-apply-fontify-rule (aref region 0)
@@ -892,17 +938,6 @@ faces appropriately."
                                 (aref region 2)))
       (setq regions (cdr regions)))))
 
-(defun nxml-do-fontify (&optional bound)
-  "Fontify at least as far as bound.
-Leave point after last fontified position."
-  (unless bound (setq bound (point-max)))
-  (let (xmltok-dependent-regions
-       xmltok-errors)
-    (while (and (< (point) bound)
-               (nxml-tokenize-forward))
-      (nxml-clear-face xmltok-start (point))
-      (nxml-apply-fontify-rule))))
-
 ;; Vectors identify a substring of the token to be highlighted in some face.
 
 ;; Token types returned by xmltok-forward.
@@ -1218,31 +1253,33 @@ No extra whitespace is inserted."
 
 (defun nxml-balanced-close-start-tag (block-or-inline)
   (let ((token-end (nxml-token-before))
-       (pos (1+ (point))))
+       (pos (1+ (point)))
+       (token-start xmltok-start))
     (unless (or (eq xmltok-type 'partial-start-tag)
                (and (memq xmltok-type '(start-tag
                                         empty-element
                                         partial-empty-element))
                     (>= token-end pos)))
       (error "Not in a start-tag"))
+    ;; Note that this insertion changes xmltok-start.
     (insert "></"
            (buffer-substring-no-properties (+ xmltok-start 1)
                                            (min xmltok-name-end (point)))
            ">")
     (if (eq block-or-inline 'inline)
        (goto-char pos)
-      (goto-char xmltok-start)
+      (goto-char token-start)
       (back-to-indentation)
-      (if (= (point) xmltok-start)
+      (if (= (point) token-start)
          (let ((indent (current-column)))
-         (goto-char pos)
-         (insert "\n")
-         (indent-line-to indent)
-         (goto-char pos)
-         (insert "\n")
-         (indent-line-to (+ nxml-child-indent indent)))
+           (goto-char pos)
+           (insert "\n")
+           (indent-line-to indent)
+           (goto-char pos)
+           (insert "\n")
+           (indent-line-to (+ nxml-child-indent indent)))
        (goto-char pos)))))
-       
+
 (defun nxml-finish-element ()
   "Finish the current element by inserting an end-tag."
   (interactive "*")
@@ -1334,7 +1371,8 @@ of the inserted start-tag or nil if none was inserted."
   "Indent current line as XML."
   (let ((indent (nxml-compute-indent))
        (from-end (- (point-max) (point))))
-    (when indent
+    (when (and indent
+              (/= indent (current-indentation)))
       (beginning-of-line)
       (let ((bol (point)))
        (skip-chars-forward " \t")
@@ -1444,8 +1482,8 @@ its line.  Otherwise return nil."
 (defun nxml-merge-indent-context-type (context)
   "Merge the indent context type CONTEXT with the token in `xmltok-type'.
 Return the merged indent context type.  An indent context type is
-either nil or one of the symbols start-tag, end-tag, markup, comment,
-mixed."
+either nil or one of the symbols `start-tag', `end-tag', `markup',
+`comment', `mixed'."
   (cond ((memq xmltok-type '(start-tag partial-start-tag))
         (if (memq context '(nil start-tag comment))
             'start-tag
@@ -1537,7 +1575,7 @@ xmltok-* variables to be set up as by `xmltok-forward'."
             (setq atts nil))
            (t (setq atts (cdr atts)))))
     value-boundary))
-            
+
 (defun nxml-compute-indent-in-delimited-token (pos open-delim close-delim)
   "Return the indent for a line that starts inside a token with delimiters.
 OPEN-DELIM and CLOSE-DELIM are strings giving the opening and closing
@@ -1568,7 +1606,7 @@ of the line.  This expects the xmltok-* variables to be set up as by
 Inserts as many characters as can be completed.  However, if not even
 one character can be completed, then a buffer with the possibilities
 is popped up and the symbol is read from the minibuffer with
-completion. If the symbol is complete, then any characters that must
+completion.  If the symbol is complete, then any characters that must
 follow the symbol are also inserted.
 
 The name space used for completion and what is treated as a symbol
@@ -1590,11 +1628,11 @@ This is the equivalent of `forward-sexp' for XML.
 
 An element contains as items strings with no markup, tags, processing
 instructions, comments, CDATA sections, entity references and
-characters references. However, if the variable
+characters references.  However, if the variable
 `nxml-sexp-element-flag' is non-nil, then an element is treated as a
 single markup item.  A start-tag contains an element name followed by
-one or more attributes.  An end-tag contains just an element name.  An
-attribute value literals contains strings with no markup, entity
+one or more attributes.  An end-tag contains just an element name.
+An attribute value literals contains strings with no markup, entity
 references and character references.  A processing instruction
 consists of a target and a content string.  A comment or a CDATA
 section contains a single string.  An entity reference contains a
@@ -2094,7 +2132,7 @@ HAD-DATA says whether there have been non-whitespace data characters yet."
             (goto-char (+ xmltok-start offset))
             (and (re-search-forward "^[ \t]*$" end t)
                  (match-beginning 0)))))
-       ((and (memq xmltok-type '(start-tag 
+       ((and (memq xmltok-type '(start-tag
                                  end-tag
                                  empty-element
                                  comment
@@ -2110,7 +2148,7 @@ HAD-DATA says whether there have been non-whitespace data characters yet."
              (looking-at "[ \t]*$")
              (not (nxml-in-mixed-content-p t)))
         (save-excursion
-          (or (search-forward "\n" nil t) 
+          (or (search-forward "\n" nil t)
               (point-max))))))
 
 (defun nxml-paragraph-start-pos (had-data offset)
@@ -2150,7 +2188,7 @@ HAD-DATA says whether there have been non-whitespace data characters yet."
           (goto-char (- (point) offset))
           (and (re-search-backward "^[ \t]*$" xmltok-start t)
                (match-beginning 0))))
-       ((and (memq xmltok-type '(start-tag 
+       ((and (memq xmltok-type '(start-tag
                                  end-tag
                                  empty-element
                                  comment
@@ -2158,7 +2196,7 @@ HAD-DATA says whether there have been non-whitespace data characters yet."
                                  entity-ref))
              (nxml-token-ends-line-p)
              (nxml-token-begins-line-p))
-        (or (search-forward "\n" nil t) 
+        (or (search-forward "\n" nil t)
             (point-max)))
        ((and (eq xmltok-type 'start-tag)
              (nxml-token-begins-line-p)
@@ -2298,7 +2336,7 @@ ENDP is t in the former case, nil in the latter."
       (fill-region-as-paragraph start end arg))
     (skip-line-prefix fill-prefix)
     fill-prefix))
-    
+
 (defun nxml-newline-and-indent (soft)
   (delete-horizontal-space)
   (if soft (insert-and-inherit ?\n) (newline 1))
@@ -2320,10 +2358,10 @@ point.  The start-tag will be inserted at or before the beginning of
 the word before point; the contents of the current buffer is used to
 decide where.
 
-It works in a similar way to \\[dabbrev-expand]. It searches first
+It works in a similar way to \\[dabbrev-expand].  It searches first
 backwards from point, then forwards from point for an element whose
 content is a string which matches the contents of the buffer before
-point and which includes at least the word before point. It then
+point and which includes at least the word before point.  It then
 copies the start- and end-tags from that element and uses them to
 surround the matching string before point.
 
@@ -2429,11 +2467,11 @@ and attempts to find another possible way to do the markup."
                              (- start-tag-close-pos xmltok-start)))
                (insert "</" name ">")
                (setq nxml-dynamic-markup-prev-pos (point))))))))))
-                                                          
+
 
 ;;; Character names
 
-(defvar nxml-char-name-ignore-case nil)
+(defvar nxml-char-name-ignore-case t)
 
 (defvar nxml-char-name-alist nil
   "Alist of character names.
@@ -2458,10 +2496,10 @@ and NAME is a string naming a character.")
 (defvar nxml-autoload-char-name-set-list nil
   "List of char namesets that can be autoloaded.")
 
-(defun nxml-enable-char-name-set (nameset)    
+(defun nxml-enable-char-name-set (nameset)
   (put nameset 'nxml-char-name-set-enabled t))
 
-(defun nxml-disable-char-name-set (nameset)    
+(defun nxml-disable-char-name-set (nameset)
   (put nameset 'nxml-char-name-set-enabled nil))
 
 (defun nxml-char-name-set-enabled-p (nameset)
@@ -2476,9 +2514,9 @@ and NAME is a string naming a character.")
 (defun nxml-define-char-name-set (nameset alist)
   "Define a set of character names.
 NAMESET is a symbol identifying the set.
-Alist is a list where each member has the form (NAME CODE),
-where NAME is a string naming a character and code
-is an integer giving the Unicode scalar value of the character."
+ALIST is a list where each member has the form (NAME CODE),
+where NAME is a string naming a character and code is an
+integer giving the Unicode scalar value of the character."
   (when (get nameset 'nxml-char-name-set-defined)
     (error "Nameset `%s' already defined" nameset))
   (let ((iter alist))
@@ -2537,7 +2575,7 @@ With a prefix argument, inserts the character directly."
                      (error "Character %x is not supported by Emacs"
                             code))
                (format "&#x%X;" code))))))
-  
+
 (defun nxml-maybe-load-char-name-set (sym)
   (when (and (get sym 'nxml-char-name-set-enabled)
             (not (get sym 'nxml-char-name-set-defined))
@@ -2545,20 +2583,14 @@ With a prefix argument, inserts the character directly."
     (load (get sym 'nxml-char-name-set-file))))
 
 (defun nxml-toggle-char-ref-extra-display (arg)
-  "*Toggle the display of extra information for character references."
+  "Toggle the display of extra information for character references."
   (interactive "P")
   (let ((new (if (null arg)
                 (not nxml-char-ref-extra-display)
               (> (prefix-numeric-value arg) 0))))
     (when (not (eq new nxml-char-ref-extra-display))
       (setq nxml-char-ref-extra-display new)
-      (save-excursion
-       (save-restriction
-         (widen)
-         (if nxml-char-ref-extra-display
-             (nxml-with-unmodifying-text-property-changes
-               (nxml-clear-fontified (point-min) (point-max)))
-           (nxml-clear-char-ref-extra-display (point-min) (point-max))))))))
+      (font-lock-fontify-buffer))))
 
 (put 'nxml-char-ref 'evaporate t)
 
@@ -2589,7 +2621,7 @@ With a prefix argument, inserts the character directly."
 (defun nxml-start-delimiter-length (type)
   (or (get type 'nxml-start-delimiter-length)
       0))
-                       
+
 (put 'cdata-section 'nxml-start-delimiter-length 9)
 (put 'comment 'nxml-start-delimiter-length 4)
 (put 'processing-instruction 'nxml-start-delimiter-length 2)
@@ -2602,7 +2634,7 @@ With a prefix argument, inserts the character directly."
 (defun nxml-end-delimiter-length (type)
   (or (get type 'nxml-end-delimiter-length)
       0))
-                       
+
 (put 'cdata-section 'nxml-end-delimiter-length 3)
 (put 'comment 'nxml-end-delimiter-length 3)
 (put 'processing-instruction 'nxml-end-delimiter-length 2)
@@ -2621,6 +2653,9 @@ With a prefix argument, inserts the character directly."
 (put 'entity-ref 'nxml-friendly-name "entity reference")
 (put 'char-ref 'nxml-friendly-name "character reference")
 
+;;;###autoload
+(defalias 'xml-mode 'nxml-mode)
+
 (provide 'nxml-mode)
 
 ;; arch-tag: 8603bc5f-1ef9-4021-b223-322fb2ca708e