]> code.delx.au - gnu-emacs/blobdiff - lisp/follow.el
Add a new function `svg-embed'
[gnu-emacs] / lisp / follow.el
index 2cbf0f2b93d54cfaef10b3fcf21eda81369cd7fa..c510e5a848beeed12a9004cc135ebea7c4bd2d26 100644 (file)
@@ -1,6 +1,6 @@
 ;;; follow.el --- synchronize windows showing the same buffer
 
-;; Copyright (C) 1995-1997, 1999, 2001-2015 Free Software Foundation,
+;; Copyright (C) 1995-1997, 1999, 2001-2016 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Anders Lindgren
@@ -399,11 +399,11 @@ virtual window.  This is accomplished by two main techniques:
   makes it possible to walk between windows using normal cursor
   movement commands.
 
-Follow mode comes to its prime when used on a large screen and two
-side-by-side windows are used.  The user can, with the help of Follow
-mode, use two full-height windows as though they would have been
-one.  Imagine yourself editing a large function, or section of text,
-and being able to use 144 lines instead of the normal 72... (your
+Follow mode comes to its prime when used on a large screen and two or
+more side-by-side windows are used.  The user can, with the help of
+Follow mode, use these full-height windows as though they were one.
+Imagine yourself editing a large function, or section of text, and
+being able to use 144 or 216 lines instead of the normal 72... (your
 mileage may vary).
 
 To split one large window into two side-by-side windows, the commands
@@ -423,16 +423,18 @@ Keys specific to Follow mode:
        (add-hook 'post-command-hook 'follow-post-command-hook t)
        (add-hook 'window-size-change-functions 'follow-window-size-change t)
         (add-hook 'after-change-functions 'follow-after-change nil t)
-
-        (setq window-start-group-function 'follow-window-start)
-        (setq window-end-group-function 'follow-window-end)
-        (setq set-window-start-group-function 'follow-set-window-start)
-        (setq recenter-group-function 'follow-recenter)
-        (setq pos-visible-in-window-p-group-function
+        (add-hook 'isearch-update-post-hook 'follow-post-command-hook nil t)
+        (add-hook 'replace-update-post-hook 'follow-post-command-hook nil t)
+        (add-hook 'ispell-update-post-hook 'follow-post-command-hook nil t)
+
+        (setq window-group-start-function 'follow-window-start)
+        (setq window-group-end-function 'follow-window-end)
+        (setq set-window-group-start-function 'follow-set-window-start)
+        (setq recenter-window-group-function 'follow-recenter)
+        (setq pos-visible-in-window-group-p-function
               'follow-pos-visible-in-window-p)
         (setq selected-window-group-function 'follow-all-followers)
-        (setq move-to-window-line-group-function 'follow-move-to-window-line)
-        (setq sit*-for-function 'follow-sit-for))
+        (setq move-to-window-group-line-function 'follow-move-to-window-line))
 
     ;; Remove globally-installed hook functions only if there is no
     ;; other Follow mode buffer.
@@ -445,15 +447,17 @@ Keys specific to Follow mode:
        (remove-hook 'post-command-hook 'follow-post-command-hook)
        (remove-hook 'window-size-change-functions 'follow-window-size-change)))
 
-    (kill-local-variable 'sit*-for-function)
-    (kill-local-variable 'move-to-window-line-group-function)
+    (kill-local-variable 'move-to-window-group-line-function)
     (kill-local-variable 'selected-window-group-function)
-    (kill-local-variable 'pos-visible-in-window-p-group-function)
-    (kill-local-variable 'recenter-group-function)
-    (kill-local-variable 'set-window-start-group-function)
-    (kill-local-variable 'window-end-group-function)
-    (kill-local-variable 'window-start-group-function)
-
+    (kill-local-variable 'pos-visible-in-window-group-p-function)
+    (kill-local-variable 'recenter-window-group-function)
+    (kill-local-variable 'set-window-group-start-function)
+    (kill-local-variable 'window-group-end-function)
+    (kill-local-variable 'window-group-start-function)
+
+    (remove-hook 'ispell-update-post-hook 'follow-post-command-hook t)
+    (remove-hook 'replace-update-post-hook 'follow-post-command-hook t)
+    (remove-hook 'isearch-update-post-hook 'follow-post-command-hook t)
     (remove-hook 'after-change-functions 'follow-after-change t)
     (remove-hook 'compilation-filter-hook 'follow-align-compilation-windows t)))
 
@@ -528,6 +532,80 @@ Return the new position."
 ;; position...  (This would also be corrected if we would have had a
 ;; good redisplay abstraction.)
 
+(defun follow-scroll-up-arg (arg)
+  "Scroll the text in a follow mode window chain up by ARG lines.
+If ARG is nil, scroll the size of the current window.
+
+This is an internal function for `follow-scroll-up' and
+`follow-scroll-up-window'."
+  (let ((opoint (point))  (owin (selected-window)))
+    (while
+        ;; If we are too near EOB, try scrolling the previous window.
+        (condition-case nil (progn (scroll-up arg) nil)
+          (end-of-buffer
+           (condition-case nil (progn (follow-previous-window) t)
+             (error
+              (select-window owin)
+              (goto-char opoint)
+              (signal 'end-of-buffer nil))))))
+    (unless (and scroll-preserve-screen-position
+                 (get this-command 'scroll-command))
+      (goto-char opoint))
+    (setq follow-fixed-window t)))
+
+(defun follow-scroll-down-arg (arg)
+  "Scroll the text in a follow mode window chain down by ARG lines.
+If ARG is nil, scroll the size of the current window.
+
+This is an internal function for `follow-scroll-down' and
+`follow-scroll-down-window'."
+  (let ((opoint (point)))
+    (scroll-down arg)
+    (unless (and scroll-preserve-screen-position
+                 (get this-command 'scroll-command))
+      (goto-char opoint))
+    (setq follow-fixed-window t)))
+
+;;;###autoload
+(defun follow-scroll-up-window (&optional arg)
+  "Scroll text in a Follow mode window up by that window's size.
+The other windows in the window chain will scroll synchronously.
+
+If called with no ARG, the `next-screen-context-lines' last lines of
+the window will be visible after the scroll.
+
+If called with an argument, scroll ARG lines up.
+Negative ARG means scroll downward.
+
+Works like `scroll-up' when not in Follow mode."
+  (interactive "P")
+  (cond ((not follow-mode)
+        (scroll-up arg))
+       ((eq arg '-)
+        (follow-scroll-down-window))
+       (t (follow-scroll-up-arg arg))))
+(put 'follow-scroll-up-window 'scroll-command t)
+
+;;;###autoload
+(defun follow-scroll-down-window (&optional arg)
+  "Scroll text in a Follow mode window down by that window's size.
+The other windows in the window chain will scroll synchronously.
+
+If called with no ARG, the `next-screen-context-lines' top lines of
+the window in the chain will be visible after the scroll.
+
+If called with an argument, scroll ARG lines down.
+Negative ARG means scroll upward.
+
+Works like `scroll-down' when not in Follow mode."
+  (interactive "P")
+  (cond ((not follow-mode)
+        (scroll-down arg))
+       ((eq arg '-)
+        (follow-scroll-up-window))
+       (t (follow-scroll-down-arg arg))))
+(put 'follow-scroll-down-window 'scroll-command t)
+
 ;;;###autoload
 (defun follow-scroll-up (&optional arg)
   "Scroll text in a Follow mode window chain up.
@@ -542,23 +620,18 @@ Works like `scroll-up' when not in Follow mode."
   (interactive "P")
   (cond ((not follow-mode)
         (scroll-up arg))
-       ((eq arg '-)
-        (follow-scroll-down))
-       (t
-        (let ((opoint (point))  (owin (selected-window)))
-          (while
-              ;; If we are too near EOB, try scrolling the previous window.
-              (condition-case nil (progn (scroll-up arg) nil)
-                (end-of-buffer
-                 (condition-case nil (progn (follow-previous-window) t)
-                   (error
-                    (select-window owin)
-                    (goto-char opoint)
-                    (signal 'end-of-buffer nil))))))
-          (unless (and scroll-preserve-screen-position
-                       (get this-command 'scroll-command))
-            (goto-char opoint))
-          (setq follow-fixed-window t)))))
+       (arg (follow-scroll-up-arg arg))
+        (t
+        (let* ((windows (follow-all-followers))
+               (end (window-end (car (reverse windows)))))
+          (if (eq end (point-max))
+              (signal 'end-of-buffer nil)
+            (select-window (car windows))
+            ;; `window-end' might return nil.
+            (if end
+                (goto-char end))
+            (vertical-motion (- next-screen-context-lines))
+            (set-window-start (car windows) (point)))))))
 (put 'follow-scroll-up 'scroll-command t)
 
 ;;;###autoload
@@ -575,15 +648,22 @@ Works like `scroll-down' when not in Follow mode."
   (interactive "P")
   (cond ((not follow-mode)
         (scroll-down arg))
-       ((eq arg '-)
-        (follow-scroll-up))
-       (t
-        (let ((opoint (point)))
-          (scroll-down arg)
-          (unless (and scroll-preserve-screen-position
-                       (get this-command 'scroll-command))
-            (goto-char opoint))
-          (setq follow-fixed-window t)))))
+       (arg (follow-scroll-down-arg arg))
+        (t
+        (let* ((windows (follow-all-followers))
+               (win (car (reverse windows)))
+               (start (window-start (car windows))))
+          (if (eq start (point-min))
+              (signal 'beginning-of-buffer nil)
+            (select-window win)
+            (goto-char start)
+            (vertical-motion (- (- (window-height win)
+                                   (if header-line-format 2 1)
+                                   next-screen-context-lines)))
+            (set-window-start win (point))
+            (goto-char start)
+            (vertical-motion (- next-screen-context-lines 1))
+            (setq follow-internal-force-redisplay t))))))
 (put 'follow-scroll-down 'scroll-command t)
 
 (declare-function comint-adjust-point "comint" (window))
@@ -1475,9 +1555,9 @@ non-first windows in Follow mode."
 
 ;; These routines are the Follow Mode versions of the low level
 ;; functions described on page "Window Start and End" of the elisp
-;; manual, e.g. `window*-start'.  The aim is to be able to handle
-;; Follow Mode windows by replacing `window-start' by `window*-start',
-;; etc.
+;; manual, e.g. `window-group-start'.  The aim is to be able to handle
+;; Follow Mode windows by replacing `window-start' by
+;; `window-group-start', etc.
 
 (defun follow-after-change (_beg _end _old-len)
   "After change function: set `follow-start-end-invalid'."
@@ -1611,27 +1691,6 @@ zero means top of the first window in the group, negative means
                  lines (+ lines count)))))))
     (+ lines (move-to-window-line arg))))
 
-(defun follow-sit-for (seconds &optional nodisp)
-  "Redisplay, then wait for SECONDS seconds.  Stop when input is available.
-Before redisplaying, synchronise all Follow windows.
-
-SECONDS may be a floating-point value.
-\(On operating systems that do not support waiting for fractions of a
-second, floating-point values are rounded down to the nearest integer.)
-
-Redisplay does not happen if input is available before it starts.
-If optional arg NODISP is t, don't synchronise or redisplay, just
-wait for input.
-
-Value is t if waited the full time with no input arriving, and nil
-otherwise.
-
-The functionality is intended to be the same as `sit-for''s."
-  (when (and (not (input-pending-p t))
-             (not nodisp))
-    (follow-adjust-window (selected-window)))
-  (sit-for seconds nodisp))
-
 ;;; Profile support
 
 ;; The following (non-evaluated) section can be used to