comparison lisp/ruler-mode.el @ 89909:68c22ea6027c

Sync to HEAD
author Kenichi Handa <handa@m17n.org>
date Fri, 16 Apr 2004 12:51:06 +0000
parents 2f877ed80fa6
children 3ebd9bdb4fe5
comparison
equal deleted inserted replaced
89908:ee1402f7b568 89909:68c22ea6027c
1 ;;; ruler-mode.el --- display a ruler in the header line 1 ;;; ruler-mode.el --- display a ruler in the header line
2 2
3 ;; Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. 3 ;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 4
5 ;; Author: David Ponce <david@dponce.com> 5 ;; Author: David Ponce <david@dponce.com>
6 ;; Maintainer: David Ponce <david@dponce.com> 6 ;; Maintainer: David Ponce <david@dponce.com>
7 ;; Created: 24 Mar 2001 7 ;; Created: 24 Mar 2001
8 ;; Version: 1.6 8 ;; Version: 1.6
92 ;; All `ruler-mode' faces inherit from `ruler-mode-default-face'. 92 ;; All `ruler-mode' faces inherit from `ruler-mode-default-face'.
93 ;; 93 ;;
94 ;; WARNING: To keep ruler graduations aligned on text columns it is 94 ;; WARNING: To keep ruler graduations aligned on text columns it is
95 ;; important to use the same font family and size for ruler and text 95 ;; important to use the same font family and size for ruler and text
96 ;; areas. 96 ;; areas.
97 ;;
98 ;; You can override the ruler format by defining an appropriate
99 ;; function as the buffer-local value of `ruler-mode-ruler-function'.
97 100
98 ;; Installation 101 ;; Installation
99 ;; 102 ;;
100 ;; To automatically display the ruler in specific major modes use: 103 ;; To automatically display the ruler in specific major modes use:
101 ;; 104 ;;
106 ;; 109 ;;
107 110
108 ;;; Code: 111 ;;; Code:
109 (eval-when-compile 112 (eval-when-compile
110 (require 'wid-edit)) 113 (require 'wid-edit))
114 (require 'scroll-bar)
115 (require 'fringe)
111 116
112 (defgroup ruler-mode nil 117 (defgroup ruler-mode nil
113 "Display a ruler in the header line." 118 "Display a ruler in the header line."
114 :version "21.4" 119 :version "21.4"
115 :group 'convenience) 120 :group 'convenience)
132 (unless (characterp value) 137 (unless (characterp value)
133 (widget-put widget :error 138 (widget-put widget :error
134 (format "Invalid character value: %S" value)) 139 (format "Invalid character value: %S" value))
135 widget)))) 140 widget))))
136 141
137 (defcustom ruler-mode-fill-column-char (if window-system 142 (defcustom ruler-mode-fill-column-char (if (char-displayable-p ?¶)
138 ?\¶ 143 ?\¶
139 ?\|) 144 ?\|)
140 "*Character used at the `fill-column' location." 145 "*Character used at the `fill-column' location."
141 :group 'ruler-mode 146 :group 'ruler-mode
142 :type '(choice 147 :type '(choice
158 :type '(choice 163 :type '(choice
159 (character :tag "Character") 164 (character :tag "Character")
160 (integer :tag "Integer char value" 165 (integer :tag "Integer char value"
161 :validate ruler-mode-character-validate))) 166 :validate ruler-mode-character-validate)))
162 167
163 (defcustom ruler-mode-current-column-char (if window-system 168 (defcustom ruler-mode-current-column-char (if (char-displayable-p ?¦)
164 ?\¦ 169 ?\¦
165 ?\@) 170 ?\@)
166 "*Character used at the `current-column' location." 171 "*Character used at the `current-column' location."
167 :group 'ruler-mode 172 :group 'ruler-mode
168 :type '(choice 173 :type '(choice
291 :foreground "yellow" 296 :foreground "yellow"
292 ))) 297 )))
293 "Face used to highlight the `current-column' character." 298 "Face used to highlight the `current-column' character."
294 :group 'ruler-mode) 299 :group 'ruler-mode)
295 300
296 (defmacro ruler-mode-left-fringe-cols ()
297 "Return the width, measured in columns, of the left fringe area."
298 '(ceiling (or (car (window-fringes)) 0)
299 (frame-char-width)))
300
301 (defmacro ruler-mode-right-fringe-cols ()
302 "Return the width, measured in columns, of the right fringe area."
303 '(ceiling (or (nth 1 (window-fringes)) 0)
304 (frame-char-width)))
305
306 (defun ruler-mode-left-scroll-bar-cols ()
307 "Return the width, measured in columns, of the right vertical scrollbar."
308 (let* ((wsb (window-scroll-bars))
309 (vtype (nth 2 wsb))
310 (cols (nth 1 wsb)))
311 (if (or (eq vtype 'left)
312 (and (eq vtype t)
313 (eq (frame-parameter nil 'vertical-scroll-bars) 'left)))
314 (or cols
315 (ceiling
316 ;; nil means it's a non-toolkit scroll bar,
317 ;; and its width in columns is 14 pixels rounded up.
318 (or (frame-parameter nil 'scroll-bar-width) 14)
319 ;; Always round up to multiple of columns.
320 (frame-char-width)))
321 0)))
322
323 (defun ruler-mode-right-scroll-bar-cols ()
324 "Return the width, measured in columns, of the right vertical scrollbar."
325 (let* ((wsb (window-scroll-bars))
326 (vtype (nth 2 wsb))
327 (cols (nth 1 wsb)))
328 (if (or (eq vtype 'right)
329 (and (eq vtype t)
330 (eq (frame-parameter nil 'vertical-scroll-bars) 'right)))
331 (or cols
332 (ceiling
333 ;; nil means it's a non-toolkit scroll bar,
334 ;; and its width in columns is 14 pixels rounded up.
335 (or (frame-parameter nil 'scroll-bar-width) 14)
336 ;; Always round up to multiple of columns.
337 (frame-char-width)))
338 0)))
339 301
340 (defsubst ruler-mode-full-window-width () 302 (defsubst ruler-mode-full-window-width ()
341 "Return the full width of the selected window." 303 "Return the full width of the selected window."
342 (let ((edges (window-edges))) 304 (let ((edges (window-edges)))
343 (- (nth 2 edges) (nth 0 edges)))) 305 (- (nth 2 edges) (nth 0 edges))))
346 "Return a column number relative to the selected window. 308 "Return a column number relative to the selected window.
347 N is a column number relative to selected frame." 309 N is a column number relative to selected frame."
348 (- n 310 (- n
349 (car (window-edges)) 311 (car (window-edges))
350 (or (car (window-margins)) 0) 312 (or (car (window-margins)) 0)
351 (ruler-mode-left-fringe-cols) 313 (fringe-columns 'left)
352 (ruler-mode-left-scroll-bar-cols))) 314 (scroll-bar-columns 'left)))
353 315
354 (defun ruler-mode-mouse-set-left-margin (start-event) 316 (defun ruler-mode-mouse-set-left-margin (start-event)
355 "Set left margin end to the graduation where the mouse pointer is on. 317 "Set left margin end to the graduation where the mouse pointer is on.
356 START-EVENT is the mouse click event." 318 START-EVENT is the mouse click event."
357 (interactive "e") 319 (interactive "e")
360 col w lm rm) 322 col w lm rm)
361 (when (eq start end) ;; mouse click 323 (when (eq start end) ;; mouse click
362 (save-selected-window 324 (save-selected-window
363 (select-window (posn-window start)) 325 (select-window (posn-window start))
364 (setq col (- (car (posn-col-row start)) (car (window-edges)) 326 (setq col (- (car (posn-col-row start)) (car (window-edges))
365 (ruler-mode-left-scroll-bar-cols)) 327 (scroll-bar-columns 'left))
366 w (- (ruler-mode-full-window-width) 328 w (- (ruler-mode-full-window-width)
367 (ruler-mode-left-scroll-bar-cols) 329 (scroll-bar-columns 'left)
368 (ruler-mode-right-scroll-bar-cols))) 330 (scroll-bar-columns 'right)))
369 (when (and (>= col 0) (< col w)) 331 (when (and (>= col 0) (< col w))
370 (setq lm (window-margins) 332 (setq lm (window-margins)
371 rm (or (cdr lm) 0) 333 rm (or (cdr lm) 0)
372 lm (or (car lm) 0)) 334 lm (or (car lm) 0))
373 (message "Left margin set to %d (was %d)" col lm) 335 (message "Left margin set to %d (was %d)" col lm)
382 col w lm rm) 344 col w lm rm)
383 (when (eq start end) ;; mouse click 345 (when (eq start end) ;; mouse click
384 (save-selected-window 346 (save-selected-window
385 (select-window (posn-window start)) 347 (select-window (posn-window start))
386 (setq col (- (car (posn-col-row start)) (car (window-edges)) 348 (setq col (- (car (posn-col-row start)) (car (window-edges))
387 (ruler-mode-left-scroll-bar-cols)) 349 (scroll-bar-columns 'left))
388 w (- (ruler-mode-full-window-width) 350 w (- (ruler-mode-full-window-width)
389 (ruler-mode-left-scroll-bar-cols) 351 (scroll-bar-columns 'left)
390 (ruler-mode-right-scroll-bar-cols))) 352 (scroll-bar-columns 'right)))
391 (when (and (>= col 0) (< col w)) 353 (when (and (>= col 0) (< col w))
392 (setq lm (window-margins) 354 (setq lm (window-margins)
393 rm (or (cdr lm) 0) 355 rm (or (cdr lm) 0)
394 lm (or (car lm) 0) 356 lm (or (car lm) 0)
395 col (- w col 1)) 357 col (- w col 1))
566 km) 528 km)
567 "Keymap for ruler minor mode.") 529 "Keymap for ruler minor mode.")
568 530
569 (defvar ruler-mode-header-line-format-old nil 531 (defvar ruler-mode-header-line-format-old nil
570 "Hold previous value of `header-line-format'.") 532 "Hold previous value of `header-line-format'.")
571 (make-variable-buffer-local 'ruler-mode-header-line-format-old) 533
534 (defvar ruler-mode-ruler-function 'ruler-mode-ruler
535 "Function to call to return ruler header line format.
536 This variable is expected to be made buffer-local by modes.")
572 537
573 (defconst ruler-mode-header-line-format 538 (defconst ruler-mode-header-line-format
574 '(:eval (ruler-mode-ruler)) 539 '(:eval (funcall ruler-mode-ruler-function))
575 "`header-line-format' used in ruler mode.") 540 "`header-line-format' used in ruler mode.
541 Call `ruler-mode-ruler-function' to compute the ruler value.")
576 542
577 ;;;###autoload 543 ;;;###autoload
578 (define-minor-mode ruler-mode 544 (define-minor-mode ruler-mode
579 "Display a ruler in the header line if ARG > 0." 545 "Display a ruler in the header line if ARG > 0."
580 nil nil 546 nil nil
583 (if ruler-mode 549 (if ruler-mode
584 (progn 550 (progn
585 ;; When `ruler-mode' is on save previous header line format 551 ;; When `ruler-mode' is on save previous header line format
586 ;; and install the ruler header line format. 552 ;; and install the ruler header line format.
587 (when (local-variable-p 'header-line-format) 553 (when (local-variable-p 'header-line-format)
588 (setq ruler-mode-header-line-format-old header-line-format)) 554 (set (make-local-variable 'ruler-mode-header-line-format-old)
555 header-line-format))
589 (setq header-line-format ruler-mode-header-line-format) 556 (setq header-line-format ruler-mode-header-line-format)
590 (add-hook 'post-command-hook ; add local hook 557 (add-hook 'post-command-hook 'force-mode-line-update nil t))
591 #'force-mode-line-update nil t))
592 ;; When `ruler-mode' is off restore previous header line format if 558 ;; When `ruler-mode' is off restore previous header line format if
593 ;; the current one is the ruler header line format. 559 ;; the current one is the ruler header line format.
594 (when (eq header-line-format ruler-mode-header-line-format) 560 (when (eq header-line-format ruler-mode-header-line-format)
595 (kill-local-variable 'header-line-format) 561 (kill-local-variable 'header-line-format)
596 (when (local-variable-p 'ruler-mode-header-line-format-old) 562 (when (local-variable-p 'ruler-mode-header-line-format-old)
597 (setq header-line-format ruler-mode-header-line-format-old))) 563 (setq header-line-format ruler-mode-header-line-format-old)
598 (remove-hook 'post-command-hook ; remove local hook 564 (kill-local-variable 'ruler-mode-header-line-format-old)))
599 #'force-mode-line-update t))) 565 (remove-hook 'post-command-hook 'force-mode-line-update t)))
600 566
601 ;; Add ruler-mode to the minor mode menu in the mode line 567 ;; Add ruler-mode to the minor mode menu in the mode line
602 (define-key mode-line-mode-menu [ruler-mode] 568 (define-key mode-line-mode-menu [ruler-mode]
603 `(menu-item "Ruler" ruler-mode 569 `(menu-item "Ruler" ruler-mode
604 :button (:toggle . ruler-mode))) 570 :button (:toggle . ruler-mode)))
644 "Help string shown when mouse is over a margin area.") 610 "Help string shown when mouse is over a margin area.")
645 611
646 (defconst ruler-mode-fringe-help-echo 612 (defconst ruler-mode-fringe-help-echo
647 "%s fringe %S" 613 "%s fringe %S"
648 "Help string shown when mouse is over a fringe area.") 614 "Help string shown when mouse is over a fringe area.")
615
616 (defsubst ruler-mode-space (width &rest props)
617 "Return a single space string of WIDTH times the normal character width.
618 Optional argument PROPS specifies other text properties to apply."
619 (apply 'propertize " " 'display (list 'space :width width) props))
649 620
650 (defun ruler-mode-ruler () 621 (defun ruler-mode-ruler ()
651 "Return a string ruler." 622 "Compute and return an header line ruler."
652 (when ruler-mode 623 (let* ((w (window-width))
653 (let* ((fullw (ruler-mode-full-window-width)) 624 (m (window-margins))
654 (w (window-width)) 625 (f (window-fringes))
655 (m (window-margins)) 626 (i 0)
656 (lsb (ruler-mode-left-scroll-bar-cols)) 627 (j (window-hscroll))
657 (lf (ruler-mode-left-fringe-cols)) 628 ;; Setup the scrollbar, fringes, and margins areas.
658 (lm (or (car m) 0)) 629 (lf (ruler-mode-space
659 (rsb (ruler-mode-right-scroll-bar-cols)) 630 'left-fringe
660 (rf (ruler-mode-right-fringe-cols)) 631 'face 'ruler-mode-fringes-face
661 (rm (or (cdr m) 0)) 632 'help-echo (format ruler-mode-fringe-help-echo
662 (ruler (make-string fullw ruler-mode-basic-graduation-char)) 633 "Left" (or (car f) 0))))
663 (o (+ lsb lf lm)) 634 (rf (ruler-mode-space
664 (x 0) 635 'right-fringe
665 (i o) 636 'face 'ruler-mode-fringes-face
666 (j (window-hscroll)) 637 'help-echo (format ruler-mode-fringe-help-echo
667 k c l1 l2 r2 r1 h1 h2 f1 f2) 638 "Right" (or (cadr f) 0))))
668 639 (lm (ruler-mode-space
669 ;; Setup the default properties. 640 'left-margin
670 (put-text-property 0 fullw 'face 'ruler-mode-default-face ruler) 641 'face 'ruler-mode-margins-face
671 (put-text-property 0 fullw 642 'help-echo (format ruler-mode-margin-help-echo
672 'help-echo 643 "Left" (or (car m) 0))))
673 (cond 644 (rm (ruler-mode-space
674 (ruler-mode-show-tab-stops 645 'right-margin
675 ruler-mode-ruler-help-echo-when-tab-stops) 646 'face 'ruler-mode-margins-face
676 (goal-column 647 'help-echo (format ruler-mode-margin-help-echo
677 ruler-mode-ruler-help-echo-when-goal-column) 648 "Right" (or (cdr m) 0))))
678 (t 649 (sb (ruler-mode-space
679 ruler-mode-ruler-help-echo)) 650 'scroll-bar
680 ruler) 651 'face 'ruler-mode-pad-face))
681 ;; Setup the local map. 652 ;; Remember the scrollbar vertical type.
682 (put-text-property 0 fullw 'local-map ruler-mode-map ruler) 653 (sbvt (car (window-current-scroll-bars)))
683 654 ;; Create an "clean" ruler.
684 ;; Setup the active area. 655 (ruler
685 (while (< x w) 656 (propertize
686 ;; Graduations. 657 (make-string w ruler-mode-basic-graduation-char)
687 (cond 658 'face 'ruler-mode-default-face
688 ;; Show a number graduation. 659 'local-map ruler-mode-map
689 ((= (mod j 10) 0) 660 'help-echo (cond
690 (setq c (number-to-string (/ j 10)) 661 (ruler-mode-show-tab-stops
691 m (length c) 662 ruler-mode-ruler-help-echo-when-tab-stops)
692 k i) 663 (goal-column
693 (put-text-property 664 ruler-mode-ruler-help-echo-when-goal-column)
694 i (1+ i) 'face 'ruler-mode-column-number-face 665 (ruler-mode-ruler-help-echo))))
695 ruler) 666 k c)
696 (while (and (> m 0) (>= k 0)) 667 ;; Setup the active area.
697 (aset ruler k (aref c (setq m (1- m)))) 668 (while (< i w)
698 (setq k (1- k)))) 669 ;; Graduations.
699 ;; Show an intermediate graduation. 670 (cond
700 ((= (mod j 5) 0) 671 ;; Show a number graduation.
701 (aset ruler i ruler-mode-inter-graduation-char))) 672 ((= (mod j 10) 0)
702 ;; Special columns. 673 (setq c (number-to-string (/ j 10))
703 (cond 674 m (length c)
704 ;; Show the `current-column' marker. 675 k i)
705 ((= j (current-column)) 676 (put-text-property
706 (aset ruler i ruler-mode-current-column-char) 677 i (1+ i) 'face 'ruler-mode-column-number-face
707 (put-text-property 678 ruler)
708 i (1+ i) 'face 'ruler-mode-current-column-face 679 (while (and (> m 0) (>= k 0))
709 ruler)) 680 (aset ruler k (aref c (setq m (1- m))))
710 ;; Show the `goal-column' marker. 681 (setq k (1- k))))
711 ((and goal-column (= j goal-column)) 682 ;; Show an intermediate graduation.
712 (aset ruler i ruler-mode-goal-column-char) 683 ((= (mod j 5) 0)
713 (put-text-property 684 (aset ruler i ruler-mode-inter-graduation-char)))
714 i (1+ i) 'face 'ruler-mode-goal-column-face 685 ;; Special columns.
715 ruler) 686 (cond
716 (put-text-property 687 ;; Show the `current-column' marker.
717 i (1+ i) 'help-echo ruler-mode-goal-column-help-echo 688 ((= j (current-column))
718 ruler)) 689 (aset ruler i ruler-mode-current-column-char)
719 ;; Show the `comment-column' marker. 690 (put-text-property
720 ((= j comment-column) 691 i (1+ i) 'face 'ruler-mode-current-column-face
721 (aset ruler i ruler-mode-comment-column-char) 692 ruler))
722 (put-text-property 693 ;; Show the `goal-column' marker.
723 i (1+ i) 'face 'ruler-mode-comment-column-face 694 ((and goal-column (= j goal-column))
724 ruler) 695 (aset ruler i ruler-mode-goal-column-char)
725 (put-text-property 696 (put-text-property
726 i (1+ i) 'help-echo ruler-mode-comment-column-help-echo 697 i (1+ i) 'face 'ruler-mode-goal-column-face
727 ruler)) 698 ruler)
728 ;; Show the `fill-column' marker. 699 (put-text-property
729 ((= j fill-column) 700 i (1+ i) 'help-echo ruler-mode-goal-column-help-echo
730 (aset ruler i ruler-mode-fill-column-char) 701 ruler))
731 (put-text-property 702 ;; Show the `comment-column' marker.
732 i (1+ i) 'face 'ruler-mode-fill-column-face 703 ((= j comment-column)
733 ruler) 704 (aset ruler i ruler-mode-comment-column-char)
734 (put-text-property 705 (put-text-property
735 i (1+ i) 'help-echo ruler-mode-fill-column-help-echo 706 i (1+ i) 'face 'ruler-mode-comment-column-face
736 ruler)) 707 ruler)
737 ;; Show the `tab-stop-list' markers. 708 (put-text-property
738 ((and ruler-mode-show-tab-stops (member j tab-stop-list)) 709 i (1+ i) 'help-echo ruler-mode-comment-column-help-echo
739 (aset ruler i ruler-mode-tab-stop-char) 710 ruler))
740 (put-text-property 711 ;; Show the `fill-column' marker.
741 i (1+ i) 'face 'ruler-mode-tab-stop-face 712 ((= j fill-column)
742 ruler))) 713 (aset ruler i ruler-mode-fill-column-char)
743 (setq i (1+ i) 714 (put-text-property
744 j (1+ j) 715 i (1+ i) 'face 'ruler-mode-fill-column-face
745 x (1+ x))) 716 ruler)
746 717 (put-text-property
747 ;; Highlight the fringes and margins. 718 i (1+ i) 'help-echo ruler-mode-fill-column-help-echo
748 (if (nth 2 (window-fringes)) 719 ruler))
749 ;; fringes outside margins. 720 ;; Show the `tab-stop-list' markers.
750 (setq l1 lf 721 ((and ruler-mode-show-tab-stops (member j tab-stop-list))
751 l2 lm 722 (aset ruler i ruler-mode-tab-stop-char)
752 r2 rm 723 (put-text-property
753 r1 rf 724 i (1+ i) 'face 'ruler-mode-tab-stop-face
754 h1 ruler-mode-fringe-help-echo 725 ruler)))
755 h2 ruler-mode-margin-help-echo 726 (setq i (1+ i)
756 f1 'ruler-mode-fringes-face 727 j (1+ j)))
757 f2 'ruler-mode-margins-face) 728 ;; Return the ruler propertized string. Using list here,
758 ;; fringes inside margins. 729 ;; instead of concat visually separate the different areas.
759 (setq l1 lm 730 (if (nth 2 (window-fringes))
760 l2 lf 731 ;; fringes outside margins.
761 r2 rf 732 (list "" (and (eq 'left sbvt) sb) lf lm
762 r1 rm 733 ruler rm rf (and (eq 'right sbvt) sb))
763 h1 ruler-mode-margin-help-echo 734 ;; fringes inside margins.
764 h2 ruler-mode-fringe-help-echo 735 (list "" (and (eq 'left sbvt) sb) lm lf
765 f1 'ruler-mode-margins-face 736 ruler rf rm (and (eq 'right sbvt) sb)))))
766 f2 'ruler-mode-fringes-face))
767 (setq i lsb j (+ i l1))
768 (put-text-property i j 'face f1 ruler)
769 (put-text-property i j 'help-echo (format h1 "Left" l1) ruler)
770 (setq i j j (+ i l2))
771 (put-text-property i j 'face f2 ruler)
772 (put-text-property i j 'help-echo (format h2 "Left" l2) ruler)
773 (setq i (+ o w) j (+ i r2))
774 (put-text-property i j 'face f2 ruler)
775 (put-text-property i j 'help-echo (format h2 "Right" r2) ruler)
776 (setq i j j (+ i r1))
777 (put-text-property i j 'face f1 ruler)
778 (put-text-property i j 'help-echo (format h1 "Right" r1) ruler)
779
780 ;; Show inactive areas.
781 (put-text-property 0 lsb 'face 'ruler-mode-pad-face ruler)
782 (put-text-property j fullw 'face 'ruler-mode-pad-face ruler)
783
784 ;; Return the ruler propertized string.
785 ruler)))
786 737
787 (provide 'ruler-mode) 738 (provide 'ruler-mode)
788 739
789 ;; Local Variables: 740 ;; Local Variables:
790 ;; coding: iso-latin-1 741 ;; coding: iso-latin-1
791 ;; End: 742 ;; End:
792 743
744 ;;; arch-tag: b2f24546-5605-44c4-b67b-c9a4eeba3ee8
793 ;;; ruler-mode.el ends here 745 ;;; ruler-mode.el ends here