]> code.delx.au - gnu-emacs/blobdiff - lisp/ruler-mode.el
(normal-splash-screen, fancy-splash-screens-1): Add a reference to the Lisp
[gnu-emacs] / lisp / ruler-mode.el
index 7673802fdfa045cb2bcc67b896676595a3a6f7c9..a441c3a112e48ac3e42dee991cb3be68d4bbd79a 100644 (file)
@@ -1,6 +1,7 @@
 ;;; ruler-mode.el --- display a ruler in the header line
 
-;; Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2002, 2003, 2004, 2005,
+;;   2006 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Maintainer: David Ponce <david@dponce.com>
@@ -22,8 +23,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;;
 ;; The following faces are customizable:
 ;;
-;; - `ruler-mode-default-face' the ruler default face.
-;; - `ruler-mode-fill-column-face' the face used to highlight the
+;; - `ruler-mode-default' the ruler default face.
+;; - `ruler-mode-fill-column' the face used to highlight the
 ;;   `fill-column' character.
-;; - `ruler-mode-comment-column-face' the face used to highlight the
+;; - `ruler-mode-comment-column' the face used to highlight the
 ;;   `comment-column' character.
-;; - `ruler-mode-goal-column-face' the face used to highlight the
+;; - `ruler-mode-goal-column' the face used to highlight the
 ;;   `goal-column' character.
-;; - `ruler-mode-current-column-face' the face used to highlight the
+;; - `ruler-mode-current-column' the face used to highlight the
 ;;   `current-column' character.
-;; - `ruler-mode-tab-stop-face' the face used to highlight tab stop
+;; - `ruler-mode-tab-stop' the face used to highlight tab stop
 ;;   characters.
-;; - `ruler-mode-margins-face' the face used to highlight graduations
+;; - `ruler-mode-margins' the face used to highlight graduations
 ;;   in the `window-margins' areas.
-;; - `ruler-mode-fringes-face' the face used to highlight graduations
+;; - `ruler-mode-fringes' the face used to highlight graduations
 ;;   in the `window-fringes' areas.
-;; - `ruler-mode-column-number-face' the face used to highlight the
+;; - `ruler-mode-column-number' the face used to highlight the
 ;;   numbered graduations.
 ;;
-;; `ruler-mode-default-face' inherits from the built-in `default' face.
-;; All `ruler-mode' faces inherit from `ruler-mode-default-face'.
+;; `ruler-mode-default' inherits from the built-in `default' face.
+;; All `ruler-mode' faces inherit from `ruler-mode-default'.
 ;;
 ;; WARNING: To keep ruler graduations aligned on text columns it is
 ;; important to use the same font family and size for ruler and text
 ;; areas.
+;;
+;; You can override the ruler format by defining an appropriate
+;; function as the buffer-local value of `ruler-mode-ruler-function'.
 
 ;; Installation
 ;;
 ;;; Code:
 (eval-when-compile
   (require 'wid-edit))
+(require 'scroll-bar)
+(require 'fringe)
 
 (defgroup ruler-mode nil
   "Display a ruler in the header line."
-  :version "21.4"
+  :version "22.1"
   :group 'convenience)
 
 (defcustom ruler-mode-show-tab-stops nil
@@ -200,7 +206,7 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] or
   :group 'ruler-mode
   :type 'boolean)
 \f
-(defface ruler-mode-default-face
+(defface ruler-mode-default
   '((((type tty))
      (:inherit default
                :background "grey64"
@@ -217,126 +223,83 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] or
   "Default face used by the ruler."
   :group 'ruler-mode)
 
-(defface ruler-mode-pad-face
+(defface ruler-mode-pad
   '((((type tty))
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :background "grey50"
                ))
     (t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :background "grey64"
                )))
   "Face used to pad inactive ruler areas."
   :group 'ruler-mode)
 
-(defface ruler-mode-margins-face
+(defface ruler-mode-margins
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "white"
                )))
   "Face used to highlight margin areas."
   :group 'ruler-mode)
 
-(defface ruler-mode-fringes-face
+(defface ruler-mode-fringes
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "green"
                )))
   "Face used to highlight fringes areas."
   :group 'ruler-mode)
 
-(defface ruler-mode-column-number-face
+(defface ruler-mode-column-number
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "black"
                )))
   "Face used to highlight number graduations."
   :group 'ruler-mode)
 
-(defface ruler-mode-fill-column-face
+(defface ruler-mode-fill-column
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "red"
                )))
   "Face used to highlight the fill column character."
   :group 'ruler-mode)
 
-(defface ruler-mode-comment-column-face
+(defface ruler-mode-comment-column
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "red"
                )))
   "Face used to highlight the comment column character."
   :group 'ruler-mode)
 
-(defface ruler-mode-goal-column-face
+(defface ruler-mode-goal-column
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "red"
                )))
   "Face used to highlight the goal column character."
   :group 'ruler-mode)
 
-(defface ruler-mode-tab-stop-face
+(defface ruler-mode-tab-stop
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :foreground "steelblue"
                )))
   "Face used to highlight tab stop characters."
   :group 'ruler-mode)
 
-(defface ruler-mode-current-column-face
+(defface ruler-mode-current-column
   '((t
-     (:inherit ruler-mode-default-face
+     (:inherit ruler-mode-default
                :weight bold
                :foreground "yellow"
                )))
   "Face used to highlight the `current-column' character."
   :group 'ruler-mode)
 \f
-(defmacro ruler-mode-left-fringe-cols ()
-  "Return the width, measured in columns, of the left fringe area."
-  '(ceiling (or (car (window-fringes)) 0)
-            (frame-char-width)))
-
-(defmacro ruler-mode-right-fringe-cols ()
-  "Return the width, measured in columns, of the right fringe area."
-  '(ceiling (or (nth 1 (window-fringes)) 0)
-            (frame-char-width)))
-
-(defun ruler-mode-left-scroll-bar-cols ()
-  "Return the width, measured in columns, of the right vertical scrollbar."
-  (let* ((wsb   (window-scroll-bars))
-         (vtype (nth 2 wsb))
-         (cols  (nth 1 wsb)))
-    (if (or (eq vtype 'left)
-            (and (eq vtype t)
-                 (eq (frame-parameter nil 'vertical-scroll-bars) 'left)))
-        (or cols
-            (ceiling
-             ;; nil means it's a non-toolkit scroll bar,
-             ;; and its width in columns is 14 pixels rounded up.
-             (or (frame-parameter nil 'scroll-bar-width) 14)
-             ;; Always round up to multiple of columns.
-             (frame-char-width)))
-      0)))
-
-(defun ruler-mode-right-scroll-bar-cols ()
-  "Return the width, measured in columns, of the right vertical scrollbar."
-  (let* ((wsb   (window-scroll-bars))
-         (vtype (nth 2 wsb))
-         (cols  (nth 1 wsb)))
-    (if (or (eq vtype 'right)
-            (and (eq vtype t)
-                 (eq (frame-parameter nil 'vertical-scroll-bars) 'right)))
-        (or cols
-            (ceiling
-             ;; nil means it's a non-toolkit scroll bar,
-             ;; and its width in columns is 14 pixels rounded up.
-             (or (frame-parameter nil 'scroll-bar-width) 14)
-             ;; Always round up to multiple of columns.
-             (frame-char-width)))
-      0)))
 
 (defsubst ruler-mode-full-window-width ()
   "Return the full width of the selected window."
@@ -349,8 +312,8 @@ N is a column number relative to selected frame."
   (- n
      (car (window-edges))
      (or (car (window-margins)) 0)
-     (ruler-mode-left-fringe-cols)
-     (ruler-mode-left-scroll-bar-cols)))
+     (fringe-columns 'left)
+     (scroll-bar-columns 'left)))
 \f
 (defun ruler-mode-mouse-set-left-margin (start-event)
   "Set left margin end to the graduation where the mouse pointer is on.
@@ -363,10 +326,10 @@ START-EVENT is the mouse click event."
       (save-selected-window
         (select-window (posn-window start))
         (setq col (- (car (posn-col-row start)) (car (window-edges))
-                     (ruler-mode-left-scroll-bar-cols))
+                     (scroll-bar-columns 'left))
               w   (- (ruler-mode-full-window-width)
-                     (ruler-mode-left-scroll-bar-cols)
-                     (ruler-mode-right-scroll-bar-cols)))
+                     (scroll-bar-columns 'left)
+                     (scroll-bar-columns 'right)))
         (when (and (>= col 0) (< col w))
           (setq lm (window-margins)
                 rm (or (cdr lm) 0)
@@ -385,10 +348,10 @@ START-EVENT is the mouse click event."
       (save-selected-window
         (select-window (posn-window start))
         (setq col (- (car (posn-col-row start)) (car (window-edges))
-                     (ruler-mode-left-scroll-bar-cols))
+                     (scroll-bar-columns 'left))
               w   (- (ruler-mode-full-window-width)
-                     (ruler-mode-left-scroll-bar-cols)
-                     (ruler-mode-right-scroll-bar-cols)))
+                     (scroll-bar-columns 'left)
+                     (scroll-bar-columns 'right)))
         (when (and (>= col 0) (< col w))
           (setq lm  (window-margins)
                 rm  (or (cdr lm) 0)
@@ -457,7 +420,7 @@ dragging.  See also the variable `ruler-mode-dragged-symbol'."
          (message "Goal column set to %d (click on %s again to unset it)"
                   newc
                   (propertize (char-to-string ruler-mode-goal-column-char)
-                              'face 'ruler-mode-goal-column-face))
+                              'face 'ruler-mode-goal-column))
          nil) ;; Don't start dragging.
         )
        (if (eq 'click (ruler-mode-mouse-drag-any-column-iteration
@@ -569,11 +532,15 @@ START-EVENT is the mouse click event."
 
 (defvar ruler-mode-header-line-format-old nil
   "Hold previous value of `header-line-format'.")
-(make-variable-buffer-local 'ruler-mode-header-line-format-old)
+
+(defvar ruler-mode-ruler-function 'ruler-mode-ruler
+  "Function to call to return ruler header line format.
+This variable is expected to be made buffer-local by modes.")
 
 (defconst ruler-mode-header-line-format
-  '(:eval (ruler-mode-ruler))
-  "`header-line-format' used in ruler mode.")
+  '(:eval (funcall ruler-mode-ruler-function))
+  "`header-line-format' used in ruler mode.
+Call `ruler-mode-ruler-function' to compute the ruler value.")
 
 ;;;###autoload
 (define-minor-mode ruler-mode
@@ -586,18 +553,18 @@ START-EVENT is the mouse click event."
         ;; When `ruler-mode' is on save previous header line format
         ;; and install the ruler header line format.
         (when (local-variable-p 'header-line-format)
-          (setq ruler-mode-header-line-format-old header-line-format))
+          (set (make-local-variable 'ruler-mode-header-line-format-old)
+               header-line-format))
         (setq header-line-format ruler-mode-header-line-format)
-        (add-hook 'post-command-hook    ; add local hook
-                  #'force-mode-line-update nil t))
+        (add-hook 'post-command-hook 'force-mode-line-update nil t))
     ;; When `ruler-mode' is off restore previous header line format if
     ;; the current one is the ruler header line format.
     (when (eq header-line-format ruler-mode-header-line-format)
       (kill-local-variable 'header-line-format)
       (when (local-variable-p 'ruler-mode-header-line-format-old)
-        (setq header-line-format ruler-mode-header-line-format-old)))
-    (remove-hook 'post-command-hook     ; remove local hook
-                 #'force-mode-line-update t)))
+        (setq header-line-format ruler-mode-header-line-format-old)
+        (kill-local-variable 'ruler-mode-header-line-format-old)))
+    (remove-hook 'post-command-hook 'force-mode-line-update t)))
 \f
 ;; Add ruler-mode to the minor mode menu in the mode line
 (define-key mode-line-mode-menu [ruler-mode]
@@ -647,143 +614,137 @@ mouse-2: unset goal column"
 (defconst ruler-mode-fringe-help-echo
   "%s fringe %S"
   "Help string shown when mouse is over a fringe area.")
+
+(defsubst ruler-mode-space (width &rest props)
+  "Return a single space string of WIDTH times the normal character width.
+Optional argument PROPS specifies other text properties to apply."
+  (apply 'propertize " " 'display (list 'space :width width) props))
 \f
 (defun ruler-mode-ruler ()
-  "Return a string ruler."
-  (when ruler-mode
-    (let* ((fullw (ruler-mode-full-window-width))
-           (w     (window-width))
-           (m     (window-margins))
-           (lsb   (ruler-mode-left-scroll-bar-cols))
-           (lf    (ruler-mode-left-fringe-cols))
-           (lm    (or (car m) 0))
-           (rsb   (ruler-mode-right-scroll-bar-cols))
-           (rf    (ruler-mode-right-fringe-cols))
-           (rm    (or (cdr m) 0))
-           (ruler (make-string fullw ruler-mode-basic-graduation-char))
-           (o     (+ lsb lf lm))
-           (x     0)
-           (i     o)
-           (j     (window-hscroll))
-           k c l1 l2 r2 r1 h1 h2 f1 f2)
-
-      ;; Setup the default properties.
-      (put-text-property 0 fullw 'face 'ruler-mode-default-face ruler)
-      (put-text-property 0 fullw
-                         'help-echo
-                         (cond
-                          (ruler-mode-show-tab-stops
-                           ruler-mode-ruler-help-echo-when-tab-stops)
-                          (goal-column
-                           ruler-mode-ruler-help-echo-when-goal-column)
-                          (t
-                           ruler-mode-ruler-help-echo))
-                         ruler)
-      ;; Setup the local map.
-      (put-text-property 0 fullw 'local-map ruler-mode-map ruler)
-
-      ;; Setup the active area.
-      (while (< x w)
-        ;; Graduations.
-        (cond
-         ;; Show a number graduation.
-         ((= (mod j 10) 0)
-          (setq c (number-to-string (/ j 10))
-                m (length c)
-                k i)
-          (put-text-property
-           i (1+ i) 'face 'ruler-mode-column-number-face
-           ruler)
-          (while (and (> m 0) (>= k 0))
-            (aset ruler k (aref c (setq m (1- m))))
-            (setq k (1- k))))
-         ;; Show an intermediate graduation.
-         ((= (mod j 5) 0)
-          (aset ruler i ruler-mode-inter-graduation-char)))
-        ;; Special columns.
-        (cond
-         ;; Show the `current-column' marker.
-         ((= j (current-column))
-          (aset ruler i ruler-mode-current-column-char)
-          (put-text-property
-           i (1+ i) 'face 'ruler-mode-current-column-face
-           ruler))
-         ;; Show the `goal-column' marker.
-         ((and goal-column (= j goal-column))
-          (aset ruler i ruler-mode-goal-column-char)
-          (put-text-property
-           i (1+ i) 'face 'ruler-mode-goal-column-face
-           ruler)
-          (put-text-property
-           i (1+ i) 'help-echo ruler-mode-goal-column-help-echo
-           ruler))
-         ;; Show the `comment-column' marker.
-         ((= j comment-column)
-          (aset ruler i ruler-mode-comment-column-char)
-          (put-text-property
-           i (1+ i) 'face 'ruler-mode-comment-column-face
-           ruler)
-          (put-text-property
-           i (1+ i) 'help-echo ruler-mode-comment-column-help-echo
-           ruler))
-         ;; Show the `fill-column' marker.
-         ((= j fill-column)
-          (aset ruler i ruler-mode-fill-column-char)
-          (put-text-property
-           i (1+ i) 'face 'ruler-mode-fill-column-face
-           ruler)
-          (put-text-property
-           i (1+ i) 'help-echo ruler-mode-fill-column-help-echo
-           ruler))
-         ;; Show the `tab-stop-list' markers.
-         ((and ruler-mode-show-tab-stops (member j tab-stop-list))
-          (aset ruler i ruler-mode-tab-stop-char)
-          (put-text-property
-           i (1+ i) 'face 'ruler-mode-tab-stop-face
-           ruler)))
-        (setq i (1+ i)
-              j (1+ j)
-              x (1+ x)))
-
-      ;; Highlight the fringes and margins.
-      (if (nth 2 (window-fringes))
-          ;; fringes outside margins.
-          (setq l1 lf
-                l2 lm
-                r2 rm
-                r1 rf
-                h1 ruler-mode-fringe-help-echo
-                h2 ruler-mode-margin-help-echo
-                f1 'ruler-mode-fringes-face
-                f2 'ruler-mode-margins-face)
-        ;; fringes inside margins.
-        (setq l1 lm
-              l2 lf
-              r2 rf
-              r1 rm
-              h1 ruler-mode-margin-help-echo
-              h2 ruler-mode-fringe-help-echo
-              f1 'ruler-mode-margins-face
-              f2 'ruler-mode-fringes-face))
-      (setq i lsb j (+ i l1))
-      (put-text-property i j 'face f1 ruler)
-      (put-text-property i j 'help-echo (format h1 "Left" l1) ruler)
-      (setq i j j (+ i l2))
-      (put-text-property i j 'face f2 ruler)
-      (put-text-property i j 'help-echo (format h2 "Left" l2) ruler)
-      (setq i (+ o w) j (+ i r2))
-      (put-text-property i j 'face f2 ruler)
-      (put-text-property i j 'help-echo (format h2 "Right" r2) ruler)
-      (setq i j j (+ i r1))
-      (put-text-property i j 'face f1 ruler)
-      (put-text-property i j 'help-echo (format h1 "Right" r1) ruler)
-
-      ;; Show inactive areas.
-      (put-text-property 0 lsb   'face 'ruler-mode-pad-face ruler)
-      (put-text-property j fullw 'face 'ruler-mode-pad-face ruler)
-
-      ;; Return the ruler propertized string.
-      ruler)))
+  "Compute and return an header line ruler."
+  (let* ((w (window-width))
+         (m (window-margins))
+         (f (window-fringes))
+         (i 0)
+         (j (window-hscroll))
+         ;; Setup the scrollbar, fringes, and margins areas.
+         (lf (ruler-mode-space
+              'left-fringe
+              'face 'ruler-mode-fringes
+              'help-echo (format ruler-mode-fringe-help-echo
+                                 "Left" (or (car f) 0))))
+         (rf (ruler-mode-space
+              'right-fringe
+              'face 'ruler-mode-fringes
+              'help-echo (format ruler-mode-fringe-help-echo
+                                 "Right" (or (cadr f) 0))))
+         (lm (ruler-mode-space
+              'left-margin
+              'face 'ruler-mode-margins
+              'help-echo (format ruler-mode-margin-help-echo
+                                 "Left" (or (car m) 0))))
+         (rm (ruler-mode-space
+              'right-margin
+              'face 'ruler-mode-margins
+              'help-echo (format ruler-mode-margin-help-echo
+                                 "Right" (or (cdr m) 0))))
+         (sb (ruler-mode-space
+              'scroll-bar
+              'face 'ruler-mode-pad))
+         ;; Remember the scrollbar vertical type.
+         (sbvt (car (window-current-scroll-bars)))
+         ;; Create an "clean" ruler.
+         (ruler
+          (propertize
+           (make-string w ruler-mode-basic-graduation-char)
+           'face 'ruler-mode-default
+           'local-map ruler-mode-map
+           'help-echo (cond
+                       (ruler-mode-show-tab-stops
+                        ruler-mode-ruler-help-echo-when-tab-stops)
+                       (goal-column
+                        ruler-mode-ruler-help-echo-when-goal-column)
+                       (ruler-mode-ruler-help-echo))))
+         k c)
+    ;; Setup the active area.
+    (while (< i w)
+      ;; Graduations.
+      (cond
+       ;; Show a number graduation.
+       ((= (mod j 10) 0)
+        (setq c (number-to-string (/ j 10))
+              m (length c)
+              k i)
+        (put-text-property
+         i (1+ i) 'face 'ruler-mode-column-number
+         ruler)
+        (while (and (> m 0) (>= k 0))
+          (aset ruler k (aref c (setq m (1- m))))
+          (setq k (1- k))))
+       ;; Show an intermediate graduation.
+       ((= (mod j 5) 0)
+        (aset ruler i ruler-mode-inter-graduation-char)))
+      ;; Special columns.
+      (cond
+       ;; Show the `current-column' marker.
+       ((= j (current-column))
+        (aset ruler i ruler-mode-current-column-char)
+        (put-text-property
+         i (1+ i) 'face 'ruler-mode-current-column
+         ruler))
+       ;; Show the `goal-column' marker.
+       ((and goal-column (= j goal-column))
+        (aset ruler i ruler-mode-goal-column-char)
+        (put-text-property
+         i (1+ i) 'face 'ruler-mode-goal-column
+         ruler)
+       (put-text-property
+         i (1+ i) 'mouse-face 'mode-line-highlight
+         ruler)
+        (put-text-property
+         i (1+ i) 'help-echo ruler-mode-goal-column-help-echo
+         ruler))
+       ;; Show the `comment-column' marker.
+       ((= j comment-column)
+        (aset ruler i ruler-mode-comment-column-char)
+        (put-text-property
+         i (1+ i) 'face 'ruler-mode-comment-column
+         ruler)
+       (put-text-property
+         i (1+ i) 'mouse-face 'mode-line-highlight
+         ruler)
+        (put-text-property
+         i (1+ i) 'help-echo ruler-mode-comment-column-help-echo
+         ruler))
+       ;; Show the `fill-column' marker.
+       ((= j fill-column)
+        (aset ruler i ruler-mode-fill-column-char)
+        (put-text-property
+         i (1+ i) 'face 'ruler-mode-fill-column
+         ruler)
+       (put-text-property
+         i (1+ i) 'mouse-face 'mode-line-highlight
+         ruler)
+        (put-text-property
+         i (1+ i) 'help-echo ruler-mode-fill-column-help-echo
+         ruler))
+       ;; Show the `tab-stop-list' markers.
+       ((and ruler-mode-show-tab-stops (member j tab-stop-list))
+        (aset ruler i ruler-mode-tab-stop-char)
+        (put-text-property
+         i (1+ i) 'face 'ruler-mode-tab-stop
+         ruler)))
+      (setq i (1+ i)
+            j (1+ j)))
+    ;; Return the ruler propertized string.  Using list here,
+    ;; instead of concat visually separate the different areas.
+    (if (nth 2 (window-fringes))
+        ;; fringes outside margins.
+        (list "" (and (eq 'left sbvt) sb) lf lm
+              ruler rm rf (and (eq 'right sbvt) sb))
+      ;; fringes inside margins.
+      (list "" (and (eq 'left sbvt) sb) lm lf
+            ruler rf rm (and (eq 'right sbvt) sb)))))
 
 (provide 'ruler-mode)