*** empty log message ***
[bpt/emacs.git] / lisp / whitespace.el
index 1e46c3c..293416c 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Keywords: data, wp
 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Keywords: data, wp
-;; Version: 11.2
+;; Version: 11.2.2
 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
 ;; This file is part of GNU Emacs.
 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
 ;; This file is part of GNU Emacs.
 ;; There are also the following useful commands:
 ;;
 ;; `whitespace-newline-mode'
 ;; There are also the following useful commands:
 ;;
 ;; `whitespace-newline-mode'
-;;    Toggle newline minor mode visualization ("nl" on modeline).
+;;    Toggle NEWLINE minor mode visualization ("nl" on modeline).
 ;;
 ;; `global-whitespace-newline-mode'
 ;;
 ;; `global-whitespace-newline-mode'
-;;    Toggle newline global minor mode visualization ("NL" on modeline).
+;;    Toggle NEWLINE global minor mode visualization ("NL" on modeline).
 ;;
 ;; `whitespace-report'
 ;;    Report some blank problems in buffer.
 ;;
 ;; `whitespace-report'
 ;;    Report some blank problems in buffer.
 ;;                             turned on.
 ;;
 ;; `whitespace-action'         Specify which action is taken when a
 ;;                             turned on.
 ;;
 ;; `whitespace-action'         Specify which action is taken when a
-;;                             buffer is visited, killed or written.
+;;                             buffer is visited or written.
 ;;
 ;;
 ;; Acknowledgements
 ;; ----------------
 ;;
 ;;
 ;;
 ;; Acknowledgements
 ;; ----------------
 ;;
+;; Thanks to David Reitter <david.reitter@gmail.com> for suggesting a
+;; `whitespace-newline' initialization with low contrast relative to
+;; the background color.
+;;
 ;; Thanks to Stephen Deasey <sdeasey@gmail.com> for the
 ;; `indent-tabs-mode' usage suggestion.
 ;;
 ;; Thanks to Eric Cooper <ecc@cmu.edu> for the suggestion to have hook
 ;; Thanks to Stephen Deasey <sdeasey@gmail.com> for the
 ;; `indent-tabs-mode' usage suggestion.
 ;;
 ;; Thanks to Eric Cooper <ecc@cmu.edu> for the suggestion to have hook
-;; actions when buffer is written or killed as the original whitespace
-;; package had.
+;; actions when buffer is written as the original whitespace package
+;; had.
 ;;
 ;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
 ;; lines tail.  See EightyColumnRule (EmacsWiki).
 ;;
 ;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
 ;; lines tail.  See EightyColumnRule (EmacsWiki).
 ;; "long" lines.  See EightyColumnRule (EmacsWiki).
 ;;
 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
 ;; "long" lines.  See EightyColumnRule (EmacsWiki).
 ;;
 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
-;; newline character mapping.
+;; NEWLINE character mapping.
 ;;
 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
 ;; whitespace-mode.el on XEmacs.
 ;;
 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
 ;; whitespace-mode.el on XEmacs.
   '(tabs spaces trailing lines space-before-tab newline
         indentation empty space-after-tab
         space-mark tab-mark newline-mark)
   '(tabs spaces trailing lines space-before-tab newline
         indentation empty space-after-tab
         space-mark tab-mark newline-mark)
-  "*Specify which kind of blank is visualized.
+  "Specify which kind of blank is visualized.
 
 It's a list containing some or all of the following values:
 
 
 It's a list containing some or all of the following values:
 
@@ -504,7 +508,7 @@ See also `whitespace-display-mappings' for documentation."
 
 
 (defcustom whitespace-space 'whitespace-space
 
 
 (defcustom whitespace-space 'whitespace-space
-  "*Symbol face used to visualize SPACE.
+  "Symbol face used to visualize SPACE.
 
 Used when `whitespace-style' includes the value `spaces'."
   :type 'face
 
 Used when `whitespace-style' includes the value `spaces'."
   :type 'face
@@ -522,7 +526,7 @@ Used when `whitespace-style' includes the value `spaces'."
 
 
 (defcustom whitespace-hspace 'whitespace-hspace
 
 
 (defcustom whitespace-hspace 'whitespace-hspace
-  "*Symbol face used to visualize HARD SPACE.
+  "Symbol face used to visualize HARD SPACE.
 
 Used when `whitespace-style' includes the value `spaces'."
   :type 'face
 
 Used when `whitespace-style' includes the value `spaces'."
   :type 'face
@@ -540,7 +544,7 @@ Used when `whitespace-style' includes the value `spaces'."
 
 
 (defcustom whitespace-tab 'whitespace-tab
 
 
 (defcustom whitespace-tab 'whitespace-tab
-  "*Symbol face used to visualize TAB.
+  "Symbol face used to visualize TAB.
 
 Used when `whitespace-style' includes the value `tabs'."
   :type 'face
 
 Used when `whitespace-style' includes the value `tabs'."
   :type 'face
@@ -558,7 +562,7 @@ Used when `whitespace-style' includes the value `tabs'."
 
 
 (defcustom whitespace-newline 'whitespace-newline
 
 
 (defcustom whitespace-newline 'whitespace-newline
-  "*Symbol face used to visualize NEWLINE char mapping.
+  "Symbol face used to visualize NEWLINE char mapping.
 
 See `whitespace-display-mappings'.
 
 
 See `whitespace-display-mappings'.
 
@@ -581,7 +585,7 @@ See `whitespace-display-mappings'."
 
 
 (defcustom whitespace-trailing 'whitespace-trailing
 
 
 (defcustom whitespace-trailing 'whitespace-trailing
-  "*Symbol face used to visualize trailing blanks.
+  "Symbol face used to visualize trailing blanks.
 
 Used when `whitespace-style' includes the value `trailing'."
   :type 'face
 
 Used when `whitespace-style' includes the value `trailing'."
   :type 'face
@@ -596,7 +600,7 @@ Used when `whitespace-style' includes the value `trailing'."
 
 
 (defcustom whitespace-line 'whitespace-line
 
 
 (defcustom whitespace-line 'whitespace-line
-  "*Symbol face used to visualize \"long\" lines.
+  "Symbol face used to visualize \"long\" lines.
 
 See `whitespace-line-column'.
 
 
 See `whitespace-line-column'.
 
@@ -615,7 +619,7 @@ See `whitespace-line-column'."
 
 
 (defcustom whitespace-space-before-tab 'whitespace-space-before-tab
 
 
 (defcustom whitespace-space-before-tab 'whitespace-space-before-tab
-  "*Symbol face used to visualize SPACEs before TAB.
+  "Symbol face used to visualize SPACEs before TAB.
 
 Used when `whitespace-style' includes the value `space-before-tab'."
   :type 'face
 
 Used when `whitespace-style' includes the value `space-before-tab'."
   :type 'face
@@ -630,7 +634,7 @@ Used when `whitespace-style' includes the value `space-before-tab'."
 
 
 (defcustom whitespace-indentation 'whitespace-indentation
 
 
 (defcustom whitespace-indentation 'whitespace-indentation
-  "*Symbol face used to visualize 8 or more SPACEs at beginning of line.
+  "Symbol face used to visualize 8 or more SPACEs at beginning of line.
 
 Used when `whitespace-style' includes the value `indentation'."
   :type 'face
 
 Used when `whitespace-style' includes the value `indentation'."
   :type 'face
@@ -645,7 +649,7 @@ Used when `whitespace-style' includes the value `indentation'."
 
 
 (defcustom whitespace-empty 'whitespace-empty
 
 
 (defcustom whitespace-empty 'whitespace-empty
-  "*Symbol face used to visualize empty lines at beginning and/or end of buffer.
+  "Symbol face used to visualize empty lines at beginning and/or end of buffer.
 
 Used when `whitespace-style' includes the value `empty'."
   :type 'face
 
 Used when `whitespace-style' includes the value `empty'."
   :type 'face
@@ -660,7 +664,7 @@ Used when `whitespace-style' includes the value `empty'."
 
 
 (defcustom whitespace-space-after-tab 'whitespace-space-after-tab
 
 
 (defcustom whitespace-space-after-tab 'whitespace-space-after-tab
-  "*Symbol face used to visualize 8 or more SPACEs after TAB.
+  "Symbol face used to visualize 8 or more SPACEs after TAB.
 
 Used when `whitespace-style' includes the value `space-after-tab'."
   :type 'face
 
 Used when `whitespace-style' includes the value `space-after-tab'."
   :type 'face
@@ -676,7 +680,7 @@ Used when `whitespace-style' includes the value `space-after-tab'."
 
 (defcustom whitespace-hspace-regexp
   "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
 
 (defcustom whitespace-hspace-regexp
   "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
-  "*Specify HARD SPACE characters regexp.
+  "Specify HARD SPACE characters regexp.
 
 If you're using `mule' package, there may be other characters besides:
 
 
 If you're using `mule' package, there may be other characters besides:
 
@@ -704,7 +708,7 @@ Used when `whitespace-style' includes `spaces'."
 
 
 (defcustom whitespace-space-regexp "\\( +\\)"
 
 
 (defcustom whitespace-space-regexp "\\( +\\)"
-  "*Specify SPACE characters regexp.
+  "Specify SPACE characters regexp.
 
 If you're using `mule' package, there may be other characters
 besides \" \" that should be considered SPACE.
 
 If you're using `mule' package, there may be other characters
 besides \" \" that should be considered SPACE.
@@ -726,7 +730,7 @@ Used when `whitespace-style' includes `spaces'."
 
 
 (defcustom whitespace-tab-regexp "\\(\t+\\)"
 
 
 (defcustom whitespace-tab-regexp "\\(\t+\\)"
-  "*Specify TAB characters regexp.
+  "Specify TAB characters regexp.
 
 If you're using `mule' package, there may be other characters
 besides \"\\t\" that should be considered TAB.
 
 If you're using `mule' package, there may be other characters
 besides \"\\t\" that should be considered TAB.
@@ -749,7 +753,7 @@ Used when `whitespace-style' includes `tabs'."
 
 (defcustom whitespace-trailing-regexp
   "\\(\\(\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)$"
 
 (defcustom whitespace-trailing-regexp
   "\\(\\(\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)$"
-  "*Specify trailing characters regexp.
+  "Specify trailing characters regexp.
 
 If you're using `mule' package, there may be other characters besides:
 
 
 If you're using `mule' package, there may be other characters besides:
 
@@ -767,7 +771,7 @@ Used when `whitespace-style' includes `trailing'."
 
 
 (defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
 
 
 (defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
-  "*Specify SPACEs before TAB regexp.
+  "Specify SPACEs before TAB regexp.
 
 If you're using `mule' package, there may be other characters besides:
 
 
 If you're using `mule' package, there may be other characters besides:
 
@@ -785,7 +789,7 @@ Used when `whitespace-style' includes `space-before-tab',
 (defcustom whitespace-indentation-regexp
   '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
     . "^ *\\(\t+\\)[^\n]")
 (defcustom whitespace-indentation-regexp
   '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
     . "^ *\\(\t+\\)[^\n]")
-  "*Specify regexp for 8 or more SPACEs at beginning of line.
+  "Specify regexp for 8 or more SPACEs at beginning of line.
 
 It is a cons where the cons car is used for SPACEs visualization
 and the cons cdr is used for TABs visualization.
 
 It is a cons where the cons car is used for SPACEs visualization
 and the cons cdr is used for TABs visualization.
@@ -805,7 +809,7 @@ Used when `whitespace-style' includes `indentation',
 
 
 (defcustom whitespace-empty-at-bob-regexp "\\`\\(\\([ \t]*\n\\)+\\)"
 
 
 (defcustom whitespace-empty-at-bob-regexp "\\`\\(\\([ \t]*\n\\)+\\)"
-  "*Specify regexp for empty lines at beginning of buffer.
+  "Specify regexp for empty lines at beginning of buffer.
 
 If you're using `mule' package, there may be other characters besides:
 
 
 If you're using `mule' package, there may be other characters besides:
 
@@ -820,7 +824,7 @@ Used when `whitespace-style' includes `empty'."
 
 
 (defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)\\'"
 
 
 (defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)\\'"
-  "*Specify regexp for empty lines at end of buffer.
+  "Specify regexp for empty lines at end of buffer.
 
 If you're using `mule' package, there may be other characters besides:
 
 
 If you're using `mule' package, there may be other characters besides:
 
@@ -837,7 +841,7 @@ Used when `whitespace-style' includes `empty'."
 (defcustom whitespace-space-after-tab-regexp
   '("\t+\\(\\( \\{%d\\}\\)+\\)"
     . "\\(\t+\\) +")
 (defcustom whitespace-space-after-tab-regexp
   '("\t+\\(\\( \\{%d\\}\\)+\\)"
     . "\\(\t+\\) +")
-  "*Specify regexp for 8 or more SPACEs after TAB.
+  "Specify regexp for 8 or more SPACEs after TAB.
 
 It is a cons where the cons car is used for SPACEs visualization
 and the cons cdr is used for TABs visualization.
 
 It is a cons where the cons car is used for SPACEs visualization
 and the cons cdr is used for TABs visualization.
@@ -856,7 +860,7 @@ Used when `whitespace-style' includes `space-after-tab',
 
 
 (defcustom whitespace-line-column 80
 
 
 (defcustom whitespace-line-column 80
-  "*Specify column beyond which the line is highlighted.
+  "Specify column beyond which the line is highlighted.
 
 Used when `whitespace-style' includes `lines' or `lines-tail'."
   :type '(integer :tag "Line Length")
 
 Used when `whitespace-style' includes `lines' or `lines-tail'."
   :type '(integer :tag "Line Length")
@@ -887,7 +891,7 @@ Used when `whitespace-style' includes `lines' or `lines-tail'."
     ;; If this is a problem for you, please, comment the line below.
     (tab-mark     ?\t    [?\xBB ?\t]   [?\\ ?\t])      ; tab - left quote mark
     )
     ;; If this is a problem for you, please, comment the line below.
     (tab-mark     ?\t    [?\xBB ?\t]   [?\\ ?\t])      ; tab - left quote mark
     )
-  "*Specify an alist of mappings for displaying characters.
+  "Specify an alist of mappings for displaying characters.
 
 Each element has the following form:
 
 
 Each element has the following form:
 
@@ -932,7 +936,7 @@ Used when `whitespace-style' includes `tab-mark', `space-mark' or
 
 
 (defcustom whitespace-global-modes t
 
 
 (defcustom whitespace-global-modes t
-  "*Modes for which global `whitespace-mode' is automagically turned on.
+  "Modes for which global `whitespace-mode' is automagically turned on.
 
 Global `whitespace-mode' is controlled by the command
 `global-whitespace-mode'.
 
 Global `whitespace-mode' is controlled by the command
 `global-whitespace-mode'.
@@ -963,7 +967,7 @@ C++ modes only."
 
 
 (defcustom whitespace-action nil
 
 
 (defcustom whitespace-action nil
-  "*Specify which action is taken when a buffer is visited, killed or written.
+  "Specify which action is taken when a buffer is visited or written.
 
 It's a list containing some or all of the following values:
 
 
 It's a list containing some or all of the following values:
 
@@ -978,12 +982,16 @@ It's a list containing some or all of the following values:
                        when local whitespace is turned on.
 
    auto-cleanup                cleanup any bogus whitespace when buffer is
                        when local whitespace is turned on.
 
    auto-cleanup                cleanup any bogus whitespace when buffer is
-                       written or killed.
+                       written.
                        See `whitespace-cleanup' and
                        `whitespace-cleanup-region'.
 
    abort-on-bogus      abort if there is any bogus whitespace and the
                        See `whitespace-cleanup' and
                        `whitespace-cleanup-region'.
 
    abort-on-bogus      abort if there is any bogus whitespace and the
-                       buffer is written or killed.
+                       buffer is written.
+
+   warn-if-read-only   give a warning if `cleanup' or `auto-cleanup'
+                       is included in `whitespace-action' and the
+                       buffer is read-only.
 
 Any other value is treated as nil."
   :type '(choice :tag "Actions"
 
 Any other value is treated as nil."
   :type '(choice :tag "Actions"
@@ -993,7 +1001,8 @@ Any other value is treated as nil."
                          (const :tag "Cleanup When On" cleanup)
                          (const :tag "Report On Bogus" report-on-bogus)
                          (const :tag "Auto Cleanup" auto-cleanup)
                          (const :tag "Cleanup When On" cleanup)
                          (const :tag "Report On Bogus" report-on-bogus)
                          (const :tag "Auto Cleanup" auto-cleanup)
-                         (const :tag "Abort On Bogus" abort-on-bogus))))
+                         (const :tag "Abort On Bogus" abort-on-bogus)
+                         (const :tag "Warn If Read-Only" warn-if-read-only))))
   :group 'whitespace)
 
 \f
   :group 'whitespace)
 
 \f
@@ -1008,7 +1017,10 @@ Any other value is treated as nil."
 If ARG is null, toggle whitespace visualization.
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
 If ARG is null, toggle whitespace visualization.
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
-Only useful with a windowing system."
+Only useful with a windowing system.
+
+See also `whitespace-style', `whitespace-newline' and
+`whitespace-display-mappings'."
   :lighter    " ws"
   :init-value nil
   :global     nil
   :lighter    " ws"
   :init-value nil
   :global     nil
@@ -1025,14 +1037,19 @@ Only useful with a windowing system."
 
 ;;;###autoload
 (define-minor-mode whitespace-newline-mode
 
 ;;;###autoload
 (define-minor-mode whitespace-newline-mode
-  "Toggle newline minor mode visualization (\"nl\" on modeline).
+  "Toggle NEWLINE minor mode visualization (\"nl\" on modeline).
 
 
-If ARG is null, toggle newline visualization.
+If ARG is null, toggle NEWLINE visualization.
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
 Only useful with a windowing system.
 
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
 Only useful with a windowing system.
 
-See also `whitespace-newline'."
+Use `whitespace-newline-mode' only for NEWLINE visualization
+exclusively.  For other visualizations, including NEWLINE
+visualization together with (HARD) SPACEs and/or TABs, please,
+use `whitespace-mode'.
+
+See also `whitespace-newline' and `whitespace-display-mappings'."
   :lighter    " nl"
   :init-value nil
   :global     nil
   :lighter    " nl"
   :init-value nil
   :global     nil
@@ -1054,7 +1071,10 @@ See also `whitespace-newline'."
 If ARG is null, toggle whitespace visualization.
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
 If ARG is null, toggle whitespace visualization.
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
-Only useful with a windowing system."
+Only useful with a windowing system.
+
+See also `whitespace-style', `whitespace-newline' and
+`whitespace-display-mappings'."
   :lighter    " WS"
   :init-value nil
   :global     t
   :lighter    " WS"
   :init-value nil
   :global     t
@@ -1103,14 +1123,19 @@ Only useful with a windowing system."
 
 ;;;###autoload
 (define-minor-mode global-whitespace-newline-mode
 
 ;;;###autoload
 (define-minor-mode global-whitespace-newline-mode
-  "Toggle newline global minor mode visualization (\"NL\" on modeline).
+  "Toggle NEWLINE global minor mode visualization (\"NL\" on modeline).
 
 
-If ARG is null, toggle newline visualization.
+If ARG is null, toggle NEWLINE visualization.
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
 Only useful with a windowing system.
 
 If ARG is a number greater than zero, turn on visualization;
 otherwise, turn off visualization.
 Only useful with a windowing system.
 
-See also `whitespace-newline'."
+Use `global-whitespace-newline-mode' only for NEWLINE
+visualization exclusively.  For other visualizations, including
+NEWLINE visualization together with (HARD) SPACEs and/or TABs,
+please, use `global-whitespace-mode'.
+
+See also `whitespace-newline' and `whitespace-display-mappings'."
   :lighter    " NL"
   :init-value nil
   :global     t
   :lighter    " NL"
   :init-value nil
   :global     t
@@ -1361,7 +1386,7 @@ See `whitespace-style' and `indent-tabs-mode' for documentation."
 
 It usually applies to the whole buffer, but in transient mark
 mode when the mark is active, it applies to the region.  It also
 
 It usually applies to the whole buffer, but in transient mark
 mode when the mark is active, it applies to the region.  It also
-applies to the region when it is not in transiente mark mode, the
+applies to the region when it is not in transient mark mode, the
 mark is active and \\[universal-argument] was pressed just before
 calling `whitespace-cleanup' interactively.
 
 mark is active and \\[universal-argument] was pressed just before
 calling `whitespace-cleanup' interactively.
 
@@ -1408,18 +1433,23 @@ The problems cleaned up are:
 
 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
 documentation."
 
 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
 documentation."
-  (interactive "@*")
-  (if (and (or transient-mark-mode
-              current-prefix-arg)
-          mark-active)
-      ;; region active
-      ;; PROBLEMs 1 and 2 are not handled in region
-      ;; PROBLEM 3: 8 or more SPACEs at bol
-      ;; PROBLEM 4: SPACEs before TAB
-      ;; PROBLEM 5: SPACEs or TABs at eol
-      ;; PROBLEM 6: 8 or more SPACEs after TAB
-      (whitespace-cleanup-region (region-beginning) (region-end))
-    ;; whole buffer
+  (interactive "@")
+  (cond
+   ;; read-only buffer
+   (buffer-read-only
+    (whitespace-warn-read-only "cleanup"))
+   ;; region active
+   ((and (or transient-mark-mode
+            current-prefix-arg)
+        mark-active)
+    ;; PROBLEMs 1 and 2 are not handled in region
+    ;; PROBLEM 3: 8 or more SPACEs at bol
+    ;; PROBLEM 4: SPACEs before TAB
+    ;; PROBLEM 5: SPACEs or TABs at eol
+    ;; PROBLEM 6: 8 or more SPACEs after TAB
+    (whitespace-cleanup-region (region-beginning) (region-end)))
+   ;; whole buffer
+   (t
     (save-excursion
       (save-match-data
        ;; PROBLEM 1: empty lines at bob
     (save-excursion
       (save-match-data
        ;; PROBLEM 1: empty lines at bob
@@ -1438,7 +1468,7 @@ documentation."
     ;; PROBLEM 4: SPACEs before TAB
     ;; PROBLEM 5: SPACEs or TABs at eol
     ;; PROBLEM 6: 8 or more SPACEs after TAB
     ;; PROBLEM 4: SPACEs before TAB
     ;; PROBLEM 5: SPACEs or TABs at eol
     ;; PROBLEM 6: 8 or more SPACEs after TAB
-    (whitespace-cleanup-region (point-min) (point-max))))
+    (whitespace-cleanup-region (point-min) (point-max)))))
 
 
 ;;;###autoload
 
 
 ;;;###autoload
@@ -1481,85 +1511,89 @@ The problems cleaned up are:
 
 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
 documentation."
 
 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
 documentation."
-  (interactive "@*r")
-  (let ((rstart           (min start end))
-       (rend             (copy-marker (max start end)))
-       (indent-tabs-mode whitespace-indent-tabs-mode)
-       (tab-width        whitespace-tab-width)
-       overwrite-mode                  ; enforce no overwrite
-       tmp)
-    (save-excursion
-      (save-match-data
-       ;; PROBLEM 1: 8 or more SPACEs at bol
-       (cond
-        ;; ACTION: replace 8 or more SPACEs at bol by TABs, if
-        ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
-        ;; SPACEs.
-        ((memq 'indentation whitespace-style)
-         (let ((regexp (whitespace-indentation-regexp)))
-           (goto-char rstart)
-           (while (re-search-forward regexp rend t)
-             (setq tmp (current-indentation))
-             (goto-char (match-beginning 0))
-             (delete-horizontal-space)
-             (unless (eolp)
-               (indent-to tmp)))))
-        ;; ACTION: replace 8 or more SPACEs at bol by TABs.
-        ((memq 'indentation::tab whitespace-style)
-         (whitespace-replace-action
-          'tabify rstart rend
-          (whitespace-indentation-regexp 'tab) 0))
-        ;; ACTION: replace TABs by SPACEs.
-        ((memq 'indentation::space whitespace-style)
-         (whitespace-replace-action
-          'untabify rstart rend
-          (whitespace-indentation-regexp 'space) 0)))
-       ;; PROBLEM 3: SPACEs or TABs at eol
-       ;; ACTION: remove all SPACEs or TABs at eol
-       (when (memq 'trailing whitespace-style)
-         (whitespace-replace-action
-          'delete-region rstart rend
-          whitespace-trailing-regexp 1))
-       ;; PROBLEM 4: 8 or more SPACEs after TAB
-       (cond
-        ;; ACTION: replace 8 or more SPACEs by TABs, if
-        ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
-        ;; SPACEs.
-        ((memq 'space-after-tab whitespace-style)
-         (whitespace-replace-action
-          (if whitespace-indent-tabs-mode 'tabify 'untabify)
-          rstart rend (whitespace-space-after-tab-regexp) 1))
-        ;; ACTION: replace 8 or more SPACEs by TABs.
-        ((memq 'space-after-tab::tab whitespace-style)
-         (whitespace-replace-action
-          'tabify rstart rend
-          (whitespace-space-after-tab-regexp 'tab) 1))
-        ;; ACTION: replace TABs by SPACEs.
-        ((memq 'space-after-tab::space whitespace-style)
-         (whitespace-replace-action
-          'untabify rstart rend
-          (whitespace-space-after-tab-regexp 'space) 1)))
-       ;; PROBLEM 2: SPACEs before TAB
-       (cond
-        ;; ACTION: replace SPACEs before TAB by TABs, if
-        ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
-        ;; SPACEs.
-        ((memq 'space-before-tab whitespace-style)
-         (whitespace-replace-action
-          (if whitespace-indent-tabs-mode 'tabify 'untabify)
-          rstart rend whitespace-space-before-tab-regexp
-          (if whitespace-indent-tabs-mode 1 2)))
-        ;; ACTION: replace SPACEs before TAB by TABs.
-        ((memq 'space-before-tab::tab whitespace-style)
-         (whitespace-replace-action
-          'tabify rstart rend
-          whitespace-space-before-tab-regexp 1))
-        ;; ACTION: replace TABs by SPACEs.
-        ((memq 'space-before-tab::space whitespace-style)
-         (whitespace-replace-action
-          'untabify rstart rend
-          whitespace-space-before-tab-regexp 2)))))
-    (set-marker rend nil)))            ; point marker to nowhere
+  (interactive "@r")
+  (if buffer-read-only
+      ;; read-only buffer
+      (whitespace-warn-read-only "cleanup region")
+    ;; non-read-only buffer
+    (let ((rstart           (min start end))
+         (rend             (copy-marker (max start end)))
+         (indent-tabs-mode whitespace-indent-tabs-mode)
+         (tab-width        whitespace-tab-width)
+         overwrite-mode                ; enforce no overwrite
+         tmp)
+      (save-excursion
+       (save-match-data
+         ;; PROBLEM 1: 8 or more SPACEs at bol
+         (cond
+          ;; ACTION: replace 8 or more SPACEs at bol by TABs, if
+          ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
+          ;; by SPACEs.
+          ((memq 'indentation whitespace-style)
+           (let ((regexp (whitespace-indentation-regexp)))
+             (goto-char rstart)
+             (while (re-search-forward regexp rend t)
+               (setq tmp (current-indentation))
+               (goto-char (match-beginning 0))
+               (delete-horizontal-space)
+               (unless (eolp)
+                 (indent-to tmp)))))
+          ;; ACTION: replace 8 or more SPACEs at bol by TABs.
+          ((memq 'indentation::tab whitespace-style)
+           (whitespace-replace-action
+            'tabify rstart rend
+            (whitespace-indentation-regexp 'tab) 0))
+          ;; ACTION: replace TABs by SPACEs.
+          ((memq 'indentation::space whitespace-style)
+           (whitespace-replace-action
+            'untabify rstart rend
+            (whitespace-indentation-regexp 'space) 0)))
+         ;; PROBLEM 3: SPACEs or TABs at eol
+         ;; ACTION: remove all SPACEs or TABs at eol
+         (when (memq 'trailing whitespace-style)
+           (whitespace-replace-action
+            'delete-region rstart rend
+            whitespace-trailing-regexp 1))
+         ;; PROBLEM 4: 8 or more SPACEs after TAB
+         (cond
+          ;; ACTION: replace 8 or more SPACEs by TABs, if
+          ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
+          ;; by SPACEs.
+          ((memq 'space-after-tab whitespace-style)
+           (whitespace-replace-action
+            (if whitespace-indent-tabs-mode 'tabify 'untabify)
+            rstart rend (whitespace-space-after-tab-regexp) 1))
+          ;; ACTION: replace 8 or more SPACEs by TABs.
+          ((memq 'space-after-tab::tab whitespace-style)
+           (whitespace-replace-action
+            'tabify rstart rend
+            (whitespace-space-after-tab-regexp 'tab) 1))
+          ;; ACTION: replace TABs by SPACEs.
+          ((memq 'space-after-tab::space whitespace-style)
+           (whitespace-replace-action
+            'untabify rstart rend
+            (whitespace-space-after-tab-regexp 'space) 1)))
+         ;; PROBLEM 2: SPACEs before TAB
+         (cond
+          ;; ACTION: replace SPACEs before TAB by TABs, if
+          ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
+          ;; by SPACEs.
+          ((memq 'space-before-tab whitespace-style)
+           (whitespace-replace-action
+            (if whitespace-indent-tabs-mode 'tabify 'untabify)
+            rstart rend whitespace-space-before-tab-regexp
+            (if whitespace-indent-tabs-mode 1 2)))
+          ;; ACTION: replace SPACEs before TAB by TABs.
+          ((memq 'space-before-tab::tab whitespace-style)
+           (whitespace-replace-action
+            'tabify rstart rend
+            whitespace-space-before-tab-regexp 1))
+          ;; ACTION: replace TABs by SPACEs.
+          ((memq 'space-before-tab::space whitespace-style)
+           (whitespace-replace-action
+            'untabify rstart rend
+            whitespace-space-before-tab-regexp 2)))))
+      (set-marker rend nil))))         ; point marker to nowhere
 
 
 (defun whitespace-replace-action (action rstart rend regexp index)
 
 
 (defun whitespace-replace-action (action rstart rend regexp index)
@@ -2049,7 +2083,7 @@ resultant list will be returned."
 (defun whitespace-turn-on ()
   "Turn on whitespace visualization."
   ;; prepare local hooks
 (defun whitespace-turn-on ()
   "Turn on whitespace visualization."
   ;; prepare local hooks
-  (whitespace-add-local-hook)
+  (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
   ;; create whitespace local buffer environment
   (set (make-local-variable 'whitespace-font-lock-mode) nil)
   (set (make-local-variable 'whitespace-font-lock) nil)
   ;; create whitespace local buffer environment
   (set (make-local-variable 'whitespace-font-lock-mode) nil)
   (set (make-local-variable 'whitespace-font-lock) nil)
@@ -2072,7 +2106,7 @@ resultant list will be returned."
 
 (defun whitespace-turn-off ()
   "Turn off whitespace visualization."
 
 (defun whitespace-turn-off ()
   "Turn off whitespace visualization."
-  (whitespace-remove-local-hook)
+  (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
   (when whitespace-active-style
     (whitespace-color-off)
     (whitespace-display-char-off)))
   (when whitespace-active-style
     (whitespace-color-off)
     (whitespace-display-char-off)))
@@ -2345,44 +2379,22 @@ resultant list will be returned."
         (whitespace-report nil t))))
 
 
         (whitespace-report nil t))))
 
 
-(defun whitespace-add-local-hook ()
-  "Add some whitespace hooks locally."
-  (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
-  (add-hook 'kill-buffer-hook 'whitespace-kill-buffer-hook nil t))
-
-
-(defun whitespace-remove-local-hook ()
-  "Remove some whitespace hooks locally."
-  (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
-  (remove-hook 'kill-buffer-hook 'whitespace-kill-buffer-hook t))
-
-
 (defun whitespace-write-file-hook ()
   "Action to be taken when buffer is written.
 It should be added buffer-locally to `write-file-functions'."
 (defun whitespace-write-file-hook ()
   "Action to be taken when buffer is written.
 It should be added buffer-locally to `write-file-functions'."
-  (when (whitespace-action)
-    (error "Abort write due to whitespace problems in %s"
-          (buffer-name)))
-  nil)                                 ; continue hook processing
-
-
-(defun whitespace-kill-buffer-hook ()
-  "Action to be taken when buffer is killed.
-It should be added buffer-locally to `kill-buffer-hook'."
-  (whitespace-action)
+  (cond ((memq 'auto-cleanup whitespace-action)
+        (whitespace-cleanup))
+       ((memq 'abort-on-bogus whitespace-action)
+        (when (whitespace-report nil t)
+          (error "Abort write due to whitespace problems in %s"
+                 (buffer-name)))))
   nil)                                 ; continue hook processing
 
 
   nil)                                 ; continue hook processing
 
 
-(defun whitespace-action ()
-  "Action to be taken when buffer is killed or written.
-Return t when the action should be aborted."
-  (cond ((memq 'auto-cleanup whitespace-action)
-        (whitespace-cleanup)
-        nil)
-       ((memq 'abort-on-bogus whitespace-action)
-        (whitespace-report nil t))
-       (t
-        nil)))
+(defun whitespace-warn-read-only (msg)
+  "Warn if buffer is read-only."
+  (when (memq 'warn-if-read-only whitespace-action)
+    (message "Can't %s: %s is read-only" msg (buffer-name))))
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;