X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/64c57303658f69b019c4599f8c960a5623855410..455700d69a1a6861dc8c9b2ba19733429727d3c3:/lisp/follow.el diff --git a/lisp/follow.el b/lisp/follow.el index 2cbf0f2b93..c510e5a848 100644 --- a/lisp/follow.el +++ b/lisp/follow.el @@ -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