]> code.delx.au - gnu-emacs/blobdiff - lisp/scroll-bar.el
(compile-command): Add defvar.
[gnu-emacs] / lisp / scroll-bar.el
index ec02d8c57c9033f7b0839297e960d85c8602f334..1fabb78dc49b2be69b35f62364623e53d188a85e 100644 (file)
@@ -1,6 +1,7 @@
-;;; scroll-bar.el --- window system-independent scroll bar support.
+;;; scroll-bar.el --- window system-independent scroll bar support
 
 
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003,
+;;   2004, 2005 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: hardware
 
 ;; Maintainer: FSF
 ;; Keywords: hardware
@@ -19,8 +20,8 @@
 
 ;; 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
 
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
@@ -53,6 +54,23 @@ that scroll bar position."
   ;; with a large scroll bar portion can easily overflow a lisp int.
   (truncate (/ (* (float (car num-denom)) whole) (cdr num-denom))))
 
   ;; with a large scroll bar portion can easily overflow a lisp int.
   (truncate (/ (* (float (car num-denom)) whole) (cdr num-denom))))
 
+(defun scroll-bar-columns (side)
+  "Return the width, measured in columns, of the vertical scrollbar on SIDE.
+SIDE must be the symbol `left' or `right'."
+  (let* ((wsb   (window-scroll-bars))
+         (vtype (nth 2 wsb))
+         (cols  (nth 1 wsb)))
+    (cond
+     ((not (memq side '(left right)))
+      (error "`left' or `right' expected instead of %S" side))
+     ((and (eq vtype side) cols))
+     ((eq (frame-parameter nil 'vertical-scroll-bars) side)
+      ;; nil means it's a non-toolkit scroll bar, and its width in
+      ;; columns is 14 pixels rounded up.
+      (ceiling (or (frame-parameter nil 'scroll-bar-width) 14)
+               (frame-char-width)))
+     (0))))
+
 \f
 ;;;; Helpful functions for enabling and disabling scroll bars.
 
 \f
 ;;;; Helpful functions for enabling and disabling scroll bars.
 
@@ -62,7 +80,10 @@ that scroll bar position."
   "Non-nil means `set-scroll-bar-mode' should really do something.
 This is nil while loading `scroll-bar.el', and t afterward.")
 
   "Non-nil means `set-scroll-bar-mode' should really do something.
 This is nil while loading `scroll-bar.el', and t afterward.")
 
-(defun set-scroll-bar-mode (ignore value)
+(defun set-scroll-bar-mode-1 (ignore value)
+  (set-scroll-bar-mode value))
+
+(defun set-scroll-bar-mode (value)
   "Set `scroll-bar-mode' to VALUE and put the new value into effect."
   (setq scroll-bar-mode value)
 
   "Set `scroll-bar-mode' to VALUE and put the new value into effect."
   (setq scroll-bar-mode value)
 
@@ -83,38 +104,40 @@ This is nil while loading `scroll-bar.el', and t afterward.")
         (list (cons 'vertical-scroll-bars scroll-bar-mode)))
        (setq frames (cdr frames))))))
 
         (list (cons 'vertical-scroll-bars scroll-bar-mode)))
        (setq frames (cdr frames))))))
 
-(defcustom scroll-bar-mode 'left
+(defcustom scroll-bar-mode default-frame-scroll-bars
   "*Specify whether to have vertical scroll bars, and on which side.
 Possible values are nil (no scroll bars), `left' (scroll bars on left)
 and `right' (scroll bars on right).
   "*Specify whether to have vertical scroll bars, and on which side.
 Possible values are nil (no scroll bars), `left' (scroll bars on left)
 and `right' (scroll bars on right).
-When you set the variable in a Lisp program, it takes effect for new frames,
-and for existing frames when `toggle-scroll-bar' is used.
-When you set this with the customization buffer,
-it takes effect immediately for all frames."
-  :type '(choice (const :tag "none (nil)")
+To set this variable in a Lisp program, use `set-scroll-bar-mode'
+to make it take real effect.
+Setting the variable with a customization buffer also takes effect."
+  :type '(choice (const :tag "none (nil)" nil)
                 (const left)
                 (const right))
   :group 'frames
                 (const left)
                 (const right))
   :group 'frames
-  :set 'set-scroll-bar-mode)
+  ;; The default value for :initialize would try to use :set
+  ;; when processing the file in cus-dep.el.
+  :initialize 'custom-initialize-default
+  :set 'set-scroll-bar-mode-1)
 
 ;; We just set scroll-bar-mode, but that was the default.
 ;; If it is set again, that is for real.
 (setq scroll-bar-mode-explicit t)
 
 
 ;; We just set scroll-bar-mode, but that was the default.
 ;; If it is set again, that is for real.
 (setq scroll-bar-mode-explicit t)
 
-(defun scroll-bar-mode (flag)
+(defun scroll-bar-mode (&optional flag)
   "Toggle display of vertical scroll bars on all frames.
 This command applies to all frames that exist and frames to be
 created in the future.
 With a numeric argument, if the argument is negative,
 turn off scroll bars; otherwise, turn on scroll bars."
   (interactive "P")
   "Toggle display of vertical scroll bars on all frames.
 This command applies to all frames that exist and frames to be
 created in the future.
 With a numeric argument, if the argument is negative,
 turn off scroll bars; otherwise, turn on scroll bars."
   (interactive "P")
-  (if flag (setq flag (prefix-numeric-value flag)))
 
   ;; Tweedle the variable according to the argument.
 
   ;; Tweedle the variable according to the argument.
-  (set-scroll-bar-mode nil
-                      (if (null flag) (not scroll-bar-mode)
-                        (and (or (not (numberp flag)) (>= flag 0))
-                             'left))))
+  (set-scroll-bar-mode (if (if (null flag) 
+                              (not scroll-bar-mode)
+                            (setq flag (prefix-numeric-value flag))
+                            (or (not (numberp flag)) (>= flag 0)))
+                          default-frame-scroll-bars)))
 
 (defun toggle-scroll-bar (arg)
   "Toggle whether or not the selected frame has vertical scroll bars.
 
 (defun toggle-scroll-bar (arg)
   "Toggle whether or not the selected frame has vertical scroll bars.
@@ -126,11 +149,13 @@ when they are turned on; if it is nil, they go on the left."
       (setq arg
            (if (cdr (assq 'vertical-scroll-bars
                           (frame-parameters (selected-frame))))
       (setq arg
            (if (cdr (assq 'vertical-scroll-bars
                           (frame-parameters (selected-frame))))
-               -1 1)))
-  (modify-frame-parameters (selected-frame)
-                          (list (cons 'vertical-scroll-bars
-                                      (if (> arg 0)
-                                          (or scroll-bar-mode 'left))))))
+               -1 1))
+    (setq arg (prefix-numeric-value arg)))
+  (modify-frame-parameters
+   (selected-frame)
+   (list (cons 'vertical-scroll-bars
+              (if (> arg 0)
+                  (or scroll-bar-mode default-frame-scroll-bars))))))
 
 (defun toggle-horizontal-scroll-bar (arg)
   "Toggle whether or not the selected frame has horizontal scroll bars.
 
 (defun toggle-horizontal-scroll-bar (arg)
   "Toggle whether or not the selected frame has horizontal scroll bars.
@@ -186,7 +211,7 @@ EVENT should be a scroll bar click or drag event."
       (setq next-portion-start (max
                                (scroll-bar-drag-position next-portion-whole)
                                (1+ portion-start)))
       (setq next-portion-start (max
                                (scroll-bar-drag-position next-portion-whole)
                                (1+ portion-start)))
-      (if (or (> current-start next-portion-start)
+      (if (or (>= current-start next-portion-start)
              (< current-start portion-start))
          (set-window-start window portion-start)
        ;; Always set window start, to ensure scroll bar position is updated.
              (< current-start portion-start))
          (set-window-start window portion-start)
        ;; Always set window start, to ensure scroll bar position is updated.
@@ -203,7 +228,7 @@ EVENT should be a scroll bar click or drag event."
       (goto-char (+ (point-min)
                    (scroll-bar-scale portion-whole
                                      (- (point-max) (point-min)))))
       (goto-char (+ (point-min)
                    (scroll-bar-scale portion-whole
                                      (- (point-max) (point-min)))))
-      (beginning-of-line)
+      (vertical-motion 0 window)
       (set-window-start window (point)))))
 
 (defun scroll-bar-drag (event)
       (set-window-start window (point)))))
 
 (defun scroll-bar-drag (event)
@@ -211,75 +236,137 @@ EVENT should be a scroll bar click or drag event."
 If you click outside the slider, the window scrolls to bring the slider there."
   (interactive "e")
   (let* (done
 If you click outside the slider, the window scrolls to bring the slider there."
   (interactive "e")
   (let* (done
-        (echo-keystrokes 0))
-    (or point-before-scroll
-       (setq point-before-scroll (point)))
-    ;; Our scrolling can move point; don't let that clear point-before-scroll.
-    (let (point-before-scroll)
-      (scroll-bar-drag-1 event)
-      (track-mouse
-       (while (not done)
-         (setq event (read-event))
-         (if (eq (car-safe event) 'mouse-movement)
-             (setq event (read-event)))
-         (cond ((eq (car-safe event) 'scroll-bar-movement)
-                (scroll-bar-drag-1 event))
-               (t
-                ;; Exit when we get the drag event; ignore that event.
-                (setq done t)))))
-      (sit-for 0))))
+        (echo-keystrokes 0)
+        (end-position (event-end event))
+        (window (nth 0 end-position))
+        (before-scroll))
+    (with-current-buffer (window-buffer window)
+      (setq before-scroll point-before-scroll))
+    (save-selected-window
+      (select-window window)
+      (setq before-scroll
+           (or before-scroll (point))))
+    (scroll-bar-drag-1 event)
+    (track-mouse
+      (while (not done)
+       (setq event (read-event))
+       (if (eq (car-safe event) 'mouse-movement)
+           (setq event (read-event)))
+       (cond ((eq (car-safe event) 'scroll-bar-movement)
+              (scroll-bar-drag-1 event))
+             (t
+              ;; Exit when we get the drag event; ignore that event.
+              (setq done t)))))
+    (sit-for 0)
+    (with-current-buffer (window-buffer window)
+      (setq point-before-scroll before-scroll))))
 
 (defun scroll-bar-scroll-down (event)
   "Scroll the window's top line down to the location of the scroll bar click.
 EVENT should be a scroll bar click."
   (interactive "e")
 
 (defun scroll-bar-scroll-down (event)
   "Scroll the window's top line down to the location of the scroll bar click.
 EVENT should be a scroll bar click."
   (interactive "e")
-  (let ((old-selected-window (selected-window)))
+  (let* ((end-position (event-end event))
+        (window (nth 0 end-position))
+        (before-scroll))
+    (with-current-buffer (window-buffer window)
+      (setq before-scroll point-before-scroll))
     (unwind-protect
     (unwind-protect
-       (progn
-         (let* ((end-position (event-end event))
-                (window (nth 0 end-position))
-                (portion-whole (nth 2 end-position)))
-           (let (point-before-scroll)
-             (select-window window))
-           (or point-before-scroll
-               (setq point-before-scroll (point)))
-           (let (point-before-scroll)
-             (scroll-down
-              (scroll-bar-scale portion-whole (1- (window-height)))))))
-      (select-window old-selected-window))))
+       (save-selected-window
+         (let ((portion-whole (nth 2 end-position)))
+           (select-window window)
+           (setq before-scroll
+                 (or before-scroll (point)))
+           (scroll-down
+            (scroll-bar-scale portion-whole (1- (window-height)))))
+         (sit-for 0))
+      (with-current-buffer (window-buffer window)
+       (setq point-before-scroll before-scroll)))))
 
 (defun scroll-bar-scroll-up (event)
   "Scroll the line next to the scroll bar click to the top of the window.
 EVENT should be a scroll bar click."
   (interactive "e")
 
 (defun scroll-bar-scroll-up (event)
   "Scroll the line next to the scroll bar click to the top of the window.
 EVENT should be a scroll bar click."
   (interactive "e")
-  (let ((old-selected-window (selected-window)))
+  (let* ((end-position (event-end event))
+        (window (nth 0 end-position))
+        (before-scroll))
+    (with-current-buffer (window-buffer window)
+      (setq before-scroll point-before-scroll))
     (unwind-protect
     (unwind-protect
-       (progn
-         (let* ((end-position (event-end event))
-                (window (nth 0 end-position))
-                (portion-whole (nth 2 end-position)))
-           (let (point-before-scroll)
-             (select-window window))
-           (or point-before-scroll
-               (setq point-before-scroll (point)))
-           (let (point-before-scroll)
-             (scroll-up
-              (scroll-bar-scale portion-whole (1- (window-height)))))))
-      (select-window old-selected-window))))
+       (save-selected-window
+         (let ((portion-whole (nth 2 end-position)))
+           (select-window window)
+           (setq before-scroll
+                 (or before-scroll (point)))
+           (scroll-up
+            (scroll-bar-scale portion-whole (1- (window-height)))))
+         (sit-for 0))
+      (with-current-buffer (window-buffer window)
+       (setq point-before-scroll before-scroll)))))
 
 \f
 
 \f
-;;;; Bindings.
+;;; Tookit scroll bars.
 
 
-;;; For now, we'll set things up to work like xterm.
-(global-set-key [vertical-scroll-bar mouse-1] 'scroll-bar-scroll-up)
-(global-set-key [vertical-scroll-bar drag-mouse-1] 'scroll-bar-scroll-up)
+(defun scroll-bar-toolkit-scroll (event)
+  (interactive "e")
+  (let* ((end-position (event-end event))
+        (window (nth 0 end-position))
+        (part (nth 4 end-position))
+        before-scroll)
+    (cond ((eq part 'end-scroll))
+         (t
+          (with-current-buffer (window-buffer window)
+            (setq before-scroll point-before-scroll))
+          (save-selected-window
+            (select-window window)
+            (setq before-scroll (or before-scroll (point)))
+            (cond ((eq part 'above-handle)
+                   (scroll-up '-))
+                  ((eq part 'below-handle)
+                   (scroll-up nil))
+                  ((eq part 'ratio)
+                   (let* ((portion-whole (nth 2 end-position))
+                          (lines (scroll-bar-scale portion-whole
+                                                   (1- (window-height)))))
+                     (scroll-up (cond ((not (zerop lines)) lines)
+                                      ((< (car portion-whole) 0) -1)
+                                      (t 1)))))
+                  ((eq part 'up)
+                   (scroll-up -1))
+                  ((eq part 'down)
+                   (scroll-up 1))
+                  ((eq part 'top)
+                   (set-window-start window (point-min)))
+                  ((eq part 'bottom)
+                   (goto-char (point-max))
+                   (recenter))
+                  ((eq part 'handle)
+                   (scroll-bar-drag-1 event))))
+          (sit-for 0)
+          (with-current-buffer (window-buffer window)
+            (setq point-before-scroll before-scroll))))))
 
 
-(global-set-key [vertical-scroll-bar down-mouse-2] 'scroll-bar-drag)
 
 
-(global-set-key [vertical-scroll-bar mouse-3] 'scroll-bar-scroll-down)
-(global-set-key [vertical-scroll-bar drag-mouse-3] 'scroll-bar-scroll-down)
+\f
+;;;; Bindings.
+
+;;; For now, we'll set things up to work like xterm.
+(cond ((and (boundp 'x-toolkit-scroll-bars) x-toolkit-scroll-bars)
+       (global-set-key [vertical-scroll-bar mouse-1]
+                      'scroll-bar-toolkit-scroll))
+      (t
+       (global-set-key [vertical-scroll-bar mouse-1]
+                      'scroll-bar-scroll-up)
+       (global-set-key [vertical-scroll-bar drag-mouse-1]
+                      'scroll-bar-scroll-up)
+       (global-set-key [vertical-scroll-bar down-mouse-2]
+                      'scroll-bar-drag)
+       (global-set-key [vertical-scroll-bar mouse-3]
+                      'scroll-bar-scroll-down)
+       (global-set-key [vertical-scroll-bar drag-mouse-3]
+                      'scroll-bar-scroll-down)))
 
 \f
 (provide 'scroll-bar)
 
 
 \f
 (provide 'scroll-bar)
 
+;;; arch-tag: 6f1d01d0-0b1e-4bf8-86db-d491e0f399f3
 ;;; scroll-bar.el ends here
 ;;; scroll-bar.el ends here