Function: follow-adjust-window
follow-adjust-window is a byte-compiled function defined in
follow.el.gz.
Signature
(follow-adjust-window WIN)
Documentation
Adjust the window WIN and its followers.
Source Code
;; Defined in /usr/src/emacs/lisp/follow.el.gz
;; NOTE: to debug follow-mode with edebug, it is helpful to add
;; `follow-post-command-hook' to `post-command-hook' temporarily. Do
;; this locally to the target buffer with, say,:
;; M-: (add-hook 'post-command-hook 'follow-post-command-hook t t)
;; .
(defun follow-adjust-window (win)
"Adjust the window WIN and its followers."
(cl-assert (eq (window-buffer win) (current-buffer)))
;; Have we moved out of or into a follow-mode window group?
;; If so, attend to the visibility of the cursors.
(when (not (eq (current-buffer) follow-prev-buffer))
;; Do we need to switch off cursor handling in the previous buffer?
(when (buffer-live-p follow-prev-buffer)
(with-current-buffer follow-prev-buffer
(when (and follow-mode
(local-variable-p 'cursor-in-non-selected-windows))
(setq cursor-in-non-selected-windows
(default-value 'cursor-in-non-selected-windows)))))
;; Do we need to switch on cursor handling in the current buffer?
(when (and follow-mode
(local-variable-p 'cursor-in-non-selected-windows))
(setq cursor-in-non-selected-windows nil))
(when (buffer-live-p (current-buffer))
(setq follow-prev-buffer (current-buffer))))
(when (and follow-mode
(not (window-minibuffer-p win)))
(let ((windows (follow-all-followers win)))
;; If we've explicitly scrolled, align the windows first.
(when follow-fixed-window
(follow-debug-message "fixed")
(follow-redisplay windows win)
(goto-char (follow-get-scrolled-point (point) windows))
(setq follow-fixed-window nil))
(let* ((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)
(setq follow-windows-start-end-cache nil))
;; Select a window to display point.
(unless follow-internal-force-redisplay
(if (eq dest (point-max))
;; Be careful at point-max: 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.
;; Otherwise, 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 (last 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 picks the `correct' window.
((follow-select-if-visible dest win-start-end)
(follow-debug-message "visible")
(goto-char dest)
;; Perform redisplay, in case line is partially visible.
(setq visible nil))
;; Not visible anywhere else, lets pick this one.
(visible
(follow-debug-message "visible in selected."))
;; If DEST is before the first window start, select the
;; first window.
((< dest (nth 1 (car win-start-end)))
(follow-debug-message "before first")
(select-window (car windows))
(goto-char dest)
(setq visible nil 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. Stick to the selected window.
(t
(follow-debug-message "None")
(setq visible nil aligned nil))))
;; If a new window was selected, make sure that the old is
;; not scrolled when point is outside the window.
(unless (eq win (selected-window))
(let ((p (window-point win)))
(set-window-start win (window-start win) nil)
(if (nth 2 (pos-visible-in-window-p p win t))
;; p is in a partially visible line. We can't leave
;; window-point there, because C-x o back into WIN
;; would then fail.
(with-selected-window win
(forward-line)) ; redisplay will recenter it in WIN.
(set-window-point win p)))))
(unless visible
;; If point may not be visible in the selected window,
;; perform a redisplay; this ensures scrolling.
(let ((opoint (point)))
(redisplay)
;; If this `redisplay' moved point, we got clobbered by a
;; previous call to `set-window-start'. Try again.
(when (/= (point) opoint)
(goto-char opoint)
(redisplay)))
(setq selected-window-up-to-date t)
(follow-avoid-tail-recenter)
(setq win-start-end (follow-windows-start-end windows)
follow-windows-start-end-cache nil
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-windows-start-end-cache nil)
;; Point can end up in another window when DEST is at
;; the beginning of the buffer and the selected window is
;; not the first. It can also 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, update windows
;; displaying the tail so that Emacs won't recenter them.
(follow-avoid-tail-recenter)))