]> code.delx.au - gnu-emacs/blobdiff - lisp/scroll-bar.el
Close bug#3992.
[gnu-emacs] / lisp / scroll-bar.el
index d8e21921458b0fc3f2c3bcd0597f363860958624..3f763fc59dad2e2d12e2a66bbdbffdde5fc99044 100644 (file)
@@ -1,16 +1,17 @@
-;;; 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, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: hardware
 
 ;; This file is part of GNU Emacs.
 
 
 ;; Maintainer: FSF
 ;; Keywords: hardware
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; 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.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,9 +19,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
@@ -53,10 +52,28 @@ 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.
 
 (defvar scroll-bar-mode)
 \f
 ;;;; Helpful functions for enabling and disabling scroll bars.
 
 (defvar scroll-bar-mode)
+(defvar previous-scroll-bar-mode nil)
 
 (defvar scroll-bar-mode-explicit nil
   "Non-nil means `set-scroll-bar-mode' should really do something.
 
 (defvar scroll-bar-mode-explicit nil
   "Non-nil means `set-scroll-bar-mode' should really do something.
@@ -67,56 +84,50 @@ This is nil while loading `scroll-bar.el', and t afterward.")
 
 (defun set-scroll-bar-mode (value)
   "Set `scroll-bar-mode' to VALUE and put the new value into effect."
 
 (defun set-scroll-bar-mode (value)
   "Set `scroll-bar-mode' to VALUE and put the new value into effect."
+  (if scroll-bar-mode
+      (setq previous-scroll-bar-mode scroll-bar-mode))
+
   (setq scroll-bar-mode value)
 
   (when scroll-bar-mode-explicit
   (setq scroll-bar-mode value)
 
   (when scroll-bar-mode-explicit
-    ;; Apply it to default-frame-alist.
-    (let ((parameter (assq 'vertical-scroll-bars default-frame-alist)))
-      (if (consp parameter)
-         (setcdr parameter scroll-bar-mode)
-       (setq default-frame-alist
-             (cons (cons 'vertical-scroll-bars scroll-bar-mode)
-                   default-frame-alist))))
-
-    ;; Apply it to existing frames.
-    (let ((frames (frame-list)))
-      (while frames
-       (modify-frame-parameters
-        (car frames)
-        (list (cons 'vertical-scroll-bars scroll-bar-mode)))
-       (setq frames (cdr frames))))))
-
-(defcustom scroll-bar-mode
-  (if (eq system-type 'windows-nt) 'right 'left)
-  "*Specify whether to have vertical scroll bars, and on which side.
+    (modify-all-frames-parameters (list (cons 'vertical-scroll-bars
+                                             scroll-bar-mode)))))
+
+(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).
 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."
 Possible values are nil (no scroll bars), `left' (scroll bars on left)
 and `right' (scroll bars on right).
 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)")
+  :type '(choice (const :tag "none (nil)" nil)
                 (const left)
                 (const right))
   :group 'frames
                 (const left)
                 (const right))
   :group 'frames
+  ;; 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)
 
   :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)
 
-(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.
   "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."
+With a numeric argument, if the argument is positive
+turn on scroll bars; otherwise turn off scroll bars."
   (interactive "P")
   (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 (if (null flag) (not scroll-bar-mode)
-                        (and (or (not (numberp flag)) (>= flag 0))
-                             (if (eq system-type 'windows-nt) 'right '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)))
+                          (or previous-scroll-bar-mode
+                              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.
@@ -134,8 +145,7 @@ when they are turned on; if it is nil, they go on the left."
    (selected-frame)
    (list (cons 'vertical-scroll-bars
               (if (> arg 0)
    (selected-frame)
    (list (cons 'vertical-scroll-bars
               (if (> arg 0)
-                  (or scroll-bar-mode
-                      (if (eq system-type 'windows-nt) 'right 'left)))))))
+                  (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.
@@ -146,7 +156,7 @@ Horizontal scroll bars aren't implemented yet."
 \f
 ;;;; Buffer navigation using the scroll bar.
 
 \f
 ;;;; Buffer navigation using the scroll bar.
 
-;;; This was used for up-events on button 2, but no longer.
+;; This was used for up-events on button 2, but no longer.
 (defun scroll-bar-set-window-start (event)
   "Set the window start according to where the scroll bar is dragged.
 EVENT should be a scroll bar click or drag event."
 (defun scroll-bar-set-window-start (event)
   "Set the window start according to where the scroll bar is dragged.
 EVENT should be a scroll bar click or drag event."
@@ -154,8 +164,7 @@ EVENT should be a scroll bar click or drag event."
   (let* ((end-position (event-end event))
         (window (nth 0 end-position))
         (portion-whole (nth 2 end-position)))
   (let* ((end-position (event-end event))
         (window (nth 0 end-position))
         (portion-whole (nth 2 end-position)))
-    (save-excursion
-      (set-buffer (window-buffer window))
+    (with-current-buffer (window-buffer window)
       (save-excursion
        (goto-char (+ (point-min)
                      (scroll-bar-scale portion-whole
       (save-excursion
        (goto-char (+ (point-min)
                      (scroll-bar-scale portion-whole
@@ -185,8 +194,7 @@ EVENT should be a scroll bar click or drag event."
         portion-start
         next-portion-start
         (current-start (window-start window)))
         portion-start
         next-portion-start
         (current-start (window-start window)))
-    (save-excursion
-      (set-buffer (window-buffer window))
+    (with-current-buffer (window-buffer window)
       (setq portion-start (scroll-bar-drag-position portion-whole))
       (setq next-portion-start (max
                                (scroll-bar-drag-position next-portion-whole)
       (setq portion-start (scroll-bar-drag-position portion-whole))
       (setq next-portion-start (max
                                (scroll-bar-drag-position next-portion-whole)
@@ -202,14 +210,14 @@ EVENT should be a scroll bar click or drag event."
   (let* ((start-position (event-start event))
         (window (nth 0 start-position))
         (portion-whole (nth 2 start-position)))
   (let* ((start-position (event-start event))
         (window (nth 0 start-position))
         (portion-whole (nth 2 start-position)))
-    (save-excursion
-      (set-buffer (window-buffer window))
-      ;; Calculate position relative to the accessible part of the buffer.
-      (goto-char (+ (point-min)
-                   (scroll-bar-scale portion-whole
-                                     (- (point-max) (point-min)))))
-      (beginning-of-line)
-      (set-window-start window (point)))))
+    (save-excursion 
+      (with-current-buffer (window-buffer window)
+       ;; Calculate position relative to the accessible part of the buffer.
+       (goto-char (+ (point-min)
+                     (scroll-bar-scale portion-whole
+                                       (- (point-max) (point-min)))))
+       (vertical-motion 0 window)
+       (set-window-start window (point))))))
 
 (defun scroll-bar-drag (event)
   "Scroll the window by dragging the scroll bar slider.
 
 (defun scroll-bar-drag (event)
   "Scroll the window by dragging the scroll bar slider.
@@ -284,18 +292,69 @@ EVENT should be a scroll bar click."
        (setq point-before-scroll before-scroll)))))
 
 \f
        (setq point-before-scroll before-scroll)))))
 
 \f
-;;;; Bindings.
+;;; Tookit scroll bars.
+
+(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))))))
 
 
-;;; 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)
 
 
-(global-set-key [vertical-scroll-bar down-mouse-2] 'scroll-bar-drag)
+\f
+;;;; Bindings.
 
 
-(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)
+;; 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