Add 2010 to copyright years.
[bpt/emacs.git] / lisp / whitespace.el
dissimilarity index 93%
index 896668f..fbdc6d1 100644 (file)
-;;; whitespace.el --- warn about and clean bogus whitespaces in the file
-
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007 Free Software Foundation, Inc.
-
-;; Author: Rajesh Vaidheeswarran <rv@gnu.org>
-;; Keywords: convenience
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; 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.
-
-;;; Commentary:
-;;
-;; URL: http://www.dsmit.com/lisp/
-;;
-;; The whitespace library is intended to find and help fix five different types
-;; of whitespace problems that commonly exist in source code.
-;;
-;; 1. Leading space (empty lines at the top of a file).
-;; 2. Trailing space (empty lines at the end of a file).
-;; 3. Indentation space (8 or more spaces at beginning of line, that should be
-;;                   replaced with TABS).
-;; 4. Spaces followed by a TAB.  (Almost always, we never want that).
-;; 5. Spaces or TABS at the end of a line.
-;;
-;; Whitespace errors are reported in a buffer, and on the modeline.
-;;
-;; Modeline will show a W:<x>!<y> to denote a particular type of whitespace,
-;; where `x' and `y' can be one (or more) of:
-;;
-;; e - End-of-Line whitespace.
-;; i - Indentation whitespace.
-;; l - Leading whitespace.
-;; s - Space followed by Tab.
-;; t - Trailing whitespace.
-;;
-;; If any of the whitespace checks is turned off, the modeline will display a
-;; !<y>.
-;;
-;;     (since (3) is the most controversial one, here is the rationale: Most
-;;     terminal drivers and printer drivers have TAB configured or even
-;;     hardcoded to be 8 spaces.  (Some of them allow configuration, but almost
-;;     always they default to 8.)
-;;
-;;     Changing `tab-width' to other than 8 and editing will cause your code to
-;;     look different from within Emacs, and say, if you cat it or more it, or
-;;     even print it.
-;;
-;;     Almost all the popular programming modes let you define an offset (like
-;;     c-basic-offset or perl-indent-level) to configure the offset, so you
-;;     should never have to set your `tab-width' to be other than 8 in all
-;;     these modes.  In fact, with an indent level of say, 4, 2 TABS will cause
-;;     Emacs to replace your 8 spaces with one \t (try it).  If vi users in
-;;     your office complain, tell them to use vim, which distinguishes between
-;;     tabstop and shiftwidth (vi equivalent of our offsets), and also ask them
-;;     to set smarttab.)
-;;
-;; All the above have caused (and will cause) unwanted codeline integration and
-;; merge problems.
-;;
-;; whitespace.el will complain if it detects whitespaces on opening a file, and
-;; warn you on closing a file also (in case you had inserted any
-;; whitespaces during the process of your editing).
-;;
-;; Exported functions:
-;;
-;; `whitespace-buffer' - To check the current buffer for whitespace problems.
-;; `whitespace-cleanup' - To cleanup all whitespaces in the current buffer.
-;; `whitespace-region' - To check between point and mark for whitespace
-;;                       problems.
-;; `whitespace-cleanup-region' - To cleanup all whitespaces between point
-;;                               and mark in the current buffer.
-
-;;; Code:
-
-(defvar whitespace-version "3.5" "Version of the whitespace library.")
-
-(defvar whitespace-all-buffer-files nil
-  "An associated list of buffers and files checked for whitespace cleanliness.
-
-This is to enable periodic checking of whitespace cleanliness in the files
-visited by the buffers.")
-
-(defvar whitespace-rescan-timer nil
-  "Timer object used to rescan the files in buffers that have been modified.")
-
-;; Tell Emacs about this new kind of minor mode
-(defvar whitespace-mode nil
-  "Non-nil when Whitespace mode (a minor mode) is enabled.")
-(make-variable-buffer-local 'whitespace-mode)
-
-(defvar whitespace-mode-line nil
-  "String to display in the mode line for Whitespace mode.")
-(make-variable-buffer-local 'whitespace-mode-line)
-
-(defvar whitespace-check-buffer-leading nil
-  "Test leading whitespace for file in current buffer if t.")
-(make-variable-buffer-local 'whitespace-check-buffer-leading)
-
-(defvar whitespace-check-buffer-trailing nil
-  "Test trailing whitespace for file in current buffer if t.")
-(make-variable-buffer-local 'whitespace-check-buffer-trailing)
-
-(defvar whitespace-check-buffer-indent nil
-  "Test indentation whitespace for file in current buffer if t.")
-(make-variable-buffer-local 'whitespace-check-buffer-indent)
-
-(defvar whitespace-check-buffer-spacetab nil
-  "Test Space-followed-by-TABS whitespace for file in current buffer if t.")
-(make-variable-buffer-local 'whitespace-check-buffer-spacetab)
-
-(defvar whitespace-check-buffer-ateol nil
-  "Test end-of-line whitespace for file in current buffer if t.")
-(make-variable-buffer-local 'whitespace-check-buffer-ateol)
-
-(defvar whitespace-highlighted-space nil
-  "The variable to store the extent to highlight.")
-(make-variable-buffer-local 'whitespace-highlighted-space)
-
-;; For flavors of Emacs which don't define `defgroup' and `defcustom'.
-(eval-when-compile
-  (if (not (fboundp 'defgroup))
-      (defmacro defgroup (sym memb doc &rest args)
-       "Null macro for `defgroup' in all versions of Emacs that don't define it."
-       t))
-  (if (not (fboundp 'defcustom))
-      (defmacro defcustom (sym val doc &rest args)
-       "Macro to alias `defcustom' to `defvar' in all versions of Emacs that
-don't define it."
-       `(defvar ,sym ,val ,doc))))
-
-(defalias 'whitespace-make-overlay
-  (if (featurep 'xemacs) 'make-extent 'make-overlay))
-(defalias 'whitespace-overlay-put
-  (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
-(defalias 'whitespace-delete-overlay
-  (if (featurep 'xemacs) 'delete-extent 'delete-overlay))
-(defalias 'whitespace-overlay-start
-  (if (featurep 'xemacs) 'extent-start 'overlay-start))
-(defalias 'whitespace-overlay-end
-  (if (featurep 'xemacs) 'extent-end 'overlay-end))
-(defalias 'whitespace-mode-line-update
-  (if (featurep 'xemacs) 'redraw-modeline 'force-mode-line-update))
-
-(defgroup whitespace nil
-  "Check for and fix five different types of whitespaces in source code."
-  :version "21.1"
-  :link '(emacs-commentary-link "whitespace.el")
-  ;; Since XEmacs doesn't have a 'convenience group, use the next best group
-  ;; which is 'editing?
-  :group (if (featurep 'xemacs) 'editing 'convenience))
-
-(defcustom whitespace-check-leading-whitespace t
-  "Flag to check leading whitespace.  This is the global for the system.
-It can be overriden by setting a buffer local variable
-`whitespace-check-buffer-leading'."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-check-trailing-whitespace t
-  "Flag to check trailing whitespace.  This is the global for the system.
-It can be overriden by setting a buffer local variable
-`whitespace-check-buffer-trailing'."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-check-spacetab-whitespace t
-  "Flag to check space followed by a TAB.  This is the global for the system.
-It can be overriden by setting a buffer local variable
-`whitespace-check-buffer-spacetab'."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-spacetab-regexp "[ ]+\t"
-  "Regexp to match one or more spaces followed by a TAB."
-  :type 'regexp
-  :group 'whitespace)
-
-(defcustom whitespace-check-indent-whitespace indent-tabs-mode
-  "Flag to check indentation whitespace.  This is the global for the system.
-It can be overriden by setting a buffer local variable
-`whitespace-check-buffer-indent'."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-indent-regexp "^\t*\\(        \\)+"
-  "Regexp to match multiples of eight spaces near line beginnings.
-The default value ignores leading TABs."
-  :type 'regexp
-  :group 'whitespace)
-
-(defcustom whitespace-check-ateol-whitespace t
-  "Flag to check end-of-line whitespace.  This is the global for the system.
-It can be overriden by setting a buffer local variable
-`whitespace-check-buffer-ateol'."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-ateol-regexp "[ \t]+$"
-  "Regexp to match one or more TABs or spaces at line ends."
-  :type 'regexp
-  :group 'whitespace)
-
-(defcustom whitespace-errbuf "*Whitespace Errors*"
-  "The name of the buffer where whitespace related messages will be logged."
-  :type 'string
-  :group 'whitespace)
-
-(defcustom whitespace-clean-msg "clean."
-  "If non-nil, this message will be displayed after a whitespace check
-determines a file to be clean."
-  :type 'string
-  :group 'whitespace)
-
-(defcustom whitespace-abort-on-error nil
-  "While writing a file, abort if the file is unclean.
-If `whitespace-auto-cleanup' is set, that takes precedence over
-this variable."
-  :type  'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-auto-cleanup nil
-  "Cleanup a buffer automatically on finding it whitespace unclean."
-  :type  'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-silent nil
-  "All whitespace errors will be shown only in the modeline when t.
-
-Note that setting this may cause all whitespaces introduced in a file to go
-unnoticed when the buffer is killed, unless the user visits the `*Whitespace
-Errors*' buffer before opening (or closing) another file."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-modes '(ada-mode asm-mode autoconf-mode awk-mode
-                                      c-mode c++-mode cc-mode
-                                      change-log-mode cperl-mode
-                                      electric-nroff-mode emacs-lisp-mode
-                                      f90-mode fortran-mode html-mode
-                                      html3-mode java-mode jde-mode
-                                      ksh-mode latex-mode LaTeX-mode
-                                      lisp-mode m4-mode makefile-mode
-                                      modula-2-mode nroff-mode objc-mode
-                                      pascal-mode perl-mode prolog-mode
-                                      python-mode scheme-mode sgml-mode
-                                      sh-mode shell-script-mode simula-mode
-                                      tcl-mode tex-mode texinfo-mode
-                                      vrml-mode xml-mode)
-
-  "Major modes in which we turn on whitespace checking.
-
-These are mostly programming and documentation modes.  But you may add other
-modes that you want whitespaces checked in by adding something like the
-following to your `.emacs':
-
-\(setq whitespace-modes (cons 'my-mode (cons 'my-other-mode
-                                           whitespace-modes))\)
-
-Or, alternately, you can use the Emacs `customize' command to set this."
-  :type '(repeat symbol)
-  :group 'whitespace)
-
-(defcustom whitespace-rescan-timer-time 600
-  "Period in seconds to rescan modified buffers for whitespace creep.
-
-This is the period after which the timer will fire causing
-`whitespace-rescan-files-in-buffers' to check for whitespace creep in
-modified buffers.
-
-To disable timer scans, set this to zero."
-  :type 'integer
-  :group 'whitespace)
-
-(defcustom whitespace-display-in-modeline t
-  "Display whitespace errors on the modeline."
-  :type 'boolean
-  :group 'whitespace)
-
-(defcustom whitespace-display-spaces-in-color t
-  "Display the bogus whitespaces by coloring them with the face
-`whitespace-highlight'."
-  :type 'boolean
-  :group 'whitespace)
-
-(defgroup whitespace-faces nil
-  "Faces used in whitespace."
-  :prefix "whitespace-"
-  :group 'whitespace
-  :group 'faces)
-
-(defface whitespace-highlight '((((class color) (background light))
-                                (:background "green1"))
-                               (((class color) (background dark))
-                                (:background "sea green"))
-                               (((class grayscale mono)
-                                 (background light))
-                                (:background "black"))
-                               (((class grayscale mono)
-                                 (background dark))
-                                (:background "white")))
-  "Face used for highlighting the bogus whitespaces that exist in the buffer."
-  :group 'whitespace-faces)
-;; backward-compatibility alias
-(put 'whitespace-highlight-face 'face-alias 'whitespace-highlight)
-
-(if (not (assoc 'whitespace-mode minor-mode-alist))
-    (setq minor-mode-alist (cons '(whitespace-mode whitespace-mode-line)
-                                minor-mode-alist)))
-
-(set-default 'whitespace-check-buffer-leading
-            whitespace-check-leading-whitespace)
-(set-default 'whitespace-check-buffer-trailing
-            whitespace-check-trailing-whitespace)
-(set-default 'whitespace-check-buffer-indent
-            whitespace-check-indent-whitespace)
-(set-default 'whitespace-check-buffer-spacetab
-            whitespace-check-spacetab-whitespace)
-(set-default 'whitespace-check-buffer-ateol
-            whitespace-check-ateol-whitespace)
-
-(defun whitespace-check-whitespace-mode (&optional arg)
-  "Test and set the whitespace-mode in qualifying buffers."
-  (if (null whitespace-mode)
-      (setq whitespace-mode
-           (if (or arg (member major-mode whitespace-modes))
-               t
-             nil))))
-
-;;;###autoload
-(defun whitespace-toggle-leading-check ()
-  "Toggle the check for leading space in the local buffer."
-  (interactive)
-  (let ((current-val whitespace-check-buffer-leading))
-    (setq whitespace-check-buffer-leading (not current-val))
-    (message "Will%s check for leading space in buffer."
-            (if whitespace-check-buffer-leading "" " not"))
-    (if whitespace-check-buffer-leading (whitespace-buffer-leading))))
-
-;;;###autoload
-(defun whitespace-toggle-trailing-check ()
-  "Toggle the check for trailing space in the local buffer."
-  (interactive)
-  (let ((current-val whitespace-check-buffer-trailing))
-    (setq whitespace-check-buffer-trailing (not current-val))
-    (message "Will%s check for trailing space in buffer."
-            (if whitespace-check-buffer-trailing "" " not"))
-    (if whitespace-check-buffer-trailing (whitespace-buffer-trailing))))
-
-;;;###autoload
-(defun whitespace-toggle-indent-check ()
-  "Toggle the check for indentation space in the local buffer."
-  (interactive)
-  (let ((current-val whitespace-check-buffer-indent))
-    (setq whitespace-check-buffer-indent (not current-val))
-    (message "Will%s check for indentation space in buffer."
-            (if whitespace-check-buffer-indent "" " not"))
-    (if whitespace-check-buffer-indent
-       (whitespace-buffer-search whitespace-indent-regexp))))
-
-;;;###autoload
-(defun whitespace-toggle-spacetab-check ()
-  "Toggle the check for space-followed-by-TABs in the local buffer."
-  (interactive)
-  (let ((current-val whitespace-check-buffer-spacetab))
-    (setq whitespace-check-buffer-spacetab (not current-val))
-    (message "Will%s check for space-followed-by-TABs in buffer."
-            (if whitespace-check-buffer-spacetab "" " not"))
-    (if whitespace-check-buffer-spacetab
-       (whitespace-buffer-search whitespace-spacetab-regexp))))
-
-
-;;;###autoload
-(defun whitespace-toggle-ateol-check ()
-  "Toggle the check for end-of-line space in the local buffer."
-  (interactive)
-  (let ((current-val whitespace-check-buffer-ateol))
-    (setq whitespace-check-buffer-ateol (not current-val))
-    (message "Will%s check for end-of-line space in buffer."
-            (if whitespace-check-buffer-ateol "" " not"))
-    (if whitespace-check-buffer-ateol
-       (whitespace-buffer-search whitespace-ateol-regexp))))
-
-
-;;;###autoload
-(defun whitespace-buffer (&optional quiet)
-  "Find five different types of white spaces in buffer.
-These are:
-1. Leading space \(empty lines at the top of a file\).
-2. Trailing space \(empty lines at the end of a file\).
-3. Indentation space \(8 or more spaces, that should be replaced with TABS\).
-4. Spaces followed by a TAB. \(Almost always, we never want that\).
-5. Spaces or TABS at the end of a line.
-
-Check for whitespace only if this buffer really contains a non-empty file
-and:
-1. the major mode is one of the whitespace-modes, or
-2. `whitespace-buffer' was explicitly called with a prefix argument."
-  (interactive)
-  (let ((whitespace-error nil))
-    (whitespace-check-whitespace-mode current-prefix-arg)
-    (if (and buffer-file-name (> (buffer-size) 0) whitespace-mode)
-       (progn
-         (whitespace-check-buffer-list (buffer-name) buffer-file-name)
-         (whitespace-tickle-timer)
-         (overlay-recenter (point-max))
-         (remove-overlays nil nil 'face 'whitespace-highlight)
-         (if whitespace-auto-cleanup
-             (if buffer-read-only
-                 (if (not quiet)
-                     (message "Can't cleanup: %s is read-only" (buffer-name)))
-               (whitespace-cleanup-internal))
-           (let ((whitespace-leading (if whitespace-check-buffer-leading
-                                         (whitespace-buffer-leading)
-                                       nil))
-                 (whitespace-trailing (if whitespace-check-buffer-trailing
-                                          (whitespace-buffer-trailing)
-                                        nil))
-                 (whitespace-indent (if whitespace-check-buffer-indent
-                                        (whitespace-buffer-search
-                                         whitespace-indent-regexp)
-                                      nil))
-                 (whitespace-spacetab (if whitespace-check-buffer-spacetab
-                                          (whitespace-buffer-search
-                                           whitespace-spacetab-regexp)
-                                        nil))
-                 (whitespace-ateol (if whitespace-check-buffer-ateol
-                                       (whitespace-buffer-search
-                                        whitespace-ateol-regexp)
-                                     nil))
-                 (whitespace-errmsg nil)
-                 (whitespace-filename buffer-file-name)
-                 (whitespace-this-modeline ""))
-
-             ;; Now let's complain if we found any of the above.
-             (setq whitespace-error (or whitespace-leading whitespace-indent
-                                        whitespace-spacetab whitespace-ateol
-                                        whitespace-trailing))
-
-             (if whitespace-error
-                 (progn
-                   (setq whitespace-errmsg
-                         (concat whitespace-filename " contains:\n"
-                                 (if whitespace-leading
-                                     "Leading whitespace\n")
-                                 (if whitespace-indent
-                                     (concat "Indentation whitespace"
-                                             whitespace-indent "\n"))
-                                 (if whitespace-spacetab
-                                     (concat "Space followed by Tab"
-                                             whitespace-spacetab "\n"))
-                                 (if whitespace-ateol
-                                     (concat "End-of-line whitespace"
-                                             whitespace-ateol "\n"))
-                                 (if whitespace-trailing
-                                     "Trailing whitespace\n")
-                                 "\ntype `M-x whitespace-cleanup' to "
-                                 "cleanup the file."))
-                   (setq whitespace-this-modeline
-                         (concat (if whitespace-ateol "e")
-                                 (if whitespace-indent "i")
-                                 (if whitespace-leading "l")
-                                 (if whitespace-spacetab "s")
-                                 (if whitespace-trailing "t")))))
-             (whitespace-update-modeline whitespace-this-modeline)
-             (if (get-buffer whitespace-errbuf)
-                 (kill-buffer whitespace-errbuf))
-             (with-current-buffer (get-buffer-create whitespace-errbuf)
-               (if whitespace-errmsg
-                   (progn
-                     (insert whitespace-errmsg)
-                     (if (not (or quiet whitespace-silent))
-                         (display-buffer (current-buffer) t))
-                     (if (not quiet)
-                         (message "Whitespaces: [%s%s] in %s"
-                                  whitespace-this-modeline
-                                  (let ((whitespace-unchecked
-                                         (whitespace-unchecked-whitespaces)))
-                                    (if whitespace-unchecked
-                                        (concat "!" whitespace-unchecked)
-                                      ""))
-                                  whitespace-filename)))
-                 (if (and (not quiet) (not (equal whitespace-clean-msg "")))
-                     (message "%s %s" whitespace-filename
-                              whitespace-clean-msg))))))))
-    whitespace-error))
-
-;;;###autoload
-(defun whitespace-region (s e)
-  "Check the region for whitespace errors."
-  (interactive "r")
-  (save-excursion
-    (save-restriction
-      (narrow-to-region s e)
-      (whitespace-buffer))))
-
-;;;###autoload
-(defun whitespace-cleanup ()
-  "Cleanup the five different kinds of whitespace problems.
-It normally applies to the whole buffer, but in Transient Mark mode
-when the mark is active it applies to the region.
-See `whitespace-buffer' docstring for a summary of the problems."
-  (interactive)
-  (if (and transient-mark-mode mark-active)
-      (whitespace-cleanup-region (region-beginning) (region-end))
-    (whitespace-cleanup-internal)))
-
-(defun whitespace-cleanup-internal (&optional region-only)
-  ;; If this buffer really contains a file, then run, else quit.
-  (whitespace-check-whitespace-mode current-prefix-arg)
-  (if (and buffer-file-name whitespace-mode)
-      (let ((whitespace-any nil)
-           (whitespace-tabwith 8)
-           (whitespace-tabwith-saved tab-width))
-
-       ;; since all printable TABS should be 8, irrespective of how
-       ;; they are displayed.
-       (setq tab-width whitespace-tabwith)
-
-       (if (and whitespace-check-buffer-leading
-                (whitespace-buffer-leading))
-           (progn
-             (whitespace-buffer-leading-cleanup)
-             (setq whitespace-any t)))
-
-       (if (and whitespace-check-buffer-trailing
-                (whitespace-buffer-trailing))
-           (progn
-             (whitespace-buffer-trailing-cleanup)
-             (setq whitespace-any t)))
-
-       (if (and whitespace-check-buffer-indent
-                (whitespace-buffer-search whitespace-indent-regexp))
-           (progn
-             (whitespace-indent-cleanup)
-             (setq whitespace-any t)))
-
-       (if (and whitespace-check-buffer-spacetab
-                (whitespace-buffer-search whitespace-spacetab-regexp))
-           (progn
-             (whitespace-buffer-cleanup whitespace-spacetab-regexp "\t")
-             (setq whitespace-any t)))
-
-       (if (and whitespace-check-buffer-ateol
-                (whitespace-buffer-search whitespace-ateol-regexp))
-           (progn
-             (whitespace-buffer-cleanup whitespace-ateol-regexp "")
-             (setq whitespace-any t)))
-
-       ;; Call this recursively till everything is taken care of
-       (if whitespace-any
-           (whitespace-cleanup-internal region-only)
-         ;; if we are done, talk to the user
-         (progn
-           (unless whitespace-silent
-             (if region-only
-                 (message "The region is now clean")
-               (message "%s is now clean" buffer-file-name)))
-           (whitespace-update-modeline)))
-       (setq tab-width whitespace-tabwith-saved))))
-
-;;;###autoload
-(defun whitespace-cleanup-region (s e)
-  "Whitespace cleanup on the region."
-  (interactive "r")
-  (save-excursion
-    (save-restriction
-      (narrow-to-region s e)
-      (whitespace-cleanup-internal t))
-    (whitespace-buffer t)))
-
-(defun whitespace-buffer-leading ()
-  "Return t if the current buffer has leading newline characters.
-If highlighting is enabled, highlight these characters."
-  (save-excursion
-    (goto-char (point-min))
-    (skip-chars-forward "\n")
-    (unless (bobp)
-      (whitespace-highlight-the-space (point-min) (point))
-      t)))
-
-(defun whitespace-buffer-leading-cleanup ()
-  "Remove any leading newline characters from current buffer."
-  (save-excursion
-    (goto-char (point-min))
-    (skip-chars-forward "\n")
-    (delete-region (point-min) (point))))
-
-(defun whitespace-buffer-trailing ()
-  "Return t if the current buffer has extra trailing newline characters.
-If highlighting is enabled, highlight these characters."
-  (save-excursion
-    (goto-char (point-max))
-    (skip-chars-backward "\n")
-    (forward-line)
-    (unless (eobp)
-      (whitespace-highlight-the-space (point) (point-max))
-      t)))
-
-(defun whitespace-buffer-trailing-cleanup ()
-  "Remove extra trailing newline characters from current buffer."
-  (save-excursion
-    (goto-char (point-max))
-    (skip-chars-backward "\n")
-    (unless (eobp)
-      (forward-line)
-      (delete-region (point) (point-max)))))
-
-(defun whitespace-buffer-search (regexp)
-  "Search for any given whitespace REGEXP."
-  (with-local-quit
-    (let (whitespace-retval)
-      (save-excursion
-       (goto-char (point-min))
-       (while (re-search-forward regexp nil t)
-         (whitespace-highlight-the-space (match-beginning 0) (match-end 0))
-         (push (match-beginning 0) whitespace-retval)))
-      (when whitespace-retval
-       (format " %s" (nreverse whitespace-retval))))))
-
-(defun whitespace-buffer-cleanup (regexp newregexp)
-  "Search for any given whitespace REGEXP and replace it with the NEWREGEXP."
-  (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward regexp nil t)
-      (replace-match newregexp))))
-
-(defun whitespace-indent-cleanup ()
-  "Search for 8/more spaces at the start of a line and replace it with tabs."
-  (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward whitespace-indent-regexp nil t)
-      (let ((column (current-column))
-           (indent-tabs-mode t))
-       (delete-region (match-beginning 0) (point))
-       (indent-to column)))))
-
-(defun whitespace-unchecked-whitespaces ()
-  "Return the list of whitespaces whose testing has been suppressed."
-  (let ((unchecked-spaces
-        (concat (if (not whitespace-check-buffer-ateol) "e")
-                (if (not whitespace-check-buffer-indent) "i")
-                (if (not whitespace-check-buffer-leading) "l")
-                (if (not whitespace-check-buffer-spacetab) "s")
-                (if (not whitespace-check-buffer-trailing) "t"))))
-    (if (not (equal unchecked-spaces ""))
-       unchecked-spaces
-      nil)))
-
-(defun whitespace-update-modeline (&optional whitespace-err)
-  "Update modeline with whitespace errors.
-Also with whitespaces whose testing has been turned off."
-  (if whitespace-display-in-modeline
-      (progn
-       (setq whitespace-mode-line nil)
-       ;; Whitespace errors
-       (if (and whitespace-err (not (equal whitespace-err "")))
-           (setq whitespace-mode-line whitespace-err))
-       ;; Whitespace suppressed errors
-       (let ((whitespace-unchecked (whitespace-unchecked-whitespaces)))
-         (if whitespace-unchecked
-             (setq whitespace-mode-line
-                   (concat whitespace-mode-line "!" whitespace-unchecked))))
-       ;; Add the whitespace modeline prefix
-       (setq whitespace-mode-line (if whitespace-mode-line
-                                      (concat " W:" whitespace-mode-line)
-                                    nil))
-       (whitespace-mode-line-update))))
-
-(defun whitespace-highlight-the-space (b e)
-  "Highlight the current line, unhighlighting a previously jumped to line."
-  (if whitespace-display-spaces-in-color
-      (let ((ol (whitespace-make-overlay b e)))
-       (whitespace-overlay-put ol 'face 'whitespace-highlight))))
-
-(defun whitespace-unhighlight-the-space()
-  "Unhighlight the currently highlight line."
-  (if (and whitespace-display-spaces-in-color whitespace-highlighted-space)
-      (progn
-       (mapc 'whitespace-delete-overlay whitespace-highlighted-space)
-       (setq whitespace-highlighted-space nil))))
-
-(defun whitespace-check-buffer-list (buf-name buf-file)
-  "Add a buffer and its file to the whitespace monitor list.
-
-The buffer named BUF-NAME and its associated file BUF-FILE are now monitored
-periodically for whitespace."
-  (if (and whitespace-mode (not (member (list buf-file buf-name)
-                                       whitespace-all-buffer-files)))
-      (add-to-list 'whitespace-all-buffer-files (list buf-file buf-name))))
-
-(defun whitespace-tickle-timer ()
-  "Tickle timer to periodically to scan qualifying files for whitespace creep.
-
-If timer is not set, then set it to scan the files in
-`whitespace-all-buffer-files' periodically (defined by
-`whitespace-rescan-timer-time') for whitespace creep."
-  (if (and whitespace-rescan-timer-time
-          (/= whitespace-rescan-timer-time 0)
-          (not whitespace-rescan-timer))
-      (setq whitespace-rescan-timer
-           (add-timeout whitespace-rescan-timer-time
-                        'whitespace-rescan-files-in-buffers nil
-                        whitespace-rescan-timer-time))))
-
-(defun whitespace-rescan-files-in-buffers (&optional arg)
-  "Check monitored files for whitespace creep since last scan."
-  (let ((whitespace-all-my-files whitespace-all-buffer-files)
-       buffile bufname thiselt buf)
-    (if (not whitespace-all-my-files)
-       (progn
-         (disable-timeout whitespace-rescan-timer)
-         (setq whitespace-rescan-timer nil))
-      (while whitespace-all-my-files
-       (setq thiselt (car whitespace-all-my-files))
-       (setq whitespace-all-my-files (cdr whitespace-all-my-files))
-       (setq buffile (car thiselt))
-       (setq bufname (cadr thiselt))
-       (setq buf (get-buffer bufname))
-       (if (buffer-live-p buf)
-           (save-excursion
-             ;;(message "buffer %s live" bufname)
-             (set-buffer bufname)
-             (if whitespace-mode
-                 (progn
-                   ;;(message "checking for whitespace in %s" bufname)
-                   (if whitespace-auto-cleanup
-                       (progn
-                         ;;(message "cleaning up whitespace in %s" bufname)
-                         (whitespace-cleanup-internal))
-                     (progn
-                       ;;(message "whitespace-buffer %s." (buffer-name))
-                       (whitespace-buffer t))))
-               ;;(message "Removing %s from refresh list" bufname)
-               (whitespace-refresh-rescan-list buffile bufname)))
-         ;;(message "Removing %s from refresh list" bufname)
-         (whitespace-refresh-rescan-list buffile bufname))))))
-
-(defun whitespace-refresh-rescan-list (buffile bufname)
-  "Refresh the list of files to be rescanned for whitespace creep."
-  (if whitespace-all-buffer-files
-      (setq whitespace-all-buffer-files
-           (delete (list buffile bufname) whitespace-all-buffer-files))
-    (when whitespace-rescan-timer
-      (disable-timeout whitespace-rescan-timer)
-      (setq whitespace-rescan-timer nil))))
-
-;;;###autoload
-(defalias 'global-whitespace-mode 'whitespace-global-mode)
-
-;;;###autoload
-(define-minor-mode whitespace-global-mode
-  "Toggle using Whitespace mode in new buffers.
-With ARG, turn the mode on if ARG is positive, otherwise turn it off.
-
-When this mode is active, `whitespace-buffer' is added to
-`find-file-hook' and `kill-buffer-hook'."
-  :global t
-  :group 'whitespace
-  (if whitespace-global-mode
-      (progn
-       (add-hook 'find-file-hook 'whitespace-buffer)
-       (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
-       (add-hook 'kill-buffer-hook 'whitespace-buffer))
-    (remove-hook 'find-file-hook 'whitespace-buffer)
-    (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
-    (remove-hook 'kill-buffer-hook 'whitespace-buffer)))
-
-;;;###autoload
-(defun whitespace-write-file-hook ()
-  "Hook function to be called on the buffer when whitespace check is enabled.
-This is meant to be added buffer-locally to `write-file-functions'."
-  (let ((werr nil))
-    (if whitespace-auto-cleanup
-       (whitespace-cleanup-internal)
-      (setq werr (whitespace-buffer)))
-    (if (and whitespace-abort-on-error werr)
-       (error "Abort write due to whitespaces in %s"
-                      buffer-file-name)))
-  nil)
-
-(defun whitespace-unload-function ()
-  "Unload the whitespace library."
-  (if (unintern "whitespace-unload-hook")
-      ;; if whitespace-unload-hook is defined, let's get rid of it
-      ;; and recursively call `unload-feature'
-      (progn (unload-feature 'whitespace) t)
-    ;; this only happens in the recursive call
-    (whitespace-global-mode -1)
-    (save-current-buffer
-      (dolist (buf (buffer-list))
-       (set-buffer buf)
-       (remove-hook 'write-file-functions 'whitespace-write-file-hook t)))
-    ;; continue standard unloading
-    nil))
-
-(defun whitespace-unload-hook ()
-  (remove-hook 'find-file-hook 'whitespace-buffer)
-  (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
-  (remove-hook 'kill-buffer-hook 'whitespace-buffer))
-
-(add-hook 'whitespace-unload-hook 'whitespace-unload-hook)
-
-(provide 'whitespace)
-
-;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c
-;;; whitespace.el ends here
+;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE
+
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;;   Free Software Foundation, Inc.
+
+;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Keywords: data, wp
+;; Version: 12.1
+;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 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
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Introduction
+;; ------------
+;;
+;; This package is a minor mode to visualize blanks (TAB, (HARD) SPACE
+;; and NEWLINE).
+;;
+;; whitespace uses two ways to visualize blanks: faces and display
+;; table.
+;;
+;; * Faces are used to highlight the background with a color.
+;;   whitespace uses font-lock to highlight blank characters.
+;;
+;; * Display table changes the way a character is displayed, that is,
+;;   it provides a visual mark for characters, for example, at the end
+;;   of line (?\xB6), at SPACEs (?\xB7) and at TABs (?\xBB).
+;;
+;; The `whitespace-style' variable selects which way blanks are
+;; visualized.
+;;
+;; Note that when whitespace is turned on, whitespace saves the
+;; font-lock state, that is, if font-lock is on or off.  And
+;; whitespace restores the font-lock state when it is turned off.  So,
+;; if whitespace is turned on and font-lock is off, whitespace also
+;; turns on the font-lock to highlight blanks, but the font-lock will
+;; be turned off when whitespace is turned off.  Thus, turn on
+;; font-lock before whitespace is on, if you want that font-lock
+;; continues on after whitespace is turned off.
+;;
+;; When whitespace is on, it takes care of highlighting some special
+;; characters over the default mechanism of `nobreak-char-display'
+;; (which see) and `show-trailing-whitespace' (which see).
+;;
+;; The trailing spaces are not highlighted while point is at end of line.
+;; Also the spaces at beginning of buffer are not highlighted while point is at
+;; beginning of buffer; and the spaces at end of buffer are not highlighted
+;; while point is at end of buffer.
+;;
+;; There are two ways of using whitespace: local and global.
+;;
+;; * Local whitespace affects only the current buffer.
+;;
+;; * Global whitespace affects all current and future buffers.  That
+;;   is, if you turn on global whitespace and then create a new
+;;   buffer, the new buffer will also have whitespace on.  The
+;;   `whitespace-global-modes' variable controls which major-mode will
+;;   be automagically turned on.
+;;
+;; You can mix the local and global usage without any conflict.  But
+;; local whitespace has priority over global whitespace.  Whitespace
+;; mode is active in a buffer if you have enabled it in that buffer or
+;; if you have enabled it globally.
+;;
+;; When global and local whitespace are on:
+;;
+;; * if local whitespace is turned off, whitespace is turned off for
+;;   the current buffer only.
+;;
+;; * if global whitespace is turned off, whitespace continues on only
+;;   in the buffers in which local whitespace is on.
+;;
+;; To use whitespace, insert in your ~/.emacs:
+;;
+;;    (require 'whitespace)
+;;
+;; Or autoload at least one of the commands`whitespace-mode',
+;; `whitespace-toggle-options', `global-whitespace-mode' or
+;; `global-whitespace-toggle-options'.  For example:
+;;
+;;    (autoload 'whitespace-mode           "whitespace"
+;;      "Toggle whitespace visualization."        t)
+;;    (autoload 'whitespace-toggle-options "whitespace"
+;;      "Toggle local `whitespace-mode' options." t)
+;;
+;; whitespace was inspired by:
+;;
+;;    whitespace.el            Rajesh Vaidheeswarran <rv@gnu.org>
+;;     Warn about and clean bogus whitespaces in the file
+;;     (inspired the idea to warn and clean some blanks)
+;;     This was the original `whitespace.el' which was replaced by
+;;     `blank-mode.el'.  And later `blank-mode.el' was renamed to
+;;     `whitespace.el'.
+;;
+;;    show-whitespace-mode.el  Aurelien Tisne <aurelien.tisne@free.fr>
+;;       Simple mode to highlight whitespaces
+;;       (inspired the idea to use font-lock)
+;;
+;;    whitespace-mode.el       Lawrence Mitchell <wence@gmx.li>
+;;       Major mode for editing Whitespace
+;;       (inspired the idea to use display table)
+;;
+;;    visws.el                 Miles Bader <miles@gnu.org>
+;;       Make whitespace visible
+;;       (handle display table, his code was modified, but the main
+;;       idea was kept)
+;;
+;;
+;; Using whitespace
+;; ----------------
+;;
+;; There is no problem if you mix local and global minor mode usage.
+;;
+;; * LOCAL whitespace:
+;;    + To toggle whitespace options locally, type:
+;;
+;;         M-x whitespace-toggle-options RET
+;;
+;;    + To activate whitespace locally, type:
+;;
+;;         C-u 1 M-x whitespace-mode RET
+;;
+;;    + To deactivate whitespace locally, type:
+;;
+;;         C-u 0 M-x whitespace-mode RET
+;;
+;;    + To toggle whitespace locally, type:
+;;
+;;         M-x whitespace-mode RET
+;;
+;; * GLOBAL whitespace:
+;;    + To toggle whitespace options globally, type:
+;;
+;;         M-x global-whitespace-toggle-options RET
+;;
+;;    + To activate whitespace globally, type:
+;;
+;;         C-u 1 M-x global-whitespace-mode RET
+;;
+;;    + To deactivate whitespace globally, type:
+;;
+;;         C-u 0 M-x global-whitespace-mode RET
+;;
+;;    + To toggle whitespace globally, type:
+;;
+;;         M-x global-whitespace-mode RET
+;;
+;; There are also the following useful commands:
+;;
+;; `whitespace-newline-mode'
+;;    Toggle NEWLINE minor mode visualization ("nl" on modeline).
+;;
+;; `global-whitespace-newline-mode'
+;;    Toggle NEWLINE global minor mode visualization ("NL" on modeline).
+;;
+;; `whitespace-report'
+;;    Report some blank problems in buffer.
+;;
+;; `whitespace-report-region'
+;;    Report some blank problems in a region.
+;;
+;; `whitespace-cleanup'
+;;    Cleanup some blank problems in all buffer or at region.
+;;
+;; `whitespace-cleanup-region'
+;;    Cleanup some blank problems at region.
+;;
+;; The problems, which are cleaned up, are:
+;;
+;; 1. empty lines at beginning of buffer.
+;; 2. empty lines at end of buffer.
+;;    If `whitespace-style' includes the value `empty', remove all
+;;    empty lines at beginning and/or end of buffer.
+;;
+;; 3. 8 or more SPACEs at beginning of line.
+;;    If `whitespace-style' includes the value `indentation':
+;;    replace 8 or more SPACEs at beginning of line by TABs, if
+;;    `indent-tabs-mode' is non-nil; otherwise, replace TABs by
+;;    SPACEs.
+;;    If `whitespace-style' includes the value `indentation::tab',
+;;    replace 8 or more SPACEs at beginning of line by TABs.
+;;    If `whitespace-style' includes the value `indentation::space',
+;;    replace TABs by SPACEs.
+;;
+;; 4. SPACEs before TAB.
+;;    If `whitespace-style' includes the value `space-before-tab':
+;;    replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
+;;    otherwise, replace TABs by SPACEs.
+;;    If `whitespace-style' includes the value
+;;    `space-before-tab::tab', replace SPACEs by TABs.
+;;    If `whitespace-style' includes the value
+;;    `space-before-tab::space', replace TABs by SPACEs.
+;;
+;; 5. SPACEs or TABs at end of line.
+;;    If `whitespace-style' includes the value `trailing', remove all
+;;    SPACEs or TABs at end of line.
+;;
+;; 6. 8 or more SPACEs after TAB.
+;;    If `whitespace-style' includes the value `space-after-tab':
+;;    replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
+;;    otherwise, replace TABs by SPACEs.
+;;    If `whitespace-style' includes the value `space-after-tab::tab',
+;;    replace SPACEs by TABs.
+;;    If `whitespace-style' includes the value
+;;    `space-after-tab::space', replace TABs by SPACEs.
+;;
+;;
+;; Hooks
+;; -----
+;;
+;; whitespace has the following hook variables:
+;;
+;; `whitespace-mode-hook'
+;;    It is evaluated always when whitespace is turned on locally.
+;;
+;; `global-whitespace-mode-hook'
+;;    It is evaluated always when whitespace is turned on globally.
+;;
+;; `whitespace-load-hook'
+;;    It is evaluated after whitespace package is loaded.
+;;
+;;
+;; Options
+;; -------
+;;
+;; Below it's shown a brief description of whitespace options, please,
+;; see the options declaration in the code for a long documentation.
+;;
+;; `whitespace-style'          Specify which kind of blank is
+;;                             visualized.
+;;
+;; `whitespace-space'          Face used to visualize SPACE.
+;;
+;; `whitespace-hspace'         Face used to visualize HARD SPACE.
+;;
+;; `whitespace-tab'            Face used to visualize TAB.
+;;
+;; `whitespace-newline'                Face used to visualize NEWLINE char
+;;                             mapping.
+;;
+;; `whitespace-trailing'       Face used to visualize trailing
+;;                             blanks.
+;;
+;; `whitespace-line'           Face used to visualize "long" lines.
+;;
+;; `whitespace-space-before-tab'       Face used to visualize SPACEs
+;;                                     before TAB.
+;;
+;; `whitespace-indentation'    Face used to visualize 8 or more
+;;                             SPACEs at beginning of line.
+;;
+;; `whitespace-empty'          Face used to visualize empty lines at
+;;                             beginning and/or end of buffer.
+;;
+;; `whitespace-space-after-tab'        Face used to visualize 8 or more
+;;                             SPACEs after TAB.
+;;
+;; `whitespace-space-regexp'   Specify SPACE characters regexp.
+;;
+;; `whitespace-hspace-regexp'  Specify HARD SPACE characters regexp.
+;;
+;; `whitespace-tab-regexp'     Specify TAB characters regexp.
+;;
+;; `whitespace-trailing-regexp'        Specify trailing characters regexp.
+;;
+;; `whitespace-space-before-tab-regexp'        Specify SPACEs before TAB
+;;                                     regexp.
+;;
+;; `whitespace-indentation-regexp'     Specify regexp for 8 or more
+;;                                     SPACEs at beginning of line.
+;;
+;; `whitespace-empty-at-bob-regexp'    Specify regexp for empty lines
+;;                                     at beginning of buffer.
+;;
+;; `whitespace-empty-at-eob-regexp'    Specify regexp for empty lines
+;;                                     at end of buffer.
+;;
+;; `whitespace-space-after-tab-regexp' Specify regexp for 8 or more
+;;                                     SPACEs after TAB.
+;;
+;; `whitespace-line-column'    Specify column beyond which the line
+;;                             is highlighted.
+;;
+;; `whitespace-display-mappings'       Specify an alist of mappings
+;;                                     for displaying characters.
+;;
+;; `whitespace-global-modes'   Modes for which global
+;;                             `whitespace-mode' is automagically
+;;                             turned on.
+;;
+;; `whitespace-action'         Specify which action is taken when a
+;;                             buffer is visited or written.
+;;
+;;
+;; 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
+;; 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 Juri Linkov <juri@jurta.org> for suggesting:
+;;    * `define-minor-mode'.
+;;    * `global-whitespace-*' name for global commands.
+;;
+;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
+;;
+;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
+;; suggestion.
+;;
+;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
+;; helping to fix `find-file-hooks' reference.
+;;
+;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
+;; indicating defface byte-compilation warnings.
+;;
+;; Thanks to TimOCallaghan (EmacsWiki) for the idea about highlight
+;; "long" lines.  See EightyColumnRule (EmacsWiki).
+;;
+;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
+;; NEWLINE character mapping.
+;;
+;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
+;; whitespace-mode.el on XEmacs.
+;;
+;; Thanks to Miles Bader <miles@gnu.org> for handling display table via
+;; visws.el (his code was modified, but the main idea was kept).
+;;
+;; Thanks to:
+;;    Rajesh Vaidheeswarran <rv@gnu.org>       (original) whitespace.el
+;;    Aurelien Tisne <aurelien.tisne@free.fr>  show-whitespace-mode.el
+;;    Lawrence Mitchell <wence@gmx.li>         whitespace-mode.el
+;;    Miles Bader <miles@gnu.org>              visws.el
+;; And to all people who contributed with them.
+;;
+;;
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; code:
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; User Variables:
+
+
+;;; Interface to the command system
+
+
+(defgroup whitespace nil
+  "Visualize blanks (TAB, (HARD) SPACE and NEWLINE)."
+  :link '(emacs-library-link :tag "Source Lisp File" "whitespace.el")
+  :version "23.1"
+  :group 'wp
+  :group 'data)
+
+
+(defcustom whitespace-style
+  '(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.
+
+It's a list containing some or all of the following values:
+
+   trailing            trailing blanks are visualized via faces.
+
+   tabs                        TABs are visualized via faces.
+
+   spaces              SPACEs and HARD SPACEs are visualized via
+                       faces.
+
+   lines               lines whose have columns beyond
+                       `whitespace-line-column' are highlighted via
+                       faces .
+                       Whole line is highlighted.
+                       It has precedence over `lines-tail' (see
+                       below).
+
+   lines-tail          lines whose have columns beyond
+                       `whitespace-line-column' are highlighted via
+                       faces.
+                       But only the part of line which goes
+                       beyond `whitespace-line-column' column.
+                       It has effect only if `lines' (see above)
+                       is not present in `whitespace-style'.
+
+   newline             NEWLINEs are visualized via faces.
+
+   empty               empty lines at beginning and/or end of buffer
+                       are visualized via faces.
+
+   indentation::tab    8 or more SPACEs at beginning of line are
+                       visualized via faces.
+
+   indentation::space  TABs at beginning of line are visualized via
+                       faces.
+
+   indentation         8 or more SPACEs at beginning of line are
+                       visualized, if `indent-tabs-mode' (which see)
+                       is non-nil; otherwise, TABs at beginning of
+                       line are visualized via faces.
+
+   space-after-tab::tab                8 or more SPACEs after a TAB are
+                               visualized via faces.
+
+   space-after-tab::space      TABs are visualized when 8 or more
+                               SPACEs occur after a TAB, via faces.
+
+   space-after-tab             8 or more SPACEs after a TAB are
+                               visualized, if `indent-tabs-mode'
+                               (which see) is non-nil; otherwise,
+                               the TABs are visualized via faces.
+
+   space-before-tab::tab       SPACEs before TAB are visualized via
+                               faces.
+
+   space-before-tab::space     TABs are visualized when SPACEs occur
+                               before TAB, via faces.
+
+   space-before-tab            SPACEs before TAB are visualized, if
+                               `indent-tabs-mode' (which see) is
+                               non-nil; otherwise, the TABs are
+                               visualized via faces.
+
+   space-mark          SPACEs and HARD SPACEs are visualized via
+                       display table.
+
+   tab-mark            TABs are visualized via display table.
+
+   newline-mark                NEWLINEs are visualized via display table.
+
+Any other value is ignored.
+
+If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs via faces and
+via display table.
+
+There is an evaluation order for some values, if some values are
+included in `whitespace-style' list.  For example, if
+indentation, indentation::tab and/or indentation::space are
+included in `whitespace-style' list.  The evaluation order for
+these values is:
+
+ * For indentation:
+   1. indentation
+   2. indentation::tab
+   3. indentation::space
+
+ * For SPACEs after TABs:
+   1. space-after-tab
+   2. space-after-tab::tab
+   3. space-after-tab::space
+
+ * For SPACEs before TABs:
+   1. space-before-tab
+   2. space-before-tab::tab
+   3. space-before-tab::space
+
+So, for example, if indentation and indentation::space are
+included in `whitespace-style' list, the indentation value is
+evaluated instead of indentation::space value.
+
+See also `whitespace-display-mappings' for documentation."
+  :type '(repeat :tag "Kind of Blank"
+                (choice :tag "Kind of Blank Face"
+                        (const :tag "(Face) Trailing TABs, SPACEs and HARD SPACEs"
+                               trailing)
+                        (const :tag "(Face) SPACEs and HARD SPACEs"
+                               spaces)
+                        (const :tag "(Face) TABs" tabs)
+                        (const :tag "(Face) Lines" lines)
+                        (const :tag "(Face) SPACEs before TAB"
+                               space-before-tab)
+                        (const :tag "(Face) NEWLINEs" newline)
+                        (const :tag "(Face) Indentation SPACEs"
+                               indentation)
+                        (const :tag "(Face) Empty Lines At BOB And/Or EOB"
+                               empty)
+                        (const :tag "(Face) SPACEs after TAB"
+                               space-after-tab)
+                        (const :tag "(Mark) SPACEs and HARD SPACEs"
+                               space-mark)
+                        (const :tag "(Mark) TABs" tab-mark)
+                        (const :tag "(Mark) NEWLINEs" newline-mark)))
+  :group 'whitespace)
+
+
+(defcustom whitespace-space 'whitespace-space
+  "Symbol face used to visualize SPACE.
+
+Used when `whitespace-style' includes the value `spaces'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-space
+  '((((class color) (background dark))
+     (:background "grey20"      :foreground "aquamarine3"))
+    (((class color) (background light))
+     (:background "LightYellow" :foreground "aquamarine3"))
+    (t (:inverse-video t)))
+  "Face used to visualize SPACE."
+  :group 'whitespace)
+
+
+(defcustom whitespace-hspace 'whitespace-hspace
+  "Symbol face used to visualize HARD SPACE.
+
+Used when `whitespace-style' includes the value `spaces'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-hspace             ; 'nobreak-space
+  '((((class color) (background dark))
+     (:background "grey24"        :foreground "aquamarine3"))
+    (((class color) (background light))
+     (:background "LemonChiffon3" :foreground "aquamarine3"))
+    (t (:inverse-video t)))
+  "Face used to visualize HARD SPACE."
+  :group 'whitespace)
+
+
+(defcustom whitespace-tab 'whitespace-tab
+  "Symbol face used to visualize TAB.
+
+Used when `whitespace-style' includes the value `tabs'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-tab
+  '((((class color) (background dark))
+     (:background "grey22" :foreground "aquamarine3"))
+    (((class color) (background light))
+     (:background "beige"  :foreground "aquamarine3"))
+    (t (:inverse-video t)))
+  "Face used to visualize TAB."
+  :group 'whitespace)
+
+
+(defcustom whitespace-newline 'whitespace-newline
+  "Symbol face used to visualize NEWLINE char mapping.
+
+See `whitespace-display-mappings'.
+
+Used when `whitespace-style' includes the values `newline-mark'
+and `newline'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-newline
+  '((((class color) (background dark))
+     (:foreground "darkgray" :bold nil))
+    (((class color) (background light))
+     (:foreground "lightgray" :bold nil))
+    (t (:underline t :bold nil)))
+  "Face used to visualize NEWLINE char mapping.
+
+See `whitespace-display-mappings'."
+  :group 'whitespace)
+
+
+(defcustom whitespace-trailing 'whitespace-trailing
+  "Symbol face used to visualize trailing blanks.
+
+Used when `whitespace-style' includes the value `trailing'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-trailing           ; 'trailing-whitespace
+  '((((class mono)) (:inverse-video t :bold t :underline t))
+    (t (:background "red1" :foreground "yellow" :bold t)))
+  "Face used to visualize trailing blanks."
+  :group 'whitespace)
+
+
+(defcustom whitespace-line 'whitespace-line
+  "Symbol face used to visualize \"long\" lines.
+
+See `whitespace-line-column'.
+
+Used when `whitespace-style' includes the value `line'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-line
+  '((((class mono)) (:inverse-video t :bold t :underline t))
+    (t (:background "gray20" :foreground "violet")))
+  "Face used to visualize \"long\" lines.
+
+See `whitespace-line-column'."
+  :group 'whitespace)
+
+
+(defcustom whitespace-space-before-tab 'whitespace-space-before-tab
+  "Symbol face used to visualize SPACEs before TAB.
+
+Used when `whitespace-style' includes the value `space-before-tab'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-space-before-tab
+  '((((class mono)) (:inverse-video t :bold t :underline t))
+    (t (:background "DarkOrange" :foreground "firebrick")))
+  "Face used to visualize SPACEs before TAB."
+  :group 'whitespace)
+
+
+(defcustom whitespace-indentation 'whitespace-indentation
+  "Symbol face used to visualize 8 or more SPACEs at beginning of line.
+
+Used when `whitespace-style' includes the value `indentation'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-indentation
+  '((((class mono)) (:inverse-video t :bold t :underline t))
+    (t (:background "yellow" :foreground "firebrick")))
+  "Face used to visualize 8 or more SPACEs at beginning of line."
+  :group 'whitespace)
+
+
+(defcustom whitespace-empty 'whitespace-empty
+  "Symbol face used to visualize empty lines at beginning and/or end of buffer.
+
+Used when `whitespace-style' includes the value `empty'."
+  :type 'face
+  :group 'whitespace)
+
+
+(defface whitespace-empty
+  '((((class mono)) (:inverse-video t :bold t :underline t))
+    (t (:background "yellow" :foreground "firebrick")))
+  "Face used to visualize empty lines at beginning and/or end of buffer."
+  :group 'whitespace)
+
+
+(defcustom whitespace-space-after-tab 'whitespace-space-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
+  :group 'whitespace)
+
+
+(defface whitespace-space-after-tab
+  '((((class mono)) (:inverse-video t :bold t :underline t))
+    (t (:background "yellow" :foreground "firebrick")))
+  "Face used to visualize 8 or more SPACEs after TAB."
+  :group 'whitespace)
+
+
+(defcustom whitespace-hspace-regexp
+  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
+  "Specify HARD SPACE characters regexp.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"
+
+that should be considered HARD SPACE.
+
+Here are some examples:
+
+   \"\\\\(^\\xA0+\\\\)\"               \
+visualize only leading HARD SPACEs.
+   \"\\\\(\\xA0+$\\\\)\"               \
+visualize only trailing HARD SPACEs.
+   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"   \
+visualize leading and/or trailing HARD SPACEs.
+   \"\\t\\\\(\\xA0+\\\\)\\t\"          \
+visualize only HARD SPACEs between TABs.
+
+NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
+      Use exactly one pair of enclosing \\\\( and \\\\).
+
+Used when `whitespace-style' includes `spaces'."
+  :type '(regexp :tag "HARD SPACE Chars")
+  :group 'whitespace)
+
+
+(defcustom whitespace-space-regexp "\\( +\\)"
+  "Specify SPACE characters regexp.
+
+If you're using `mule' package, there may be other characters
+besides \" \" that should be considered SPACE.
+
+Here are some examples:
+
+   \"\\\\(^ +\\\\)\"           visualize only leading SPACEs.
+   \"\\\\( +$\\\\)\"           visualize only trailing SPACEs.
+   \"\\\\(^ +\\\\| +$\\\\)\"   \
+visualize leading and/or trailing SPACEs.
+   \"\\t\\\\( +\\\\)\\t\"      visualize only SPACEs between TABs.
+
+NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
+      Use exactly one pair of enclosing \\\\( and \\\\).
+
+Used when `whitespace-style' includes `spaces'."
+  :type '(regexp :tag "SPACE Chars")
+  :group 'whitespace)
+
+
+(defcustom whitespace-tab-regexp "\\(\t+\\)"
+  "Specify TAB characters regexp.
+
+If you're using `mule' package, there may be other characters
+besides \"\\t\" that should be considered TAB.
+
+Here are some examples:
+
+   \"\\\\(^\\t+\\\\)\"         visualize only leading TABs.
+   \"\\\\(\\t+$\\\\)\"         visualize only trailing TABs.
+   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"       \
+visualize leading and/or trailing TABs.
+   \" \\\\(\\t+\\\\) \"        visualize only TABs between SPACEs.
+
+NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
+      Use exactly one pair of enclosing \\\\( and \\\\).
+
+Used when `whitespace-style' includes `tabs'."
+  :type '(regexp :tag "TAB Chars")
+  :group 'whitespace)
+
+
+(defcustom whitespace-trailing-regexp
+  "\\(\\(\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)$"
+  "Specify trailing characters regexp.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
+\"\\xF20\"
+
+that should be considered blank.
+
+NOTE: Enclose always by \"\\\\(\" and \"\\\\)$\" the elements to highlight.
+      Use exactly one pair of enclosing elements above.
+
+Used when `whitespace-style' includes `trailing'."
+  :type '(regexp :tag "Trailing Chars")
+  :group 'whitespace)
+
+
+(defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
+  "Specify SPACEs before TAB regexp.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
+\"\\xF20\"
+
+that should be considered blank.
+
+Used when `whitespace-style' includes `space-before-tab',
+`space-before-tab::tab' or  `space-before-tab::space'."
+  :type '(regexp :tag "SPACEs Before TAB")
+  :group 'whitespace)
+
+
+(defcustom whitespace-indentation-regexp
+  '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
+    . "^ *\\(\t+\\)[^\n]")
+  "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.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
+\"\\xF20\"
+
+that should be considered blank.
+
+Used when `whitespace-style' includes `indentation',
+`indentation::tab' or  `indentation::space'."
+  :type '(cons (regexp :tag "Indentation SPACEs")
+              (regexp :tag "Indentation TABs"))
+  :group 'whitespace)
+
+
+(defcustom whitespace-empty-at-bob-regexp "\\`\\(\\([ \t]*\n\\)+\\)"
+  "Specify regexp for empty lines at beginning of buffer.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
+\"\\xF20\"
+
+that should be considered blank.
+
+Used when `whitespace-style' includes `empty'."
+  :type '(regexp :tag "Empty Lines At Beginning Of Buffer")
+  :group 'whitespace)
+
+
+(defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)\\'"
+  "Specify regexp for empty lines at end of buffer.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
+\"\\xF20\"
+
+that should be considered blank.
+
+Used when `whitespace-style' includes `empty'."
+  :type '(regexp :tag "Empty Lines At End Of Buffer")
+  :group 'whitespace)
+
+
+(defcustom whitespace-space-after-tab-regexp
+  '("\t+\\(\\( \\{%d\\}\\)+\\)"
+    . "\\(\t+\\) +")
+  "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.
+
+If you're using `mule' package, there may be other characters besides:
+
+   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
+\"\\xF20\"
+
+that should be considered blank.
+
+Used when `whitespace-style' includes `space-after-tab',
+`space-after-tab::tab' or `space-after-tab::space'."
+  :type '(regexp :tag "SPACEs After TAB")
+  :group 'whitespace)
+
+
+(defcustom whitespace-line-column 80
+  "Specify column beyond which the line is highlighted.
+
+Used when `whitespace-style' includes `lines' or `lines-tail'."
+  :type '(integer :tag "Line Length")
+  :group 'whitespace)
+
+
+;; Hacked from `visible-whitespace-mappings' in visws.el
+(defcustom whitespace-display-mappings
+  '(
+    (space-mark   ?\     [?\u00B7]     [?.])           ; space - centered dot
+    (space-mark   ?\xA0  [?\u00A4]     [?_])           ; hard space - currency
+    (space-mark   ?\x8A0 [?\x8A4]      [?_])           ; hard space - currency
+    (space-mark   ?\x920 [?\x924]      [?_])           ; hard space - currency
+    (space-mark   ?\xE20 [?\xE24]      [?_])           ; hard space - currency
+    (space-mark   ?\xF20 [?\xF24]      [?_])           ; hard space - currency
+    ;; NEWLINE is displayed using the face `whitespace-newline'
+    (newline-mark ?\n    [?$ ?\n])                     ; eol - dollar sign
+    ;; (newline-mark ?\n    [?\u21B5 ?\n] [?$ ?\n])    ; eol - downwards arrow
+    ;; (newline-mark ?\n    [?\u00B6 ?\n] [?$ ?\n])    ; eol - pilcrow
+    ;; (newline-mark ?\n    [?\x8AF ?\n]  [?$ ?\n])    ; eol - overscore
+    ;; (newline-mark ?\n    [?\x8AC ?\n]  [?$ ?\n])    ; eol - negation
+    ;; (newline-mark ?\n    [?\x8B0 ?\n]  [?$ ?\n])    ; eol - grade
+    ;;
+    ;; WARNING: the mapping below has a problem.
+    ;; When a TAB occupies exactly one column, it will display the
+    ;; character ?\xBB at that column followed by a TAB which goes to
+    ;; the next TAB column.
+    ;; If this is a problem for you, please, comment the line below.
+    (tab-mark     ?\t    [?\u00BB ?\t] [?\\ ?\t])      ; tab - left quote mark
+    )
+  "Specify an alist of mappings for displaying characters.
+
+Each element has the following form:
+
+   (KIND CHAR VECTOR...)
+
+Where:
+
+KIND   is the kind of character.
+       It can be one of the following symbols:
+
+       tab-mark        for TAB character
+
+       space-mark      for SPACE or HARD SPACE character
+
+       newline-mark    for NEWLINE character
+
+CHAR   is the character to be mapped.
+
+VECTOR is a vector of characters to be displayed in place of CHAR.
+       The first display vector that can be displayed is used;
+       if no display vector for a mapping can be displayed, then
+       that character is displayed unmodified.
+
+The NEWLINE character is displayed using the face given by
+`whitespace-newline' variable.
+
+Used when `whitespace-style' includes `tab-mark', `space-mark' or
+`newline-mark'."
+  :type '(repeat
+         (list :tag "Character Mapping"
+               (choice :tag "Char Kind"
+                       (const :tag "Tab" tab-mark)
+                       (const :tag "Space" space-mark)
+                       (const :tag "Newline" newline-mark))
+               (character :tag "Char")
+               (repeat :inline t :tag "Vector List"
+                       (vector :tag ""
+                               (repeat :inline t
+                                       :tag "Vector Characters"
+                                       (character :tag "Char"))))))
+  :group 'whitespace)
+
+
+(defcustom whitespace-global-modes t
+  "Modes for which global `whitespace-mode' is automagically turned on.
+
+Global `whitespace-mode' is controlled by the command
+`global-whitespace-mode'.
+
+If nil, means no modes have `whitespace-mode' automatically
+turned on.
+
+If t, all modes that support `whitespace-mode' have it
+automatically turned on.
+
+Else it should be a list of `major-mode' symbol names for which
+`whitespace-mode' should be automatically turned on.  The sense
+of the list is negated if it begins with `not'.  For example:
+
+   (c-mode c++-mode)
+
+means that `whitespace-mode' is turned on for buffers in C and
+C++ modes only."
+  :type '(choice :tag "Global Modes"
+                (const :tag "None" nil)
+                (const :tag "All" t)
+                (set :menu-tag "Mode Specific" :tag "Modes"
+                     :value (not)
+                     (const :tag "Except" not)
+                     (repeat :inline t
+                             (symbol :tag "Mode"))))
+  :group 'whitespace)
+
+
+(defcustom whitespace-action nil
+  "Specify which action is taken when a buffer is visited or written.
+
+It's a list containing some or all of the following values:
+
+   nil                 no action is taken.
+
+   cleanup             cleanup any bogus whitespace always when local
+                       whitespace is turned on.
+                       See `whitespace-cleanup' and
+                       `whitespace-cleanup-region'.
+
+   report-on-bogus     report if there is any bogus whitespace always
+                       when local whitespace is turned on.
+
+   auto-cleanup                cleanup any bogus whitespace when buffer is
+                       written.
+                       See `whitespace-cleanup' and
+                       `whitespace-cleanup-region'.
+
+   abort-on-bogus      abort if there is any bogus whitespace and the
+                       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"
+                (const :tag "None" nil)
+                (repeat :tag "Action List"
+                 (choice :tag "Action"
+                         (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 "Warn If Read-Only" warn-if-read-only))))
+  :group 'whitespace)
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; User commands - Local mode
+
+
+;;;###autoload
+(define-minor-mode whitespace-mode
+  "Toggle whitespace minor mode visualization (\"ws\" on modeline).
+
+If ARG is null, toggle whitespace visualization.
+If ARG is a number greater than zero, turn on visualization;
+otherwise, turn off visualization.
+
+See also `whitespace-style', `whitespace-newline' and
+`whitespace-display-mappings'."
+  :lighter    " ws"
+  :init-value nil
+  :global     nil
+  :group      'whitespace
+  (cond
+   (noninteractive                     ; running a batch job
+    (setq whitespace-mode nil))
+   (whitespace-mode                    ; whitespace-mode on
+    (whitespace-turn-on)
+    (whitespace-action-when-on))
+   (t                                  ; whitespace-mode off
+    (whitespace-turn-off))))
+
+
+;;;###autoload
+(define-minor-mode whitespace-newline-mode
+  "Toggle NEWLINE minor mode visualization (\"nl\" on modeline).
+
+If ARG is null, toggle NEWLINE visualization.
+If ARG is a number greater than zero, turn on visualization;
+otherwise, turn off visualization.
+
+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
+  :group      'whitespace
+  (let ((whitespace-style '(newline-mark newline)))
+    (whitespace-mode whitespace-newline-mode)
+    ;; sync states (running a batch job)
+    (setq whitespace-newline-mode whitespace-mode)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; User commands - Global mode
+
+
+;;;###autoload
+(define-minor-mode global-whitespace-mode
+  "Toggle whitespace global minor mode visualization (\"WS\" on modeline).
+
+If ARG is null, toggle whitespace visualization.
+If ARG is a number greater than zero, turn on visualization;
+otherwise, turn off visualization.
+
+See also `whitespace-style', `whitespace-newline' and
+`whitespace-display-mappings'."
+  :lighter    " WS"
+  :init-value nil
+  :global     t
+  :group      'whitespace
+  (cond
+   (noninteractive                     ; running a batch job
+    (setq global-whitespace-mode nil))
+   (global-whitespace-mode             ; global-whitespace-mode on
+    (save-excursion
+      (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
+      (dolist (buffer (buffer-list))   ; adjust all local mode
+       (set-buffer buffer)
+       (unless whitespace-mode
+         (whitespace-turn-on-if-enabled)))))
+   (t                                  ; global-whitespace-mode off
+    (save-excursion
+      (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
+      (dolist (buffer (buffer-list))   ; adjust all local mode
+       (set-buffer buffer)
+       (unless whitespace-mode
+         (whitespace-turn-off)))))))
+
+
+(defun whitespace-turn-on-if-enabled ()
+  (when (cond
+        ((eq whitespace-global-modes t))
+        ((listp whitespace-global-modes)
+         (if (eq (car-safe whitespace-global-modes) 'not)
+             (not (memq major-mode (cdr whitespace-global-modes)))
+           (memq major-mode whitespace-global-modes)))
+        (t nil))
+    (let (inhibit-quit)
+      ;; Don't turn on whitespace mode if...
+      (or
+       ;; ...we don't have a display (we're running a batch job)
+       noninteractive
+       ;; ...or if the buffer is invisible (name starts with a space)
+       (eq (aref (buffer-name) 0) ?\ )
+       ;; ...or if the buffer is temporary (name starts with *)
+       (and (eq (aref (buffer-name) 0) ?*)
+           ;; except the scratch buffer.
+           (not (string= (buffer-name) "*scratch*")))
+       ;; Otherwise, turn on whitespace mode.
+       (whitespace-turn-on)))))
+
+
+;;;###autoload
+(define-minor-mode global-whitespace-newline-mode
+  "Toggle NEWLINE global minor mode visualization (\"NL\" on modeline).
+
+If ARG is null, toggle NEWLINE visualization.
+If ARG is a number greater than zero, turn on visualization;
+otherwise, turn off visualization.
+
+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
+  :group      'whitespace
+  (let ((whitespace-style '(newline-mark newline)))
+    (global-whitespace-mode global-whitespace-newline-mode)
+    ;; sync states (running a batch job)
+    (setq global-whitespace-newline-mode global-whitespace-mode)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; User commands - Toggle
+
+
+(defconst whitespace-style-value-list
+  '(tabs
+    spaces
+    trailing
+    lines
+    lines-tail
+    newline
+    empty
+    indentation
+    indentation::tab
+    indentation::space
+    space-after-tab
+    space-after-tab::tab
+    space-after-tab::space
+    space-before-tab
+    space-before-tab::tab
+    space-before-tab::space
+    help-newline       ; value used by `whitespace-insert-option-mark'
+    tab-mark
+    space-mark
+    newline-mark
+    )
+  "List of valid `whitespace-style' values.")
+
+
+(defconst whitespace-toggle-option-alist
+  '((?t    . tabs)
+    (?s    . spaces)
+    (?r    . trailing)
+    (?l    . lines)
+    (?L    . lines-tail)
+    (?n    . newline)
+    (?e    . empty)
+    (?\C-i . indentation)
+    (?I    . indentation::tab)
+    (?i    . indentation::space)
+    (?\C-a . space-after-tab)
+    (?A    . space-after-tab::tab)
+    (?a    . space-after-tab::space)
+    (?\C-b . space-before-tab)
+    (?B    . space-before-tab::tab)
+    (?b    . space-before-tab::space)
+    (?T    . tab-mark)
+    (?S    . space-mark)
+    (?N    . newline-mark)
+    (?x    . whitespace-style)
+    )
+  "Alist of toggle options.
+
+Each element has the form:
+
+   (CHAR . SYMBOL)
+
+Where:
+
+CHAR   is a char which the user will have to type.
+
+SYMBOL is a valid symbol associated with CHAR.
+       See `whitespace-style-value-list'.")
+
+
+(defvar whitespace-active-style nil
+  "Used to save locally `whitespace-style' value.")
+
+(defvar whitespace-indent-tabs-mode indent-tabs-mode
+  "Used to save locally `indent-tabs-mode' value.")
+
+(defvar whitespace-tab-width tab-width
+  "Used to save locally `tab-width' value.")
+
+(defvar whitespace-point (point)
+  "Used to save locally current point value.
+Used by `whitespace-trailing-regexp' function (which see).")
+
+(defvar whitespace-font-lock-refontify nil
+  "Used to save locally the font-lock refontify state.
+Used by `whitespace-post-command-hook' function (which see).")
+
+
+;;;###autoload
+(defun whitespace-toggle-options (arg)
+  "Toggle local `whitespace-mode' options.
+
+If local whitespace-mode is off, toggle the option given by ARG
+and turn on local whitespace-mode.
+
+If local whitespace-mode is on, toggle the option given by ARG
+and restart local whitespace-mode.
+
+Interactively, it reads one of the following chars:
+
+  CHAR MEANING
+  (VIA FACES)
+   t   toggle TAB visualization
+   s   toggle SPACE and HARD SPACE visualization
+   r   toggle trailing blanks visualization
+   l   toggle \"long lines\" visualization
+   L   toggle \"long lines\" tail visualization
+   n   toggle NEWLINE visualization
+   e   toggle empty line at bob and/or eob visualization
+   C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
+   I   toggle indentation SPACEs visualization
+   i   toggle indentation TABs visualization
+   C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
+   A   toggle SPACEs after TAB: SPACEs visualization
+   a   toggle SPACEs after TAB: TABs visualization
+   C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
+   B   toggle SPACEs before TAB: SPACEs visualization
+   b   toggle SPACEs before TAB: TABs visualization
+
+  (VIA DISPLAY TABLE)
+   T   toggle TAB visualization
+   S   toggle SPACEs before TAB visualization
+   N   toggle NEWLINE visualization
+
+   x   restore `whitespace-style' value
+   ?   display brief help
+
+Non-interactively, ARG should be a symbol or a list of symbols.
+The valid symbols are:
+
+   tabs                        toggle TAB visualization
+   spaces              toggle SPACE and HARD SPACE visualization
+   trailing            toggle trailing blanks visualization
+   lines               toggle \"long lines\" visualization
+   lines-tail          toggle \"long lines\" tail visualization
+   newline             toggle NEWLINE visualization
+   empty               toggle empty line at bob and/or eob visualization
+   indentation         toggle indentation SPACEs visualization
+   indentation::tab    toggle indentation SPACEs visualization
+   indentation::space  toggle indentation TABs visualization
+   space-after-tab             toggle SPACEs after TAB visualization
+   space-after-tab::tab                toggle SPACEs after TAB: SPACEs visualization
+   space-after-tab::space      toggle SPACEs after TAB: TABs visualization
+   space-before-tab            toggle SPACEs before TAB visualization
+   space-before-tab::tab       toggle SPACEs before TAB: SPACEs visualization
+   space-before-tab::space     toggle SPACEs before TAB: TABs visualization
+
+   tab-mark            toggle TAB visualization
+   space-mark          toggle SPACEs before TAB visualization
+   newline-mark                toggle NEWLINE visualization
+
+   whitespace-style    restore `whitespace-style' value
+
+See `whitespace-style' and `indent-tabs-mode' for documentation."
+  (interactive (whitespace-interactive-char t))
+  (let ((whitespace-style
+        (whitespace-toggle-list t arg whitespace-active-style)))
+    (whitespace-mode 0)
+    (whitespace-mode 1)))
+
+
+(defvar whitespace-toggle-style nil
+  "Used to toggle the global `whitespace-style' value.")
+
+
+;;;###autoload
+(defun global-whitespace-toggle-options (arg)
+  "Toggle global `whitespace-mode' options.
+
+If global whitespace-mode is off, toggle the option given by ARG
+and turn on global whitespace-mode.
+
+If global whitespace-mode is on, toggle the option given by ARG
+and restart global whitespace-mode.
+
+Interactively, it accepts one of the following chars:
+
+  CHAR MEANING
+  (VIA FACES)
+   t   toggle TAB visualization
+   s   toggle SPACE and HARD SPACE visualization
+   r   toggle trailing blanks visualization
+   l   toggle \"long lines\" visualization
+   L   toggle \"long lines\" tail visualization
+   n   toggle NEWLINE visualization
+   e   toggle empty line at bob and/or eob visualization
+   C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
+   I   toggle indentation SPACEs visualization
+   i   toggle indentation TABs visualization
+   C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
+   A   toggle SPACEs after TAB: SPACEs visualization
+   a   toggle SPACEs after TAB: TABs visualization
+   C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
+   B   toggle SPACEs before TAB: SPACEs visualization
+   b   toggle SPACEs before TAB: TABs visualization
+
+  (VIA DISPLAY TABLE)
+   T   toggle TAB visualization
+   S   toggle SPACEs before TAB visualization
+   N   toggle NEWLINE visualization
+
+   x   restore `whitespace-style' value
+   ?   display brief help
+
+Non-interactively, ARG should be a symbol or a list of symbols.
+The valid symbols are:
+
+   tabs                        toggle TAB visualization
+   spaces              toggle SPACE and HARD SPACE visualization
+   trailing            toggle trailing blanks visualization
+   lines               toggle \"long lines\" visualization
+   lines-tail          toggle \"long lines\" tail visualization
+   newline             toggle NEWLINE visualization
+   empty               toggle empty line at bob and/or eob visualization
+   indentation         toggle indentation SPACEs visualization
+   indentation::tab    toggle indentation SPACEs visualization
+   indentation::space  toggle indentation TABs visualization
+   space-after-tab             toggle SPACEs after TAB visualization
+   space-after-tab::tab                toggle SPACEs after TAB: SPACEs visualization
+   space-after-tab::space      toggle SPACEs after TAB: TABs visualization
+   space-before-tab            toggle SPACEs before TAB visualization
+   space-before-tab::tab       toggle SPACEs before TAB: SPACEs visualization
+   space-before-tab::space     toggle SPACEs before TAB: TABs visualization
+
+   tab-mark            toggle TAB visualization
+   space-mark          toggle SPACEs before TAB visualization
+   newline-mark                toggle NEWLINE visualization
+
+   whitespace-style    restore `whitespace-style' value
+
+See `whitespace-style' and `indent-tabs-mode' for documentation."
+  (interactive (whitespace-interactive-char nil))
+  (let ((whitespace-style
+        (whitespace-toggle-list nil arg whitespace-toggle-style)))
+    (setq whitespace-toggle-style whitespace-style)
+    (global-whitespace-mode 0)
+    (global-whitespace-mode 1)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; User commands - Cleanup
+
+
+;;;###autoload
+(defun whitespace-cleanup ()
+  "Cleanup some blank problems in all buffer or at region.
+
+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 transient mark mode, the
+mark is active and \\[universal-argument] was pressed just before
+calling `whitespace-cleanup' interactively.
+
+See also `whitespace-cleanup-region'.
+
+The problems cleaned up are:
+
+1. empty lines at beginning of buffer.
+2. empty lines at end of buffer.
+   If `whitespace-style' includes the value `empty', remove all
+   empty lines at beginning and/or end of buffer.
+
+3. 8 or more SPACEs at beginning of line.
+   If `whitespace-style' includes the value `indentation':
+   replace 8 or more SPACEs at beginning of line by TABs, if
+   `indent-tabs-mode' is non-nil; otherwise, replace TABs by
+   SPACEs.
+   If `whitespace-style' includes the value `indentation::tab',
+   replace 8 or more SPACEs at beginning of line by TABs.
+   If `whitespace-style' includes the value `indentation::space',
+   replace TABs by SPACEs.
+
+4. SPACEs before TAB.
+   If `whitespace-style' includes the value `space-before-tab':
+   replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
+   otherwise, replace TABs by SPACEs.
+   If `whitespace-style' includes the value
+   `space-before-tab::tab', replace SPACEs by TABs.
+   If `whitespace-style' includes the value
+   `space-before-tab::space', replace TABs by SPACEs.
+
+5. SPACEs or TABs at end of line.
+   If `whitespace-style' includes the value `trailing', remove
+   all SPACEs or TABs at end of line.
+
+6. 8 or more SPACEs after TAB.
+   If `whitespace-style' includes the value `space-after-tab':
+   replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
+   otherwise, replace TABs by SPACEs.
+   If `whitespace-style' includes the value
+   `space-after-tab::tab', replace SPACEs by TABs.
+   If `whitespace-style' includes the value
+   `space-after-tab::space', replace TABs by SPACEs.
+
+See `whitespace-style', `indent-tabs-mode' and `tab-width' for
+documentation."
+  (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
+       ;; PROBLEM 2: empty lines at eob
+       ;; ACTION: remove all empty lines at bob and/or eob
+       (when (memq 'empty whitespace-style)
+         (let (overwrite-mode)         ; enforce no overwrite
+           (goto-char (point-min))
+           (when (re-search-forward
+                  whitespace-empty-at-bob-regexp nil t)
+             (delete-region (match-beginning 1) (match-end 1)))
+           (when (re-search-forward
+                  whitespace-empty-at-eob-regexp nil t)
+             (delete-region (match-beginning 1) (match-end 1)))))))
+    ;; 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 (point-min) (point-max)))))
+
+
+;;;###autoload
+(defun whitespace-cleanup-region (start end)
+  "Cleanup some blank problems at region.
+
+The problems cleaned up are:
+
+1. 8 or more SPACEs at beginning of line.
+   If `whitespace-style' includes the value `indentation':
+   replace 8 or more SPACEs at beginning of line by TABs, if
+   `indent-tabs-mode' is non-nil; otherwise, replace TABs by
+   SPACEs.
+   If `whitespace-style' includes the value `indentation::tab',
+   replace 8 or more SPACEs at beginning of line by TABs.
+   If `whitespace-style' includes the value `indentation::space',
+   replace TABs by SPACEs.
+
+2. SPACEs before TAB.
+   If `whitespace-style' includes the value `space-before-tab':
+   replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
+   otherwise, replace TABs by SPACEs.
+   If `whitespace-style' includes the value
+   `space-before-tab::tab', replace SPACEs by TABs.
+   If `whitespace-style' includes the value
+   `space-before-tab::space', replace TABs by SPACEs.
+
+3. SPACEs or TABs at end of line.
+   If `whitespace-style' includes the value `trailing', remove
+   all SPACEs or TABs at end of line.
+
+4. 8 or more SPACEs after TAB.
+   If `whitespace-style' includes the value `space-after-tab':
+   replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
+   otherwise, replace TABs by SPACEs.
+   If `whitespace-style' includes the value
+   `space-after-tab::tab', replace SPACEs by TABs.
+   If `whitespace-style' includes the value
+   `space-after-tab::space', replace TABs by SPACEs.
+
+See `whitespace-style', `indent-tabs-mode' and `tab-width' for
+documentation."
+  (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)
+  "Do ACTION in the string matched by REGEXP between RSTART and REND.
+
+INDEX is the level group matched by REGEXP and used by ACTION.
+
+See also `tab-width'."
+  (goto-char rstart)
+  (while (re-search-forward regexp rend t)
+    (goto-char (match-end index))
+    (funcall action (match-beginning index) (match-end index))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; User command - report
+
+
+(defun whitespace-regexp (regexp &optional kind)
+  "Return REGEXP depending on `whitespace-indent-tabs-mode'."
+  (cond
+   ((or (eq kind 'tab)
+       whitespace-indent-tabs-mode)
+    (format (car regexp) whitespace-tab-width))
+   ((or (eq kind 'space)
+       (not whitespace-indent-tabs-mode))
+    (cdr regexp))))
+
+
+(defun whitespace-indentation-regexp (&optional kind)
+  "Return the indentation regexp depending on `whitespace-indent-tabs-mode'."
+  (whitespace-regexp whitespace-indentation-regexp kind))
+
+
+(defun whitespace-space-after-tab-regexp (&optional kind)
+  "Return the space-after-tab regexp depending on `whitespace-indent-tabs-mode'."
+  (whitespace-regexp whitespace-space-after-tab-regexp kind))
+
+
+(defconst whitespace-report-list
+  (list
+   (cons 'empty                   whitespace-empty-at-bob-regexp)
+   (cons 'empty                   whitespace-empty-at-eob-regexp)
+   (cons 'trailing                whitespace-trailing-regexp)
+   (cons 'indentation             nil)
+   (cons 'indentation::tab        nil)
+   (cons 'indentation::space      nil)
+   (cons 'space-before-tab        whitespace-space-before-tab-regexp)
+   (cons 'space-before-tab::tab   whitespace-space-before-tab-regexp)
+   (cons 'space-before-tab::space whitespace-space-before-tab-regexp)
+   (cons 'space-after-tab         nil)
+   (cons 'space-after-tab::tab    nil)
+   (cons 'space-after-tab::space  nil)
+   )
+   "List of whitespace bogus symbol and corresponding regexp.")
+
+
+(defconst whitespace-report-text
+  '( ;; `indent-tabs-mode' has non-nil value
+    "\
+ Whitespace Report
+
+ Current Setting                       Whitespace Problem
+
+ empty                    []     []  empty lines at beginning of buffer
+ empty                    []     []  empty lines at end of buffer
+ trailing                 []     []  SPACEs or TABs at end of line
+ indentation              []     []  8 or more SPACEs at beginning of line
+ indentation::tab         []     []  8 or more SPACEs at beginning of line
+ indentation::space       []     []  TABs at beginning of line
+ space-before-tab         []     []  SPACEs before TAB
+ space-before-tab::tab    []     []  SPACEs before TAB: SPACEs
+ space-before-tab::space  []     []  SPACEs before TAB: TABs
+ space-after-tab          []     []  8 or more SPACEs after TAB
+ space-after-tab::tab     []     []  8 or more SPACEs after TAB: SPACEs
+ space-after-tab::space   []     []  8 or more SPACEs after TAB: TABs
+
+ indent-tabs-mode =
+ tab-width        = \n\n"
+    . ;; `indent-tabs-mode' has nil value
+    "\
+ Whitespace Report
+
+ Current Setting                       Whitespace Problem
+
+ empty                    []     []  empty lines at beginning of buffer
+ empty                    []     []  empty lines at end of buffer
+ trailing                 []     []  SPACEs or TABs at end of line
+ indentation              []     []  TABs at beginning of line
+ indentation::tab         []     []  8 or more SPACEs at beginning of line
+ indentation::space       []     []  TABs at beginning of line
+ space-before-tab         []     []  SPACEs before TAB
+ space-before-tab::tab    []     []  SPACEs before TAB: SPACEs
+ space-before-tab::space  []     []  SPACEs before TAB: TABs
+ space-after-tab          []     []  8 or more SPACEs after TAB
+ space-after-tab::tab     []     []  8 or more SPACEs after TAB: SPACEs
+ space-after-tab::space   []     []  8 or more SPACEs after TAB: TABs
+
+ indent-tabs-mode =
+ tab-width        = \n\n")
+  "Text for whitespace bogus report.
+
+It is a cons of strings, where the car part is used when
+`indent-tabs-mode' is non-nil, and the cdr part is used when
+`indent-tabs-mode' is nil.")
+
+
+(defconst whitespace-report-buffer-name "*Whitespace Report*"
+  "The buffer name for whitespace bogus report.")
+
+
+;;;###autoload
+(defun whitespace-report (&optional force report-if-bogus)
+  "Report some whitespace problems in buffer.
+
+Return nil if there is no whitespace problem; otherwise, return
+non-nil.
+
+If FORCE is non-nil or \\[universal-argument] was pressed just
+before calling `whitespace-report' interactively, it forces
+`whitespace-style' to have:
+
+   empty
+   trailing
+   indentation
+   space-before-tab
+   space-after-tab
+
+If REPORT-IF-BOGUS is non-nil, it reports only when there are any
+whitespace problems in buffer.
+
+Report if some of the following whitespace problems exist:
+
+* If `indent-tabs-mode' is non-nil:
+   empty               1. empty lines at beginning of buffer.
+   empty               2. empty lines at end of buffer.
+   trailing            3. SPACEs or TABs at end of line.
+   indentation         4. 8 or more SPACEs at beginning of line.
+   space-before-tab    5. SPACEs before TAB.
+   space-after-tab     6. 8 or more SPACEs after TAB.
+
+* If `indent-tabs-mode' is nil:
+   empty               1. empty lines at beginning of buffer.
+   empty               2. empty lines at end of buffer.
+   trailing            3. SPACEs or TABs at end of line.
+   indentation         4. TABS at beginning of line.
+   space-before-tab    5. SPACEs before TAB.
+   space-after-tab     6. 8 or more SPACEs after TAB.
+
+See `whitespace-style' for documentation.
+See also `whitespace-cleanup' and `whitespace-cleanup-region' for
+cleaning up these problems."
+  (interactive (list current-prefix-arg))
+  (whitespace-report-region (point-min) (point-max)
+                           force report-if-bogus))
+
+
+;;;###autoload
+(defun whitespace-report-region (start end &optional force report-if-bogus)
+  "Report some whitespace problems in a region.
+
+Return nil if there is no whitespace problem; otherwise, return
+non-nil.
+
+If FORCE is non-nil or \\[universal-argument] was pressed just
+before calling `whitespace-report-region' interactively, it
+forces `whitespace-style' to have:
+
+   empty
+   indentation
+   space-before-tab
+   trailing
+   space-after-tab
+
+If REPORT-IF-BOGUS is non-nil, it reports only when there are any
+whitespace problems in buffer.
+
+Report if some of the following whitespace problems exist:
+
+* If `indent-tabs-mode' is non-nil:
+   empty               1. empty lines at beginning of buffer.
+   empty               2. empty lines at end of buffer.
+   trailing            3. SPACEs or TABs at end of line.
+   indentation         4. 8 or more SPACEs at beginning of line.
+   space-before-tab    5. SPACEs before TAB.
+   space-after-tab     6. 8 or more SPACEs after TAB.
+
+* If `indent-tabs-mode' is nil:
+   empty               1. empty lines at beginning of buffer.
+   empty               2. empty lines at end of buffer.
+   trailing            3. SPACEs or TABs at end of line.
+   indentation         4. TABS at beginning of line.
+   space-before-tab    5. SPACEs before TAB.
+   space-after-tab     6. 8 or more SPACEs after TAB.
+
+See `whitespace-style' for documentation.
+See also `whitespace-cleanup' and `whitespace-cleanup-region' for
+cleaning up these problems."
+  (interactive "r")
+  (setq force (or current-prefix-arg force))
+  (save-excursion
+    (save-match-data
+      (let* ((has-bogus nil)
+            (rstart    (min start end))
+            (rend      (max start end))
+            (bogus-list
+             (mapcar
+              #'(lambda (option)
+                  (when force
+                    (add-to-list 'whitespace-style (car option)))
+                  (goto-char rstart)
+                  (let ((regexp
+                         (cond
+                          ((eq (car option) 'indentation)
+                           (whitespace-indentation-regexp))
+                          ((eq (car option) 'indentation::tab)
+                           (whitespace-indentation-regexp 'tab))
+                          ((eq (car option) 'indentation::space)
+                           (whitespace-indentation-regexp 'space))
+                          ((eq (car option) 'space-after-tab)
+                           (whitespace-space-after-tab-regexp))
+                          ((eq (car option) 'space-after-tab::tab)
+                           (whitespace-space-after-tab-regexp 'tab))
+                          ((eq (car option) 'space-after-tab::space)
+                           (whitespace-space-after-tab-regexp 'space))
+                          (t
+                           (cdr option)))))
+                    (and (re-search-forward regexp rend t)
+                         (setq has-bogus t))))
+              whitespace-report-list)))
+       (when (if report-if-bogus has-bogus t)
+         (whitespace-kill-buffer whitespace-report-buffer-name)
+         ;; `whitespace-indent-tabs-mode' is local to current buffer
+         ;; `whitespace-tab-width' is local to current buffer
+         (let ((ws-indent-tabs-mode whitespace-indent-tabs-mode)
+               (ws-tab-width whitespace-tab-width))
+           (with-current-buffer (get-buffer-create
+                                 whitespace-report-buffer-name)
+             (erase-buffer)
+             (insert (if ws-indent-tabs-mode
+                         (car whitespace-report-text)
+                       (cdr whitespace-report-text)))
+             (goto-char (point-min))
+             (forward-line 3)
+             (dolist (option whitespace-report-list)
+               (forward-line 1)
+               (whitespace-mark-x
+                27 (memq (car option) whitespace-style))
+               (whitespace-mark-x 7 (car bogus-list))
+               (setq bogus-list (cdr bogus-list)))
+             (forward-line 1)
+             (whitespace-insert-value ws-indent-tabs-mode)
+             (whitespace-insert-value ws-tab-width)
+             (when has-bogus
+               (goto-char (point-max))
+               (insert " Type `M-x whitespace-cleanup'"
+                       " to cleanup the buffer.\n\n"
+                       " Type `M-x whitespace-cleanup-region'"
+                       " to cleanup a region.\n\n"))
+             (whitespace-display-window (current-buffer)))))
+       has-bogus))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Internal functions
+
+
+(defvar whitespace-font-lock-mode nil
+  "Used to remember whether a buffer had font lock mode on or not.")
+
+(defvar whitespace-font-lock nil
+  "Used to remember whether a buffer initially had font lock on or not.")
+
+(defvar whitespace-font-lock-keywords nil
+  "Used to save locally `font-lock-keywords' value.")
+
+
+(defconst whitespace-help-text
+  "\
+ Whitespace Toggle Options
+
+ FACES
+ []  t   - toggle TAB visualization
+ []  s   - toggle SPACE and HARD SPACE visualization
+ []  r   - toggle trailing blanks visualization
+ []  l   - toggle \"long lines\" visualization
+ []  L   - toggle \"long lines\" tail visualization
+ []  n   - toggle NEWLINE visualization
+ []  e   - toggle empty line at bob and/or eob visualization
+ []  C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode')
+ []  I   - toggle indentation SPACEs visualization
+ []  i   - toggle indentation TABs visualization
+ []  C-a - toggle SPACEs after TAB visualization (via `indent-tabs-mode')
+ []  A   - toggle SPACEs after TAB: SPACEs visualization
+ []  a   - toggle SPACEs after TAB: TABs visualization
+ []  C-b - toggle SPACEs before TAB visualization (via `indent-tabs-mode')
+ []  B   - toggle SPACEs before TAB: SPACEs visualization
+ []  b   - toggle SPACEs before TAB: TABs visualization
+
+ DISPLAY TABLE
+ []  T - toggle TAB visualization
+ []  S - toggle SPACE and HARD SPACE visualization
+ []  N - toggle NEWLINE visualization
+
+      x - restore `whitespace-style' value
+
+      ? - display this text\n\n"
+  "Text for whitespace toggle options.")
+
+
+(defconst whitespace-help-buffer-name "*Whitespace Toggle Options*"
+  "The buffer name for whitespace toggle options.")
+
+
+(defun whitespace-insert-value (value)
+  "Insert VALUE at column 20 of next line."
+  (forward-line 1)
+  (move-to-column 20 t)
+  (insert (format "%s" value)))
+
+
+(defun whitespace-mark-x (nchars condition)
+  "Insert the mark ('X' or ' ') after NCHARS depending on CONDITION."
+  (forward-char nchars)
+  (insert (if condition "X" " ")))
+
+
+(defun whitespace-insert-option-mark (the-list the-value)
+  "Insert the option mark ('X' or ' ') in toggle options buffer."
+  (goto-char (point-min))
+  (forward-line 2)
+  (dolist (sym  the-list)
+    (if (eq sym 'help-newline)
+       (forward-line 2)
+      (forward-line 1)
+      (whitespace-mark-x 2 (memq sym the-value)))))
+
+
+(defun whitespace-help-on (style)
+  "Display the whitespace toggle options."
+  (unless (get-buffer whitespace-help-buffer-name)
+    (delete-other-windows)
+    (let ((buffer (get-buffer-create whitespace-help-buffer-name)))
+      (with-current-buffer buffer
+       (erase-buffer)
+       (insert whitespace-help-text)
+       (whitespace-insert-option-mark
+        whitespace-style-value-list style)
+       (whitespace-display-window buffer)))))
+
+
+(defun whitespace-display-window (buffer)
+  "Display BUFFER in a new window."
+  (goto-char (point-min))
+  (set-buffer-modified-p nil)
+  (let ((size (- (window-height)
+                (max window-min-height
+                     (1+ (count-lines (point-min)
+                                      (point-max)))))))
+    (when (<= size 0)
+      (kill-buffer buffer)
+      (error "Frame height is too small; \
+can't split window to display whitespace toggle options"))
+    (set-window-buffer (split-window nil size) buffer)))
+
+
+(defun whitespace-kill-buffer (buffer-name)
+  "Kill buffer BUFFER-NAME and windows related with it."
+  (let ((buffer (get-buffer buffer-name)))
+    (when buffer
+      (delete-windows-on buffer)
+      (kill-buffer buffer))))
+
+
+(defun whitespace-help-off ()
+  "Remove the buffer and window of the whitespace toggle options."
+  (whitespace-kill-buffer whitespace-help-buffer-name))
+
+
+(defun whitespace-interactive-char (local-p)
+  "Interactive function to read a char and return a symbol.
+
+If LOCAL-P is non-nil, it uses a local context; otherwise, it
+uses a global context.
+
+It accepts one of the following chars:
+
+  CHAR MEANING
+  (VIA FACES)
+   t   toggle TAB visualization
+   s   toggle SPACE and HARD SPACE visualization
+   r   toggle trailing blanks visualization
+   l   toggle \"long lines\" visualization
+   L   toggle \"long lines\" tail visualization
+   n   toggle NEWLINE visualization
+   e   toggle empty line at bob and/or eob visualization
+   C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
+   I   toggle indentation SPACEs visualization
+   i   toggle indentation TABs visualization
+   C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
+   A   toggle SPACEs after TAB: SPACEs visualization
+   a   toggle SPACEs after TAB: TABs visualization
+   C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
+   B   toggle SPACEs before TAB: SPACEs visualization
+   b   toggle SPACEs before TAB: TABs visualization
+
+  (VIA DISPLAY TABLE)
+   T   toggle TAB visualization
+   S   toggle SPACE and HARD SPACE visualization
+   N   toggle NEWLINE visualization
+
+   x   restore `whitespace-style' value
+   ?   display brief help
+
+See also `whitespace-toggle-option-alist'."
+  (let* ((is-off (not (if local-p
+                         whitespace-mode
+                       global-whitespace-mode)))
+        (style  (cond (is-off  whitespace-style) ; use default value
+                      (local-p whitespace-active-style)
+                      (t       whitespace-toggle-style)))
+        (prompt
+         (format "Whitespace Toggle %s (type ? for further options)-"
+                 (if local-p "Local" "Global")))
+        ch sym)
+    ;; read a valid option and get the corresponding symbol
+    (save-window-excursion
+      (condition-case data
+         (progn
+           (while
+               ;; while condition
+               (progn
+                 (setq ch (read-char prompt))
+                 (not
+                  (setq sym
+                        (cdr
+                         (assq ch whitespace-toggle-option-alist)))))
+             ;; while body
+             (if (eq ch ?\?)
+                 (whitespace-help-on style)
+               (ding)))
+           (whitespace-help-off)
+           (message " "))              ; clean echo area
+       ;; handler
+       ((quit error)
+        (whitespace-help-off)
+        (error (error-message-string data)))))
+    (list sym)))                       ; return the apropriate symbol
+
+
+(defun whitespace-toggle-list (local-p arg the-list)
+  "Toggle options in THE-LIST based on list ARG.
+
+If LOCAL-P is non-nil, it uses a local context; otherwise, it
+uses a global context.
+
+ARG is a list of options to be toggled.
+
+THE-LIST is a list of options.  This list will be toggled and the
+resultant list will be returned."
+  (unless (if local-p whitespace-mode global-whitespace-mode)
+    (setq the-list whitespace-style))
+  (setq the-list (copy-sequence the-list)) ; keep original list
+  (dolist (sym (if (listp arg) arg (list arg)))
+    (cond
+     ;; ignore help value
+     ((eq sym 'help-newline))
+     ;; restore default values
+     ((eq sym 'whitespace-style)
+      (setq the-list whitespace-style))
+     ;; toggle valid values
+     ((memq sym whitespace-style-value-list)
+      (setq the-list (if (memq sym the-list)
+                        (delq sym the-list)
+                      (cons sym the-list))))))
+  the-list)
+
+
+(defvar whitespace-display-table nil
+  "Used to save a local display table.")
+
+(defvar whitespace-display-table-was-local nil
+  "Used to remember whether a buffer initially had a local display table.")
+
+
+(defun whitespace-turn-on ()
+  "Turn on whitespace visualization."
+  ;; prepare local hooks
+  (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)
+  (set (make-local-variable 'whitespace-font-lock-keywords) nil)
+  (set (make-local-variable 'whitespace-display-table) nil)
+  (set (make-local-variable 'whitespace-display-table-was-local) nil)
+  (set (make-local-variable 'whitespace-active-style)
+       (if (listp whitespace-style)
+          whitespace-style
+        (list whitespace-style)))
+  (set (make-local-variable 'whitespace-indent-tabs-mode)
+       indent-tabs-mode)
+  (set (make-local-variable 'whitespace-tab-width)
+       tab-width)
+  ;; turn on whitespace
+  (when whitespace-active-style
+    (whitespace-color-on)
+    (whitespace-display-char-on)))
+
+
+(defun whitespace-turn-off ()
+  "Turn off whitespace visualization."
+  (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
+  (when whitespace-active-style
+    (whitespace-color-off)
+    (whitespace-display-char-off)))
+
+
+(defun whitespace-style-face-p ()
+  "Return t if there is some visualization via face."
+  (or (memq 'tabs                    whitespace-active-style)
+      (memq 'spaces                  whitespace-active-style)
+      (memq 'trailing                whitespace-active-style)
+      (memq 'lines                   whitespace-active-style)
+      (memq 'lines-tail              whitespace-active-style)
+      (memq 'newline                 whitespace-active-style)
+      (memq 'empty                   whitespace-active-style)
+      (memq 'indentation             whitespace-active-style)
+      (memq 'indentation::tab        whitespace-active-style)
+      (memq 'indentation::space      whitespace-active-style)
+      (memq 'space-after-tab         whitespace-active-style)
+      (memq 'space-after-tab::tab    whitespace-active-style)
+      (memq 'space-after-tab::space  whitespace-active-style)
+      (memq 'space-before-tab        whitespace-active-style)
+      (memq 'space-before-tab::tab   whitespace-active-style)
+      (memq 'space-before-tab::space whitespace-active-style)))
+
+
+(defun whitespace-color-on ()
+  "Turn on color visualization."
+  (when (whitespace-style-face-p)
+    (unless whitespace-font-lock
+      (setq whitespace-font-lock t
+           whitespace-font-lock-keywords
+           (copy-sequence font-lock-keywords)))
+    ;; save current point and refontify when necessary
+    (set (make-local-variable 'whitespace-point)
+        (point))
+    (set (make-local-variable 'whitespace-font-lock-refontify)
+        nil)
+    (add-hook 'post-command-hook #'whitespace-post-command-hook nil t)
+    ;; turn off font lock
+    (set (make-local-variable 'whitespace-font-lock-mode)
+        font-lock-mode)
+    (font-lock-mode 0)
+    ;; add whitespace-mode color into font lock
+    (when (memq 'spaces whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs
+       (list #'whitespace-space-regexp  1 whitespace-space  t)
+       ;; Show HARD SPACEs
+       (list whitespace-hspace-regexp 1 whitespace-hspace t))
+       t))
+    (when (memq 'tabs whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show TABs
+       (list #'whitespace-tab-regexp 1 whitespace-tab t))
+       t))
+    (when (memq 'trailing whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show trailing blanks
+       (list #'whitespace-trailing-regexp 1 whitespace-trailing t))
+       t))
+    (when (or (memq 'lines      whitespace-active-style)
+             (memq 'lines-tail whitespace-active-style))
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show "long" lines
+       (list
+        (format
+         "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
+         whitespace-tab-width (1- whitespace-tab-width)
+         (/ whitespace-line-column whitespace-tab-width)
+         (let ((rem (% whitespace-line-column whitespace-tab-width)))
+           (if (zerop rem)
+               ""
+             (format ".\\{%d\\}" rem))))
+        (if (memq 'lines whitespace-active-style)
+            0                          ; whole line
+          2)                           ; line tail
+        whitespace-line t))
+       t))
+    (cond
+     ((memq 'space-before-tab whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs before TAB (indent-tabs-mode)
+       (list whitespace-space-before-tab-regexp
+             (if whitespace-indent-tabs-mode 1 2)
+             whitespace-space-before-tab t))
+       t))
+     ((memq 'space-before-tab::tab whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs before TAB (SPACEs)
+       (list whitespace-space-before-tab-regexp
+             1 whitespace-space-before-tab t))
+       t))
+     ((memq 'space-before-tab::space whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs before TAB (TABs)
+       (list whitespace-space-before-tab-regexp
+             2 whitespace-space-before-tab t))
+       t)))
+    (cond
+     ((memq 'indentation whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show indentation SPACEs (indent-tabs-mode)
+       (list (whitespace-indentation-regexp)
+             1 whitespace-indentation t))
+       t))
+     ((memq 'indentation::tab whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show indentation SPACEs (SPACEs)
+       (list (whitespace-indentation-regexp 'tab)
+             1 whitespace-indentation t))
+       t))
+     ((memq 'indentation::space whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show indentation SPACEs (TABs)
+       (list (whitespace-indentation-regexp 'space)
+             1 whitespace-indentation t))
+       t)))
+    (when (memq 'empty whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show empty lines at beginning of buffer
+       (list #'whitespace-empty-at-bob-regexp
+             1 whitespace-empty t))
+       t)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show empty lines at end of buffer
+       (list #'whitespace-empty-at-eob-regexp
+             1 whitespace-empty t))
+       t))
+    (cond
+     ((memq 'space-after-tab whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs after TAB (indent-tabs-mode)
+       (list (whitespace-space-after-tab-regexp)
+             1 whitespace-space-after-tab t))
+       t))
+     ((memq 'space-after-tab::tab whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs after TAB (SPACEs)
+       (list (whitespace-space-after-tab-regexp 'tab)
+             1 whitespace-space-after-tab t))
+       t))
+     ((memq 'space-after-tab::space whitespace-active-style)
+      (font-lock-add-keywords
+       nil
+       (list
+       ;; Show SPACEs after TAB (TABs)
+       (list (whitespace-space-after-tab-regexp 'space)
+             1 whitespace-space-after-tab t))
+       t)))
+    ;; now turn on font lock and highlight blanks
+    (font-lock-mode 1)))
+
+
+(defun whitespace-color-off ()
+  "Turn off color visualization."
+  ;; turn off font lock
+  (when (whitespace-style-face-p)
+    (font-lock-mode 0)
+    (remove-hook 'post-command-hook #'whitespace-post-command-hook)
+    (when whitespace-font-lock
+      (setq whitespace-font-lock nil
+           font-lock-keywords   whitespace-font-lock-keywords))
+    ;; restore original font lock state
+    (font-lock-mode whitespace-font-lock-mode)))
+
+
+(defun whitespace-trailing-regexp (limit)
+  "Match trailing spaces which do not contain the point at end of line."
+  (let ((status t))
+    (while (if (re-search-forward whitespace-trailing-regexp limit t)
+              (save-match-data
+                (= whitespace-point (match-end 1))) ;; loop if point at eol
+            (setq status nil)))                     ;; end of buffer
+    status))
+
+
+(defun whitespace-empty-at-bob-regexp (limit)
+  "Match spaces at beginning of buffer which do not contain the point at \
+beginning of buffer."
+  (and (/= whitespace-point 1)
+       (re-search-forward whitespace-empty-at-bob-regexp limit t)))
+
+
+(defun whitespace-empty-at-eob-regexp (limit)
+  "Match spaces at end of buffer which do not contain the point at end of \
+buffer."
+  (and (/= whitespace-point (1+ (buffer-size)))
+       (re-search-forward whitespace-empty-at-eob-regexp limit t)))
+
+
+(defun whitespace-space-regexp (limit)
+  "Match spaces."
+  (setq whitespace-font-lock-refontify t)
+  (re-search-forward whitespace-space-regexp limit t))
+
+
+(defun whitespace-tab-regexp (limit)
+  "Match tabs."
+  (setq whitespace-font-lock-refontify t)
+  (re-search-forward whitespace-tab-regexp limit t))
+
+
+(defun whitespace-post-command-hook ()
+  "Save current point into `whitespace-point' variable.
+Also refontify when necessary."
+  (setq whitespace-point (point))
+  (let ((refontify (or (eolp)                   ; end of line
+                      (= whitespace-point 1)))) ; beginning of buffer
+    (when (or whitespace-font-lock-refontify refontify)
+      (setq whitespace-font-lock-refontify refontify)
+      (jit-lock-refontify))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
+
+
+(defun whitespace-style-mark-p ()
+  "Return t if there is some visualization via display table."
+  (or (memq 'tab-mark     whitespace-active-style)
+      (memq 'space-mark   whitespace-active-style)
+      (memq 'newline-mark whitespace-active-style)))
+
+
+(defsubst whitespace-char-valid-p (char)
+  ;; This check should be improved!!!
+  (or (< char 256)
+      (characterp char)))
+
+
+(defun whitespace-display-vector-p (vec)
+  "Return true if every character in vector VEC can be displayed."
+  (let ((i (length vec)))
+    (when (> i 0)
+      (while (and (>= (setq i (1- i)) 0)
+                 (whitespace-char-valid-p (aref vec i))))
+      (< i 0))))
+
+
+(defun whitespace-display-char-on ()
+  "Turn on character display mapping."
+  (when (and whitespace-display-mappings
+            (whitespace-style-mark-p))
+    (let (vecs vec)
+      ;; Remember whether a buffer has a local display table.
+      (unless whitespace-display-table-was-local
+       (setq whitespace-display-table-was-local t
+             whitespace-display-table
+             (copy-sequence buffer-display-table)))
+      ;; asure `buffer-display-table' is unique
+      ;; when two or more windows are visible.
+      (set (make-local-variable 'buffer-display-table)
+          (copy-sequence buffer-display-table))
+      (unless buffer-display-table
+       (setq buffer-display-table (make-display-table)))
+      (dolist (entry whitespace-display-mappings)
+       ;; check if it is to display this mark
+       (when (memq (car entry) whitespace-style)
+         ;; Get a displayable mapping.
+         (setq vecs (cddr entry))
+         (while (and vecs
+                     (not (whitespace-display-vector-p (car vecs))))
+           (setq vecs (cdr vecs)))
+         ;; Display a valid mapping.
+         (when vecs
+           (setq vec (copy-sequence (car vecs)))
+           ;; NEWLINE char
+           (when (and (eq (cadr entry) ?\n)
+                      (memq 'newline whitespace-active-style))
+             ;; Only insert face bits on NEWLINE char mapping to avoid
+             ;; obstruction of other faces like TABs and (HARD) SPACEs
+             ;; faces, font-lock faces, etc.
+             (dotimes (i (length vec))
+               (or (eq (aref vec i) ?\n)
+                   (aset vec i
+                         (make-glyph-code (aref vec i)
+                                          whitespace-newline)))))
+           ;; Display mapping
+           (aset buffer-display-table (cadr entry) vec)))))))
+
+
+(defun whitespace-display-char-off ()
+  "Turn off character display mapping."
+  (and whitespace-display-mappings
+       (whitespace-style-mark-p)
+       whitespace-display-table-was-local
+       (setq whitespace-display-table-was-local nil
+            buffer-display-table whitespace-display-table)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Hook
+
+
+(defun whitespace-action-when-on ()
+  "Action to be taken always when local whitespace is turned on."
+  (cond ((memq 'cleanup whitespace-action)
+        (whitespace-cleanup))
+       ((memq 'report-on-bogus whitespace-action)
+        (whitespace-report nil t))))
+
+
+(defun whitespace-write-file-hook ()
+  "Action to be taken when buffer is written.
+It should be added buffer-locally to `write-file-functions'."
+  (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
+
+
+(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
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun whitespace-unload-function ()
+  "Unload the whitespace library."
+  (global-whitespace-mode -1)
+  ;; be sure all local whitespace mode is turned off
+  (save-current-buffer
+    (dolist (buf (buffer-list))
+      (set-buffer buf)
+      (whitespace-mode -1)))
+  nil)                                 ; continue standard unloading
+
+
+(provide 'whitespace)
+
+
+(run-hooks 'whitespace-load-hook)
+
+
+;; arch-tag: 1b1e2500-dbd4-4a26-8f7a-5a5edfd3c97e
+;;; whitespace.el ends here