diff lisp/font-lock.el @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children 11054d720c21
line wrap: on
line diff
--- a/lisp/font-lock.el	Mon Aug 13 11:19:22 2007 +0200
+++ b/lisp/font-lock.el	Mon Aug 13 11:20:41 2007 +0200
@@ -4,7 +4,7 @@
 ;; Copyright (C) 1995 Amdahl Corporation.
 ;; Copyright (C) 1996 Ben Wing.
 
-;; Author: Jamie Zawinski <jwz@jwz.org>, for the LISPM Preservation Society.
+;; Author: Jamie Zawinski <jwz@netscape.com>, for the LISPM Preservation Society.
 ;; Minimally merged with FSF 19.34 by Barry Warsaw <bwarsaw@python.org>
 ;; Then (partially) synched with FSF 19.30, leading to:
 ;; Next Author: RMS
@@ -178,8 +178,8 @@
 but not `font-lock-fontify-buffer'. (In other words, when you first visit
 a file and it gets fontified, you will see status messages no matter what
 size the file is.  However, if you do something else like paste a
-chunk of text, you will see status messages only if the changed region is
-large enough.)
+chunk of text or revert a buffer, you will see status messages only if the
+changed region is large enough.)
 
 Note that setting `font-lock-verbose' to nil disables the status
 messages entirely."
@@ -318,123 +318,95 @@
 
 ;;;###autoload
 (defvar font-lock-keywords nil
-  "A list defining the keywords for `font-lock-mode' to highlight.
-
- FONT-LOCK-KEYWORDS := List of FONT-LOCK-FORM's.
-
- FONT-LOCK-FORM     :== MATCHER
-                      | (MATCHER . MATCH)
-                      | (MATCHER . FACE-FORM)
-                      | (MATCHER . HIGHLIGHT)
-                      | (MATCHER HIGHLIGHT ...)
-                      | (eval . FORM)
-
- MATCHER            :== A string containing a regexp.
-                      | A variable containing a regexp to search for.
-                      | A function to call to make the search.
-                        It is called with one arg, the limit of the search,
-                        and should leave MATCH results in the XEmacs global
-                        match data.
-
- MATCH              :== An integer match subexpression number from MATCHER.
-
- FACE-FORM           :== The symbol naming a defined face.
-                      | Expression whos value is the face name to use.  If you
-                        want FACE-FORM to be a symbol that evaluates to a face,
-                        use a form like \"(progn sym)\".
-
- HIGHLIGHT          :== MATCH-HIGHLIGHT
-                      | MATCH-ANCHORED
-
- FORM               :== Expression returning a FONT-LOCK-FORM, evaluated when
-                        the FONT-LOCK-FORM is first used in a buffer.  This
-                        feature can be used to provide a FONT-LOCK-FORM that
-                        can only be generated when Font Lock mode is actually
-                        turned on.
-
- MATCH-HIGHLIGHT    :== (MATCH FACE-FORM OVERRIDE LAXMATCH)
-
- OVERRIDE           :== t        - overwrite existing fontification
-                      | 'keep    - only parts not already fontified are
-                                   highlighted.
-                      | 'prepend - merge faces, this fontification has
-                                   precedence over existing
-                      | 'append  - merge faces, existing fontification has
-                                   precedence over
-                                   this face.
-
- LAXMATCH           :== If non-nil, no error is signalled if there is no MATCH
-                        in MATCHER.
-
- MATCH-ANCHORED     :== (ANCHOR-MATCHER PRE-MATCH-FORM \\
-                                          POST-MATCH-FORM MATCH-HIGHLIGHT ...)
+  "A list of the keywords to highlight.
+Each element should be of the form:
 
- ANCHOR-MATCHER     :== Like a MATCHER, except that the limit of the search
-                        defaults to the end of the line after PRE-MATCH-FORM
-                        is evaluated.  However, if PRE-MATCH-FORM returns a
-                        position greater than the end of the line, that
-                        position is used as the limit of the search.  It is
-                        generally a bad idea to return a position greater than
-                        the end of the line, i.e., cause the ANCHOR-MATCHER
-                        search to span lines.
-
- PRE-MATCH-FORM     :== Evaluated before the ANCHOR-MATCHER is used, therefore
-                        can be used to initialize before, ANCHOR-MATCHER is
-                        used.  Typically, PRE-MATCH-FORM is used to move to
-                        some position relative to the original MATCHER, before
-                        starting with the ANCHOR-MATCHER.
-
- POST-MATCH-FORM    :== Like PRE-MATCH-FORM, but used to clean up after the
-                        ANCHOR-MATCHER.  It might be used to move, before
-                        resuming with MATCH-ANCHORED's parent's MATCHER.
-
-For example, an element of the first form highlights (if not already highlighted):
-
-  \"\\\\<foo\\\\>\"                    Discrete occurrences of \"foo\" in the value
-                                 of the variable `font-lock-keyword-face'.
+ MATCHER
+ (MATCHER . MATCH)
+ (MATCHER . FACENAME)
+ (MATCHER . HIGHLIGHT)
+ (MATCHER HIGHLIGHT ...)
+ (eval . FORM)
 
-  (\"fu\\\\(bar\\\\)\" . 1)            Substring \"bar\" within all occurrences of
-                                 \"fubar\" in the value of
-                                 `font-lock-keyword-face'.
-
-  (\"fubar\" . fubar-face)         Occurrences of \"fubar\" in the value of
-                                 `fubar-face'.
-
-  (\"foo\\\\|bar\" 0 foo-bar-face t) Occurrences of either \"foo\" or \"bar\" in the
-                                 value of `foo-bar-face', even if already
-                                 highlighted.
+where HIGHLIGHT should be either MATCH-HIGHLIGHT or MATCH-ANCHORED.
 
-  (fubar-match 1 fubar-face)     The first subexpression within all
-                                 occurrences of whatever the function
-                                 `fubar-match' finds and matches in the value
-                                 of `fubar-face'.
-
-  (\"\\\\<anchor\\\\>\" (0 anchor-face) (\"\\\\<item\\\\>\" nil nil (0 item-face)))
-   -------------- ---------------  ------------ --- --- -------------
-       |            |               |            |   |          |
-   MATCHER          |         ANCHOR-MATCHER     |   +------+ MATCH-HIGHLIGHT
-             MATCH-HIGHLIGHT                 PRE-MATCH-FORM |
-                                                           POST-MATCH-FORM
-
-  Discrete occurrences of \"anchor\" in the value of `anchor-face', and
-  subsequent discrete occurrences of \"item\" (on the same line) in the value
-  of `item-face'.  (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil.
-  Therefore \"item\" is initially searched for starting from the end of the
-  match of \"anchor\", and searching for subsequent instance of \"anchor\"
-  resumes from where searching for \"item\" concluded.)
+FORM is an expression, whose value should be a keyword element,
+evaluated when the keyword is (first) used in a buffer.  This feature
+can be used to provide a keyword that can only be generated when Font
+Lock mode is actually turned on.
 
 For highlighting single items, typically only MATCH-HIGHLIGHT is required.
-However, if an item or (typically) several items are to be highlighted
-following the instance of another item (the anchor) then MATCH-ANCHORED may be
-required.
+However, if an item or (typically) items is to be highlighted following the
+instance of another item (the anchor) then MATCH-ANCHORED may be required.
+
+MATCH-HIGHLIGHT should be of the form:
+
+ (MATCH FACENAME OVERRIDE LAXMATCH)
+
+Where MATCHER can be either the regexp to search for, a variable
+containing the regexp to search for, or the function to call to make
+the search (called with one argument, the limit of the search).  MATCH
+is the subexpression of MATCHER to be highlighted.  FACENAME is either
+a symbol naming a face, or an expression whose value is the face name
+to use.  If you want FACENAME to be a symbol that evaluates to a face,
+use a form like \"(progn sym)\".
+
+OVERRIDE and LAXMATCH are flags.  If OVERRIDE is t, existing fontification may
+be overwritten.  If `keep', only parts not already fontified are highlighted.
+If `prepend' or `append', existing fontification is merged with the new, in
+which the new or existing fontification, respectively, takes precedence.
+If LAXMATCH is non-nil, no error is signalled if there is no MATCH in MATCHER.
+
+For example, an element of the form highlights (if not already highlighted):
+
+ \"\\\\\\=<foo\\\\\\=>\"		Discrete occurrences of \"foo\" in the value of the
+			variable `font-lock-keyword-face'.
+ (\"fu\\\\(bar\\\\)\" . 1)	Substring \"bar\" within all occurrences of \"fubar\" in
+			the value of `font-lock-keyword-face'.
+ (\"fubar\" . fubar-face)	Occurrences of \"fubar\" in the value of `fubar-face'.
+ (\"foo\\\\|bar\" 0 foo-bar-face t)
+			Occurrences of either \"foo\" or \"bar\" in the value
+			of `foo-bar-face', even if already highlighted.
+
+MATCH-ANCHORED should be of the form:
+
+ (MATCHER PRE-MATCH-FORM POST-MATCH-FORM MATCH-HIGHLIGHT ...)
+
+Where MATCHER is as for MATCH-HIGHLIGHT with one exception; see below.
+PRE-MATCH-FORM and POST-MATCH-FORM are evaluated before the first, and after
+the last, instance MATCH-ANCHORED's MATCHER is used.  Therefore they can be
+used to initialize before, and cleanup after, MATCHER is used.  Typically,
+PRE-MATCH-FORM is used to move to some position relative to the original
+MATCHER, before starting with MATCH-ANCHORED's MATCHER.  POST-MATCH-FORM might
+be used to move, before resuming with MATCH-ANCHORED's parent's MATCHER.
+
+For example, an element of the form highlights (if not already highlighted):
+
+ (\"\\\\\\=<anchor\\\\\\=>\" (0 anchor-face) (\"\\\\\\=<item\\\\\\=>\" nil nil (0 item-face)))
+
+ Discrete occurrences of \"anchor\" in the value of `anchor-face', and subsequent
+ discrete occurrences of \"item\" (on the same line) in the value of `item-face'.
+ (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil.  Therefore \"item\" is
+ initially searched for starting from the end of the match of \"anchor\", and
+ searching for subsequent instance of \"anchor\" resumes from where searching
+ for \"item\" concluded.)
+
+The above-mentioned exception is as follows.  The limit of the MATCHER search
+defaults to the end of the line after PRE-MATCH-FORM is evaluated.
+However, if PRE-MATCH-FORM returns a position greater than the position after
+PRE-MATCH-FORM is evaluated, that position is used as the limit of the search.
+It is generally a bad idea to return a position greater than the end of the
+line, i.e., cause the MATCHER search to span lines.
+
+Note that the MATCH-ANCHORED feature is experimental; in the future, we may
+replace it with other ways of providing this functionality.
 
 These regular expressions should not match text which spans lines.  While
-\\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating when you
-edit the buffer does not, since it considers text one line at a time.
+\\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating
+when you edit the buffer does not, since it considers text one line at a time.
 
-Be very careful composing regexps for this list; the wrong pattern can
-dramatically slow things down!
-")
+Be very careful composing regexps for this list;
+the wrong pattern can dramatically slow things down!")
 ;;;###autoload
 (make-variable-buffer-local 'font-lock-keywords)
 
@@ -580,55 +552,25 @@
 
 ;; #### barf gag retch.  Horrid FSF lossage that we need to
 ;; keep around for compatibility with font-lock-keywords that
-;; forget to properly quote their faces.  I tried just let-binding
-;; them when we eval the face expression, but that failes because
-;; some	files actually use the variables directly in their init code
-;; without quoting them. --ben
+;; forget to properly quote their faces.
 (defvar font-lock-comment-face 'font-lock-comment-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-doc-string-face 'font-lock-doc-string-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-string-face 'font-lock-string-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-keyword-face 'font-lock-keyword-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-function-name-face 'font-lock-function-name-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-variable-name-face 'font-lock-variable-name-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-type-face 'font-lock-type-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-reference-face 'font-lock-reference-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 (defvar font-lock-preprocessor-face 'font-lock-preprocessor-face
-  "This variable should not be set.
-It is present only for horrid FSF compatibility reasons.
-The corresponding face should be set using `edit-faces' or the
-`set-face-*' functions.")
+  "Don't even think of using this.")
 
 (defconst font-lock-face-list
   '(font-lock-comment-face
@@ -642,10 +584,11 @@
     font-lock-preprocessor-face
     font-lock-warning-face))
 
+;; #### There should be an emulation for the old font-lock-use-*
+;; settings!
+
 (defface font-lock-comment-face
   '((((class color) (background dark)) (:foreground "gray80"))
-    ;; blue4 is hardly different from black on windows.
-    (((class color) (background light) (type mswindows)) (:foreground "blue"))
     (((class color) (background light)) (:foreground "blue4"))
     (((class grayscale) (background light))
      (:foreground "DimGray" :bold t :italic t))
@@ -668,17 +611,11 @@
   '((((class color) (background dark)) (:foreground "light coral"))
     (((class color) (background light)) (:foreground "green4"))
     (t (:bold t)))
-  "Font Lock mode face used to highlight documentation strings.
-This is currently supported only in Lisp-like modes, which are those
-with \"lisp\" or \"scheme\" in their name.  You can explicitly make
-a mode Lisp-like by putting a non-nil `font-lock-lisp-like' property
-on the major mode's symbol."
+  "Font Lock mode face used to highlight documentation strings."
   :group 'font-lock-faces)
 
 (defface font-lock-keyword-face
   '((((class color) (background dark)) (:foreground "cyan"))
-    ;; red4 is hardly different from black on windows.
-    (((class color) (background light) (type mswindows)) (:foreground "red"))
     (((class color) (background light)) (:foreground "red4"))
     (((class grayscale) (background light)) (:foreground "LightGray" :bold t))
     (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
@@ -688,11 +625,6 @@
 
 (defface font-lock-function-name-face
   '((((class color) (background dark)) (:foreground "aquamarine"))
-    ;; brown4 is hardly different from black on windows.
-    ;; I changed it to red because IMO it's pointless and ugly to
-    ;; use a million slightly different colors for niggly syntactic
-    ;; differences. --ben
-    (((class color) (background light) (type mswindows)) (:foreground "red"))
     (((class color) (background light)) (:foreground "brown4"))
     (t (:bold t :underline t)))
   "Font Lock mode face used to highlight function names."
@@ -887,20 +819,28 @@
     (set (make-local-variable 'font-lock-mode) on-p)
     (cond (on-p
 	   (font-lock-set-defaults-1)
+	   (make-local-hook 'before-revert-hook)
+	   (make-local-hook 'after-revert-hook)
+	   ;; If buffer is reverted, must clean up the state.
+	   (add-hook 'before-revert-hook 'font-lock-revert-setup nil t)
+	   (add-hook 'after-revert-hook 'font-lock-revert-cleanup nil t)
 	   (run-hooks 'font-lock-mode-hook)
 	   (cond (font-lock-fontified
 		  nil)
 		 ((or (null maximum-size) (<= (buffer-size) maximum-size))
 		  (font-lock-fontify-buffer))
 		 (font-lock-verbose
-		  (lprogress-display 'font-lock
-			     "Fontifying %s... buffer too big." 'abort
-			     (buffer-name)))))
+		  (lmessage 'command "Fontifying %s... buffer too big."
+		    (buffer-name)))))
 	  (font-lock-fontified
 	   (setq font-lock-fontified nil)
+	   (remove-hook 'before-revert-hook 'font-lock-revert-setup t)
+	   (remove-hook 'after-revert-hook 'font-lock-revert-cleanup t)
 	   (font-lock-unfontify-region (point-min) (point-max))
 	   (font-lock-thing-lock-cleanup))
 	  (t
+	   (remove-hook 'before-revert-hook 'font-lock-revert-setup t)
+	   (remove-hook 'after-revert-hook 'font-lock-revert-cleanup t)
 	   (font-lock-thing-lock-cleanup)))
     (redraw-modeline)))
 
@@ -1023,46 +963,45 @@
 (defun font-lock-unfontify-region (beg end &optional loudly)
   (funcall font-lock-unfontify-region-function beg end loudly))
 
+;; #### In these functions, the FSF is careful to do
+;; (save-restriction
+;;   (widen)
+;; before anything else.  Should we copy?
 (defun font-lock-default-fontify-buffer ()
   (interactive)
-  ;; if we don't widen, then the C code will fail to
-  ;; realize that we're inside a comment.
-  (save-restriction
-    (widen)
-    (let ((was-on font-lock-mode)
-	  (font-lock-verbose (or font-lock-verbose (interactive-p)))
-	  (font-lock-message-threshold 0)
-	  (aborted nil))
-      ;; Turn it on to run hooks and get the right font-lock-keywords.
-      (or was-on (font-lock-mode 1))
-      (font-lock-unfontify-region (point-min) (point-max) t)
-      ;;    (buffer-syntactic-context-flush-cache)
+  (let ((was-on font-lock-mode)
+	(font-lock-verbose (or font-lock-verbose (interactive-p)))
+	(font-lock-message-threshold 0)
+	(aborted nil))
+    ;; Turn it on to run hooks and get the right font-lock-keywords.
+    (or was-on (font-lock-mode 1))
+    (font-lock-unfontify-region (point-min) (point-max) t)
+;;    (buffer-syntactic-context-flush-cache)
     
-      ;; If a ^G is typed during fontification, abort the fontification, but
-      ;; return normally (do not signal.)  This is to make it easy to abort
-      ;; fontification if it's taking a long time, without also causing the
-      ;; buffer not to pop up.  If a real abort is desired, the user can ^G
-      ;; again.
-      ;;
-      ;; Possibly this should happen down in font-lock-fontify-region instead
-      ;; of here, but since that happens from the after-change-hook (meaning
-      ;; much more frequently) I'm afraid of the bad consequences of stealing
-      ;; the interrupt character at inopportune times.
-      ;;
-      (condition-case nil
-	  (save-excursion
-	    (font-lock-fontify-region (point-min) (point-max)))
-	(t
-	 (setq aborted t)))
+    ;; If a ^G is typed during fontification, abort the fontification, but
+    ;; return normally (do not signal.)  This is to make it easy to abort
+    ;; fontification if it's taking a long time, without also causing the
+    ;; buffer not to pop up.  If a real abort is desired, the user can ^G
+    ;; again.
+    ;;
+    ;; Possibly this should happen down in font-lock-fontify-region instead
+    ;; of here, but since that happens from the after-change-hook (meaning
+    ;; much more frequently) I'm afraid of the bad consequences of stealing
+    ;; the interrupt character at inopportune times.
+    ;;
+    (condition-case nil
+	(save-excursion
+	  (font-lock-fontify-region (point-min) (point-max)))
+      (quit
+       (setq aborted t)))
 
-      (or was-on			; turn it off if it was off.
-	  (let ((font-lock-fontified nil)) ; kludge to prevent defontification
-	    (font-lock-mode 0)))
-      (set (make-local-variable 'font-lock-fontified) t)
-      (when (and aborted font-lock-verbose)
-	(lprogress-display 'font-lock "Fontifying %s... aborted."
-			   'abort (buffer-name))))
-    (run-hooks 'font-lock-after-fontify-buffer-hook)))
+    (or was-on		; turn it off if it was off.
+	(let ((font-lock-fontified nil)) ; kludge to prevent defontification
+	  (font-lock-mode 0)))
+    (set (make-local-variable 'font-lock-fontified) t)
+    (when (and aborted font-lock-verbose)
+	(lmessage 'command  "Fontifying %s... aborted." (buffer-name))))
+  (run-hooks 'font-lock-after-fontify-buffer-hook))
 
 (defun font-lock-default-unfontify-buffer ()
   (font-lock-unfontify-region (point-min) (point-max))
@@ -1100,7 +1039,7 @@
 (defun font-lock-default-unfontify-region (beg end &optional maybe-loudly)
   (when (and maybe-loudly font-lock-verbose
 	     (>= (- end beg) font-lock-message-threshold))
-    (lprogress-display 'font-lock "Fontifying %s..." 0 (buffer-name)))
+    (lmessage 'progress "Fontifying %s..." (buffer-name)))
   (let ((modified (buffer-modified-p))
 	(buffer-undo-list t) (inhibit-read-only t)
 	buffer-file-name buffer-file-truename)
@@ -1108,7 +1047,10 @@
     (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil))))
 
 ;; Following is the original FSF version (similar to our original
-;; version, before the deferred stuff was added).
+;; version, before all the crap I added below).
+;;
+;; Probably that crap should either be fixed up so it works better,
+;; or tossed away.
 ;;
 ;; I think that lazy-lock v2 tries to do something similar.
 ;; Those efforts should be merged.
@@ -1122,99 +1064,111 @@
 ;	(progn (goto-char beg) (beginning-of-line) (point))
 ;	(progn (goto-char end) (forward-line 1) (point))))))
 
-(defvar font-lock-always-fontify-immediately nil
-  "Set this to non-nil to disable font-lock deferral.
-Otherwise, changes to existing text will not be processed until the
-next redisplay cycle, avoiding excessive fontification when many
-buffer modifications are performed or a buffer is reverted.")
+(defvar font-lock-old-extent nil)
+(defvar font-lock-old-len 0)
 
-(defvar font-lock-pending-extent-table (make-hash-table :weakness 'key))
-(defvar font-lock-range-table (make-range-table))
+(defun font-lock-fontify-glumped-region ()
+  ;; even if something goes wrong in the fontification, mark the glumped
+  ;; region as fontified; otherwise, the same error might get signaled
+  ;; after every command.
+  (unwind-protect
+      ;; buffer/extent may be deleted.
+      (if (and (extent-live-p font-lock-old-extent)
+	       (buffer-live-p (extent-object font-lock-old-extent)))
+	  (save-excursion
+	    (set-buffer (extent-object font-lock-old-extent))
+	    (font-lock-after-change-function-1
+	     (extent-start-position font-lock-old-extent)
+	     (extent-end-position font-lock-old-extent)
+	     font-lock-old-len)))
+    (detach-extent font-lock-old-extent)
+    (setq font-lock-old-extent nil)))
 
 (defun font-lock-pre-idle-hook ()
-  (condition-case font-lock-error
-      (if (> (hash-table-count font-lock-pending-extent-table) 0)
-	  (font-lock-fontify-pending-extents))
-    (error (warn "Error caught in `font-lock-pre-idle-hook': %s"
-		 font-lock-error))))
+  (condition-case nil
+      (if font-lock-old-extent
+	  (font-lock-fontify-glumped-region))
+    (error (warn "Error caught in `font-lock-pre-idle-hook'"))))
+
+(defvar font-lock-always-fontify-immediately nil
+  "Set this to non-nil to disable font-lock deferral.")
 
 ;;; called when any modification is made to buffer text.  This function
-;;; remembers the changed ranges until the next redisplay, at which point
-;;; the extents are merged and pruned, and the resulting ranges fontified.
-;;; This function could easily be adapted to other after-change-functions.
+;;; attempts to glump adjacent changes together so that excessive
+;;; fontification is avoided.  This function could easily be adapted
+;;; to other after-change-functions.
 
 (defun font-lock-after-change-function (beg end old-len)
-  (when font-lock-mode
-    (let ((ex (make-extent beg end)))
-      (set-extent-property ex 'detachable nil)
-      (set-extent-property ex 'end-open nil)
-      (let ((exs (gethash (current-buffer) font-lock-pending-extent-table)))
-	(push ex exs)
-	(puthash (current-buffer) exs font-lock-pending-extent-table)))
-    (if font-lock-always-fontify-immediately
-	(font-lock-fontify-pending-extents))))
+  (let ((obeg (and font-lock-old-extent
+		   (extent-start-position font-lock-old-extent)))
+	(oend (and font-lock-old-extent
+		   (extent-end-position font-lock-old-extent)))
+	(bc-end (+ beg old-len)))
+
+    ;; If this change can't be merged into the glumped one,
+    ;; we need to fontify the glumped one right now.
+    (if (and font-lock-old-extent
+	     (or (not (eq (current-buffer)
+			  (extent-object font-lock-old-extent)))
+		 (< bc-end obeg)
+		 (> beg oend)))
+	(font-lock-fontify-glumped-region))
+  
+    (if font-lock-old-extent
+	;; Update glumped region.
+	(progn
+	  ;; Any characters in the before-change region that are
+	  ;; outside the glumped region go into the glumped
+	  ;; before-change region.
+	  (if (> bc-end oend)
+	      (setq font-lock-old-len (+ font-lock-old-len (- bc-end oend))))
+	  (if (> obeg beg)
+	      (setq font-lock-old-len (+ font-lock-old-len (- obeg beg))))
+	  ;; New glumped region is the union of the glumped region
+	  ;; and the new region.
+	  (set-extent-endpoints font-lock-old-extent
+				(min obeg beg)
+				(max oend end)))
 
-(defun font-lock-fontify-pending-extents ()
-  ;; ah, the beauty of mapping functions.
-  ;; this function is actually shorter than the old version, which handled
-  ;; only one buffer and one contiguous region!
-  (save-match-data
-    (maphash
-     #'(lambda (buffer exs)
-	 ;; remove first, to avoid infinite reprocessing if error
-	 (remhash buffer font-lock-pending-extent-table)
-	 (when (buffer-live-p buffer)
-	   (clear-range-table font-lock-range-table)
-	   (with-current-buffer buffer
-	     (save-excursion
-	       (save-restriction
-		 ;; if we don't widen, then the C code will fail to
-		 ;; realize that we're inside a comment.
-		 (widen)
-		 (let ((zmacs-region-stays
-			zmacs-region-stays)) ; protect from change!
-		   (mapc
-		    #'(lambda (ex)
-			;; paranoia.
-			(when (and (extent-live-p ex)
-				   (not (extent-detached-p ex)))
-			  ;; first expand the ranges to full lines, because
-			  ;; that is what will be fontified; then use a
-			  ;; range table to merge the ranges.
-			  (let* ((beg (extent-start-position ex))
-				 (end (extent-end-position ex))
-				 (beg (progn (goto-char beg)
-					     (beginning-of-line)
-					     (point)))
-				 (end (progn (goto-char end)
-					     (forward-line 1)
-					     (point))))
-			    (detach-extent ex)
-			    (put-range-table beg end t
-					     font-lock-range-table))))
-		    exs)
-		   (map-range-table
-		    #'(lambda (beg end val)
-			;; Maybe flush the internal cache used by
-			;; syntactically-sectionize.  (It'd be nice if this
-			;; was more automatic.)  Any deletions mean the
-			;; cache is invalid, and insertions at beginning or
-			;; end of line mean that the bol cache might be
-			;; invalid.
-			;; #### This code has been commented out for some time
-			;; now and is bit-rotting.  Someone should look into
-			;; this.
-;;			(if (or change-was-deletion (bobp)
-;;				(= (preceding-char) ?\n))
-;;			    (buffer-syntactic-context-flush-cache))
-			;; #### This creates some unnecessary progress gauges.
-;;			(if (and (= beg (point-min))
-;;				 (= end (point-max)))
-;;			    (font-lock-fontify-buffer)
-;;			  (font-lock-fontify-region beg end)))
-			(font-lock-fontify-region beg end))
-		    font-lock-range-table)))))))
-     font-lock-pending-extent-table)))
+      ;; No glumped region, so create one.
+      (setq font-lock-old-extent (make-extent beg end))
+      (set-extent-property font-lock-old-extent 'detachable nil)
+      (set-extent-property font-lock-old-extent 'end-open nil)
+      (setq font-lock-old-len old-len))
+
+    (if font-lock-always-fontify-immediately
+	(font-lock-fontify-glumped-region))))
+
+(defun font-lock-after-change-function-1 (beg end old-len)
+  (if (null font-lock-mode)
+      nil
+    (save-excursion
+      (save-restriction
+	;; if we don't widen, then fill-paragraph (and any command that
+	;; operates on a narrowed region) confuses things, because the C
+	;; code will fail to realize that we're inside a comment.
+	(widen)
+	(save-match-data
+	  (let ((zmacs-region-stays zmacs-region-stays)) ; protect from change!
+	    (goto-char beg)
+	    ;; Maybe flush the internal cache used by syntactically-sectionize.
+	    ;; (It'd be nice if this was more automatic.)  Any deletions mean
+	    ;; the cache is invalid, and insertions at beginning or end of line
+	    ;; mean that the bol cache might be invalid.
+;;	    (if (or (> old-len 0) (bobp) (= (preceding-char) ?\n))
+;;		(buffer-syntactic-context-flush-cache))
+
+	    ;; Always recompute the whole line.
+	    (goto-char end)
+	    (forward-line 1)
+	    (setq end (point))
+	    (goto-char beg)
+	    (beginning-of-line)
+	    (setq beg (point))
+	    ;; Rescan between start of line from `beg' and start of line after
+	    ;; `end'.
+	    (font-lock-fontify-region beg end)))))))
+
 
 ;; Syntactic fontification functions.
 
@@ -1330,16 +1284,6 @@
 ;    ;; Clean up.
 ;    (and prev (remove-text-properties prev end '(face nil)))))
 
-(defun font-lock-lisp-like (mode)
-  ;; Note: (or (get mode 'font-lock-lisp-like) (string-match ...)) is
-  ;; not enough because the property needs to be able to specify a nil
-  ;; value.
-  (if (plist-member (symbol-plist mode) 'font-lock-lisp-like)
-      (get mode 'font-lock-lisp-like)
-    ;; If the property is not specified, guess.  Similar logic exists
-    ;; in add-log, but I think this encompasses more modes.
-    (string-match "lisp\\|scheme" (symbol-name mode))))
-
 (defun font-lock-fontify-syntactically-region (start end &optional loudly)
   "Put proper face on each string and comment between START and END.
 START should be at the beginning of a line."
@@ -1347,29 +1291,26 @@
       nil
     (when (and font-lock-verbose
 	       (>= (- end start) font-lock-message-threshold))
-      (lprogress-display 'font-lock "Fontifying %s... (syntactically)" 5
-		 (buffer-name)))
+      (lmessage 'progress "Fontifying %s... (syntactically...)"
+	(buffer-name)))
     (font-lock-unfontify-region start end loudly)
     (goto-char start)
     (if (> end (point-max)) (setq end (point-max)))
-    (let ((lisp-like (font-lock-lisp-like major-mode)))
-      (syntactically-sectionize
-       #'(lambda (s e context depth)
-	   (let (face)
-	     (cond ((eq context 'string)
-		    (setq face
-			  ;; #### It would be nice if we handled
-			  ;; Python and other non-Lisp languages with
-			  ;; docstrings correctly.
-			  (if (and lisp-like (= depth 1))
-			      ;; really we should only use this if
-			      ;;  in position 3 depth 1, but that's
-			      ;;  too expensive to compute.
-			      'font-lock-doc-string-face
-			    'font-lock-string-face)))
-		   ((or (eq context 'comment)
-			(eq context 'block-comment))
-		    (setq face 'font-lock-comment-face)
+    (syntactically-sectionize
+      #'(lambda (s e context depth)
+	  (let (face)
+	    (cond ((eq context 'string)
+		   ;;#### Should only do this is Lisp-like modes!
+		   (setq face
+			 (if (= depth 1)
+			     ;; really we should only use this if
+			     ;;  in position 3 depth 1, but that's
+			     ;;  too expensive to compute.
+			     'font-lock-doc-string-face
+			   'font-lock-string-face)))
+		  ((or (eq context 'comment)
+		       (eq context 'block-comment))
+		   (setq face 'font-lock-comment-face)
 ;		 ;; Don't fontify whitespace at the beginning of lines;
 ;		 ;;  otherwise comment blocks may not line up with code.
 ;		 ;; (This is sometimes a good idea, sometimes not; in any
@@ -1382,9 +1323,9 @@
 ;		       (skip-chars-forward " \t\n")
 ;		       (setq s (point)))
 		   ))
-	     (font-lock-set-face s e face)))
-       start end)
-      )))
+	    (font-lock-set-face s e face)))
+      start end)
+    ))
 
 ;;; Additional text property functions.
 
@@ -1531,22 +1472,18 @@
 START should be at the beginning of a line."
   (let ((loudly (and font-lock-verbose
 		     (>= (- end start) font-lock-message-threshold))))
-    (let* ((case-fold-search font-lock-keywords-case-fold-search)
-	   (keywords (cdr (if (eq (car-safe font-lock-keywords) t)
-			      font-lock-keywords
-			    (font-lock-compile-keywords))))
-	   (bufname (buffer-name)) 
-	   (progress 5) (old-progress 5)
-	   (iter 0)
-	   (nkeywords (length keywords))
-	   keyword matcher highlights)
+    (let ((case-fold-search font-lock-keywords-case-fold-search)
+	  (keywords (cdr (if (eq (car-safe font-lock-keywords) t)
+			     font-lock-keywords
+			   (font-lock-compile-keywords))))
+	  (bufname (buffer-name)) (count 0)
+	  keyword matcher highlights)
       ;;
       ;; Fontify each item in `font-lock-keywords' from `start' to `end'.
-      ;; In order to measure progress accurately we need to know how
-      ;; many keywords we have and how big the region is. Then progress
-      ;; is ((pos - start)/ (end - start) * nkeywords 
-      ;; 	+ iteration / nkeywords) * 100
       (while keywords
+	(when loudly (lmessage 'progress "Fontifying %s... (regexps..%s)"
+		       bufname
+		       (make-string (setq count (1+ count)) ?.)))
 	;;
 	;; Find an occurrence of `matcher' from `start' to `end'.
 	(setq keyword (car keywords) matcher (car keyword))
@@ -1555,14 +1492,6 @@
 		    (if (stringp matcher)
 			(re-search-forward matcher end t)
 		      (funcall matcher end)))
-	  ;; calculate progress
-	  (setq progress
-		(+ (/ (* (- (point) start) 95) (* (- end start) nkeywords))
-		   (/ (* iter 95) nkeywords) 5))
-	  (when (and loudly (> progress old-progress))
-	    (lprogress-display 'font-lock "Fontifying %s... (regexps)"
-			       progress bufname))
-	  (setq old-progress progress)
 	  ;; Apply each highlight to this instance of `matcher', which may be
 	  ;; specific highlights or more keywords anchored to `matcher'.
 	  (setq highlights (cdr keyword))
@@ -1576,9 +1505,8 @@
 		  (and end (goto-char end)))
 	      (font-lock-fontify-anchored-keywords (car highlights) end))
 	    (setq highlights (cdr highlights))))
-	(setq iter (1+ iter))
 	(setq keywords (cdr keywords))))
-    (if loudly (lprogress-display 'font-lock "Fontifying %s... " 100 (buffer-name)))))
+    (if loudly (lmessage 'progress "Fontifying %s... done." (buffer-name)))))
 
 
 ;; Various functions.
@@ -1602,6 +1530,19 @@
 	((and (boundp 'lazy-lock-mode) lazy-lock-mode)
 	 (lazy-lock-after-fontify-buffer))))
 
+;; If the buffer is about to be reverted, it won't be fontified afterward.
+(defun font-lock-revert-setup ()
+  (setq font-lock-fontified nil))
+
+;; If the buffer has just been reverted, normally that turns off
+;; Font Lock mode.  So turn the mode back on if necessary.
+;; sb 1999-03-03 -- The above comment no longer appears to be operative as
+;; the first call to normal-mode *will* restore the font-lock state and
+;; this call forces a second font-locking to occur when reverting a buffer,
+;; which is wasteful at best.
+;(defalias 'font-lock-revert-cleanup 'turn-on-font-lock)
+(defun font-lock-revert-cleanup ())
+
 
 ;; Various functions.
 
@@ -2381,9 +2322,8 @@
 	 '("\\<\\(false\\|null\\|true\\)\\>" (1 font-lock-keyword-face))
 
 	 ;; Class names:
-	 (list (concat "\\<\\(class\\|interface\\)\\>\\s *"
-		       java-font-lock-identifier-regexp)
-	       2 'font-lock-function-name-face)
+	 (list (concat "\\<class\\>\\s *" java-font-lock-identifier-regexp)
+	       1 'font-lock-function-name-face)
         
 	 ;; Package declarations:
 	 (list (concat "\\<\\(package\\|import\\)\\>\\s *"
@@ -2504,11 +2444,11 @@
 		  (goto-char (match-end 1))
 		  (goto-char (match-end 0))
 		  (1 font-lock-variable-name-face))))))
-	
+
   ;; Modifier keywords and Java doc tags
   (setq java-font-lock-keywords-3
 	(append
- 
+
 	 '(
 	   ;; Feature scoping:
 	   ;; These must come first or the Modifiers from keywords-1 will
@@ -2518,11 +2458,11 @@
 	   ("\\<protected\\>" 0 font-lock-preprocessor-face)
 	   ("\\<public\\>"    0 font-lock-reference-face))
 	 java-font-lock-keywords-2
- 
+
 	 (list
 
-	  ;; Javadoc tags
-	  '("@\\(author\\|deprecated\\|exception\\|throws\\|param\\|return\\|see\\|since\\|version\\|serial\\|serialData\\|serialField\\)\\s "
+	  ;; Java doc tags
+	  '("@\\(author\\|exception\\|param\\|return\\|see\\|version\\)\\s "
 	    0 font-lock-keyword-face t)
 
 	  ;; Doc tag - Parameter identifiers
@@ -2530,32 +2470,19 @@
 		1 'font-lock-variable-name-face t)
 
 	  ;; Doc tag - Exception types
-	  (list (concat "@\\(exception\\|throws\\)\\s +"
+	  (list (concat "@exception\\ s*"
 			java-font-lock-identifier-regexp)
-		'(2 (if (equal (char-after (match-end 0)) ?.)
+		'(1 (if (equal (char-after (match-end 0)) ?.)
 			font-lock-reference-face font-lock-type-face) t)
 		(list (concat "\\=\\." java-font-lock-identifier-regexp)
 		      '(goto-char (match-end 0)) nil
 		      '(1 (if (equal (char-after (match-end 0)) ?.)
 			      'font-lock-reference-face 'font-lock-type-face) t)))
-    
+
 	  ;; Doc tag - Cross-references, usually to methods 
 	  '("@see\\s +\\(\\S *[^][ \t\n\r\f(){},.;:]\\)"
 	    1 font-lock-function-name-face t)
-    
-	  ;; Doc tag - docRoot (1.3)
-	  '("\\({ *@docRoot *}\\)"
-	    0 font-lock-keyword-face t)
-	  ;; Doc tag - beaninfo, unofficial but widely used, even by Sun
-	  '("\\(@beaninfo\\)"
-	    0 font-lock-keyword-face t)
-	  ;; Doc tag - Links
-	  '("{ *@link\\s +\\([^}]+\\)}"
-	    0 font-lock-keyword-face t)
-	  ;; Doc tag - Links
-	  '("{ *@link\\s +\\(\\(\\S +\\)\\|\\(\\S +\\s +\\S +\\)\\) *}"
-	    1 font-lock-function-name-face t)
-    
+
 	  )))
   )