;;; follow.el --- synchronize windows showing the same buffer
;; Copyright (C) 1995, 1996, 1997, 1999, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: Anders Lindgren <andersl@andersl.com>
;; Maintainer: FSF (Anders' email bounces, Sep 2005)
;; 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
-;; the Free Software Foundation; either version 3, 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 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
(select-window win)
(goto-char start)
(vertical-motion (- (- (window-height win)
- 1
+ (if header-line-format 2 1)
next-screen-context-lines)))
(set-window-start win (point))
(goto-char start)
;; This code works on both XEmacs and Emacs, but now
;; that XEmacs has got custom-written code, this could
;; be optimized for Emacs.
- (let ((orig-win (and win (selected-window)))
- height
- buffer-end-p)
- (if win (select-window win))
- (prog1
- (save-excursion
- (goto-char (window-start))
- (setq height (- (window-height) 1))
- (setq buffer-end-p
- (if (bolp)
- (not (= height (vertical-motion height)))
- (save-restriction
- ;; Fix a mis-feature in `vertical-motion':
- ;; The start of the window is assumed to
- ;; coinside with the start of a line.
- (narrow-to-region (point) (point-max))
- (not (= height (vertical-motion height))))))
- (list (point) buffer-end-p))
- (if orig-win
- (select-window orig-win))))))
+ (let (height buffer-end-p)
+ (with-selected-window (or win (selected-window))
+ (save-excursion
+ (goto-char (window-start))
+ (setq height
+ (- (window-height)
+ (if header-line-format 2 1)))
+ (setq buffer-end-p
+ (if (bolp)
+ (not (= height (vertical-motion height)))
+ (save-restriction
+ ;; Fix a mis-feature in `vertical-motion':
+ ;; The start of the window is assumed to
+ ;; coinside with the start of a line.
+ (narrow-to-region (point) (point-max))
+ (not (= height (vertical-motion height))))))
+ (list (point) buffer-end-p))))))
;; Can't use `save-window-excursion' since it triggers a redraw.
(while (and windows (not (eq (car windows) win)))
(setq start (window-start (car windows)))
(set-window-start (car windows) pos 'noforce)
- (setq pos (car (inline (follow-calc-win-end (car windows)))))
+ (setq pos (car (follow-calc-win-end (car windows))))
(set-window-start (car windows) start 'noforce)
(setq windows (cdr windows)))
pos))
"Builds a list of (WIN START END BUFFER-END-P) for every window in WINDOWS."
(if (follow-cache-valid-p windows)
follow-windows-start-end-cache
- (let ((win-start-end '())
- (orig-win (selected-window)))
- (while windows
- (select-window (car windows))
- (setq win-start-end
- (cons (cons (car windows)
- (cons (window-start)
- (follow-calc-win-end)))
- win-start-end))
- (setq windows (cdr windows)))
+ (let ((orig-win (selected-window))
+ win-start-end)
+ (dolist (w windows)
+ (select-window w)
+ (push (cons w (cons (window-start) (follow-calc-win-end)))
+ win-start-end))
(select-window orig-win)
- (setq follow-windows-start-end-cache (nreverse win-start-end))
- follow-windows-start-end-cache)))
+ (setq follow-windows-start-end-cache (nreverse win-start-end)))))
(defsubst follow-pos-visible (pos win win-start-end)
"Non-nil when POS is visible in WIN."
(let ((wstart-wend-bend (cdr (assq win win-start-end))))
(and (>= pos (car wstart-wend-bend))
- (or (< pos (car (cdr wstart-wend-bend)))
+ (or (< pos (cadr wstart-wend-bend))
(nth 2 wstart-wend-bend)))))
-;; By `aligned' we mean that for all adjecent windows, the end of the
+;; By `aligned' we mean that for all adjacent windows, the end of the
;; first is equal with the start of the successor. The first window
;; should start at a full screen line.
"Non-nil if the follower windows are aligned."
(let ((res t))
(save-excursion
- (goto-char (window-start (car (car win-start-end))))
- (if (bolp)
- nil
- (vertical-motion 0 (car (car win-start-end)))
- (setq res (eq (point) (window-start (car (car win-start-end)))))))
+ (goto-char (window-start (caar win-start-end)))
+ (unless (bolp)
+ (vertical-motion 0 (caar win-start-end))
+ (setq res (eq (point) (window-start (caar win-start-end))))))
(while (and res (cdr win-start-end))
;; At least two followers left
(setq res (eq (car (cdr (cdr (car win-start-end))))
"Make sure that the start of WIN starts at a full screen line."
(save-excursion
(goto-char (window-start win))
- (if (bolp)
- nil
+ (unless (bolp)
(vertical-motion 0 win)
- (if (eq (point) (window-start win))
- nil
+ (unless (eq (point) (window-start win))
(vertical-motion 1 win)
(set-window-start win (point) 'noforce)))))
(defun follow-select-if-visible (dest win-start-end)
"Select and return a window, if DEST is visible in it.
Return the selected window."
- (let ((win nil))
+ (let (win win-end)
(while (and (not win) win-start-end)
;; Don't select a window that was just moved. This makes it
;; possible to later select the last window after a `end-of-buffer'
;; command.
- (if (follow-pos-visible dest (car (car win-start-end)) win-start-end)
- (progn
- (setq win (car (car win-start-end)))
- (select-window win)))
+ (when (follow-pos-visible dest (caar win-start-end) win-start-end)
+ (setq win (caar win-start-end)
+ win-end (car (cddr (car win-start-end))))
+ (select-window win))
(setq win-start-end (cdr win-start-end)))
+ ;; The last line of the window may be partially visible; if so,
+ ;; and if point is visible in the next window, select the next
+ ;; window instead.
+ (and win
+ (/= dest (point-max))
+ win-start-end
+ (follow-pos-visible dest (caar win-start-end) win-start-end)
+ (save-excursion
+ (goto-char dest)
+ (vertical-motion 1 win)
+ (>= (point) win-end))
+ (setq win (caar win-start-end))
+ (select-window win))
win))
;; as the point is not visible in any window.
(defun follow-select-if-visible-from-first (dest windows)
- "Select and return a window with DEST, if WINDOWS are redrawn from top."
- (let ((win nil)
- end-pos-end-p)
+ "Try to select one of WINDOWS without repositioning the topmost window.
+If one of the windows in WINDOWS contains DEST, select it, call
+`follow-redisplay', move point to DEST, and return that window.
+Otherwise, return nil."
+ (let (win end-pos-end-p)
(save-excursion
(goto-char (window-start (car windows)))
;; Make sure the line start in the beginning of a real screen
;; line.
(vertical-motion 0 (car windows))
- (if (< dest (point))
- ;; Above the start, not visible.
- nil
+ (when (>= dest (point))
;; At or below the start. Check the windows.
(save-window-excursion
- (while (and (not win) windows)
- (set-window-start (car windows) (point) 'noforce)
- (setq end-pos-end-p (follow-calc-win-end (car windows)))
- (goto-char (car end-pos-end-p))
- ;; Visible, if dest above end, or if eob is visible inside
- ;; the window.
- (if (or (car (cdr end-pos-end-p))
- (< dest (point)))
+ (let ((windows windows))
+ (while (and (not win) windows)
+ (set-window-start (car windows) (point) 'noforce)
+ (setq end-pos-end-p (follow-calc-win-end (car windows)))
+ (goto-char (car end-pos-end-p))
+ ;; Visible, if dest above end, or if eob is visible inside
+ ;; the window.
+ (if (or (car (cdr end-pos-end-p))
+ (< dest (point)))
(setq win (car windows))
- (setq windows (cdr windows)))))))
- (if win
- (select-window win))
+ (setq windows (cdr windows))))))))
+ (when win
+ (select-window win)
+ (follow-redisplay windows (car windows))
+ (goto-char dest))
win))
;; Redraw all the windows on the screen, starting with the top window.
;; The window used as as marker is WIN, or the selcted window if WIN
-;; is nil.
+;; is nil. Start every window directly after the end of the previous
+;; window, to make sure long lines are displayed correctly.
-(defun follow-redisplay (&optional windows win)
+(defun follow-redisplay (&optional windows win preserve-win)
"Reposition the WINDOWS around WIN.
Should the point be too close to the roof we redisplay everything
from the top. WINDOWS should contain a list of windows to
redisplay, it is assumed that WIN is a member of the list.
Should WINDOWS be nil, the windows displaying the
same buffer as WIN, in the current frame, are used.
-Should WIN be nil, the selected window is used."
- (or win
- (setq win (selected-window)))
- (or windows
- (setq windows (follow-all-followers win)))
- (follow-downward windows (follow-calculate-first-window-start windows win)))
-
-
-;; Redisplay a chain of windows. Start every window directly after the
-;; end of the previous window, to make sure long lines are displayed
-;; correctly.
-
-(defun follow-downward (windows pos)
- "Redisplay all WINDOWS starting at POS."
- (while windows
- (set-window-start (car windows) pos)
- (setq pos (car (follow-calc-win-end (car windows))))
- (setq windows (cdr windows))))
-
-
-;;(defun follow-downward (windows pos)
-;; "Redisplay all WINDOWS starting at POS."
-;; (let (p)
-;; (while windows
-;; (setq p (window-point (car windows)))
-;; (set-window-start (car windows) pos)
-;; (set-window-point (car windows) (max p pos))
-;; (setq pos (car (follow-calc-win-end (car windows))))
-;; (setq windows (cdr windows)))))
-
-
-;; Return the start of the first window.
-;;
-;; First, estimate the position. It the value is not perfect (i.e. we
-;; have somewhere splited a line between windows) we try to enhance
-;; the value.
-;;
-;; The guess is always perfect if no long lines is split between
-;; windows.
-;;
-;; The worst case peformace of probably very bad, but it is very
-;; unlikely that we ever will miss the correct start by more than one
-;; or two lines.
-
-(defun follow-calculate-first-window-start (windows &optional win start)
- "Calculate the start of the first window.
-
-WINDOWS is a chain of windows to work with. WIN is the window
-to recenter around. It is assumed that WIN starts at position
-START."
- (or win
- (setq win (selected-window)))
- (or start
- (setq start (window-start win)))
- (let ((guess (follow-estimate-first-window-start windows win start)))
- (if (car guess)
- (cdr guess)
- ;; The guess wasn't exact, try to enhance it.
- (let ((win-start (follow-calc-win-start windows (cdr guess) win)))
- (cond ((= win-start start)
- (follow-debug-message "exact")
- (cdr guess))
- ((< win-start start)
- (follow-debug-message "above")
- (follow-calculate-first-window-start-from-above
- windows (cdr guess) win start))
- (t
- (follow-debug-message "below")
- (follow-calculate-first-window-start-from-below
- windows (cdr guess) win start)))))))
+Should WIN be nil, the selected window is used.
+If PRESERVE-WIN is non-nil, keep WIN itself unchanged while
+repositioning the other windows."
+ (or win (setq win (selected-window)))
+ (or windows (setq windows (follow-all-followers win)))
+ ;; Calculate the start of the first window.
+ (let* ((old-win-start (window-start win))
+ (try-first-start (follow-estimate-first-window-start
+ windows win old-win-start))
+ (try-win-start (follow-calc-win-start
+ windows try-first-start win))
+ (start (cond ((= try-win-start old-win-start)
+ (follow-debug-message "exact")
+ try-first-start)
+ ((< try-win-start old-win-start)
+ (follow-debug-message "above")
+ (follow-calculate-first-window-start-from-above
+ windows try-first-start win old-win-start))
+ (t
+ (follow-debug-message "below")
+ (follow-calculate-first-window-start-from-below
+ windows try-first-start win old-win-start)))))
+ (dolist (w windows)
+ (unless (and preserve-win (eq w win))
+ (set-window-start w start))
+ (setq start (car (follow-calc-win-end w))))))
-;; `exact' is disabled due to XEmacs and fonts of variable
-;; height.
(defun follow-estimate-first-window-start (windows win start)
"Estimate the position of the first window.
-
-Returns (EXACT . POS). If EXACT is non-nil, POS is the starting
-position of the first window. Otherwise it is a good guess."
- (let ((pred (car (follow-split-followers windows win)))
- (exact nil))
+The estimate is computed by assuming that the window WIN, which
+should be a member of WINDOWS, starts at position START."
+ (let ((windows-before (car (follow-split-followers windows win))))
(save-excursion
(goto-char start)
- ;(setq exact (bolp))
(vertical-motion 0 win)
- (while pred
- (vertical-motion (- 1 (window-height (car pred))) (car pred))
- (if (not (bolp))
- (setq exact nil))
- (setq pred (cdr pred)))
- (cons exact (point)))))
+ (dolist (w windows-before)
+ (vertical-motion (- 1 (window-text-height w)) w))
+ (point))))
;; Find the starting point, start at GUESS and search downward.
(setq res (point-max)))
(setq win-start (follow-calc-win-start windows (point) win))
(if (>= win-start start)
- (progn
- (setq done t)
- (setq res (point))))))
+ (setq done t res (point)))))
res)))
(setq win (or win (selected-window)))
(setq start (or start (window-start win)))
(save-excursion
- (let ((done nil)
- win-start
- res)
+ (let (done win-start res opoint)
;; Always calculate what happens when no line is displayed in the first
;; window. (The `previous' res is needed below!)
(goto-char guess)
(vertical-motion 0 (car windows))
(setq res (point))
(while (not done)
+ (setq opoint (point))
(if (not (= (vertical-motion -1 (car windows)) -1))
;; Hit roof!
- (progn
- (setq done t)
- (setq res (point-min)))
+ (setq done t res (point-min))
(setq win-start (follow-calc-win-start windows (point) win))
- (cond ((= win-start start) ; Perfect match, use this value
- (setq done t)
- (setq res (point)))
+ (cond ((>= (point) opoint)
+ ;; In some pathological cases, vertical-motion may
+ ;; return -1 even though point has not decreased. In
+ ;; that case, avoid looping forever.
+ (setq done t res (point)))
+ ((= win-start start) ; Perfect match, use this value
+ (setq done t res (point)))
((< win-start start) ; Walked to far, use preious result
(setq done t))
(t ; Store result for next iteration
;; the screen if it should be unaligned.
;;
;; We divide the check into two parts; whether we are at the end or not.
-;; This is due to the fact that the end can actaually be visible
+;; This is due to the fact that the end can actually be visible
;; in several window even though they are aligned.
(defun follow-post-command-hook ()
"Ensure that the windows in Follow mode are adjacent after each command."
- (setq follow-inside-post-command-hook t)
- (if (or (not (input-pending-p))
- ;; Sometimes, in XEmacs, mouse events are not handled
- ;; properly by `input-pending-p'. A typical example is
- ;; when clicking on a node in `info'.
- (and (boundp 'current-mouse-event)
- (symbol-value 'current-mouse-event)
- (fboundp 'button-event-p)
- (funcall (symbol-function 'button-event-p)
- (symbol-value 'current-mouse-event))))
+ (unless (input-pending-p)
+ (let ((follow-inside-post-command-hook t)
+ (win (selected-window)))
;; Work in the selected window, not in the current buffer.
- (let ((orig-buffer (current-buffer))
- (win (selected-window)))
- (set-buffer (window-buffer win))
- (or (and (symbolp this-command)
- (get this-command 'follow-mode-use-cache))
- (follow-invalidate-cache))
- (if (and (boundp 'follow-mode) follow-mode
- (not (window-minibuffer-p win)))
- ;; The buffer shown in the selected window is in follow
- ;; mode, lets find the current state of the display and
- ;; cache the result for speed (i.e. `aligned' and `visible'.)
- (let* ((windows (inline (follow-all-followers win)))
- (dest (point))
- (win-start-end (inline
- (follow-update-window-start (car windows))
- (follow-windows-start-end windows)))
- (aligned (follow-windows-aligned-p win-start-end))
- (visible (follow-pos-visible dest win win-start-end)))
- (if (not (and aligned visible))
- (follow-invalidate-cache))
- (inline (follow-avoid-tail-recenter))
- ;; Select a window to display the point.
- (or follow-internal-force-redisplay
- (progn
- (if (eq dest (point-max))
- ;; We're at the end, we have to be careful since
- ;; the display can be aligned while `dest' can
- ;; be visible in several windows.
- (cond
- ;; Select the current window, but only when
- ;; the display is correct. (When inserting
- ;; character in a tail window, the display is
- ;; not correct, as they are shown twice.)
- ;;
- ;; Never stick to the current window after a
- ;; deletion. The reason is cosmetic, when
- ;; typing `DEL' in a window showing only the
- ;; end of the file, character are removed
- ;; from the window above, which is very
- ;; unintuitive.
- ((and visible
- aligned
- (not (memq this-command
- '(backward-delete-char
- delete-backward-char
- backward-delete-char-untabify
- kill-region))))
- (follow-debug-message "Max: same"))
- ;; If the end is visible, and the window
- ;; doesn't seems like it just has been moved,
- ;; select it.
- ((follow-select-if-end-visible win-start-end)
- (follow-debug-message "Max: end visible")
- (setq visible t)
- (setq aligned nil)
- (goto-char dest))
- ;; Just show the end...
- (t
- (follow-debug-message "Max: default")
- (select-window (car (reverse windows)))
- (goto-char dest)
- (setq visible nil)
- (setq aligned nil)))
-
- ;; We're not at the end, here life is much simpler.
- (cond
- ;; This is the normal case!
- ;; It should be optimized for speed.
- ((and visible aligned)
- (follow-debug-message "same"))
- ;; Pick a position in any window. If the
- ;; display is ok, this will pick the `correct'
- ;; window. If the display is wierd do this
- ;; anyway, this will be the case after a delete
- ;; at the beginning of the window.
- ((follow-select-if-visible dest win-start-end)
- (follow-debug-message "visible")
- (setq visible t)
- (goto-char dest))
- ;; Not visible anywhere else, lets pick this one.
- ;; (Is this case used?)
- (visible
- (follow-debug-message "visible in selected."))
- ;; Far out!
- ((eq dest (point-min))
- (follow-debug-message "min")
- (select-window (car windows))
- (goto-char dest)
- (set-window-start (selected-window) (point-min))
- (setq win-start-end (follow-windows-start-end windows))
- (follow-invalidate-cache)
- (setq visible t)
- (setq aligned nil))
- ;; If we can position the cursor without moving the first
- ;; window, do it. This is the case that catches `RET'
- ;; at the bottom of a window.
- ((follow-select-if-visible-from-first dest windows)
- (follow-debug-message "Below first")
- (setq visible t)
- (setq aligned t)
- (follow-redisplay windows (car windows))
- (goto-char dest))
- ;; None of the above. For simplicity, we stick to the
- ;; selected window.
- (t
- (follow-debug-message "None")
- (setq visible nil)
- (setq aligned nil))))
- ;; If a new window has been selected, make sure that the
- ;; old is not scrolled when the point is outside the
- ;; window.
- (or (eq win (selected-window))
- (let ((p (window-point win)))
- (set-window-start win (window-start win) nil)
- (set-window-point win p)))))
- ;; Make sure the point is visible in the selected window.
- ;; (This could lead to a scroll.)
- (if (or visible
- (follow-pos-visible dest win win-start-end))
- nil
- (sit-for 0)
- (follow-avoid-tail-recenter)
- (setq win-start-end (follow-windows-start-end windows))
- (follow-invalidate-cache)
- (setq aligned nil))
- ;; Redraw the windows whenever needed.
- (if (or follow-internal-force-redisplay
- (not (or aligned
- (follow-windows-aligned-p win-start-end)))
- (not (inline (follow-point-visible-all-windows-p
- win-start-end))))
- (progn
- (setq follow-internal-force-redisplay nil)
- (follow-redisplay windows (selected-window))
- (setq win-start-end (follow-windows-start-end windows))
- (follow-invalidate-cache)
- ;; When the point ends up in another window. This
- ;; happens when dest is in the beginning of the
- ;; file and the selected window is not the first.
- ;; It can also, in rare situations happen when
- ;; long lines are used and there is a big
- ;; difference between the width of the windows.
- ;; (When scrolling one line in a wide window which
- ;; will cause a move larger that an entire small
- ;; window.)
- (if (follow-pos-visible dest win win-start-end)
- nil
- (follow-select-if-visible dest win-start-end)
- (goto-char dest))))
-
- ;; If the region is visible, make it look good when spanning
- ;; multiple windows.
- (if (or (and (boundp 'mark-active) (symbol-value 'mark-active))
- ;; The following isn't used in Emacs,
- ;; since `mark-active' is bound.
- (and (fboundp 'region-active-p)
- (funcall (symbol-function 'region-active-p))))
- (follow-maximize-region
- (selected-window) windows win-start-end))
-
- (inline (follow-avoid-tail-recenter))
- ;; DEBUG
- ;;(if (not (follow-windows-aligned-p
- ;; (follow-windows-start-end windows)))
- ;; (message "follow-mode: windows still unaligend!"))
- ;; END OF DEBUG
- ) ; Matches (let*
- ;; Buffer not in follow mode:
- ;; We still must update the windows displaying the tail so that
- ;; Emacs won't recenter them.
- (follow-avoid-tail-recenter))
- (set-buffer orig-buffer)))
- (setq follow-inside-post-command-hook nil))
+ (with-current-buffer (window-buffer win)
+ (unless (and (symbolp this-command)
+ (get this-command 'follow-mode-use-cache))
+ (follow-invalidate-cache))
+ (when (and follow-mode
+ (not (window-minibuffer-p win)))
+ ;; The buffer shown in the selected window is in follow
+ ;; mode. Find the current state of the display.
+ (let* ((windows (follow-all-followers win))
+ (dest (point))
+ (win-start-end (progn
+ (follow-update-window-start (car windows))
+ (follow-windows-start-end windows)))
+ (aligned (follow-windows-aligned-p win-start-end))
+ (visible (follow-pos-visible dest win win-start-end))
+ selected-window-up-to-date)
+ (unless (and aligned visible)
+ (follow-invalidate-cache))
+ (follow-avoid-tail-recenter)
+ ;; Select a window to display point.
+ (unless follow-internal-force-redisplay
+ (if (eq dest (point-max))
+ ;; At point-max, we have to be careful since the
+ ;; display can be aligned while `dest' can be
+ ;; visible in several windows.
+ (cond
+ ;; Select the current window, but only when the
+ ;; display is correct. (When inserting characters
+ ;; in a tail window, the display is not correct, as
+ ;; they are shown twice.)
+ ;;
+ ;; Never stick to the current window after a
+ ;; deletion. The reason is cosmetic: when typing
+ ;; `DEL' in a window showing only the end of the
+ ;; file, a character would be removed from the
+ ;; window above, which is very unintuitive.
+ ((and visible
+ aligned
+ (not (memq this-command
+ '(backward-delete-char
+ delete-backward-char
+ backward-delete-char-untabify
+ kill-region))))
+ (follow-debug-message "Max: same"))
+ ;; If the end is visible, and the window doesn't
+ ;; seems like it just has been moved, select it.
+ ((follow-select-if-end-visible win-start-end)
+ (follow-debug-message "Max: end visible")
+ (setq visible t aligned nil)
+ (goto-char dest))
+ ;; Just show the end...
+ (t
+ (follow-debug-message "Max: default")
+ (select-window (car (reverse windows)))
+ (goto-char dest)
+ (setq visible nil aligned nil)))
+
+ ;; We're not at the end, here life is much simpler.
+ (cond
+ ;; This is the normal case!
+ ;; It should be optimized for speed.
+ ((and visible aligned)
+ (follow-debug-message "same"))
+ ;; Pick a position in any window. If the display is
+ ;; ok, this will pick the `correct' window.
+ ((follow-select-if-visible dest win-start-end)
+ (follow-debug-message "visible")
+ (goto-char dest)
+ ;; We have to perform redisplay, since scrolling is
+ ;; needed in case the line is partially visible.
+ (setq visible nil))
+ ;; Not visible anywhere else, lets pick this one.
+ ;; (Is this case used?)
+ (visible
+ (follow-debug-message "visible in selected."))
+ ;; Far out!
+ ((eq dest (point-min))
+ (follow-debug-message "min")
+ (select-window (car windows))
+ (goto-char dest)
+ (set-window-start (selected-window) (point-min))
+ (setq win-start-end (follow-windows-start-end windows))
+ (follow-invalidate-cache)
+ (setq visible t aligned nil))
+ ;; If we can position the cursor without moving the first
+ ;; window, do it. This is the case that catches `RET'
+ ;; at the bottom of a window.
+ ((follow-select-if-visible-from-first dest windows)
+ (follow-debug-message "Below first")
+ (setq visible t aligned t))
+ ;; None of the above. For simplicity, we stick to the
+ ;; selected window.
+ (t
+ (follow-debug-message "None")
+ (setq visible nil aligned nil))))
+ ;; If a new window has been selected, make sure that the
+ ;; old is not scrolled when the point is outside the
+ ;; window.
+ (unless (eq win (selected-window))
+ (let ((p (window-point win)))
+ (set-window-start win (window-start win) nil)
+ (set-window-point win p))))
+ (unless visible
+ ;; If point may not be visible in the selected window,
+ ;; perform a redisplay; this ensures scrolling.
+ (redisplay)
+ (setq selected-window-up-to-date t)
+ (follow-avoid-tail-recenter)
+ (setq win-start-end (follow-windows-start-end windows))
+ (follow-invalidate-cache)
+ (setq aligned nil))
+ ;; Now redraw the windows around the selected window.
+ (unless (and (not follow-internal-force-redisplay)
+ (or aligned
+ (follow-windows-aligned-p win-start-end))
+ (follow-point-visible-all-windows-p
+ win-start-end))
+ (setq follow-internal-force-redisplay nil)
+ (follow-redisplay windows (selected-window)
+ selected-window-up-to-date)
+ (setq win-start-end (follow-windows-start-end windows))
+ (follow-invalidate-cache)
+ ;; When the point ends up in another window. This
+ ;; happens when dest is in the beginning of the file and
+ ;; the selected window is not the first. It can also,
+ ;; in rare situations happen when long lines are used
+ ;; and there is a big difference between the width of
+ ;; the windows. (When scrolling one line in a wide
+ ;; window which will cause a move larger that an entire
+ ;; small window.)
+ (unless (follow-pos-visible dest win win-start-end)
+ (follow-select-if-visible dest win-start-end)
+ (goto-char dest)))
+
+ ;; If the region is visible, make it look good when spanning
+ ;; multiple windows.
+ (when (region-active-p)
+ (follow-maximize-region
+ (selected-window) windows win-start-end))))
+ ;; Whether or not the buffer was in follow mode, we must
+ ;; update the windows displaying the tail so that Emacs won't
+ ;; recenter them.
+ (follow-avoid-tail-recenter)))))
;;}}}
;;{{{ The region
((follow-select-if-visible-from-first
new-window-point windows)
(follow-debug-message "filter: Seen from first")
- (follow-redisplay windows (car windows))
- (goto-char new-window-point)
(setq win-start-end
(follow-windows-start-end windows)))
;; None of the above. We stick to the current window.
follow-all-followers
follow-split-followers
follow-redisplay
- follow-downward
- follow-calculate-first-window-start
follow-estimate-first-window-start
follow-calculate-first-window-start-from-above
follow-calculate-first-window-start-from-below