Error if ps-lpr-switches is not a list.
[bpt/emacs.git] / lisp / hilit-chg.el
index f670079..a167b2b 100644 (file)
@@ -1,6 +1,7 @@
 ;;; hilit-chg.el --- minor mode displaying buffer changes with special face
 
-;; Copyright (C) 1998, 2000, 2005  Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Richard Sharman <rsharman@pobox.com>
 ;; Keywords: faces
@@ -9,7 +10,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -19,8 +20,8 @@
 
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -37,9 +38,9 @@
 ;; it on to active mode to see them, then toggle it back off to avoid
 ;; distraction.
 ;;
-;; When active, changes are displayed in `highlight-changes-face'.  When
-;; text is deleted, the following character is displayed in
-;; `highlight-changes-delete-face' face.
+;; 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.
 ;;
 ;;
 ;; You can "age" different sets of changes by using
 ;; 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
-;; `highlight-changes-face' only in the foreground color, you can simply set
-;; `highlight-changes-colours'.  If `highlight-changes-face-list' is nil when
+;; the `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-colours'.
+;; `highlight-changes-colors'.
 ;;
 ;;
 ;; When a Highlight Changes mode is on (either active or passive) you can go
 ;;
 ;; Example usage:
 ;; (defun my-highlight-changes-enable-hook ()
-;;   (add-hook 'local-write-file-hooks 'highlight-changes-rotate-faces)
+;;   (add-hook 'write-file-functions 'highlight-changes-rotate-faces nil t)
 ;; )
 ;;
 ;; (defun my-highlight-changes-disable-hook ()
-;;   (remove-hook 'local-write-file-hooks 'highlight-changes-rotate-faces)
+;;   (remove-hook 'write-file-functions 'highlight-changes-rotate-faces t)
 ;; )
 ;;
 ;; (add-hook 'highlight-changes-enable-hook 'my-highlight-changes-enable-hook)
 ;;   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 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
 ;; However, having it set for non-delete changes can be annoying because all
 ;; indentation on inserts gets underlined (which can look pretty ugly!).
 
-(defface highlight-changes-face
-  '((((class color)) (:foreground "red" ))
+(defface highlight-changes
+  '((((min-colors 88) (class color)) (:foreground "red1"))
+    (((class color)) (:foreground "red" ))
     (t (:inverse-video t)))
   "Face used for highlighting changes."
   :group 'highlight-changes)
+;; backward-compatibility alias
+(put 'highlight-changes-face 'face-alias 'highlight-changes)
 
 ;; This looks pretty ugly, actually.  Maybe the underline should be removed.
-(defface highlight-changes-delete-face
-  '((((class color)) (:foreground "red" :underline t))
+(defface highlight-changes-delete
+  '((((min-colors 88) (class color)) (:foreground "red1" :underline t))
+    (((class color)) (:foreground "red" :underline t))
     (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)
 
 
 
-;; A (not very good) default list of colours to rotate through.
+;; A (not very good) default list of colors to rotate through.
 ;;
-(defcustom highlight-changes-colours
+(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"))
-  "*Colours 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.
 
 This list is used if `highlight-changes-face-list' is nil, otherwise that
 variable overrides this list.  If you only care about foreground
-colours then use this, if you want fancier faces then set
+colors then use this, if you want fancier faces then set
 `highlight-changes-face-list'."
   :type '(repeat color)
   :group 'highlight-changes)
 
+(define-obsolete-variable-alias 'highlight-changes-colours
+                                'highlight-changes-colors "22.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' should start in.
-This is used when `highlight-changes' is called with no argument.
+  "*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-global-initial-state 'passive
-  "*What state `global-highlight-changes' should start in.
+  "*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'"
+This variable must be set to either `active' or `passive'."
   :type '(choice (const :tag "Active" active)
                 (const :tag "Passive" passive))
   :group 'highlight-changes)
@@ -293,13 +303,13 @@ A list means the elements are major modes suitable for Highlight
 Changes mode, or a list whose first element is `not' followed by major
 modes which are not suitable.
 
-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'
 \(effectively disabling the mode).
 
-Examples:
+Example:
         (c-mode c++-mode)
 means that Highlight Changes mode is turned on for buffers in C and C++
 modes only."
@@ -345,18 +355,18 @@ remove it from existing buffers."
             )
          (while p
            (setq old-name (car p))
-           (setq new-name (intern (format "highlight-changes-face-%d" n)))
+           (setq new-name (intern (format "highlight-changes-%d" n)))
            (if (eq old-name new-name)
                nil
              ;; A new face has been inserted: we don't want to modify the
              ;; default face so copy it.  Better, though, (I think) is to
              ;; make a new face have the same attributes as
-             ;; highlight-changes-face .
+             ;; the `highlight-changes' face.
              (if (eq old-name 'default)
-                 (copy-face 'highlight-changes-face  new-name)
+                 (copy-face 'highlight-changes new-name)
                (copy-face old-name new-name)
                ))
-           (setq new-list (append  (list new-name) new-list))
+           (setq new-list (append (list new-name) new-list))
            (setq n (1- n))
            (setq p (cdr p)))
          (if (equal new-list (widget-value w))
@@ -375,16 +385,16 @@ remove it from existing buffers."
 (defcustom highlight-changes-face-list nil
   "*A list of faces used when rotating changes.
 Normally the variable is initialized to nil and the list is created from
-`highlight-changes-colours' when needed.  However, you can set this variable
+`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
-don't just differ from `highlight-changes-face' by the foreground colour.
+don't just differ from the `highlight-changes' face by the foreground color.
 Otherwise, this list will be constructed when needed from
-`highlight-changes-colours'."
+`highlight-changes-colors'."
   :type '(choice
          (repeat
            :notify hilit-chg-cust-fix-changes-face-list
            face  )
-         (const :tag "Derive from highlight-changes-colours"  nil)
+         (const :tag "Derive from highlight-changes-colors"  nil)
          )
   :group 'highlight-changes)
 
@@ -409,7 +419,7 @@ Otherwise, this list will be constructed when needed from
 
 ;;; 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
@@ -443,7 +453,7 @@ This is the opposite of `hilit-chg-hide-changes'."
   (let ((ov (make-overlay start end))
        face)
     (if (eq prop 'hilit-chg-delete)
-       (setq face 'highlight-changes-delete-face)
+       (setq face 'highlight-changes-delete)
       (setq face (nth 1 (member prop hilit-chg-list))))
     (if face
        (progn
@@ -479,7 +489,7 @@ This is the opposite of `hilit-chg-display-changes'."
   "Fix change overlays in region between BEG and END.
 
 Ensure the overlays agree with the changes as determined from
-the text properties of type `hilit-chg' ."
+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:
@@ -511,7 +521,7 @@ the text properties of type `hilit-chg' ."
 This allows you to manually remove highlighting from uninteresting changes."
   (interactive "r")
   (let ((after-change-functions nil))
-    (remove-text-properties beg end  '(hilit-chg nil))
+    (remove-text-properties beg end '(hilit-chg nil))
     (hilit-chg-fixup beg end)))
 
 (defun hilit-chg-set-face-on-change (beg end leng-before
@@ -632,12 +642,12 @@ Functions:
 \\[highlight-changes-remove-highlight] - remove the change face from the region
 \\[highlight-changes-rotate-faces] - rotate different \"ages\" of changes \
 through
-       various faces.
+       various faces
 
 Hook variables:
-`highlight-changes-enable-hook'  - when enabling Highlight Changes mode.
+`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."
+`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)))
@@ -652,7 +662,7 @@ Hook variables:
              ;; an argument is given
              ((eq arg 'active)
               'active)
-             ((eq arg  'passive)
+             ((eq arg 'passive)
               'passive)
              ((> (prefix-numeric-value arg) 0)
               'active)
@@ -725,24 +735,24 @@ Hook variables:
   ;; so we pick up any changes?
   (if (or (null highlight-changes-face-list)  ; Don't do it if it
          force) ; already exists unless FORCE non-nil.
-      (let ((p highlight-changes-colours)
+      (let ((p highlight-changes-colors)
            (n 1) name)
        (setq highlight-changes-face-list nil)
        (while p
-         (setq name (intern (format "highlight-changes-face-%d" n)))
-         (copy-face 'highlight-changes-face name)
+         (setq name (intern (format "highlight-changes-%d" n)))
+         (copy-face 'highlight-changes name)
          (set-face-foreground name (car p))
          (setq highlight-changes-face-list
                (append highlight-changes-face-list (list name)))
          (setq p (cdr p))
          (setq n (1+ n)))))
-  (setq hilit-chg-list (list 'hilit-chg 'highlight-changes-face))
+  (setq hilit-chg-list (list 'hilit-chg 'highlight-changes))
   (let ((p highlight-changes-face-list)
        (n 1)
        last-category last-face)
     (while p
       (setq last-category (intern (format "change-%d" n)))
-      ;; (setq last-face (intern (format "highlight-changes-face-%d" n)))
+      ;; (setq last-face (intern (format "highlight-changes-%d" n)))
       (setq last-face (car p))
       (setq hilit-chg-list
            (append hilit-chg-list
@@ -772,27 +782,46 @@ of `highlight-changes-face-list', one level older changes are shown in
 face described by the second element, and so on.  Very old changes remain
 shown in the last face in the list.
 
-You can automatically rotate colours when the buffer is saved
-by adding the following to `local-write-file-hooks', by evaling it in the
-buffer to be saved):
+You can automatically rotate colors when the buffer is saved by adding
+this function to `write-file-functions' as a buffer-local value.  To do
+this, eval the following in the buffer to be saved:
 
-  \(add-hook 'local-write-file-hooks 'highlight-changes-rotate-faces)"
+  \(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.
-  (if (eq highlight-changes-mode 'active)
-      (let ((after-change-functions nil))
-       ;; ensure hilit-chg-list is made and up to date
-       (hilit-chg-make-list)
-       ;; remove our existing overlays
-       (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))))
-  ;; This always returns nil so it is safe to use in
-  ;; local-write-file-hook
+  (when (eq highlight-changes-mode 'active)
+    (let ((modified (buffer-modified-p))
+         (inhibit-modification-hooks t))
+      ;; The `modified' related code tries to combine two goals: (1) Record the
+      ;; rotation in `buffer-undo-list' and (2) avoid setting the modified flag
+      ;; 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)))
+      (unwind-protect
+         (progn
+           ;; ensure hilit-chg-list is made and up to date
+           (hilit-chg-make-list)
+           ;; remove our existing overlays
+           (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)))
+       (unless modified
+         ;; Install the "after" entry.
+         (setq buffer-undo-list
+               (cons '(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
   nil)
 
 ;; ========================================================================
@@ -840,7 +869,7 @@ is non-nil."
 
       (setq change-a (car change-info))
       (setq change-b (car (cdr change-info)))
-      
+
       (hilit-chg-make-list)
       (while change-a
        (setq a-start (nth 0 (car change-a)))
@@ -877,18 +906,18 @@ The default is the current buffer and the one in the next window.
 If either buffer is modified and is visiting a file, you are prompted
 to save the file.
 
-Unless the buffer is unmodified and visiting a file,  the buffer is
+Unless the buffer is unmodified and visiting a file, the buffer is
 written to a temporary file for comparison.
 
 If a 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 
+   (list
     (get-buffer (read-buffer "buffer-a " (current-buffer) t))
     (get-buffer
      (read-buffer "buffer-b "
-                 (window-buffer (next-window (selected-window))) t)))) 
+                 (window-buffer (next-window (selected-window))) t))))
   (let ((file-a (buffer-file-name buf-a))
        (file-b (buffer-file-name buf-b)))
     (highlight-markup-buffers buf-a file-a buf-b file-b)
@@ -915,10 +944,10 @@ changes are made, so \\[highlight-changes-next-change] and
               nil                      ;; default
               'yes                     ;; must exist
               (let ((f (buffer-file-name (current-buffer))))
-                (if f 
+                (if f
                     (progn
                       (setq f (make-backup-file-name f))
-                      (or (file-exists-p f) 
+                      (or (file-exists-p f)
                           (setq f nil)))
                   )
                 f))))
@@ -950,9 +979,9 @@ changes are made, so \\[highlight-changes-next-change] and
   ;; which calls this function as a hook
   (defvar x)  ;; placate the byte-compiler
   (defvar y)
-  (setq  e (current-buffer))
+  (setq e (current-buffer))
   (let ((n 0) extent p va vb a b)
-    (setq  x nil  y nil)    ;; x and y are bound by hilit-chg-get-diff-info
+    (setq x nil y nil)    ;; x and y are bound by hilit-chg-get-diff-info
     (while (< n ediff-number-of-differences)
       (ediff-make-fine-diffs n)
       (setq va (ediff-get-fine-diff-vector n 'A))
@@ -993,12 +1022,12 @@ changes are made, so \\[highlight-changes-next-change] and
 
 ;; 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-hooks' and `change-major-mode-hook' are set.
-;; `find-file-hooks' is called when visiting a file, the new 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-hooks' has already been called and has done its work.
+;; `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.
@@ -1038,7 +1067,7 @@ changes are made, so \\[highlight-changes-next-change] and
 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 zero prefix turn it on in passive mode
 - if called with a negative prefix turn it off
 
 When called from a program:
@@ -1075,23 +1104,23 @@ variable `highlight-changes-global-changes-existing-buffers' is non-nil).
       (progn
        (if (eq arg 'active)
            (setq highlight-changes-global-initial-state 'active)
-         (if (eq arg  'passive)
+         (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)
-       (add-hook 'hilit-chg-major-mode-hook 'hilit-chg-major-mode-hook)
-       (add-hook 'find-file-hooks 'hilit-chg-check-global)
+       ;; 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")
-    (remove-hook 'hilit-chg-major-mode-hook 'hilit-chg-major-mode-hook)
-    (remove-hook 'find-file-hooks 'hilit-chg-check-global)
-    (remove-hook 'post-command-hook
-                'hilit-chg-post-command-hook)
-    (remove-hook 'find-file-hooks 'hilit-chg-check-global)
+    ;; 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))))
 
@@ -1101,9 +1130,9 @@ variable `highlight-changes-global-changes-existing-buffers' is non-nil).
 
 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 ` ')
+  `*' or ` '),
 - the buffer's mode is suitable as per variable
-  `highlight-changes-global-modes'
+  `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
@@ -1121,7 +1150,7 @@ from `global-highlight-changes' when turning on global Highlight Changes mode."
               (memq major-mode highlight-changes-global-modes)))
            (t
             (and
-             (not (string-match "^[ *]"  (buffer-name)))
+             (not (string-match "^[ *]" (buffer-name)))
              (buffer-file-name))))
          (progn
            (hilit-chg-set value)
@@ -1136,14 +1165,27 @@ from `global-highlight-changes' when turning on global Highlight Changes mode."
 
 
 (defun hilit-chg-update-all-buffers (value)
-  (mapcar
+  (mapc
    (function (lambda (buffer)
               (with-current-buffer buffer
                 (if value
                     (hilit-chg-turn-on-maybe value)
                   (hilit-chg-turn-off-maybe))
                 )))
-   (buffer-list)))
+   (buffer-list))
+  nil)
+
+;;;; Desktop support.
+
+;; Called by `desktop-create-buffer' to restore `highlight-changes-mode'.
+(defun hilit-chg-desktop-restore (desktop-buffer-locals)
+  (highlight-changes-mode
+   (or (cdr (assq 'highlight-changes-mode desktop-buffer-locals)) 1)))
+
+(add-to-list 'desktop-minor-mode-handlers
+             '(highlight-changes-mode . hilit-chg-desktop-restore))
+
+(add-to-list 'desktop-locals-to-save 'highlight-changes-mode)
 
 ;; ===================== debug ==================
 ;; For debug & test use: