- (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
- ;; happends when dest is in the beginning of the
- ;; file and the selected window is not the first.
- ;; It can also, in rare situations happend 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))
- (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)))))