unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* blank-mode.el
@ 2007-10-28 14:20 Vinicius Jose Latorre
  2007-10-28 14:27 ` blank-mode.el Leo
  2007-10-28 17:31 ` blank-mode.el Drew Adams
  0 siblings, 2 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-10-28 14:20 UTC (permalink / raw)
  To: GNU Emacs (devel)

[-- Attachment #1: Type: text/plain, Size: 829 bytes --]

Hi,


It seems there is an interest to install blank-mode package in the Emacs 
distribution.

blank-mode is a minor mode to visualise blanks (SPACE, HARD SPACE and TAB).

blank-mode uses two ways to visualise blanks: faces and display table.

  * Faces are used to highlight the background with a color.  blank-mode 
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 `blank-style' and `blank-chars' variables are used to select which way
should be used to visualise blanks.

To see some screenshots and documentation:

    http://www.emacswiki.org/cgi-bin/wiki/BlankMode


Send your suggestions, comments, etc.


Vinicius


[-- Attachment #2: blank-mode.el --]
[-- Type: text/plain, Size: 30592 bytes --]

;;; blank-mode.el --- Minor mode to visualise blanks (SPACE, HARD SPACE and TAB).

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/10/11 08:46:10 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 6.7
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 2, or (at your option) any later
;; version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE and
;; TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display table.
;;
;; * Faces are used to highlight the background with a color.  blank-mode 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 `blank-style' and `blank-chars' variables are used to select which way
;; should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the font-lock
;; state, that is, if font-lock is on or off.  And blank-mode restores the
;; font-lock state when it is turned off.  So, if blank-mode is turned on and
;; font-lock is off, blank-mode also turns on the font-lock to highlight
;; blanks, but the font-lock will be turned off when blank-mode is turned off.
;; Thus, turn on font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-global-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'blank-global-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'blank-global-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21 and 22.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To activate blank-mode globally, type:
;;
;;         M-x blank-global-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-global-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x blank-global-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-global-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x blank-global-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `blank-global-mode', `blank-global-mode-on', `blank-global-mode-off' and
;; `blank-mode-customize' to some key, like:
;;
;;    (global-set-key "\C-c\C-a" 'blank-mode-on)
;;    (global-set-key "\C-c\C-b" 'blank-mode-off)
;;    (global-set-key "\C-c\C-l" 'blank-mode)
;;    (global-set-key "\C-c\C-d" 'blank-global-mode-on)
;;    (global-set-key "\C-c\C-e" 'blank-global-mode-off)
;;    (global-set-key "\C-c\C-g" 'blank-global-mode)
;;    (global-set-key "\C-c\C-c" 'blank-mode-customize)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `blank-global-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please, see the
;; options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab regexp.
;;
;; `blank-line-length'		Specify length beyond which the line is
;;				highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for displaying
;;				characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new Emacs
;;    session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs session.
;;
;; c) or use customization, for example:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs" space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "SteelBlue4"  :foreground "Aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "Aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face ; 'nobreak-space
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face
  '((((class color) (background dark))
     :background "CadetBlue5"    :foreground "Aquamarine3")
    (((class color) (background light))
     :background "LemonChiffon3" :foreground "Aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "SkyBlue4" :foreground "Aquamarine3")
    (((class color) (background light))
     :background "Beige"    :foreground "Aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.  See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "CadetBlue5" :foreground "Aquamarine3" :bold t)
    (((class color) (background light))
     :background "Linen"      :foreground "Aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.  See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face ; 'trailing-whitespace
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.  See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.  See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp "\\(\xA0+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides \"\\xA0\"
that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	visualise leading and/or trailing hard spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters besides \" \"
that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters besides \"\\t\"
that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has 'tabs
as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp "\t\\| \\|\xA0"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides \" \",
\"\\t\" or \"\\xA0\" that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and `blank-chars' has
'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides \" \",
\"\\t\" or \"\\xA0\" that it should be considered blank.

Used when `blank-style' has 'color as an element, and `blank-chars' has
'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and `blank-chars' has 'lines
as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '((?\    [?\xB7]     [?.])		; space
    (?\xA0 [?\xA4]     [?_])		; hard space
    (?\n   [?\xB6 ?\n] [?$ ?\n])	; end-of-line
    ;; 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.
    (?\t   [?\xBB ?\t] [?\\ ?\t])	; tab
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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 `blank-map-face'
variable.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t :tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `blank-global-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically turned on.
If a list, it should be a list of `major-mode' symbol names for which
`blank-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 `blank-mode' is turned on for buffers in C and C++ modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Macros


(defmacro blank-message (&rest body)
  `(and blank-verbose (interactive-p)
	(message ,@body)))


(defmacro blank-minor-mode (arg mode on off)
  `(progn
     (if (if arg
	     (> (prefix-numeric-value arg) 0)
	   (not ,mode))
	 (,on)
       (,off))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Local mode


(defvar blank-mode nil
  "Non-nil means blank-mode local minor mode is enabled (bl on modeline).")
(make-variable-buffer-local 'blank-mode)


;;;###autoload
(defun blank-mode (&optional arg)
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation."
  (interactive "P")
  (blank-minor-mode arg blank-mode
		    blank-mode-on blank-mode-off)
  (blank-message "Blank Mode is now %s." (if blank-mode "on" "off")))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (or (and (boundp 'blank-mode) blank-mode)
      (when blank-style
	(setq blank-mode t)
	(blank-turn-on)
	(run-hooks 'blank-mode-hook)
	(blank-message "Blank Mode is now on."))))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (and (boundp 'blank-mode) blank-mode
       (progn
	 (setq blank-mode nil)
	 (blank-turn-off)
	 (blank-message "Blank Mode is now off."))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Global mode


(defvar blank-global-mode nil
  "Non-nil means blank-mode global minor mode is enabled (BL on modeline).")


;;;###autoload
(defun blank-global-mode (&optional arg)
  "Toggle blank global minor mode visualisation (BL on modeline).

With ARG, turn highline mode on if ARG is positive, off otherwise.
Only useful with a windowing system."
  (interactive "P")
  (blank-minor-mode arg blank-global-mode
		    blank-global-mode-on blank-global-mode-off)
  (blank-message "Blank Global Mode is %s" (if blank-global-mode "on" "off")))


;;;###autoload
(defun blank-global-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (or (and (boundp 'blank-global-mode) blank-global-mode)
      (progn
	(save-excursion
	  (let ((buffers (buffer-list)))
	    (setq blank-global-mode t)
	    (if (boundp 'find-file-hook)
		(add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	      (add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
	    (while buffers		; adjust all local mode
	      (set-buffer (car buffers))
	      (unless blank-mode
		(blank-turn-on-if-enabled))
	      (setq buffers (cdr buffers)))))
	(run-hooks 'blank-global-mode-hook)
	(blank-message "Blank Global Mode is on"))))


;;;###autoload
(defun blank-global-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (and (boundp 'blank-global-mode) blank-global-mode
       (progn
	 (save-excursion
	   (let ((buffers (buffer-list)))
	     (setq blank-global-mode nil)
	    (if (boundp 'find-file-hook)
		(remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	      (remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
	     (while buffers		; adjust all local mode
	       (set-buffer (car buffers))
	       (unless blank-mode
		 (blank-turn-off))
	       (setq buffers (cdr buffers)))))
	 (blank-message "Blank Global Mode is off"))))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank mode if...
      (or
       ;; ...we don't have a display (we're running a batch job)
       noninteractive
       ;; ...or if the buffer is invisible (the name starts with a space)
       (eq (aref (buffer-name) 0) ?\ )
       ;; ...or if the buffer is temporary (the name starts with *)
       (and (eq (aref (buffer-name) 0) ?*)
	    ;; except the scratch buffer.
	    (not (string= (buffer-name) "*scratch*")))
       ;; Otherwise, turn on blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Internal functions


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length) ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode nil)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode t)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode nil)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in the display vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (and blank-display-mappings
       (let ((face-bits (ash (face-id blank-map-face) 19))
	     (map-list blank-display-mappings)
	     entry vecs len vec i)
	 ;; Remember whether a buffer has a local display table.
	 (unless blank-display-table-was-local
	   (setq blank-display-table-was-local t
		 blank-display-table (copy-sequence buffer-display-table)))
	 (or buffer-display-table
	     (setq buffer-display-table (make-display-table)))
	 (while map-list
	   (setq entry    (car map-list)
		 vecs     (cdr entry)
		 map-list (cdr map-list))
	   ;; Get a displayable mapping.
	   (while (and vecs (not (blank-legal-display-vector-p (car vecs))))
	     (setq vecs (cdr vecs)))
	   ;; Display a valid mapping.
	   (when vecs
	     (setq vec (copy-sequence (car vecs)))
	     ;; Only insert face bits on NEWLINE char mapping to avoid
	     ;; obstruction of other faces like TABs and (HARD) SPACEs faces,
	     ;; font-lock faces, etc.
	     (when (eq (car entry) ?\n)
	       (setq len (length (car vecs))
		     i -1)
	       (while (< (setq i (1+ i)) len)
		 (or (eq (aref vec i) ?\n)
		     (aset vec i (logior (aref vec i) face-bits)))))
	     (aset buffer-display-table (car entry) vec))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(add-to-list 'minor-mode-alist '(blank-mode        " bl"))
(add-to-list 'minor-mode-alist '(blank-global-mode " BL"))


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-28 14:20 blank-mode.el Vinicius Jose Latorre
@ 2007-10-28 14:27 ` Leo
  2007-10-28 18:10   ` blank-mode.el Vinicius Jose Latorre
  2007-10-28 17:31 ` blank-mode.el Drew Adams
  1 sibling, 1 reply; 56+ messages in thread
From: Leo @ 2007-10-28 14:27 UTC (permalink / raw)
  To: emacs-devel

On 2007-10-28 14:20 +0000, Vinicius Jose Latorre wrote:
> Hi,
>
> It seems there is an interest to install blank-mode package in the
> Emacs distribution.
[...]

There is another package whitespace.el included in Emacs already that
seems to do similar things.

-- 
.:  Leo  :.  [ sdl.web AT gmail.com ]  .:  [ GPG Key: 9283AA3F ]  :.

       Use the most powerful email client -- http://gnus.org/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: blank-mode.el
  2007-10-28 14:20 blank-mode.el Vinicius Jose Latorre
  2007-10-28 14:27 ` blank-mode.el Leo
@ 2007-10-28 17:31 ` Drew Adams
  2007-10-28 19:35   ` blank-mode.el Vinicius Jose Latorre
  1 sibling, 1 reply; 56+ messages in thread
From: Drew Adams @ 2007-10-28 17:31 UTC (permalink / raw)
  To: Vinicius Jose Latorre, GNU Emacs (devel)

> It seems there is an interest to install blank-mode package in the Emacs
> distribution. blank-mode is a minor mode to visualise blanks (SPACE,
> HARD SPACE and TAB). blank-mode uses two ways to visualise blanks:
> faces and display table.
...
> The `blank-style' and `blank-chars' variables are used to select which way
> should be used to visualise blanks. To see some screenshots and
documentation:
>     http://www.emacswiki.org/cgi-bin/wiki/BlankMode

I am in favor of it.

User option `blank-chars' specifies which blank characters to highlight, but
it would be good to also have commands to toggle each highlighting type. For
example, `M-x blank-toggle-trailing' and `M-x blank-toggle-tabs'. And it
would be good to have this for both local and global use:
`blank-toggle-tabs-global', in addition to `blank-toggle-tabs'.

There are a few other libraries at
http://www.emacswiki.org/cgi-bin/wiki/ShowWhiteSpace. I think Vinicius's
approach might be the best, but it would be good to take a look at the
others for possible features (such as the selectivity commands mentioned
above).

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-28 14:27 ` blank-mode.el Leo
@ 2007-10-28 18:10   ` Vinicius Jose Latorre
  0 siblings, 0 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-10-28 18:10 UTC (permalink / raw)
  To: Leo; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1234 bytes --]

Leo wrote:
> On 2007-10-28 14:20 +0000, Vinicius Jose Latorre wrote:
>   
>> Hi,
>>
>> It seems there is an interest to install blank-mode package in the
>> Emacs distribution.
>>     
> [...]
>
> There is another package whitespace.el included in Emacs already that
> seems to do similar things.
>   

whitespace.el is different from blank-mode:

;; 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.

Also, whitespace uses text properties to highlight and blank-mode uses 
font-lock and/or display table.

The whitespace purpose is to detect problems and blank-mode purpose is 
only to visualise any space.  That is, whitespace only highlight spaces 
when there is a problem.

The attached image shows when blank-mode is on.


[-- Attachment #2: BlankModeOn.png --]
[-- Type: image/png, Size: 11914 bytes --]

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: blank-mode.el
  2007-10-28 19:35   ` blank-mode.el Vinicius Jose Latorre
@ 2007-10-28 19:05     ` Drew Adams
  2007-10-28 23:04       ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Drew Adams @ 2007-10-28 19:05 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: GNU Emacs (devel)

> > User option `blank-chars' specifies which blank characters to
> > highlight, but it would be good to also have commands to toggle
> > each highlighting type. For example, `M-x blank-toggle-trailing'
> > and `M-x blank-toggle-tabs'. And it would be good to have this
> > for both local and global use: `blank-toggle-tabs-global', in
> > addition to `blank-toggle-tabs'.
>
> Hummm, maybe a better approach could be to pass a list to blank-mode or
> blank-global-mode like:
>
> ; turn on local blank-mode but only highlight trailing spaces and spaces
> before tab
> (blank-mode '(trailing space-before-tab))
>
> So, the command above is the same as the following sequence:
>
> (blank-mode nil)
> (setq blank-chars '(trailing space-before-tab))
> (blank-mode t)

What would that mean interactively? Would the user need to decide which
chars to highlight each time s?he used the mode command? How would s?he
specify those chars - input their names with completion? What if s?he just
wants the default (current) `blank-chars' - does s?he still need to specify
all the chars to highlight when turning on the mode?

I don't think the choice of what to highlight should be connected with the
mode command. That should remain a simple toggle, just turning on/off
highlighting as specified by the current value of `blank-chars'. Much of the
time, that will be all a user needs.

I'd prefer to have a separate toggle command for each kind of blank
highlighting - those commands would only change the value of `blank-chars'.
That, to me, is the most convenient for the user - more convenient than
`set-variable' or `customize-option', and more convenient that coupling
highlighting changes with the mode command.

Second best is just using `set-variable' (but that requires you to specify
each of the chars to highlight). IIUC, least convenient of all, IMO, is
coupling the minor-mode command with the chars choice.

My suggestion lets users change the highlighting by expressing only the
delta - not all of the chars to highlight, but just what to change.

Just one opinion.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-28 17:31 ` blank-mode.el Drew Adams
@ 2007-10-28 19:35   ` Vinicius Jose Latorre
  2007-10-28 19:05     ` blank-mode.el Drew Adams
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-10-28 19:35 UTC (permalink / raw)
  To: Drew Adams; +Cc: GNU Emacs (devel)

Drew Adams wrote:
> User option `blank-chars' specifies which blank characters to highlight, but
> it would be good to also have commands to toggle each highlighting type. For
> example, `M-x blank-toggle-trailing' and `M-x blank-toggle-tabs'. And it
> would be good to have this for both local and global use:
> `blank-toggle-tabs-global', in addition to `blank-toggle-tabs'.
>   

Hummm, maybe a better approach could be to pass a list to blank-mode or 
blank-global-mode like:

; turn on local blank-mode but only highlight trailing spaces and spaces 
before tab
(blank-mode '(trailing space-before-tab))

So, the command above is the same as the following sequence:

(blank-mode nil)
(setq blank-chars '(trailing space-before-tab))
(blank-mode t)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: blank-mode.el
  2007-10-28 23:04       ` blank-mode.el Vinicius Jose Latorre
@ 2007-10-28 22:11         ` Drew Adams
  2007-10-29 10:00         ` blank-mode.el Kim F. Storm
  1 sibling, 0 replies; 56+ messages in thread
From: Drew Adams @ 2007-10-28 22:11 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: GNU Emacs (devel)

> Ok, instead of modifying blank-mode behavior passing a list,
> we could have the following commands:
>     blank-toggle
>     blank-global-toggle

`blank-toggle-global' - it's easier to see that both exist when using
completion.

> When activated interactively, it asks to user which feature to highlight
> (it could be via a menu, in a similar way that C-h behaves).  The menu
> options could be something like:
>     t - tabs
>     s - spaces and hard spaces
>     r - trailing blanks
>     b - spaces before tab
>     l - lines
>     ? - display the menu
> So, if blank-toggle is binded to a key, for example, C-c b, then the
> user could type:
>     C-c b t      toggle tabs
>     C-c b s      toggle spaces and hard spaces
>     C-c b r      toggle trailing blanks
>     C-c b b      toggle spaces before tab
>     C-c b l      toggle lines
> Or the user could type:
>     M-x blank-toggle RET t
>     M-x blank-toggle RET s
>     etc.
> And via ELisp code, it could pass a symbol like:
>     (blank-toggle 'trailing)
>     (blank-toggle 'space-before-tab)
>     etc.
> Also, via ELisp code, it could pass a list like:
>     (blank-toggle '(trailing space-before-tab))

Sounds good to me.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-28 19:05     ` blank-mode.el Drew Adams
@ 2007-10-28 23:04       ` Vinicius Jose Latorre
  2007-10-28 22:11         ` blank-mode.el Drew Adams
  2007-10-29 10:00         ` blank-mode.el Kim F. Storm
  0 siblings, 2 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-10-28 23:04 UTC (permalink / raw)
  To: Drew Adams; +Cc: GNU Emacs (devel)

Drew Adams wrote:
>>> User option `blank-chars' specifies which blank characters to
>>> highlight, but it would be good to also have commands to toggle
>>> each highlighting type. For example, `M-x blank-toggle-trailing'
>>> and `M-x blank-toggle-tabs'. And it would be good to have this
>>> for both local and global use: `blank-toggle-tabs-global', in
>>> addition to `blank-toggle-tabs'.
>> Hummm, maybe a better approach could be to pass a list to blank-mode or
>> blank-global-mode like:
>>
>> ; turn on local blank-mode but only highlight trailing spaces and spaces
>> before tab
>> (blank-mode '(trailing space-before-tab))
>>
>> So, the command above is the same as the following sequence:
>>
>> (blank-mode nil)
>> (setq blank-chars '(trailing space-before-tab))
>> (blank-mode t)
>
> What would that mean interactively?

Indeed, I was thinking only in terms of an ELisp code.


>                                     Would the user need to decide which
> chars to highlight each time s?he used the mode command?

Well, the user always have to decide which blank to highlight via a toggle
command interactively or via a list in an ELisp code.


>                                                          How would s?he
> specify those chars - input their names with completion?

Interactively, well, it could pass an ELisp expression, if the command uses
(interactive "X").  Hummm, this doesn't seem to be a good thing to do.


>                                                          What if s?he just
> wants the default (current) `blank-chars' - does s?he still need to specify
> all the chars to highlight when turning on the mode?

Interactively, it could pass an ELisp expression, so it could pass 
blank-chars
var as an argument.


> I don't think the choice of what to highlight should be connected with the
> mode command. That should remain a simple toggle, just turning on/off
> highlighting as specified by the current value of `blank-chars'. Much of the
> time, that will be all a user needs.
>
> I'd prefer to have a separate toggle command for each kind of blank
> highlighting - those commands would only change the value of `blank-chars'.
> That, to me, is the most convenient for the user - more convenient than
> `set-variable' or `customize-option', and more convenient that coupling
> highlighting changes with the mode command.
>
> Second best is just using `set-variable' (but that requires you to specify
> each of the chars to highlight). IIUC, least convenient of all, IMO, is
> coupling the minor-mode command with the chars choice.
>
> My suggestion lets users change the highlighting by expressing only the
> delta - not all of the chars to highlight, but just what to change.

Ok, instead of modifying blank-mode behavior passing a list,
we could have the following commands:

    blank-toggle

    blank-global-toggle

When activated interactively, it asks to user which feature to highlight
(it could be via a menu, in a similar way that C-h behaves).  The menu
options could be something like:

    t - tabs
    s - spaces and hard spaces
    r - trailing blanks
    b - spaces before tab
    l - lines
    ? - display the menu

So, if blank-toggle is binded to a key, for example, C-c b, then the 
user could
type:

    C-c b t      toggle tabs
    C-c b s      toggle spaces and hard spaces
    C-c b r      toggle trailing blanks
    C-c b b      toggle spaces before tab
    C-c b l      toggle lines

Or the user could type:

    M-x blank-toggle RET t
    M-x blank-toggle RET s
    etc.

And via ELisp code, it could pass a symbol like:

    (blank-toggle 'trailing)
    (blank-toggle 'space-before-tab)
    etc.

Also, via ELisp code, it could pass a list like:

    (blank-toggle '(trailing space-before-tab))


> Just one opinion.

Thanks for your opinion.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-28 23:04       ` blank-mode.el Vinicius Jose Latorre
  2007-10-28 22:11         ` blank-mode.el Drew Adams
@ 2007-10-29 10:00         ` Kim F. Storm
  2007-10-29 15:37           ` blank-mode.el Vinicius Jose Latorre
  1 sibling, 1 reply; 56+ messages in thread
From: Kim F. Storm @ 2007-10-29 10:00 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: Drew Adams, GNU Emacs (devel)

Vinicius Jose Latorre <viniciusjl@ig.com.br> writes:

> So, if blank-toggle is binded to a key, for example, C-c b, then the
> user could
> type:
>
>    C-c b t      toggle tabs
>    C-c b s      toggle spaces and hard spaces
>    C-c b r      toggle trailing blanks
>    C-c b b      toggle spaces before tab
>    C-c b l      toggle lines

I like the idea (and blank-mode in general), but according to the
Emacs Lisp reference, C-c b is reserved for major modes:

   The key sequences bound in a minor mode should consist of `C-c'
followed by one of `.,/?`'"[]\|~!#$%^&*()-_+='.  (The other punctuation
characters are reserved for major modes.)

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-29 10:00         ` blank-mode.el Kim F. Storm
@ 2007-10-29 15:37           ` Vinicius Jose Latorre
  2007-10-30 14:17             ` blank-mode.el Juri Linkov
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-10-29 15:37 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: Drew Adams, GNU Emacs (devel)

Kim F. Storm wrote:
> Vinicius Jose Latorre <viniciusjl@ig.com.br> writes:
>
>   
>> So, if blank-toggle is binded to a key, for example, C-c b, then the
>> user could
>> type:
>>
>>    C-c b t      toggle tabs
>>    C-c b s      toggle spaces and hard spaces
>>    C-c b r      toggle trailing blanks
>>    C-c b b      toggle spaces before tab
>>    C-c b l      toggle lines
>>     
>
> I like the idea (and blank-mode in general), but according to the
> Emacs Lisp reference, C-c b is reserved for major modes:
>
>    The key sequences bound in a minor mode should consist of `C-c'
> followed by one of `.,/?`'"[]\|~!#$%^&*()-_+='.  (The other punctuation
> characters are reserved for major modes.)
>   

No problem, the key binding above was only an example, it could be any 
other key binding.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-29 15:37           ` blank-mode.el Vinicius Jose Latorre
@ 2007-10-30 14:17             ` Juri Linkov
  2007-10-31  4:16               ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Juri Linkov @ 2007-10-30 14:17 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: emacs-devel

>>> So, if blank-toggle is binded to a key, for example, C-c b, then the
>>> user could
>>> type:
>>>
>>>    C-c b t      toggle tabs
>>>    C-c b s      toggle spaces and hard spaces
>>>    C-c b r      toggle trailing blanks
>>>    C-c b b      toggle spaces before tab
>>>    C-c b l      toggle lines
>>
>> I like the idea (and blank-mode in general),

I like this package too, and I have some suggestions: since it implements
a minor mode I suggest defining it with `define-minor-mode', and name the
global mode `global-blank-mode'.

Also I have a question how it interacts with nobreak-char-display.
Does your package overwrite highlighting of nobreak space displayed
by nobreak-char-display feature, or ignores it?

>> but according to the
>> Emacs Lisp reference, C-c b is reserved for major modes:
>>
>>    The key sequences bound in a minor mode should consist of `C-c'
>> followed by one of `.,/?`'"[]\|~!#$%^&*()-_+='.  (The other punctuation
>> characters are reserved for major modes.)
>
> No problem, the key binding above was only an example, it could be any
> other key binding.

I think a key prefix with good mnemonics for blank-minor-mode is `C-c _'.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-30 14:17             ` blank-mode.el Juri Linkov
@ 2007-10-31  4:16               ` Vinicius Jose Latorre
  2007-10-31 16:11                 ` blank-mode.el Juri Linkov
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-10-31  4:16 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2301 bytes --]


The blank-mode.el (attached in this email) now has the toggle funs:

    blank-toggle
    blank-toggle-global

If it's called interactively, it reads a char.

If it's called non-interactively, it should be passed a symbol or a list 
of symbols.

Please, read the fun docstring.


Juri Linkov wrote:
>>>> So, if blank-toggle is binded to a key, for example, C-c b, then the
>>>> user could
>>>> type:
>>>>
>>>>    C-c b t      toggle tabs
>>>>    C-c b s      toggle spaces and hard spaces
>>>>    C-c b r      toggle trailing blanks
>>>>    C-c b b      toggle spaces before tab
>>>>    C-c b l      toggle lines
>>> I like the idea (and blank-mode in general),
>
> I like this package too, and I have some suggestions: since it implements
> a minor mode I suggest defining it with `define-minor-mode', and name the
> global mode `global-blank-mode'.

Well, I'll try to use define-minor-mode in the next blank-mode version.

Is there some convention (or consensus) about global mode name?


> Also I have a question how it interacts with nobreak-char-display.
> Does your package overwrite highlighting of nobreak space displayed
> by nobreak-char-display feature, or ignores it?

I've made some tests and both blank-mode faces and display table are 
displayed when blank-mode is on and nobreak-char-display is t.

When blank-mode is turned off and nobreak-char-display is t, the 
nobreak-char-display faces and display table are displayed.

That is, blank-mode have precedence over nobreak-char-display but only 
over hard spaces (or nobreak spaces), the soft hyphens is handled only 
by nobreak-char-display.

The same occurs with show-trailing-whitespace feature.


>>> but according to the
>>> Emacs Lisp reference, C-c b is reserved for major modes:
>>>
>>>    The key sequences bound in a minor mode should consist of `C-c'
>>> followed by one of `.,/?`'"[]\|~!#$%^&*()-_+='.  (The other punctuation
>>> characters are reserved for major modes.)
>> No problem, the key binding above was only an example, it could be any
>> other key binding.
>
> I think a key prefix with good mnemonics for blank-minor-mode is `C-c _'.

Cool!

At moment blank-mode doesn't have any key binding, this is left to the 
user do.

But I'll put a tip in blank-mode documentation suggesting the key prefix 
`C-c _'.


[-- Attachment #2: blank-mode.el --]
[-- Type: text/plain, Size: 39347 bytes --]

;;; blank-mode.el --- Minor mode to visualise blanks (SPACE, HARD SPACE and TAB).

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/10/31 00:49:12 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.0
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 2, or (at your option) any later
;; version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE and
;; TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display table.
;;
;; * Faces are used to highlight the background with a color.  blank-mode 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 `blank-style' and `blank-chars' variables are used to select which way
;; should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the font-lock
;; state, that is, if font-lock is on or off.  And blank-mode restores the
;; font-lock state when it is turned off.  So, if blank-mode is turned on and
;; font-lock is off, blank-mode also turns on the font-lock to highlight
;; blanks, but the font-lock will be turned off when blank-mode is turned off.
;; Thus, turn on font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-global-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'blank-global-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'blank-global-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21 and 22.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle RET
;;
;; * GLOBAL blank-mode:
;;    + To activate blank-mode globally, type:
;;
;;         M-x blank-global-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-global-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x blank-global-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-global-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x blank-global-mode RET
;;
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x blank-toggle-global RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `blank-global-mode', `blank-global-mode-on', `blank-global-mode-off',
;; `blank-mode-customize', `blank-toggle' and `blank-toggle-global' to some
;; key, like:
;;
;;    (global-set-key "\C-c\C-a" 'blank-mode-on)
;;    (global-set-key "\C-c\C-b" 'blank-mode-off)
;;    (global-set-key "\C-c\C-l" 'blank-mode)
;;    (global-set-key "\C-c\C-d" 'blank-global-mode-on)
;;    (global-set-key "\C-c\C-e" 'blank-global-mode-off)
;;    (global-set-key "\C-c\C-g" 'blank-global-mode)
;;    (global-set-key "\C-c\C-c" 'blank-mode-customize)
;;    (global-set-key "\C-c_"    'blank-toggle)
;;    (global-set-key "\C-c="    'blank-toggle-global)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `blank-global-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please, see the
;; options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab regexp.
;;
;; `blank-line-length'		Specify length beyond which the line is
;;				highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for displaying
;;				characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new Emacs
;;    session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs session.
;;
;; c) or use customization, for example:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs" space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "SteelBlue4"  :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face ; 'nobreak-space
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face
  '((((class color) (background dark))
     :background "CadetBlue4"    :foreground "aquamarine3")
    (((class color) (background light))
     :background "LemonChiffon3" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "SkyBlue4" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"    :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.  See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "CadetBlue5" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"      :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.  See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face ; 'trailing-whitespace
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.  See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.  See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides \"\\xA0\"
that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	visualise leading and/or trailing hard
					spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters besides \" \"
that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters besides \"\\t\"
that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has 'tabs
as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides \" \",
\"\\t\" or \"\\xA0\" that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and `blank-chars' has
'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides \" \",
\"\\t\" or \"\\xA0\" that it should be considered blank.

Used when `blank-style' has 'color as an element, and `blank-chars' has
'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and `blank-chars' has 'lines
as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '((?\xA0  [?\xA4]     [?_])		; hard space
    (?\x8A0 [?\x8A4]    [?_])		; hard space
    (?\x920 [?\x924]    [?_])		; hard space
    (?\xe20 [?\xe24]    [?_])		; hard space
    (?\xf20 [?\xf24]    [?_])		; hard space
    (?\     [?\xB7]     [?.])		; space
    (?\n    [?\xB6 ?\n] [?$ ?\n])	; end-of-line
    ;; 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.
    (?\t    [?\xBB ?\t] [?\\ ?\t])	; tab
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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 `blank-map-face'
variable.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t :tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `blank-global-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically turned on.
If a list, it should be a list of `major-mode' symbol names for which
`blank-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 `blank-mode' is turned on for buffers in C and C++ modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Macros


(defmacro blank-message (&rest body)
  `(and blank-verbose (interactive-p)
	(message ,@body)))


(defmacro blank-minor-mode (arg mode on off)
  `(progn
     (if (if arg
	     (> (prefix-numeric-value arg) 0)
	   (not ,mode))
	 (,on)
       (,off))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Local mode


(defvar blank-mode nil
  "Non-nil means blank-mode local minor mode is enabled (bl on modeline).")
(make-variable-buffer-local 'blank-mode)


;;;###autoload
(defun blank-mode (&optional arg)
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation.
Only useful with a windowing system."
  (interactive "P")
  (blank-minor-mode arg blank-mode
		    blank-mode-on blank-mode-off)
  (blank-message "Blank Mode is now %s." (if blank-mode "on" "off")))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (or noninteractive
      blank-mode
      (when blank-style
	(setq blank-mode t)
	(blank-turn-on)
	(run-hooks 'blank-mode-hook)
	(blank-message "Blank Mode is now on."))))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (and blank-mode
       (progn
	 (setq blank-mode nil)
	 (blank-turn-off)
	 (blank-message "Blank Mode is now off."))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Global mode


(defvar blank-global-mode nil
  "Non-nil means blank-mode global minor mode is enabled (BL on modeline).")


;;;###autoload
(defun blank-global-mode (&optional arg)
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation.
Only useful with a windowing system."
  (interactive "P")
  (blank-minor-mode arg blank-global-mode
		    blank-global-mode-on blank-global-mode-off)
  (blank-message "Blank Global Mode is %s" (if blank-global-mode "on" "off")))


;;;###autoload
(defun blank-global-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (or noninteractive
      blank-global-mode
      (progn
	(save-excursion
	  (let ((buffers (buffer-list)))
	    (setq blank-global-mode t)
	    (if (boundp 'find-file-hook)
		(add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	      (add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
	    (while buffers		; adjust all local mode
	      (set-buffer (car buffers))
	      (unless blank-mode
		(blank-turn-on-if-enabled))
	      (setq buffers (cdr buffers)))))
	(run-hooks 'blank-global-mode-hook)
	(blank-message "Blank Global Mode is on"))))


;;;###autoload
(defun blank-global-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (and blank-global-mode
       (progn
	 (save-excursion
	   (let ((buffers (buffer-list)))
	     (setq blank-global-mode nil)
	    (if (boundp 'find-file-hook)
		(remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	      (remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
	     (while buffers		; adjust all local mode
	       (set-buffer (car buffers))
	       (unless blank-mode
		 (blank-turn-off))
	       (setq buffers (cdr buffers)))))
	 (blank-message "Blank Global Mode is off"))))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank mode if...
      (or
       ;; ...we don't have a display (we're running a batch job)
       noninteractive
       ;; ...or if the buffer is invisible (the name starts with a space)
       (eq (aref (buffer-name) 0) ?\ )
       ;; ...or if the buffer is temporary (the name starts with *)
       (and (eq (aref (buffer-name) 0) ?*)
	    ;; except the scratch buffer.
	    (not (string= (buffer-name) "*scratch*")))
       ;; Otherwise, turn on blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Toggle


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (save-excursion
      (let ((buffer (get-buffer-create blank-help-buffer-name)))
	(delete-windows-on buffer)
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(forward-line 1)
	(dolist (sym  blank-chars-value-list)
	  (forward-line 1)
	  (forward-char 2)
	  (insert (if (memq sym chars) "*" " ")))
	(forward-line 1)
	(dolist (sym  blank-style-value-list)
	  (forward-line 1)
	  (forward-char 2)
	  (insert (if (memq sym style) "*" " ")))
	(goto-char (point-min))
	(set-buffer-modified-p nil)
	(let* ((lines (count-lines (point-min) (point-max)))
	       (size (- (window-height)
			(max window-min-height
			     (1+ lines)))))
	  (set-window-buffer (split-window nil size) buffer)))))
  t)


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-interactive-char (local-p)
  "Interactive function to read a char and return the corresponding symbol.

If LOCAL-P is non-nil, it uses a local context; otherwise, it uses a global
context.

It reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let ((prompt (format "Blank Toggle %s (type ? for further options)-"
			(if local-p "Local" "Global")))
	(chars (if local-p blank-active-chars blank-toggle-chars))
	(style (if local-p blank-active-style blank-toggle-style))
	c s emsg)
    ;; if blank-mode is off, use default value
    (unless (if local-p blank-mode blank-global-mode)
      (unless chars
	(setq chars blank-chars))
      (unless style
	(setq style blank-style)))
    ;; read a valid option and get the corresponding symbol
    (condition-case data
	(progn
	  (while (progn
		   (setq c (read-char prompt))
		   (not (setq s (cdr (assq c blank-toggle-option-alist)))))
	    (if (eq c ?\?)
		(blank-help-on chars style)
	      (ding))))
      ;; handler
      ((quit error)
       (setq emsg (error-message-string data))))
    (blank-help-off)
    (when emsg
      (error emsg))
    (message " ")			; clean echo area
    (list s)))


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to restore the options
in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's options are
valid."
  (unless (if local-p
	      (and blank-mode blank-active-style)
	    blank-global-mode)
    (setq the-list default-list))
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


;;;###autoload
(defun blank-toggle (arg)
  "Toggle local `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.  The valid
symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars (blank-toggle-list t arg blank-active-chars blank-chars
					'blank-chars blank-chars-value-list))
	(blank-style (blank-toggle-list t arg blank-active-style blank-style
					'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun blank-toggle-global (arg)
  "Toggle global `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.  The valid
symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars (blank-toggle-list nil arg blank-toggle-chars blank-chars
					'blank-chars blank-chars-value-list))
	(blank-style (blank-toggle-list nil arg blank-toggle-style blank-style
					'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (blank-global-mode 0)
    (blank-global-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Internal functions


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length) ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in the display vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (and blank-display-mappings
       (let ((face-bits (ash (face-id blank-map-face) 19))
	     (map-list blank-display-mappings)
	     entry vecs len vec i)
	 ;; Remember whether a buffer has a local display table.
	 (unless blank-display-table-was-local
	   (setq blank-display-table-was-local t
		 blank-display-table (copy-sequence buffer-display-table)))
	 (or buffer-display-table
	     (setq buffer-display-table (make-display-table)))
	 (while map-list
	   (setq entry    (car map-list)
		 vecs     (cdr entry)
		 map-list (cdr map-list))
	   ;; Get a displayable mapping.
	   (while (and vecs (not (blank-legal-display-vector-p (car vecs))))
	     (setq vecs (cdr vecs)))
	   ;; Display a valid mapping.
	   (when vecs
	     (setq vec (copy-sequence (car vecs)))
	     ;; Only insert face bits on NEWLINE char mapping to avoid
	     ;; obstruction of other faces like TABs and (HARD) SPACEs faces,
	     ;; font-lock faces, etc.
	     (when (eq (car entry) ?\n)
	       (setq len (length (car vecs))
		     i -1)
	       (while (< (setq i (1+ i)) len)
		 (or (eq (aref vec i) ?\n)
		     (aset vec i (logior (aref vec i) face-bits)))))
	     (aset buffer-display-table (car entry) vec))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(add-to-list 'minor-mode-alist '(blank-mode        " bl"))
(add-to-list 'minor-mode-alist '(blank-global-mode " BL"))


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-31  4:16               ` blank-mode.el Vinicius Jose Latorre
@ 2007-10-31 16:11                 ` Juri Linkov
  2007-11-09 17:10                   ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Juri Linkov @ 2007-10-31 16:11 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: emacs-devel

>> I like this package too, and I have some suggestions: since it implements
>> a minor mode I suggest defining it with `define-minor-mode', and name the
>> global mode `global-blank-mode'.
>
> Well, I'll try to use define-minor-mode in the next blank-mode version.
>
> Is there some convention (or consensus) about global mode name?

I can't find such conventions in (info "(elisp)Major Mode Conventions")
and (info "(elisp)Minor Mode Conventions").

>> Also I have a question how it interacts with nobreak-char-display.
>> Does your package overwrite highlighting of nobreak space displayed
>> by nobreak-char-display feature, or ignores it?
>
> I've made some tests and both blank-mode faces and display table are
> displayed when blank-mode is on and nobreak-char-display is t.
>
> When blank-mode is turned off and nobreak-char-display is t, the
> nobreak-char-display faces and display table are displayed.
>
> That is, blank-mode have precedence over nobreak-char-display but only
> over hard spaces (or nobreak spaces), the soft hyphens is handled only by
> nobreak-char-display.

I think this is the right behavior: when blank-mode is on, it should take
care of highlighting these special characters over the default mechanism
of nobreak-char-display.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-10-31 16:11                 ` blank-mode.el Juri Linkov
@ 2007-11-09 17:10                   ` Vinicius Jose Latorre
  2007-11-09 18:11                     ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-09 17:10 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1538 bytes --]

Juri Linkov wrote:
>>> I like this package too, and I have some suggestions: since it implements
>>> a minor mode I suggest defining it with `define-minor-mode', and name the
>>> global mode `global-blank-mode'.
>>>       
>> Well, I'll try to use define-minor-mode in the next blank-mode version.
>>
>> Is there some convention (or consensus) about global mode name?
>>     
>
> I can't find such conventions in (info "(elisp)Major Mode Conventions")
> and (info "(elisp)Minor Mode Conventions").
>   

Ok, I changed all blank-*global functions to global-blank-*.

Also now blank-mode uses define-minor-mode.
See attached file (blank-mode v7.1).


>>> Also I have a question how it interacts with nobreak-char-display.
>>> Does your package overwrite highlighting of nobreak space displayed
>>> by nobreak-char-display feature, or ignores it?
>>>       
>> I've made some tests and both blank-mode faces and display table are
>> displayed when blank-mode is on and nobreak-char-display is t.
>>
>> When blank-mode is turned off and nobreak-char-display is t, the
>> nobreak-char-display faces and display table are displayed.
>>
>> That is, blank-mode have precedence over nobreak-char-display but only
>> over hard spaces (or nobreak spaces), the soft hyphens is handled only by
>> nobreak-char-display.
>>     
>
> I think this is the right behavior: when blank-mode is on, it should take
> care of highlighting these special characters over the default mechanism
> of nobreak-char-display.
>   

Ok, this is the blank-mode behavior.


[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 39102 bytes --]

;;; blank-mode.el --- Minor mode to visualise blanks (SPACE, HARD SPACE and TAB).

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/09 14:04:58 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 2, or (at your option) any later
;; version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE and
;; TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display table.
;;
;; * Faces are used to highlight the background with a color.  blank-mode 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 `blank-style' and `blank-chars' variables are used to select which way
;; should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the font-lock
;; state, that is, if font-lock is on or off.  And blank-mode restores the
;; font-lock state when it is turned off.  So, if blank-mode is turned on and
;; font-lock is off, blank-mode also turns on the font-lock to highlight
;; blanks, but the font-lock will be turned off when blank-mode is turned off.
;; Thus, turn on font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'global-blank-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'blank-toggle          "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'global-blank-toggle   "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on', `global-blank-mode-off',
;; `blank-mode-customize', `blank-toggle' and `global-blank-toggle' to some
;; key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c_t" 'blank-toggle)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please, see the
;; options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab regexp.
;;
;; `blank-line-length'		Specify length beyond which the line is
;;				highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for displaying
;;				characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new Emacs
;;    session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs session.
;;
;; c) or use customization, for example:
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix.
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs" space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "SteelBlue4"  :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face ; 'nobreak-space
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face
  '((((class color) (background dark))
     :background "CadetBlue4"    :foreground "aquamarine3")
    (((class color) (background light))
     :background "LemonChiffon3" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "SkyBlue4" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"    :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.  See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "CadetBlue5" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"      :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.  See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face ; 'trailing-whitespace
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.  See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.  See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	visualise leading and/or trailing hard
					spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters besides \" \"
that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters besides \"\\t\"
that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has 'tabs
as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and `blank-chars' has
'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and `blank-chars' has
'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and `blank-chars' has 'lines
as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '((?\xA0  [?\xA4]     [?_])		; hard space
    (?\x8A0 [?\x8A4]    [?_])		; hard space
    (?\x920 [?\x924]    [?_])		; hard space
    (?\xE20 [?\xE24]    [?_])		; hard space
    (?\xF20 [?\xF24]    [?_])		; hard space
    (?\     [?\xB7]     [?.])		; space
    (?\n    [?\xB6 ?\n] [?$ ?\n])	; end-of-line
    ;; 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.
    (?\t    [?\xBB ?\t] [?\\ ?\t])	; tab
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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 `blank-map-face'
variable.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t :tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically turned on.
If a list, it should be a list of `major-mode' symbol names for which
`blank-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 `blank-mode' is turned on for buffers in C and C++ modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (when blank-style
      (blank-turn-on)))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank mode if...
      (or
       ;; ...we don't have a display (we're running a batch job)
       noninteractive
       ;; ...or if the buffer is invisible (the name starts with a space)
       (eq (aref (buffer-name) 0) ?\ )
       ;; ...or if the buffer is temporary (the name starts with *)
       (and (eq (aref (buffer-name) 0) ?*)
	    ;; except the scratch buffer.
	    (not (string= (buffer-name) "*scratch*")))
       ;; Otherwise, turn on blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Toggle


;;;###autoload
(defun blank-toggle (arg)
  "Toggle local `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.  The valid
symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars (blank-toggle-list t arg blank-active-chars blank-chars
					'blank-chars blank-chars-value-list))
	(blank-style (blank-toggle-list t arg blank-active-style blank-style
					'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle (arg)
  "Toggle global `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.  The valid
symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars (blank-toggle-list nil arg blank-toggle-chars blank-chars
					'blank-chars blank-chars-value-list))
	(blank-style (blank-toggle-list nil arg blank-toggle-style blank-style
					'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('*' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "*" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(goto-char (point-min))
	(set-buffer-modified-p nil)
	(let* ((lines (count-lines (point-min) (point-max)))
	       (size (- (window-height)
			(max window-min-height
			     (1+ lines)))))
	  (if (<= size 0)
	      (error (concat "Frame height is too small; "
			     "can't split window to display "
			     "blank toggle options"))
	    (set-window-buffer (split-window nil size) buffer)))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-interactive-char (local-p)
  "Interactive function to read a char and return the corresponding symbol.

If LOCAL-P is non-nil, it uses a local context; otherwise, it uses a global
context.

It reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let ((prompt (format "Blank Toggle %s (type ? for further options)-"
			(if local-p "Local" "Global")))
	(chars (if local-p blank-active-chars blank-toggle-chars))
	(style (if local-p blank-active-style blank-toggle-style))
	ch sym)
    ;; if blank-mode is off, use default value
    (unless (if local-p blank-mode global-blank-mode)
      (unless chars
	(setq chars blank-chars))
      (unless style
	(setq style blank-style)))
    ;; read a valid option and get the corresponding symbol
    (save-window-excursion
      (condition-case data
	  (progn
	    (while (progn
		     (setq ch (read-char prompt))
		     (not (setq sym
				(cdr (assq ch blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to restore the options
in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's options are
valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length) ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in the display vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (and blank-display-mappings
       (let ((face-bits (ash (face-id blank-map-face) 19))
	     (map-list blank-display-mappings)
	     entry vecs len vec i)
	 ;; Remember whether a buffer has a local display table.
	 (unless blank-display-table-was-local
	   (setq blank-display-table-was-local t
		 blank-display-table (copy-sequence buffer-display-table)))
	 (or buffer-display-table
	     (setq buffer-display-table (make-display-table)))
	 (while map-list
	   (setq entry    (car map-list)
		 vecs     (cdr entry)
		 map-list (cdr map-list))
	   ;; Get a displayable mapping.
	   (while (and vecs (not (blank-legal-display-vector-p (car vecs))))
	     (setq vecs (cdr vecs)))
	   ;; Display a valid mapping.
	   (when vecs
	     (setq vec (copy-sequence (car vecs)))
	     ;; Only insert face bits on NEWLINE char mapping to avoid
	     ;; obstruction of other faces like TABs and (HARD) SPACEs faces,
	     ;; font-lock faces, etc.
	     (when (eq (car entry) ?\n)
	       (setq len (length (car vecs))
		     i -1)
	       (while (< (setq i (1+ i)) len)
		 (or (eq (aref vec i) ?\n)
		     (aset vec i (logior (aref vec i) face-bits)))))
	     (aset buffer-display-table (car entry) vec))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-09 17:10                   ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-09 18:11                     ` Vinicius Jose Latorre
  2007-11-09 20:41                       ` blank-mode.el Robert J. Chassell
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-09 18:11 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 106 bytes --]


I've just fixed the blank-mode documentation.

The latest blank-mode version is attached in this email.


[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 40119 bytes --]

;;; blank-mode.el --- Minor mode to visualise blanks (SPACE, HARD SPACE and TAB).

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/09 15:09:07 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 2, or (at your option) any later
;; version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE and
;; TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display table.
;;
;; * Faces are used to highlight the background with a color.  blank-mode 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 `blank-style' and `blank-chars' variables are used to select which way
;; should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the font-lock
;; state, that is, if font-lock is on or off.  And blank-mode restores the
;; font-lock state when it is turned off.  So, if blank-mode is turned on and
;; font-lock is off, blank-mode also turns on the font-lock to highlight
;; blanks, but the font-lock will be turned off when blank-mode is turned off.
;; Thus, turn on font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode is on, it takes care of highlighting some special characters
;; over the default mechanism of `nobreak-char-display' and
;; `show-trailing-whitespace' (which see).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That is, if you
;;   turn on global blank-mode and then create a new buffer, the new buffer
;;   will also have blank-mode on.  The `blank-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
;; blank-mode has priority over global blank-mode.  That is, when global and
;; local blank-mode are on, if local blank-mode is turned off, blank-mode is
;; turned off for the current buffer only.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle          "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle   "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on', `global-blank-mode-off',
;; `blank-mode-customize', `blank-toggle' and `global-blank-toggle' to some
;; key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please, see the
;; options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab regexp.
;;
;; `blank-line-length'		Specify length beyond which the line is
;;				highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for displaying
;;				characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new Emacs
;;    session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs session.
;;
;; c) or use customization, for example:
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not when
;;    you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' name for global commands.
;;
;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix.
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs" space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "SteelBlue4"  :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face ; 'nobreak-space
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face
  '((((class color) (background dark))
     :background "CadetBlue4"    :foreground "aquamarine3")
    (((class color) (background light))
     :background "LemonChiffon3" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "SkyBlue4" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"    :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.  See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "CadetBlue5" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"      :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.  See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face ; 'trailing-whitespace
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.  See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.  See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	visualise leading and/or trailing hard
					spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters besides \" \"
that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has
'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters besides \"\\t\"
that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and `blank-chars' has 'tabs
as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and `blank-chars' has
'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and `blank-chars' has
'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and `blank-chars' has 'lines
as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '((?\xA0  [?\xA4]     [?_])		; hard space
    (?\x8A0 [?\x8A4]    [?_])		; hard space
    (?\x920 [?\x924]    [?_])		; hard space
    (?\xE20 [?\xE24]    [?_])		; hard space
    (?\xF20 [?\xF24]    [?_])		; hard space
    (?\     [?\xB7]     [?.])		; space
    (?\n    [?\xB6 ?\n] [?$ ?\n])	; end-of-line
    ;; 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.
    (?\t    [?\xBB ?\t] [?\\ ?\t])	; tab
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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 `blank-map-face'
variable.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t :tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically turned on.
If a list, it should be a list of `major-mode' symbol names for which
`blank-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 `blank-mode' is turned on for buffers in C and C++ modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (when blank-style
      (blank-turn-on)))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on visualisation; otherwise,
turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank mode if...
      (or
       ;; ...we don't have a display (we're running a batch job)
       noninteractive
       ;; ...or if the buffer is invisible (the name starts with a space)
       (eq (aref (buffer-name) 0) ?\ )
       ;; ...or if the buffer is temporary (the name starts with *)
       (and (eq (aref (buffer-name) 0) ?*)
	    ;; except the scratch buffer.
	    (not (string= (buffer-name) "*scratch*")))
       ;; Otherwise, turn on blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User commands - Toggle


;;;###autoload
(defun blank-toggle (arg)
  "Toggle local `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.  The valid
symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars (blank-toggle-list t arg blank-active-chars blank-chars
					'blank-chars blank-chars-value-list))
	(blank-style (blank-toggle-list t arg blank-active-style blank-style
					'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle (arg)
  "Toggle global `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.  The valid
symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars (blank-toggle-list nil arg blank-toggle-chars blank-chars
					'blank-chars blank-chars-value-list))
	(blank-style (blank-toggle-list nil arg blank-toggle-style blank-style
					'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('*' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "*" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(goto-char (point-min))
	(set-buffer-modified-p nil)
	(let* ((lines (count-lines (point-min) (point-max)))
	       (size (- (window-height)
			(max window-min-height
			     (1+ lines)))))
	  (if (<= size 0)
	      (error (concat "Frame height is too small; "
			     "can't split window to display "
			     "blank toggle options"))
	    (set-window-buffer (split-window nil size) buffer)))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-interactive-char (local-p)
  "Interactive function to read a char and return the corresponding symbol.

If LOCAL-P is non-nil, it uses a local context; otherwise, it uses a global
context.

It reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let ((prompt (format "Blank Toggle %s (type ? for further options)-"
			(if local-p "Local" "Global")))
	(chars (if local-p blank-active-chars blank-toggle-chars))
	(style (if local-p blank-active-style blank-toggle-style))
	ch sym)
    ;; if blank-mode is off, use default value
    (unless (if local-p blank-mode global-blank-mode)
      (unless chars
	(setq chars blank-chars))
      (unless style
	(setq style blank-style)))
    ;; read a valid option and get the corresponding symbol
    (save-window-excursion
      (condition-case data
	  (progn
	    (while (progn
		     (setq ch (read-char prompt))
		     (not (setq sym
				(cdr (assq ch blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to restore the options
in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's options are
valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length) ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in the display vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (and blank-display-mappings
       (let ((face-bits (ash (face-id blank-map-face) 19))
	     (map-list blank-display-mappings)
	     entry vecs len vec i)
	 ;; Remember whether a buffer has a local display table.
	 (unless blank-display-table-was-local
	   (setq blank-display-table-was-local t
		 blank-display-table (copy-sequence buffer-display-table)))
	 (or buffer-display-table
	     (setq buffer-display-table (make-display-table)))
	 (while map-list
	   (setq entry    (car map-list)
		 vecs     (cdr entry)
		 map-list (cdr map-list))
	   ;; Get a displayable mapping.
	   (while (and vecs (not (blank-legal-display-vector-p (car vecs))))
	     (setq vecs (cdr vecs)))
	   ;; Display a valid mapping.
	   (when vecs
	     (setq vec (copy-sequence (car vecs)))
	     ;; Only insert face bits on NEWLINE char mapping to avoid
	     ;; obstruction of other faces like TABs and (HARD) SPACEs faces,
	     ;; font-lock faces, etc.
	     (when (eq (car entry) ?\n)
	       (setq len (length (car vecs))
		     i -1)
	       (while (< (setq i (1+ i)) len)
		 (or (eq (aref vec i) ?\n)
		     (aset vec i (logior (aref vec i) face-bits)))))
	     (aset buffer-display-table (car entry) vec))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-09 18:11                     ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-09 20:41                       ` Robert J. Chassell
  2007-11-11  2:13                         ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-09 20:41 UTC (permalink / raw)
  To: emacs-devel

 1. Rather than exceed 80 characters, the first line of blank-mode.el
    should be:

;;; blank-mode.el --- Minor mode to visualise blanks (SPACE, HARD SPACE, TAB)

    with a comma instead of an `and' before the word `TAB' and no period.
    That is 77 characters long which is almost, but not quite, too much
    for a heading.

 2. Regarding the body of the library, as a general rule, comments
    should be filled according to the Emacs default -- I notice the
    lengths are longer although they are less than 80 characters.

 3. Also, while a carriage return occurs at the end of a line, that
    place does not necessarily mark the end of a paragraph.  By
    default, please do not use a between-paragraph symbol for the end
    of a line (a carriage return or \n) that is not the end of a
    paragraph.  (Five out of the six carriage returns in this
    paragraph do not mark its end.)

Thank you.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-09 20:41                       ` blank-mode.el Robert J. Chassell
@ 2007-11-11  2:13                         ` Vinicius Jose Latorre
  2007-11-11 12:19                           ` blank-mode.el Robert J. Chassell
  2007-11-11 17:01                           ` blank-mode.el Robert J. Chassell
  0 siblings, 2 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-11  2:13 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

Robert J. Chassell wrote:
>  1. Rather than exceed 80 characters, the first line of blank-mode.el
>     should be:
>
> ;;; blank-mode.el --- Minor mode to visualise blanks (SPACE, HARD SPACE, TAB)
>
>     with a comma instead of an `and' before the word `TAB' and no period.
>     That is 77 characters long which is almost, but not quite, too much
>     for a heading.
>   

Ok, I've just modified the very first line.

>  2. Regarding the body of the library, as a general rule, comments
>     should be filled according to the Emacs default -- I notice the
>     lengths are longer although they are less than 80 characters.
>   

Ok.

>  3. Also, while a carriage return occurs at the end of a line, that
>     place does not necessarily mark the end of a paragraph.  By
>     default, please do not use a between-paragraph symbol for the end
>     of a line (a carriage return or \n) that is not the end of a
>     paragraph.  (Five out of the six carriage returns in this
>     paragraph do not mark its end.)
>   

Well, it's not the blank-mode intention to visualize paragraphs,
but space, hard space, tab and also end of lines (\n).

The visual mark used to display end of line can be changed any time
by modifying blank-display-mappings variable.

It happens that the visual mark for end of line is the same
used in other editors to visualize end of paragraphs.
This visual mark was suggested by some blank-mode users.
What visual mark do you suggest?

BTW you could change the visual mark of any character
using blank-display-mappings variable.

> Thank you.
>   

You're welcome.

--
   Vinicius

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11  2:13                         ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-11 12:19                           ` Robert J. Chassell
  2007-11-11 14:37                             ` blank-mode.el Drew Adams
  2007-11-11 14:57                             ` blank-mode.el Jason Rumney
  2007-11-11 17:01                           ` blank-mode.el Robert J. Chassell
  1 sibling, 2 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-11 12:19 UTC (permalink / raw)
  To: emacs-devel

    It happens that the visual mark for end of line is the same
    used in other editors to visualize end of paragraphs.

The symbol for marking where to put in a paragraph break has been
common for years -- it is a standard proofreader's mark.  It does not
indicate the end of a line but where to start a new paragraph.  It has
a very different meaning.  You might want to draw a symbol to indicate
the end of a line.

I don't know of any standard symbol for the end of a line besides the
curved arrow conventionally used in a fringe in an Emacs for a newline
on a windowing system ... and that symbol in a fringe means that a
newline does not exist ...  My hunch is that before the coming of
computers, proofreaders presumed that typesetters would always avoid
running lines to the right because of boundaries in their frame or
boundaries of the paper on which proofs were printed.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: blank-mode.el
  2007-11-11 12:19                           ` blank-mode.el Robert J. Chassell
@ 2007-11-11 14:37                             ` Drew Adams
  2007-11-11 14:57                             ` blank-mode.el Jason Rumney
  1 sibling, 0 replies; 56+ messages in thread
From: Drew Adams @ 2007-11-11 14:37 UTC (permalink / raw)
  To: bob, emacs-devel

> The symbol for marking where to put in a paragraph break has been
> common for years -- it is a standard proofreader's mark.

pilcrow - http://en.wikipedia.org/wiki/Pilcrow (FYI)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 12:19                           ` blank-mode.el Robert J. Chassell
  2007-11-11 14:37                             ` blank-mode.el Drew Adams
@ 2007-11-11 14:57                             ` Jason Rumney
  2007-11-11 17:52                               ` blank-mode.el Robert J. Chassell
  1 sibling, 1 reply; 56+ messages in thread
From: Jason Rumney @ 2007-11-11 14:57 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

Robert J. Chassell wrote:
> I don't know of any standard symbol for the end of a line besides the
> curved arrow conventionally used in a fringe in an Emacs for a newline
> on a windowing system 
What about U+21B5 (downwards arrow with corner leftwards)?

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11  2:13                         ` blank-mode.el Vinicius Jose Latorre
  2007-11-11 12:19                           ` blank-mode.el Robert J. Chassell
@ 2007-11-11 17:01                           ` Robert J. Chassell
  1 sibling, 0 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-11 17:01 UTC (permalink / raw)
  To: emacs-devel

       It happens that the visual mark for end of line is the same
       used in other editors to visualize end of paragraphs.
       This visual mark was suggested by some blank-mode users.
       What visual mark do you suggest?

With input method: latin-1-prefix (mode line indicator:1>) you could
try: / = (but with no space, i.e., /=) which should look like ¬.

That is to say, replace

    (?\n    [?\xB6 ?\n] [?$ ?\n])	; end-of-line

in  `blank-display-mappings' in blank-mode.el with

    (?\n    [?\xAC ?\n] [?$ ?\n])	; end-of-line

`(blank-mode-on)' and `(blank-mode-off)' succeed in this *mail*
buffer, which is an undecided-unix buffer in which I evoke
`toggle-input-method' to show the not-sign, and in a utf-8 buffer.  I
have not checked others.

This mathematical not-sign is the best I could find among common
characters.  It is not very good but is better than putting
start-new-paragraph signs in the middle of a paragraph.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 14:57                             ` blank-mode.el Jason Rumney
@ 2007-11-11 17:52                               ` Robert J. Chassell
  2007-11-11 21:23                                 ` blank-mode.el Vinicius Jose Latorre
  2007-11-11 22:01                                 ` blank-mode.el Jason Rumney
  0 siblings, 2 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-11 17:52 UTC (permalink / raw)
  To: Jason Rumney; +Cc: emacs-devel

On 11 Nov 2007, Jason Rumney <jasonr@gnu.org> asks

    What about U+21B5 (downwards arrow with corner leftwards)?

On my system, changing `blank-display-mappings' in blank-mode.el so
that

    (?\n    [?\x21B5 ?\n] [?$ ?\n])	; end-of-line
 
produces a dollar-sign.

The dollar-sign is bigger than the not-sign, but may be a better 
end of line marker.  It is definitely better than a pilcrow.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 17:52                               ` blank-mode.el Robert J. Chassell
@ 2007-11-11 21:23                                 ` Vinicius Jose Latorre
  2007-11-11 21:48                                   ` blank-mode.el Juri Linkov
                                                     ` (2 more replies)
  2007-11-11 22:01                                 ` blank-mode.el Jason Rumney
  1 sibling, 3 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-11 21:23 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel, Jason Rumney

Robert J. Chassell wrote:
> On 11 Nov 2007, Jason Rumney <jasonr@gnu.org> asks
>
>     What about U+21B5 (downwards arrow with corner leftwards)?
>   

The char ?\x21B5 is not valid in Emacs, see:

    (char-valid-p ?\x21B5)
    ==> nil


> On my system, changing `blank-display-mappings' in blank-mode.el so
> that
>
>     (?\n    [?\x21B5 ?\n] [?$ ?\n])	; end-of-line
>  
> produces a dollar-sign.
>
> The dollar-sign is bigger than the not-sign, but may be a better 
> end of line marker.  It is definitely better than a pilcrow.
>   

Yes, it uses dollar-sign (second option, that is, the second vector)
because ?\x21B5 is not a valid char for Emacs.

I've just experimented these characters:

    ?\x8AC => ¬    (negation)
    ?\x8AF => ¯    ("overscore")
    ?\x8B0 => °    (grade)
    ?\x8FE => þ   

All of them are cool.  Well, ?\x8B6 (¶ - pilcrow) is also cool. :-)

The character ?\x8AF seems to be lighter than the other characters.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 21:23                                 ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-11 21:48                                   ` Juri Linkov
  2007-11-11 21:59                                     ` blank-mode.el Juanma Barranquero
  2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
  2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
  2 siblings, 1 reply; 56+ messages in thread
From: Juri Linkov @ 2007-11-11 21:48 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: bob, jasonr, emacs-devel

>>     What about U+21B5 (downwards arrow with corner leftwards)?
>
> The char ?\x21B5 is not valid in Emacs, see:
>
>    (char-valid-p ?\x21B5)
>    ==> nil

This hex code is not the same as Unicode, and its hex code is valid:

  (char-valid-p ?\x53bb5)
  ==> t

  ?\x53bb5
  ==> 342965 (#o1235665, #x53bb5, ?↵)

Also there is a special symbol for newline U+2424, but it is not as
nice-looking as U+21B5.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 21:48                                   ` blank-mode.el Juri Linkov
@ 2007-11-11 21:59                                     ` Juanma Barranquero
  2007-11-11 22:36                                       ` blank-mode.el Juri Linkov
  2007-11-12  0:05                                       ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 2 replies; 56+ messages in thread
From: Juanma Barranquero @ 2007-11-11 21:59 UTC (permalink / raw)
  To: Juri Linkov; +Cc: bob, emacs-devel, jasonr

On 11/11/07, Juri Linkov <juri@jurta.org> wrote:

> This hex code is not the same as Unicode, and its hex code is valid:
>
>   (char-valid-p ?\x53bb5)
>   ==> t

Isn't easier just to do (char-valid-p ?\u21b5) ?

             Juanma

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 17:52                               ` blank-mode.el Robert J. Chassell
  2007-11-11 21:23                                 ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-11 22:01                                 ` Jason Rumney
  2007-11-11 22:37                                   ` blank-mode.el Juri Linkov
  1 sibling, 1 reply; 56+ messages in thread
From: Jason Rumney @ 2007-11-11 22:01 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

Robert J. Chassell wrote:
> On 11 Nov 2007, Jason Rumney <jasonr@gnu.org> asks
>
>     What about U+21B5 (downwards arrow with corner leftwards)?
>
> On my system, changing `blank-display-mappings' in blank-mode.el so
> that
>
>     (?\n    [?\x21B5 ?\n] [?$ ?\n])	; end-of-line
>   

In Emacs 22 and trunk, ?\x21B5 is an emacs-mule codepoint, not a unicode
codepoint.

I think there is an easy way to get an emacs character from a unicode
codepoint, but I can't find it now (apropos ucs, unicode did not bring
up what I wanted). But the following gives the correct character:

(make-char 'mule-unicode-0100-24ff #xF7 #xb5)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 21:23                                 ` blank-mode.el Vinicius Jose Latorre
  2007-11-11 21:48                                   ` blank-mode.el Juri Linkov
@ 2007-11-11 22:04                                   ` Robert J. Chassell
  2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
  2 siblings, 0 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-11 22:04 UTC (permalink / raw)
  To: emacs-devel

   I've just experimented these characters:

       ?\x8AC => ¬    (negation)
       ?\x8AF => ¯    ("overscore")
       ?\x8B0 => °    (grade)
       ?\x8FE => þ   

   ...

   The character ?\x8AF seems to be lighter than the other characters.

I agree, it is lighter.  Unfortunately, the dollar sign is the
standard symbol for the end-of-line.   Evoke    (info "(emacs) Regexps")

There is not anything that I know of that is conventional except the
dollar sign ...

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 21:23                                 ` blank-mode.el Vinicius Jose Latorre
  2007-11-11 21:48                                   ` blank-mode.el Juri Linkov
  2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
@ 2007-11-11 22:04                                   ` Robert J. Chassell
  2007-11-12  0:01                                     ` blank-mode.el Vinicius Jose Latorre
  2 siblings, 1 reply; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-11 22:04 UTC (permalink / raw)
  To: emacs-devel

    The char ?\x21B5 is not valid in Emacs, see:

        (char-valid-p ?\x21B5)
        ==> nil

That's true, but for my system,

    (?\n    [?\x21B5 ?\n] [?$ ?\n])

provides a dollar sign in blank-mode.el as does

   (?\n    [?\x24 ?\n] [?$ ?\n])

However

    (?\n    [?\x21 ?\n] [?$ ?\n])

provides an exclamation point and

    (?\n    [?\xB5 ?\n] [?$ ?\n])

provides a  mu, i.e., a micro-micro (the symbol for a millionth).

--
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 21:59                                     ` blank-mode.el Juanma Barranquero
@ 2007-11-11 22:36                                       ` Juri Linkov
  2007-11-11 23:25                                         ` blank-mode.el Juanma Barranquero
  2007-11-12  0:05                                       ` blank-mode.el Vinicius Jose Latorre
  1 sibling, 1 reply; 56+ messages in thread
From: Juri Linkov @ 2007-11-11 22:36 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: bob, emacs-devel, jasonr

> On 11/11/07, Juri Linkov <juri@jurta.org> wrote:
>
>> This hex code is not the same as Unicode, and its hex code is valid:
>>
>>   (char-valid-p ?\x53bb5)
>>   ==> t
>
> Isn't easier just to do (char-valid-p ?\u21b5) ?

I forgot that this notation is available not only in the Unicode branch.
And this notation is not printed anywhere, unlike emacs-mule hex/dec/oct
values seen in `C-x C-e' and `C-u C-x =',  Shouldn't ?\uUUUU be printed
as well, or this will be unnecessary in the Unicode branch?

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 22:01                                 ` blank-mode.el Jason Rumney
@ 2007-11-11 22:37                                   ` Juri Linkov
  2007-11-11 22:46                                     ` blank-mode.el Jason Rumney
  0 siblings, 1 reply; 56+ messages in thread
From: Juri Linkov @ 2007-11-11 22:37 UTC (permalink / raw)
  To: Jason Rumney; +Cc: bob, emacs-devel

> In Emacs 22 and trunk, ?\x21B5 is an emacs-mule codepoint, not a unicode
> codepoint.
>
> I think there is an easy way to get an emacs character from a unicode
> codepoint, but I can't find it now (apropos ucs, unicode did not bring
> up what I wanted). But the following gives the correct character:
>
> (make-char 'mule-unicode-0100-24ff #xF7 #xb5)

I use programmatically (decode-char 'ucs ?\x21B5) and interactively
`M-x ucs-insert', even though it is inconvenient.  After the Unicode merge
it would be good to add reading in the Unicode notation to `C-q'.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 22:37                                   ` blank-mode.el Juri Linkov
@ 2007-11-11 22:46                                     ` Jason Rumney
  0 siblings, 0 replies; 56+ messages in thread
From: Jason Rumney @ 2007-11-11 22:46 UTC (permalink / raw)
  To: Juri Linkov; +Cc: bob, emacs-devel

Juri Linkov wrote:
> I use programmatically (decode-char 'ucs ?\x21B5)

Thanks, that was the one I was trying to recall. But as Juanma pointed
out, you can simply use ?\u21B5.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 22:36                                       ` blank-mode.el Juri Linkov
@ 2007-11-11 23:25                                         ` Juanma Barranquero
  0 siblings, 0 replies; 56+ messages in thread
From: Juanma Barranquero @ 2007-11-11 23:25 UTC (permalink / raw)
  To: Juri Linkov; +Cc: bob, emacs-devel, jasonr

On 11/11/07, Juri Linkov <juri@jurta.org> wrote:

> Shouldn't ?\uUUUU be printed as well

Well, describe-char shows U+uuuu; \uUUUU would be a bit redundant.

             Juanma

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-12  0:05                                       ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-11 23:28                                         ` Juanma Barranquero
  2007-11-12  0:43                                           ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Juanma Barranquero @ 2007-11-11 23:28 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: Juri Linkov, bob, emacs-devel, jasonr

On 11/12/07, Vinicius Jose Latorre <viniciusjl@ig.com.br> wrote:

> But using ?\u21b5 in blank-mode in my system gives an empty rectangle box.
>
> Doing:
>
>     M-: (format "%c" ?\u21b5) RET
>
> Is ok, the character appears and it's cool.

I'm not sure what does it mean "using ?\u21b5 in blank mode". In my
system, (format "%c" ?\u21b5) and M-x ucs-insert 21B5 [RET] give the
same result, for example.

             Juanma

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
@ 2007-11-12  0:01                                     ` Vinicius Jose Latorre
  0 siblings, 0 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-12  0:01 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

Robert J. Chassell wrote:
>     The char ?\x21B5 is not valid in Emacs, see:
>
>         (char-valid-p ?\x21B5)
>         ==> nil
>
> That's true, but for my system,
>
>     (?\n    [?\x21B5 ?\n] [?$ ?\n])
>
> provides a dollar sign in blank-mode.el as does
>   

This is due ?\x21B5 is not a valid char,
so blank-mode uses the other vector:

    [?$ ?\n]

Which specifies ?$ as a visual mark.

Try this command in your system:

    M-: (format "%c" ?\x21B5) RET

>    (?\n    [?\x24 ?\n] [?$ ?\n])
>   

Because ?\x24 == ?$ (valid char).

That is, both vectors have the same values.

> However
>
>     (?\n    [?\x21 ?\n] [?$ ?\n])
>
> provides an exclamation point and
>   

Because ?\x21 == ?! (valid char).

>     (?\n    [?\xB5 ?\n] [?$ ?\n])
>
> provides a  mu, i.e., a micro-micro (the symbol for a millionth).
>   

Because ?\xB5 == µ (valid char).

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 21:59                                     ` blank-mode.el Juanma Barranquero
  2007-11-11 22:36                                       ` blank-mode.el Juri Linkov
@ 2007-11-12  0:05                                       ` Vinicius Jose Latorre
  2007-11-11 23:28                                         ` blank-mode.el Juanma Barranquero
  1 sibling, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-12  0:05 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: Juri Linkov, bob, emacs-devel, jasonr

Juanma Barranquero wrote:
> On 11/11/07, Juri Linkov <juri@jurta.org> wrote:
>
>   
>> This hex code is not the same as Unicode, and its hex code is valid:
>>
>>   (char-valid-p ?\x53bb5)
>>   ==> t
>>     
>
> Isn't easier just to do (char-valid-p ?\u21b5) ?
>   

Yes, I also forgot this notation.

But using ?\u21b5 in blank-mode in my system gives an empty rectangle box.

Doing:

    M-: (format "%c" ?\u21b5) RET

Is ok, the character appears and it's cool.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-11 23:28                                         ` blank-mode.el Juanma Barranquero
@ 2007-11-12  0:43                                           ` Vinicius Jose Latorre
  2007-11-12 18:26                                             ` blank-mode.el Robert J. Chassell
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-12  0:43 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: Juri Linkov, bob, emacs-devel, jasonr

Juanma Barranquero wrote:
> On 11/12/07, Vinicius Jose Latorre <viniciusjl@ig.com.br> wrote:
>   
>> But using ?\u21b5 in blank-mode in my system gives an empty rectangle box.
>>
>> Doing:
>>
>>     M-: (format "%c" ?\u21b5) RET
>>
>> Is ok, the character appears and it's cool.
>>     
>
> I'm not sure what does it mean "using ?\u21b5 in blank mode". In my
> system, (format "%c" ?\u21b5) and M-x ucs-insert 21B5 [RET] give the
> same result, for example.
>   

Well, in my system both commands are ok too.

By "using ?\u21b5 in blank mode" I meant
putting ?\u21b5 in blank-display-mappings like:

    (?\n    [?\u21b5 ?\n] [?$ ?\n])

When blank-mode is on using the setting above,
instead of appear ↵ at the end of line (\n)
it appears an empty rectangle box at the end of line.

Usually the empty rectangle box appears
when Emacs recognizes the character
but can't represent a character in the display screen.

I have no glue why this is happening.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-12  0:43                                           ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-12 18:26                                             ` Robert J. Chassell
  2007-11-12 19:53                                               ` blank-mode.el Andreas Schwab
  2007-11-12 21:51                                               ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 2 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-12 18:26 UTC (permalink / raw)
  To: emacs-devel

    By "using ?\u21b5 in blank mode" I meant
    putting ?\u21b5 in blank-display-mappings like:

        (?\n    [?\u21b5 ?\n] [?$ ?\n])

    When blank-mode is on using the setting above,
    instead of appear ↵ at the end of line (\n)
    it appears an empty rectangle box at the end of line.

That happened to me, too, but when I evaluated

    (setq default-input-method 'ucs)

in an Emacs with my usual font, i.e., emacs -Q -D \ 
-fn "-Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO8859-1", I got
the downwards arrow with corner leftwards.  (My usual font is larger
than normal because I have a high resolution screen and my eyes are
not as good as they once were.)  But when I evaluated that expression
in an instance with the system defined fonts, i.e., emacs -Q -D only,
I saw hollow boxes at the ends of lines.

Both had a charset of     ascii (ASCII (ISO646 IRV))

The one had a font of

     -Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO8859-1

the other

     -Adobe-Courier-Medium-R-Normal--17-120-100-100-M-100-ISO8859-1
     but on my screen that font looks like it was 12 points!

Today's GNU Emacs CVS snapshot, Mon, 2007 Nov 12  10:48 UTC
GNU Emacs 23.0.50.1 (i686-pc-linux-gnu, GTK+ Version 2.12.1)

--
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-12 18:26                                             ` blank-mode.el Robert J. Chassell
@ 2007-11-12 19:53                                               ` Andreas Schwab
  2007-11-12 21:51                                               ` blank-mode.el Vinicius Jose Latorre
  1 sibling, 0 replies; 56+ messages in thread
From: Andreas Schwab @ 2007-11-12 19:53 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

"Robert J. Chassell" <bob@rattlesnake.com> writes:

>      -Adobe-Courier-Medium-R-Normal--17-120-100-100-M-100-ISO8859-1
>      but on my screen that font looks like it was 12 points!

Probably because it _is_ a 12 point font. :-)

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-12 18:26                                             ` blank-mode.el Robert J. Chassell
  2007-11-12 19:53                                               ` blank-mode.el Andreas Schwab
@ 2007-11-12 21:51                                               ` Vinicius Jose Latorre
  2007-11-13 10:45                                                 ` blank-mode.el Robert J. Chassell
  1 sibling, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-12 21:51 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

Robert J. Chassell wrote:
>     By "using ?\u21b5 in blank mode" I meant
>     putting ?\u21b5 in blank-display-mappings like:
>
>         (?\n    [?\u21b5 ?\n] [?$ ?\n])
>
>     When blank-mode is on using the setting above,
>     instead of appear ↵ at the end of line (\n)
>     it appears an empty rectangle box at the end of line.
>
> That happened to me, too, but when I evaluated
>
>     (setq default-input-method 'ucs)
>   

Humm, the command above didn't work in my system,
that is, it continues to display hollow box at end of line.

Even doing: emacs -Q

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-12 21:51                                               ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-13 10:45                                                 ` Robert J. Chassell
  2007-11-13 12:13                                                   ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-13 10:45 UTC (permalink / raw)
  To: emacs-devel

   >     (setq default-input-method 'ucs)

   Humm, the command above didn't work in my system,
   that is, it continues to display hollow box at end of line.

That is a problem.  It means that different machines have different
possibilities.  I fear that only ASCII is common to them all.  In that
case, the end of line should be a dollar sign (octal 44, decimal 36,
hexadecimal 24).  I don't like it.  A dollar sign is heavy, ?\u21b5 is
good -- but it is not within the ASCII range and of those glyphs that
are, the dollar sign is the best for this purpose.

Perhaps you could provide an option for ?\u21b5.  Certainly, the
documentation should mention it.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-13 10:45                                                 ` blank-mode.el Robert J. Chassell
@ 2007-11-13 12:13                                                   ` Vinicius Jose Latorre
  2007-11-13 16:41                                                     ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-13 12:13 UTC (permalink / raw)
  To: bob; +Cc: Miles Bader, emacs-devel

Robert J. Chassell wrote:
>    >     (setq default-input-method 'ucs)
>
>    Humm, the command above didn't work in my system,
>    that is, it continues to display hollow box at end of line.
>
> That is a problem.  It means that different machines have different
> possibilities.  I fear that only ASCII is common to them all.  In that
> case, the end of line should be a dollar sign (octal 44, decimal 36,
> hexadecimal 24).  I don't like it.  A dollar sign is heavy, ?\u21b5 is
> good -- but it is not within the ASCII range and of those glyphs that
> are, the dollar sign is the best for this purpose.
>
> Perhaps you could provide an option for ?\u21b5.  Certainly, the
> documentation should mention it.
>   

I found the problem.

The problem only happens for characters code
above #x0FFFF (?\u21B5 == #x53BB5).

blank-mode uses the same mechanism of visws.el
(from Miles Bader <miles@gnu.org>) to map
character code representation using
buffer-display-table variable.

This mechanism also embeds the face id
into the character code, it seems that this is the only
way to have face property associated with these
characters without interference of font-lock.

Humm, ok, one way to solve this it is not embed face id
for characters code above #x0FFFF, but these characters
will not have any face property, that is,
if font-lock is enabled, it'll use the face that font-lock
designates to that region of text.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-13 12:13                                                   ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-13 16:41                                                     ` Vinicius Jose Latorre
  2007-11-13 23:54                                                       ` blank-mode.el Juri Linkov
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-13 16:41 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 442 bytes --]

Vinicius Jose Latorre wrote:
> Humm, ok, one way to solve this it is not embed face id
> for characters code above #x0FFFF, but these characters
> will not have any face property, that is,
> if font-lock is enabled, it'll use the face that font-lock
> designates to that region of text.

Here is a blank-mode version which it does not embed
face id for characters code above #x0FFFF.

Also the default end of line display char is ?\u21B5.




[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 41123 bytes --]

;;; blank-mode.el --- minor mode to visualise blanks (SPACE, HARD SPACE, TAB)

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/13 13:26:11 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE
;; and TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display
;; table.
;;
;; * Faces are used to highlight the background with a color.
;;   blank-mode 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 `blank-style' and `blank-chars' variables are used to select
;; which way should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the
;; font-lock state, that is, if font-lock is on or off.  And
;; blank-mode restores the font-lock state when it is turned off.  So,
;; if blank-mode is turned on and font-lock is off, blank-mode also
;; turns on the font-lock to highlight blanks, but the font-lock will
;; be turned off when blank-mode is turned off.  Thus, turn on
;; font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode 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).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That
;;   is, if you turn on global blank-mode and then create a new
;;   buffer, the new buffer will also have blank-mode on.  The
;;   `blank-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 blank-mode has priority over global blank-mode.  That is:
;;
;; * when global and local blank-mode are on:
;;
;;    + if local blank-mode is turned off, blank-mode is turned off
;;      for the current buffer only.
;;
;;    + if global blank-mode is turned off, blank-mode continues on
;;      only in the buffers in which local blank-mode is on.
;;
;; * when global blank-mode is on and local blank-mode are off:
;;
;;    + if local blank-mode is turned on, only the modeline is
;;      modified.
;;
;; * when global blank-mode is off and local blank-mode are on:
;;
;;    + if global blank-mode is turned on, blank-mode is turned on in
;;      all buffers except that which has local blank-mode on.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle          "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle   "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on',
;; `global-blank-mode-off', `blank-mode-customize', `blank-toggle' and
;; `global-blank-toggle' to some key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please,
;; see the options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is
;;				visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char
;;				mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing
;;				blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space
;;					before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab
;;					regexp.
;;
;; `blank-line-length'		Specify length beyond which the line
;;				is highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for
;;				displaying characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new
;;    Emacs session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs
;;    session.
;;
;; c) or use customization, for example:
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' name for global commands.
;;
;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix.
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs"
				space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "SteelBlue4"  :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face		; 'nobreak-space
  '((((class color) (background dark))
     :background "CadetBlue4"    :foreground "aquamarine3")
    (((class color) (background light))
     :background "LemonChiffon3" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "SkyBlue4" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"    :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.

See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "CadetBlue5" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"      :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.

See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face		; 'trailing-whitespace
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.

See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.

See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		\
visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		\
visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	\
visualise leading and/or trailing hard spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		\
visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters
besides \" \" that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	\
visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters
besides \"\\t\" that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	\
visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'tabs as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'lines as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '((?\xA0  [?\xA4]       [?_])		; hard space - currency
    (?\x8A0 [?\x8A4]      [?_])		; hard space - currency
    (?\x920 [?\x924]      [?_])		; hard space - currency
    (?\xE20 [?\xE24]      [?_])		; hard space - currency
    (?\xF20 [?\xF24]      [?_])		; hard space - currency
    (?\     [?\xB7]       [?.])		; space - centered dot
    (?\n    [?\u21B5 ?\n] [?$ ?\n])	; end-of-line - downwards arrow
    ;; (?\n    [?\xB6 ?\n]   [?$ ?\n])	; end-of-line - pilcrow
    ;; (?\n    [?\x8AF ?\n]  [?$ ?\n])	; end-of-line - overscore
    ;; (?\n    [?\x8AC ?\n]  [?$ ?\n])	; end-of-line - negation
    ;; (?\n    [?\x8B0 ?\n]  [?$ ?\n])	; end-of-line - 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.
    (?\t    [?\xBB ?\t]   [?\\ ?\t])	; tab - left quote mark
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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
`blank-map-face' variable.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t
					:tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically
turned on.
If a list, it should be a list of `major-mode' symbol names for
which `blank-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 `blank-mode' is turned on for buffers in C and C++
modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (when blank-style
      (blank-turn-on)))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank 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 blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Toggle


;;;###autoload
(defun blank-toggle (arg)
  "Toggle local `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars
	 (blank-toggle-list t arg blank-active-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list t arg blank-active-style blank-style
			    'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle (arg)
  "Toggle global `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars
	 (blank-toggle-list nil arg blank-toggle-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list nil arg blank-toggle-style blank-style
			    'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('*' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "*" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(goto-char (point-min))
	(set-buffer-modified-p nil)
	(let* ((lines (count-lines (point-min) (point-max)))
	       (size (- (window-height)
			(max window-min-height
			     (1+ lines)))))
	  (if (<= size 0)
	      (error (concat "Frame height is too small; "
			     "can't split window to display "
			     "blank toggle options"))
	    (set-window-buffer (split-window nil size) buffer)))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-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 reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let ((prompt
	 (format "Blank Toggle %s (type ? for further options)-"
		 (if local-p "Local" "Global")))
	(chars (if local-p blank-active-chars blank-toggle-chars))
	(style (if local-p blank-active-style blank-toggle-style))
	ch sym)
    ;; if blank-mode is off, use default value
    (unless (if local-p blank-mode global-blank-mode)
      (unless chars
	(setq chars blank-chars))
      (unless style
	(setq style blank-style)))
    ;; read a valid option and get the corresponding symbol
    (save-window-excursion
      (condition-case data
	  (progn
	    (while (progn
		     (setq ch (read-char prompt))
		     (not
		      (setq sym
			    (cdr (assq ch
				       blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to
restore the options in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options
in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's
options are valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords
	    (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length)
		    ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (and blank-display-mappings
       (let ((face-bits (ash (face-id blank-map-face) 19))
	     (map-list blank-display-mappings)
	     entry vecs len vec i)
	 ;; Remember whether a buffer has a local display table.
	 (unless blank-display-table-was-local
	   (setq blank-display-table-was-local t
		 blank-display-table
		 (copy-sequence buffer-display-table)))
	 (or buffer-display-table
	     (setq buffer-display-table (make-display-table)))
	 (while map-list
	   (setq entry    (car map-list)
		 vecs     (cdr entry)
		 map-list (cdr map-list))
	   ;; Get a displayable mapping.
	   (while (and vecs
		       (not
			(blank-legal-display-vector-p (car vecs))))
	     (setq vecs (cdr vecs)))
	   ;; Display a valid mapping.
	   (when vecs
	     (setq vec (copy-sequence (car vecs)))
	     ;; Only insert face bits on NEWLINE char mapping to avoid
	     ;; obstruction of other faces like TABs and (HARD) SPACEs
	     ;; faces, font-lock faces, etc.
	     (when (eq (car entry) ?\n)
	       (setq len (length (car vecs))
		     i -1)
	       (while (< (setq i (1+ i)) len)
		 (or (eq (aref vec i) ?\n)
		     (> (aref vec i) #x0FFFF)
		     (aset vec i (logior (aref vec i) face-bits)))))
	     (aset buffer-display-table (car entry) vec))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-13 16:41                                                     ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-13 23:54                                                       ` Juri Linkov
  2007-11-14  0:19                                                         ` blank-mode.el Jason Rumney
                                                                           ` (2 more replies)
  0 siblings, 3 replies; 56+ messages in thread
From: Juri Linkov @ 2007-11-13 23:54 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: emacs-devel

> Here is a blank-mode version which it does not embed
> face id for characters code above #x0FFFF.
>
> Also the default end of line display char is ?\u21B5.

I think it is bad not to use face id for characters code above #x0FFFF,
because when they are displayed with the same faces as surrounding text,
they look as part of the buffer's text, and so this package defeats its
own purpose to visualize blanks clearly with a special background color.

And still this change doesn't help to avoid rectangle boxes that are
displayed for ?\u21B5 with small fonts.  There is a function
`char-displayable-p' that could help, but it returns non-nil even
when ?\u21B5 is displayed as an empty rectangle box, e.g.:

(char-displayable-p ?\u21B5)

returns when ?\u21B5 is displayed as an empty rectangle box:
"-Misc-Fixed-Medium-R-SemiCondensed--12-110-75-75-C-60-ISO10646-1"

returns when ?\u21B5 is displayed normally as an arrow:
"-Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1"

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-13 23:54                                                       ` blank-mode.el Juri Linkov
@ 2007-11-14  0:19                                                         ` Jason Rumney
  2007-11-14 10:29                                                         ` blank-mode.el Andreas Schwab
  2007-11-16  4:10                                                         ` blank-mode.el Vinicius Jose Latorre
  2 siblings, 0 replies; 56+ messages in thread
From: Jason Rumney @ 2007-11-14  0:19 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov wrote:
> (char-displayable-p ?\u21B5)
>
> returns when ?\u21B5 is displayed as an empty rectangle box:
> "-Misc-Fixed-Medium-R-SemiCondensed--12-110-75-75-C-60-ISO10646-1"
>
> returns when ?\u21B5 is displayed normally as an arrow:
> "-Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1"
>   

In emacs-unicode-2, it might be possible to return character granularity
results with at least some font backends.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-13 23:54                                                       ` blank-mode.el Juri Linkov
  2007-11-14  0:19                                                         ` blank-mode.el Jason Rumney
@ 2007-11-14 10:29                                                         ` Andreas Schwab
  2007-11-16  4:10                                                         ` blank-mode.el Vinicius Jose Latorre
  2 siblings, 0 replies; 56+ messages in thread
From: Andreas Schwab @ 2007-11-14 10:29 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@jurta.org> writes:

> And still this change doesn't help to avoid rectangle boxes that are
> displayed for ?\u21B5 with small fonts.

It's not restricted to small fonts.  That character in particular does
not seem to be included in many fonts.

> There is a function `char-displayable-p' that could help, but it
> returns non-nil even when ?\u21B5 is displayed as an empty rectangle
> box, e.g.:

See the docstring: char-displayable-p only tests whether the charset is
displayable in general.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
@ 2007-11-14 13:44 Robert J. Chassell
  0 siblings, 0 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-14 13:44 UTC (permalink / raw)
  To: emacs-devel

Today's GNU Emacs CVS snapshot, Wed, 2007 Nov 14  10:55 UTC
GNU Emacs 23.0.50.3 (i686-pc-linux-gnu, GTK+ Version 2.12.1)
started with
  emacs -q -D --visit ~/emacs-21/blank-mode-07oct31.el \
     --visit ~bob/emacs-21/blank-mode.el


    > Here is a blank-mode version which it does not embed
    > face id for characters code above #x0FFFF.

    I think it is bad not to use face id for characters code above #x0FFFF,
    because when they are displayed with the same faces as surrounding text,
    they look as part of the buffer's text ...

Juri Linkov is right.

    ... and so this package defeats its own purpose to visualize
    blanks clearly ...

Unfortunately,  Version 7.0,  2007/10/31, 

    http://www.emacswiki.org/cgi-bin/emacs/download/blank-mode.el

looks better (with a dollar sign rather than a pilcrow, although I prefer
\u21B5).

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-13 23:54                                                       ` blank-mode.el Juri Linkov
  2007-11-14  0:19                                                         ` blank-mode.el Jason Rumney
  2007-11-14 10:29                                                         ` blank-mode.el Andreas Schwab
@ 2007-11-16  4:10                                                         ` Vinicius Jose Latorre
  2007-11-16 12:02                                                           ` blank-mode.el Robert J. Chassell
  2 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-16  4:10 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1986 bytes --]

Juri Linkov wrote:
>> Here is a blank-mode version which it does not embed
>> face id for characters code above #x0FFFF.
>>
>> Also the default end of line display char is ?\u21B5.
>>     
>
> I think it is bad not to use face id for characters code above #x0FFFF,
> because when they are displayed with the same faces as surrounding text,
> they look as part of the buffer's text, and so this package defeats its
> own purpose to visualize blanks clearly with a special background color.
>   

I also think it is a bad thing, but this is a limitation of Emacs trunk 
(see make-glyph-code in disp-table.el file).

Probably this will not be a problem when Emacs unicode will be merged 
into trunk.

And this is not against the package purpose, as blank-mode has two ways 
to visualize blanks: faces and display table.  By default, both ways are 
used (see blank-style variable), but the user can select only faces or 
only display table to visualize blanks.  In the case of chars with code 
above #x0FFFF (for Emacs trunk), it is used only display table.

> And still this change doesn't help to avoid rectangle boxes that are
> displayed for ?\u21B5 with small fonts.  There is a function
> `char-displayable-p' that could help, but it returns non-nil even
> when ?\u21B5 is displayed as an empty rectangle box, e.g.:
>
> (char-displayable-p ?\u21B5)
>
> returns when ?\u21B5 is displayed as an empty rectangle box:
> "-Misc-Fixed-Medium-R-SemiCondensed--12-110-75-75-C-60-ISO10646-1"
>
> returns when ?\u21B5 is displayed normally as an arrow:
> "-Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1"
>   

Ok, but char-displayable-p doesn't help too as it returns non-nil in 
situations where a hollow box is displayed.

As a temporary solution (until Emacs unicode merging), I set ?$ as a 
default value for end of line visualization.

Attached is blank-mode package with this default and also I changed the 
face background color when Emacs is using a dark background.


[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 41089 bytes --]

;;; blank-mode.el --- minor mode to visualise blanks (SPACE, HARD SPACE, TAB)

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/16 00:41:55 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE
;; and TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display
;; table.
;;
;; * Faces are used to highlight the background with a color.
;;   blank-mode 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 `blank-style' and `blank-chars' variables are used to select
;; which way should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the
;; font-lock state, that is, if font-lock is on or off.  And
;; blank-mode restores the font-lock state when it is turned off.  So,
;; if blank-mode is turned on and font-lock is off, blank-mode also
;; turns on the font-lock to highlight blanks, but the font-lock will
;; be turned off when blank-mode is turned off.  Thus, turn on
;; font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode 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).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That
;;   is, if you turn on global blank-mode and then create a new
;;   buffer, the new buffer will also have blank-mode on.  The
;;   `blank-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 blank-mode has priority over global blank-mode.  That is:
;;
;; * when global and local blank-mode are on:
;;
;;    + if local blank-mode is turned off, blank-mode is turned off
;;      for the current buffer only.
;;
;;    + if global blank-mode is turned off, blank-mode continues on
;;      only in the buffers in which local blank-mode is on.
;;
;; * when global blank-mode is on and local blank-mode are off:
;;
;;    + if local blank-mode is turned on, only the modeline is
;;      modified.
;;
;; * when global blank-mode is off and local blank-mode are on:
;;
;;    + if global blank-mode is turned on, blank-mode is turned on in
;;      all buffers except that which has local blank-mode on.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle          "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle   "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on',
;; `global-blank-mode-off', `blank-mode-customize', `blank-toggle' and
;; `global-blank-toggle' to some key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please,
;; see the options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is
;;				visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char
;;				mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing
;;				blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space
;;					before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab
;;					regexp.
;;
;; `blank-line-length'		Specify length beyond which the line
;;				is highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for
;;				displaying characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new
;;    Emacs session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs
;;    session.
;;
;; c) or use customization, for example:
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' name for global commands.
;;
;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix.
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs"
				space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "grey20"      :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face		; '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 visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "grey22" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"  :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.

See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "grey26" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"  :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.

See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face		; 'trailing-whitespace
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.

See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.

See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		\
visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		\
visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	\
visualise leading and/or trailing hard spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		\
visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters
besides \" \" that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	\
visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters
besides \"\\t\" that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	\
visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'tabs as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'lines as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '(
    (?\     [?\xB7]       [?.])		; space - centered dot
    (?\xA0  [?\xA4]       [?_])		; hard space - currency
    (?\x8A0 [?\x8A4]      [?_])		; hard space - currency
    (?\x920 [?\x924]      [?_])		; hard space - currency
    (?\xE20 [?\xE24]      [?_])		; hard space - currency
    (?\xF20 [?\xF24]      [?_])		; hard space - currency
    (?\n    [?$ ?\n])			; end-of-line - dollar sign
    ;; (?\n    [?\u21B5 ?\n] [?$ ?\n])	; end-of-line - downwards arrow
    ;; (?\n    [?\xB6 ?\n]   [?$ ?\n])	; end-of-line - pilcrow
    ;; (?\n    [?\x8AF ?\n]  [?$ ?\n])	; end-of-line - overscore
    ;; (?\n    [?\x8AC ?\n]  [?$ ?\n])	; end-of-line - negation
    ;; (?\n    [?\x8B0 ?\n]  [?$ ?\n])	; end-of-line - 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.
    (?\t    [?\xBB ?\t]   [?\\ ?\t])	; tab - left quote mark
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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
`blank-map-face' variable.  The characters in the vector to be
displayed will not have applied this face if the character code is
above #x0FFFF.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t
					:tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically
turned on.
If a list, it should be a list of `major-mode' symbol names for
which `blank-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 `blank-mode' is turned on for buffers in C and C++
modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (when blank-style
      (blank-turn-on)))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank 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 blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Toggle


;;;###autoload
(defun blank-toggle (arg)
  "Toggle local `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars
	 (blank-toggle-list t arg blank-active-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list t arg blank-active-style blank-style
			    'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle (arg)
  "Toggle global `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars
	 (blank-toggle-list nil arg blank-toggle-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list nil arg blank-toggle-style blank-style
			    'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('*' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "*" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(goto-char (point-min))
	(set-buffer-modified-p nil)
	(let* ((lines (count-lines (point-min) (point-max)))
	       (size (- (window-height)
			(max window-min-height
			     (1+ lines)))))
	  (if (<= size 0)
	      (error (concat "Frame height is too small; "
			     "can't split window to display "
			     "blank toggle options"))
	    (set-window-buffer (split-window nil size) buffer)))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-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 reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let ((prompt
	 (format "Blank Toggle %s (type ? for further options)-"
		 (if local-p "Local" "Global")))
	(chars (if local-p blank-active-chars blank-toggle-chars))
	(style (if local-p blank-active-style blank-toggle-style))
	ch sym)
    ;; if blank-mode is off, use default value
    (unless (if local-p blank-mode global-blank-mode)
      (unless chars
	(setq chars blank-chars))
      (unless style
	(setq style blank-style)))
    ;; read a valid option and get the corresponding symbol
    (save-window-excursion
      (condition-case data
	  (progn
	    (while (progn
		     (setq ch (read-char prompt))
		     (not
		      (setq sym
			    (cdr (assq ch
				       blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to
restore the options in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options
in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's
options are valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords
	    (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length)
		    ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (when blank-display-mappings
    (let (vecs vec)
      ;; Remember whether a buffer has a local display table.
      (unless blank-display-table-was-local
	(setq blank-display-table-was-local t
	      blank-display-table
	      (copy-sequence buffer-display-table)))
      (unless buffer-display-table
	(setq buffer-display-table (make-display-table)))
      (dolist (entry blank-display-mappings)
	(setq vecs (cdr entry))
	;; Get a displayable mapping.
	(while (and vecs
		    (not (blank-legal-display-vector-p (car vecs))))
	  (setq vecs (cdr vecs)))
	;; Display a valid mapping.
	(when vecs
	  (setq vec (copy-sequence (car vecs)))
	  ;; Only insert face bits on NEWLINE char mapping to avoid
	  ;; obstruction of other faces like TABs and (HARD) SPACEs
	  ;; faces, font-lock faces, etc.
	  (when (eq (car entry) ?\n)
	    (dotimes (i (length vec))
	      (or (eq (aref vec i) ?\n)
		  (> (aref vec i) #x1FFFF)
		  (aset vec i (make-glyph-code (aref vec i)
					       blank-map-face))))))
	(aset buffer-display-table (car entry) vec)))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-16  4:10                                                         ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-16 12:02                                                           ` Robert J. Chassell
  2007-11-17 21:05                                                             ` blank-mode.el Vinicius Jose Latorre
  2007-11-19 14:44                                                             ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 2 replies; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-16 12:02 UTC (permalink / raw)
  To: emacs-devel

Today's GNU Emacs CVS snapshot, Fri, 2007 Nov 16  10:51 UTC
GNU Emacs 23.0.50.5 (i686-pc-linux-gnu, GTK+ Version 2.12.1) 
started with

    emacs -q -D \
        -l ~bob/emacs-21/blank-mode.el \
        --visit ~bob/emacs-21/blank-mode.el \
        --visit ~bob/emacs-21/blank-mode-README

The new blank-mode.el
    ;; Time-stamp: <2007/11/16 00:41:55 vinicius>
but still
    ;; Version: 7.1
is much better.  

I do not like dollar signs compared to ?\u21B5 but I prefer the color
which come with the glyph being less than #x0FFFF.  That turns out to
be dramatically important -- I did not realize how much.  (I could not
live with pilcrows at the ends of lines even if they had the right
color, but I can live with dollar signs.)

In the default set up, four options to `blank-toggle'

    (blank-toggle 'color)
    (blank-toggle 'mark)
    (blank-toggle 'blank-chars)
    (blank-toggle 'blank-style)

do not seem to do anything except invoke except invoke (blank-mode 1)
but not (blank-mode 0) when you already have (blank-mode 1).

The documentation should explain this.  

Also, the name might better be `blank-options-toggle' which is longer
but less likely to be confused with the other toggle commands, such as
`blank-mode'.

A comment in the source for `defcustom blank-display-mappings' should
explain why and when dollar sign was chosen.  You might say  

    ;; 2007 Nov 15:  ?\u21B5 is better than a dollar sign at 
    ;; ?\x24 or?$, but numerically it comes above #x0FFFF.
    ;; Until Emacs unicode merging, such a downwards arrow is 
    ;; displayed with the same face as surrounding text.

As I said, the library is getting better.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-16 12:02                                                           ` blank-mode.el Robert J. Chassell
@ 2007-11-17 21:05                                                             ` Vinicius Jose Latorre
  2007-11-17 22:57                                                               ` blank-mode.el Juri Linkov
  2007-11-19 14:44                                                             ` blank-mode.el Vinicius Jose Latorre
  1 sibling, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-17 21:05 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1629 bytes --]

Robert J. Chassell wrote:
> Today's GNU Emacs CVS snapshot, Fri, 2007 Nov 16  10:51 UTC
> GNU Emacs 23.0.50.5 (i686-pc-linux-gnu, GTK+ Version 2.12.1) 
> started with
>
>     emacs -q -D \
>         -l ~bob/emacs-21/blank-mode.el \
>         --visit ~bob/emacs-21/blank-mode.el \
>         --visit ~bob/emacs-21/blank-mode-README
>
> The new blank-mode.el
>     ;; Time-stamp: <2007/11/16 00:41:55 vinicius>
> but still
>     ;; Version: 7.1
> is much better.  

Version 7.1 is being used for development.


> I do not like dollar signs compared to ?\u21B5 but I prefer the color
> which come with the glyph being less than #x0FFFF.  That turns out to
> be dramatically important -- I did not realize how much.  (I could not
> live with pilcrows at the ends of lines even if they had the right
> color, but I can live with dollar signs.)  

Well, I prefer pilcrow instead of dollar sign.  Dollar sign is a problem 
when editing Perl, shell script or Makefile, as in these environments $ 
has a meaning.  Pilcrow in these environments don't have any meaning.

BTW, pilcrow has been used by blank-mode for 7 years and it was 
suggested / chosen by blank-mode users.


> In the default set up, four options to `blank-toggle'
>
>     (blank-toggle 'color)
>     (blank-toggle 'mark)
>     (blank-toggle 'blank-chars)
>     (blank-toggle 'blank-style)
>
> do not seem to do anything except invoke except invoke (blank-mode 1)
> but not (blank-mode 0) when you already have (blank-mode 1).
>   

Problem fixed in the new blank-mode file attached (still v7.1).


> [......]
>   
> As I said, the library is getting better.
>   

Cool!


[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 41152 bytes --]

;;; blank-mode.el --- minor mode to visualise blanks (SPACE, HARD SPACE, TAB)

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/17 17:51:41 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE
;; and TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display
;; table.
;;
;; * Faces are used to highlight the background with a color.
;;   blank-mode 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 `blank-style' and `blank-chars' variables are used to select
;; which way should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the
;; font-lock state, that is, if font-lock is on or off.  And
;; blank-mode restores the font-lock state when it is turned off.  So,
;; if blank-mode is turned on and font-lock is off, blank-mode also
;; turns on the font-lock to highlight blanks, but the font-lock will
;; be turned off when blank-mode is turned off.  Thus, turn on
;; font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode 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).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That
;;   is, if you turn on global blank-mode and then create a new
;;   buffer, the new buffer will also have blank-mode on.  The
;;   `blank-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 blank-mode has priority over global blank-mode.  That is:
;;
;; * when global and local blank-mode are on:
;;
;;    + if local blank-mode is turned off, blank-mode is turned off
;;      for the current buffer only.
;;
;;    + if global blank-mode is turned off, blank-mode continues on
;;      only in the buffers in which local blank-mode is on.
;;
;; * when global blank-mode is on and local blank-mode are off:
;;
;;    + if local blank-mode is turned on, only the modeline is
;;      modified.
;;
;; * when global blank-mode is off and local blank-mode are on:
;;
;;    + if global blank-mode is turned on, blank-mode is turned on in
;;      all buffers except that which has local blank-mode on.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on         "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off        "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode            "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle          "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize  "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on  "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode     "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle   "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on',
;; `global-blank-mode-off', `blank-mode-customize', `blank-toggle' and
;; `global-blank-toggle' to some key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please,
;; see the options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is
;;				visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-map-face'		Face used to visualise NEWLINE char
;;				mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing
;;				blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space
;;					before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab
;;					regexp.
;;
;; `blank-line-length'		Specify length beyond which the line
;;				is highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for
;;				displaying characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new
;;    Emacs session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs
;;    session.
;;
;; c) or use customization, for example:
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' name for global commands.
;;
;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix.
;;
;; 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs"
				space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "grey20"      :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face		; '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 visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "grey22" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"  :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-map-face 'blank-map-face
  "*Symbol face used to visualise NEWLINE char mapping.

See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-map-face
  '((((class color) (background dark))
     :background "grey26" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"  :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.

See `blank-display-mappings'."
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face		; 'trailing-whitespace
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.

See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.

See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		\
visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		\
visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	\
visualise leading and/or trailing hard spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		\
visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters
besides \" \" that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	\
visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters
besides \"\\t\" that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	\
visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'tabs as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'lines as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  '(
    (?\     [?\xB7]       [?.])		; space - centered dot
    (?\xA0  [?\xA4]       [?_])		; hard space - currency
    (?\x8A0 [?\x8A4]      [?_])		; hard space - currency
    (?\x920 [?\x924]      [?_])		; hard space - currency
    (?\xE20 [?\xE24]      [?_])		; hard space - currency
    (?\xF20 [?\xF24]      [?_])		; hard space - currency
    (?\n    [?$ ?\n])			; end-of-line - dollar sign
    ;; (?\n    [?\u21B5 ?\n] [?$ ?\n])	; end-of-line - downwards arrow
    ;; (?\n    [?\xB6 ?\n]   [?$ ?\n])	; end-of-line - pilcrow
    ;; (?\n    [?\x8AF ?\n]  [?$ ?\n])	; end-of-line - overscore
    ;; (?\n    [?\x8AC ?\n]  [?$ ?\n])	; end-of-line - negation
    ;; (?\n    [?\x8B0 ?\n]  [?$ ?\n])	; end-of-line - 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.
    (?\t    [?\xBB ?\t]   [?\\ ?\t])	; tab - left quote mark
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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
`blank-map-face' variable.  The characters in the vector to be
displayed will not have applied this face if the character code is
above #x0FFFF.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t
					:tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically
turned on.
If a list, it should be a list of `major-mode' symbol names for
which `blank-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 `blank-mode' is turned on for buffers in C and C++
modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (blank-turn-on))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank 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 blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Toggle


;;;###autoload
(defun blank-toggle (arg)
  "Toggle local `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars
	 (blank-toggle-list t arg blank-active-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list t arg blank-active-style blank-style
			    'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle (arg)
  "Toggle global `blank-mode' options.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars
	 (blank-toggle-list nil arg blank-toggle-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list nil arg blank-toggle-style blank-style
			    'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('X' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "X" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(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)
	    (error "Frame height is too small; \
can't split window to display blank toggle options"))
	  (set-window-buffer (split-window nil size) buffer))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-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 reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let* ((is-off (not (if local-p blank-mode global-blank-mode)))
	 (chars  (cond (is-off  blank-chars) ; use default value
		       (local-p blank-active-chars)
		       (t       blank-toggle-chars)))
	 (style  (cond (is-off  blank-style) ; use default value
		       (local-p blank-active-style)
		       (t       blank-toggle-style)))
	 (prompt
	  (format "Blank 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 (progn
		     (setq ch (read-char prompt))
		     (not
		      (setq sym
			    (cdr (assq ch
				       blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to
restore the options in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options
in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's
options are valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (setq the-list (copy-sequence the-list)) ; do no change original list
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords
	    (copy-sequence font-lock-keywords)))
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length)
		    ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defun blank-legal-display-vector-p (vec)
  "Return true if every character in vector VEC can be displayed."
  (let ((i (length vec)))
    (when (> i 0)
      ;; This check should be improved!!!
      (while (and (>= (setq i (1- i)) 0)
		  (or (< (aref vec i) 256)
		      (char-valid-p (aref vec i)))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (when blank-display-mappings
    (let (vecs vec)
      ;; Remember whether a buffer has a local display table.
      (unless blank-display-table-was-local
	(setq blank-display-table-was-local t
	      blank-display-table
	      (copy-sequence buffer-display-table)))
      (unless buffer-display-table
	(setq buffer-display-table (make-display-table)))
      (dolist (entry blank-display-mappings)
	(setq vecs (cdr entry))
	;; Get a displayable mapping.
	(while (and vecs
		    (not (blank-legal-display-vector-p (car vecs))))
	  (setq vecs (cdr vecs)))
	;; Display a valid mapping.
	(when vecs
	  (setq vec (copy-sequence (car vecs)))
	  ;; Only insert face bits on NEWLINE char mapping to avoid
	  ;; obstruction of other faces like TABs and (HARD) SPACEs
	  ;; faces, font-lock faces, etc.
	  (when (and (eq (car entry) ?\n)
		     (memq 'color blank-active-style))
	    (dotimes (i (length vec))
	      (or (eq (aref vec i) ?\n)
		  (> (aref vec i) #x1FFFF)
		  (aset vec i (make-glyph-code (aref vec i)
					       blank-map-face))))))
	(aset buffer-display-table (car entry) vec)))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-17 21:05                                                             ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-17 22:57                                                               ` Juri Linkov
  2007-11-18 14:55                                                                 ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Juri Linkov @ 2007-11-17 22:57 UTC (permalink / raw)
  To: Vinicius Jose Latorre; +Cc: bob, emacs-devel

>> I do not like dollar signs compared to ?\u21B5 but I prefer the color
>> which come with the glyph being less than #x0FFFF.  That turns out to
>> be dramatically important -- I did not realize how much.  (I could not
>> live with pilcrows at the ends of lines even if they had the right
>> color, but I can live with dollar signs.)
>
> Well, I prefer pilcrow instead of dollar sign.  Dollar sign is a problem
> when editing Perl, shell script or Makefile, as in these environments
> $ has a meaning.  Pilcrow in these environments don't have any meaning.
>
> BTW, pilcrow has been used by blank-mode for 7 years and it was suggested
> / chosen by blank-mode users.

The pilcrow is used to denote paragraphs.  In word processors where
hard newlines separate paragraphs it would be acceptable to use the
pilcrow to denote hard newlines.  This is acceptable also for
longlines-mode in Emacs.  But otherwise in Emacs where hard and soft
newlines are not normally distinguished you could put pilcrows only
on positions denoted by `paragraph-start' and `paragraph-separate'.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-17 22:57                                                               ` blank-mode.el Juri Linkov
@ 2007-11-18 14:55                                                                 ` Vinicius Jose Latorre
  0 siblings, 0 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-18 14:55 UTC (permalink / raw)
  To: Juri Linkov; +Cc: bob, emacs-devel


> The pilcrow is used to denote paragraphs.  In word processors where
> hard newlines separate paragraphs it would be acceptable to use the
> pilcrow to denote hard newlines.  This is acceptable also for
> longlines-mode in Emacs.  But otherwise in Emacs where hard and soft
> newlines are not normally distinguished you could put pilcrows only
> on positions denoted by `paragraph-start' and `paragraph-separate'.
>   

Ok, but it seems that word processors edit documents, not a source code 
file.

In the case of documents, ok, it makes sense to think in terms of 
paragraphs.  It also makes sense to think in terms of paragraph when 
editing a text file in Emacs which is a text file document.

In the case of source code file, what is a paragraph?

Editing a source code file in Emacs and typing M-} (forward-paragraph), 
the point goes to the next empty line, no matter where this empty line 
is located (in the middle of a comment, command, function, etc.)

Editing a source code file in OpenOffice, each source code line is a 
paragraph.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-16 12:02                                                           ` blank-mode.el Robert J. Chassell
  2007-11-17 21:05                                                             ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-19 14:44                                                             ` Vinicius Jose Latorre
  2007-11-19 16:22                                                               ` blank-mode.el Robert J. Chassell
  1 sibling, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-19 14:44 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 815 bytes --]


> Also, the name might better be `blank-options-toggle' which is longer
> but less likely to be confused with the other toggle commands, such as
> `blank-mode'.
>   

Done, but the names now are blank-toggle-options and 
global-blank-toggle-options.

The docstring of these commands were improved (a little bit).

> A comment in the source for `defcustom blank-display-mappings' should
> explain why and when dollar sign was chosen.  You might say  
>
>     ;; 2007 Nov 15:  ?\u21B5 is better than a dollar sign at 
>     ;; ?\x24 or?$, but numerically it comes above #x0FFFF.
>     ;; Until Emacs unicode merging, such a downwards arrow is 
>     ;; displayed with the same face as surrounding text.
>   

Done, but a different text was added.

The new blank-mode version is attached in this email (still v7.1).


[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 42263 bytes --]

;;; blank-mode.el --- minor mode to visualise blanks (SPACE, HARD SPACE, TAB)

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/19 11:42:33 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE
;; and TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display
;; table.
;;
;; * Faces are used to highlight the background with a color.
;;   blank-mode 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 `blank-style' and `blank-chars' variables are used to select
;; which way should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the
;; font-lock state, that is, if font-lock is on or off.  And
;; blank-mode restores the font-lock state when it is turned off.  So,
;; if blank-mode is turned on and font-lock is off, blank-mode also
;; turns on the font-lock to highlight blanks, but the font-lock will
;; be turned off when blank-mode is turned off.  Thus, turn on
;; font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode 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).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That
;;   is, if you turn on global blank-mode and then create a new
;;   buffer, the new buffer will also have blank-mode on.  The
;;   `blank-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 blank-mode has priority over global blank-mode.  That is:
;;
;; * when global and local blank-mode are on:
;;
;;    + if local blank-mode is turned off, blank-mode is turned off
;;      for the current buffer only.
;;
;;    + if global blank-mode is turned off, blank-mode continues on
;;      only in the buffers in which local blank-mode is on.
;;
;; * when global blank-mode is on and local blank-mode are off:
;;
;;    + if local blank-mode is turned on, only the modeline associated
;;      with the current buffer is modified.
;;
;; * when global blank-mode is off and local blank-mode are on:
;;
;;    + if global blank-mode is turned on, blank-mode is turned on in
;;      all buffers except that which has local blank-mode on.
;;      The modeline associated with the buffers with local
;;      blank-mode on is modified.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on               "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off              "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode                  "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle-options        "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize        "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on        "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off       "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode           "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle-options "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle-options RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle-options RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on',
;; `global-blank-mode-off', `blank-mode-customize',
;; `blank-toggle-options' and `global-blank-toggle-options' to some
;; key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle-options)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle-options)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please,
;; see the options declaration in the code for a long documentation.
;;
;; `blank-verbose'		Non-nil means generate messages.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is
;;				visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-newline-face'		Face used to visualise NEWLINE char
;;				mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing
;;				blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space
;;					before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab
;;					regexp.
;;
;; `blank-line-length'		Specify length beyond which the line
;;				is highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for
;;				displaying characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new
;;    Emacs session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs
;;    session.
;;
;; c) or use customization, for example:
;;
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-verbose t
  "*Non-nil means generate messages."
  :type 'boolean
  :version "20.6"
  :group 'blank)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars '(tabs spaces trailing lines space-before-tab)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs"
				space-before-tab)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "grey20"      :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face		; '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 visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "grey22" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"  :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-newline-face 'blank-newline-face
  "*Symbol face used to visualise NEWLINE char mapping.

See `blank-display-mappings'.

Used when `blank-style' has 'mark as an element."
  :type 'face
  :version "22.2"
  :group 'blank)


(defface blank-newline-face
  '((((class color) (background dark))
     :background "grey26" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"  :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.

See `blank-display-mappings'."
  :version "22.2"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face		; 'trailing-whitespace
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.

See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.

See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		\
visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		\
visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	\
visualise leading and/or trailing hard spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		\
visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters
besides \" \" that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	\
visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters
besides \"\\t\" that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	\
visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'tabs as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'lines as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  ;; Due to limitations of glyph representation, the char code can not
  ;; be above ?\x0FFFF.  Probably, this will be fixed after Emacs
  ;; unicode merging.
  '(
    (?\     [?\xB7]       [?.])		; space - centered dot
    (?\xA0  [?\xA4]       [?_])		; hard space - currency
    (?\x8A0 [?\x8A4]      [?_])		; hard space - currency
    (?\x920 [?\x924]      [?_])		; hard space - currency
    (?\xE20 [?\xE24]      [?_])		; hard space - currency
    (?\xF20 [?\xF24]      [?_])		; hard space - currency
    (?\n    [?$ ?\n])			; end-of-line - dollar sign
    ;; (?\n    [?\u21B5 ?\n] [?$ ?\n])	; end-of-line - downwards arrow
    ;; (?\n    [?\xB6 ?\n]   [?$ ?\n])	; end-of-line - pilcrow
    ;; (?\n    [?\x8AF ?\n]  [?$ ?\n])	; end-of-line - overscore
    ;; (?\n    [?\x8AC ?\n]  [?$ ?\n])	; end-of-line - negation
    ;; (?\n    [?\x8B0 ?\n]  [?$ ?\n])	; end-of-line - 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.
    (?\t    [?\xBB ?\t]   [?\\ ?\t])	; tab - left quote mark
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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
`blank-newline-face' variable.  The characters in the vector to be
displayed will not have applied this face if the character code is
above #x0FFFF.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t
					:tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically
turned on.
If a list, it should be a list of `major-mode' symbol names for
which `blank-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 `blank-mode' is turned on for buffers in C and C++
modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (blank-turn-on))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank 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 blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Toggle


;;;###autoload
(defun blank-toggle-options (arg)
  "Toggle local `blank-mode' options.

If local blank-mode is off, toggle the option given by ARG and
turn on local blank-mode.

If local blank-mode is on, toggle the option given by ARG and
restart local blank-mode.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars
	 (blank-toggle-list t arg blank-active-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list t arg blank-active-style blank-style
			    'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle-options (arg)
  "Toggle global `blank-mode' options.

If global blank-mode is off, toggle the option given by ARG and
turn on global blank-mode.

If global blank-mode is on, toggle the option given by ARG and
restart global blank-mode.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars
	 (blank-toggle-list nil arg blank-toggle-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list nil arg blank-toggle-style blank-style
			    'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('X' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "X" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(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)
	    (error "Frame height is too small; \
can't split window to display blank toggle options"))
	  (set-window-buffer (split-window nil size) buffer))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-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 reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let* ((is-off (not (if local-p blank-mode global-blank-mode)))
	 (chars  (cond (is-off  blank-chars) ; use default value
		       (local-p blank-active-chars)
		       (t       blank-toggle-chars)))
	 (style  (cond (is-off  blank-style) ; use default value
		       (local-p blank-active-style)
		       (t       blank-toggle-style)))
	 (prompt
	  (format "Blank 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 (progn
		     (setq ch (read-char prompt))
		     (not
		      (setq sym
			    (cdr (assq ch
				       blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to
restore the options in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options
in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's
options are valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (setq the-list (copy-sequence the-list)) ; do no change original list
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords
	    (copy-sequence font-lock-keywords)))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; add blank-mode color into font lock
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length)
		    ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defsubst blank-char-valid-p (char)
  ;; This check should be improved!!!
  (or (< char 256)
      (char-valid-p char)))


(defun blank-legal-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)
		  (blank-char-valid-p (aref vec i))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (when blank-display-mappings
    (let (vecs vec)
      ;; Remember whether a buffer has a local display table.
      (unless blank-display-table-was-local
	(setq blank-display-table-was-local t
	      blank-display-table
	      (copy-sequence buffer-display-table)))
      (unless buffer-display-table
	(setq buffer-display-table (make-display-table)))
      (dolist (entry blank-display-mappings)
	(setq vecs (cdr entry))
	;; Get a displayable mapping.
	(while (and vecs
		    (not (blank-legal-display-vector-p (car vecs))))
	  (setq vecs (cdr vecs)))
	;; Display a valid mapping.
	(when vecs
	  (setq vec (copy-sequence (car vecs)))
	  ;; Only insert face bits on NEWLINE char mapping to avoid
	  ;; obstruction of other faces like TABs and (HARD) SPACEs
	  ;; faces, font-lock faces, etc.
	  (when (and (eq (car entry) ?\n)
		     (memq 'color blank-active-style))
	    (dotimes (i (length vec))
	      ;; Due to limitations of glyph representation, the char
	      ;; code can not be above ?\x0FFFF.  Probably, this will
	      ;; be fixed after Emacs unicode merging.
	      (or (eq (aref vec i) ?\n)
		  (> (aref vec i) #x1FFFF)
		  (aset vec i (make-glyph-code (aref vec i)
					       blank-newline-face)))))
	  ;; Display mapping
	  (aset buffer-display-table (car entry) vec))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-19 14:44                                                             ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-19 16:22                                                               ` Robert J. Chassell
  2007-11-19 19:19                                                                 ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Robert J. Chassell @ 2007-11-19 16:22 UTC (permalink / raw)
  To: emacs-devel

    Done, but the names now are blank-toggle-options and 
    global-blank-toggle-options.

It would be better for blank to go first so every defun, defvar,
defconst, defcustom, defface, defgroup, and define-minor-mode start
with `blank-'.  That is easier to track, especially 20 years from now
by someone who does not know blank-mode.el.  The four that need
changing are:

    global-blank-mode
    global-blank-mode-on
    global-blank-mode-off
    global-blank-toggle-options

Otherwise, what I saw looks good.

-- 
    Robert J. Chassell                          GnuPG Key ID: 004B4AC8
    bob@rattlesnake.com                         bob@gnu.org
    http://www.rattlesnake.com                  http://www.teak.cc

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-19 16:22                                                               ` blank-mode.el Robert J. Chassell
@ 2007-11-19 19:19                                                                 ` Vinicius Jose Latorre
  2007-11-20  3:24                                                                   ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-19 19:19 UTC (permalink / raw)
  To: bob; +Cc: emacs-devel


>     Done, but the names now are blank-toggle-options and 
>     global-blank-toggle-options.
>
> It would be better for blank to go first so every defun, defvar,
> defconst, defcustom, defface, defgroup, and define-minor-mode start
> with `blank-'.  That is easier to track, especially 20 years from now
> by someone who does not know blank-mode.el.  The four that need
> changing are:
>
>     global-blank-mode
>     global-blank-mode-on
>     global-blank-mode-off
>     global-blank-toggle-options
>
> Otherwise, what I saw looks good.
>   

(Note that only some command names have "global-" prefix.
All defvar, defun (except some commands), defconst, defcustom,
defface and defgroup are prefixed by "blank-".)

Well, I also think this way, but there is no convention
(or consensus) about global minor mode name.

Initially, global blank-mode had the name blank-global-mode,
but Juri Linkov <juri@jurta.org> suggested to change to global-blank-mode.

I made a `grep -e "global-" *.el' in emacs/lisp dir.
It seems that some of global minor mode names are prefixed by "global-",
for example, global-font-lock-mode (instead of font-lock-global-mode),
global-auto-revert-mode, global-cwarn-mode, global-hi-lock-mode,
global-highlight-changes, global-hl-line-mode.

I don't know what convention to use if that already used by some
global minor mode ("global-" prefix) or if I use "blank-*-global-mode".

BTW, I think it should have some note in
Emacs Lisp Reference Manual about global minor mode name.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-19 19:19                                                                 ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-20  3:24                                                                   ` Vinicius Jose Latorre
  2007-11-21 13:42                                                                     ` blank-mode.el Vinicius Jose Latorre
  0 siblings, 1 reply; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-20  3:24 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 258 bytes --]


New blank-mode version attached in this email (still v7.1).

blank-verbose was eliminated.

Added 'newline as a new element of blank-chars.
Now, newlines visualization can be toggled.
See blank-chars, blank-toggle-options and global-blank-toggle-options.



[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 42788 bytes --]

;;; blank-mode.el --- minor mode to visualise blanks (SPACE, HARD SPACE, TAB)

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/20 00:06:50 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (SPACE, HARD SPACE
;; and TAB).
;;
;; blank-mode uses two ways to visualise blanks: faces and display
;; table.
;;
;; * Faces are used to highlight the background with a color.
;;   blank-mode 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 `blank-style' and `blank-chars' variables are used to select
;; which way should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the
;; font-lock state, that is, if font-lock is on or off.  And
;; blank-mode restores the font-lock state when it is turned off.  So,
;; if blank-mode is turned on and font-lock is off, blank-mode also
;; turns on the font-lock to highlight blanks, but the font-lock will
;; be turned off when blank-mode is turned off.  Thus, turn on
;; font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode 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).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That
;;   is, if you turn on global blank-mode and then create a new
;;   buffer, the new buffer will also have blank-mode on.  The
;;   `blank-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 blank-mode has priority over global blank-mode.  That is:
;;
;; * when global and local blank-mode are on:
;;
;;    + if local blank-mode is turned off, blank-mode is turned off
;;      for the current buffer only.
;;
;;    + if global blank-mode is turned off, blank-mode continues on
;;      only in the buffers in which local blank-mode is on.
;;
;; * when global blank-mode is on and local blank-mode are off:
;;
;;    + if local blank-mode is turned on, only the modeline associated
;;      with the current buffer is modified.
;;
;; * when global blank-mode is off and local blank-mode are on:
;;
;;    + if global blank-mode is turned on, blank-mode is turned on in
;;      all buffers except that which has local blank-mode on.
;;      The modeline associated with the buffers with local
;;      blank-mode on is modified.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on               "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off              "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode                  "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle-options        "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize        "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on        "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off       "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode           "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle-options "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle-options RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle-options RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on',
;; `global-blank-mode-off', `blank-mode-customize',
;; `blank-toggle-options' and `global-blank-toggle-options' to some
;; key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle-options)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle-options)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please,
;; see the options declaration in the code for a long documentation.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is
;;				visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-newline-face'		Face used to visualise NEWLINE char
;;				mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing
;;				blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise space
;;					before tab.
;;
;; `blank-space-regexp'		Specify space characters regexp.
;;
;; `blank-hspace-regexp'	Specify hard space characters regexp.
;;
;; `blank-tab-regexp'		Specify tab characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify space before tab
;;					regexp.
;;
;; `blank-line-length'		Specify length beyond which the line
;;				is highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for
;;				displaying characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new
;;    Emacs session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs
;;    session.
;;
;; c) or use customization, for example:
;;
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (SPACE, HARD SPACE and TAB)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars
  '(tabs spaces trailing lines space-before-tab newline)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than `blank-line-length'
			are highlighted.

   'space-before-tab	spaces before tabs are visualised.

   'newline		NEWLINEs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, SPACEs and HARD SPACEs.

Used when `blank-style' has 'color as an element.
If `blank-chars' has 'newline as an element, used when `blank-style'
has 'mark as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TABs"
				space-before-tab)
			 (const :tag "NEWLINEs" newline)))
  :version "22.1"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "grey20"      :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face		; '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 visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "grey22" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"  :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-newline-face 'blank-newline-face
  "*Symbol face used to visualise NEWLINE char mapping.

See `blank-display-mappings'.

Used when `blank-style' has 'mark and 'color as elements
and `blank-chars' has 'newline as an element."
  :type 'face
  :version "22.2"
  :group 'blank)


(defface blank-newline-face
  '((((class color) (background dark))
     :background "grey26" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"  :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.

See `blank-display-mappings'."
  :version "22.2"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face		; 'trailing-whitespace
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.

See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.

See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise space before tab.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise space before tab."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify hard space characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered hard space.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		\
visualise only leading hard spaces.
   \"\\\\(\\xA0+$\\\\)\"		\
visualise only trailing hard spaces.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	\
visualise leading and/or trailing hard spaces.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		\
visualise only hard spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Hard Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify space characters regexp.

If you're using `mule' package, it may exist other characters
besides \" \" that it should be considered space.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading spaces.
   \"\\\\( +$\\\\)\"		visualise only trailing spaces.
   \"\\\\(^ +\\\\| +$\\\\)\"	\
visualise leading and/or trailing spaces.
   \"\\t\\\\( +\\\\)\\t\"	visualise only spaces between tabs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "Space Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify tab characters regexp.

If you're using `mule' package, it may exist other characters
besides \"\\t\" that it should be considered tab.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading tabs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing tabs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	\
visualise leading and/or trailing tabs.
   \" \\\\(\\t+\\\\) \"	visualise only tabs between spaces.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'tabs as an element."
  :type '(regexp :tag "Tab Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify spaces before tabs regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'space-before-tab as an element."
  :type '(regexp :tag "Space Before Tab")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'lines as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  ;; Due to limitations of glyph representation, the char code can not
  ;; be above ?\x1FFFF.  Probably, this will be fixed after Emacs
  ;; unicode merging.
  '(
    (?\     [?\xB7]       [?.])		; space - centered dot
    (?\xA0  [?\xA4]       [?_])		; hard space - currency
    (?\x8A0 [?\x8A4]      [?_])		; hard space - currency
    (?\x920 [?\x924]      [?_])		; hard space - currency
    (?\xE20 [?\xE24]      [?_])		; hard space - currency
    (?\xF20 [?\xF24]      [?_])		; hard space - currency
    (?\n    [?$ ?\n])			; end-of-line - dollar sign
    ;; (?\n    [?\u21B5 ?\n] [?$ ?\n])	; end-of-line - downwards arrow
    ;; (?\n    [?\xB6 ?\n]   [?$ ?\n])	; end-of-line - pilcrow
    ;; (?\n    [?\x8AF ?\n]  [?$ ?\n])	; end-of-line - overscore
    ;; (?\n    [?\x8AC ?\n]  [?$ ?\n])	; end-of-line - negation
    ;; (?\n    [?\x8B0 ?\n]  [?$ ?\n])	; end-of-line - 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.
    (?\t    [?\xBB ?\t]   [?\\ ?\t])	; tab - left quote mark
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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
`blank-newline-face' variable.  The characters in the vector to be
displayed will not have applied this face if the character code is
above #x1FFFF.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t
					:tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically
turned on.
If a list, it should be a list of `major-mode' symbol names for
which `blank-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 `blank-mode' is turned on for buffers in C and C++
modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (blank-turn-on))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank 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 blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Toggle


;;;###autoload
(defun blank-toggle-options (arg)
  "Toggle local `blank-mode' options.

If local blank-mode is off, toggle the option given by ARG and
turn on local blank-mode.

If local blank-mode is on, toggle the option given by ARG and
restart local blank-mode.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   n	toggle NEWLINE visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   newline		toggle NEWLINE visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars
	 (blank-toggle-list t arg blank-active-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list t arg blank-active-style blank-style
			    'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle-options (arg)
  "Toggle global `blank-mode' options.

If global blank-mode is off, toggle the option given by ARG and
turn on global blank-mode.

If global blank-mode is on, toggle the option given by ARG and
restart global blank-mode.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   n	toggle NEWLINE visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle spaces before tab visualisation
   lines		toggle \"long lines\" visualisation
   newline		toggle NEWLINE visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars
	 (blank-toggle-list nil arg blank-toggle-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list nil arg blank-toggle-style blank-style
			    'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    newline
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?n . newline)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle spaces before tab visualisation
 []  l - toggle \"long lines\" visualisation
 []  n - toggle NEWLINE visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('X' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "X" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(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)
	    (error "Frame height is too small; \
can't split window to display blank toggle options"))
	  (set-window-buffer (split-window nil size) buffer))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-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 reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle spaces before tab visualisation
   l	toggle \"long lines\" visualisation
   n	toggle NEWLINE visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let* ((is-off (not (if local-p blank-mode global-blank-mode)))
	 (chars  (cond (is-off  blank-chars) ; use default value
		       (local-p blank-active-chars)
		       (t       blank-toggle-chars)))
	 (style  (cond (is-off  blank-style) ; use default value
		       (local-p blank-active-style)
		       (t       blank-toggle-style)))
	 (prompt
	  (format "Blank 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 (progn
		     (setq ch (read-char prompt))
		     (not
		      (setq sym
			    (cdr (assq ch
				       blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to
restore the options in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options
in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's
options are valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (setq the-list (copy-sequence the-list)) ; keep original list
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords
	    (copy-sequence font-lock-keywords)))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; add blank-mode color into font lock
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show hard spaces
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show tabs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length)
		    ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show spaces before tabs
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defsubst blank-char-valid-p (char)
  ;; This check should be improved!!!
  (or (< char 256)
      (char-valid-p char)))


(defun blank-legal-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)
		  (blank-char-valid-p (aref vec i))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (when blank-display-mappings
    (let (vecs vec)
      ;; Remember whether a buffer has a local display table.
      (unless blank-display-table-was-local
	(setq blank-display-table-was-local t
	      blank-display-table
	      (copy-sequence buffer-display-table)))
      (unless buffer-display-table
	(setq buffer-display-table (make-display-table)))
      (dolist (entry blank-display-mappings)
	(setq vecs (cdr entry))
	;; Get a displayable mapping.
	(while (and vecs
		    (not (blank-legal-display-vector-p (car vecs))))
	  (setq vecs (cdr vecs)))
	;; Display a valid mapping.
	(when vecs
	  (setq vec (copy-sequence (car vecs)))
	  (cond
	   ;; Any char except newline
	   ((not (eq (car entry) ?\n))
	    (aset buffer-display-table (car entry) vec))
	   ;; Newline char - display
	   ((memq 'newline blank-active-chars)
	    ;; Only insert face bits on NEWLINE char mapping to avoid
	    ;; obstruction of other faces like TABs and (HARD) SPACEs
	    ;; faces, font-lock faces, etc.
	    (when (memq 'color blank-active-style)
	      (dotimes (i (length vec))
		;; Due to limitations of glyph representation, the char
		;; code can not be above ?\x1FFFF.  Probably, this will
		;; be fixed after Emacs unicode merging.
		(or (eq (aref vec i) ?\n)
		    (> (aref vec i) #x1FFFF)
		    (aset vec i (make-glyph-code (aref vec i)
						 blank-newline-face)))))
	    ;; Display mapping
	    (aset buffer-display-table (car entry) vec))
	   ;; Newline char - don't display
	   (t
	    ;; Do nothing
	    )))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: blank-mode.el
  2007-11-20  3:24                                                                   ` blank-mode.el Vinicius Jose Latorre
@ 2007-11-21 13:42                                                                     ` Vinicius Jose Latorre
  0 siblings, 0 replies; 56+ messages in thread
From: Vinicius Jose Latorre @ 2007-11-21 13:42 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 100 bytes --]


Some doc fix.  blank-mode file attached in this email (still v7.1).

Comments, suggestions, etc.



[-- Attachment #2: blank-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 42806 bytes --]

;;; blank-mode.el --- minor mode to visualise TAB, (HARD) SPACE, NEWLINE

;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
;;   Vinicius Jose Latorre

;; Time-stamp: <2007/11/21 10:39:11 vinicius>
;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
;; Keywords: data, wp
;; Version: 7.1
;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program 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:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package is a minor mode to visualise blanks (TAB, (HARD) SPACE
;; and NEWLINE).
;;
;; blank-mode uses two ways to visualise blanks: faces and display
;; table.
;;
;; * Faces are used to highlight the background with a color.
;;   blank-mode 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 `blank-style' and `blank-chars' variables are used to select
;; which way should be used to visualise blanks.
;;
;; Note that when blank-mode is turned on, blank-mode saves the
;; font-lock state, that is, if font-lock is on or off.  And
;; blank-mode restores the font-lock state when it is turned off.  So,
;; if blank-mode is turned on and font-lock is off, blank-mode also
;; turns on the font-lock to highlight blanks, but the font-lock will
;; be turned off when blank-mode is turned off.  Thus, turn on
;; font-lock before blank-mode is on, if you want that font-lock
;; continues on after blank-mode is turned off.
;;
;; When blank-mode 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).
;;
;; There are two ways of using blank-mode: local and global.
;;
;; * Local blank-mode affects only the current buffer.
;;
;; * Global blank-mode affects all current and future buffers.  That
;;   is, if you turn on global blank-mode and then create a new
;;   buffer, the new buffer will also have blank-mode on.  The
;;   `blank-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 blank-mode has priority over global blank-mode.  That is:
;;
;; * when global and local blank-mode are on:
;;
;;    + if local blank-mode is turned off, blank-mode is turned off
;;      for the current buffer only.
;;
;;    + if global blank-mode is turned off, blank-mode continues on
;;      only in the buffers in which local blank-mode is on.
;;
;; * when global blank-mode is on and local blank-mode are off:
;;
;;    + if local blank-mode is turned on, only the modeline associated
;;      with the current buffer is modified.
;;
;; * when global blank-mode is off and local blank-mode are on:
;;
;;    + if global blank-mode is turned on, blank-mode is turned on in
;;      all buffers except that which has local blank-mode on.
;;      The modeline associated with the buffers with local
;;      blank-mode on is modified.
;;
;; To use blank-mode, insert in your ~/.emacs:
;;
;;    (require 'blank-mode)
;;
;; Or:
;;
;;    (autoload 'blank-mode-on               "blank-mode"
;;      "Turn on blank visualisation."         t)
;;    (autoload 'blank-mode-off              "blank-mode"
;;      "Turn off blank visualisation."        t)
;;    (autoload 'blank-mode                  "blank-mode"
;;      "Toggle blank visualisation."          t)
;;    (autoload 'blank-toggle-options        "blank-mode"
;;      "Toggle local `blank-mode' options."   t)
;;    (autoload 'blank-mode-customize        "blank-mode"
;;      "Customize blank visualisation."       t)
;;    (autoload 'global-blank-mode-on        "blank-mode"
;;      "Turn on blank mode in every buffer."  t)
;;    (autoload 'global-blank-mode-off       "blank-mode"
;;      "Turn off blank mode in every buffer." t)
;;    (autoload 'global-blank-mode           "blank-mode"
;;      "Toggle blank mode in every buffer."   t)
;;    (autoload 'global-blank-toggle-options "blank-mode"
;;      "Toggle global `blank-mode' options."  t)
;;
;; For good performance, be sure to byte-compile blank-mode.el, e.g.
;;
;;    M-x byte-compile-file <give the path to blank-mode.el when prompted>
;;
;; This will generate blank-mode.elc, which will be loaded instead of
;; blank-mode.el.
;;
;; blank-mode was tested with GNU Emacs 20.6.1, 21, 22 and 23.
;;
;;
;; Using blank-mode
;; ----------------
;;
;; There is no problem if you mix local and global minor mode usage.
;;
;; * To customize blank-mode, type:
;;
;;    M-x blank-mode-customize RET
;;
;; * LOCAL blank-mode:
;;    + To toggle blank-mode options locally, type:
;;
;;         M-x blank-toggle-options RET
;;
;;    + To activate blank-mode locally, type:
;;
;;         M-x blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x blank-mode RET
;;
;;    + To deactivate blank-mode locally, type:
;;
;;         M-x blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x blank-mode RET
;;
;;    + To toggle blank-mode locally, type:
;;
;;         M-x blank-mode RET
;;
;; * GLOBAL blank-mode:
;;    + To toggle blank-mode options globally, type:
;;
;;         M-x global-blank-toggle-options RET
;;
;;    + To activate blank-mode globally, type:
;;
;;         M-x global-blank-mode-on RET
;;
;;      Or:
;;
;;         C-u 1 M-x global-blank-mode RET
;;
;;    + To deactivate blank-mode globally, type:
;;
;;         M-x global-blank-mode-off RET
;;
;;      Or:
;;
;;         C-u 0 M-x global-blank-mode RET
;;
;;    + To toggle blank-mode globally, type:
;;
;;         M-x global-blank-mode RET
;;
;; You can also bind `blank-mode', `blank-mode-on', `blank-mode-off',
;; `global-blank-mode', `global-blank-mode-on',
;; `global-blank-mode-off', `blank-mode-customize',
;; `blank-toggle-options' and `global-blank-toggle-options' to some
;; key, like:
;;
;;    (global-set-key "\C-c_1" 'blank-mode-on)
;;    (global-set-key "\C-c_0" 'blank-mode-off)
;;    (global-set-key "\C-c_b" 'blank-mode)
;;    (global-set-key "\C-c_t" 'blank-toggle-options)
;;    (global-set-key "\C-c_c" 'blank-mode-customize)
;;    (global-set-key "\C-c=1" 'global-blank-mode-on)
;;    (global-set-key "\C-c=0" 'global-blank-mode-off)
;;    (global-set-key "\C-c=b" 'global-blank-mode)
;;    (global-set-key "\C-c=t" 'global-blank-toggle-options)
;;
;;
;; Hooks
;; -----
;;
;; blank-mode has the following hook variables:
;;
;; `blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on locally.
;;
;; `global-blank-mode-hook'
;;    It is evaluated always when blank-mode is turned on globally.
;;
;; `blank-load-hook'
;;    It is evaluated after blank-mode package is loaded.
;;
;;
;; Options
;; -------
;;
;; Below it's shown a brief description of blank-mode options, please,
;; see the options declaration in the code for a long documentation.
;;
;; `blank-style'		Specify the visualisation style.
;;
;; `blank-chars'		Specify which kind of blank is
;;				visualised.
;;
;; `blank-space-face'		Face used to visualise SPACE.
;;
;; `blank-hspace-face'		Face used to visualise HARD SPACE.
;;
;; `blank-tab-face'		Face used to visualise TAB.
;;
;; `blank-newline-face'		Face used to visualise NEWLINE char
;;				mapping.
;;
;; `blank-trailing-face'	Face used to visualise trailing
;;				blanks.
;;
;; `blank-line-face'		Face used to visualise "long" lines.
;;
;; `blank-space-before-tab-face'	Face used to visualise SPACEs
;;					before TAB.
;;
;; `blank-space-regexp'		Specify SPACE characters regexp.
;;
;; `blank-hspace-regexp'	Specify HARD SPACE characters regexp.
;;
;; `blank-tab-regexp'		Specify TAB characters regexp.
;;
;; `blank-trailing-regexp'	Specify trailing characters regexp.
;;
;; `blank-space-before-tab-regexp'	Specify SPACEs before TAB
;;					regexp.
;;
;; `blank-line-length'		Specify length beyond which the line
;;				is highlighted.
;;
;; `blank-display-mappings'	Specify an alist of mappings for
;;				displaying characters.
;;
;; `blank-global-modes'		Modes for which global `blank-mode' is
;;				automagically turned on.
;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;;	 (setq blank-space-face 'underline)
;;
;;    This way always keep your default settings when you enter a new
;;    Emacs session.
;;
;; b) or use `set-variable' in your Emacs session, like:
;;
;;	 M-x set-variable RET blank-space-face RET underline RET
;;
;;    This way keep your settings only during the current Emacs
;;    session.
;;
;; c) or use customization, for example:
;;
;;    In Emacs 21 or lower:
;;	 click on menu-bar *Help* option,
;;	 then click on *Customize*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;
;;    In Emacs 22 or higher:
;;	 click on menu-bar *Options* option,
;;	 then click on *Customize Emacs*,
;;	 then click on *Browse Customization Groups*,
;;	 expand *Data* group,
;;	 expand *Blank* group
;;	 and then customize blank-mode options.
;;
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; d) or see the option value:
;;
;;	 C-h v blank-space-face RET
;;
;;    and click the *customize* hypertext button.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;; e) or invoke:
;;
;;	 M-x blank-mode-customize RET
;;
;;    and then customize blank-mode options.
;;    Through this way, you may choose if the settings are kept or not
;;    when you leave out the current Emacs session.
;;
;;
;; Acknowledgements
;; ----------------
;;
;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
;;    * `define-minor-mode'.
;;    * `global-blank-*' 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 on XEmacs.
;;
;; Thanks to:
;;    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 blank nil
  "Visualise blanks (TAB, (HARD) SPACE and NEWLINE)."
  :link '(emacs-library-link :tag "Source Lisp File" "blank-mode.el")
  :version "20.6"
  :group 'wp
  :group 'data)


(defcustom blank-style '(mark color)
  "*Specify the visualisation style.

It's a list which element value can be:

   'mark	display mappings are visualised.

   'color	faces are visualised.

Any other value is ignored.

If it's nil, don't visualise TABs, (HARD) SPACEs and NEWLINEs.

See also `blank-display-mappings' for documentation."
  :type '(repeat :tag "Style of Blank"
		 (choice :tag "Style of Blank"
			 (const :tag "Display Table" mark)
			 (const :tag "Faces" color)))
  :version "20.6"
  :group 'blank)


(defcustom blank-chars
  '(tabs spaces trailing lines space-before-tab newline)
  "*Specify which kind of blank is visualised.

It's a list which element value can be:

   'trailing		trailing blanks are visualised.

   'tabs		TABs are visualised.

   'spaces		SPACEs and HARD SPACEs are visualised.

   'lines		lines whose length is greater than
			`blank-line-length' are highlighted.

   'space-before-tab	SPACEs before TAB are visualised.

   'newline		NEWLINEs are visualised.

Any other element value is ignored.

If it's nil, don't visualise TABs, (HARD) SPACEs and NEWLINEs.

Used when `blank-style' has 'color as an element.
If `blank-chars' has 'newline as an element, used when `blank-style'
has 'mark as an element."
  :type '(repeat :tag "Kind of Blank"
		 (choice :tag "Kind of Blank"
			 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
				trailing)
			 (const :tag "SPACEs and HARD SPACEs" spaces)
			 (const :tag "TABs" tabs)
			 (const :tag "Lines" lines)
			 (const :tag "SPACEs before TAB"
				space-before-tab)
			 (const :tag "NEWLINEs" newline)))
  :version "20.6"
  :group 'blank)


(defcustom blank-space-face 'blank-space-face
  "*Symbol face used to visualise SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-space-face
  '((((class color) (background dark))
     :background "grey20"      :foreground "aquamarine3")
    (((class color) (background light))
     :background "LightYellow" :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-hspace-face 'blank-hspace-face
  "*Symbol face used to visualise HARD SPACE.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-hspace-face		; '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 visualise HARD SPACE."
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-face 'blank-tab-face
  "*Symbol face used to visualise TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-tab-face
  '((((class color) (background dark))
     :background "grey22" :foreground "aquamarine3")
    (((class color) (background light))
     :background "beige"  :foreground "aquamarine3")
    (t (:inverse-video t)))
  "Face used to visualise TAB."
  :version "20.6"
  :group 'blank)


(defcustom blank-newline-face 'blank-newline-face
  "*Symbol face used to visualise NEWLINE char mapping.

See `blank-display-mappings'.

Used when `blank-style' has 'mark and 'color as elements
and `blank-chars' has 'newline as an element."
  :type 'face
  :version "22.2"
  :group 'blank)


(defface blank-newline-face
  '((((class color) (background dark))
     :background "grey26" :foreground "aquamarine3" :bold t)
    (((class color) (background light))
     :background "linen"  :foreground "aquamarine3" :bold t)
    (t (:bold t :underline t)))
  "Face used to visualise NEWLINE char mapping.

See `blank-display-mappings'."
  :version "22.2"
  :group 'blank)


(defcustom blank-trailing-face 'blank-trailing-face
  "*Symbol face used to visualise traling blanks.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-trailing-face		; 'trailing-whitespace
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "red1" :foreground "yellow" :bold t)))
  "Face used to visualise trailing blanks."
  :version "20.6"
  :group 'blank)


(defcustom blank-line-face 'blank-line-face
  "*Symbol face used to visualise \"long\" lines.

See `blank-line-legnth'.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "20.6"
  :group 'blank)


(defface blank-line-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "gray20" :foreground "violet")))
  "Face used to visualise \"long\" lines.

See `blank-line-length'."
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-face 'blank-space-before-tab-face
  "*Symbol face used to visualise SPACEs before TAB.

Used when `blank-style' has 'color as an element."
  :type 'face
  :version "22"
  :group 'blank)


(defface blank-space-before-tab-face
  '((((class mono)) (:inverse-video t :bold t :underline t))
    (t (:background "DarkOrange" :foreground "firebrick")))
  "Face used to visualise SPACEs before TAB."
  :version "22"
  :group 'blank)


(defcustom blank-hspace-regexp
  "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
  "*Specify HARD SPACE characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \"\\xA0\"   \"\\x8A0\"   \"\\x920\"   \"\\xE20\"   \"\\xF20\"

that it should be considered HARD SPACE.

Here are some examples:

   \"\\\\(^\\xA0+\\\\)\"		\
visualise only leading HARD SPACEs.
   \"\\\\(\\xA0+$\\\\)\"		\
visualise only trailing HARD SPACEs.
   \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\"	\
visualise leading and/or trailing HARD SPACEs.
   \"\\t\\\\(\\xA0+\\\\)\\t\"		\
visualise only HARD SPACEs between TABs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "HARD SPACE Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-regexp "\\( +\\)"
  "*Specify SPACE characters regexp.

If you're using `mule' package, it may exist other characters
besides \" \" that it should be considered SPACE.

Here are some examples:

   \"\\\\(^ +\\\\)\"		visualise only leading SPACEs.
   \"\\\\( +$\\\\)\"		visualise only trailing SPACEs.
   \"\\\\(^ +\\\\| +$\\\\)\"	\
visualise leading and/or trailing SPACEs.
   \"\\t\\\\( +\\\\)\\t\"	visualise only SPACEs between TABs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'spaces as an element."
  :type '(regexp :tag "SPACE Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-tab-regexp "\\(\t+\\)"
  "*Specify TAB characters regexp.

If you're using `mule' package, it may exist other characters
besides \"\\t\" that it should be considered TAB.

Here are some examples:

   \"\\\\(^\\t+\\\\)\"		visualise only leading TABs.
   \"\\\\(\\t+$\\\\)\"		visualise only trailing TABs.
   \"\\\\(^\\t+\\\\|\\t+$\\\\)\"	\
visualise leading and/or trailing TABs.
   \" \\\\(\\t+\\\\) \"	visualise only TABs between SPACEs.

NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
      Use exactly one pair of enclosing \\\\( and \\\\).

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'tabs as an element."
  :type '(regexp :tag "TAB Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-trailing-regexp
  "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
  "*Specify trailing characters regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

NOTE: DOES NOT enclose by \\\\( and \\\\) the elements to highlight.
      `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
      \"\\\\)+\\\\)$\".

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'trailing as an element."
  :type '(regexp :tag "Trailing Chars")
  :version "20.6"
  :group 'blank)


(defcustom blank-space-before-tab-regexp "\\( +\\)\t"
  "*Specify SPACEs before TAB regexp.

If you're using `mule' package, it may exist other characters besides:

   \" \"  \"\\t\"  \"\\xA0\"  \"\\x8A0\"  \"\\x920\"  \"\\xE20\"  \
\"\\xF20\"

that it should be considered blank.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'space-before-tab as an element."
  :type '(regexp :tag "SPACEs Before TAB")
  :version "22"
  :group 'blank)


(defcustom blank-line-length 80
  "*Specify length beyond which the line is highlighted.

Used when `blank-style' has 'color as an element, and
`blank-chars' has 'lines as an element."
  :type '(integer :tag "Line Length")
  :version "20.6"
  :group 'blank)


;; Hacked from `visible-whitespace-mappings' in visws.el
(defcustom blank-display-mappings
  ;; Due to limitations of glyph representation, the char code can not
  ;; be above ?\x1FFFF.  Probably, this will be fixed after Emacs
  ;; unicode merging.
  '(
    (?\     [?\xB7]       [?.])		; space - centered dot
    (?\xA0  [?\xA4]       [?_])		; hard space - currency
    (?\x8A0 [?\x8A4]      [?_])		; hard space - currency
    (?\x920 [?\x924]      [?_])		; hard space - currency
    (?\xE20 [?\xE24]      [?_])		; hard space - currency
    (?\xF20 [?\xF24]      [?_])		; hard space - currency
    (?\n    [?$ ?\n])			; end-of-line - dollar sign
    ;; (?\n    [?\u21B5 ?\n] [?$ ?\n])	; end-of-line - downwards arrow
    ;; (?\n    [?\xB6 ?\n]   [?$ ?\n])	; end-of-line - pilcrow
    ;; (?\n    [?\x8AF ?\n]  [?$ ?\n])	; end-of-line - overscore
    ;; (?\n    [?\x8AC ?\n]  [?$ ?\n])	; end-of-line - negation
    ;; (?\n    [?\x8B0 ?\n]  [?$ ?\n])	; end-of-line - 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.
    (?\t    [?\xBB ?\t]   [?\\ ?\t])	; tab - left quote mark
    )
  "*Specify an alist of mappings for displaying characters.

Each element has the following form:

   (CHAR VECTOR...)

Where:

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
`blank-newline-face' variable.  The characters in the vector to be
displayed will not have applied this face if the character code is
above #x1FFFF.

Used when `blank-style' has 'mark as an element."
  :type '(repeat
	  (list :tag "Character Mapping"
		(character :tag "Char")
		(repeat :inline t :tag "Vector List"
			(vector :tag ""
				(repeat :inline t
					:tag "Vector Characters"
					(character :tag "Char"))))))
  :version "20.6"
  :group 'blank)


(defcustom blank-global-modes t
  "*Modes for which global `blank-mode' is automagically turned on.

Global `blank-mode' is controlled by the command `global-blank-mode'.

If nil, means no modes have `blank-mode' automatically turned on.
If t, all modes that support `blank-mode' have it automatically
turned on.
If a list, it should be a list of `major-mode' symbol names for
which `blank-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 `blank-mode' is turned on for buffers in C and C++
modes only."
  :type '(choice (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"))))
  :version "20.6"
  :group 'blank)

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Customization


;;;###autoload
(defun blank-mode-customize ()
  "Customize blank-mode options."
  (interactive)
  (customize-group 'blank))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Local mode


;;;###autoload
(define-minor-mode blank-mode
  "Toggle blank minor mode visualisation (bl on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " bl"
  :init-value nil
  :global     nil
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq blank-mode nil))
   (blank-mode				; blank-mode on
    (blank-turn-on))
   (t					; blank-mode off
    (blank-turn-off))))


;;;###autoload
(defun blank-mode-on ()
  "Turn on blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 1))


;;;###autoload
(defun blank-mode-off ()
  "Turn off blank minor mode visualisation (bl on modeline)."
  (interactive)
  (blank-mode 0))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Global mode


(define-minor-mode global-blank-mode
  "Toggle blank global minor mode visualisation (BL on modeline).

If ARG is null, toggle blank visualisation.
If ARG is a number and is greater than zero, turn on
visualisation; otherwise, turn off visualisation.
Only useful with a windowing system."
  :lighter    " BL"
  :init-value nil
  :global     t
  :group      'blank
  :version    "21"
  (cond
   (noninteractive			; running a batch job
    (setq global-blank-mode nil))
   (global-blank-mode			; global-blank-mode on
    (save-excursion
      (if (boundp 'find-file-hook)
	  (add-hook 'find-file-hook 'blank-turn-on-if-enabled t)
	(add-hook 'find-file-hooks 'blank-turn-on-if-enabled t))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-on-if-enabled)))))
   (t					; global-blank-mode off
    (save-excursion
      (if (boundp 'find-file-hook)
	  (remove-hook 'find-file-hook 'blank-turn-on-if-enabled)
	(remove-hook 'find-file-hooks 'blank-turn-on-if-enabled))
      (dolist (buffer (buffer-list))	; adjust all local mode
	(set-buffer buffer)
	(unless blank-mode
	  (blank-turn-off)))))))


;;;###autoload
(defun global-blank-mode-on ()
  "Turn on blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 1))


;;;###autoload
(defun global-blank-mode-off ()
  "Turn off blank global minor mode visualisation (BL on modeline)."
  (interactive)
  (global-blank-mode 0))


(defun blank-turn-on-if-enabled ()
  (when (cond
	 ((eq blank-global-modes t))
	 ((listp blank-global-modes)
	  (if (eq (car-safe blank-global-modes) 'not)
	      (not (memq major-mode (cdr blank-global-modes)))
	    (memq major-mode blank-global-modes)))
	 (t nil))
    (let (inhibit-quit)
      ;; Don't turn on blank 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 blank mode.
       (blank-turn-on)))))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User commands - Toggle


;;;###autoload
(defun blank-toggle-options (arg)
  "Toggle local `blank-mode' options.

If local blank-mode is off, toggle the option given by ARG and
turn on local blank-mode.

If local blank-mode is on, toggle the option given by ARG and
restart local blank-mode.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle SPACEs before TAB visualisation
   l	toggle \"long lines\" visualisation
   n	toggle NEWLINE visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle SPACEs before TAB visualisation
   lines		toggle \"long lines\" visualisation
   newline		toggle NEWLINE visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char t))
  (let ((blank-chars
	 (blank-toggle-list t arg blank-active-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list t arg blank-active-style blank-style
			    'blank-style blank-style-value-list)))
    (blank-mode 0)
    (blank-mode 1)))


(defvar blank-toggle-chars nil
  "Used to toggle the global `blank-chars' value.")
(defvar blank-toggle-style nil
  "Used to toggle the global `blank-style' value.")


;;;###autoload
(defun global-blank-toggle-options (arg)
  "Toggle global `blank-mode' options.

If global blank-mode is off, toggle the option given by ARG and
turn on global blank-mode.

If global blank-mode is on, toggle the option given by ARG and
restart global blank-mode.

Interactively, it reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle SPACEs before TAB visualisation
   l	toggle \"long lines\" visualisation
   n	toggle NEWLINE visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

Non-interactively, ARG should be a symbol or a list of symbol.
The valid symbols are:

   tabs			toggle TAB visualisation
   spaces		toggle SPACE and HARD SPACE visualisation
   trailing		toggle trailing blanks visualisation
   space-before-tab	toggle SPACEs before TAB visualisation
   lines		toggle \"long lines\" visualisation
   newline		toggle NEWLINE visualisation
   color		toggle color faces
   mark			toggle visual mark
   blank-chars		restore `blank-chars' value
   blank-style		restore `blank-style' value

Only useful with a windowing system."
  (interactive (blank-interactive-char nil))
  (let ((blank-chars
	 (blank-toggle-list nil arg blank-toggle-chars blank-chars
			    'blank-chars blank-chars-value-list))
	(blank-style
	 (blank-toggle-list nil arg blank-toggle-style blank-style
			    'blank-style blank-style-value-list)))
    (setq blank-toggle-chars blank-chars
	  blank-toggle-style blank-style)
    (global-blank-mode 0)
    (global-blank-mode 1)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Internal functions


(defconst blank-chars-value-list
  '(tabs
    spaces
    trailing
    space-before-tab
    lines
    newline
    )
  "List of valid `blank-chars' value.")


(defconst blank-style-value-list
  '(color
    mark
    )
  "List of valid `blank-style' value.")


(defconst blank-toggle-option-alist
  '((?t . tabs)
    (?s . spaces)
    (?r . trailing)
    (?b . space-before-tab)
    (?l . lines)
    (?n . newline)
    (?c . color)
    (?m . mark)
    (?x . blank-chars)
    (?z . blank-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 `blank-chars-value-list' and `blank-style-value-list'.")


(defconst blank-help-text
  "\
      blank-mode toggle options:

 []  t - toggle TAB visualisation
 []  s - toggle SPACE and HARD SPACE visualisation
 []  r - toggle trailing blanks visualisation
 []  b - toggle SPACEs before TAB visualisation
 []  l - toggle \"long lines\" visualisation
 []  n - toggle NEWLINE visualisation

 []  c - toggle color faces
 []  m - toggle visual mark

      x - restore `blank-chars' value
      z - restore `blank-style' value

      ? - display this text\n\n"
  "Text for blank toggle options.")


(defconst blank-help-buffer-name "*Blank Toggle Options*"
  "The buffer name for blank toggle options.")


(defun blank-insert-option-mark (the-list the-value)
  "Insert the option mark ('X' or ' ') in toggle options buffer."
  (forward-line 1)
  (dolist (sym  the-list)
    (forward-line 1)
    (forward-char 2)
    (insert (if (memq sym the-value) "X" " "))))


(defun blank-help-on (chars style)
  "Display the blank toggle options."
  (unless (get-buffer blank-help-buffer-name)
    (delete-other-windows)
    (let ((buffer (get-buffer-create blank-help-buffer-name)))
      (save-excursion
	(set-buffer buffer)
	(erase-buffer)
	(insert blank-help-text)
	(goto-char (point-min))
	(blank-insert-option-mark blank-chars-value-list chars)
	(blank-insert-option-mark blank-style-value-list style)
	(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)
	    (error "Frame height is too small; \
can't split window to display blank toggle options"))
	  (set-window-buffer (split-window nil size) buffer))))))


(defun blank-help-off ()
  "Remove the buffer and window of the blank toggle options."
  (let ((buffer (get-buffer blank-help-buffer-name)))
    (when buffer
      (delete-windows-on buffer)
      (kill-buffer buffer))))


(defun blank-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 reads one of the following chars:

  CHAR	MEANING
   t	toggle TAB visualisation
   s	toggle SPACE and HARD SPACE visualisation
   r	toggle trailing blanks visualisation
   b	toggle SPACEs before TAB visualisation
   l	toggle \"long lines\" visualisation
   n	toggle NEWLINE visualisation
   c	toggle color faces
   m	toggle visual mark
   x	restore `blank-chars' value
   z	restore `blank-style' value
   ?	display brief help

See also `blank-toggle-option-alist'."
  (let* ((is-off (not (if local-p blank-mode global-blank-mode)))
	 (chars  (cond (is-off  blank-chars) ; use default value
		       (local-p blank-active-chars)
		       (t       blank-toggle-chars)))
	 (style  (cond (is-off  blank-style) ; use default value
		       (local-p blank-active-style)
		       (t       blank-toggle-style)))
	 (prompt
	  (format "Blank 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 (progn
		     (setq ch (read-char prompt))
		     (not
		      (setq sym
			    (cdr (assq ch
				       blank-toggle-option-alist)))))
	      (if (eq ch ?\?)
		  (blank-help-on chars style)
		(ding)))
	    (blank-help-off)
	    (message " "))		; clean echo area
	;; handler
	((quit error)
	 (blank-help-off)
	 (error (error-message-string data)))))
    (list sym)))			; return the apropriate symbol


(defun blank-toggle-list (local-p arg the-list default-list
				  sym-restore sym-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.

DEFAULT-LIST is the default list of options.  It is used to
restore the options in THE-LIST.

SYM-RESTORE is the symbol which indicates to restore the options
in THE-LIST.

SYM-LIST is a list of valid options, used to check if the ARG's
options are valid."
  (unless (if local-p blank-mode global-blank-mode)
    (setq the-list default-list))
  (setq the-list (copy-sequence the-list)) ; keep original list
  (dolist (sym (if (listp arg) arg (list arg)))
    (cond
     ;; restore default values
     ((eq sym sym-restore)
      (setq the-list default-list))
     ;; toggle valid values
     ((memq sym sym-list)
      (setq the-list (if (memq sym the-list)
			 (delq sym the-list)
		       (cons sym the-list))))
     ))
  the-list)


(defvar blank-font-lock-mode nil
  "Used to remember whether a buffer had font lock mode on or not.")
(make-variable-buffer-local 'blank-font-lock-mode)

(defvar blank-font-lock nil
  "Used to remember whether a buffer initially had font lock on or not.")
(make-variable-buffer-local 'blank-font-lock)

(defvar blank-font-lock-keywords nil
  "Used to save locally `font-lock-keywords' value.")
(make-variable-buffer-local 'blank-font-lock-keywords)

(defvar blank-active-chars nil
  "Used to save locally `blank-chars' value.")
(make-variable-buffer-local 'blank-active-chars)

(defvar blank-active-style nil
  "Used to save locally `blank-style' value.")
(make-variable-buffer-local 'blank-active-style)


(defun blank-turn-on ()
  "Turn on blank visualisation."
  (setq blank-active-style (if (listp blank-style)
			       blank-style
			     (list blank-style)))
  (setq blank-active-chars (if (listp blank-chars)
			       blank-chars
			     (list blank-chars)))
  (and (memq 'color blank-active-style)
       (blank-color-on))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-on)))


(defun blank-turn-off ()
  "Turn off blank visualisation."
  (and (memq 'color blank-active-style)
       (blank-color-off))
  (and (memq 'mark  blank-active-style)
       (blank-display-char-off)))


(defun blank-color-on ()
  "Turn on color visualisation."
  (when blank-active-chars
    (unless blank-font-lock
      (setq blank-font-lock t
	    blank-font-lock-keywords
	    (copy-sequence font-lock-keywords)))
    ;; turn off font lock
    (setq blank-font-lock-mode font-lock-mode)
    (font-lock-mode 0)
    ;; add blank-mode color into font lock
    (and (memq 'spaces blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show SPACEs
	   (list blank-space-regexp  1 blank-space-face  t)
	   ;; Show HARD SPACEs
	   (list blank-hspace-regexp 1 blank-hspace-face t))
	  t))
    (and (memq 'tabs blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show TABs
	   (list blank-tab-regexp 1 blank-tab-face t))
	  t))
    (and (memq 'trailing blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show trailing blanks
	   (list (concat "\\(\\(" blank-trailing-regexp "\\)+\\)$")
		 1 blank-trailing-face t))
	  t))
    (and (memq 'lines blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show "long" lines
	   (list
	    (concat "^\\(.\\{" (int-to-string blank-line-length)
		    ",\\}\\)$")
	    1 blank-line-face t))
	  t))
    (and (memq 'space-before-tab blank-active-chars)
	 (font-lock-add-keywords
	  nil
	  (list
	   ;; Show SPACEs before TAB
	   (list blank-space-before-tab-regexp 1
		 blank-space-before-tab-face t))
	  t))
    ;; now turn on font lock and highlight blanks
    (font-lock-mode 1)))


(defun blank-color-off ()
  "Turn off color visualisation."
  (when blank-active-chars
    (when blank-font-lock
      (setq blank-font-lock nil
	    font-lock-keywords blank-font-lock-keywords))
    ;; turn off font lock
    (font-lock-mode 0)
    ;; restore original font lock state
    (font-lock-mode blank-font-lock-mode)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el


(defvar blank-display-table nil
  "Used to save a local display table.")
(make-variable-buffer-local 'blank-display-table)

(defvar blank-display-table-was-local nil
  "Used to remember whether a buffer initially had a local display table or not.")
(make-variable-buffer-local 'blank-display-table-was-local)


(defsubst blank-char-valid-p (char)
  ;; This check should be improved!!!
  (or (< char 256)
      (char-valid-p char)))


(defun blank-legal-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)
		  (blank-char-valid-p (aref vec i))))
      (< i 0))))


(defun blank-display-char-on ()
  "Turn on character display mapping."
  (when blank-display-mappings
    (let (vecs vec)
      ;; Remember whether a buffer has a local display table.
      (unless blank-display-table-was-local
	(setq blank-display-table-was-local t
	      blank-display-table
	      (copy-sequence buffer-display-table)))
      (unless buffer-display-table
	(setq buffer-display-table (make-display-table)))
      (dolist (entry blank-display-mappings)
	(setq vecs (cdr entry))
	;; Get a displayable mapping.
	(while (and vecs
		    (not (blank-legal-display-vector-p (car vecs))))
	  (setq vecs (cdr vecs)))
	;; Display a valid mapping.
	(when vecs
	  (setq vec (copy-sequence (car vecs)))
	  (cond
	   ;; Any char except newline
	   ((not (eq (car entry) ?\n))
	    (aset buffer-display-table (car entry) vec))
	   ;; Newline char - display it
	   ((memq 'newline blank-active-chars)
	    ;; Only insert face bits on NEWLINE char mapping to avoid
	    ;; obstruction of other faces like TABs and (HARD) SPACEs
	    ;; faces, font-lock faces, etc.
	    (when (memq 'color blank-active-style)
	      (dotimes (i (length vec))
		;; Due to limitations of glyph representation, the char
		;; code can not be above ?\x1FFFF.  Probably, this will
		;; be fixed after Emacs unicode merging.
		(or (eq (aref vec i) ?\n)
		    (> (aref vec i) #x1FFFF)
		    (aset vec i (make-glyph-code (aref vec i)
						 blank-newline-face)))))
	    ;; Display mapping
	    (aset buffer-display-table (car entry) vec))
	   ;; Newline char - don't display it
	   (t
	    ;; Do nothing
	    )))))))


(defun blank-display-char-off ()
  "Turn off character display mapping."
  (and blank-display-mappings
       blank-display-table-was-local
       (setq blank-display-table-was-local nil
	     buffer-display-table          blank-display-table)))

\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'blank-mode)


(run-hooks 'blank-load-hook)


;;; blank-mode.el ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2007-11-21 13:42 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-28 14:20 blank-mode.el Vinicius Jose Latorre
2007-10-28 14:27 ` blank-mode.el Leo
2007-10-28 18:10   ` blank-mode.el Vinicius Jose Latorre
2007-10-28 17:31 ` blank-mode.el Drew Adams
2007-10-28 19:35   ` blank-mode.el Vinicius Jose Latorre
2007-10-28 19:05     ` blank-mode.el Drew Adams
2007-10-28 23:04       ` blank-mode.el Vinicius Jose Latorre
2007-10-28 22:11         ` blank-mode.el Drew Adams
2007-10-29 10:00         ` blank-mode.el Kim F. Storm
2007-10-29 15:37           ` blank-mode.el Vinicius Jose Latorre
2007-10-30 14:17             ` blank-mode.el Juri Linkov
2007-10-31  4:16               ` blank-mode.el Vinicius Jose Latorre
2007-10-31 16:11                 ` blank-mode.el Juri Linkov
2007-11-09 17:10                   ` blank-mode.el Vinicius Jose Latorre
2007-11-09 18:11                     ` blank-mode.el Vinicius Jose Latorre
2007-11-09 20:41                       ` blank-mode.el Robert J. Chassell
2007-11-11  2:13                         ` blank-mode.el Vinicius Jose Latorre
2007-11-11 12:19                           ` blank-mode.el Robert J. Chassell
2007-11-11 14:37                             ` blank-mode.el Drew Adams
2007-11-11 14:57                             ` blank-mode.el Jason Rumney
2007-11-11 17:52                               ` blank-mode.el Robert J. Chassell
2007-11-11 21:23                                 ` blank-mode.el Vinicius Jose Latorre
2007-11-11 21:48                                   ` blank-mode.el Juri Linkov
2007-11-11 21:59                                     ` blank-mode.el Juanma Barranquero
2007-11-11 22:36                                       ` blank-mode.el Juri Linkov
2007-11-11 23:25                                         ` blank-mode.el Juanma Barranquero
2007-11-12  0:05                                       ` blank-mode.el Vinicius Jose Latorre
2007-11-11 23:28                                         ` blank-mode.el Juanma Barranquero
2007-11-12  0:43                                           ` blank-mode.el Vinicius Jose Latorre
2007-11-12 18:26                                             ` blank-mode.el Robert J. Chassell
2007-11-12 19:53                                               ` blank-mode.el Andreas Schwab
2007-11-12 21:51                                               ` blank-mode.el Vinicius Jose Latorre
2007-11-13 10:45                                                 ` blank-mode.el Robert J. Chassell
2007-11-13 12:13                                                   ` blank-mode.el Vinicius Jose Latorre
2007-11-13 16:41                                                     ` blank-mode.el Vinicius Jose Latorre
2007-11-13 23:54                                                       ` blank-mode.el Juri Linkov
2007-11-14  0:19                                                         ` blank-mode.el Jason Rumney
2007-11-14 10:29                                                         ` blank-mode.el Andreas Schwab
2007-11-16  4:10                                                         ` blank-mode.el Vinicius Jose Latorre
2007-11-16 12:02                                                           ` blank-mode.el Robert J. Chassell
2007-11-17 21:05                                                             ` blank-mode.el Vinicius Jose Latorre
2007-11-17 22:57                                                               ` blank-mode.el Juri Linkov
2007-11-18 14:55                                                                 ` blank-mode.el Vinicius Jose Latorre
2007-11-19 14:44                                                             ` blank-mode.el Vinicius Jose Latorre
2007-11-19 16:22                                                               ` blank-mode.el Robert J. Chassell
2007-11-19 19:19                                                                 ` blank-mode.el Vinicius Jose Latorre
2007-11-20  3:24                                                                   ` blank-mode.el Vinicius Jose Latorre
2007-11-21 13:42                                                                     ` blank-mode.el Vinicius Jose Latorre
2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
2007-11-11 22:04                                   ` blank-mode.el Robert J. Chassell
2007-11-12  0:01                                     ` blank-mode.el Vinicius Jose Latorre
2007-11-11 22:01                                 ` blank-mode.el Jason Rumney
2007-11-11 22:37                                   ` blank-mode.el Juri Linkov
2007-11-11 22:46                                     ` blank-mode.el Jason Rumney
2007-11-11 17:01                           ` blank-mode.el Robert J. Chassell
  -- strict thread matches above, loose matches on Subject: below --
2007-11-14 13:44 blank-mode.el Robert J. Chassell

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).