]> code.delx.au - gnu-emacs/blobdiff - lisp/hilit-chg.el
Close bug#3992.
[gnu-emacs] / lisp / hilit-chg.el
index 19cecb1c8be8ec7cbce838878af531f105487dd4..ec9c88fd6ec97f6e79d320ac028b7934f6b2843a 100644 (file)
@@ -1,17 +1,17 @@
 ;;; hilit-chg.el --- minor mode displaying buffer changes with special face
 
 ;;; hilit-chg.el --- minor mode displaying buffer changes with special face
 
-;; Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+;;   2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Author: Richard Sharman <rsharman@pobox.com>
 ;; Keywords: faces
 
 ;; This file is part of GNU Emacs.
 
 
 ;; Author: Richard Sharman <rsharman@pobox.com>
 ;; Keywords: faces
 
 ;; 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
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, 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 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
 ;; 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:
 
 ;; A minor mode: "Highlight Changes mode".
 
 ;;; Commentary:
 
 ;; A minor mode: "Highlight Changes mode".
-;;
 
 
-;; Highlight Changes mode has 2 submodes: active and passive.
-;; When active, changes to the buffer are displayed in a different face.
-;; When passive, any existing displayed changes are saved and new ones
-;; recorded but are not displayed differently.
-;; Why active and passive?  Having the changes visible can be handy when you
-;; want the information but very distracting otherwise.  So, you can keep
-;; Highlight Changes mode in passive state while you make your changes, toggle
-;; it on to active mode to see them, then toggle it back off to avoid
-;; distraction.
-;;
-;; When active, changes are displayed in the `highlight-changes' face.
-;; When text is deleted, the following character is displayed in the
-;; `highlight-changes-delete' face.
-;;
+;; When Highlight Changes mode is enabled changes to the buffer are
+;; recorded with a text property.  Normally these ranges of text are
+;; displayed in a distinctive face.  However, sometimes it is
+;; desirable to temporarily not see these changes.  Instead of
+;; disabling Highlight Changes mode (which would remove the text property)
+;; use the command highlight-changes-visible-mode.
+
+;; Two faces are supported: one for changed or inserted text and
+;; another for the first character after text has been deleted.
+
+;; When Highlight Changes mode is on (even if changes are not visible)
+;; you can go to the next or previous change with
+;; `highlight-changes-next-change' or `highlight-changes-previous-change'.
+
+;; Command highlight-compare-with-file shows changes in this file
+;; compared with another file (by default the previous version of the
+;; file).
 ;;
 ;;
+;; The command highlight-compare-buffers compares two buffers by
+;; highlighting their differences.
+
 ;; You can "age" different sets of changes by using
 ;; `highlight-changes-rotate-faces'.  This rotates through a series
 ;; of different faces, so you can distinguish "new" changes from "older"
 ;; changes.  You can customize these "rotated" faces in two ways.  You can
 ;; either explicitly define each face by customizing
 ;; `highlight-changes-face-list'.  If, however, the faces differ from
 ;; You can "age" different sets of changes by using
 ;; `highlight-changes-rotate-faces'.  This rotates through a series
 ;; of different faces, so you can distinguish "new" changes from "older"
 ;; changes.  You can customize these "rotated" faces in two ways.  You can
 ;; either explicitly define each face by customizing
 ;; `highlight-changes-face-list'.  If, however, the faces differ from
-;; the `highlight-changes' face only in the foreground color, you can simply set
+;; `highlight-changes-face' only in the foreground color, you can simply set
 ;; `highlight-changes-colors'.  If `highlight-changes-face-list' is nil when
 ;; the faces are required they will be constructed from
 ;; `highlight-changes-colors'.
 ;; `highlight-changes-colors'.  If `highlight-changes-face-list' is nil when
 ;; the faces are required they will be constructed from
 ;; `highlight-changes-colors'.
-;;
-;;
-;; When a Highlight Changes mode is on (either active or passive) you can go
-;; to the next or previous change with `highlight-changes-next-change' and
-;; `highlight-changes-previous-change'.
-;;
-;;
-;; You can also use the command highlight-compare-with-file to show changes
-;; in this file compared with another file (typically the previous version
-;; of the file).  The command highlight-compare-buffers can be used to
-;; compare two buffers.
-;;
-;;
-;; There are currently three hooks run by `highlight-changes-mode':
-;; `highlight-changes-enable-hook'  - is run when Highlight Changes mode
-;;                                 is initially enabled for a buffer.
-;; `highlight-changes-disable-hook' - is run when Highlight Changes mode
-;;                                 is turned off.
-;; `highlight-changes-toggle-hook'  - is run each time `highlight-changes-mode'
-;;                                 is called.  Typically this is when
-;;                                 toggling between active and passive
-;;                                 modes.  The variable
-;;                                 `highlight-changes-mode' contains the new
-;;                                 state (`active' or `passive'.)
-;;
-;;
+
+;; You can automatically rotate faces when the buffer is saved;
+;; see function `highlight-changes-rotate-faces' for how to do this.
+
+;; The hook `highlight-changes-mode-hook' is called when
+;; Highlight Changes mode is turned on or off.
+;; When it called, variable `highlight-changes-mode' has been updated
+;; to the new value.
 ;;
 ;; Example usage:
 ;;
 ;; Example usage:
-;; (defun my-highlight-changes-enable-hook ()
-;;   (add-hook 'write-file-functions 'highlight-changes-rotate-faces nil t)
-;; )
-;;
-;; (defun my-highlight-changes-disable-hook ()
-;;   (remove-hook 'write-file-functions 'highlight-changes-rotate-faces t)
-;; )
-;;
-;; (add-hook 'highlight-changes-enable-hook 'my-highlight-changes-enable-hook)
-;; (add-hook 'highlight-changes-disable-hook
-;;             'my-highlight-changes-disable-hook)
+;; (defun my-highlight-changes-mode-hook ()
+;;   (if highlight-changes-mode
+;;       (add-hook 'write-file-functions 'highlight-changes-rotate-faces nil t)
+;;     (remove-hook 'write-file-functions 'highlight-changes-rotate-faces t)
+;;     ))
 
 
 
 
-;;           Explicit vs. Implicit
+;;           Automatically enabling Highlight Changes mode
 ;;
 
 ;; Normally, Highlight Changes mode is turned on explicitly in a buffer.
 ;;
 ;; If you prefer to have it automatically invoked you can do it as
 ;; follows.
 ;;
 
 ;; Normally, Highlight Changes mode is turned on explicitly in a buffer.
 ;;
 ;; If you prefer to have it automatically invoked you can do it as
 ;; follows.
-;;
+
 ;; 1. Most modes have a major-hook, typically called MODE-hook.  You
 ;; can use `add-hook' to call `highlight-changes-mode'.
 ;; 1. Most modes have a major-hook, typically called MODE-hook.  You
 ;; can use `add-hook' to call `highlight-changes-mode'.
-;;
+
 ;;   Example:
 ;;     (add-hook 'c-mode-hook 'highlight-changes-mode)
 ;;   Example:
 ;;     (add-hook 'c-mode-hook 'highlight-changes-mode)
-;;
-;;  If you want to make it start up in passive mode (regardless of the
-;;  setting of highlight-changes-initial-state):
-;;      (add-hook 'emacs-lisp-mode-hook
-;;         (lambda ()
-;;           (highlight-changes-mode 'passive)))
-;;
+
 ;; However, this cannot be done for Fundamental mode for there is no
 ;; such hook.
 ;; However, this cannot be done for Fundamental mode for there is no
 ;; such hook.
-;;
-;; 2. You can use the function `global-highlight-changes'
+
+;; 2. You can use the function `global-highlight-changes-mode'
 ;;
 ;; This function, which is fashioned after the way `global-font-lock' works,
 ;; toggles on or off global Highlight Changes mode.  When activated, it turns
 ;; on Highlight Changes mode in all "suitable" existing buffers and will turn
 ;; it on in new "suitable" buffers to be created.
 ;;
 ;; This function, which is fashioned after the way `global-font-lock' works,
 ;; toggles on or off global Highlight Changes mode.  When activated, it turns
 ;; on Highlight Changes mode in all "suitable" existing buffers and will turn
 ;; it on in new "suitable" buffers to be created.
-;;
+
 ;; A buffer's "suitability" is determined by variable
 ;; A buffer's "suitability" is determined by variable
-;; `highlight-changes-global-modes', as follows.  If the variable is
+;; `highlight-changes-global-modes', as follows.  If it is
 ;; * nil  -- then no buffers are suitable;
 ;; * a function -- this function is called and the result is used.  As
 ;;   an example, if the value is `buffer-file-name' then all buffers
 ;;   who are visiting files are suitable, but others (like dired
 ;;   buffers) are not;
 ;; * nil  -- then no buffers are suitable;
 ;; * a function -- this function is called and the result is used.  As
 ;;   an example, if the value is `buffer-file-name' then all buffers
 ;;   who are visiting files are suitable, but others (like dired
 ;;   buffers) are not;
-;; * a list -- then the buffer is suitable iff its mode is in the
+;; * a list -- then the buffer is suitable if and only if its mode is in the
 ;;   list, except if the first element is `not', in which case the test
 ;;   is reversed (i.e. it is a list of unsuitable modes).
 ;; * Otherwise, the buffer is suitable if its name does not begin with
 ;;   ` ' or `*' and if `buffer-file-name' returns true.
 ;;   list, except if the first element is `not', in which case the test
 ;;   is reversed (i.e. it is a list of unsuitable modes).
 ;; * Otherwise, the buffer is suitable if its name does not begin with
 ;;   ` ' or `*' and if `buffer-file-name' returns true.
-;;
 
 
+;; To enable it for future sessions put this in your ~/.emacs file:
+;;             (global-highlight-changes-mode t)
 
 
 ;;     Possible bindings:
 ;; (global-set-key '[C-right] 'highlight-changes-next-change)
 ;; (global-set-key '[C-left]  'highlight-changes-previous-change)
 ;;
 
 
 ;;     Possible bindings:
 ;; (global-set-key '[C-right] 'highlight-changes-next-change)
 ;; (global-set-key '[C-left]  'highlight-changes-previous-change)
 ;;
-;;     Other interactive functions (which could be bound if desired):
+;;     Other interactive functions (that could be bound if desired):
 ;; highlight-changes-mode
 ;; highlight-changes-mode
+;; highlight-changes-toggle-visibility
 ;; highlight-changes-remove-highlight
 ;; highlight-changes-remove-highlight
-;; highlight-changes-rotate-faces
 ;; highlight-compare-with-file
 ;; highlight-compare-buffers
 ;; highlight-compare-with-file
 ;; highlight-compare-buffers
-
-;;
-;; You can automatically rotate faces when the buffer is saved;
-;; see function `highlight-changes-rotate-faces' for how to do this.
-;;
+;; highlight-changes-rotate-faces
 
 
 ;;; Bugs:
 
 
 ;;; Bugs:
 
 ;; - having different faces for deletion and non-deletion: is it
 ;;   really worth the hassle?
 
 ;; - having different faces for deletion and non-deletion: is it
 ;;   really worth the hassle?
-;; - should have better hooks:  when should they be run?
 ;; - highlight-compare-with-file should allow RCS files - e.g. nice to be
 ;;   able to say show changes compared with version 2.1.
 ;; - highlight-compare-with-file should allow RCS files - e.g. nice to be
 ;;   able to say show changes compared with version 2.1.
-;; - Maybe we should have compare-with-buffer as well.  (When I tried
-;;   a while back I ran into a problem with ediff-buffers-internal.)
 
 
 ;;; History:
 
 
 ;;; History:
 ;; Dec 2003
 ;; - Use require for ediff stuff
 ;; - Added highlight-compare-buffers
 ;; Dec 2003
 ;; - Use require for ediff stuff
 ;; - Added highlight-compare-buffers
+;; Mar 2008
+;; - Made highlight-changes-mode like other modes (toggle on/off)
+;; - Added new command highlight-changes-visible-mode to replace the
+;;   previous active/passive aspect of highlight-changes-mode.
+;; - Removed highlight-changes-toggle-hook
+;; - Put back eval-and-compile inadvertently dropped
+;; May 2008
+;; - Removed highlight-changes-disable-hook and highlight-changes-enable-hook
+;;   because highlight-changes-mode-hook can do both.
 
 ;;; Code:
 
 
 ;;; Code:
 
     (t (:inverse-video t)))
   "Face used for highlighting changes."
   :group 'highlight-changes)
     (t (:inverse-video t)))
   "Face used for highlighting changes."
   :group 'highlight-changes)
-;; backward-compatibility alias
-(put 'highlight-changes-face 'face-alias 'highlight-changes)
+(define-obsolete-face-alias 'highlight-changes-face
+  'highlight-changes "22.1")
 
 ;; This looks pretty ugly, actually.  Maybe the underline should be removed.
 (defface highlight-changes-delete
 
 ;; This looks pretty ugly, actually.  Maybe the underline should be removed.
 (defface highlight-changes-delete
     (t (:inverse-video t)))
   "Face used for highlighting deletions."
   :group 'highlight-changes)
     (t (:inverse-video t)))
   "Face used for highlighting deletions."
   :group 'highlight-changes)
-;; backward-compatibility alias
-(put 'highlight-changes-delete-face 'face-alias 'highlight-changes-delete)
-
+(define-obsolete-face-alias 'highlight-changes-delete-face
+  'highlight-changes-delete "22.1")
 
 
 ;; A (not very good) default list of colors to rotate through.
 
 
 ;; A (not very good) default list of colors to rotate through.
-;;
+(define-obsolete-variable-alias 'highlight-changes-colours
+                                'highlight-changes-colors "22.1")
+
 (defcustom highlight-changes-colors
   (if (eq (frame-parameter nil 'background-mode) 'light)
       ;; defaults for light background:
       '( "magenta" "blue" "darkgreen" "chocolate" "sienna4" "NavyBlue")
       ;; defaults for dark background:
     '("yellow" "magenta" "blue" "maroon" "firebrick" "green4" "DarkOrchid"))
 (defcustom highlight-changes-colors
   (if (eq (frame-parameter nil 'background-mode) 'light)
       ;; defaults for light background:
       '( "magenta" "blue" "darkgreen" "chocolate" "sienna4" "NavyBlue")
       ;; defaults for dark background:
     '("yellow" "magenta" "blue" "maroon" "firebrick" "green4" "DarkOrchid"))
-  "*Colors used by `highlight-changes-rotate-faces'.
+  "Colors used by `highlight-changes-rotate-faces'.
 The newest rotated change will be displayed in the first element of this list,
 the next older will be in the second element etc.
 
 The newest rotated change will be displayed in the first element of this list,
 the next older will be in the second element etc.
 
@@ -253,40 +230,42 @@ colors then use this, if you want fancier faces then set
   :type '(repeat color)
   :group 'highlight-changes)
 
   :type '(repeat color)
   :group 'highlight-changes)
 
-(define-obsolete-variable-alias 'highlight-changes-colours
-                                'highlight-changes-colors "22.1")
+;; When you invoke highlight-changes-mode, should highlight-changes-visible-mode
+;; be on or off?
 
 
+(define-obsolete-variable-alias 'highlight-changes-initial-state
+  'highlight-changes-visibility-initial-state "23.1")
 
 
-;; If you invoke highlight-changes-mode with no argument, should it start in
-;; active or passive mode?
-;;
-(defcustom highlight-changes-initial-state 'active
-  "*What state (active or passive) Highlight Changes mode should start in.
-This is used when `highlight-changes-mode' is called with no argument.
-This variable must be set to one of the symbols `active' or `passive'."
-  :type '(choice (const :tag "Active" active)
-                (const :tag "Passive" passive))
-  :group 'highlight-changes)
+(defcustom highlight-changes-visibility-initial-state t
+  "Controls whether changes are initially visible in Highlight Changes mode.
 
 
-(defcustom highlight-changes-global-initial-state 'passive
-  "*What state global Highlight Changes mode should start in.
-This is used if `global-highlight-changes' is called with no argument.
-This variable must be set to either `active' or `passive'."
-  :type '(choice (const :tag "Active" active)
-                (const :tag "Passive" passive))
+This controls the initial value of `highlight-changes-visible-mode'.
+When a buffer is in Highlight Changes mode the function
+`highlight-changes-visible-mode' is used to toggle the mode on or off."
+  :type 'boolean
   :group 'highlight-changes)
 
   :group 'highlight-changes)
 
-;; The strings displayed in the mode-line for the minor mode:
-(defcustom highlight-changes-active-string " +Chg"
-  "*The string used when Highlight Changes mode is in the active state.
+;; highlight-changes-global-initial-state has been removed
+
+
+
+;; These are the strings displayed in the mode-line for the minor mode:
+(define-obsolete-variable-alias 'highlight-changes-active-string
+  'highlight-changes-visible-string "23.1")
+
+(defcustom highlight-changes-visible-string " +Chg"
+  "The string used when in Highlight Changes mode and changes are visible.
 This should be set to nil if no indication is desired, or to
 a string with a leading space."
   :type '(choice string
                 (const :tag "None"  nil))
   :group 'highlight-changes)
 
 This should be set to nil if no indication is desired, or to
 a string with a leading space."
   :type '(choice string
                 (const :tag "None"  nil))
   :group 'highlight-changes)
 
-(defcustom highlight-changes-passive-string " -Chg"
-  "*The string used when Highlight Changes mode is in the passive state.
+(define-obsolete-variable-alias 'highlight-changes-passive-string
+  'highlight-changes-invisible-string "23.1")
+
+(defcustom highlight-changes-invisible-string " -Chg"
+  "The string used when in Highlight Changes mode and changes are hidden.
 This should be set to nil if no indication is desired, or to
 a string with a leading space."
   :type '(choice string
 This should be set to nil if no indication is desired, or to
 a string with a leading space."
   :type '(choice string
@@ -294,7 +273,7 @@ a string with a leading space."
   :group 'highlight-changes)
 
 (defcustom highlight-changes-global-modes t
   :group 'highlight-changes)
 
 (defcustom highlight-changes-global-modes t
-  "*Determine whether a buffer is suitable for global Highlight Changes mode.
+  "Determine whether a buffer is suitable for global Highlight Changes mode.
 
 A function means call that function to decide: if it returns non-nil,
 the buffer is suitable.
 
 A function means call that function to decide: if it returns non-nil,
 the buffer is suitable.
@@ -306,11 +285,11 @@ modes which are not suitable.
 A value of t means the buffer is suitable if it is visiting a file and
 its name does not begin with ` ' or `*'.
 
 A value of t means the buffer is suitable if it is visiting a file and
 its name does not begin with ` ' or `*'.
 
-A value of nil means no buffers are suitable for `global-highlight-changes'
+A value of nil means no buffers are suitable for `global-highlight-changes-mode'
 \(effectively disabling the mode).
 
 Example:
 \(effectively disabling the mode).
 
 Example:
-        (c-mode c++-mode)
+       (c-mode c++-mode)
 means that Highlight Changes mode is turned on for buffers in C and C++
 modes only."
   :type '(choice
 means that Highlight Changes mode is turned on for buffers in C and C++
 modes only."
   :type '(choice
@@ -325,10 +304,8 @@ modes only."
          )
   :group 'highlight-changes)
 
          )
   :group 'highlight-changes)
 
-(defvar global-highlight-changes nil)
-
 (defcustom highlight-changes-global-changes-existing-buffers nil
 (defcustom highlight-changes-global-changes-existing-buffers nil
-  "*If non-nil, toggling global Highlight Changes mode affects existing buffers.
+  "If non-nil, toggling global Highlight Changes mode affects existing buffers.
 Normally, `global-highlight-changes' affects only new buffers (to be
 created).  However, if `highlight-changes-global-changes-existing-buffers'
 is non-nil, then turning on `global-highlight-changes' will turn on
 Normally, `global-highlight-changes' affects only new buffers (to be
 created).  However, if `highlight-changes-global-changes-existing-buffers'
 is non-nil, then turning on `global-highlight-changes' will turn on
@@ -337,6 +314,78 @@ remove it from existing buffers."
   :type 'boolean
   :group 'highlight-changes)
 
   :type 'boolean
   :group 'highlight-changes)
 
+;; These are for internal use.
+
+(defvar hilit-chg-list nil)
+(defvar hilit-chg-string " ??")
+
+(make-variable-buffer-local 'hilit-chg-string)
+
+
+
+;;; Functions...
+
+;;;###autoload
+(define-minor-mode highlight-changes-mode
+  "Toggle Highlight Changes mode.
+
+With ARG, turn Highlight Changes mode on if and only if arg is positive.
+
+In Highlight Changes mode changes are recorded with a text property.
+Normally they are displayed in a distinctive face, but command
+\\[highlight-changes-visible-mode] can be used to toggles this
+on and off.
+
+Other functions for buffers in this mode include:
+\\[highlight-changes-next-change] - move point to beginning of next change
+\\[highlight-changes-previous-change] - move to beginning of previous change
+\\[highlight-changes-remove-highlight] - remove the change face from the region
+\\[highlight-changes-rotate-faces] - rotate different \"ages\" of changes
+through        various faces.
+\\[highlight-compare-with-file] - mark text as changed by comparing this
+buffer with the contents of a file
+\\[highlight-compare-buffers] highlights differences between two buffers."
+  nil                  ;; init-value
+  hilit-chg-string     ;; lighter
+  nil                  ;; keymap
+  (if (or (display-color-p)
+         (and (fboundp 'x-display-grayscale-p) (x-display-grayscale-p)))
+      (progn
+       (if (and (eq this-command 'global-highlight-changes-mode)
+                (not highlight-changes-global-changes-existing-buffers))
+           ;; The global mode has toggled the value of the mode variable,
+           ;; but not other changes have been mode, so we are safe
+           ;; to retoggle it.
+           (setq highlight-changes-mode (not highlight-changes-mode)))
+       (if highlight-changes-mode
+           ;; it is being turned on
+           (hilit-chg-set)
+         ;; mode is turned off
+         (hilit-chg-clear)))
+    (message "Highlight Changes mode requires color or grayscale display")))
+
+
+;;;###autoload
+(define-minor-mode highlight-changes-visible-mode
+  "Toggle visiblility of changes when buffer is in Highlight Changes mode.
+
+This mode only has an effect when Highlight Changes mode is on.
+It allows toggling between whether or not the changed text is displayed
+in a distinctive face.
+
+The default value can be customized with variable
+`highlight-changes-visibility-initial-state'
+
+This command does not itself set highlight-changes mode."
+
+  t            ;; init-value
+  nil          ;; lighter
+  nil          ;; keymap
+
+  (hilit-chg-update)
+  )
+
+
 (defun hilit-chg-cust-fix-changes-face-list (w wc &optional event)
   ;; When customization function `highlight-changes-face-list' inserts a new
   ;; face it uses the default face.  We don't want the user to modify this
 (defun hilit-chg-cust-fix-changes-face-list (w wc &optional event)
   ;; When customization function `highlight-changes-face-list' inserts a new
   ;; face it uses the default face.  We don't want the user to modify this
@@ -383,7 +432,7 @@ remove it from existing buffers."
 
 
 (defcustom highlight-changes-face-list nil
 
 
 (defcustom highlight-changes-face-list nil
-  "*A list of faces used when rotating changes.
+  "A list of faces used when rotating changes.
 Normally the variable is initialized to nil and the list is created from
 `highlight-changes-colors' when needed.  However, you can set this variable
 to any list of faces.  You will have to do this if you want faces which
 Normally the variable is initialized to nil and the list is created from
 `highlight-changes-colors' when needed.  However, you can set this variable
 to any list of faces.  You will have to do this if you want faces which
@@ -398,32 +447,12 @@ Otherwise, this list will be constructed when needed from
          )
   :group 'highlight-changes)
 
          )
   :group 'highlight-changes)
 
-;; ========================================================================
-
-;; These shouldn't be changed!
-
-(defvar highlight-changes-mode nil)
-(defvar hilit-chg-list nil)
-(defvar hilit-chg-string " ??")
-(or (assq 'highlight-changes-mode minor-mode-alist)
-    (setq minor-mode-alist
-         (cons '(highlight-changes-mode hilit-chg-string) minor-mode-alist)
-         ))
-(make-variable-buffer-local 'highlight-changes-mode)
-(make-variable-buffer-local 'hilit-chg-string)
-
-
-(require 'ediff-init)
-(require 'ediff-util)
-
-
-;;; Functions...
 
 (defun hilit-chg-map-changes (func &optional start-position end-position)
 
 (defun hilit-chg-map-changes (func &optional start-position end-position)
-  "Call function FUNC for each region used by Highlight Changes mode."
-  ;; if start-position is nil, (point-min) is used
-  ;; if end-position is nil, (point-max) is used
-  ;; FUNC is called with 3 params: property start stop
+  "Call function FUNC for each region used by Highlight Changes mode.
+If START-POSITION is nil, (point-min) is used.
+If END-POSITION is nil, (point-max) is used.
+FUNC is called with 3 params: PROPERTY START STOP."
   (let ((start (or start-position (point-min)))
        (limit (or end-position (point-max)))
        prop end)
   (let ((start (or start-position (point-min)))
        (limit (or end-position (point-max)))
        prop end)
@@ -438,8 +467,8 @@ Otherwise, this list will be constructed when needed from
 (defun hilit-chg-display-changes (&optional beg end)
   "Display face information for Highlight Changes mode.
 
 (defun hilit-chg-display-changes (&optional beg end)
   "Display face information for Highlight Changes mode.
 
-An overlay containing a change face is added from the information
-in the text property of type `hilit-chg'.
+An overlay from BEG to END containing a change face is added from the
+information in the text property of type `hilit-chg'.
 
 This is the opposite of `hilit-chg-hide-changes'."
   (hilit-chg-map-changes 'hilit-chg-make-ov beg end))
 
 This is the opposite of `hilit-chg-hide-changes'."
   (hilit-chg-map-changes 'hilit-chg-make-ov beg end))
@@ -448,16 +477,15 @@ This is the opposite of `hilit-chg-hide-changes'."
 (defun hilit-chg-make-ov (prop start end)
   (or prop
       (error "hilit-chg-make-ov: prop is nil"))
 (defun hilit-chg-make-ov (prop start end)
   (or prop
       (error "hilit-chg-make-ov: prop is nil"))
-  ;; for the region make change overlays corresponding to
-  ;; the text property 'hilit-chg
+  ;; For the region create overlays with a distincive face
+  ;; and the text property 'hilit-chg.
   (let ((ov (make-overlay start end))
   (let ((ov (make-overlay start end))
-       face)
-    (if (eq prop 'hilit-chg-delete)
-       (setq face 'highlight-changes-delete)
-      (setq face (nth 1 (member prop hilit-chg-list))))
+       (face (if (eq prop 'hilit-chg-delete)
+                  'highlight-changes-delete
+                (nth 1 (member prop hilit-chg-list)))))
     (if face
        (progn
     (if face
        (progn
-         ;; We must mark the face, that is the purpose of the overlay
+         ;; We must mark the face, that is the purpose of the overlay.
          (overlay-put ov 'face face)
          ;; I don't think we need to set evaporate since we should
          ;; be controlling them!
          (overlay-put ov 'face face)
          ;; I don't think we need to set evaporate since we should
          ;; be controlling them!
@@ -476,14 +504,12 @@ containing the change information is retained.
 
 This is the opposite of `hilit-chg-display-changes'."
   (let ((start (or beg (point-min)))
 
 This is the opposite of `hilit-chg-display-changes'."
   (let ((start (or beg (point-min)))
-       (limit (or end (point-max)))
-       p ov)
-    (setq p (overlays-in start limit))
-    (while p
+       (limit (or end (point-max))))
+    (dolist (p (overlays-in start limit))
       ;; don't delete the overlay if it isn't ours!
       ;; don't delete the overlay if it isn't ours!
-      (if (overlay-get (car p) 'hilit-chg)
-         (delete-overlay (car p)))
-      (setq p (cdr p)))))
+      (if (overlay-get p 'hilit-chg)
+         (delete-overlay p)))))
+
 
 (defun hilit-chg-fixup (beg end)
   "Fix change overlays in region between BEG and END.
 
 (defun hilit-chg-fixup (beg end)
   "Fix change overlays in region between BEG and END.
@@ -491,36 +517,31 @@ This is the opposite of `hilit-chg-display-changes'."
 Ensure the overlays agree with the changes as determined from
 the text properties of type `hilit-chg'."
   ;; Remove or alter overlays in region beg..end
 Ensure the overlays agree with the changes as determined from
 the text properties of type `hilit-chg'."
   ;; Remove or alter overlays in region beg..end
-  (let (ov-start ov-end         props q)
-    ;; temp for debugging:
-    ;; (or (eq highlight-changes-mode 'active)
-    ;;  (error "hilit-chg-fixup called but Highlight Changes mode not active"))
-    (dolist (ov (overlays-in beg end))
-      ;; Don't alter overlays that are not ours.
-      (when (overlay-get ov 'hilit-chg)
-       (let ((ov-start (overlay-start ov))
-             (ov-end (overlay-end ov)))
-         (if (< ov-start beg)
-             (progn
-               (move-overlay ov ov-start beg)
-               (if (> ov-end end)
-                   (progn
-                     (setq props (overlay-properties ov))
-                     (setq ov (make-overlay end ov-end))
-                     (while props
-                       (overlay-put ov (car props)(car (cdr props)))
-                       (setq props (cdr (cdr props)))))))
-           (if (> ov-end end)
-               (move-overlay ov end ov-end)
-             (delete-overlay ov))))))
-    (hilit-chg-display-changes beg end)))
+  (remove-overlays beg end 'hilit-chg t)
+  (hilit-chg-display-changes beg end))
+
+;; Inspired by font-lock.  Something like this should be moved to subr.el.
+(defmacro highlight-save-buffer-state (&rest body)
+  "Bind variables according to VARLIST and eval BODY restoring buffer state."
+  (declare (indent 0) (debug t))
+  (let ((modified (make-symbol "modified")))
+    `(let* ((,modified (buffer-modified-p))
+            (inhibit-modification-hooks t)
+            deactivate-mark
+            ;; So we don't check the file's mtime.
+            buffer-file-name
+            buffer-file-truename)
+       (progn
+         ,@body)
+       (unless ,modified
+         (restore-buffer-modified-p nil)))))
 
 ;;;###autoload
 (defun highlight-changes-remove-highlight (beg end)
   "Remove the change face from the region between BEG and END.
 This allows you to manually remove highlighting from uninteresting changes."
   (interactive "r")
 
 ;;;###autoload
 (defun highlight-changes-remove-highlight (beg end)
   "Remove the change face from the region between BEG and END.
 This allows you to manually remove highlighting from uninteresting changes."
   (interactive "r")
-  (let ((after-change-functions nil))
+  (highlight-save-buffer-state
     (remove-text-properties beg end '(hilit-chg nil))
     (hilit-chg-fixup beg end)))
 
     (remove-text-properties beg end '(hilit-chg nil))
     (hilit-chg-fixup beg end)))
 
@@ -541,55 +562,62 @@ This allows you to manually remove highlighting from uninteresting changes."
          (type 'hilit-chg)
          old)
       (if undo-in-progress
          (type 'hilit-chg)
          old)
       (if undo-in-progress
-         (if (eq highlight-changes-mode 'active)
+         (if (and highlight-changes-mode
+                  highlight-changes-visible-mode)
              (hilit-chg-fixup beg end))
              (hilit-chg-fixup beg end))
-       (if (and (= beg end) (> leng-before 0))
-           ;; deletion
-           (progn
-             ;; The eolp and bolp tests are a kludge!  But they prevent
-             ;; rather nasty looking displays when deleting text at the end
-             ;; of line, such as normal corrections as one is typing and
-             ;; immediately makes a correction, and when deleting first
-             ;; character of a line.
-;;;          (if (= leng-before 1)
-;;;              (if (eolp)
-;;;                  (setq beg-decr 0 end-incr 0)
-;;;                (if (bolp)
-;;;                    (setq beg-decr 0))))
-;;;          (setq beg (max (- beg beg-decr) (point-min)))
-             (setq end (min (+ end end-incr) (point-max)))
-             (setq type 'hilit-chg-delete))
-         ;; Not a deletion.
-         ;; Most of the time the following is not necessary, but
-         ;; if the current text was marked as a deletion then
-         ;; the old overlay is still in effect, so if we add some
-         ;; text then remove the deletion marking, but set it to
+        (highlight-save-buffer-state
+          (if (and (= beg end) (> leng-before 0))
+              ;; deletion
+              (progn
+                ;; The eolp and bolp tests are a kludge!  But they prevent
+                ;; rather nasty looking displays when deleting text at the end
+                ;; of line, such as normal corrections as one is typing and
+                ;; immediately makes a correction, and when deleting first
+                ;; character of a line.
+                ;; (if (= leng-before 1)
+                ;;     (if (eolp)
+                ;;         (setq beg-decr 0 end-incr 0)
+                ;;       (if (bolp)
+                ;;     (setq beg-decr 0))))
+                ;; (setq beg (max (- beg beg-decr) (point-min)))
+                (setq end (min (+ end end-incr) (point-max)))
+                (setq type 'hilit-chg-delete))
+            ;; Not a deletion.
+            ;; Most of the time the following is not necessary, but
+            ;; if the current text was marked as a deletion then
+            ;; the old overlay is still in effect, so if we add some
+            ;; text then remove the deletion marking, but set it to
          ;; changed otherwise its highlighting disappears.
          (if (eq (get-text-property end 'hilit-chg) 'hilit-chg-delete)
              (progn
          ;; changed otherwise its highlighting disappears.
          (if (eq (get-text-property end 'hilit-chg) 'hilit-chg-delete)
              (progn
-               (remove-text-properties end (+ end 1) '(hilit-chg nil))
                (put-text-property end (+ end 1) 'hilit-chg 'hilit-chg)
                (put-text-property end (+ end 1) 'hilit-chg 'hilit-chg)
-               (if (eq highlight-changes-mode 'active)
+               (if highlight-changes-visible-mode
                    (hilit-chg-fixup beg (+ end 1))))))
                    (hilit-chg-fixup beg (+ end 1))))))
-       (unless no-property-change
-               (put-text-property beg end 'hilit-chg type))
-       (if (or (eq highlight-changes-mode 'active) no-property-change)
-           (hilit-chg-make-ov type beg end))))))
-
-(defun hilit-chg-set (value)
-  "Turn on Highlight Changes mode for this buffer."
-  (setq highlight-changes-mode value)
-  (remove-hook 'after-change-functions 'hilit-chg-set-face-on-change t)
-  (hilit-chg-make-list)
-  (if (eq highlight-changes-mode 'active)
+          (unless no-property-change
+            (put-text-property beg end 'hilit-chg type))
+          (if (or highlight-changes-visible-mode no-property-change)
+              (hilit-chg-make-ov type beg end)))))))
+
+(defun hilit-chg-update ()
+  "Update a buffer's highlight changes when visibility changed."
+  (if highlight-changes-visible-mode
+      ;; changes are visible
       (progn
       (progn
-       (setq hilit-chg-string highlight-changes-active-string)
+       (setq hilit-chg-string highlight-changes-visible-string)
        (or buffer-read-only
            (hilit-chg-display-changes)))
        (or buffer-read-only
            (hilit-chg-display-changes)))
-    ;; mode is passive
-    (setq hilit-chg-string highlight-changes-passive-string)
+    ;; changes are invisible
+    (setq hilit-chg-string highlight-changes-invisible-string)
     (or buffer-read-only
     (or buffer-read-only
-       (hilit-chg-hide-changes)))
+       (hilit-chg-hide-changes))))
+
+(defun hilit-chg-set ()
+  "Turn on Highlight Changes mode for this buffer."
+  (remove-hook 'after-change-functions 'hilit-chg-set-face-on-change t)
+  (hilit-chg-make-list)
+  (setq highlight-changes-mode t)
+  (setq highlight-changes-visible-mode highlight-changes-visibility-initial-state)
+  (hilit-chg-update)
   (force-mode-line-update)
   (add-hook 'after-change-functions 'hilit-chg-set-face-on-change nil t))
 
   (force-mode-line-update)
   (add-hook 'after-change-functions 'hilit-chg-set-face-on-change nil t))
 
@@ -598,90 +626,18 @@ This allows you to manually remove highlighting from uninteresting changes."
 This removes all saved change information."
   (if buffer-read-only
       ;; We print the buffer name because this function could be called
 This removes all saved change information."
   (if buffer-read-only
       ;; We print the buffer name because this function could be called
-      ;; on many buffers from `global-highlight-changes'.
+      ;; on many buffers from `global-highlight-changes-mode'.
       (message "Cannot remove highlighting from read-only mode buffer %s"
               (buffer-name))
     (remove-hook 'after-change-functions 'hilit-chg-set-face-on-change t)
       (message "Cannot remove highlighting from read-only mode buffer %s"
               (buffer-name))
     (remove-hook 'after-change-functions 'hilit-chg-set-face-on-change t)
-    (let ((after-change-functions nil))
+    (highlight-save-buffer-state
       (hilit-chg-hide-changes)
       (hilit-chg-map-changes
       (hilit-chg-hide-changes)
       (hilit-chg-map-changes
-       '(lambda (prop start stop)
-         (remove-text-properties start stop '(hilit-chg nil))))
-      )
+       (lambda (prop start stop)
+         (remove-text-properties start stop '(hilit-chg nil)))))
     (setq highlight-changes-mode nil)
     (setq highlight-changes-mode nil)
-    (force-mode-line-update)
-    ;; If we type:  C-u -1 M-x highlight-changes-mode
-    ;; we want to turn it off, but hilit-chg-post-command-hook
-    ;; runs and that turns it back on!
-    (remove-hook 'post-command-hook 'hilit-chg-post-command-hook)))
+    (force-mode-line-update)))
 
 
-;;;###autoload
-(defun highlight-changes-mode (&optional arg)
-  "Toggle (or initially set) Highlight Changes mode.
-
-Without an argument:
-  If Highlight Changes mode is not enabled, then enable it (in either active
-  or passive state as determined by the variable
-  `highlight-changes-initial-state'); otherwise, toggle between active
-  and passive state.
-
-With an argument ARG:
-  If ARG is positive, set state to active;
-  If ARG is zero, set state to passive;
-  If ARG is negative, disable Highlight Changes mode completely.
-
-Active state  - means changes are shown in a distinctive face.
-Passive state - means changes are kept and new ones recorded but are
-               not displayed in a different face.
-
-Functions:
-\\[highlight-changes-next-change] - move point to beginning of next change
-\\[highlight-changes-previous-change] - move to beginning of previous change
-\\[highlight-compare-with-file] - mark text as changed by comparing this
-       buffer with the contents of a file
-\\[highlight-changes-remove-highlight] - remove the change face from the region
-\\[highlight-changes-rotate-faces] - rotate different \"ages\" of changes \
-through
-       various faces
-
-Hook variables:
-`highlight-changes-enable-hook'  - when enabling Highlight Changes mode
-`highlight-changes-toggle-hook'  - when entering active or passive state
-`highlight-changes-disable-hook' - when turning off Highlight Changes mode"
-  (interactive "P")
-  (if (or (display-color-p)
-         (and (fboundp 'x-display-grayscale-p) (x-display-grayscale-p)))
-      (let ((was-on highlight-changes-mode)
-           (new-highlight-changes-mode
-            (cond
-             ((null arg)
-              ;; no arg => toggle (or set to active initially)
-              (if highlight-changes-mode
-                  (if (eq highlight-changes-mode 'active) 'passive 'active)
-                highlight-changes-initial-state))
-             ;; an argument is given
-             ((eq arg 'active)
-              'active)
-             ((eq arg 'passive)
-              'passive)
-             ((> (prefix-numeric-value arg) 0)
-              'active)
-             ((< (prefix-numeric-value arg) 0)
-              nil)
-             (t
-              'passive))))
-       (if new-highlight-changes-mode
-           ;; mode is turned on -- but may be passive
-           (progn
-             (hilit-chg-set new-highlight-changes-mode)
-             (or was-on
-                 ;; run highlight-changes-enable-hook once
-                 (run-hooks 'highlight-changes-enable-hook))
-             (run-hooks 'highlight-changes-toggle-hook))
-         ;; mode is turned off
-         (run-hooks 'highlight-changes-disable-hook)
-         (hilit-chg-clear)))
-    (message "Highlight Changes mode requires color or grayscale display")))
 
 ;;;###autoload
 (defun highlight-changes-next-change ()
 
 ;;;###autoload
 (defun highlight-changes-next-change ()
@@ -775,7 +731,7 @@ Hook variables:
 
 ;;;###autoload
 (defun highlight-changes-rotate-faces ()
 
 ;;;###autoload
 (defun highlight-changes-rotate-faces ()
-  "Rotate the faces used by Highlight Changes mode.
+  "Rotate the faces if in Highlight Changes mode and the changes are visible.
 
 Current changes are displayed in the face described by the first element
 of `highlight-changes-face-list', one level older changes are shown in
 
 Current changes are displayed in the face described by the first element
 of `highlight-changes-face-list', one level older changes are shown in
@@ -788,9 +744,7 @@ this, eval the following in the buffer to be saved:
 
   \(add-hook 'write-file-functions 'highlight-changes-rotate-faces nil t)"
   (interactive)
 
   \(add-hook 'write-file-functions 'highlight-changes-rotate-faces nil t)"
   (interactive)
-  ;; If not in active mode do nothing but don't complain because this
-  ;; may be bound to a hook.
-  (when (eq highlight-changes-mode 'active)
+  (when (and highlight-changes-mode highlight-changes-visible-mode)
     (let ((modified (buffer-modified-p))
          (inhibit-modification-hooks t))
       ;; The `modified' related code tries to combine two goals: (1) Record the
     (let ((modified (buffer-modified-p))
          (inhibit-modification-hooks t))
       ;; The `modified' related code tries to combine two goals: (1) Record the
@@ -798,11 +752,12 @@ this, eval the following in the buffer to be saved:
       ;; of the current buffer due to the rotation.  We do this by inserting (in
       ;; `buffer-undo-list') entries restoring buffer-modified-p to nil before
       ;; and after the entry for the rotation.
       ;; of the current buffer due to the rotation.  We do this by inserting (in
       ;; `buffer-undo-list') entries restoring buffer-modified-p to nil before
       ;; and after the entry for the rotation.
-      (unless modified
-       ;; Install the "before" entry.
-       (setq buffer-undo-list
-             (cons '(apply restore-buffer-modified-p nil)
-                   buffer-undo-list)))
+      ;; FIXME: this is no good: we need to test the `modified' state at the
+      ;; time of the undo, not at the time of the "do", otherwise the undo
+      ;; may erroneously clear the modified flag.  --Stef
+      ;; (unless modified
+      ;;   ;; Install the "before" entry.
+      ;;   (push '(apply restore-buffer-modified-p nil) buffer-undo-list))
       (unwind-protect
          (progn
            ;; ensure hilit-chg-list is made and up to date
       (unwind-protect
          (progn
            ;; ensure hilit-chg-list is made and up to date
@@ -811,14 +766,11 @@ this, eval the following in the buffer to be saved:
            (hilit-chg-hide-changes)
            ;; for each change text property, increment it
            (hilit-chg-map-changes 'hilit-chg-bump-change)
            (hilit-chg-hide-changes)
            ;; for each change text property, increment it
            (hilit-chg-map-changes 'hilit-chg-bump-change)
-           ;; and display them all if active
-           (if (eq highlight-changes-mode 'active)
-               (hilit-chg-display-changes)))
+           ;; and display them
+           (hilit-chg-display-changes))
        (unless modified
        (unless modified
-         ;; Install the "after" entry.
-         (setq buffer-undo-list
-               (cons '(apply restore-buffer-modified-p nil)
-                     buffer-undo-list))
+         ;; Install the "after" entry.  FIXME: See above.
+         ;; (push '(apply restore-buffer-modified-p nil) buffer-undo-list)
 
          (restore-buffer-modified-p nil)))))
   ;; This always returns nil so it is safe to use in write-file-functions
 
          (restore-buffer-modified-p nil)))))
   ;; This always returns nil so it is safe to use in write-file-functions
@@ -833,6 +785,8 @@ this, eval the following in the buffer to be saved:
   "Get differences between two buffers and set highlight changes.
 Both buffers are done unless optional parameter MARKUP-A-ONLY
 is non-nil."
   "Get differences between two buffers and set highlight changes.
 Both buffers are done unless optional parameter MARKUP-A-ONLY
 is non-nil."
+  (eval-and-compile
+    (require 'ediff-util))
   (save-window-excursion
     (let* (change-info
           change-a change-b
   (save-window-excursion
     (let* (change-info
           change-a change-b
@@ -861,9 +815,9 @@ is non-nil."
       (or file-b
          (setq temp-b (setq file-b (ediff-make-temp-file buf-b nil))))
       (set-buffer buf-a)
       (or file-b
          (setq temp-b (setq file-b (ediff-make-temp-file buf-b nil))))
       (set-buffer buf-a)
-      (highlight-changes-mode 'active)
+      (highlight-changes-mode 1)
       (or markup-a-only (with-current-buffer buf-b
       (or markup-a-only (with-current-buffer buf-b
-                         (highlight-changes-mode 'active)))
+                         (highlight-changes-mode 1)))
       (setq change-info (hilit-chg-get-diff-info buf-a file-a buf-b file-b))
 
 
       (setq change-info (hilit-chg-get-diff-info buf-a file-a buf-b file-b))
 
 
@@ -937,20 +891,23 @@ read in temporarily but the buffer is deleted.
 If the buffer is read-only, differences will be highlighted but no property
 changes are made, so \\[highlight-changes-next-change] and
 \\[highlight-changes-previous-change] will not work."
 If the buffer is read-only, differences will be highlighted but no property
 changes are made, so \\[highlight-changes-next-change] and
 \\[highlight-changes-previous-change] will not work."
-  (interactive (list
-             (read-file-name
-              "File to compare with? " ;; prompt
-              ""                       ;; directory
-              nil                      ;; default
-              'yes                     ;; must exist
-              (let ((f (buffer-file-name (current-buffer))))
-                (if f
-                    (progn
-                      (setq f (make-backup-file-name f))
-                      (or (file-exists-p f)
-                          (setq f nil)))
-                  )
-                f))))
+  (interactive
+   (let ((file buffer-file-name)
+        (file-name nil)
+        (file-dir nil))
+     (and file
+         (setq file-name (file-name-nondirectory file)
+               file-dir (file-name-directory file)))
+     (setq file-name (make-backup-file-name file-name))
+     (unless (file-exists-p file-name)
+            (setq file-name nil))
+     (list (read-file-name
+           "Find to compare with: "    ;; prompt
+           file-dir                    ;; directory
+           nil                         ;; default
+           nil                         ;; existing
+           file-name)                  ;; initial
+          )))
   (let* ((buf-a (current-buffer))
         (file-a (buffer-file-name))
         (existing-buf (get-file-buffer file-b))
   (let* ((buf-a (current-buffer))
         (file-a (buffer-file-name))
         (existing-buf (get-file-buffer file-b))
@@ -1018,125 +975,19 @@ changes are made, so \\[highlight-changes-next-change] and
     ;; No point in returning a value, since this is a hook function.
     ))
 
     ;; No point in returning a value, since this is a hook function.
     ))
 
-;; ======================= automatic stuff ==============
-
-;; Global Highlight Changes mode is modeled after Global Font-lock mode.
-;; Three hooks are used to gain control.  When Global Changes Mode is
-;; enabled, `find-file-hook' and `change-major-mode-hook' are set.
-;; `find-file-hook' is called when visiting a file, the new mode is
-;; known at this time.
-;; `change-major-mode-hook' is called when a buffer is changing mode.
-;; This could be because of finding a file in which case
-;; `find-file-hook' has already been called and has done its work.
-;; However, it also catches the case where a new mode is being set by
-;; the user.  However, it is called from `kill-all-variables' and at
-;; this time the mode is the old mode, which is not what we want.
-;; So, our function temporarily sets `post-command-hook' which will
-;; be called after the buffer has been completely set up (with the new
-;; mode).  It then removes the `post-command-hook'.
-;; One other wrinkle - every M-x command runs the `change-major-mode-hook'
-;; so we ignore this by examining the buffer name.
-
-
-(defun hilit-chg-major-mode-hook ()
-  (add-hook 'post-command-hook 'hilit-chg-post-command-hook))
-
-(defun hilit-chg-post-command-hook ()
-  ;; This is called after changing a major mode, but also after each
-  ;; M-x command, in which case the current buffer is a minibuffer.
-  ;; In that case, do not act on it here, but don't turn it off
-  ;; either, we will get called here again soon-after.
-  ;; Also, don't enable it for other special buffers.
-  (if (string-match "^[ *]"  (buffer-name))
-      nil ;; (message "ignoring this post-command-hook")
-    (remove-hook 'post-command-hook 'hilit-chg-post-command-hook)
-    ;; The following check isn't necessary, since
-    ;; hilit-chg-turn-on-maybe makes this check too.
-    (or highlight-changes-mode ;; don't turn it on if it already is
-       (hilit-chg-turn-on-maybe highlight-changes-global-initial-state))))
-
-(defun hilit-chg-check-global ()
-  ;; This is called from the find file hook.
-  (hilit-chg-turn-on-maybe highlight-changes-global-initial-state))
-
+;; ======================= global-highlight-changes-mode ==============
 
 ;;;###autoload
 
 ;;;###autoload
-(defun global-highlight-changes (&optional arg)
-  "Turn on or off global Highlight Changes mode.
-
-When called interactively:
-- if no prefix, toggle global Highlight Changes mode on or off
-- if called with a positive prefix (or just C-u) turn it on in active mode
-- if called with a zero prefix turn it on in passive mode
-- if called with a negative prefix turn it off
-
-When called from a program:
-- if ARG is nil or omitted, turn it off
-- if ARG is `active', turn it on in active mode
-- if ARG is `passive', turn it on in passive mode
-- otherwise just turn it on
-
-When global Highlight Changes mode is enabled, Highlight Changes mode is turned
-on for future \"suitable\" buffers (and for \"suitable\" existing buffers if
-variable `highlight-changes-global-changes-existing-buffers' is non-nil).
-\"Suitability\" is determined by variable `highlight-changes-global-modes'."
+(define-globalized-minor-mode global-highlight-changes-mode
+  highlight-changes-mode highlight-changes-mode-turn-on)
 
 
-  (interactive
-   (list
-    (cond
-     ((null current-prefix-arg)
-      ;; no arg => toggle it on/off
-      (setq global-highlight-changes (not global-highlight-changes)))
-     ;; positive interactive arg - turn it on as active
-     ((> (prefix-numeric-value current-prefix-arg) 0)
-      (setq global-highlight-changes t)
-      'active)
-     ;; zero interactive arg - turn it on as passive
-     ((= (prefix-numeric-value current-prefix-arg) 0)
-      (setq global-highlight-changes t)
-      'passive)
-     ;; negative interactive arg - turn it off
-     (t
-      (setq global-highlight-changes nil)
-      nil))))
-
-  (if arg
-      (progn
-       (if (eq arg 'active)
-           (setq highlight-changes-global-initial-state 'active)
-         (if (eq arg 'passive)
-             (setq highlight-changes-global-initial-state 'passive)))
-       (setq global-highlight-changes t)
-       (message "Turning ON Global Highlight Changes mode in %s state"
-                highlight-changes-global-initial-state)
-       ;; FIXME: Not sure what this was intended to do.  --Stef
-       ;; (add-hook 'hilit-chg-major-mode-hook 'hilit-chg-major-mode-hook)
-       (add-hook 'find-file-hook 'hilit-chg-check-global)
-       (if highlight-changes-global-changes-existing-buffers
-           (hilit-chg-update-all-buffers
-            highlight-changes-global-initial-state)))
-
-    (message "Turning OFF global Highlight Changes mode")
-    ;; FIXME: Not sure what this was intended to do.  --Stef
-    ;; (remove-hook 'hilit-chg-major-mode-hook 'hilit-chg-major-mode-hook)
-    (remove-hook 'post-command-hook 'hilit-chg-post-command-hook)
-    (remove-hook 'find-file-hook 'hilit-chg-check-global)
-    (if highlight-changes-global-changes-existing-buffers
-       (hilit-chg-update-all-buffers nil))))
-
-
-(defun hilit-chg-turn-on-maybe (value)
-  "Turn on Highlight Changes mode if it is appropriate for this buffer.
-
-A buffer is appropriate for Highlight Changes mode if all these are true:
-- the buffer is not a special buffer (one whose name begins with
-  `*' or ` '),
-- the buffer's mode is suitable as per variable
-  `highlight-changes-global-modes',
-- Highlight Changes mode is not already on for this buffer.
-
-This function is called from `hilit-chg-update-all-buffers' or
-from `global-highlight-changes' when turning on global Highlight Changes mode."
+(define-obsolete-function-alias
+ 'global-highlight-changes
+  'global-highlight-changes-mode "23.1")
+
+(defun highlight-changes-mode-turn-on ()
+  "See if Highlight Changes mode should be turned on for this buffer.
+This is called when `global-highlight-changes-mode' is turned on."
   (or highlight-changes-mode                   ; do nothing if already on
       (if
          (cond
   (or highlight-changes-mode                   ; do nothing if already on
       (if
          (cond
@@ -1152,29 +1003,10 @@ from `global-highlight-changes' when turning on global Highlight Changes mode."
             (and
              (not (string-match "^[ *]" (buffer-name)))
              (buffer-file-name))))
             (and
              (not (string-match "^[ *]" (buffer-name)))
              (buffer-file-name))))
-         (progn
-           (hilit-chg-set value)
-           (run-hooks 'highlight-changes-enable-hook)))))
+         (highlight-changes-mode 1))
+       ))
 
 
 
 
-(defun hilit-chg-turn-off-maybe ()
-  (if highlight-changes-mode
-      (progn
-       (run-hooks 'highlight-changes-disable-hook)
-       (hilit-chg-clear))))
-
-
-(defun hilit-chg-update-all-buffers (value)
-  (mapc
-   (function (lambda (buffer)
-              (with-current-buffer buffer
-                (if value
-                    (hilit-chg-turn-on-maybe value)
-                  (hilit-chg-turn-off-maybe))
-                )))
-   (buffer-list))
-  nil)
-
 ;;;; Desktop support.
 
 ;; Called by `desktop-create-buffer' to restore `highlight-changes-mode'.
 ;;;; Desktop support.
 
 ;; Called by `desktop-create-buffer' to restore `highlight-changes-mode'.