[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] emacs/lisp follow.el
From: |
Chong Yidong |
Subject: |
[Emacs-diffs] emacs/lisp follow.el |
Date: |
Tue, 30 Dec 2008 13:26:23 +0000 |
CVSROOT: /sources/emacs
Module name: emacs
Changes by: Chong Yidong <cyd> 08/12/30 13:26:23
Modified files:
lisp : follow.el
Log message:
(follow-calc-win-end): Use with-selected-window.
(follow-windows-start-end, follow-pos-visible)
(follow-windows-aligned-p): Code cleanup.
(follow-select-if-visible): Try to avoid partially-visible lines.
(follow-select-if-visible-from-first): Call follow-redisplay and
move point to destination.
(follow-redisplay): New arg, to keep selected window unchanged.
(follow-post-command-hook): In final check for destination
visibility, use window-start and window-end instead of the less
accurate follow-pos-visible. If the selected window is redrawn,
tell follow-redisplay to preserve it.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/emacs/lisp/follow.el?cvsroot=emacs&r1=1.50&r2=1.51
Patches:
Index: follow.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/follow.el,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -b -r1.50 -r1.51
--- follow.el 30 Dec 2008 10:52:01 -0000 1.50
+++ follow.el 30 Dec 2008 13:26:23 -0000 1.51
@@ -880,11 +880,8 @@
;; 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
+ (let (height buffer-end-p)
+ (with-selected-window (or win (selected-window))
(save-excursion
(goto-char (window-start))
(setq height
@@ -899,9 +896,7 @@
;; 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))))))
+ (list (point) buffer-end-p))))))
;; Can't use `save-window-excursion' since it triggers a redraw.
@@ -955,30 +950,25 @@
"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)))
+ (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))
- (setq windows (cdr windows)))
(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.
@@ -986,11 +976,10 @@
"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))))
@@ -1053,6 +1042,14 @@
(setq win (caar 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 (/= dest (point-max))
+ win-start-end
+ (follow-pos-visible dest (caar win-start-end) win-start-end)
+ (setq win (caar win-start-end))
+ (select-window win))
win))
@@ -1090,19 +1087,20 @@
;; 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
+ (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)))
@@ -1112,9 +1110,11 @@
(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))
@@ -1126,14 +1126,16 @@
;; 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."
+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.
@@ -1154,7 +1156,8 @@
(follow-calculate-first-window-start-from-below
windows try-first-start win old-win-start)))))
(dolist (w windows)
- (set-window-start w start)
+ (unless (and preserve-win (eq w win))
+ (set-window-start w start))
(setq start (car (follow-calc-win-end w))))))
@@ -1310,15 +1313,15 @@
(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 and cache
- ;; the result for speed (i.e. `aligned' and `visible'.)
+ ;; 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)))
+ (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)
@@ -1392,9 +1395,7 @@
;; at the bottom of a window.
((follow-select-if-visible-from-first dest windows)
(follow-debug-message "Below first")
- (setq visible t aligned t)
- (follow-redisplay windows (car windows))
- (goto-char dest))
+ (setq visible t aligned t))
;; None of the above. For simplicity, we stick to the
;; selected window.
(t
@@ -1403,27 +1404,34 @@
;; 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))
+ (unless (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.)
(unless (or visible
- (follow-pos-visible dest win win-start-end))
+ ;; Use the UPDATE argument of window-end
+ ;; instead of calling follow-pos-visible
+ ;; (which may be inaccurate for partially
+ ;; visible lines).
+ (and (>= dest (window-start))
+ (< dest (window-end nil t))))
+ ;; If point is not visible in the selected window,
+ ;; perform a redisplay; this causes scrolling.
(sit-for 0)
+ (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))
- ;; Redraw the windows whenever needed.
+ ;; 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))
+ (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
@@ -1833,8 +1841,6 @@
((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.