aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Rudalics2008-09-10 08:53:26 +0000
committerMartin Rudalics2008-09-10 08:53:26 +0000
commit2564beceace9324a832a7a22bc653bdfd1e5fdf4 (patch)
tree89ed6a9c2114e58eed9e29fb327f682a323b5b20
parentfc3a285ed7c00f251e1ed7e85f1e6014918d9a7a (diff)
downloademacs-2564beceace9324a832a7a22bc653bdfd1e5fdf4.tar.gz
emacs-2564beceace9324a832a7a22bc653bdfd1e5fdf4.zip
*** empty log message ***
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/window.el3258
2 files changed, 1633 insertions, 1629 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 90aa1e14a45..8a9364ae40c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
12008-09-10 Martin Rudalics <rudalics@gmx.at>
2
3 * window.el (display-buffer): Fix doc-string typo.
4
12008-09-10 Kenichi Handa <handa@m17n.org> 52008-09-10 Kenichi Handa <handa@m17n.org>
2 6
3 * composite.el (compose-gstring-for-graphic): Fix previous change. 7 * composite.el (compose-gstring-for-graphic): Fix previous change.
diff --git a/lisp/window.el b/lisp/window.el
index a15d785ff6c..5875a5ba8e8 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -1,1629 +1,1629 @@
1;;; window.el --- GNU Emacs window commands aside from those written in C 1;;; window.el --- GNU Emacs window commands aside from those written in C
2 2
3;; Copyright (C) 1985, 1989, 1992, 1993, 1994, 2000, 2001, 2002, 3;; Copyright (C) 1985, 1989, 1992, 1993, 1994, 2000, 2001, 2002,
4;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. 4;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 5
6;; Maintainer: FSF 6;; Maintainer: FSF
7;; Keywords: internal 7;; Keywords: internal
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
10 10
11;; GNU Emacs is free software: you can redistribute it and/or modify 11;; GNU Emacs is free software: you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by 12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation, either version 3 of the License, or 13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version. 14;; (at your option) any later version.
15 15
16;; GNU Emacs is distributed in the hope that it will be useful, 16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details. 19;; GNU General Public License for more details.
20 20
21;; You should have received a copy of the GNU General Public License 21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 23
24;;; Commentary: 24;;; Commentary:
25 25
26;; Window tree functions. 26;; Window tree functions.
27 27
28;;; Code: 28;;; Code:
29 29
30(eval-when-compile (require 'cl)) 30(eval-when-compile (require 'cl))
31 31
32(defvar window-size-fixed nil 32(defvar window-size-fixed nil
33 "*Non-nil in a buffer means windows displaying the buffer are fixed-size. 33 "*Non-nil in a buffer means windows displaying the buffer are fixed-size.
34If the value is `height', then only the window's height is fixed. 34If the value is `height', then only the window's height is fixed.
35If the value is `width', then only the window's width is fixed. 35If the value is `width', then only the window's width is fixed.
36Any other non-nil value fixes both the width and the height. 36Any other non-nil value fixes both the width and the height.
37Emacs won't change the size of any window displaying that buffer, 37Emacs won't change the size of any window displaying that buffer,
38unless you explicitly change the size, or Emacs has no other choice.") 38unless you explicitly change the size, or Emacs has no other choice.")
39(make-variable-buffer-local 'window-size-fixed) 39(make-variable-buffer-local 'window-size-fixed)
40 40
41(defmacro save-selected-window (&rest body) 41(defmacro save-selected-window (&rest body)
42 "Execute BODY, then select the window that was selected before BODY. 42 "Execute BODY, then select the window that was selected before BODY.
43The value returned is the value of the last form in BODY. 43The value returned is the value of the last form in BODY.
44 44
45This macro saves and restores the current buffer, since otherwise 45This macro saves and restores the current buffer, since otherwise
46its normal operation could potentially make a different 46its normal operation could potentially make a different
47buffer current. It does not alter the buffer list ordering. 47buffer current. It does not alter the buffer list ordering.
48 48
49This macro saves and restores the selected window, as well as 49This macro saves and restores the selected window, as well as
50the selected window in each frame. If the previously selected 50the selected window in each frame. If the previously selected
51window of some frame is no longer live at the end of BODY, that 51window of some frame is no longer live at the end of BODY, that
52frame's selected window is left alone. If the selected window is 52frame's selected window is left alone. If the selected window is
53no longer live, then whatever window is selected at the end of 53no longer live, then whatever window is selected at the end of
54BODY remains selected." 54BODY remains selected."
55 `(let ((save-selected-window-window (selected-window)) 55 `(let ((save-selected-window-window (selected-window))
56 ;; It is necessary to save all of these, because calling 56 ;; It is necessary to save all of these, because calling
57 ;; select-window changes frame-selected-window for whatever 57 ;; select-window changes frame-selected-window for whatever
58 ;; frame that window is in. 58 ;; frame that window is in.
59 (save-selected-window-alist 59 (save-selected-window-alist
60 (mapcar (lambda (frame) (cons frame (frame-selected-window frame))) 60 (mapcar (lambda (frame) (cons frame (frame-selected-window frame)))
61 (frame-list)))) 61 (frame-list))))
62 (save-current-buffer 62 (save-current-buffer
63 (unwind-protect 63 (unwind-protect
64 (progn ,@body) 64 (progn ,@body)
65 (dolist (elt save-selected-window-alist) 65 (dolist (elt save-selected-window-alist)
66 (and (frame-live-p (car elt)) 66 (and (frame-live-p (car elt))
67 (window-live-p (cdr elt)) 67 (window-live-p (cdr elt))
68 (set-frame-selected-window (car elt) (cdr elt)))) 68 (set-frame-selected-window (car elt) (cdr elt))))
69 (if (window-live-p save-selected-window-window) 69 (if (window-live-p save-selected-window-window)
70 (select-window save-selected-window-window)))))) 70 (select-window save-selected-window-window))))))
71 71
72(defun window-body-height (&optional window) 72(defun window-body-height (&optional window)
73 "Return number of lines in window WINDOW for actual buffer text. 73 "Return number of lines in window WINDOW for actual buffer text.
74This does not include the mode line (if any) or the header line (if any)." 74This does not include the mode line (if any) or the header line (if any)."
75 (or window (setq window (selected-window))) 75 (or window (setq window (selected-window)))
76 (if (window-minibuffer-p window) 76 (if (window-minibuffer-p window)
77 (window-height window) 77 (window-height window)
78 (with-current-buffer (window-buffer window) 78 (with-current-buffer (window-buffer window)
79 (max 1 (- (window-height window) 79 (max 1 (- (window-height window)
80 (if mode-line-format 1 0) 80 (if mode-line-format 1 0)
81 (if header-line-format 1 0)))))) 81 (if header-line-format 1 0))))))
82 82
83(defun one-window-p (&optional nomini all-frames) 83(defun one-window-p (&optional nomini all-frames)
84 "Return non-nil if the selected window is the only window. 84 "Return non-nil if the selected window is the only window.
85Optional arg NOMINI non-nil means don't count the minibuffer 85Optional arg NOMINI non-nil means don't count the minibuffer
86even if it is active. Otherwise, the minibuffer is counted 86even if it is active. Otherwise, the minibuffer is counted
87when it is active. 87when it is active.
88 88
89The optional arg ALL-FRAMES t means count windows on all frames. 89The optional arg ALL-FRAMES t means count windows on all frames.
90If it is `visible', count windows on all visible frames. 90If it is `visible', count windows on all visible frames.
91ALL-FRAMES nil or omitted means count only the selected frame, 91ALL-FRAMES nil or omitted means count only the selected frame,
92plus the minibuffer it uses (which may be on another frame). 92plus the minibuffer it uses (which may be on another frame).
93ALL-FRAMES 0 means count all windows in all visible or iconified frames. 93ALL-FRAMES 0 means count all windows in all visible or iconified frames.
94If ALL-FRAMES is anything else, count only the selected frame." 94If ALL-FRAMES is anything else, count only the selected frame."
95 (let ((base-window (selected-window))) 95 (let ((base-window (selected-window)))
96 (if (and nomini (eq base-window (minibuffer-window))) 96 (if (and nomini (eq base-window (minibuffer-window)))
97 (setq base-window (next-window base-window))) 97 (setq base-window (next-window base-window)))
98 (eq base-window 98 (eq base-window
99 (next-window base-window (if nomini 'arg) all-frames)))) 99 (next-window base-window (if nomini 'arg) all-frames))))
100 100
101(defun window-current-scroll-bars (&optional window) 101(defun window-current-scroll-bars (&optional window)
102 "Return the current scroll-bar settings in window WINDOW. 102 "Return the current scroll-bar settings in window WINDOW.
103Value is a cons (VERTICAL . HORIZONTAL) where VERTICAL specifies the 103Value is a cons (VERTICAL . HORIZONTAL) where VERTICAL specifies the
104current location of the vertical scroll-bars (left, right, or nil), 104current location of the vertical scroll-bars (left, right, or nil),
105and HORIZONTAL specifies the current location of the horizontal scroll 105and HORIZONTAL specifies the current location of the horizontal scroll
106bars (top, bottom, or nil)." 106bars (top, bottom, or nil)."
107 (let ((vert (nth 2 (window-scroll-bars window))) 107 (let ((vert (nth 2 (window-scroll-bars window)))
108 (hor nil)) 108 (hor nil))
109 (when (or (eq vert t) (eq hor t)) 109 (when (or (eq vert t) (eq hor t))
110 (let ((fcsb (frame-current-scroll-bars 110 (let ((fcsb (frame-current-scroll-bars
111 (window-frame (or window (selected-window)))))) 111 (window-frame (or window (selected-window))))))
112 (if (eq vert t) 112 (if (eq vert t)
113 (setq vert (car fcsb))) 113 (setq vert (car fcsb)))
114 (if (eq hor t) 114 (if (eq hor t)
115 (setq hor (cdr fcsb))))) 115 (setq hor (cdr fcsb)))))
116 (cons vert hor))) 116 (cons vert hor)))
117 117
118(defun walk-windows (proc &optional minibuf all-frames) 118(defun walk-windows (proc &optional minibuf all-frames)
119 "Cycle through all visible windows, calling PROC for each one. 119 "Cycle through all visible windows, calling PROC for each one.
120PROC is called with a window as argument. 120PROC is called with a window as argument.
121 121
122Optional second arg MINIBUF t means count the minibuffer window even 122Optional second arg MINIBUF t means count the minibuffer window even
123if not active. MINIBUF nil or omitted means count the minibuffer only if 123if not active. MINIBUF nil or omitted means count the minibuffer only if
124it is active. MINIBUF neither t nor nil means not to count the 124it is active. MINIBUF neither t nor nil means not to count the
125minibuffer even if it is active. 125minibuffer even if it is active.
126 126
127Several frames may share a single minibuffer; if the minibuffer 127Several frames may share a single minibuffer; if the minibuffer
128counts, all windows on all frames that share that minibuffer count 128counts, all windows on all frames that share that minibuffer count
129too. Therefore, if you are using a separate minibuffer frame 129too. Therefore, if you are using a separate minibuffer frame
130and the minibuffer is active and MINIBUF says it counts, 130and the minibuffer is active and MINIBUF says it counts,
131`walk-windows' includes the windows in the frame from which you 131`walk-windows' includes the windows in the frame from which you
132entered the minibuffer, as well as the minibuffer window. 132entered the minibuffer, as well as the minibuffer window.
133 133
134ALL-FRAMES is the optional third argument. 134ALL-FRAMES is the optional third argument.
135ALL-FRAMES nil or omitted means cycle within the frames as specified above. 135ALL-FRAMES nil or omitted means cycle within the frames as specified above.
136ALL-FRAMES = `visible' means include windows on all visible frames. 136ALL-FRAMES = `visible' means include windows on all visible frames.
137ALL-FRAMES = 0 means include windows on all visible and iconified frames. 137ALL-FRAMES = 0 means include windows on all visible and iconified frames.
138ALL-FRAMES = t means include windows on all frames including invisible frames. 138ALL-FRAMES = t means include windows on all frames including invisible frames.
139If ALL-FRAMES is a frame, it means include windows on that frame. 139If ALL-FRAMES is a frame, it means include windows on that frame.
140Anything else means restrict to the selected frame." 140Anything else means restrict to the selected frame."
141 ;; If we start from the minibuffer window, don't fail to come back to it. 141 ;; If we start from the minibuffer window, don't fail to come back to it.
142 (if (window-minibuffer-p (selected-window)) 142 (if (window-minibuffer-p (selected-window))
143 (setq minibuf t)) 143 (setq minibuf t))
144 (save-selected-window 144 (save-selected-window
145 (if (framep all-frames) 145 (if (framep all-frames)
146 (select-window (frame-first-window all-frames))) 146 (select-window (frame-first-window all-frames)))
147 (let* (walk-windows-already-seen 147 (let* (walk-windows-already-seen
148 (walk-windows-current (selected-window))) 148 (walk-windows-current (selected-window)))
149 (while (progn 149 (while (progn
150 (setq walk-windows-current 150 (setq walk-windows-current
151 (next-window walk-windows-current minibuf all-frames)) 151 (next-window walk-windows-current minibuf all-frames))
152 (not (memq walk-windows-current walk-windows-already-seen))) 152 (not (memq walk-windows-current walk-windows-already-seen)))
153 (setq walk-windows-already-seen 153 (setq walk-windows-already-seen
154 (cons walk-windows-current walk-windows-already-seen)) 154 (cons walk-windows-current walk-windows-already-seen))
155 (funcall proc walk-windows-current))))) 155 (funcall proc walk-windows-current)))))
156 156
157(defun get-window-with-predicate (predicate &optional minibuf 157(defun get-window-with-predicate (predicate &optional minibuf
158 all-frames default) 158 all-frames default)
159 "Return a window satisfying PREDICATE. 159 "Return a window satisfying PREDICATE.
160 160
161This function cycles through all visible windows using `walk-windows', 161This function cycles through all visible windows using `walk-windows',
162calling PREDICATE on each one. PREDICATE is called with a window as 162calling PREDICATE on each one. PREDICATE is called with a window as
163argument. The first window for which PREDICATE returns a non-nil 163argument. The first window for which PREDICATE returns a non-nil
164value is returned. If no window satisfies PREDICATE, DEFAULT is 164value is returned. If no window satisfies PREDICATE, DEFAULT is
165returned. 165returned.
166 166
167Optional second arg MINIBUF t means count the minibuffer window even 167Optional second arg MINIBUF t means count the minibuffer window even
168if not active. MINIBUF nil or omitted means count the minibuffer only if 168if not active. MINIBUF nil or omitted means count the minibuffer only if
169it is active. MINIBUF neither t nor nil means not to count the 169it is active. MINIBUF neither t nor nil means not to count the
170minibuffer even if it is active. 170minibuffer even if it is active.
171 171
172Several frames may share a single minibuffer; if the minibuffer 172Several frames may share a single minibuffer; if the minibuffer
173counts, all windows on all frames that share that minibuffer count 173counts, all windows on all frames that share that minibuffer count
174too. Therefore, if you are using a separate minibuffer frame 174too. Therefore, if you are using a separate minibuffer frame
175and the minibuffer is active and MINIBUF says it counts, 175and the minibuffer is active and MINIBUF says it counts,
176`walk-windows' includes the windows in the frame from which you 176`walk-windows' includes the windows in the frame from which you
177entered the minibuffer, as well as the minibuffer window. 177entered the minibuffer, as well as the minibuffer window.
178 178
179ALL-FRAMES is the optional third argument. 179ALL-FRAMES is the optional third argument.
180ALL-FRAMES nil or omitted means cycle within the frames as specified above. 180ALL-FRAMES nil or omitted means cycle within the frames as specified above.
181ALL-FRAMES = `visible' means include windows on all visible frames. 181ALL-FRAMES = `visible' means include windows on all visible frames.
182ALL-FRAMES = 0 means include windows on all visible and iconified frames. 182ALL-FRAMES = 0 means include windows on all visible and iconified frames.
183ALL-FRAMES = t means include windows on all frames including invisible frames. 183ALL-FRAMES = t means include windows on all frames including invisible frames.
184If ALL-FRAMES is a frame, it means include windows on that frame. 184If ALL-FRAMES is a frame, it means include windows on that frame.
185Anything else means restrict to the selected frame." 185Anything else means restrict to the selected frame."
186 (catch 'found 186 (catch 'found
187 (walk-windows #'(lambda (window) 187 (walk-windows #'(lambda (window)
188 (when (funcall predicate window) 188 (when (funcall predicate window)
189 (throw 'found window))) 189 (throw 'found window)))
190 minibuf all-frames) 190 minibuf all-frames)
191 default)) 191 default))
192 192
193(defalias 'some-window 'get-window-with-predicate) 193(defalias 'some-window 'get-window-with-predicate)
194 194
195;; This should probably be written in C (i.e., without using `walk-windows'). 195;; This should probably be written in C (i.e., without using `walk-windows').
196(defun get-buffer-window-list (buffer &optional minibuf all-frames) 196(defun get-buffer-window-list (buffer &optional minibuf all-frames)
197 "Return list of all windows displaying BUFFER, or nil if none. 197 "Return list of all windows displaying BUFFER, or nil if none.
198BUFFER can be a buffer or a buffer name. 198BUFFER can be a buffer or a buffer name.
199See `walk-windows' for the meaning of MINIBUF and ALL-FRAMES." 199See `walk-windows' for the meaning of MINIBUF and ALL-FRAMES."
200 (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows) 200 (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows)
201 (walk-windows (function (lambda (window) 201 (walk-windows (function (lambda (window)
202 (if (eq (window-buffer window) buffer) 202 (if (eq (window-buffer window) buffer)
203 (setq windows (cons window windows))))) 203 (setq windows (cons window windows)))))
204 minibuf all-frames) 204 minibuf all-frames)
205 windows)) 205 windows))
206 206
207(defun minibuffer-window-active-p (window) 207(defun minibuffer-window-active-p (window)
208 "Return t if WINDOW (a minibuffer window) is now active." 208 "Return t if WINDOW (a minibuffer window) is now active."
209 (eq window (active-minibuffer-window))) 209 (eq window (active-minibuffer-window)))
210 210
211(defun count-windows (&optional minibuf) 211(defun count-windows (&optional minibuf)
212 "Return the number of visible windows. 212 "Return the number of visible windows.
213This counts the windows in the selected frame and (if the minibuffer is 213This counts the windows in the selected frame and (if the minibuffer is
214to be counted) its minibuffer frame (if that's not the same frame). 214to be counted) its minibuffer frame (if that's not the same frame).
215The optional arg MINIBUF non-nil means count the minibuffer 215The optional arg MINIBUF non-nil means count the minibuffer
216even if it is inactive." 216even if it is inactive."
217 (let ((count 0)) 217 (let ((count 0))
218 (walk-windows (lambda (w) (setq count (+ count 1))) 218 (walk-windows (lambda (w) (setq count (+ count 1)))
219 minibuf) 219 minibuf)
220 count)) 220 count))
221 221
222(defun window-safely-shrinkable-p (&optional window) 222(defun window-safely-shrinkable-p (&optional window)
223 "Non-nil if the WINDOW can be shrunk without shrinking other windows. 223 "Non-nil if the WINDOW can be shrunk without shrinking other windows.
224If WINDOW is nil or omitted, it defaults to the currently selected window." 224If WINDOW is nil or omitted, it defaults to the currently selected window."
225 (with-selected-window (or window (selected-window)) 225 (with-selected-window (or window (selected-window))
226 (let ((edges (window-edges))) 226 (let ((edges (window-edges)))
227 (or (= (nth 2 edges) (nth 2 (window-edges (previous-window)))) 227 (or (= (nth 2 edges) (nth 2 (window-edges (previous-window))))
228 (= (nth 0 edges) (nth 0 (window-edges (next-window)))))))) 228 (= (nth 0 edges) (nth 0 (window-edges (next-window))))))))
229 229
230 230
231;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 231;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232;;; `balance-windows' subroutines using `window-tree' 232;;; `balance-windows' subroutines using `window-tree'
233 233
234;;; Translate from internal window tree format 234;;; Translate from internal window tree format
235 235
236(defun bw-get-tree (&optional window-or-frame) 236(defun bw-get-tree (&optional window-or-frame)
237 "Get a window split tree in our format. 237 "Get a window split tree in our format.
238 238
239WINDOW-OR-FRAME must be nil, a frame, or a window. If it is nil, 239WINDOW-OR-FRAME must be nil, a frame, or a window. If it is nil,
240then the whole window split tree for `selected-frame' is returned. 240then the whole window split tree for `selected-frame' is returned.
241If it is a frame, then this is used instead. If it is a window, 241If it is a frame, then this is used instead. If it is a window,
242then the smallest tree containing that window is returned." 242then the smallest tree containing that window is returned."
243 (when window-or-frame 243 (when window-or-frame
244 (unless (or (framep window-or-frame) 244 (unless (or (framep window-or-frame)
245 (windowp window-or-frame)) 245 (windowp window-or-frame))
246 (error "Not a frame or window: %s" window-or-frame))) 246 (error "Not a frame or window: %s" window-or-frame)))
247 (let ((subtree (bw-find-tree-sub window-or-frame))) 247 (let ((subtree (bw-find-tree-sub window-or-frame)))
248 (when subtree 248 (when subtree
249 (if (integerp subtree) 249 (if (integerp subtree)
250 nil 250 nil
251 (bw-get-tree-1 subtree))))) 251 (bw-get-tree-1 subtree)))))
252 252
253(defun bw-get-tree-1 (split) 253(defun bw-get-tree-1 (split)
254 (if (windowp split) 254 (if (windowp split)
255 split 255 split
256 (let ((dir (car split)) 256 (let ((dir (car split))
257 (edges (car (cdr split))) 257 (edges (car (cdr split)))
258 (childs (cdr (cdr split)))) 258 (childs (cdr (cdr split))))
259 (list 259 (list
260 (cons 'dir (if dir 'ver 'hor)) 260 (cons 'dir (if dir 'ver 'hor))
261 (cons 'b (nth 3 edges)) 261 (cons 'b (nth 3 edges))
262 (cons 'r (nth 2 edges)) 262 (cons 'r (nth 2 edges))
263 (cons 't (nth 1 edges)) 263 (cons 't (nth 1 edges))
264 (cons 'l (nth 0 edges)) 264 (cons 'l (nth 0 edges))
265 (cons 'childs (mapcar #'bw-get-tree-1 childs)))))) 265 (cons 'childs (mapcar #'bw-get-tree-1 childs))))))
266 266
267(defun bw-find-tree-sub (window-or-frame &optional get-parent) 267(defun bw-find-tree-sub (window-or-frame &optional get-parent)
268 (let* ((window (when (windowp window-or-frame) window-or-frame)) 268 (let* ((window (when (windowp window-or-frame) window-or-frame))
269 (frame (when (windowp window) (window-frame window))) 269 (frame (when (windowp window) (window-frame window)))
270 (wt (car (window-tree frame)))) 270 (wt (car (window-tree frame))))
271 (when (< 1 (length (window-list frame 0))) 271 (when (< 1 (length (window-list frame 0)))
272 (if window 272 (if window
273 (bw-find-tree-sub-1 wt window get-parent) 273 (bw-find-tree-sub-1 wt window get-parent)
274 wt)))) 274 wt))))
275 275
276(defun bw-find-tree-sub-1 (tree win &optional get-parent) 276(defun bw-find-tree-sub-1 (tree win &optional get-parent)
277 (unless (windowp win) (error "Not a window: %s" win)) 277 (unless (windowp win) (error "Not a window: %s" win))
278 (if (memq win tree) 278 (if (memq win tree)
279 (if get-parent 279 (if get-parent
280 get-parent 280 get-parent
281 tree) 281 tree)
282 (let ((childs (cdr (cdr tree))) 282 (let ((childs (cdr (cdr tree)))
283 child 283 child
284 subtree) 284 subtree)
285 (while (and childs (not subtree)) 285 (while (and childs (not subtree))
286 (setq child (car childs)) 286 (setq child (car childs))
287 (setq childs (cdr childs)) 287 (setq childs (cdr childs))
288 (when (and child (listp child)) 288 (when (and child (listp child))
289 (setq subtree (bw-find-tree-sub-1 child win get-parent)))) 289 (setq subtree (bw-find-tree-sub-1 child win get-parent))))
290 (if (integerp subtree) 290 (if (integerp subtree)
291 (progn 291 (progn
292 (if (= 1 subtree) 292 (if (= 1 subtree)
293 tree 293 tree
294 (1- subtree))) 294 (1- subtree)))
295 subtree 295 subtree
296 )))) 296 ))))
297 297
298;;; Window or object edges 298;;; Window or object edges
299 299
300(defun bw-l (obj) 300(defun bw-l (obj)
301 "Left edge of OBJ." 301 "Left edge of OBJ."
302 (if (windowp obj) (nth 0 (window-edges obj)) (cdr (assq 'l obj)))) 302 (if (windowp obj) (nth 0 (window-edges obj)) (cdr (assq 'l obj))))
303(defun bw-t (obj) 303(defun bw-t (obj)
304 "Top edge of OBJ." 304 "Top edge of OBJ."
305 (if (windowp obj) (nth 1 (window-edges obj)) (cdr (assq 't obj)))) 305 (if (windowp obj) (nth 1 (window-edges obj)) (cdr (assq 't obj))))
306(defun bw-r (obj) 306(defun bw-r (obj)
307 "Right edge of OBJ." 307 "Right edge of OBJ."
308 (if (windowp obj) (nth 2 (window-edges obj)) (cdr (assq 'r obj)))) 308 (if (windowp obj) (nth 2 (window-edges obj)) (cdr (assq 'r obj))))
309(defun bw-b (obj) 309(defun bw-b (obj)
310 "Bottom edge of OBJ." 310 "Bottom edge of OBJ."
311 (if (windowp obj) (nth 3 (window-edges obj)) (cdr (assq 'b obj)))) 311 (if (windowp obj) (nth 3 (window-edges obj)) (cdr (assq 'b obj))))
312 312
313;;; Split directions 313;;; Split directions
314 314
315(defun bw-dir (obj) 315(defun bw-dir (obj)
316 "Return window split tree direction if OBJ. 316 "Return window split tree direction if OBJ.
317If OBJ is a window return 'both. If it is a window split tree 317If OBJ is a window return 'both. If it is a window split tree
318then return its direction." 318then return its direction."
319 (if (symbolp obj) 319 (if (symbolp obj)
320 obj 320 obj
321 (if (windowp obj) 321 (if (windowp obj)
322 'both 322 'both
323 (let ((dir (cdr (assq 'dir obj)))) 323 (let ((dir (cdr (assq 'dir obj))))
324 (unless (memq dir '(hor ver both)) 324 (unless (memq dir '(hor ver both))
325 (error "Can't find dir in %s" obj)) 325 (error "Can't find dir in %s" obj))
326 dir)))) 326 dir))))
327 327
328(defun bw-eqdir (obj1 obj2) 328(defun bw-eqdir (obj1 obj2)
329 "Return t if window split tree directions are equal. 329 "Return t if window split tree directions are equal.
330OBJ1 and OBJ2 should be either windows or window split trees in 330OBJ1 and OBJ2 should be either windows or window split trees in
331our format. The directions returned by `bw-dir' are compared and 331our format. The directions returned by `bw-dir' are compared and
332t is returned if they are `eq' or one of them is 'both." 332t is returned if they are `eq' or one of them is 'both."
333 (let ((dir1 (bw-dir obj1)) 333 (let ((dir1 (bw-dir obj1))
334 (dir2 (bw-dir obj2))) 334 (dir2 (bw-dir obj2)))
335 (or (eq dir1 dir2) 335 (or (eq dir1 dir2)
336 (eq dir1 'both) 336 (eq dir1 'both)
337 (eq dir2 'both)))) 337 (eq dir2 'both))))
338 338
339;;; Building split tree 339;;; Building split tree
340 340
341(defun bw-refresh-edges (obj) 341(defun bw-refresh-edges (obj)
342 "Refresh the edge information of OBJ and return OBJ." 342 "Refresh the edge information of OBJ and return OBJ."
343 (unless (windowp obj) 343 (unless (windowp obj)
344 (let ((childs (cdr (assq 'childs obj))) 344 (let ((childs (cdr (assq 'childs obj)))
345 (ol 1000) 345 (ol 1000)
346 (ot 1000) 346 (ot 1000)
347 (or -1) 347 (or -1)
348 (ob -1)) 348 (ob -1))
349 (dolist (o childs) 349 (dolist (o childs)
350 (when (> ol (bw-l o)) (setq ol (bw-l o))) 350 (when (> ol (bw-l o)) (setq ol (bw-l o)))
351 (when (> ot (bw-t o)) (setq ot (bw-t o))) 351 (when (> ot (bw-t o)) (setq ot (bw-t o)))
352 (when (< or (bw-r o)) (setq or (bw-r o))) 352 (when (< or (bw-r o)) (setq or (bw-r o)))
353 (when (< ob (bw-b o)) (setq ob (bw-b o)))) 353 (when (< ob (bw-b o)) (setq ob (bw-b o))))
354 (setq obj (delq 'l obj)) 354 (setq obj (delq 'l obj))
355 (setq obj (delq 't obj)) 355 (setq obj (delq 't obj))
356 (setq obj (delq 'r obj)) 356 (setq obj (delq 'r obj))
357 (setq obj (delq 'b obj)) 357 (setq obj (delq 'b obj))
358 (add-to-list 'obj (cons 'l ol)) 358 (add-to-list 'obj (cons 'l ol))
359 (add-to-list 'obj (cons 't ot)) 359 (add-to-list 'obj (cons 't ot))
360 (add-to-list 'obj (cons 'r or)) 360 (add-to-list 'obj (cons 'r or))
361 (add-to-list 'obj (cons 'b ob)) 361 (add-to-list 'obj (cons 'b ob))
362 )) 362 ))
363 obj) 363 obj)
364 364
365;;; Balance windows 365;;; Balance windows
366 366
367(defun balance-windows (&optional window-or-frame) 367(defun balance-windows (&optional window-or-frame)
368 "Make windows the same heights or widths in window split subtrees. 368 "Make windows the same heights or widths in window split subtrees.
369 369
370When called non-interactively WINDOW-OR-FRAME may be either a 370When called non-interactively WINDOW-OR-FRAME may be either a
371window or a frame. It then balances the windows on the implied 371window or a frame. It then balances the windows on the implied
372frame. If the parameter is a window only the corresponding window 372frame. If the parameter is a window only the corresponding window
373subtree is balanced." 373subtree is balanced."
374 (interactive) 374 (interactive)
375 (let ( 375 (let (
376 (wt (bw-get-tree window-or-frame)) 376 (wt (bw-get-tree window-or-frame))
377 (w) 377 (w)
378 (h) 378 (h)
379 (tried-sizes) 379 (tried-sizes)
380 (last-sizes) 380 (last-sizes)
381 (windows (window-list nil 0))) 381 (windows (window-list nil 0)))
382 (when wt 382 (when wt
383 (while (not (member last-sizes tried-sizes)) 383 (while (not (member last-sizes tried-sizes))
384 (when last-sizes (setq tried-sizes (cons last-sizes tried-sizes))) 384 (when last-sizes (setq tried-sizes (cons last-sizes tried-sizes)))
385 (setq last-sizes (mapcar (lambda (w) 385 (setq last-sizes (mapcar (lambda (w)
386 (window-edges w)) 386 (window-edges w))
387 windows)) 387 windows))
388 (when (eq 'hor (bw-dir wt)) 388 (when (eq 'hor (bw-dir wt))
389 (setq w (- (bw-r wt) (bw-l wt)))) 389 (setq w (- (bw-r wt) (bw-l wt))))
390 (when (eq 'ver (bw-dir wt)) 390 (when (eq 'ver (bw-dir wt))
391 (setq h (- (bw-b wt) (bw-t wt)))) 391 (setq h (- (bw-b wt) (bw-t wt))))
392 (bw-balance-sub wt w h))))) 392 (bw-balance-sub wt w h)))))
393 393
394(defun bw-adjust-window (window delta horizontal) 394(defun bw-adjust-window (window delta horizontal)
395 "Wrapper around `adjust-window-trailing-edge' with error checking. 395 "Wrapper around `adjust-window-trailing-edge' with error checking.
396Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function." 396Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
397 ;; `adjust-window-trailing-edge' may fail if delta is too large. 397 ;; `adjust-window-trailing-edge' may fail if delta is too large.
398 (while (>= (abs delta) 1) 398 (while (>= (abs delta) 1)
399 (condition-case err 399 (condition-case err
400 (progn 400 (progn
401 (adjust-window-trailing-edge window delta horizontal) 401 (adjust-window-trailing-edge window delta horizontal)
402 (setq delta 0)) 402 (setq delta 0))
403 (error 403 (error
404 ;;(message "adjust: %s" (error-message-string err)) 404 ;;(message "adjust: %s" (error-message-string err))
405 (setq delta (/ delta 2)))))) 405 (setq delta (/ delta 2))))))
406 406
407(defun bw-balance-sub (wt w h) 407(defun bw-balance-sub (wt w h)
408 (setq wt (bw-refresh-edges wt)) 408 (setq wt (bw-refresh-edges wt))
409 (unless w (setq w (- (bw-r wt) (bw-l wt)))) 409 (unless w (setq w (- (bw-r wt) (bw-l wt))))
410 (unless h (setq h (- (bw-b wt) (bw-t wt)))) 410 (unless h (setq h (- (bw-b wt) (bw-t wt))))
411 (if (windowp wt) 411 (if (windowp wt)
412 (progn 412 (progn
413 (when w 413 (when w
414 (let ((dw (- w (- (bw-r wt) (bw-l wt))))) 414 (let ((dw (- w (- (bw-r wt) (bw-l wt)))))
415 (when (/= 0 dw) 415 (when (/= 0 dw)
416 (bw-adjust-window wt dw t)))) 416 (bw-adjust-window wt dw t))))
417 (when h 417 (when h
418 (let ((dh (- h (- (bw-b wt) (bw-t wt))))) 418 (let ((dh (- h (- (bw-b wt) (bw-t wt)))))
419 (when (/= 0 dh) 419 (when (/= 0 dh)
420 (bw-adjust-window wt dh nil))))) 420 (bw-adjust-window wt dh nil)))))
421 (let* ((childs (cdr (assq 'childs wt))) 421 (let* ((childs (cdr (assq 'childs wt)))
422 (cw (when w (/ w (if (bw-eqdir 'hor wt) (length childs) 1)))) 422 (cw (when w (/ w (if (bw-eqdir 'hor wt) (length childs) 1))))
423 (ch (when h (/ h (if (bw-eqdir 'ver wt) (length childs) 1))))) 423 (ch (when h (/ h (if (bw-eqdir 'ver wt) (length childs) 1)))))
424 (dolist (c childs) 424 (dolist (c childs)
425 (bw-balance-sub c cw ch))))) 425 (bw-balance-sub c cw ch)))))
426 426
427;;; A different solution to balance-windows 427;;; A different solution to balance-windows
428 428
429(defun window-fixed-size-p (&optional window direction) 429(defun window-fixed-size-p (&optional window direction)
430 "Non-nil if WINDOW cannot be resized in DIRECTION. 430 "Non-nil if WINDOW cannot be resized in DIRECTION.
431DIRECTION can be nil (i.e. any), `height' or `width'." 431DIRECTION can be nil (i.e. any), `height' or `width'."
432 (with-current-buffer (window-buffer window) 432 (with-current-buffer (window-buffer window)
433 (let ((fixed (and (boundp 'window-size-fixed) window-size-fixed))) 433 (let ((fixed (and (boundp 'window-size-fixed) window-size-fixed)))
434 (when fixed 434 (when fixed
435 (not (and direction 435 (not (and direction
436 (member (cons direction window-size-fixed) 436 (member (cons direction window-size-fixed)
437 '((height . width) (width . height))))))))) 437 '((height . width) (width . height)))))))))
438 438
439(defvar window-area-factor 1 439(defvar window-area-factor 1
440 "Factor by which the window area should be over-estimated. 440 "Factor by which the window area should be over-estimated.
441This is used by `balance-windows-area'. 441This is used by `balance-windows-area'.
442Changing this globally has no effect.") 442Changing this globally has no effect.")
443(make-variable-buffer-local 'window-area-factor) 443(make-variable-buffer-local 'window-area-factor)
444 444
445(defun balance-windows-area () 445(defun balance-windows-area ()
446 "Make all visible windows the same area (approximately). 446 "Make all visible windows the same area (approximately).
447See also `window-area-factor' to change the relative size of specific buffers." 447See also `window-area-factor' to change the relative size of specific buffers."
448 (interactive) 448 (interactive)
449 (let* ((unchanged 0) (carry 0) (round 0) 449 (let* ((unchanged 0) (carry 0) (round 0)
450 ;; Remove fixed-size windows. 450 ;; Remove fixed-size windows.
451 (wins (delq nil (mapcar (lambda (win) 451 (wins (delq nil (mapcar (lambda (win)
452 (if (not (window-fixed-size-p win)) win)) 452 (if (not (window-fixed-size-p win)) win))
453 (window-list nil 'nomini)))) 453 (window-list nil 'nomini))))
454 (changelog nil) 454 (changelog nil)
455 next) 455 next)
456 ;; Resizing a window changes the size of surrounding windows in complex 456 ;; Resizing a window changes the size of surrounding windows in complex
457 ;; ways, so it's difficult to balance them all. The introduction of 457 ;; ways, so it's difficult to balance them all. The introduction of
458 ;; `adjust-window-trailing-edge' made it a bit easier, but it is still 458 ;; `adjust-window-trailing-edge' made it a bit easier, but it is still
459 ;; very difficult to do. `balance-window' above takes an off-line 459 ;; very difficult to do. `balance-window' above takes an off-line
460 ;; approach: get the whole window tree, then balance it, then try to 460 ;; approach: get the whole window tree, then balance it, then try to
461 ;; adjust the windows so they fit the result. 461 ;; adjust the windows so they fit the result.
462 ;; Here, instead, we take a "local optimization" approach, where we just 462 ;; Here, instead, we take a "local optimization" approach, where we just
463 ;; go through all the windows several times until nothing needs to be 463 ;; go through all the windows several times until nothing needs to be
464 ;; changed. The main problem with this approach is that it's difficult 464 ;; changed. The main problem with this approach is that it's difficult
465 ;; to make sure it terminates, so we use some heuristic to try and break 465 ;; to make sure it terminates, so we use some heuristic to try and break
466 ;; off infinite loops. 466 ;; off infinite loops.
467 ;; After a round without any change, we allow a second, to give a chance 467 ;; After a round without any change, we allow a second, to give a chance
468 ;; to the carry to propagate a minor imbalance from the end back to 468 ;; to the carry to propagate a minor imbalance from the end back to
469 ;; the beginning. 469 ;; the beginning.
470 (while (< unchanged 2) 470 (while (< unchanged 2)
471 ;; (message "New round") 471 ;; (message "New round")
472 (setq unchanged (1+ unchanged) round (1+ round)) 472 (setq unchanged (1+ unchanged) round (1+ round))
473 (dolist (win wins) 473 (dolist (win wins)
474 (setq next win) 474 (setq next win)
475 (while (progn (setq next (next-window next)) 475 (while (progn (setq next (next-window next))
476 (window-fixed-size-p next))) 476 (window-fixed-size-p next)))
477 ;; (assert (eq next (or (cadr (member win wins)) (car wins)))) 477 ;; (assert (eq next (or (cadr (member win wins)) (car wins))))
478 (let* ((horiz 478 (let* ((horiz
479 (< (car (window-edges win)) (car (window-edges next)))) 479 (< (car (window-edges win)) (car (window-edges next))))
480 (areadiff (/ (- (* (window-height next) (window-width next) 480 (areadiff (/ (- (* (window-height next) (window-width next)
481 (buffer-local-value 'window-area-factor 481 (buffer-local-value 'window-area-factor
482 (window-buffer next))) 482 (window-buffer next)))
483 (* (window-height win) (window-width win) 483 (* (window-height win) (window-width win)
484 (buffer-local-value 'window-area-factor 484 (buffer-local-value 'window-area-factor
485 (window-buffer win)))) 485 (window-buffer win))))
486 (max (buffer-local-value 'window-area-factor 486 (max (buffer-local-value 'window-area-factor
487 (window-buffer win)) 487 (window-buffer win))
488 (buffer-local-value 'window-area-factor 488 (buffer-local-value 'window-area-factor
489 (window-buffer next))))) 489 (window-buffer next)))))
490 (edgesize (if horiz 490 (edgesize (if horiz
491 (+ (window-height win) (window-height next)) 491 (+ (window-height win) (window-height next))
492 (+ (window-width win) (window-width next)))) 492 (+ (window-width win) (window-width next))))
493 (diff (/ areadiff edgesize))) 493 (diff (/ areadiff edgesize)))
494 (when (zerop diff) 494 (when (zerop diff)
495 ;; Maybe diff is actually closer to 1 than to 0. 495 ;; Maybe diff is actually closer to 1 than to 0.
496 (setq diff (/ (* 3 areadiff) (* 2 edgesize)))) 496 (setq diff (/ (* 3 areadiff) (* 2 edgesize))))
497 (when (and (zerop diff) (not (zerop areadiff))) 497 (when (and (zerop diff) (not (zerop areadiff)))
498 (setq diff (/ (+ areadiff carry) edgesize)) 498 (setq diff (/ (+ areadiff carry) edgesize))
499 ;; Change things smoothly. 499 ;; Change things smoothly.
500 (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))) 500 (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2))))
501 (if (zerop diff) 501 (if (zerop diff)
502 ;; Make sure negligible differences don't accumulate to 502 ;; Make sure negligible differences don't accumulate to
503 ;; become significant. 503 ;; become significant.
504 (setq carry (+ carry areadiff)) 504 (setq carry (+ carry areadiff))
505 (bw-adjust-window win diff horiz) 505 (bw-adjust-window win diff horiz)
506 ;; (sit-for 0.5) 506 ;; (sit-for 0.5)
507 (let ((change (cons win (window-edges win)))) 507 (let ((change (cons win (window-edges win))))
508 ;; If the same change has been seen already for this window, 508 ;; If the same change has been seen already for this window,
509 ;; we're most likely in an endless loop, so don't count it as 509 ;; we're most likely in an endless loop, so don't count it as
510 ;; a change. 510 ;; a change.
511 (unless (member change changelog) 511 (unless (member change changelog)
512 (push change changelog) 512 (push change changelog)
513 (setq unchanged 0 carry 0))))))) 513 (setq unchanged 0 carry 0)))))))
514 ;; We've now basically balanced all the windows. 514 ;; We've now basically balanced all the windows.
515 ;; But there may be some minor off-by-one imbalance left over, 515 ;; But there may be some minor off-by-one imbalance left over,
516 ;; so let's do some fine tuning. 516 ;; so let's do some fine tuning.
517 ;; (bw-finetune wins) 517 ;; (bw-finetune wins)
518 ;; (message "Done in %d rounds" round) 518 ;; (message "Done in %d rounds" round)
519 )) 519 ))
520 520
521 521
522(defcustom display-buffer-function nil 522(defcustom display-buffer-function nil
523 "If non-nil, function to call to handle `display-buffer'. 523 "If non-nil, function to call to handle `display-buffer'.
524It will receive two args, the buffer and a flag which if non-nil 524It will receive two args, the buffer and a flag which if non-nil
525means that the currently selected window is not acceptable. It 525means that the currently selected window is not acceptable. It
526should choose or create a window, display the specified buffer in 526should choose or create a window, display the specified buffer in
527it, and return the window. 527it, and return the window.
528 528
529Commands such as `switch-to-buffer-other-window' and 529Commands such as `switch-to-buffer-other-window' and
530`find-file-other-window' work using this function." 530`find-file-other-window' work using this function."
531 :type '(choice 531 :type '(choice
532 (const nil) 532 (const nil)
533 (function :tag "function")) 533 (function :tag "function"))
534 :group 'windows) 534 :group 'windows)
535 535
536(defun special-display-p (buffer-name) 536(defun special-display-p (buffer-name)
537 "Return non-nil if a buffer named BUFFER-NAME gets a special frame. 537 "Return non-nil if a buffer named BUFFER-NAME gets a special frame.
538If the value is t, `display-buffer' or `pop-to-buffer' would 538If the value is t, `display-buffer' or `pop-to-buffer' would
539create a special frame for that buffer using the default frame 539create a special frame for that buffer using the default frame
540parameters. 540parameters.
541 541
542If the value is a list, it is a list of frame parameters that 542If the value is a list, it is a list of frame parameters that
543would be used to make a frame for that buffer. The variables 543would be used to make a frame for that buffer. The variables
544`special-display-buffer-names' and `special-display-regexps' 544`special-display-buffer-names' and `special-display-regexps'
545control this." 545control this."
546 (let (tmp) 546 (let (tmp)
547 (cond 547 (cond
548 ((not (stringp buffer-name))) 548 ((not (stringp buffer-name)))
549 ;; Make sure to return t in the following two cases. 549 ;; Make sure to return t in the following two cases.
550 ((member buffer-name special-display-buffer-names) t) 550 ((member buffer-name special-display-buffer-names) t)
551 ((setq tmp (assoc buffer-name special-display-buffer-names)) (cdr tmp)) 551 ((setq tmp (assoc buffer-name special-display-buffer-names)) (cdr tmp))
552 ((catch 'found 552 ((catch 'found
553 (dolist (regexp special-display-regexps) 553 (dolist (regexp special-display-regexps)
554 (cond 554 (cond
555 ((stringp regexp) 555 ((stringp regexp)
556 (when (string-match-p regexp buffer-name) 556 (when (string-match-p regexp buffer-name)
557 (throw 'found t))) 557 (throw 'found t)))
558 ((and (consp regexp) (stringp (car regexp)) 558 ((and (consp regexp) (stringp (car regexp))
559 (string-match-p (car regexp) buffer-name)) 559 (string-match-p (car regexp) buffer-name))
560 (throw 'found (cdr regexp)))))))))) 560 (throw 'found (cdr regexp))))))))))
561 561
562(defcustom special-display-buffer-names nil 562(defcustom special-display-buffer-names nil
563 "List of buffer names that should have their own special frames. 563 "List of buffer names that should have their own special frames.
564Displaying a buffer with `display-buffer' or `pop-to-buffer', if 564Displaying a buffer with `display-buffer' or `pop-to-buffer', if
565its name is in this list, makes a special frame for it using 565its name is in this list, makes a special frame for it using
566`special-display-function'. See also `special-display-regexps'. 566`special-display-function'. See also `special-display-regexps'.
567 567
568An element of the list can be a list instead of just a string. 568An element of the list can be a list instead of just a string.
569There are two ways to use a list as an element: 569There are two ways to use a list as an element:
570 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...) 570 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
571In the first case, the FRAME-PARAMETERS are pairs of the form 571In the first case, the FRAME-PARAMETERS are pairs of the form
572\(PARAMETER . VALUE); these parameter values are used to create 572\(PARAMETER . VALUE); these parameter values are used to create
573the frame. In the second case, FUNCTION is called with BUFFER as 573the frame. In the second case, FUNCTION is called with BUFFER as
574the first argument, followed by the OTHER-ARGS--it can display 574the first argument, followed by the OTHER-ARGS--it can display
575BUFFER in any way it likes. All this is done by the function 575BUFFER in any way it likes. All this is done by the function
576found in `special-display-function'. 576found in `special-display-function'.
577 577
578If the specified frame parameters include (same-buffer . t), the 578If the specified frame parameters include (same-buffer . t), the
579buffer is displayed in the currently selected window. Otherwise, if 579buffer is displayed in the currently selected window. Otherwise, if
580they include (same-frame . t), the buffer is displayed in a new window 580they include (same-frame . t), the buffer is displayed in a new window
581in the currently selected frame. 581in the currently selected frame.
582 582
583If this variable appears \"not to work\", because you add a name to it 583If this variable appears \"not to work\", because you add a name to it
584but that buffer still appears in the selected window, look at the 584but that buffer still appears in the selected window, look at the
585values of `same-window-buffer-names' and `same-window-regexps'. 585values of `same-window-buffer-names' and `same-window-regexps'.
586Those variables take precedence over this one." 586Those variables take precedence over this one."
587 :type '(repeat (choice :tag "Buffer" 587 :type '(repeat (choice :tag "Buffer"
588 :value "" 588 :value ""
589 (string :format "%v") 589 (string :format "%v")
590 (cons :tag "With attributes" 590 (cons :tag "With attributes"
591 :format "%v" 591 :format "%v"
592 :value ("" . nil) 592 :value ("" . nil)
593 (string :format "%v") 593 (string :format "%v")
594 (repeat :tag "Attributes" 594 (repeat :tag "Attributes"
595 (cons :format "%v" 595 (cons :format "%v"
596 (symbol :tag "Parameter") 596 (symbol :tag "Parameter")
597 (sexp :tag "Value")))))) 597 (sexp :tag "Value"))))))
598 :group 'frames) 598 :group 'frames)
599 599
600(defcustom special-display-regexps nil 600(defcustom special-display-regexps nil
601 "List of regexps saying which buffers should have their own special frames. 601 "List of regexps saying which buffers should have their own special frames.
602When displaying a buffer with `display-buffer' or 602When displaying a buffer with `display-buffer' or
603`pop-to-buffer', if any regexp in this list matches the buffer 603`pop-to-buffer', if any regexp in this list matches the buffer
604name, it makes a special frame for the buffer by calling 604name, it makes a special frame for the buffer by calling
605`special-display-function'. 605`special-display-function'.
606 606
607An element of the list can be a list instead of just a string. 607An element of the list can be a list instead of just a string.
608There are two ways to use a list as an element: 608There are two ways to use a list as an element:
609 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...) 609 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
610In the first case, the FRAME-PARAMETERS are pairs of the form 610In the first case, the FRAME-PARAMETERS are pairs of the form
611\(PARAMETER . VALUE); these parameter values are used to create 611\(PARAMETER . VALUE); these parameter values are used to create
612the frame. In the second case, FUNCTION is called with BUFFER as 612the frame. In the second case, FUNCTION is called with BUFFER as
613the first argument, followed by the OTHER-ARGS--it can display 613the first argument, followed by the OTHER-ARGS--it can display
614the buffer in any way it likes. All this is done by the function 614the buffer in any way it likes. All this is done by the function
615found in `special-display-function'. 615found in `special-display-function'.
616 616
617If the specified frame parameters include (same-buffer . t), the 617If the specified frame parameters include (same-buffer . t), the
618buffer is displayed in the currently selected window. Otherwise, 618buffer is displayed in the currently selected window. Otherwise,
619if they include (same-frame . t), the buffer is displayed in a 619if they include (same-frame . t), the buffer is displayed in a
620new window in the currently selected frame. 620new window in the currently selected frame.
621 621
622If this variable appears \"not to work\", because you add a 622If this variable appears \"not to work\", because you add a
623regexp to it but the matching buffers still appear in the 623regexp to it but the matching buffers still appear in the
624selected window, look at the values of `same-window-buffer-names' 624selected window, look at the values of `same-window-buffer-names'
625and `same-window-regexps'. Those variables take precedence over 625and `same-window-regexps'. Those variables take precedence over
626this one." 626this one."
627 :type '(repeat (choice :tag "Buffer" 627 :type '(repeat (choice :tag "Buffer"
628 :value "" 628 :value ""
629 (regexp :format "%v") 629 (regexp :format "%v")
630 (cons :tag "With attributes" 630 (cons :tag "With attributes"
631 :format "%v" 631 :format "%v"
632 :value ("" . nil) 632 :value ("" . nil)
633 (regexp :format "%v") 633 (regexp :format "%v")
634 (repeat :tag "Attributes" 634 (repeat :tag "Attributes"
635 (cons :format "%v" 635 (cons :format "%v"
636 (symbol :tag "Parameter") 636 (symbol :tag "Parameter")
637 (sexp :tag "Value")))))) 637 (sexp :tag "Value"))))))
638 :group 'frames) 638 :group 'frames)
639 639
640(defcustom special-display-function 'special-display-popup-frame 640(defcustom special-display-function 'special-display-popup-frame
641 "Function to call to make a new frame for a special buffer. 641 "Function to call to make a new frame for a special buffer.
642It is called with two arguments, the buffer and optional buffer 642It is called with two arguments, the buffer and optional buffer
643specific data, and should return a window displaying that buffer. 643specific data, and should return a window displaying that buffer.
644The default value normally makes a separate frame for the buffer, 644The default value normally makes a separate frame for the buffer,
645using `special-display-frame-alist' to specify the frame 645using `special-display-frame-alist' to specify the frame
646parameters. 646parameters.
647 647
648But if the buffer specific data includes (same-buffer . t) then 648But if the buffer specific data includes (same-buffer . t) then
649the buffer is displayed in the current selected window. 649the buffer is displayed in the current selected window.
650Otherwise if it includes (same-frame . t) then the buffer is 650Otherwise if it includes (same-frame . t) then the buffer is
651displayed in a new window in the currently selected frame. 651displayed in a new window in the currently selected frame.
652 652
653A buffer is special if it is listed in 653A buffer is special if it is listed in
654`special-display-buffer-names' or matches a regexp in 654`special-display-buffer-names' or matches a regexp in
655`special-display-regexps'." 655`special-display-regexps'."
656 :type 'function 656 :type 'function
657 :group 'frames) 657 :group 'frames)
658 658
659(defun same-window-p (buffer-name) 659(defun same-window-p (buffer-name)
660 "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window. 660 "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window.
661This function returns non-nil if `display-buffer' or 661This function returns non-nil if `display-buffer' or
662`pop-to-buffer' would show a buffer named BUFFER-NAME in the 662`pop-to-buffer' would show a buffer named BUFFER-NAME in the
663selected rather than \(as usual\) some other window. See 663selected rather than \(as usual\) some other window. See
664`same-window-buffer-names' and `same-window-regexps'." 664`same-window-buffer-names' and `same-window-regexps'."
665 (cond 665 (cond
666 ((not (stringp buffer-name))) 666 ((not (stringp buffer-name)))
667 ;; The elements of `same-window-buffer-names' can be buffer 667 ;; The elements of `same-window-buffer-names' can be buffer
668 ;; names or cons cells whose cars are buffer names. 668 ;; names or cons cells whose cars are buffer names.
669 ((member buffer-name same-window-buffer-names)) 669 ((member buffer-name same-window-buffer-names))
670 ((assoc buffer-name same-window-buffer-names)) 670 ((assoc buffer-name same-window-buffer-names))
671 ((catch 'found 671 ((catch 'found
672 (dolist (regexp same-window-regexps) 672 (dolist (regexp same-window-regexps)
673 ;; The elements of `same-window-regexps' can be regexps 673 ;; The elements of `same-window-regexps' can be regexps
674 ;; or cons cells whose cars are regexps. 674 ;; or cons cells whose cars are regexps.
675 (when (or (and (stringp regexp) 675 (when (or (and (stringp regexp)
676 (string-match regexp buffer-name)) 676 (string-match regexp buffer-name))
677 (and (consp regexp) (stringp (car regexp)) 677 (and (consp regexp) (stringp (car regexp))
678 (string-match-p (car regexp) buffer-name))) 678 (string-match-p (car regexp) buffer-name)))
679 (throw 'found t))))))) 679 (throw 'found t)))))))
680 680
681(defcustom same-window-buffer-names nil 681(defcustom same-window-buffer-names nil
682 "List of names of buffers that should appear in the \"same\" window. 682 "List of names of buffers that should appear in the \"same\" window.
683`display-buffer' and `pop-to-buffer' show a buffer whose name is 683`display-buffer' and `pop-to-buffer' show a buffer whose name is
684on this list in the selected rather than some other window. 684on this list in the selected rather than some other window.
685 685
686An element of this list can be a cons cell instead of just a 686An element of this list can be a cons cell instead of just a
687string. In that case the car must be a string specifying the 687string. In that case the car must be a string specifying the
688buffer name. This is for compatibility with 688buffer name. This is for compatibility with
689`special-display-buffer-names'; the cdr of the cons cell is 689`special-display-buffer-names'; the cdr of the cons cell is
690ignored. 690ignored.
691 691
692See also `same-window-regexps'." 692See also `same-window-regexps'."
693 :type '(repeat (string :format "%v")) 693 :type '(repeat (string :format "%v"))
694 :group 'windows) 694 :group 'windows)
695 695
696(defcustom same-window-regexps nil 696(defcustom same-window-regexps nil
697 "List of regexps saying which buffers should appear in the \"same\" window. 697 "List of regexps saying which buffers should appear in the \"same\" window.
698`display-buffer' and `pop-to-buffer' show a buffer whose name 698`display-buffer' and `pop-to-buffer' show a buffer whose name
699matches a regexp on this list in the selected rather than some 699matches a regexp on this list in the selected rather than some
700other window. 700other window.
701 701
702An element of this list can be a cons cell instead of just a 702An element of this list can be a cons cell instead of just a
703string. In that case the car must be a string, which specifies 703string. In that case the car must be a string, which specifies
704the buffer name. This is for compatibility with 704the buffer name. This is for compatibility with
705`special-display-buffer-names'; the cdr of the cons cell is 705`special-display-buffer-names'; the cdr of the cons cell is
706ignored. 706ignored.
707 707
708See also `same-window-buffer-names'." 708See also `same-window-buffer-names'."
709 :type '(repeat (regexp :format "%v")) 709 :type '(repeat (regexp :format "%v"))
710 :group 'windows) 710 :group 'windows)
711 711
712(defcustom pop-up-frames nil 712(defcustom pop-up-frames nil
713 "Non-nil means `display-buffer' should make a separate frame." 713 "Non-nil means `display-buffer' should make a separate frame."
714 :type 'boolean 714 :type 'boolean
715 :group 'windows) 715 :group 'windows)
716 716
717(defcustom display-buffer-reuse-frames nil 717(defcustom display-buffer-reuse-frames nil
718 "Non-nil means `display-buffer' should reuse frames. 718 "Non-nil means `display-buffer' should reuse frames.
719If the buffer in question is already displayed in a frame, raise 719If the buffer in question is already displayed in a frame, raise
720that frame." 720that frame."
721 :type 'boolean 721 :type 'boolean
722 :version "21.1" 722 :version "21.1"
723 :group 'windows) 723 :group 'windows)
724 724
725(defcustom pop-up-windows t 725(defcustom pop-up-windows t
726 "Non-nil means `display-buffer' should make a new window." 726 "Non-nil means `display-buffer' should make a new window."
727 :type 'boolean 727 :type 'boolean
728 :group 'windows) 728 :group 'windows)
729 729
730(defcustom split-height-threshold 80 730(defcustom split-height-threshold 80
731 "Minimum height of window to be split vertically. 731 "Minimum height of window to be split vertically.
732If the value is a number, `display-buffer' can split a window 732If the value is a number, `display-buffer' can split a window
733only if it has at least as many lines. If the value is nil, 733only if it has at least as many lines. If the value is nil,
734`display-buffer' cannot split a window vertically. 734`display-buffer' cannot split a window vertically.
735 735
736If the window is the only window on its frame, `display-buffer' 736If the window is the only window on its frame, `display-buffer'
737can split it regardless of this value." 737can split it regardless of this value."
738 :type '(choice (const nil) (number :tag "lines")) 738 :type '(choice (const nil) (number :tag "lines"))
739 :version "23.1" 739 :version "23.1"
740 :group 'windows) 740 :group 'windows)
741 741
742(defcustom split-width-threshold 160 742(defcustom split-width-threshold 160
743 "Minimum width of window to be split horizontally. 743 "Minimum width of window to be split horizontally.
744If the value is a number, `display-buffer' can split a window 744If the value is a number, `display-buffer' can split a window
745only if it has at least as many columns. If the value is nil, 745only if it has at least as many columns. If the value is nil,
746`display-buffer' cannot split a window horizontally." 746`display-buffer' cannot split a window horizontally."
747 :type '(choice (const nil) (number :tag "columns")) 747 :type '(choice (const nil) (number :tag "columns"))
748 :version "23.1" 748 :version "23.1"
749 :group 'windows) 749 :group 'windows)
750 750
751(defcustom split-window-preferred-function nil 751(defcustom split-window-preferred-function nil
752 "Function used by `display-buffer' to split windows. 752 "Function used by `display-buffer' to split windows.
753If non-nil, a function called with a window as single argument 753If non-nil, a function called with a window as single argument
754supposed to split that window and return the new window. If the 754supposed to split that window and return the new window. If the
755function returns nil the window is not split. 755function returns nil the window is not split.
756 756
757If nil, `display-buffer' will split the window respecting the 757If nil, `display-buffer' will split the window respecting the
758values of `split-height-threshold' and `split-width-threshold'." 758values of `split-height-threshold' and `split-width-threshold'."
759 :type '(choice (const nil) (function :tag "Function")) 759 :type '(choice (const nil) (function :tag "Function"))
760 :version "23.1" 760 :version "23.1"
761 :group 'windows) 761 :group 'windows)
762 762
763(defun window--splittable-p (window &optional horizontal) 763(defun window--splittable-p (window &optional horizontal)
764 "Return non-nil if window WINDOW can be split evenly. 764 "Return non-nil if window WINDOW can be split evenly.
765Optional argument HORIZONTAL non-nil means check whether WINDOW 765Optional argument HORIZONTAL non-nil means check whether WINDOW
766can be split horizontally. 766can be split horizontally.
767 767
768WINDOW can be split vertically when the following conditions 768WINDOW can be split vertically when the following conditions
769hold: 769hold:
770 770
771- `window-size-fixed' is either nil or equals `width' for the 771- `window-size-fixed' is either nil or equals `width' for the
772 buffer of WINDOW. 772 buffer of WINDOW.
773 773
774- `split-height-threshold' is a number and WINDOW is at least as 774- `split-height-threshold' is a number and WINDOW is at least as
775 high as `split-height-threshold'. 775 high as `split-height-threshold'.
776 776
777- When WINDOW is split evenly, the emanating windows are at least 777- When WINDOW is split evenly, the emanating windows are at least
778 `window-min-height' lines tall and can accommodate at least one 778 `window-min-height' lines tall and can accommodate at least one
779 line plus - if WINDOW has one - a modeline. 779 line plus - if WINDOW has one - a modeline.
780 780
781WINDOW can be split horizontally when the following conditions 781WINDOW can be split horizontally when the following conditions
782hold: 782hold:
783 783
784- `window-size-fixed' is either nil or equals `height' for the 784- `window-size-fixed' is either nil or equals `height' for the
785 buffer of WINDOW. 785 buffer of WINDOW.
786 786
787- `split-width-threshold' is a number and WINDOW is at least as 787- `split-width-threshold' is a number and WINDOW is at least as
788 wide as `split-width-threshold'. 788 wide as `split-width-threshold'.
789 789
790- When WINDOW is split evenly, the emanating windows are at least 790- When WINDOW is split evenly, the emanating windows are at least
791 `window-min-width' or two (whichever is larger) columns wide." 791 `window-min-width' or two (whichever is larger) columns wide."
792 (when (window-live-p window) 792 (when (window-live-p window)
793 (with-current-buffer (window-buffer window) 793 (with-current-buffer (window-buffer window)
794 (if horizontal 794 (if horizontal
795 ;; A window can be split horizontally when its width is not 795 ;; A window can be split horizontally when its width is not
796 ;; fixed, it is at least `split-width-threshold' columns wide 796 ;; fixed, it is at least `split-width-threshold' columns wide
797 ;; and at least twice as wide as `window-min-width' and 2 (the 797 ;; and at least twice as wide as `window-min-width' and 2 (the
798 ;; latter value is hardcoded). 798 ;; latter value is hardcoded).
799 (and (memq window-size-fixed '(nil height)) 799 (and (memq window-size-fixed '(nil height))
800 ;; Testing `window-full-width-p' here hardly makes any 800 ;; Testing `window-full-width-p' here hardly makes any
801 ;; sense nowadays. This can be done more intuitively by 801 ;; sense nowadays. This can be done more intuitively by
802 ;; setting up `split-width-threshold' appropriately. 802 ;; setting up `split-width-threshold' appropriately.
803 (numberp split-width-threshold) 803 (numberp split-width-threshold)
804 (>= (window-width window) 804 (>= (window-width window)
805 (max split-width-threshold 805 (max split-width-threshold
806 (* 2 (max window-min-width 2))))) 806 (* 2 (max window-min-width 2)))))
807 ;; A window can be split vertically when its height is not 807 ;; A window can be split vertically when its height is not
808 ;; fixed, it is at least `split-height-threshold' lines high, 808 ;; fixed, it is at least `split-height-threshold' lines high,
809 ;; and it is at least twice as high as `window-min-height' and 2 809 ;; and it is at least twice as high as `window-min-height' and 2
810 ;; if it has a modeline or 1. 810 ;; if it has a modeline or 1.
811 (and (memq window-size-fixed '(nil width)) 811 (and (memq window-size-fixed '(nil width))
812 (numberp split-height-threshold) 812 (numberp split-height-threshold)
813 (>= (window-height window) 813 (>= (window-height window)
814 (max split-height-threshold 814 (max split-height-threshold
815 (* 2 (max window-min-height 815 (* 2 (max window-min-height
816 (if mode-line-format 2 1)))))))))) 816 (if mode-line-format 2 1))))))))))
817 817
818(defun window--try-to-split-window (window) 818(defun window--try-to-split-window (window)
819 "Split window WINDOW if it is splittable. 819 "Split window WINDOW if it is splittable.
820See `window--splittable-p' for how to determine whether a window 820See `window--splittable-p' for how to determine whether a window
821is splittable. If WINDOW can be split, return the value returned 821is splittable. If WINDOW can be split, return the value returned
822by `split-window' or `split-window-preferred-function'." 822by `split-window' or `split-window-preferred-function'."
823 (when (and (window-live-p window) 823 (when (and (window-live-p window)
824 (not (frame-parameter (window-frame window) 'unsplittable))) 824 (not (frame-parameter (window-frame window) 'unsplittable)))
825 (if (functionp split-window-preferred-function) 825 (if (functionp split-window-preferred-function)
826 ;; `split-window-preferred-function' is specified, so use it. 826 ;; `split-window-preferred-function' is specified, so use it.
827 (funcall split-window-preferred-function window) 827 (funcall split-window-preferred-function window)
828 (or (and (window--splittable-p window) 828 (or (and (window--splittable-p window)
829 ;; Split window vertically. 829 ;; Split window vertically.
830 (split-window window)) 830 (split-window window))
831 (and (window--splittable-p window t) 831 (and (window--splittable-p window t)
832 ;; Split window horizontally. 832 ;; Split window horizontally.
833 (split-window window nil t)) 833 (split-window window nil t))
834 (and (eq window (frame-root-window (window-frame window))) 834 (and (eq window (frame-root-window (window-frame window)))
835 (not (window-minibuffer-p window)) 835 (not (window-minibuffer-p window))
836 ;; If WINDOW is the only window on its frame and not the 836 ;; If WINDOW is the only window on its frame and not the
837 ;; minibuffer window, attempt to split it vertically 837 ;; minibuffer window, attempt to split it vertically
838 ;; disregarding the value of `split-height-threshold'. 838 ;; disregarding the value of `split-height-threshold'.
839 (let ((split-height-threshold 0)) 839 (let ((split-height-threshold 0))
840 (and (window--splittable-p window) 840 (and (window--splittable-p window)
841 (split-window window)))))))) 841 (split-window window))))))))
842 842
843(defun window--frame-usable-p (frame) 843(defun window--frame-usable-p (frame)
844 "Return frame FRAME if it can be used to display another buffer." 844 "Return frame FRAME if it can be used to display another buffer."
845 (when (framep frame) 845 (when (framep frame)
846 (let ((window (frame-root-window frame))) 846 (let ((window (frame-root-window frame)))
847 ;; `frame-root-window' may be an internal window which is considered 847 ;; `frame-root-window' may be an internal window which is considered
848 ;; "dead" by `window-live-p'. Hence if `window' is not live we 848 ;; "dead" by `window-live-p'. Hence if `window' is not live we
849 ;; implicitly know that `frame' has a visible window we can use. 849 ;; implicitly know that `frame' has a visible window we can use.
850 (when (or (not (window-live-p window)) 850 (when (or (not (window-live-p window))
851 (and (not (window-minibuffer-p window)) 851 (and (not (window-minibuffer-p window))
852 (not (window-dedicated-p window)))) 852 (not (window-dedicated-p window))))
853 frame)))) 853 frame))))
854 854
855(defcustom even-window-heights t 855(defcustom even-window-heights t
856 "If non-nil `display-buffer' will try to even window heights. 856 "If non-nil `display-buffer' will try to even window heights.
857Otherwise `display-buffer' will leave the window configuration 857Otherwise `display-buffer' will leave the window configuration
858alone. Heights are evened only when `display-buffer' chooses a 858alone. Heights are evened only when `display-buffer' chooses a
859window that appears above or below the selected window." 859window that appears above or below the selected window."
860 :type 'boolean 860 :type 'boolean
861 :group 'windows) 861 :group 'windows)
862 862
863(defun window--even-window-heights (window) 863(defun window--even-window-heights (window)
864 "Even heights of window WINDOW and selected window. 864 "Even heights of window WINDOW and selected window.
865Do this only if these windows are vertically adjacent to each 865Do this only if these windows are vertically adjacent to each
866other, `even-window-heights' is non-nil, and the selected window 866other, `even-window-heights' is non-nil, and the selected window
867is higher than WINDOW." 867is higher than WINDOW."
868 (when (and even-window-heights 868 (when (and even-window-heights
869 (not (eq window (selected-window))) 869 (not (eq window (selected-window)))
870 ;; Don't resize minibuffer windows. 870 ;; Don't resize minibuffer windows.
871 (not (window-minibuffer-p (selected-window))) 871 (not (window-minibuffer-p (selected-window)))
872 (> (window-height (selected-window)) (window-height window)) 872 (> (window-height (selected-window)) (window-height window))
873 (eq (window-frame window) (window-frame (selected-window))) 873 (eq (window-frame window) (window-frame (selected-window)))
874 (let ((sel-edges (window-edges (selected-window))) 874 (let ((sel-edges (window-edges (selected-window)))
875 (win-edges (window-edges window))) 875 (win-edges (window-edges window)))
876 (and (= (nth 0 sel-edges) (nth 0 win-edges)) 876 (and (= (nth 0 sel-edges) (nth 0 win-edges))
877 (= (nth 2 sel-edges) (nth 2 win-edges)) 877 (= (nth 2 sel-edges) (nth 2 win-edges))
878 (or (= (nth 1 sel-edges) (nth 3 win-edges)) 878 (or (= (nth 1 sel-edges) (nth 3 win-edges))
879 (= (nth 3 sel-edges) (nth 1 win-edges)))))) 879 (= (nth 3 sel-edges) (nth 1 win-edges))))))
880 (let ((window-min-height 1)) 880 (let ((window-min-height 1))
881 ;; Don't throw an error if we can't even window heights for 881 ;; Don't throw an error if we can't even window heights for
882 ;; whatever reason. 882 ;; whatever reason.
883 (condition-case nil 883 (condition-case nil
884 (enlarge-window (/ (- (window-height window) (window-height)) 2)) 884 (enlarge-window (/ (- (window-height window) (window-height)) 2))
885 (error nil))))) 885 (error nil)))))
886 886
887(defun window--display-buffer-1 (window) 887(defun window--display-buffer-1 (window)
888 "Deiconify the frame containing the window WINDOW. 888 "Deiconify the frame containing the window WINDOW.
889Do not deiconify the selected frame. Return WINDOW." 889Do not deiconify the selected frame. Return WINDOW."
890 (let* ((frame (window-frame window)) 890 (let* ((frame (window-frame window))
891 (visible (frame-visible-p frame))) 891 (visible (frame-visible-p frame)))
892 (unless (or (not visible) 892 (unless (or (not visible)
893 ;; Assume the selected frame is already visible enough. 893 ;; Assume the selected frame is already visible enough.
894 (eq frame (selected-frame)) 894 (eq frame (selected-frame))
895 ;; Assume the frame from which we invoked the minibuffer 895 ;; Assume the frame from which we invoked the minibuffer
896 ;; is visible. 896 ;; is visible.
897 (and (minibuffer-window-active-p (selected-window)) 897 (and (minibuffer-window-active-p (selected-window))
898 (eq frame (window-frame (minibuffer-selected-window))))) 898 (eq frame (window-frame (minibuffer-selected-window)))))
899 (when (eq visible 'icon) 899 (when (eq visible 'icon)
900 (make-frame-visible frame)) 900 (make-frame-visible frame))
901 (raise-frame frame)) 901 (raise-frame frame))
902 window)) 902 window))
903 903
904(defun window--display-buffer-2 (buffer window) 904(defun window--display-buffer-2 (buffer window)
905 "Display buffer BUFFER in window WINDOW and make its frame visible. 905 "Display buffer BUFFER in window WINDOW and make its frame visible.
906Return WINDOW." 906Return WINDOW."
907 (when (and (buffer-live-p buffer) (window-live-p window)) 907 (when (and (buffer-live-p buffer) (window-live-p window))
908 (set-window-buffer window buffer) 908 (set-window-buffer window buffer)
909 (window--display-buffer-1 window))) 909 (window--display-buffer-1 window)))
910 910
911(defun display-buffer (buffer-or-name &optional not-this-window frame) 911(defun display-buffer (buffer-or-name &optional not-this-window frame)
912 "Make buffer BUFFER-OR-NAME appear in some window but don't select it. 912 "Make buffer BUFFER-OR-NAME appear in some window but don't select it.
913BUFFER-OR-NAME must be a buffer or the name of an existing 913BUFFER-OR-NAME must be a buffer or the name of an existing
914buffer. Return the window chosen to display BUFFER-OR-NAME or 914buffer. Return the window chosen to display BUFFER-OR-NAME or
915nil is no such window is found. 915nil if no such window is found.
916 916
917Optional argument NOT-THIS-WINDOW non-nil means display the 917Optional argument NOT-THIS-WINDOW non-nil means display the
918buffer in a window other than the selected one, even if it is 918buffer in a window other than the selected one, even if it is
919already displayed in the selected window. 919already displayed in the selected window.
920 920
921Optional argument FRAME specifies which frames to investigate 921Optional argument FRAME specifies which frames to investigate
922when the specified buffer is already displayed. If the buffer is 922when the specified buffer is already displayed. If the buffer is
923already displayed in some window on one of these frames simply 923already displayed in some window on one of these frames simply
924return that window. Possible values of FRAME are: 924return that window. Possible values of FRAME are:
925 925
926`visible' - consider windows on all visible frames. 926`visible' - consider windows on all visible frames.
927 927
9280 - consider windows on all visible or iconified frames. 9280 - consider windows on all visible or iconified frames.
929 929
930t - consider windows on all frames. 930t - consider windows on all frames.
931 931
932A specific frame - consider windows on that frame only. 932A specific frame - consider windows on that frame only.
933 933
934nil - consider windows on the selected frame \(actually the 934nil - consider windows on the selected frame \(actually the
935last non-minibuffer frame\) only. If, however, either 935last non-minibuffer frame\) only. If, however, either
936`display-buffer-reuse-frames' or `pop-up-frames' is non-nil, 936`display-buffer-reuse-frames' or `pop-up-frames' is non-nil,
937consider all visible or iconified frames." 937consider all visible or iconified frames."
938 (interactive "BDisplay buffer:\nP") 938 (interactive "BDisplay buffer:\nP")
939 (let* ((can-use-selected-window 939 (let* ((can-use-selected-window
940 ;; The selected window is usable unless either NOT-THIS-WINDOW 940 ;; The selected window is usable unless either NOT-THIS-WINDOW
941 ;; is non-nil, it is dedicated to its buffer, or it is the 941 ;; is non-nil, it is dedicated to its buffer, or it is the
942 ;; `minibuffer-window'. 942 ;; `minibuffer-window'.
943 (not (or not-this-window 943 (not (or not-this-window
944 (window-dedicated-p (selected-window)) 944 (window-dedicated-p (selected-window))
945 (window-minibuffer-p)))) 945 (window-minibuffer-p))))
946 (buffer (if (bufferp buffer-or-name) 946 (buffer (if (bufferp buffer-or-name)
947 buffer-or-name 947 buffer-or-name
948 (get-buffer buffer-or-name))) 948 (get-buffer buffer-or-name)))
949 (name-of-buffer (buffer-name buffer)) 949 (name-of-buffer (buffer-name buffer))
950 ;; `frame-to-use' is the frame where to show `buffer' - either 950 ;; `frame-to-use' is the frame where to show `buffer' - either
951 ;; the selected frame or the last nonminibuffer frame. 951 ;; the selected frame or the last nonminibuffer frame.
952 (frame-to-use 952 (frame-to-use
953 (or (window--frame-usable-p (selected-frame)) 953 (or (window--frame-usable-p (selected-frame))
954 (window--frame-usable-p (last-nonminibuffer-frame)))) 954 (window--frame-usable-p (last-nonminibuffer-frame))))
955 ;; `window-to-use' is the window we use for showing `buffer'. 955 ;; `window-to-use' is the window we use for showing `buffer'.
956 window-to-use) 956 window-to-use)
957 (cond 957 (cond
958 ((not (buffer-live-p buffer)) 958 ((not (buffer-live-p buffer))
959 (error "No such buffer %s" buffer)) 959 (error "No such buffer %s" buffer))
960 (display-buffer-function 960 (display-buffer-function
961 ;; Let `display-buffer-function' do the job. 961 ;; Let `display-buffer-function' do the job.
962 (funcall display-buffer-function buffer not-this-window)) 962 (funcall display-buffer-function buffer not-this-window))
963 ((and (not not-this-window) 963 ((and (not not-this-window)
964 (eq (window-buffer (selected-window)) buffer)) 964 (eq (window-buffer (selected-window)) buffer))
965 ;; The selected window already displays BUFFER and 965 ;; The selected window already displays BUFFER and
966 ;; `not-this-window' is nil, so use it. 966 ;; `not-this-window' is nil, so use it.
967 (window--display-buffer-1 (selected-window))) 967 (window--display-buffer-1 (selected-window)))
968 ((and can-use-selected-window (same-window-p name-of-buffer)) 968 ((and can-use-selected-window (same-window-p name-of-buffer))
969 ;; If the buffer's name tells us to use the selected window do so. 969 ;; If the buffer's name tells us to use the selected window do so.
970 (window--display-buffer-2 buffer (selected-window))) 970 (window--display-buffer-2 buffer (selected-window)))
971 ((let ((frames (or frame 971 ((let ((frames (or frame
972 (and (or pop-up-frames display-buffer-reuse-frames 972 (and (or pop-up-frames display-buffer-reuse-frames
973 (not (last-nonminibuffer-frame))) 973 (not (last-nonminibuffer-frame)))
974 0) 974 0)
975 (last-nonminibuffer-frame)))) 975 (last-nonminibuffer-frame))))
976 (and (setq window-to-use (get-buffer-window buffer frames)) 976 (and (setq window-to-use (get-buffer-window buffer frames))
977 (or can-use-selected-window 977 (or can-use-selected-window
978 (not (eq (selected-window) window-to-use))))) 978 (not (eq (selected-window) window-to-use)))))
979 ;; If the buffer is already displayed in some window use that. 979 ;; If the buffer is already displayed in some window use that.
980 (window--display-buffer-1 window-to-use)) 980 (window--display-buffer-1 window-to-use))
981 ((and special-display-function 981 ((and special-display-function
982 ;; `special-display-p' returns either t or a list of frame 982 ;; `special-display-p' returns either t or a list of frame
983 ;; parameters to pass to `special-display-function'. 983 ;; parameters to pass to `special-display-function'.
984 (let ((pars (special-display-p name-of-buffer))) 984 (let ((pars (special-display-p name-of-buffer)))
985 (when pars 985 (when pars
986 (funcall special-display-function 986 (funcall special-display-function
987 buffer (if (listp pars) pars)))))) 987 buffer (if (listp pars) pars))))))
988 ((or pop-up-frames (not frame-to-use)) 988 ((or pop-up-frames (not frame-to-use))
989 ;; We want or need a new frame. 989 ;; We want or need a new frame.
990 (window--display-buffer-2 990 (window--display-buffer-2
991 buffer (frame-selected-window (funcall pop-up-frame-function)))) 991 buffer (frame-selected-window (funcall pop-up-frame-function))))
992 ((and pop-up-windows 992 ((and pop-up-windows
993 ;; Make a new window. 993 ;; Make a new window.
994 (or (not (frame-parameter frame-to-use 'unsplittable)) 994 (or (not (frame-parameter frame-to-use 'unsplittable))
995 ;; If the selected frame cannot be split look at 995 ;; If the selected frame cannot be split look at
996 ;; `last-nonminibuffer-frame'. 996 ;; `last-nonminibuffer-frame'.
997 (and (eq frame-to-use (selected-frame)) 997 (and (eq frame-to-use (selected-frame))
998 (setq frame-to-use (last-nonminibuffer-frame)) 998 (setq frame-to-use (last-nonminibuffer-frame))
999 (window--frame-usable-p frame-to-use) 999 (window--frame-usable-p frame-to-use)
1000 (not (frame-parameter frame-to-use 'unsplittable)))) 1000 (not (frame-parameter frame-to-use 'unsplittable))))
1001 ;; Attempt to split largest or least recently used window. 1001 ;; Attempt to split largest or least recently used window.
1002 (setq window-to-use 1002 (setq window-to-use
1003 (or (window--try-to-split-window 1003 (or (window--try-to-split-window
1004 (get-largest-window frame-to-use t)) 1004 (get-largest-window frame-to-use t))
1005 (window--try-to-split-window 1005 (window--try-to-split-window
1006 (get-lru-window frame-to-use t)))) 1006 (get-lru-window frame-to-use t))))
1007 (window--display-buffer-2 buffer window-to-use))) 1007 (window--display-buffer-2 buffer window-to-use)))
1008 ((setq window-to-use 1008 ((setq window-to-use
1009 ;; Reuse an existing window. 1009 ;; Reuse an existing window.
1010 (or (get-lru-window frame-to-use) 1010 (or (get-lru-window frame-to-use)
1011 (get-buffer-window buffer 'visible) 1011 (get-buffer-window buffer 'visible)
1012 (get-largest-window 'visible nil) 1012 (get-largest-window 'visible nil)
1013 (get-buffer-window buffer 0) 1013 (get-buffer-window buffer 0)
1014 (get-largest-window 0 nil) 1014 (get-largest-window 0 nil)
1015 (frame-selected-window (funcall pop-up-frame-function)))) 1015 (frame-selected-window (funcall pop-up-frame-function))))
1016 (window--even-window-heights window-to-use) 1016 (window--even-window-heights window-to-use)
1017 (window--display-buffer-2 buffer window-to-use))))) 1017 (window--display-buffer-2 buffer window-to-use)))))
1018 1018
1019(defun pop-to-buffer (buffer-or-name &optional other-window norecord) 1019(defun pop-to-buffer (buffer-or-name &optional other-window norecord)
1020 "Select buffer BUFFER-OR-NAME in some window, preferably a different one. 1020 "Select buffer BUFFER-OR-NAME in some window, preferably a different one.
1021BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or 1021BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
1022nil. If BUFFER-OR-NAME is a string not naming an existent 1022nil. If BUFFER-OR-NAME is a string not naming an existent
1023buffer, create a buffer with that name. If BUFFER-OR-NAME is 1023buffer, create a buffer with that name. If BUFFER-OR-NAME is
1024nil, choose some other buffer. 1024nil, choose some other buffer.
1025 1025
1026If `pop-up-windows' is non-nil, windows can be split to display 1026If `pop-up-windows' is non-nil, windows can be split to display
1027the buffer. If optional second arg OTHER-WINDOW is non-nil, 1027the buffer. If optional second arg OTHER-WINDOW is non-nil,
1028insist on finding another window even if the specified buffer is 1028insist on finding another window even if the specified buffer is
1029already visible in the selected window, and ignore 1029already visible in the selected window, and ignore
1030`same-window-regexps' and `same-window-buffer-names'. 1030`same-window-regexps' and `same-window-buffer-names'.
1031 1031
1032This function returns the buffer it switched to. This uses the 1032This function returns the buffer it switched to. This uses the
1033function `display-buffer' as a subroutine; see the documentation 1033function `display-buffer' as a subroutine; see the documentation
1034of `display-buffer' for additional customization information. 1034of `display-buffer' for additional customization information.
1035 1035
1036Optional third arg NORECORD non-nil means do not put this buffer 1036Optional third arg NORECORD non-nil means do not put this buffer
1037at the front of the list of recently selected ones." 1037at the front of the list of recently selected ones."
1038 (let ((buffer 1038 (let ((buffer
1039 ;; FIXME: This behavior is carried over from the previous C version 1039 ;; FIXME: This behavior is carried over from the previous C version
1040 ;; of pop-to-buffer, but really we should use just 1040 ;; of pop-to-buffer, but really we should use just
1041 ;; `get-buffer' here. 1041 ;; `get-buffer' here.
1042 (if (null buffer-or-name) (other-buffer (current-buffer)) 1042 (if (null buffer-or-name) (other-buffer (current-buffer))
1043 (or (get-buffer buffer-or-name) 1043 (or (get-buffer buffer-or-name)
1044 (let ((buf (get-buffer-create buffer-or-name))) 1044 (let ((buf (get-buffer-create buffer-or-name)))
1045 (set-buffer-major-mode buf) 1045 (set-buffer-major-mode buf)
1046 buf))))) 1046 buf)))))
1047 (set-buffer buffer) 1047 (set-buffer buffer)
1048 (select-window (display-buffer buffer other-window) norecord) 1048 (select-window (display-buffer buffer other-window) norecord)
1049 buffer)) 1049 buffer))
1050 1050
1051;; I think this should be the default; I think people will prefer it--rms. 1051;; I think this should be the default; I think people will prefer it--rms.
1052(defcustom split-window-keep-point t 1052(defcustom split-window-keep-point t
1053 "If non-nil, \\[split-window-vertically] keeps the original point \ 1053 "If non-nil, \\[split-window-vertically] keeps the original point \
1054in both children. 1054in both children.
1055This is often more convenient for editing. 1055This is often more convenient for editing.
1056If nil, adjust point in each of the two windows to minimize redisplay. 1056If nil, adjust point in each of the two windows to minimize redisplay.
1057This is convenient on slow terminals, but point can move strangely. 1057This is convenient on slow terminals, but point can move strangely.
1058 1058
1059This option applies only to `split-window-vertically' and 1059This option applies only to `split-window-vertically' and
1060functions that call it. `split-window' always keeps the original 1060functions that call it. `split-window' always keeps the original
1061point in both children." 1061point in both children."
1062 :type 'boolean 1062 :type 'boolean
1063 :group 'windows) 1063 :group 'windows)
1064 1064
1065(defun split-window-vertically (&optional arg) 1065(defun split-window-vertically (&optional arg)
1066 "Split current window into two windows, one above the other. 1066 "Split current window into two windows, one above the other.
1067The uppermost window gets ARG lines and the other gets the rest. 1067The uppermost window gets ARG lines and the other gets the rest.
1068Negative ARG means select the size of the lowermost window instead. 1068Negative ARG means select the size of the lowermost window instead.
1069With no argument, split equally or close to it. 1069With no argument, split equally or close to it.
1070Both windows display the same buffer now current. 1070Both windows display the same buffer now current.
1071 1071
1072If the variable `split-window-keep-point' is non-nil, both new windows 1072If the variable `split-window-keep-point' is non-nil, both new windows
1073will get the same value of point as the current window. This is often 1073will get the same value of point as the current window. This is often
1074more convenient for editing. The upper window is the selected window. 1074more convenient for editing. The upper window is the selected window.
1075 1075
1076Otherwise, we choose window starts so as to minimize the amount of 1076Otherwise, we choose window starts so as to minimize the amount of
1077redisplay; this is convenient on slow terminals. The new selected 1077redisplay; this is convenient on slow terminals. The new selected
1078window is the one that the current value of point appears in. The 1078window is the one that the current value of point appears in. The
1079value of point can change if the text around point is hidden by the 1079value of point can change if the text around point is hidden by the
1080new mode line. 1080new mode line.
1081 1081
1082Regardless of the value of `split-window-keep-point', the upper 1082Regardless of the value of `split-window-keep-point', the upper
1083window is the original one and the return value is the new, lower 1083window is the original one and the return value is the new, lower
1084window." 1084window."
1085 (interactive "P") 1085 (interactive "P")
1086 (let ((old-w (selected-window)) 1086 (let ((old-w (selected-window))
1087 (old-point (point)) 1087 (old-point (point))
1088 (size (and arg (prefix-numeric-value arg))) 1088 (size (and arg (prefix-numeric-value arg)))
1089 (window-full-p nil) 1089 (window-full-p nil)
1090 new-w bottom moved) 1090 new-w bottom moved)
1091 (and size (< size 0) (setq size (+ (window-height) size))) 1091 (and size (< size 0) (setq size (+ (window-height) size)))
1092 (setq new-w (split-window nil size)) 1092 (setq new-w (split-window nil size))
1093 (or split-window-keep-point 1093 (or split-window-keep-point
1094 (progn 1094 (progn
1095 (save-excursion 1095 (save-excursion
1096 (set-buffer (window-buffer)) 1096 (set-buffer (window-buffer))
1097 (goto-char (window-start)) 1097 (goto-char (window-start))
1098 (setq moved (vertical-motion (window-height))) 1098 (setq moved (vertical-motion (window-height)))
1099 (set-window-start new-w (point)) 1099 (set-window-start new-w (point))
1100 (if (> (point) (window-point new-w)) 1100 (if (> (point) (window-point new-w))
1101 (set-window-point new-w (point))) 1101 (set-window-point new-w (point)))
1102 (and (= moved (window-height)) 1102 (and (= moved (window-height))
1103 (progn 1103 (progn
1104 (setq window-full-p t) 1104 (setq window-full-p t)
1105 (vertical-motion -1))) 1105 (vertical-motion -1)))
1106 (setq bottom (point))) 1106 (setq bottom (point)))
1107 (and window-full-p 1107 (and window-full-p
1108 (<= bottom (point)) 1108 (<= bottom (point))
1109 (set-window-point old-w (1- bottom))) 1109 (set-window-point old-w (1- bottom)))
1110 (and window-full-p 1110 (and window-full-p
1111 (<= (window-start new-w) old-point) 1111 (<= (window-start new-w) old-point)
1112 (progn 1112 (progn
1113 (set-window-point new-w old-point) 1113 (set-window-point new-w old-point)
1114 (select-window new-w))))) 1114 (select-window new-w)))))
1115 (split-window-save-restore-data new-w old-w))) 1115 (split-window-save-restore-data new-w old-w)))
1116 1116
1117;; This is to avoid compiler warnings. 1117;; This is to avoid compiler warnings.
1118(defvar view-return-to-alist) 1118(defvar view-return-to-alist)
1119 1119
1120(defun split-window-save-restore-data (new-w old-w) 1120(defun split-window-save-restore-data (new-w old-w)
1121 (with-current-buffer (window-buffer) 1121 (with-current-buffer (window-buffer)
1122 (if view-mode 1122 (if view-mode
1123 (let ((old-info (assq old-w view-return-to-alist))) 1123 (let ((old-info (assq old-w view-return-to-alist)))
1124 (if old-info 1124 (if old-info
1125 (push (cons new-w (cons (car (cdr old-info)) t)) 1125 (push (cons new-w (cons (car (cdr old-info)) t))
1126 view-return-to-alist)))) 1126 view-return-to-alist))))
1127 new-w)) 1127 new-w))
1128 1128
1129(defun split-window-horizontally (&optional arg) 1129(defun split-window-horizontally (&optional arg)
1130 "Split current window into two windows side by side. 1130 "Split current window into two windows side by side.
1131This window becomes the leftmost of the two, and gets ARG columns. 1131This window becomes the leftmost of the two, and gets ARG columns.
1132Negative ARG means select the size of the rightmost window instead. 1132Negative ARG means select the size of the rightmost window instead.
1133The argument includes the width of the window's scroll bar; if there 1133The argument includes the width of the window's scroll bar; if there
1134are no scroll bars, it includes the width of the divider column 1134are no scroll bars, it includes the width of the divider column
1135to the window's right, if any. No ARG means split equally. 1135to the window's right, if any. No ARG means split equally.
1136 1136
1137The original, leftmost window remains selected. 1137The original, leftmost window remains selected.
1138The return value is the new, rightmost window." 1138The return value is the new, rightmost window."
1139 (interactive "P") 1139 (interactive "P")
1140 (let ((old-w (selected-window)) 1140 (let ((old-w (selected-window))
1141 (size (and arg (prefix-numeric-value arg)))) 1141 (size (and arg (prefix-numeric-value arg))))
1142 (and size (< size 0) 1142 (and size (< size 0)
1143 (setq size (+ (window-width) size))) 1143 (setq size (+ (window-width) size)))
1144 (split-window-save-restore-data (split-window nil size t) old-w))) 1144 (split-window-save-restore-data (split-window nil size t) old-w)))
1145 1145
1146 1146
1147(defun set-window-text-height (window height) 1147(defun set-window-text-height (window height)
1148 "Sets the height in lines of the text display area of WINDOW to HEIGHT. 1148 "Sets the height in lines of the text display area of WINDOW to HEIGHT.
1149This doesn't include the mode-line (or header-line if any) or any 1149This doesn't include the mode-line (or header-line if any) or any
1150partial-height lines in the text display area. 1150partial-height lines in the text display area.
1151 1151
1152If WINDOW is nil, the selected window is used. 1152If WINDOW is nil, the selected window is used.
1153 1153
1154Note that the current implementation of this function cannot always set 1154Note that the current implementation of this function cannot always set
1155the height exactly, but attempts to be conservative, by allocating more 1155the height exactly, but attempts to be conservative, by allocating more
1156lines than are actually needed in the case where some error may be present." 1156lines than are actually needed in the case where some error may be present."
1157 (let ((delta (- height (window-text-height window)))) 1157 (let ((delta (- height (window-text-height window))))
1158 (unless (zerop delta) 1158 (unless (zerop delta)
1159 ;; Setting window-min-height to a value like 1 can lead to very 1159 ;; Setting window-min-height to a value like 1 can lead to very
1160 ;; bizarre displays because it also allows Emacs to make *other* 1160 ;; bizarre displays because it also allows Emacs to make *other*
1161 ;; windows 1-line tall, which means that there's no more space for 1161 ;; windows 1-line tall, which means that there's no more space for
1162 ;; the modeline. 1162 ;; the modeline.
1163 (let ((window-min-height (min 2 height))) ;One text line plus a modeline. 1163 (let ((window-min-height (min 2 height))) ;One text line plus a modeline.
1164 (if (and window (not (eq window (selected-window)))) 1164 (if (and window (not (eq window (selected-window))))
1165 (save-selected-window 1165 (save-selected-window
1166 (select-window window) 1166 (select-window window)
1167 (enlarge-window delta)) 1167 (enlarge-window delta))
1168 (enlarge-window delta)))))) 1168 (enlarge-window delta))))))
1169 1169
1170 1170
1171(defun enlarge-window-horizontally (arg) 1171(defun enlarge-window-horizontally (arg)
1172 "Make current window ARG columns wider." 1172 "Make current window ARG columns wider."
1173 (interactive "p") 1173 (interactive "p")
1174 (enlarge-window arg t)) 1174 (enlarge-window arg t))
1175 1175
1176(defun shrink-window-horizontally (arg) 1176(defun shrink-window-horizontally (arg)
1177 "Make current window ARG columns narrower." 1177 "Make current window ARG columns narrower."
1178 (interactive "p") 1178 (interactive "p")
1179 (shrink-window arg t)) 1179 (shrink-window arg t))
1180 1180
1181(defun window-buffer-height (window) 1181(defun window-buffer-height (window)
1182 "Return the height (in screen lines) of the buffer that WINDOW is displaying." 1182 "Return the height (in screen lines) of the buffer that WINDOW is displaying."
1183 (with-current-buffer (window-buffer window) 1183 (with-current-buffer (window-buffer window)
1184 (max 1 1184 (max 1
1185 (count-screen-lines (point-min) (point-max) 1185 (count-screen-lines (point-min) (point-max)
1186 ;; If buffer ends with a newline, ignore it when 1186 ;; If buffer ends with a newline, ignore it when
1187 ;; counting height unless point is after it. 1187 ;; counting height unless point is after it.
1188 (eobp) 1188 (eobp)
1189 window)))) 1189 window))))
1190 1190
1191(defun count-screen-lines (&optional beg end count-final-newline window) 1191(defun count-screen-lines (&optional beg end count-final-newline window)
1192 "Return the number of screen lines in the region. 1192 "Return the number of screen lines in the region.
1193The number of screen lines may be different from the number of actual lines, 1193The number of screen lines may be different from the number of actual lines,
1194due to line breaking, display table, etc. 1194due to line breaking, display table, etc.
1195 1195
1196Optional arguments BEG and END default to `point-min' and `point-max' 1196Optional arguments BEG and END default to `point-min' and `point-max'
1197respectively. 1197respectively.
1198 1198
1199If region ends with a newline, ignore it unless optional third argument 1199If region ends with a newline, ignore it unless optional third argument
1200COUNT-FINAL-NEWLINE is non-nil. 1200COUNT-FINAL-NEWLINE is non-nil.
1201 1201
1202The optional fourth argument WINDOW specifies the window used for obtaining 1202The optional fourth argument WINDOW specifies the window used for obtaining
1203parameters such as width, horizontal scrolling, and so on. The default is 1203parameters such as width, horizontal scrolling, and so on. The default is
1204to use the selected window's parameters. 1204to use the selected window's parameters.
1205 1205
1206Like `vertical-motion', `count-screen-lines' always uses the current buffer, 1206Like `vertical-motion', `count-screen-lines' always uses the current buffer,
1207regardless of which buffer is displayed in WINDOW. This makes possible to use 1207regardless of which buffer is displayed in WINDOW. This makes possible to use
1208`count-screen-lines' in any buffer, whether or not it is currently displayed 1208`count-screen-lines' in any buffer, whether or not it is currently displayed
1209in some window." 1209in some window."
1210 (unless beg 1210 (unless beg
1211 (setq beg (point-min))) 1211 (setq beg (point-min)))
1212 (unless end 1212 (unless end
1213 (setq end (point-max))) 1213 (setq end (point-max)))
1214 (if (= beg end) 1214 (if (= beg end)
1215 0 1215 0
1216 (save-excursion 1216 (save-excursion
1217 (save-restriction 1217 (save-restriction
1218 (widen) 1218 (widen)
1219 (narrow-to-region (min beg end) 1219 (narrow-to-region (min beg end)
1220 (if (and (not count-final-newline) 1220 (if (and (not count-final-newline)
1221 (= ?\n (char-before (max beg end)))) 1221 (= ?\n (char-before (max beg end))))
1222 (1- (max beg end)) 1222 (1- (max beg end))
1223 (max beg end))) 1223 (max beg end)))
1224 (goto-char (point-min)) 1224 (goto-char (point-min))
1225 (1+ (vertical-motion (buffer-size) window)))))) 1225 (1+ (vertical-motion (buffer-size) window))))))
1226 1226
1227(defun fit-window-to-buffer (&optional window max-height min-height) 1227(defun fit-window-to-buffer (&optional window max-height min-height)
1228 "Make WINDOW the right height to display its contents exactly. 1228 "Make WINDOW the right height to display its contents exactly.
1229If WINDOW is omitted or nil, it defaults to the selected window. 1229If WINDOW is omitted or nil, it defaults to the selected window.
1230If the optional argument MAX-HEIGHT is supplied, it is the maximum height 1230If the optional argument MAX-HEIGHT is supplied, it is the maximum height
1231 the window is allowed to be, defaulting to the frame height. 1231 the window is allowed to be, defaulting to the frame height.
1232If the optional argument MIN-HEIGHT is supplied, it is the minimum 1232If the optional argument MIN-HEIGHT is supplied, it is the minimum
1233 height the window is allowed to be, defaulting to `window-min-height'. 1233 height the window is allowed to be, defaulting to `window-min-height'.
1234 1234
1235The heights in MAX-HEIGHT and MIN-HEIGHT include the mode-line and/or 1235The heights in MAX-HEIGHT and MIN-HEIGHT include the mode-line and/or
1236header-line." 1236header-line."
1237 (interactive) 1237 (interactive)
1238 1238
1239 (when (null window) 1239 (when (null window)
1240 (setq window (selected-window))) 1240 (setq window (selected-window)))
1241 (when (null max-height) 1241 (when (null max-height)
1242 (setq max-height (frame-height (window-frame window)))) 1242 (setq max-height (frame-height (window-frame window))))
1243 1243
1244 (let* ((buf 1244 (let* ((buf
1245 ;; Buffer that is displayed in WINDOW 1245 ;; Buffer that is displayed in WINDOW
1246 (window-buffer window)) 1246 (window-buffer window))
1247 (window-height 1247 (window-height
1248 ;; The current height of WINDOW 1248 ;; The current height of WINDOW
1249 (window-height window)) 1249 (window-height window))
1250 (desired-height 1250 (desired-height
1251 ;; The height necessary to show the buffer displayed by WINDOW 1251 ;; The height necessary to show the buffer displayed by WINDOW
1252 ;; (`count-screen-lines' always works on the current buffer). 1252 ;; (`count-screen-lines' always works on the current buffer).
1253 (with-current-buffer buf 1253 (with-current-buffer buf
1254 (+ (count-screen-lines) 1254 (+ (count-screen-lines)
1255 ;; If the buffer is empty, (count-screen-lines) is 1255 ;; If the buffer is empty, (count-screen-lines) is
1256 ;; zero. But, even in that case, we need one text line 1256 ;; zero. But, even in that case, we need one text line
1257 ;; for cursor. 1257 ;; for cursor.
1258 (if (= (point-min) (point-max)) 1258 (if (= (point-min) (point-max))
1259 1 0) 1259 1 0)
1260 ;; For non-minibuffers, count the mode-line, if any 1260 ;; For non-minibuffers, count the mode-line, if any
1261 (if (and (not (window-minibuffer-p window)) 1261 (if (and (not (window-minibuffer-p window))
1262 mode-line-format) 1262 mode-line-format)
1263 1 0) 1263 1 0)
1264 ;; Count the header-line, if any 1264 ;; Count the header-line, if any
1265 (if header-line-format 1 0)))) 1265 (if header-line-format 1 0))))
1266 (delta 1266 (delta
1267 ;; Calculate how much the window height has to change to show 1267 ;; Calculate how much the window height has to change to show
1268 ;; desired-height lines, constrained by MIN-HEIGHT and MAX-HEIGHT. 1268 ;; desired-height lines, constrained by MIN-HEIGHT and MAX-HEIGHT.
1269 (- (max (min desired-height max-height) 1269 (- (max (min desired-height max-height)
1270 (or min-height window-min-height)) 1270 (or min-height window-min-height))
1271 window-height))) 1271 window-height)))
1272 1272
1273 ;; Don't try to redisplay with the cursor at the end 1273 ;; Don't try to redisplay with the cursor at the end
1274 ;; on its own line--that would force a scroll and spoil things. 1274 ;; on its own line--that would force a scroll and spoil things.
1275 (when (with-current-buffer buf 1275 (when (with-current-buffer buf
1276 (and (eobp) (bolp) (not (bobp)))) 1276 (and (eobp) (bolp) (not (bobp))))
1277 (set-window-point window (1- (window-point window)))) 1277 (set-window-point window (1- (window-point window))))
1278 1278
1279 (save-selected-window 1279 (save-selected-window
1280 (select-window window) 1280 (select-window window)
1281 1281
1282 ;; Adjust WINDOW to the nominally correct size (which may actually 1282 ;; Adjust WINDOW to the nominally correct size (which may actually
1283 ;; be slightly off because of variable height text, etc). 1283 ;; be slightly off because of variable height text, etc).
1284 (unless (zerop delta) 1284 (unless (zerop delta)
1285 (enlarge-window delta)) 1285 (enlarge-window delta))
1286 1286
1287 ;; Check if the last line is surely fully visible. If not, 1287 ;; Check if the last line is surely fully visible. If not,
1288 ;; enlarge the window. 1288 ;; enlarge the window.
1289 (let ((end (with-current-buffer buf 1289 (let ((end (with-current-buffer buf
1290 (save-excursion 1290 (save-excursion
1291 (goto-char (point-max)) 1291 (goto-char (point-max))
1292 (when (and (bolp) (not (bobp))) 1292 (when (and (bolp) (not (bobp)))
1293 ;; Don't include final newline 1293 ;; Don't include final newline
1294 (backward-char 1)) 1294 (backward-char 1))
1295 (when truncate-lines 1295 (when truncate-lines
1296 ;; If line-wrapping is turned off, test the 1296 ;; If line-wrapping is turned off, test the
1297 ;; beginning of the last line for visibility 1297 ;; beginning of the last line for visibility
1298 ;; instead of the end, as the end of the line 1298 ;; instead of the end, as the end of the line
1299 ;; could be invisible by virtue of extending past 1299 ;; could be invisible by virtue of extending past
1300 ;; the edge of the window. 1300 ;; the edge of the window.
1301 (forward-line 0)) 1301 (forward-line 0))
1302 (point))))) 1302 (point)))))
1303 (set-window-vscroll window 0) 1303 (set-window-vscroll window 0)
1304 (while (and (< desired-height max-height) 1304 (while (and (< desired-height max-height)
1305 (= desired-height (window-height window)) 1305 (= desired-height (window-height window))
1306 (not (pos-visible-in-window-p end window))) 1306 (not (pos-visible-in-window-p end window)))
1307 (enlarge-window 1) 1307 (enlarge-window 1)
1308 (setq desired-height (1+ desired-height))))))) 1308 (setq desired-height (1+ desired-height)))))))
1309 1309
1310(defun shrink-window-if-larger-than-buffer (&optional window) 1310(defun shrink-window-if-larger-than-buffer (&optional window)
1311 "Shrink the WINDOW to be as small as possible to display its contents. 1311 "Shrink the WINDOW to be as small as possible to display its contents.
1312If WINDOW is omitted or nil, it defaults to the selected window. 1312If WINDOW is omitted or nil, it defaults to the selected window.
1313Do not shrink to less than `window-min-height' lines. 1313Do not shrink to less than `window-min-height' lines.
1314Do nothing if the buffer contains more lines than the present window height, 1314Do nothing if the buffer contains more lines than the present window height,
1315or if some of the window's contents are scrolled out of view, 1315or if some of the window's contents are scrolled out of view,
1316or if shrinking this window would also shrink another window, 1316or if shrinking this window would also shrink another window,
1317or if the window is the only window of its frame." 1317or if the window is the only window of its frame."
1318 (interactive) 1318 (interactive)
1319 (when (null window) 1319 (when (null window)
1320 (setq window (selected-window))) 1320 (setq window (selected-window)))
1321 (let* ((frame (window-frame window)) 1321 (let* ((frame (window-frame window))
1322 (mini (frame-parameter frame 'minibuffer)) 1322 (mini (frame-parameter frame 'minibuffer))
1323 (edges (window-edges window))) 1323 (edges (window-edges window)))
1324 (if (and (not (eq window (frame-root-window frame))) 1324 (if (and (not (eq window (frame-root-window frame)))
1325 (window-safely-shrinkable-p) 1325 (window-safely-shrinkable-p)
1326 (pos-visible-in-window-p (point-min) window) 1326 (pos-visible-in-window-p (point-min) window)
1327 (not (eq mini 'only)) 1327 (not (eq mini 'only))
1328 (or (not mini) 1328 (or (not mini)
1329 (let ((mini-window (minibuffer-window frame))) 1329 (let ((mini-window (minibuffer-window frame)))
1330 (or (null mini-window) 1330 (or (null mini-window)
1331 (not (eq frame (window-frame mini-window))) 1331 (not (eq frame (window-frame mini-window)))
1332 (< (nth 3 edges) 1332 (< (nth 3 edges)
1333 (nth 1 (window-edges mini-window))) 1333 (nth 1 (window-edges mini-window)))
1334 (> (nth 1 edges) 1334 (> (nth 1 edges)
1335 (frame-parameter frame 'menu-bar-lines)))))) 1335 (frame-parameter frame 'menu-bar-lines))))))
1336 (fit-window-to-buffer window (window-height window))))) 1336 (fit-window-to-buffer window (window-height window)))))
1337 1337
1338(defun kill-buffer-and-window () 1338(defun kill-buffer-and-window ()
1339 "Kill the current buffer and delete the selected window." 1339 "Kill the current buffer and delete the selected window."
1340 (interactive) 1340 (interactive)
1341 (let ((window-to-delete (selected-window)) 1341 (let ((window-to-delete (selected-window))
1342 (buffer-to-kill (current-buffer)) 1342 (buffer-to-kill (current-buffer))
1343 (delete-window-hook (lambda () 1343 (delete-window-hook (lambda ()
1344 (condition-case nil 1344 (condition-case nil
1345 (delete-window) 1345 (delete-window)
1346 (error nil))))) 1346 (error nil)))))
1347 (unwind-protect 1347 (unwind-protect
1348 (progn 1348 (progn
1349 (add-hook 'kill-buffer-hook delete-window-hook t t) 1349 (add-hook 'kill-buffer-hook delete-window-hook t t)
1350 (if (kill-buffer (current-buffer)) 1350 (if (kill-buffer (current-buffer))
1351 ;; If `delete-window' failed before, we rerun it to regenerate 1351 ;; If `delete-window' failed before, we rerun it to regenerate
1352 ;; the error so it can be seen in the echo area. 1352 ;; the error so it can be seen in the echo area.
1353 (when (eq (selected-window) window-to-delete) 1353 (when (eq (selected-window) window-to-delete)
1354 (delete-window)))) 1354 (delete-window))))
1355 ;; If the buffer is not dead for some reason (probably because 1355 ;; If the buffer is not dead for some reason (probably because
1356 ;; of a `quit' signal), remove the hook again. 1356 ;; of a `quit' signal), remove the hook again.
1357 (condition-case nil 1357 (condition-case nil
1358 (with-current-buffer buffer-to-kill 1358 (with-current-buffer buffer-to-kill
1359 (remove-hook 'kill-buffer-hook delete-window-hook t)) 1359 (remove-hook 'kill-buffer-hook delete-window-hook t))
1360 (error nil))))) 1360 (error nil)))))
1361 1361
1362(defun quit-window (&optional kill window) 1362(defun quit-window (&optional kill window)
1363 "Quit the current buffer. Bury it, and maybe delete the selected frame. 1363 "Quit the current buffer. Bury it, and maybe delete the selected frame.
1364\(The frame is deleted if it contains a dedicated window for the buffer.) 1364\(The frame is deleted if it contains a dedicated window for the buffer.)
1365With a prefix argument, kill the buffer instead. 1365With a prefix argument, kill the buffer instead.
1366 1366
1367Noninteractively, if KILL is non-nil, then kill the current buffer, 1367Noninteractively, if KILL is non-nil, then kill the current buffer,
1368otherwise bury it. 1368otherwise bury it.
1369 1369
1370If WINDOW is non-nil, it specifies a window; we delete that window, 1370If WINDOW is non-nil, it specifies a window; we delete that window,
1371and the buffer that is killed or buried is the one in that window." 1371and the buffer that is killed or buried is the one in that window."
1372 (interactive "P") 1372 (interactive "P")
1373 (let ((buffer (window-buffer window)) 1373 (let ((buffer (window-buffer window))
1374 (frame (window-frame (or window (selected-window)))) 1374 (frame (window-frame (or window (selected-window))))
1375 (window-solitary 1375 (window-solitary
1376 (save-selected-window 1376 (save-selected-window
1377 (if window 1377 (if window
1378 (select-window window)) 1378 (select-window window))
1379 (one-window-p t))) 1379 (one-window-p t)))
1380 window-handled) 1380 window-handled)
1381 1381
1382 (save-selected-window 1382 (save-selected-window
1383 (if window 1383 (if window
1384 (select-window window)) 1384 (select-window window))
1385 (or (window-minibuffer-p) 1385 (or (window-minibuffer-p)
1386 (window-dedicated-p (selected-window)) 1386 (window-dedicated-p (selected-window))
1387 (switch-to-buffer (other-buffer)))) 1387 (switch-to-buffer (other-buffer))))
1388 1388
1389 ;; Get rid of the frame, if it has just one dedicated window 1389 ;; Get rid of the frame, if it has just one dedicated window
1390 ;; and other visible frames exist. 1390 ;; and other visible frames exist.
1391 (and (or (window-minibuffer-p) (window-dedicated-p window)) 1391 (and (or (window-minibuffer-p) (window-dedicated-p window))
1392 (delq frame (visible-frame-list)) 1392 (delq frame (visible-frame-list))
1393 window-solitary 1393 window-solitary
1394 (if (and (eq default-minibuffer-frame frame) 1394 (if (and (eq default-minibuffer-frame frame)
1395 (= 1 (length (minibuffer-frame-list)))) 1395 (= 1 (length (minibuffer-frame-list))))
1396 (setq window nil) 1396 (setq window nil)
1397 (delete-frame frame) 1397 (delete-frame frame)
1398 (setq window-handled t))) 1398 (setq window-handled t)))
1399 1399
1400 ;; Deal with the buffer. 1400 ;; Deal with the buffer.
1401 (if kill 1401 (if kill
1402 (kill-buffer buffer) 1402 (kill-buffer buffer)
1403 (bury-buffer buffer)) 1403 (bury-buffer buffer))
1404 1404
1405 ;; Maybe get rid of the window. 1405 ;; Maybe get rid of the window.
1406 (and window (not window-handled) (not window-solitary) 1406 (and window (not window-handled) (not window-solitary)
1407 (delete-window window)))) 1407 (delete-window window))))
1408 1408
1409(defvar recenter-last-op nil 1409(defvar recenter-last-op nil
1410 "Indicates the last recenter operation performed. 1410 "Indicates the last recenter operation performed.
1411Possible values: `top', `middle', `bottom'.") 1411Possible values: `top', `middle', `bottom'.")
1412 1412
1413(defun recenter-top-bottom (&optional arg) 1413(defun recenter-top-bottom (&optional arg)
1414 "Move current line to window center, top, and bottom, successively. 1414 "Move current line to window center, top, and bottom, successively.
1415With no prefix argument, the first call redraws the frame and 1415With no prefix argument, the first call redraws the frame and
1416 centers point vertically within the window. Successive calls 1416 centers point vertically within the window. Successive calls
1417 scroll the window, placing point on the top, bottom, and middle 1417 scroll the window, placing point on the top, bottom, and middle
1418 consecutively. The cycling order is middle -> top -> bottom. 1418 consecutively. The cycling order is middle -> top -> bottom.
1419 1419
1420A prefix argument is handled like `recenter': 1420A prefix argument is handled like `recenter':
1421 With numeric prefix ARG, move current line to window-line ARG. 1421 With numeric prefix ARG, move current line to window-line ARG.
1422 With plain `C-u', move current line to window center. 1422 With plain `C-u', move current line to window center.
1423 1423
1424Top and bottom destinations are actually `scroll-margin' lines 1424Top and bottom destinations are actually `scroll-margin' lines
1425 the from true window top and bottom." 1425 the from true window top and bottom."
1426 (interactive "P") 1426 (interactive "P")
1427 (cond 1427 (cond
1428 (arg (recenter arg)) ; Always respect ARG. 1428 (arg (recenter arg)) ; Always respect ARG.
1429 ((or (not (eq this-command last-command)) 1429 ((or (not (eq this-command last-command))
1430 (eq recenter-last-op 'bottom)) 1430 (eq recenter-last-op 'bottom))
1431 (setq recenter-last-op 'middle) 1431 (setq recenter-last-op 'middle)
1432 (recenter)) 1432 (recenter))
1433 (t 1433 (t
1434 (let ((this-scroll-margin 1434 (let ((this-scroll-margin
1435 (min (max 0 scroll-margin) 1435 (min (max 0 scroll-margin)
1436 (truncate (/ (window-body-height) 4.0))))) 1436 (truncate (/ (window-body-height) 4.0)))))
1437 (cond ((eq recenter-last-op 'middle) 1437 (cond ((eq recenter-last-op 'middle)
1438 (setq recenter-last-op 'top) 1438 (setq recenter-last-op 'top)
1439 (recenter this-scroll-margin)) 1439 (recenter this-scroll-margin))
1440 ((eq recenter-last-op 'top) 1440 ((eq recenter-last-op 'top)
1441 (setq recenter-last-op 'bottom) 1441 (setq recenter-last-op 'bottom)
1442 (recenter (- -1 this-scroll-margin)))))))) 1442 (recenter (- -1 this-scroll-margin))))))))
1443 1443
1444(define-key global-map [?\C-l] 'recenter-top-bottom) 1444(define-key global-map [?\C-l] 'recenter-top-bottom)
1445 1445
1446(defvar mouse-autoselect-window-timer nil 1446(defvar mouse-autoselect-window-timer nil
1447 "Timer used by delayed window autoselection.") 1447 "Timer used by delayed window autoselection.")
1448 1448
1449(defvar mouse-autoselect-window-position nil 1449(defvar mouse-autoselect-window-position nil
1450 "Last mouse position recorded by delayed window autoselection.") 1450 "Last mouse position recorded by delayed window autoselection.")
1451 1451
1452(defvar mouse-autoselect-window-window nil 1452(defvar mouse-autoselect-window-window nil
1453 "Last window recorded by delayed window autoselection.") 1453 "Last window recorded by delayed window autoselection.")
1454 1454
1455(defvar mouse-autoselect-window-state nil 1455(defvar mouse-autoselect-window-state nil
1456 "When non-nil, special state of delayed window autoselection. 1456 "When non-nil, special state of delayed window autoselection.
1457Possible values are `suspend' \(suspend autoselection after a menu or 1457Possible values are `suspend' \(suspend autoselection after a menu or
1458scrollbar interaction\) and `select' \(the next invocation of 1458scrollbar interaction\) and `select' \(the next invocation of
1459'handle-select-window' shall select the window immediately\).") 1459'handle-select-window' shall select the window immediately\).")
1460 1460
1461(defun mouse-autoselect-window-cancel (&optional force) 1461(defun mouse-autoselect-window-cancel (&optional force)
1462 "Cancel delayed window autoselection. 1462 "Cancel delayed window autoselection.
1463Optional argument FORCE means cancel unconditionally." 1463Optional argument FORCE means cancel unconditionally."
1464 (unless (and (not force) 1464 (unless (and (not force)
1465 ;; Don't cancel for select-window or select-frame events 1465 ;; Don't cancel for select-window or select-frame events
1466 ;; or when the user drags a scroll bar. 1466 ;; or when the user drags a scroll bar.
1467 (or (memq this-command 1467 (or (memq this-command
1468 '(handle-select-window handle-switch-frame)) 1468 '(handle-select-window handle-switch-frame))
1469 (and (eq this-command 'scroll-bar-toolkit-scroll) 1469 (and (eq this-command 'scroll-bar-toolkit-scroll)
1470 (memq (nth 4 (event-end last-input-event)) 1470 (memq (nth 4 (event-end last-input-event))
1471 '(handle end-scroll))))) 1471 '(handle end-scroll)))))
1472 (setq mouse-autoselect-window-state nil) 1472 (setq mouse-autoselect-window-state nil)
1473 (when (timerp mouse-autoselect-window-timer) 1473 (when (timerp mouse-autoselect-window-timer)
1474 (cancel-timer mouse-autoselect-window-timer)) 1474 (cancel-timer mouse-autoselect-window-timer))
1475 (remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel))) 1475 (remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel)))
1476 1476
1477(defun mouse-autoselect-window-start (mouse-position &optional window suspend) 1477(defun mouse-autoselect-window-start (mouse-position &optional window suspend)
1478 "Start delayed window autoselection. 1478 "Start delayed window autoselection.
1479MOUSE-POSITION is the last position where the mouse was seen as returned 1479MOUSE-POSITION is the last position where the mouse was seen as returned
1480by `mouse-position'. Optional argument WINDOW non-nil denotes the 1480by `mouse-position'. Optional argument WINDOW non-nil denotes the
1481window where the mouse was seen. Optional argument SUSPEND non-nil 1481window where the mouse was seen. Optional argument SUSPEND non-nil
1482means suspend autoselection." 1482means suspend autoselection."
1483 ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND. 1483 ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND.
1484 (setq mouse-autoselect-window-position mouse-position) 1484 (setq mouse-autoselect-window-position mouse-position)
1485 (when window (setq mouse-autoselect-window-window window)) 1485 (when window (setq mouse-autoselect-window-window window))
1486 (setq mouse-autoselect-window-state (when suspend 'suspend)) 1486 (setq mouse-autoselect-window-state (when suspend 'suspend))
1487 ;; Install timer which runs `mouse-autoselect-window-select' after 1487 ;; Install timer which runs `mouse-autoselect-window-select' after
1488 ;; `mouse-autoselect-window' seconds. 1488 ;; `mouse-autoselect-window' seconds.
1489 (setq mouse-autoselect-window-timer 1489 (setq mouse-autoselect-window-timer
1490 (run-at-time 1490 (run-at-time
1491 (abs mouse-autoselect-window) nil 'mouse-autoselect-window-select))) 1491 (abs mouse-autoselect-window) nil 'mouse-autoselect-window-select)))
1492 1492
1493(defun mouse-autoselect-window-select () 1493(defun mouse-autoselect-window-select ()
1494 "Select window with delayed window autoselection. 1494 "Select window with delayed window autoselection.
1495If the mouse position has stabilized in a non-selected window, select 1495If the mouse position has stabilized in a non-selected window, select
1496that window. The minibuffer window is selected only if the minibuffer is 1496that window. The minibuffer window is selected only if the minibuffer is
1497active. This function is run by `mouse-autoselect-window-timer'." 1497active. This function is run by `mouse-autoselect-window-timer'."
1498 (condition-case nil 1498 (condition-case nil
1499 (let* ((mouse-position (mouse-position)) 1499 (let* ((mouse-position (mouse-position))
1500 (window 1500 (window
1501 (condition-case nil 1501 (condition-case nil
1502 (window-at (cadr mouse-position) (cddr mouse-position) 1502 (window-at (cadr mouse-position) (cddr mouse-position)
1503 (car mouse-position)) 1503 (car mouse-position))
1504 (error nil)))) 1504 (error nil))))
1505 (cond 1505 (cond
1506 ((or (menu-or-popup-active-p) 1506 ((or (menu-or-popup-active-p)
1507 (and window 1507 (and window
1508 (not (coordinates-in-window-p (cdr mouse-position) window)))) 1508 (not (coordinates-in-window-p (cdr mouse-position) window))))
1509 ;; A menu / popup dialog is active or the mouse is on the scroll-bar 1509 ;; A menu / popup dialog is active or the mouse is on the scroll-bar
1510 ;; of WINDOW, temporarily suspend delayed autoselection. 1510 ;; of WINDOW, temporarily suspend delayed autoselection.
1511 (mouse-autoselect-window-start mouse-position nil t)) 1511 (mouse-autoselect-window-start mouse-position nil t))
1512 ((eq mouse-autoselect-window-state 'suspend) 1512 ((eq mouse-autoselect-window-state 'suspend)
1513 ;; Delayed autoselection was temporarily suspended, reenable it. 1513 ;; Delayed autoselection was temporarily suspended, reenable it.
1514 (mouse-autoselect-window-start mouse-position)) 1514 (mouse-autoselect-window-start mouse-position))
1515 ((and window (not (eq window (selected-window))) 1515 ((and window (not (eq window (selected-window)))
1516 (or (not (numberp mouse-autoselect-window)) 1516 (or (not (numberp mouse-autoselect-window))
1517 (and (> mouse-autoselect-window 0) 1517 (and (> mouse-autoselect-window 0)
1518 ;; If `mouse-autoselect-window' is positive, select 1518 ;; If `mouse-autoselect-window' is positive, select
1519 ;; window if the window is the same as before. 1519 ;; window if the window is the same as before.
1520 (eq window mouse-autoselect-window-window)) 1520 (eq window mouse-autoselect-window-window))
1521 ;; Otherwise select window if the mouse is at the same 1521 ;; Otherwise select window if the mouse is at the same
1522 ;; position as before. Observe that the first test after 1522 ;; position as before. Observe that the first test after
1523 ;; starting autoselection usually fails since the value of 1523 ;; starting autoselection usually fails since the value of
1524 ;; `mouse-autoselect-window-position' recorded there is the 1524 ;; `mouse-autoselect-window-position' recorded there is the
1525 ;; position where the mouse has entered the new window and 1525 ;; position where the mouse has entered the new window and
1526 ;; not necessarily where the mouse has stopped moving. 1526 ;; not necessarily where the mouse has stopped moving.
1527 (equal mouse-position mouse-autoselect-window-position)) 1527 (equal mouse-position mouse-autoselect-window-position))
1528 ;; The minibuffer is a candidate window if it's active. 1528 ;; The minibuffer is a candidate window if it's active.
1529 (or (not (window-minibuffer-p window)) 1529 (or (not (window-minibuffer-p window))
1530 (eq window (active-minibuffer-window)))) 1530 (eq window (active-minibuffer-window))))
1531 ;; Mouse position has stabilized in non-selected window: Cancel 1531 ;; Mouse position has stabilized in non-selected window: Cancel
1532 ;; delayed autoselection and try to select that window. 1532 ;; delayed autoselection and try to select that window.
1533 (mouse-autoselect-window-cancel t) 1533 (mouse-autoselect-window-cancel t)
1534 ;; Select window where mouse appears unless the selected window is the 1534 ;; Select window where mouse appears unless the selected window is the
1535 ;; minibuffer. Use `unread-command-events' in order to execute pre- 1535 ;; minibuffer. Use `unread-command-events' in order to execute pre-
1536 ;; and post-command hooks and trigger idle timers. To avoid delaying 1536 ;; and post-command hooks and trigger idle timers. To avoid delaying
1537 ;; autoselection again, set `mouse-autoselect-window-state'." 1537 ;; autoselection again, set `mouse-autoselect-window-state'."
1538 (unless (window-minibuffer-p (selected-window)) 1538 (unless (window-minibuffer-p (selected-window))
1539 (setq mouse-autoselect-window-state 'select) 1539 (setq mouse-autoselect-window-state 'select)
1540 (setq unread-command-events 1540 (setq unread-command-events
1541 (cons (list 'select-window (list window)) 1541 (cons (list 'select-window (list window))
1542 unread-command-events)))) 1542 unread-command-events))))
1543 ((or (and window (eq window (selected-window))) 1543 ((or (and window (eq window (selected-window)))
1544 (not (numberp mouse-autoselect-window)) 1544 (not (numberp mouse-autoselect-window))
1545 (equal mouse-position mouse-autoselect-window-position)) 1545 (equal mouse-position mouse-autoselect-window-position))
1546 ;; Mouse position has either stabilized in the selected window or at 1546 ;; Mouse position has either stabilized in the selected window or at
1547 ;; `mouse-autoselect-window-position': Cancel delayed autoselection. 1547 ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
1548 (mouse-autoselect-window-cancel t)) 1548 (mouse-autoselect-window-cancel t))
1549 (t 1549 (t
1550 ;; Mouse position has not stabilized yet, resume delayed 1550 ;; Mouse position has not stabilized yet, resume delayed
1551 ;; autoselection. 1551 ;; autoselection.
1552 (mouse-autoselect-window-start mouse-position window)))) 1552 (mouse-autoselect-window-start mouse-position window))))
1553 (error nil))) 1553 (error nil)))
1554 1554
1555(defun handle-select-window (event) 1555(defun handle-select-window (event)
1556 "Handle select-window events." 1556 "Handle select-window events."
1557 (interactive "e") 1557 (interactive "e")
1558 (let ((window (posn-window (event-start event)))) 1558 (let ((window (posn-window (event-start event))))
1559 (unless (or (not (window-live-p window)) 1559 (unless (or (not (window-live-p window))
1560 ;; Don't switch if we're currently in the minibuffer. 1560 ;; Don't switch if we're currently in the minibuffer.
1561 ;; This tries to work around problems where the 1561 ;; This tries to work around problems where the
1562 ;; minibuffer gets unselected unexpectedly, and where 1562 ;; minibuffer gets unselected unexpectedly, and where
1563 ;; you then have to move your mouse all the way down to 1563 ;; you then have to move your mouse all the way down to
1564 ;; the minibuffer to select it. 1564 ;; the minibuffer to select it.
1565 (window-minibuffer-p (selected-window)) 1565 (window-minibuffer-p (selected-window))
1566 ;; Don't switch to minibuffer window unless it's active. 1566 ;; Don't switch to minibuffer window unless it's active.
1567 (and (window-minibuffer-p window) 1567 (and (window-minibuffer-p window)
1568 (not (minibuffer-window-active-p window))) 1568 (not (minibuffer-window-active-p window)))
1569 ;; Don't switch when autoselection shall be delayed. 1569 ;; Don't switch when autoselection shall be delayed.
1570 (and (numberp mouse-autoselect-window) 1570 (and (numberp mouse-autoselect-window)
1571 (not (zerop mouse-autoselect-window)) 1571 (not (zerop mouse-autoselect-window))
1572 (not (eq mouse-autoselect-window-state 'select)) 1572 (not (eq mouse-autoselect-window-state 'select))
1573 (progn 1573 (progn
1574 ;; Cancel any delayed autoselection. 1574 ;; Cancel any delayed autoselection.
1575 (mouse-autoselect-window-cancel t) 1575 (mouse-autoselect-window-cancel t)
1576 ;; Start delayed autoselection from current mouse 1576 ;; Start delayed autoselection from current mouse
1577 ;; position and window. 1577 ;; position and window.
1578 (mouse-autoselect-window-start (mouse-position) window) 1578 (mouse-autoselect-window-start (mouse-position) window)
1579 ;; Executing a command cancels delayed autoselection. 1579 ;; Executing a command cancels delayed autoselection.
1580 (add-hook 1580 (add-hook
1581 'pre-command-hook 'mouse-autoselect-window-cancel)))) 1581 'pre-command-hook 'mouse-autoselect-window-cancel))))
1582 (when mouse-autoselect-window 1582 (when mouse-autoselect-window
1583 ;; Reset state of delayed autoselection. 1583 ;; Reset state of delayed autoselection.
1584 (setq mouse-autoselect-window-state nil) 1584 (setq mouse-autoselect-window-state nil)
1585 ;; Run `mouse-leave-buffer-hook' when autoselecting window. 1585 ;; Run `mouse-leave-buffer-hook' when autoselecting window.
1586 (run-hooks 'mouse-leave-buffer-hook)) 1586 (run-hooks 'mouse-leave-buffer-hook))
1587 (select-window window)))) 1587 (select-window window))))
1588 1588
1589(defun delete-other-windows-vertically (&optional window) 1589(defun delete-other-windows-vertically (&optional window)
1590 "Delete the windows in the same column with WINDOW, but not WINDOW itself. 1590 "Delete the windows in the same column with WINDOW, but not WINDOW itself.
1591This may be a useful alternative binding for \\[delete-other-windows] 1591This may be a useful alternative binding for \\[delete-other-windows]
1592 if you often split windows horizontally." 1592 if you often split windows horizontally."
1593 (interactive) 1593 (interactive)
1594 (let* ((window (or window (selected-window))) 1594 (let* ((window (or window (selected-window)))
1595 (edges (window-edges window)) 1595 (edges (window-edges window))
1596 (w window) delenda) 1596 (w window) delenda)
1597 (while (not (eq (setq w (next-window w 1)) window)) 1597 (while (not (eq (setq w (next-window w 1)) window))
1598 (let ((e (window-edges w))) 1598 (let ((e (window-edges w)))
1599 (when (and (= (car e) (car edges)) 1599 (when (and (= (car e) (car edges))
1600 (= (caddr e) (caddr edges))) 1600 (= (caddr e) (caddr edges)))
1601 (push w delenda)))) 1601 (push w delenda))))
1602 (mapc 'delete-window delenda))) 1602 (mapc 'delete-window delenda)))
1603 1603
1604(defun truncated-partial-width-window-p (&optional window) 1604(defun truncated-partial-width-window-p (&optional window)
1605 "Non-nil if lines in WINDOW are specifically truncated due to its width. 1605 "Non-nil if lines in WINDOW are specifically truncated due to its width.
1606This returns nil if WINDOW is not a partial-width window 1606This returns nil if WINDOW is not a partial-width window
1607 (regardless of the value of `truncate-lines'). 1607 (regardless of the value of `truncate-lines').
1608Otherwise, consult the value of `truncate-partial-width-windows' 1608Otherwise, consult the value of `truncate-partial-width-windows'
1609 for the buffer shown in WINDOW. 1609 for the buffer shown in WINDOW.
1610If WINDOW is nil, use the selected window." 1610If WINDOW is nil, use the selected window."
1611 (unless window 1611 (unless window
1612 (setq window (selected-window))) 1612 (setq window (selected-window)))
1613 (unless (window-full-width-p window) 1613 (unless (window-full-width-p window)
1614 (let ((t-p-w-w (buffer-local-value 'truncate-partial-width-windows 1614 (let ((t-p-w-w (buffer-local-value 'truncate-partial-width-windows
1615 (window-buffer window)))) 1615 (window-buffer window))))
1616 (if (integerp t-p-w-w) 1616 (if (integerp t-p-w-w)
1617 (< (window-width window) t-p-w-w) 1617 (< (window-width window) t-p-w-w)
1618 t-p-w-w)))) 1618 t-p-w-w))))
1619 1619
1620(define-key ctl-x-map "2" 'split-window-vertically) 1620(define-key ctl-x-map "2" 'split-window-vertically)
1621(define-key ctl-x-map "3" 'split-window-horizontally) 1621(define-key ctl-x-map "3" 'split-window-horizontally)
1622(define-key ctl-x-map "}" 'enlarge-window-horizontally) 1622(define-key ctl-x-map "}" 'enlarge-window-horizontally)
1623(define-key ctl-x-map "{" 'shrink-window-horizontally) 1623(define-key ctl-x-map "{" 'shrink-window-horizontally)
1624(define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer) 1624(define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer)
1625(define-key ctl-x-map "+" 'balance-windows) 1625(define-key ctl-x-map "+" 'balance-windows)
1626(define-key ctl-x-4-map "0" 'kill-buffer-and-window) 1626(define-key ctl-x-4-map "0" 'kill-buffer-and-window)
1627 1627
1628;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9 1628;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9
1629;;; window.el ends here 1629;;; window.el ends here