Merge with trunk
[emacs.git] / lisp / window.el
blob57e5b9b883b7f7d11d04bf7b9a4942d591c8f983
1 ;;; window.el --- GNU Emacs window commands aside from those written in C
3 ;; Copyright (C) 1985, 1989, 1992, 1993, 1994, 2000, 2001, 2002,
4 ;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
5 ;; Free Software Foundation, Inc.
7 ;; Maintainer: FSF
8 ;; Keywords: internal
9 ;; Package: emacs
11 ;; This file is part of GNU Emacs.
13 ;; GNU Emacs is free software: you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation, either version 3 of the License, or
16 ;; (at your option) any later version.
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26 ;;; Commentary:
28 ;; TODO
30 ;; Use `walk-window-tree' instead of `window-list-1' wherever possible.
31 ;; Or maybe not because writing code with wwt is not very transparent.
32 ;; Or better, rewrite wwt as a macro.
34 ;; Use (pop-up-windows (or pop-up-windows t)) instead of (pop-up-windows
35 ;; t) wherever this is locally rebound (has some twenty hits in Elisp
36 ;; sources).
38 ;;; Code:
40 (eval-when-compile (require 'cl))
42 (defmacro save-selected-window (&rest body)
43 "Execute BODY, then select the previously selected window.
44 The value returned is the value of the last form in BODY.
46 This macro saves and restores the selected window, as well as the
47 selected window in each frame. If the previously selected window
48 is no longer live, then whatever window is selected at the end of
49 BODY remains selected. If the previously selected window of some
50 frame is no longer live at the end of BODY, that frame's selected
51 window is left alone.
53 This macro saves and restores the current buffer, since otherwise
54 its normal operation could make a different buffer current. The
55 order of recently selected windows and the buffer list ordering
56 are not altered by this macro (unless they are altered in BODY)."
57 (declare (indent 0) (debug t))
58 `(let ((save-selected-window-window (selected-window))
59 ;; It is necessary to save all of these, because calling
60 ;; select-window changes frame-selected-window for whatever
61 ;; frame that window is in.
62 (save-selected-window-alist
63 (mapcar (lambda (frame) (cons frame (frame-selected-window frame)))
64 (frame-list))))
65 (save-current-buffer
66 (unwind-protect
67 (progn ,@body)
68 (dolist (elt save-selected-window-alist)
69 (and (frame-live-p (car elt))
70 (window-live-p (cdr elt))
71 (set-frame-selected-window (car elt) (cdr elt) 'norecord)))
72 (when (window-live-p save-selected-window-window)
73 (select-window save-selected-window-window 'norecord))))))
75 ;; The following two functions are like `window-next' and `window-prev'
76 ;; but the WINDOW argument is _not_ optional (so they don't substitute
77 ;; the selected window for nil), and they return nil when WINDOW doesn't
78 ;; have a parent (like a frame's root window or a minibuffer window).
79 (defsubst window-right (window)
80 "Return WINDOW's right sibling.
81 Return nil if WINDOW is the root window of its frame. WINDOW can
82 be any window."
83 (and window (window-parent window) (window-next window)))
85 (defsubst window-left (window)
86 "Return WINDOW's left sibling.
87 Return nil if WINDOW is the root window of its frame. WINDOW can
88 be any window."
89 (and window (window-parent window) (window-prev window)))
91 (defsubst window-child (window)
92 "Return WINDOW's first child window."
93 (or (window-vchild window) (window-hchild window)))
95 (defsubst window-internal-p (object)
96 "Return t if OBJECT is an internal window and nil otherwise.
97 An internal window is a window that has either a vertical or a
98 horizontal child window."
99 (and (windowp object) (window-child object) t))
101 (defsubst window-any-p (object)
102 "Return t if OBJECT denotes a live or internal window."
103 (and (windowp object)
104 (or (window-buffer object) (window-child object))
107 (defsubst normalize-live-buffer (buffer-or-name)
108 "Return buffer specified by BUFFER-OR-NAME.
109 BUFFER-OR-NAME must be either a buffer or a string naming a live
110 buffer and defaults to the current buffer."
111 (cond
112 ((not buffer-or-name)
113 (current-buffer))
114 ((bufferp buffer-or-name)
115 (if (buffer-live-p buffer-or-name)
116 buffer-or-name
117 (error "Buffer %s is not a live buffer" buffer-or-name)))
118 ((get-buffer buffer-or-name))
120 (error "No such buffer %s" buffer-or-name))))
122 ;; This should probably go to frame.el.
123 (defsubst normalize-live-frame (frame)
124 "Return normalized FRAME argument for live frames."
125 (if frame
126 (if (frame-live-p frame)
127 frame
128 (error "%s is not a live frame" frame))
129 (selected-frame)))
131 (defsubst normalize-any-window (window)
132 "Return normalized WINDOW argument for any window.
133 WINDOW defaults to the selected window."
134 (if window
135 (if (window-any-p window)
136 window
137 (error "%s is not a window" window))
138 (selected-window)))
140 (defsubst normalize-live-window (window)
141 "Return normalized WINDOW argument for live windows.
142 WINDOW defaults to the selected window."
143 (if window
144 (if (and (windowp window) (window-buffer window))
145 window
146 (error "%s is not a live window" window))
147 (selected-window)))
149 (defvar ignore-window-parameters nil
150 "If non-nil standard functions ignore window parameters.
151 The functions currently affected by this are `split-window',
152 `delete-window', `delete-other-windows' and `other-window'.
154 When this variable equals `pre', parameters are not consulted
155 before but are updated after performing the requested operation.
156 When this variable equals `post', parameters are consulted before
157 but are not updated after performing the requested operation.
159 The value t means parameters are not consulted before and not
160 updated after performing the requested operation. Currently any
161 other non-nil value is handled like t.
163 An application may bind this to a non-nil value around calls to
164 these functions. If it does so and the value is not `pre', the
165 application is fully responsible for correctly setting the
166 parameters of all windows participating in the function called.")
168 (defconst window-safe-min-height 1
169 "The absolut minimum number of lines of a window.
170 Anything less might crash Emacs.")
172 (defcustom window-min-height 4
173 "The minimum number of lines of any window.
174 The value has to accomodate a mode- or header-line if present. A
175 value less than `window-safe-min-height' is ignored. The value
176 of this variable is honored when windows are resized or split.
178 Applications should never rebind this variable. To resize a
179 window to a height less than the one specified here, an
180 application should instead call `resize-window' with a non-nil
181 IGNORE argument. In order to have `split-window' make a window
182 shorter, explictly specify the SIZE argument of that function."
183 :type 'integer
184 :version "24.1"
185 :group 'windows)
187 (defconst window-safe-min-width 2
188 "The absolut minimum number of columns of a window.
189 Anything less might crash Emacs.")
191 (defcustom window-min-width 10
192 "The minimum number of columns of any window.
193 The value has to accomodate margins, fringes, or scrollbars if
194 present. A value less than `window-safe-min-width' is ignored.
195 The value of this variable is honored when windows are resized or
196 split.
198 Applications should never rebind this variable. To resize a
199 window to a width less than the one specified here, an
200 application should instead call `resize-window' with a non-nil
201 IGNORE argument. In order to have `split-window' make a window
202 narrower, explictly specify the SIZE argument of that function."
203 :type 'integer
204 :version "24.1"
205 :group 'windows)
207 (defsubst window-iso-combined-p (&optional window horizontal)
208 "Return non-nil if and only if WINDOW is vertically combined.
209 WINDOW can be any window and defaults to the selected one.
210 Optional argument HORIZONTAL non-nil means return non-nil if and
211 only if WINDOW is horizontally combined."
212 (setq window (normalize-any-window window))
213 (when (window-parent window)
214 (if horizontal
215 (window-hchild (window-parent window))
216 (window-vchild (window-parent window)))))
218 (defvar window-size-fixed nil
219 "Non-nil in a buffer means windows displaying the buffer are fixed-size.
220 If the value is `height', then only the window's height is fixed.
221 If the value is `width', then only the window's width is fixed.
222 Any other non-nil value fixes both the width and the height.
223 Emacs won't change the size of any window displaying that buffer,
224 unless you explicitly change the size, or Emacs has no other
225 choice \(like when deleting a neighboring window).")
226 (make-variable-buffer-local 'window-size-fixed)
228 (defsubst window-size-ignore (window ignore)
229 "Return non-nil if IGNORE says to ignore size restrictions for WINDOW."
230 (if (window-any-p ignore) (eq window ignore) ignore))
232 (defun window-min-size (&optional window horizontal ignore)
233 "Return the minimum number of lines of WINDOW.
234 WINDOW can be an arbitrary window and defaults to the selected
235 one. Optional argument HORIZONTAL non-nil means return the
236 minimum number of columns of WINDOW.
238 Optional argument IGNORE non-nil means ignore any restrictions
239 imposed by fixed size windows, `window-min-height' or
240 `window-min-width' settings. IGNORE equal `safe' means live
241 windows may get as small as `window-safe-min-height' lines and
242 `window-safe-min-width' columns. IGNORE a window means ignore
243 restrictions for that window only."
244 (window-min-size-1
245 (normalize-any-window window) horizontal ignore))
247 (defun window-min-size-1 (window horizontal ignore)
248 "Internal function of `window-min-size'."
249 (let ((sub (window-child window)))
250 (if sub
251 (let ((value 0))
252 ;; WINDOW is an internal window.
253 (if (window-iso-combined-p sub horizontal)
254 ;; The minimum size of an iso-combination is the sum of
255 ;; the minimum sizes of its subwindows.
256 (while sub
257 (setq value (+ value
258 (window-min-size-1 sub horizontal ignore)))
259 (setq sub (window-right sub)))
260 ;; The minimum size of an ortho-combination is the maximum of
261 ;; the minimum sizes of its subwindows.
262 (while sub
263 (setq value (max value
264 (window-min-size-1 sub horizontal ignore)))
265 (setq sub (window-right sub))))
266 value)
267 (with-current-buffer (window-buffer window)
268 (cond
269 ((and (not (window-size-ignore window ignore))
270 (window-size-fixed-p window horizontal))
271 ;; The minimum size of a fixed size window is its size.
272 (window-total-size window horizontal))
273 ((or (eq ignore 'safe) (eq ignore window))
274 ;; If IGNORE equals `safe' or WINDOW return the safe values.
275 (if horizontal window-safe-min-width window-safe-min-height))
276 (horizontal
277 ;; For the minimum width of a window take fringes and
278 ;; scroll-bars into account. This is questionable and should
279 ;; be removed as soon as we are able to split (and resize)
280 ;; windows such that the new (or resized) windows can get a
281 ;; size less than the user-specified `window-min-height' and
282 ;; `window-min-width'.
283 (let ((frame (window-frame window))
284 (fringes (window-fringes window))
285 (scroll-bars (window-scroll-bars window)))
286 (max
287 (+ window-safe-min-width
288 (ceiling (car fringes) (frame-char-width frame))
289 (ceiling (cadr fringes) (frame-char-width frame))
290 (cond
291 ((memq (nth 2 scroll-bars) '(left right))
292 (nth 1 scroll-bars))
293 ((memq (frame-parameter frame 'vertical-scroll-bars)
294 '(left right))
295 (ceiling (or (frame-parameter frame 'scroll-bar-width) 14)
296 (frame-char-width)))
297 (t 0)))
298 (if (and (not (window-size-ignore window ignore))
299 (numberp window-min-width))
300 window-min-width
301 0))))
303 ;; For the minimum height of a window take any mode- or
304 ;; header-line into account.
305 (max (+ window-safe-min-height
306 (if header-line-format 1 0)
307 (if mode-line-format 1 0))
308 (if (and (not (window-size-ignore window ignore))
309 (numberp window-min-height))
310 window-min-height
311 0))))))))
313 (defun window-sizable (window delta &optional horizontal ignore)
314 "Return DELTA if DELTA lines can be added to WINDOW.
315 Optional argument HORIZONTAL non-nil means return DELTA if DELTA
316 columns can be added to WINDOW. A return value of zero means
317 that no lines (or columns) can be added to WINDOW.
319 This function looks only at WINDOW and its subwindows. The
320 function `window-resizable' looks at other windows as well.
322 DELTA positive means WINDOW shall be enlarged by DELTA lines or
323 columns. If WINDOW cannot be enlarged by DELTA lines or columns
324 return the maximum value in the range 0..DELTA by which WINDOW
325 can be enlarged.
327 DELTA negative means WINDOW shall be shrunk by -DELTA lines or
328 columns. If WINDOW cannot be shrunk by -DELTA lines or columns,
329 return the minimum value in the range DELTA..0 by which WINDOW
330 can be shrunk.
332 Optional argument IGNORE non-nil means ignore any restrictions
333 imposed by fixed size windows, `window-min-height' or
334 `window-min-width' settings. IGNORE equal `safe' means live
335 windows may get as small as `window-safe-min-height' lines and
336 `window-safe-min-width' columns. IGNORE any window means ignore
337 restrictions for that window only."
338 (setq window (normalize-any-window window))
339 (cond
340 ((< delta 0)
341 (max (- (window-min-size window horizontal ignore)
342 (window-total-size window horizontal))
343 delta))
344 ((window-size-ignore window ignore)
345 delta)
346 ((> delta 0)
347 (if (window-size-fixed-p window horizontal)
349 delta))
350 (t 0)))
352 (defsubst window-sizable-p (window delta &optional horizontal ignore)
353 "Return t if WINDOW can have DELTA lines.
354 For the meaning of the arguments of this function see the
355 doc-string of `window-sizable'."
356 (setq window (normalize-any-window window))
357 (if (> delta 0)
358 (>= (window-sizable window delta horizontal ignore) delta)
359 (<= (window-sizable window delta horizontal ignore) delta)))
361 (defun window-size-fixed-p (&optional window horizontal)
362 "Return non-nil if WINDOW's height is fixed.
363 WINDOW can be an arbitrary window and defaults to the selected
364 window. Optional argument HORIZONTAL non-nil means return
365 non-nil if WINDOW's width is fixed.
367 If this function returns nil, this does not necessarily mean that
368 WINDOW can be resized in the desired direction. The functions
369 `window-resizable' and `window-resizable-p' will tell that."
370 (window-size-fixed-1
371 (normalize-any-window window) horizontal))
373 (defun window-size-fixed-1 (window horizontal)
374 "Internal function for `window-size-fixed-p'."
375 (let ((sub (window-child window)))
376 (catch 'fixed
377 (if sub
378 ;; WINDOW is an internal window.
379 (if (window-iso-combined-p sub horizontal)
380 ;; An iso-combination is fixed size if all its subwindows
381 ;; are fixed-size.
382 (progn
383 (while sub
384 (unless (window-size-fixed-1 sub horizontal)
385 ;; We found a non-fixed-size subwindow, so WINDOW's
386 ;; size is not fixed.
387 (throw 'fixed nil))
388 (setq sub (window-right sub)))
389 ;; All subwindows are fixed-size, so WINDOW's size is
390 ;; fixed.
391 (throw 'fixed t))
392 ;; An ortho-combination is fixed-size if at least one of its
393 ;; subwindows is fixed-size.
394 (while sub
395 (when (window-size-fixed-1 sub horizontal)
396 ;; We found a fixed-size subwindow, so WINDOW's size is
397 ;; fixed.
398 (throw 'fixed t))
399 (setq sub (window-right sub))))
400 ;; WINDOW is a live window.
401 (with-current-buffer (window-buffer window)
402 (if horizontal
403 (memq window-size-fixed '(width t))
404 (memq window-size-fixed '(height t))))))))
406 (defun window-min-delta (&optional window horizontal ignore side noup nodown)
407 "Return number of lines by which WINDOW can be shrunk.
408 WINDOW can be an arbitrary window and defaults to the selected
409 window. Return zero if WINDOW cannot be shrunk.
411 Optional argument HORIZONTAL non-nil means return number of
412 columns by which WINDOW can be shrunk.
414 Optional argument IGNORE non-nil means ignore any restrictions
415 imposed by fixed size windows, `window-min-height' or
416 `window-min-width' settings. IGNORE a window means ignore
417 restrictions for that window only. IGNORE equal `safe' means
418 live windows may get as small as `window-safe-min-height' lines
419 and `window-safe-min-width' columns.
421 Optional argument SIDE `left' means assume only windows to the
422 left of or above WINDOW can be enlarged. Optional argument SIDE
423 `right' means assumes only windows to the right of or below
424 WINDOW can be enlarged.
426 Optional argument NOUP non-nil means don't go up in the window
427 tree but try to enlarge windows within WINDOW's combination only.
429 Optional argument NODOWN non-nil means don't check whether WINDOW
430 and its subwindows can be shrunk."
431 (setq window (normalize-any-window window))
432 (let ((size (window-total-size window horizontal))
433 (minimum (window-min-size window horizontal ignore)))
434 (if (and (not nodown) (= size minimum))
435 ;; Nothing to recover.
437 (window-min-delta-1
438 ;; Think positive.
439 window (- size minimum) horizontal ignore side noup))))
441 (defun window-min-delta-1 (window delta &optional horizontal ignore side noup)
442 "Internal function for `window-min-delta'."
443 (if (not (window-parent window))
444 0 ; delta
445 ;;; (min delta
446 ;;; (- (window-total-size window horizontal)
447 ;;; (window-min-size window horizontal ignore)))
448 (let* ((parent (window-parent window))
449 (sub (window-child parent)))
450 (catch 'done
451 (if (window-iso-combined-p sub horizontal)
452 ;; In an iso-combination throw DELTA if we find at least one
453 ;; subwindow and that subwindow is either non-fixed-size or
454 ;; we can ignore fixed-sizeness.
455 (let ((skip (eq side 'right)))
456 (while sub
457 (cond
458 ((eq sub window)
459 (setq skip (eq side 'left)))
460 (skip)
461 ((and (not (window-size-ignore window ignore))
462 (window-size-fixed-p sub horizontal)))
464 ;; We found a non-fixed-size subwindow.
465 (throw 'done delta)))
466 (setq sub (window-right sub))))
467 ;; In an ortho-combination set DELTA to the minimum value by
468 ;; which other subwindows can shrink.
469 (while sub
470 (unless (eq sub window)
471 (setq delta
472 (min delta
473 (- (window-total-size sub horizontal)
474 (window-min-size sub horizontal ignore)))))
475 (setq sub (window-right sub))))
476 (if noup
477 delta
478 (window-min-delta-1 parent delta horizontal ignore side))))))
480 (defun window-max-delta (&optional window horizontal ignore side noup nodown)
481 "Return maximum number of lines WINDOW by which WINDOW can be enlarged.
482 WINDOW can be an arbitrary window and defaults to the selected
483 window. The return value is zero if WINDOW cannot be enlarged.
485 Optional argument HORIZONTAL non-nil means return maximum number
486 of columns by which WINDOW can be enlarged.
488 Optional argument IGNORE non-nil means ignore any restrictions
489 imposed by fixed size windows, `window-min-height' or
490 `window-min-width' settings. IGNORE a window means ignore
491 restrictions for that window only. IGNORE equal `safe' means
492 live windows may get as small as `window-safe-min-height' lines
493 and `window-safe-min-width' columns.
495 Optional argument SIDE `left' means assume only windows to the
496 left of or below WINDOW can be shrunk. Optional argument SIDE
497 `right' means assumes only windows to the right of or above
498 WINDOW can be shrunk.
500 Optional argument NOUP non-nil means don't go up in the window
501 tree but try to obtain the entire space from windows within
502 WINDOW's combination.
504 Optional argument NODOWN non-nil means do not check whether
505 WINDOW and its subwindows can be enlarged."
506 (setq window (normalize-any-window window))
507 (if (and (not (window-size-ignore window ignore))
508 (not nodown) (window-size-fixed-p window horizontal))
510 (window-max-delta-1 window 0 horizontal ignore side noup)))
512 (defun window-max-delta-1 (window delta &optional horizontal ignore side noup)
513 "Internal function of `window-max-delta'."
514 (if (not (window-parent window))
515 ;; Can't go up. Return DELTA.
516 delta
517 (let* ((parent (window-parent window))
518 (sub (window-child parent)))
519 (catch 'fixed
520 (if (window-iso-combined-p sub horizontal)
521 ;; For an iso-combination calculate how much we can get from
522 ;; other subwindows.
523 (let ((skip (eq side 'right)))
524 (while sub
525 (cond
526 ((eq sub window)
527 (setq skip (eq side 'left)))
528 (skip)
530 (setq delta
531 (+ delta
532 (- (window-total-size sub horizontal)
533 (window-min-size sub horizontal ignore))))))
534 (setq sub (window-right sub))))
535 ;; For an ortho-combination throw DELTA when at least one
536 ;; subwindow is fixed-size.
537 (while sub
538 (when (and (not (eq sub window))
539 (not (window-size-ignore sub ignore))
540 (window-size-fixed-p sub horizontal))
541 (throw 'fixed delta))
542 (setq sub (window-right sub))))
543 (if noup
544 delta
545 ;; Try to go up.
546 (window-max-delta-1 parent delta horizontal ignore side))))))
548 ;; Make NOUP also inhibit the min-size check.
549 (defun window-resizable (window delta &optional horizontal ignore side noup nodown)
550 "Return DELTA if WINDOW can be resized vertically by DELTA lines.
551 Optional argument HORIZONTAL non-nil means return DELTA if WINDOW
552 can be resized horizontally by DELTA columns. A return value of
553 zero means that WINDOW is not resizable.
555 DELTA positive means WINDOW shall be enlarged by DELTA lines or
556 columns. If WINDOW cannot be enlarged by DELTA lines or columns
557 return the maximum value in the range 0..DELTA by which WINDOW
558 can be enlarged.
560 DELTA negative means WINDOW shall be shrunk by -DELTA lines or
561 columns. If WINDOW cannot be shrunk by -DELTA lines or columns,
562 return the minimum value in the range DELTA..0 that can be used
563 for shrinking WINDOW.
565 Optional argument IGNORE non-nil means ignore any restrictions
566 imposed by fixed size windows, `window-min-height' or
567 `window-min-width' settings. IGNORE a window means ignore
568 restrictions for that window only. IGNORE equal `safe' means
569 live windows may get as small as `window-safe-min-height' lines
570 and `window-safe-min-width' columns.
572 Optional argument NOUP non-nil means don't go up in the window
573 tree but try to distribute the space among the other windows
574 within WINDOW's combination.
576 Optional argument NODOWN non-nil means don't check whether WINDOW
577 and its subwindows can be resized."
578 (setq window (normalize-any-window window))
579 (cond
580 ((< delta 0)
581 (max (- (window-min-delta window horizontal ignore side noup nodown))
582 delta))
583 ((> delta 0)
584 (min (window-max-delta window horizontal ignore side noup nodown)
585 delta))
586 (t 0)))
588 (defun window-resizable-p (window delta &optional horizontal ignore side noup nodown)
589 "Return t if WINDOW can be resized vertically by DELTA lines.
590 For the meaning of the arguments of this function see the
591 doc-string of `window-resizable'."
592 (setq window (normalize-any-window window))
593 (if (> delta 0)
594 (>= (window-resizable window delta horizontal ignore side noup nodown)
595 delta)
596 (<= (window-resizable window delta horizontal ignore side noup nodown)
597 delta)))
599 (defsubst window-total-height (&optional window)
600 "Return the total number of lines of WINDOW.
601 WINDOW can be any window and defaults to the selected one. The
602 return value includes WINDOW's mode line and header line, if any.
603 If WINDOW is internal the return value is the sum of the total
604 number of lines of WINDOW's child windows if these are vertically
605 combined and the height of WINDOW's first child otherwise.
607 Note: This function does not take into account the value of
608 `line-spacing' when calculating the number of lines in WINDOW."
609 (window-total-size window))
611 ;; Eventually we should make `window-height' obsolete.
612 (defalias 'window-height 'window-total-height)
614 ;; See discussion in bug#4543.
615 (defsubst window-full-height-p (&optional window)
616 "Return t if WINDOW is as high as the containing frame.
617 More precisely, return t if and only if the total height of
618 WINDOW equals the total height of the root window of WINDOW's
619 frame. WINDOW can be any window and defaults to the selected
620 one."
621 (setq window (normalize-any-window window))
622 (= (window-total-size window)
623 (window-total-size (frame-root-window window))))
625 (defsubst window-total-width (&optional window)
626 "Return the total number of columns of WINDOW.
627 WINDOW can be any window and defaults to the selected one. The
628 return value includes any vertical dividers or scrollbars of
629 WINDOW. If WINDOW is internal, the return value is the sum of
630 the total number of columns of WINDOW's child windows if these
631 are horizontally combined and the width of WINDOW's first child
632 otherwise."
633 (window-total-size window t))
635 (defsubst window-full-width-p (&optional window)
636 "Return t if WINDOW is as wide as the containing frame.
637 More precisely, return t if and only if the total width of WINDOW
638 equals the total width of the root window of WINDOW's frame.
639 WINDOW can be any window and defaults to the selected one."
640 (setq window (normalize-any-window window))
641 (= (window-total-size window t)
642 (window-total-size (frame-root-window window) t)))
644 (defsubst window-body-height (&optional window)
645 "Return the number of lines of WINDOW's body.
646 WINDOW must be a live window and defaults to the selected one.
648 The return value does not include WINDOW's mode line and header
649 line, if any. If a line at the bottom of the window is only
650 partially visible, that line is included in the return value. If
651 you do not want to include a partially visible bottom line in the
652 return value, use `window-text-height' instead."
653 (window-body-size window))
655 (defsubst window-body-width (&optional window)
656 "Return the number of columns of WINDOW's body.
657 WINDOW must be a live window and defaults to the selected one.
659 The return value does not include any vertical dividers or scroll
660 bars owned by WINDOW. On a window-system the return value does
661 not include the number of columns used for WINDOW's fringes or
662 display margins either."
663 (window-body-size window t))
665 ;; Eventually we should make `window-height' obsolete.
666 (defalias 'window-width 'window-body-width)
668 (defun window-current-scroll-bars (&optional window)
669 "Return the current scroll bar settings for WINDOW.
670 WINDOW must be a live window and defaults to the selected one.
672 The return value is a cons cell (VERTICAL . HORIZONTAL) where
673 VERTICAL specifies the current location of the vertical scroll
674 bars (`left', `right', or nil), and HORIZONTAL specifies the
675 current location of the horizontal scroll bars (`top', `bottom',
676 or nil).
678 Unlike `window-scroll-bars', this function reports the scroll bar
679 type actually used, once frame defaults and `scroll-bar-mode' are
680 taken into account."
681 (setq window (normalize-live-window window))
682 (let ((vert (nth 2 (window-scroll-bars window)))
683 (hor nil))
684 (when (or (eq vert t) (eq hor t))
685 (let ((fcsb (frame-current-scroll-bars (window-frame window))))
686 (if (eq vert t)
687 (setq vert (car fcsb)))
688 (if (eq hor t)
689 (setq hor (cdr fcsb)))))
690 (cons vert hor)))
692 (defun walk-windows (proc &optional minibuf all-frames)
693 "Cycle through all live windows, calling PROC for each one.
694 PROC must specify a function with a window as its sole argument.
695 The optional arguments MINIBUF and ALL-FRAMES specify the set of
696 windows to include in the walk.
698 MINIBUF t means include the minibuffer window even if the
699 minibuffer is not active. MINIBUF nil or omitted means include
700 the minibuffer window only if the minibuffer is active. Any
701 other value means do not include the minibuffer window even if
702 the minibuffer is active.
704 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
705 frame, plus the minibuffer window if specified by the MINIBUF
706 argument. If the minibuffer counts, consider all windows on all
707 frames that share that minibuffer too. The following non-nil
708 values of ALL-FRAMES have special meanings:
710 - t means consider all windows on all existing frames.
712 - `visible' means consider all windows on all visible frames.
714 - 0 (the number zero) means consider all windows on all visible
715 and iconified frames.
717 - A frame means consider all windows on that frame only.
719 Anything else means consider all windows on WINDOW's frame and no
720 others.
722 This function changes neither the order of recently selected
723 windows nor the buffer list."
724 ;; If we start from the minibuffer window, don't fail to come
725 ;; back to it.
726 (when (window-minibuffer-p (selected-window))
727 (setq minibuf t))
728 ;; Make sure to not mess up the order of recently selected
729 ;; windows. Use `save-selected-window' and `select-window'
730 ;; with second argument non-nil for this purpose.
731 (save-selected-window
732 (when (framep all-frames)
733 (select-window (frame-first-window all-frames) 'norecord))
734 (dolist (walk-windows-window (window-list-1 nil minibuf all-frames))
735 (funcall proc walk-windows-window))))
737 (defun walk-window-tree-1 (proc walk-window-tree-window any)
738 "Helper function for `walk-window-tree'."
739 (let (walk-window-tree-buffer)
740 (while walk-window-tree-window
741 (setq walk-window-tree-buffer
742 (window-buffer walk-window-tree-window))
743 (when (or walk-window-tree-buffer any)
744 (funcall proc walk-window-tree-window))
745 (unless walk-window-tree-buffer
746 (walk-window-tree-1
747 proc (window-hchild walk-window-tree-window) any)
748 (walk-window-tree-1
749 proc (window-vchild walk-window-tree-window) any))
750 (setq walk-window-tree-window
751 (window-right walk-window-tree-window)))))
753 (defun walk-window-tree (proc &optional frame any)
754 "Run function PROC on each live window of FRAME.
755 PROC must be a function with one argument - a window. FRAME must
756 be a live frame and defaults to the selected one. ANY, if
757 non-nil means to run PROC on all live and internal windows of
758 FRAME.
760 This function performs a pre-order, depth-first traversal of the
761 window tree. If PROC changes the window tree, the result is
762 unpredictable."
763 (let ((walk-window-tree-frame (normalize-live-frame frame)))
764 (walk-window-tree-1
765 proc (frame-root-window walk-window-tree-frame) any)))
767 (defun window-in-direction-2 (window posn &optional horizontal)
768 "Support function for `window-in-direction'."
769 (if horizontal
770 (let ((top (window-top-line window)))
771 (if (> top posn)
772 (- top posn)
773 (- posn top (window-total-height window))))
774 (let ((left (window-left-column window)))
775 (if (> left posn)
776 (- left posn)
777 (- posn left (window-total-width window))))))
779 (defun window-in-direction (direction &optional window ignore)
780 "Return window in DIRECTION as seen from WINDOW.
781 DIRECTION must be one of `above', `below', `left' or `right'.
782 WINDOW must be a live window and defaults to the selected one.
783 IGNORE, when non-nil means a window can be returned even if its
784 `no-other-window' parameter is non-nil."
785 (setq window (normalize-live-window window))
786 (unless (memq direction '(above below left right))
787 (error "Wrong direction %s" direction))
788 (let* ((frame (window-frame window))
789 (hor (memq direction '(left right)))
790 (first (if hor
791 (window-left-column window)
792 (window-top-line window)))
793 (last (+ first (if hor
794 (window-total-width window)
795 (window-total-height window))))
796 (posn-cons (nth 6 (posn-at-point (window-point window) window)))
797 (posn (if hor
798 (+ (cdr posn-cons) (window-top-line window))
799 (+ (car posn-cons) (window-left-column window))))
800 (best-edge
801 (cond
802 ((eq direction 'below) (frame-height frame))
803 ((eq direction 'right) (frame-width frame))
804 (t -1)))
805 (best-edge-2 best-edge)
806 (best-diff-2 (if hor (frame-height frame) (frame-width frame)))
807 best best-2 best-diff-2-new)
808 (walk-window-tree
809 (lambda (w)
810 (let* ((w-top (window-top-line w))
811 (w-left (window-left-column w)))
812 (cond
813 ((or (eq window w)
814 ;; Ignore ourselves.
815 (and (window-parameter w 'no-other-window)
816 ;; Ignore W unless IGNORE is non-nil.
817 (not ignore))))
818 (hor
819 (cond
820 ((and (<= w-top posn)
821 (< posn (+ w-top (window-total-height w))))
822 ;; W is to the left or right of WINDOW and covers POSN.
823 (when (or (and (eq direction 'left)
824 (<= w-left first) (> w-left best-edge))
825 (and (eq direction 'right)
826 (>= w-left last) (< w-left best-edge)))
827 (setq best-edge w-left)
828 (setq best w)))
829 ((and (or (and (eq direction 'left)
830 (<= (+ w-left (window-total-width w)) first))
831 (and (eq direction 'right) (<= last w-left)))
832 ;; W is to the left or right of WINDOW but does not
833 ;; cover POSN.
834 (setq best-diff-2-new
835 (window-in-direction-2 w posn hor))
836 (or (< best-diff-2-new best-diff-2)
837 (and (= best-diff-2-new best-diff-2)
838 (if (eq direction 'left)
839 (> w-left best-edge-2)
840 (< w-left best-edge-2)))))
841 (setq best-edge-2 w-left)
842 (setq best-diff-2 best-diff-2-new)
843 (setq best-2 w))))
845 (cond
846 ((and (<= w-left posn)
847 (< posn (+ w-left (window-total-width w))))
848 ;; W is above or below WINDOW and covers POSN.
849 (when (or (and (eq direction 'above)
850 (<= w-top first) (> w-top best-edge))
851 (and (eq direction 'below)
852 (>= w-top first) (< w-top best-edge)))
853 (setq best-edge w-top)
854 (setq best w)))
855 ((and (or (and (eq direction 'above)
856 (<= (+ w-top (window-total-height w)) first))
857 (and (eq direction 'below) (<= last w-top)))
858 ;; W is above or below WINDOW but does not cover POSN.
859 (setq best-diff-2-new
860 (window-in-direction-2 w posn hor))
861 (or (< best-diff-2-new best-diff-2)
862 (and (= best-diff-2-new best-diff-2)
863 (if (eq direction 'above)
864 (> w-top best-edge-2)
865 (< w-top best-edge-2)))))
866 (setq best-edge-2 w-top)
867 (setq best-diff-2 best-diff-2-new)
868 (setq best-2 w)))))))
869 (window-frame window))
870 (or best best-2)))
872 (defun get-window-with-predicate (predicate &optional minibuf
873 all-frames default)
874 "Return a live window satisfying PREDICATE.
875 More precisely, cycle through all windows calling the function
876 PREDICATE on each one of them with the window as its sole
877 argument. Return the first window for which PREDICATE returns
878 non-nil. If no window satisfies PREDICATE, return DEFAULT.
880 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
881 frame, plus the minibuffer window if specified by the MINIBUF
882 argument. If the minibuffer counts, consider all windows on all
883 frames that share that minibuffer too. The following non-nil
884 values of ALL-FRAMES have special meanings:
886 - t means consider all windows on all existing frames.
888 - `visible' means consider all windows on all visible frames.
890 - 0 (the number zero) means consider all windows on all visible
891 and iconified frames.
893 - A frame means consider all windows on that frame only.
895 Anything else means consider all windows on WINDOW's frame and no
896 others."
897 (catch 'found
898 (dolist (window (window-list-1 nil minibuf all-frames))
899 (when (funcall predicate window)
900 (throw 'found window)))
901 default))
903 (defalias 'some-window 'get-window-with-predicate)
905 (defun get-lru-window (&optional all-frames dedicated)
906 "Return the least recently used window on frames specified by ALL-FRAMES.
907 Return a full-width window if possible. A minibuffer window is
908 never a candidate. A dedicated window is never a candidate
909 unless DEDICATED is non-nil, so if all windows are dedicated, the
910 value is nil. Avoid returning the selected window if possible.
912 The following non-nil values of the optional argument ALL-FRAMES
913 have special meanings:
915 - t means consider all windows on all existing frames.
917 - `visible' means consider all windows on all visible frames.
919 - 0 (the number zero) means consider all windows on all visible
920 and iconified frames.
922 - A frame means consider all windows on that frame only.
924 Any other value of ALL-FRAMES means consider all windows on the
925 selected frame and no others."
926 (let (best-window best-time second-best-window second-best-time time)
927 (dolist (window (window-list-1 nil nil all-frames))
928 (when (or dedicated (not (window-dedicated-p window)))
929 (setq time (window-use-time window))
930 (if (or (eq window (selected-window))
931 (not (window-full-width-p window)))
932 (when (or (not second-best-time) (< time second-best-time))
933 (setq second-best-time time)
934 (setq second-best-window window))
935 (when (or (not best-time) (< time best-time))
936 (setq best-time time)
937 (setq best-window window)))))
938 (or best-window second-best-window)))
940 (defun get-mru-window (&optional all-frames)
941 "Return the least recently used window on frames specified by ALL-FRAMES.
942 Do not return a minibuffer window.
944 The following non-nil values of the optional argument ALL-FRAMES
945 have special meanings:
947 - t means consider all windows on all existing frames.
949 - `visible' means consider all windows on all visible frames.
951 - 0 (the number zero) means consider all windows on all visible
952 and iconified frames.
954 - A frame means consider all windows on that frame only.
956 Any other value of ALL-FRAMES means consider all windows on the
957 selected frame and no others."
958 (let (best-window best-time time)
959 (dolist (window (window-list-1 nil nil all-frames))
960 (setq time (window-use-time window))
961 (when (or (not best-time) (> time best-time))
962 (setq best-time time)
963 (setq best-window window)))
964 best-window))
966 (defun get-largest-window (&optional all-frames dedicated)
967 "Return the largest window on frames specified by ALL-FRAMES.
968 A minibuffer window is never a candidate. A dedicated window is
969 never a candidate unless DEDICATED is non-nil, so if all windows
970 are dedicated, the value is nil.
972 The following non-nil values of the optional argument ALL-FRAMES
973 have special meanings:
975 - t means consider all windows on all existing frames.
977 - `visible' means consider all windows on all visible frames.
979 - 0 (the number zero) means consider all windows on all visible
980 and iconified frames.
982 - A frame means consider all windows on that frame only.
984 Any other value of ALL-FRAMES means consider all windows on the
985 selected frame and no others."
986 (let ((best-size 0)
987 best-window size)
988 (dolist (window (window-list-1 nil nil all-frames))
989 (when (or dedicated (not (window-dedicated-p window)))
990 (setq size (* (window-total-size window)
991 (window-total-size window t)))
992 (when (> size best-size)
993 (setq best-size size)
994 (setq best-window window))))
995 best-window))
997 ;; The following is what `get-buffer-window' would look like if it were
998 ;; implemented in Elisp. Since this function is needed for dumping,
999 ;; leave it in C.
1001 ;; (defun get-buffer-window (&optional buffer-or-name all-frames)
1002 ;; "Return a window currently displaying BUFFER-OR-NAME, or nil if none.
1003 ;; BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
1004 ;; the current buffer.
1006 ;; The following non-nil values of the optional argument ALL-FRAMES
1007 ;; have special meanings:
1008 ;; - t means consider all windows on all existing frames.
1009 ;; - `visible' means consider all windows on all visible frames.
1010 ;; - 0 (the number zero) means consider all windows on all visible
1011 ;; and iconified frames.
1012 ;; - A frame means consider all windows on that frame only.
1013 ;; Any other value of ALL-FRAMES means consider all windows on the
1014 ;; selected frame and no others."
1015 ;; (let ((buffer (get-buffer buffer-or-name))
1016 ;; best-window)
1017 ;; (when (bufferp buffer)
1018 ;; (dolist (window (window-list-1 nil t all-frames))
1019 ;; (when (and (eq (window-buffer window) buffer)
1020 ;; ;; The following SHOULD have been handled by
1021 ;; ;; `window-list-1' already ...
1022 ;; (or (not (window-minibuffer-p window))
1023 ;; ;; Don't find any minibuffer window except the
1024 ;; ;; one that is currently in use.
1025 ;; (eq window (minibuffer-window)))
1026 ;; (or (not best-window)
1027 ;; ;; Prefer to return selected window.
1028 ;; (eq window (selected-window))
1029 ;; ;; Prefer windows on selected frame.
1030 ;; (eq (window-frame window) (selected-frame))))
1031 ;; (setq best-window window))))
1032 ;; best-window))
1034 (defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames)
1035 "Return list of all windows displaying BUFFER-OR-NAME, or nil if none.
1036 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
1037 and defaults to the current buffer.
1039 Any windows showing BUFFER-OR-NAME on the selected frame are listed
1040 first.
1042 MINIBUF t means include the minibuffer window even if the
1043 minibuffer is not active. MINIBUF nil or omitted means include
1044 the minibuffer window only if the minibuffer is active. Any
1045 other value means do not include the minibuffer window even if
1046 the minibuffer is active.
1048 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
1049 frame, plus the minibuffer window if specified by the MINIBUF
1050 argument. If the minibuffer counts, consider all windows on all
1051 frames that share that minibuffer too. The following non-nil
1052 values of ALL-FRAMES have special meanings:
1054 - t means consider all windows on all existing frames.
1056 - `visible' means consider all windows on all visible frames.
1058 - 0 (the number zero) means consider all windows on all visible
1059 and iconified frames.
1061 - A frame means consider all windows on that frame only.
1063 Anything else means consider all windows on WINDOW's frame and no
1064 others."
1065 (let ((buffer (normalize-live-buffer buffer-or-name))
1066 windows)
1067 (dolist (window (window-list-1 (frame-first-window) minibuf all-frames))
1068 (when (eq (window-buffer window) buffer)
1069 (setq windows (cons window windows))))
1070 (nreverse windows)))
1072 (defun minibuffer-window-active-p (window)
1073 "Return t if WINDOW is the currently active minibuffer window."
1074 (eq window (active-minibuffer-window)))
1076 (defun count-windows (&optional minibuf)
1077 "Return the number of live windows on the selected frame.
1078 The optional argument MINIBUF specifies whether the minibuffer
1079 window shall be counted. See `walk-windows' for the precise
1080 meaning of this argument."
1081 (length (window-list-1 nil minibuf)))
1083 ;;; Resizing windows.
1084 (defun resize-window-reset (&optional frame horizontal)
1085 "Reset resize values for all windows on FRAME.
1086 FRAME defaults to the selected frame.
1088 This function stores the current value of `window-total-size' applied
1089 with argument HORIZONTAL in the new total size of all windows on
1090 FRAME. It also resets the new normal size of each of these
1091 windows."
1092 (resize-window-reset-1
1093 (frame-root-window (normalize-live-frame frame)) horizontal))
1095 (defun resize-window-reset-1 (window horizontal)
1096 "Internal function of `resize-window-reset'."
1097 ;; Register old size in the new total size.
1098 (resize-window-total window (window-total-size window horizontal))
1099 ;; Reset new normal size.
1100 (resize-window-normal window)
1101 (when (window-child window)
1102 (resize-window-reset-1 (window-child window) horizontal))
1103 (when (window-right window)
1104 (resize-window-reset-1 (window-right window) horizontal)))
1106 (defvar resize-window-safe-window nil
1107 "Internal variable bound by `resize-window'.")
1109 (defun resize-window (window delta &optional horizontal ignore)
1110 "Resize WINDOW vertically by DELTA lines.
1111 WINDOW can be an arbitrary window and defaults to the selected
1112 one. An attempt to resize the root window of a frame will raise
1113 an error though.
1115 DELTA a positive number means WINDOW shall be enlarged by DELTA
1116 lines. DELTA negative means WINDOW shall be shrunk by -DELTA
1117 lines.
1119 Optional argument HORIZONTAL non-nil means resize WINDOW
1120 horizontally by DELTA columns. In this case a positive DELTA
1121 means enlarge WINDOW by DELTA columns. DELTA negative means
1122 WINDOW shall be shrunk by -DELTA columns.
1124 Optional argument IGNORE non-nil means ignore any restrictions
1125 imposed by fixed size windows, `window-min-height' or
1126 `window-min-width' settings. IGNORE any window means ignore
1127 restrictions for that window only. IGNORE equal `safe' means
1128 live windows may get as small as `window-safe-min-height' lines
1129 and `window-safe-min-width' columns.
1131 This function resizes other windows proportionally and never
1132 deletes any windows. If you want to move only the low (right)
1133 edge of WINDOW consider using `adjust-window-trailing-edge'
1134 instead."
1135 (setq window (normalize-any-window window))
1136 (let* ((frame (window-frame window))
1137 right)
1138 (cond
1139 ((eq window (frame-root-window frame))
1140 (error "Cannot resize root window of frame"))
1141 ((window-resizable-p window delta horizontal ignore)
1142 (resize-window-reset frame horizontal)
1143 (resize-this-window window delta horizontal ignore t)
1144 (if (and (not (eq window-splits 'resize))
1145 (window-iso-combined-p window horizontal)
1146 (setq right (window-right window))
1147 (or (window-size-ignore window ignore)
1148 (not (window-size-fixed-p right)))
1149 (or (< delta 0)
1150 (> (- (window-total-size right horizontal)
1151 (window-min-size right horizontal))
1152 delta)))
1153 ;; Resize window below/on the right of WINDOW - this is the
1154 ;; classic Emacs behavior, so retain it for `window-splits'
1155 ;; not 'resize, iso-combined windows. It's a PITA, though.
1156 (let ((parent-size
1157 (window-total-size (window-parent window) horizontal)))
1158 (resize-this-window right (- delta) horizontal nil t)
1159 (resize-window-normal
1160 window (/ (float (window-new-total-size window)) parent-size))
1161 (resize-window-normal
1162 right (/ (float (window-new-total-size right)) parent-size)))
1163 (resize-other-windows window delta horizontal ignore))
1164 (resize-window-apply frame horizontal))
1166 (error "Cannot resize window %s" window)))))
1168 (defsubst resize-subwindows-skip-p (window)
1169 "Return non-nil if WINDOW shall be skipped by resizing routines."
1170 (memq (window-new-normal-size window) '(ignore stuck skip)))
1172 (defun resize-subwindows-normal (parent horizontal window delta side)
1173 "Set new normal height of all subwindows of window PARENT.
1174 HORIZONTAL non-nil means set normal width of these windows.
1175 WINDOW has to specify a subwindow of PARENT that has been resized
1176 by DELTA lines \(columns). SIDE non-nil means set values for
1177 windows on the specified side of WINDOW only."
1178 (let* ((parent-new-total (window-new-total-size parent))
1179 (window-new-total
1180 (+ (window-total-size window horizontal) delta))
1181 (window-new-normal
1182 (/ (float window-new-total) parent-new-total))
1183 (others-old-normal
1184 (- 1 (window-normal-size window horizontal)))
1185 (others-new-normal (- 1 window-new-normal))
1186 (sub (window-child parent))
1187 (skip (eq side 'right)))
1189 (when (memq side '(left right))
1190 (while sub
1191 (cond
1192 ((eq sub window)
1193 (setq skip (eq side 'left)))
1194 (skip
1195 (setq others-old-normal
1196 (- others-old-normal
1197 (window-normal-size sub horizontal)))
1198 (setq others-new-normal
1199 (- others-new-normal
1200 (window-normal-size sub horizontal)))))
1201 (setq sub (window-right sub)))
1202 (setq sub (window-child parent))
1203 (setq skip (eq side 'right)))
1205 (setq sub (window-child parent))
1206 (while sub
1207 (cond
1208 ((eq sub window)
1209 (resize-window-normal sub window-new-normal)
1210 (setq skip (eq side 'left)))
1211 (skip)
1213 (resize-window-normal
1214 sub (if (zerop others-old-normal)
1216 (/ (* (window-normal-size sub horizontal)
1217 others-new-normal)
1218 others-old-normal)))))
1219 (setq sub (window-right sub)))))
1221 ;; Calling the following has
1222 ;; 1. SIDE non-nil => WINDOW nil.
1223 ;; 2. WINDOW non-nil => resize PARENT and WINDOW by DELTA.
1224 ;; 3. WINDOW nil => resize PARENT by DELTA.
1225 (defun resize-subwindows (parent delta &optional horizontal ignore side)
1226 "Resize subwindows of window PARENT vertically by DELTA lines.
1227 PARENT must be a vertically combined internal window.
1229 Optional argument HORIZONTAL non-nil means resize subwindows of
1230 PARENT horizontally by DELTA columns. In this case PARENT must
1231 be a horizontally combined internal window.
1233 Optional argument IGNORE non-nil means ignore any restrictions
1234 imposed by fixed size windows, `window-min-height' or
1235 `window-min-width' settings. IGNORE equal `safe' means live
1236 windows may get as small as `window-safe-min-height' lines and
1237 `window-safe-min-width' columns. IGNORE any window means ignore
1238 restrictions for that window only.
1240 Optional argument SIDE `left' means try to resize only the last
1241 subwindow of PARENT provided DELTA is greater zero. SIDE `right'
1242 means try to only resize the first subwindow of PARENT provided
1243 DELTA is greater zero. Any other value of SIDE is ignored."
1244 (let* ((first (window-child parent))
1245 (sub first)
1246 (normal-sum 0.0)
1247 (total-sum delta)
1248 (failed t)
1249 (amount 0)
1250 found sub-total sub-normal sub-int sub-float sub-delta sub-amount
1251 sub-rest best best-rest)
1252 ;; `normal-sum' is the sum of the normal sizes of all resizable
1253 ;; subwindows of PARENT. `total-sum' is the sum of the total
1254 ;; sizes of all resizable subwindows of PARENT plus DELTA.
1255 (catch 'done
1256 (while sub
1257 (unless (or (resize-subwindows-skip-p sub)
1258 (and (not ignore)
1259 ;; Ignore fixed-size subwindows.
1260 (window-size-fixed-p sub horizontal)
1261 (resize-window-normal sub 'ignore)))
1262 (setq normal-sum (+ normal-sum
1263 (window-normal-size sub horizontal)))
1264 (setq total-sum (+ total-sum
1265 (window-total-size sub horizontal)))
1266 ;; `found' non-nil tells that there is at least one subwindow
1267 ;; left that can be resized (should stay `t' now ;-().
1268 (setq found t))
1269 (setq sub (window-right sub)))
1271 ;; When SIDE is non-nil and DELTA is greater zero try to resize
1272 ;; the first subwindow (when SIDE is `right') or the last
1273 ;; subwindow (when SIDE is `left') first. This is the behavior
1274 ;; needed by `adjust-window-trailing-edge' when the edge-adjacent
1275 ;; subwindow the user wants to enlarge is nested in a combination.
1276 (when (and (> delta 0)
1277 ;; Skip a fixed-size window: This is inherently not
1278 ;; TRT because a fixed-size internal window might
1279 ;; still have a resizable subwindow which we could
1280 ;; enlarge. But DTRT here is quite non-trivial :-(
1281 (or (and (eq side 'left)
1282 (progn
1283 (setq sub first)
1284 (while (window-right sub)
1285 (setq sub (window-right sub)))
1286 sub))
1287 (and (eq side 'right) (setq sub first)))
1288 (not (resize-subwindows-skip-p sub)))
1289 ;; DELTA > 0 guarantees that resizing SUB always succeeds.
1290 (resize-this-window sub delta horizontal ignore t side)
1291 ;; Assign new normal sizes.
1292 (resize-subwindows-normal parent horizontal sub delta side)
1293 (throw 'done 0))
1295 ;; We resize subwindows in "rounds". We assume that usually a
1296 ;; resize request succeeds in the first round. If it fails -
1297 ;; which means at least one subwindow cannot be resized as desired
1298 ;; - we need another round. Failures are recorded in the variable
1299 ;; `failed' and, for the failed subwindow, by setting that
1300 ;; window's new normal size to a negative value.
1302 ;; Note that in each round we record (via `resize-window-total')
1303 ;; only the amount by which the window shall be resized. Only
1304 ;; when we know how each inidvidual subwindow shall be resized
1305 ;; (that is after the final round) we add the current size of the
1306 ;; window to the amount recorded previously.
1307 (while (and failed found)
1308 ;; We try to resize each resizable subwindow `sub' by a value
1309 ;; `sub-delta' individually calculated for `sub'. `sub-amount'
1310 ;; specifies the actual amount `sub' can be resized to in the
1311 ;; present round. `amount' represents the sum of the
1312 ;; `sub-amount' for all subwindows we are able to resize in the
1313 ;; present round. `delta' is de-/increased by the sum of
1314 ;; `sub-amount' for all subwindows we we're not able to resize
1315 ;; completely in the present round. So `amount' and `delta'
1316 ;; grow/shrink towards each other and we are done when the have
1317 ;; the same value. `sub-rest' is the remainder when calculating
1318 ;; `sub-delta' and is used when calculating the new normal
1319 ;; sizes.
1320 (setq amount 0)
1321 (setq found nil)
1322 (setq failed nil)
1323 (setq sub first)
1324 ;; The following loop represents one round.
1325 (while (and sub (not failed))
1326 ;; Ignore subwindows that should be ignored or are stuck.
1327 (unless (resize-subwindows-skip-p sub)
1328 ;; Set `found' to t to make sure that if this round fails we
1329 ;; make another round.
1330 (setq found t)
1331 ;; `sub-total' records the total size of this subwindow.
1332 (setq sub-total (window-total-size sub horizontal))
1333 ;; `sub-normal' records the normal of this subwindow.
1334 (setq sub-normal (window-normal-size sub horizontal))
1335 ;; `sub-delta' records the number of lines or columns by
1336 ;; which this subwindow should grow or shrink. `sub-float'
1337 ;; and `sub-int' record the new ideal total size as a float
1338 ;; and integer value.
1339 (setq sub-float (/ (* sub-normal total-sum) normal-sum))
1340 (setq sub-int (floor sub-float))
1341 (setq sub-delta (- sub-int sub-total))
1342 ;; `sub-rest' is the remainder.
1343 (setq sub-rest (abs (- sub-float sub-int)))
1344 (if (and side (< delta 0) (>= sub-delta 0))
1345 ;; With `adjust-window-trailing-edge' some window can
1346 ;; get penalized such that its normal size exceeds its
1347 ;; fractional total size considerably. In that case
1348 ;; dragging a divider in the opposite direction in order
1349 ;; to enlarge some other window may cause this window
1350 ;; get _enlarged_ which looks silly. We try to avoid
1351 ;; such behavior here.
1352 (resize-window-total sub sub-total)
1353 ;; `sub-amount' records the number of lines or columns by
1354 ;; which this subwindow can grow or shrink.
1355 (setq sub-amount
1356 (window-sizable sub sub-delta horizontal ignore))
1357 ;; Register the new total size for this subwindow.
1358 (resize-window-total sub (+ sub-total sub-amount))
1359 (if (= sub-amount sub-delta)
1360 ;; We succeeded to get this subwindow's share.
1361 (progn
1362 (if (and (< delta 0) (zerop sub-amount))
1363 ;; When shrinking avoid that a window that has
1364 ;; not shrunk gets a remainder before a window
1365 ;; that has shrunk.
1366 (resize-window-normal sub 'rest)
1367 ;; Record remainder.
1368 (resize-window-normal sub sub-rest))
1369 (setq amount (+ amount sub-amount)))
1370 ;; We failed and need a new round.
1371 (setq failed t)
1372 ;; Don't consider this subwindow again when calculating
1373 ;; desired sizes.
1374 (setq normal-sum (- normal-sum sub-normal))
1375 (setq total-sum (- total-sum sub-total sub-amount))
1376 (setq delta (- delta sub-amount))
1377 (resize-window-normal sub 'stuck))))
1378 (setq sub (window-right sub))))
1380 ;; Fix rounding by trying to enlarge non-stuck, non-rest windows
1381 ;; by one line (column) until `amount' equals `delta'.
1382 (when found
1383 (catch 'found
1384 (while (< amount delta)
1385 (setq sub first)
1386 (setq best nil)
1387 (setq best-rest 0)
1388 (while sub
1389 (setq sub-normal (window-new-normal-size sub))
1390 (when (and (numberp sub-normal) (>= sub-normal best-rest))
1391 (setq best sub)
1392 (setq best-rest sub-normal)
1393 (setq found t))
1394 (setq sub (window-right sub)))
1395 (if (not best)
1396 (throw 'found nil)
1397 (resize-window-total best 1 'add)
1398 (resize-window-normal best (max 0 (1- best-rest)))
1399 (setq amount (1+ amount))))))
1401 ;; Fix rounding by trying to enlarge "rest" windows by one line
1402 ;; (column) until `amount' equals `delta'.
1403 (catch 'found
1404 (while (< amount delta)
1405 (setq sub first)
1406 (setq best nil)
1407 (when (eq (window-new-normal-size sub) 'rest)
1408 (setq best t)
1409 (resize-window-total sub 1 'add)
1410 (setq amount (1+ amount))
1411 (setq sub (window-right sub)))
1412 (unless best
1413 (throw 'found nil))))
1415 ;; Fix rounding by trying to enlarge stuck windows by one line
1416 ;; (column) until `amount' equals `delta'.
1417 (catch 'found
1418 (while (< amount delta)
1419 (setq sub first)
1420 (setq best nil)
1421 (when (eq (window-new-normal-size sub) 'stuck)
1422 (setq best t)
1423 (resize-window-total sub 1 'add)
1424 (setq amount (1+ amount))
1425 (setq sub (window-right sub)))
1426 (unless best
1427 (throw 'found nil))))
1429 ;; Reset new normal size fields so `resize-window-apply' won't use
1430 ;; them to apply new sizes.
1431 (setq sub first)
1432 (while sub
1433 (when (numberp (window-new-normal-size sub))
1434 (resize-window-normal sub))
1435 (setq sub (window-right sub)))
1437 ;; Now recursively resize each resized subwindow's subwindows.
1438 (setq sub first)
1439 (while sub
1440 (unless (eq (window-new-normal-size sub) 'ignore)
1441 ;; Resize this subwindow's subwindows. Note that above we
1442 ;; recorded (via `resize-window-total') only the amount by
1443 ;; which this subwindow had to be resized. Now we add the old
1444 ;; total size.
1445 (let ((delta (- (window-new-total-size sub)
1446 (window-total-size sub horizontal))))
1447 (unless (and (zerop delta) (not side))
1448 (resize-this-window sub delta horizontal ignore nil side))))
1449 (setq sub (window-right sub))))))
1451 (defun resize-other-windows (window delta &optional horizontal ignore side)
1452 "Resize other windows when WINDOW is resized vertically by DELTA lines.
1453 Optional argument HORIZONTAL non-nil means resize other windows
1454 when WINDOW is resized horizontally by DELTA columns. WINDOW
1455 itself is not resized by this function.
1457 Optional argument IGNORE non-nil means ignore any restrictions
1458 imposed by fixed size windows, `window-min-height' or
1459 `window-min-width' settings. IGNORE equal `safe' means live
1460 windows may get as small as `window-safe-min-height' lines and
1461 `window-safe-min-width' columns. IGNORE any window means ignore
1462 restrictions for that window only.
1464 Optional argument SIDE `left' means resize other windows above
1465 \(on left of) WINDOW only. SIDE `right' means resize other
1466 windows below \(on right of) WINDOW only. Any other value of
1467 SIDE is ignored."
1468 (when (window-parent window)
1469 (let* ((parent (window-parent window))
1470 (sub (window-child parent))
1471 non-fixed)
1472 (if (window-iso-combined-p sub horizontal)
1473 ;; In an iso-combination resize WINDOW's siblings.
1474 (let ((first sub)
1475 (skip (eq side 'right))
1476 this-delta)
1477 ;; Decide which windows shall be left alone.
1478 (while sub
1479 (cond
1480 ((eq sub window)
1481 ;; Make sure WINDOW is left alone when
1482 ;; resizing its siblings.
1483 (resize-window-normal sub 'ignore)
1484 (setq skip (eq side 'left)))
1485 (skip
1486 ;; Make sure this sibling is left alone when
1487 ;; resizing its siblings.
1488 (resize-window-normal sub 'ignore))
1489 ((or (window-size-ignore sub ignore)
1490 (not (window-size-fixed-p sub horizontal)))
1491 (setq non-fixed t)))
1492 (setq sub (window-right sub)))
1493 (if (= (- delta) (window-total-size window horizontal))
1494 ;; A deletion, presumably.
1495 (if non-fixed
1496 ;; There's at least on resizable sibling.
1497 (setq this-delta delta)
1498 ;; No resizable sibling present.
1499 (setq this-delta 0))
1500 (setq this-delta
1501 (window-resizable
1502 window delta horizontal ignore side t)))
1503 (unless (= delta this-delta)
1504 (resize-window-total parent (- delta this-delta) 'add))
1505 (unless (zerop this-delta)
1506 (resize-window-normal window 'ignore)
1507 (resize-subwindows
1508 parent (- this-delta) horizontal ignore side)
1509 ;; Now set the normal sizes.
1510 (resize-subwindows-normal
1511 parent horizontal window this-delta side)
1512 (setq delta (- delta this-delta))))
1514 ;; In an ortho-combination all siblings of WINDOW must be
1515 ;; resized by DELTA. Store the new total size of parent first.
1516 (resize-window-total parent delta 'add)
1517 (while sub
1518 (unless (eq sub window)
1519 (resize-this-window sub delta horizontal ignore t))
1520 (setq sub (window-right sub))))
1522 (unless (zerop delta)
1523 ;; "Go up."
1524 (resize-other-windows parent delta horizontal ignore side)))))
1526 (defun resize-this-window (window delta &optional horizontal ignore add-total side)
1527 "Resize WINDOW vertically by DELTA lines.
1528 Optional argument HORIZONTAL non-nil means resize WINDOW
1529 horizontally by DELTA columns.
1531 Optional argument IGNORE non-nil means ignore any restrictions
1532 imposed by fixed size windows, `window-min-height' or
1533 `window-min-width' settings. IGNORE equal `safe' means live
1534 windows may get as small as `window-safe-min-height' lines and
1535 `window-safe-min-width' columns. IGNORE any window means ignore
1536 restrictions for that window only.
1538 Optional argument ADD-TOTAL non-nil means add DELTA to the new
1539 total size of WINDOW.
1541 Optional argument SIDE `left' means resize other windows above
1542 \(on left of) WINDOW only. SIDE `right' means resize other
1543 windows below \(on right of) WINDOW only. Any other value of
1544 SIDE is ignored.
1546 This function recursively resizes WINDOW's subwindows to fit the
1547 new size. Make sure that WINDOW is `window-resizable' before
1548 calling this function. Note that this function does not resize
1549 siblings of WINDOW or WINDOW's parent window. You have to
1550 eventually call `resize-window-apply' in order to make resizing
1551 actually take effect."
1552 (when add-total
1553 ;; Add DELTA to the new total size of WINDOW.
1554 (resize-window-total window delta t))
1556 (let ((sub (window-child window)))
1557 (cond
1558 ((not sub))
1559 ((window-iso-combined-p sub horizontal)
1560 ;; In an iso-combination resize subwindows according to their
1561 ;; fractions.
1562 (resize-subwindows window delta horizontal ignore side))
1563 ;; In an ortho-combination resize each subwindow by DELTA.
1565 (while sub
1566 (resize-this-window sub delta horizontal ignore t side)
1567 (setq sub (window-right sub)))))))
1569 (defun resize-root-window (window delta horizontal ignore)
1570 "Resize root window WINDOW vertically by DELTA lines.
1571 HORIZONTAL non-nil means resize root window WINDOW horizontally
1572 by DELTA columns.
1574 IGNORE non-nil means ignore any restrictions imposed by fixed
1575 size windows, `window-min-height' or `window-min-width' settings.
1577 This function is called by Emacs' frame resizing routines. It
1578 resizes windows proportionally and never deletes any windows."
1579 (when (and (windowp window) (numberp delta)
1580 (window-sizable-p window delta horizontal ignore))
1581 (resize-window-reset (window-frame window) horizontal)
1582 (resize-this-window window delta horizontal ignore t)))
1584 (defun resize-root-window-vertically (window delta)
1585 "Resize root window WINDOW vertically by DELTA lines.
1586 If DELTA is less than zero and we can't shrink WINDOW by DELTA
1587 lines, shrink it as much as possible. If DELTA is greater than
1588 zero, this function can resize fixed-size subwindows in order to
1589 recover the necessary lines.
1591 Return the number of lines that were recovered.
1593 This function is called by Emacs' minibuffer resizing routines.
1594 It resizes windows proportionally and never deletes any windows."
1595 (when (numberp delta)
1596 (let (ignore)
1597 (cond
1598 ((< delta 0)
1599 (setq delta (window-sizable window delta)))
1600 ((> delta 0)
1601 (unless (window-sizable window delta)
1602 (setq ignore t))))
1603 (resize-window-reset (window-frame window))
1604 (resize-this-window window delta nil ignore t)
1605 delta)))
1607 (defun adjust-window-trailing-edge (window delta &optional horizontal)
1608 "Move WINDOW's bottom edge by DELTA lines.
1609 Optional argument HORIZONTAL non-nil means move WINDOW's right
1610 edge by DELTA columns. WINDOW defaults to the selected window.
1612 If the edge can't be moved by DELTA lines, move it as far as
1613 possible in the desired direction."
1614 (setq window (normalize-any-window window))
1615 (let ((frame (window-frame window))
1616 (right window)
1617 left this-delta min-delta max-delta failed)
1618 ;; Find the edge we want to move.
1619 (while (and (or (not (window-iso-combined-p right horizontal))
1620 (not (window-right right)))
1621 (setq right (window-parent right))))
1622 (unless (and (setq left right) (setq right (window-right right)))
1623 (error "No window following this one"))
1625 ;; Set LEFT to the first resizable window on the left. This step is
1626 ;; needed to handle fixed-size windows.
1627 (while (and left (window-size-fixed-p left horizontal))
1628 (setq left
1629 (or (window-left left)
1630 (progn
1631 (while (and (setq left (window-parent left))
1632 (not (window-iso-combined-p left horizontal))))
1633 (window-left left)))))
1634 (unless left
1635 (error "No resizable window preceding this one"))
1637 ;; Set RIGHT to the first resizable window on the right. This step
1638 ;; is needed to handle fixed-size windows.
1639 (while (and right (window-size-fixed-p right horizontal))
1640 (setq right
1641 (or (window-right right)
1642 (progn
1643 (while (and (setq right (window-parent right))
1644 (not (window-iso-combined-p right horizontal))))
1645 (window-right right)))))
1646 (unless right
1647 (error "No resizable window following this one"))
1649 ;; LEFT and RIGHT (which might be both internal windows) are now the
1650 ;; two windows we want to resize.
1651 (cond
1652 ((> delta 0)
1653 (setq max-delta (window-max-delta-1 left 0 horizontal nil 'right))
1654 (setq min-delta (window-min-delta-1 right (- delta) horizontal nil 'left))
1655 (when (or (< max-delta delta) (> min-delta (- delta)))
1656 ;; We can't get the whole DELTA - move as far as possible.
1657 (setq delta (min max-delta (- min-delta))))
1658 (unless (zerop delta)
1659 ;; Start resizing.
1660 (resize-window-reset frame horizontal)
1661 ;; Try to enlarge LEFT first.
1662 (setq this-delta (window-resizable left delta horizontal))
1663 (unless (zerop this-delta)
1664 (resize-this-window left this-delta horizontal nil t 'left))
1665 (unless (= this-delta delta)
1666 ;; We didn't get it all from LEFT, enlarge windows on left of
1667 ;; LEFT (for this purpose make `resize-other-windows' believe
1668 ;; that we shrink LEFT).
1669 (resize-other-windows
1670 left (- this-delta delta) horizontal nil 'left))
1671 ;; Shrink windows on right of LEFT.
1672 (resize-other-windows left delta horizontal nil 'right)))
1673 ((< delta 0)
1674 (setq max-delta (window-max-delta-1 right 0 horizontal nil 'left))
1675 (setq min-delta (window-min-delta-1 left delta horizontal nil 'right))
1676 (when (or (< max-delta (- delta)) (> min-delta delta))
1677 ;; We can't get the whole DELTA - move as far as possible.
1678 (setq delta (max (- max-delta) min-delta)))
1679 (unless (zerop delta)
1680 ;; Start resizing.
1681 (resize-window-reset frame horizontal)
1682 ;; Try to enlarge RIGHT.
1683 (setq this-delta (window-resizable right (- delta) horizontal))
1684 (unless (zerop this-delta)
1685 (resize-this-window right this-delta horizontal nil t 'right))
1686 (unless (= (- this-delta) delta)
1687 ;; We didn't get it all from RIGHT, enlarge windows on right of
1688 ;; RIGHT (for this purpose make `resize-other-windows' believe
1689 ;; that we grow RIGHT).
1690 (resize-other-windows
1691 right (- this-delta delta) horizontal nil 'right))
1692 ;; Shrink windows on left of RIGHT.
1693 (resize-other-windows right (- delta) horizontal nil 'left))))
1694 (unless (zerop delta)
1695 ;; Don't report an error in the standard case.
1696 (unless (resize-window-apply frame horizontal)
1697 ;; But do report an error it applying the changes fails.
1698 (error "Failed adjusting window %s" window)))))
1700 (defun resize-mini-window (window delta)
1701 "Resize minibuffer window WINDOW by DELTA lines."
1702 (when (window-minibuffer-p window)
1703 (let* ((frame (window-frame window))
1704 (root (frame-root-window frame))
1705 (height (window-total-size window)))
1706 (unless (> (- height delta) 0)
1707 (setq delta (- height 1)))
1708 (when (window-sizable-p root delta)
1709 (resize-window-reset frame)
1710 (resize-this-window root delta nil nil t)
1711 (resize-window-total window (- height delta))
1712 (resize-mini-window-internal window)))))
1714 (defun enlarge-window (delta &optional horizontal)
1715 "Make selected window DELTA lines taller.
1716 Interactively, if no argument is given, make the selected window
1717 one line taller. If optional argument HORIZONTAL is non-nil,
1718 make selected window wider by DELTA columns. If DELTA is
1719 negative, shrink selected window by -DELTA lines or columns.
1720 Return nil."
1721 (interactive "p")
1722 (resize-window (selected-window) delta horizontal))
1724 (defun shrink-window (delta &optional horizontal)
1725 "Make selected window DELTA lines smaller.
1726 Interactively, if no argument is given, make the selected window
1727 one line smaller. If optional argument HORIZONTAL is non-nil,
1728 make selected window narrower by DELTA columns. If DELTA is
1729 negative, enlarge selected window by -DELTA lines or columns.
1730 Return nil."
1731 (interactive "p")
1732 (resize-window (selected-window) (- delta) horizontal))
1734 (defun maximize-window (&optional window)
1735 "Maximize WINDOW.
1736 Make WINDOW as large as possible without deleting any windows.
1737 WINDOW can be any window and defaults to the selected window."
1738 (interactive)
1739 (setq window (normalize-any-window window))
1740 (resize-window window (window-max-delta window))
1741 (resize-window window (window-max-delta window t) t))
1743 (defun minimize-window (&optional window)
1744 "Minimize WINDOW.
1745 Make WINDOW as small as possible without deleting any windows.
1746 WINDOW can be any window and defaults to the selected window."
1747 (interactive)
1748 (setq window (normalize-any-window window))
1749 (resize-window window (- (window-min-delta window)))
1750 (resize-window window (- (window-min-delta window t)) t))
1752 (defsubst frame-root-window-p (window)
1753 "Return non-nil if WINDOW is the root window of its frame."
1754 (eq window (frame-root-window window)))
1756 (defun window-tree-1 (window &optional next)
1757 "Return window tree rooted at WINDOW.
1758 Optional argument NEXT non-nil means include windows right
1759 siblings in the return value.
1761 See the documentation of `window-tree' for a description of the
1762 return value."
1763 (let (list)
1764 (while window
1765 (setq list
1766 (cons
1767 (cond
1768 ((window-vchild window)
1769 (cons t (cons (window-edges window)
1770 (window-tree-1 (window-vchild window) t))))
1771 ((window-hchild window)
1772 (cons nil (cons (window-edges window)
1773 (window-tree-1 (window-hchild window) t))))
1774 (t window))
1775 list))
1776 (setq window (when next (window-next window))))
1777 (nreverse list)))
1779 (defun window-tree (&optional frame)
1780 "Return the window tree of frame FRAME.
1781 FRAME must be a live frame and defaults to the selected frame.
1782 The return value is a list of the form (ROOT MINI), where ROOT
1783 represents the window tree of the frame's root window, and MINI
1784 is the frame's minibuffer window.
1786 If the root window is not split, ROOT is the root window itself.
1787 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil
1788 for a horizontal split, and t for a vertical split. EDGES gives
1789 the combined size and position of the subwindows in the split,
1790 and the rest of the elements are the subwindows in the split.
1791 Each of the subwindows may again be a window or a list
1792 representing a window split, and so on. EDGES is a list \(LEFT
1793 TOP RIGHT BOTTOM) as returned by `window-edges'."
1794 (setq frame (normalize-live-frame frame))
1795 (window-tree-1 (frame-root-window frame) t))
1797 ;;; Composite Windows
1799 ;; The basic invariant of the composite window code is:
1801 ;; \A window \in Windows:
1802 ;; \A sibling \in Siblings [window]:
1803 ;; composite-window-p [window] =>
1804 ;; /\ composite-window-p [sibling]
1805 ;; /\ composite-root-window [window] = composite-root-window [sibling]
1807 ;; that is, for any window that is part of a composite window, any
1808 ;; sibling of that window is a subwindow of the same composite window.
1810 ;; This is usually not called as a "predicate" but it's more consistent
1811 ;; to maintain our defsubsts as predicate.
1812 (defsubst composite-window-p (window)
1813 "Return non-nil if WINDOW is a subwindow of a composite window.
1814 The return value is the value of the `composite' window parameter
1815 of WINDOW."
1816 (window-parameter window 'composite))
1818 (defsubst composite-root-window-p (window)
1819 "Return non-nil if WINDOW is the root of a composite window.
1820 The return value is the type of that composite window, either
1821 `compound' or `group'."
1822 (or (window-parameter window 'compound)
1823 (window-parameter window 'group)))
1825 (defsubst composite-main-window-p (window)
1826 "Return t if WINDOW is a main window of a composite window."
1827 (eq (cdr-safe (composite-window-p window)) 'main))
1829 (defsubst composite-support-window-p (window)
1830 "Return t if WINDOW is a support window of a composite window."
1831 (eq (cdr-safe (composite-window-p window)) 'support))
1833 (defun composite-root-window (window)
1834 "Return root window of the composite window WINDOW is a part of.
1835 Return nil if WINDOW is not part of a composite window or the
1836 path from WINDOW to the root of the composite window is broken."
1837 (let ((type (car-safe (window-parameter window 'composite))))
1838 (when type
1839 (setq window (window-parent window))
1840 (catch 'done
1841 (while window
1842 (cond
1843 ((window-parameter window type)
1844 (throw 'done window))
1845 ((eq (car-safe (window-parameter window 'composite)) type))
1847 ;; Broken path.
1848 (throw 'done nil)))
1849 (setq window (window-parent window)))))))
1851 (defun composite-major-window (window)
1852 "Return major window of composite window WINDOW belongs to.
1853 The major window is the last main or root window found by
1854 following the path from WINDOW to the root of the composite
1855 window WINDOW belongs to. Each composite window should have one
1856 and only one major window to make sure that functions on its
1857 component windows behave \"as intended\".
1859 This function returns a meaningful result if and only if WINDOW
1860 is a main window."
1861 (let ((main window))
1862 (setq window (window-parent window))
1863 (while (and window (composite-main-window-p window)
1864 (not (composite-root-window-p window)))
1865 (setq main window)
1866 (setq window (window-parent window)))
1867 ;; We can't go up any further but maybe the window we're looking at
1868 ;; is the root window.
1869 (when (composite-root-window-p window)
1870 (let ((sibling (window-child window)))
1871 ;; Make sure that all children of the group root window are main
1872 ;; windows.
1873 (catch 'done
1874 (while sibling
1875 (if (not (composite-main-window-p sibling))
1876 (throw 'done nil)
1877 (setq sibling (window-right sibling))))
1878 (setq main window))))
1879 main))
1881 (defun composite-main-sibling (window)
1882 "Return first \"main\" sibling of WINDOW.
1883 A main sibling is a main window of a composite window. Both,
1884 WINDOW and the main sibling must have the same parent window and
1885 thus be part of one and the same composite window. Return nil if
1886 no such window can be found."
1887 (let ((parent (window-parent window))
1888 sibling)
1889 (when parent
1890 (setq sibling (window-child parent))
1891 (catch 'done
1892 (while sibling
1893 (if (and (not (eq sibling window))
1894 (eq (cdr-safe (window-parameter sibling 'composite)) 'main))
1895 (throw 'done sibling)
1896 (setq sibling (window-right sibling))))))))
1898 (defun composite-lowest-child-role (window)
1899 "Return lowest \"non-main\" role among WINDOW's children."
1900 (let ((sibling (window-child window))
1901 (highest 'main)
1902 role)
1903 (catch 'done
1904 (while sibling
1905 (setq role (cdr-safe (window-parameter sibling 'composite)))
1906 (cond
1907 ((eq role t)
1908 (setq highest t))
1909 ((eq role 'support)
1910 (throw 'done 'support)))
1911 (setq sibling (window-right sibling)))
1912 highest)))
1914 (defsubst compound-window-p (window)
1915 "Return non-nil if WINDOW is a subwindow of a compound window."
1916 (eq (car-safe (window-parameter window 'composite)) 'compound))
1918 (defsubst compound-main-window-p (window)
1919 "Return non-nil if WINDOW is a main window of a compound window."
1920 (let ((composite (composite-window-p window)))
1921 (and (eq (car-safe composite) 'compound)
1922 (eq (cdr-safe composite) 'main))))
1924 (defun compound-root-window (window)
1925 "Return topmost root window of compound window WINDOW belongs to."
1926 (while (and window (compound-window-p window))
1927 (setq window (window-parent window)))
1928 (when (window-parameter window 'compound)
1929 window))
1931 (defsubst group-window-p (window)
1932 "Return non-nil if WINDOW is a subwindow of a window group."
1933 (eq (car-safe (window-parameter window 'composite)) 'group))
1935 (defsubst group-window-main-p (window)
1936 "Return non-nil if WINDOW is a main window of a window group."
1937 (let ((composite (composite-window-p window)))
1938 (and (eq (car-safe composite) 'group)
1939 (eq (cdr-safe composite) 'main))))
1941 (defun group-root-window (window)
1942 "Return root window of window group WINDOW belongs to.
1943 If WINDOW is part of a compound window, return the root window of
1944 the group the root of the compound window belongs too."
1945 (while (and window (compound-window-p window))
1946 (setq window (window-parent window)))
1947 (while (and window (group-window-p window)
1948 (not (composite-root-window-p window)))
1949 (setq window (window-parent window)))
1950 (when (window-parameter window 'group)
1951 window))
1953 ;;; Getting the "other" window.
1954 ;; FIXME: Handle `ignore-window-parameters' and some other things maybe.
1955 (defun other-window (count &optional all-frames)
1956 "Select another window in cyclic ordering of windows.
1957 COUNT specifies the number of windows to skip, starting with the
1958 selected window, before making the selection. If COUNT is
1959 positive, skip COUNT windows forwards. If COUNT is negative,
1960 skip -COUNT windows backwards. COUNT zero means do not skip any
1961 window, so select the selected window. In an interactive call,
1962 COUNT is the numeric prefix argument. Return nil.
1964 This function does not select a window whose `no-other-window'
1965 parameter is non-nil. Also, this function never selects the
1966 support window of a composite window unless the support window's
1967 `maybe-other-window' parameter is non-nil.
1969 This function uses `next-window' for finding the window to
1970 select. The argument ALL-FRAMES has the same meaning as in
1971 `next-window', but the MINIBUF argument of `next-window' is
1972 always effectively nil."
1973 (interactive "p")
1974 (let* ((window (selected-window))
1975 (function (window-parameter window 'other-window))
1976 old-window old-count)
1977 (if (functionp function)
1978 (funcall function count all-frames)
1979 ;; `next-window' and `previous-window' may return a window we are
1980 ;; not allowed to select. Hence we need an exit strategy in case
1981 ;; all windows are non-selectable.
1982 (catch 'exit
1983 (while (> count 0)
1984 (setq window (next-window window nil all-frames))
1985 (cond
1986 ((eq window old-window)
1987 (when (= count old-count)
1988 ;; Keep out of infinite loops. When COUNT has not changed
1989 ;; since we last looked at `window' we're probably in one.
1990 (throw 'exit nil)))
1991 ((or (and (composite-support-window-p window)
1992 (not (window-parameter window 'maybe-other-window)))
1993 (window-parameter window 'no-other-window))
1994 ;; The first non-selectable window `next-window' got us:
1995 ;; Remember it and the current value of COUNT.
1996 (unless old-window
1997 (setq old-window window)
1998 (setq old-count count)))
2000 (setq count (1- count)))))
2001 (while (< count 0)
2002 (setq window (previous-window window nil all-frames))
2003 (cond
2004 ((eq window old-window)
2005 (when (= count old-count)
2006 ;; Keep out of infinite loops. When COUNT has not changed
2007 ;; since we last looked at `window' we're probably in one.
2008 (throw 'exit nil)))
2009 ((or (and (composite-support-window-p window)
2010 (not (window-parameter window 'maybe-other-window)))
2011 (window-parameter window 'no-other-window))
2012 ;; The first non-selectable window `previous-window' got us:
2013 ;; Remember it and the current value of COUNT.
2014 (unless old-window
2015 (setq old-window window)
2016 (setq old-count count)))
2018 (setq count (1+ count)))))
2019 (select-window window)
2020 nil))))
2022 ;; This should probably return non-nil when the selected window is part
2023 ;; of a compound window whose root is the frame's root window.
2024 (defun one-window-p (&optional nomini all-frames)
2025 "Return non-nil if the selected window is the only window.
2026 Optional arg NOMINI non-nil means don't count the minibuffer
2027 even if it is active. Otherwise, the minibuffer is counted
2028 when it is active.
2030 Optional argument ALL-FRAMES specifies the set of frames to
2031 consider, see also `next-window'. ALL-FRAMES nil or omitted
2032 means consider windows on WINDOW's frame only, plus the
2033 minibuffer window if specified by the NOMINI argument. If the
2034 minibuffer counts, consider all windows on all frames that share
2035 that minibuffer too. The remaining non-nil values of ALL-FRAMES
2036 with a special meaning are:
2038 - t means consider all windows on all existing frames.
2040 - `visible' means consider all windows on all visible frames.
2042 - 0 (the number zero) means consider all windows on all visible
2043 and iconified frames.
2045 - A frame means consider all windows on that frame only.
2047 Anything else means consider all windows on WINDOW's frame and no
2048 others."
2049 (let ((base-window (selected-window)))
2050 (if (and nomini (eq base-window (minibuffer-window)))
2051 (setq base-window (next-window base-window)))
2052 (eq base-window
2053 (next-window base-window (if nomini 'arg) all-frames))))
2055 ;;; Deleting windows.
2056 (defun window-deletable-p (&optional window)
2057 "Return t if WINDOW can be safely deleted from its frame.
2058 Return `frame' if deleting WINDOW should delete its frame
2059 instead."
2060 (setq window (normalize-any-window window))
2061 (let ((frame (window-frame window))
2062 (dedicated (and (window-buffer window) (window-dedicated-p window)))
2063 (quit-restore (car-safe (window-parameter window 'quit-restore)))
2064 composite type role root)
2065 (cond
2066 ((frame-root-window-p window)
2067 (when (and (or dedicated
2068 (and (eq quit-restore t)
2069 (with-current-buffer (window-buffer window)
2070 ;; `view-remove-frame-by-deleting' and
2071 ;; `view-mode' are autoloaded.
2072 (or (not view-mode)
2073 view-remove-frame-by-deleting))))
2074 (other-visible-frames-p frame))
2075 ;; WINDOW is the root window of its frame. Return `frame' but
2076 ;; only if WINDOW is (1) either dedicated or quit-restore's car
2077 ;; is t and (2) there are other frames left.
2078 'frame))
2079 ((setq composite (window-parameter window 'composite))
2080 (setq type (car-safe composite))
2081 (setq role (cdr-safe composite))
2082 (setq root (composite-root-window window))
2083 (cond
2084 ;; When `ignore-window-parameters' or the `delete-window'
2085 ;; parameter say or WINDOW is part of a broken composite window,
2086 ;; WINDOW is deletable. We cannot handle the case where WINDOW's
2087 ;; `delete-window' parameter is a function (that's impossible).
2088 ((or (not (memq ignore-window-parameters '(nil post)))
2089 (eq (window-parameter window 'delete-window) t)
2090 (not root) (not type) (not role))
2092 ((eq type 'compound)
2093 ;; A component of a compound window is deletable if and only if
2094 ;; its root is deletable.
2095 (window-deletable-p root))
2096 ((eq type 'group)
2097 ;; In a window group only a main window with a main sibling is
2098 ;; deletable.
2099 (and (eq role 'main) (composite-main-sibling window)))))
2100 (t))))
2102 (defun window-or-subwindow-p (subwindow window)
2103 "Return t if SUBWINDOW is either WINDOW or a subwindow of WINDOW."
2104 (or (eq subwindow window)
2105 (let ((parent (window-parent subwindow)))
2106 (catch 'done
2107 (while parent
2108 (if (eq parent window)
2109 (throw 'done t)
2110 (setq parent (window-parent parent))))))))
2112 (defun delete-window (&optional window)
2113 "Delete WINDOW.
2114 WINDOW can be an arbitrary window and defaults to the selected
2115 one. Return nil.
2117 This function respects the variable `ignore-window-parameters'
2118 when processing window parameters so any processing of WINDOW's
2119 parameters may be suppressed.
2121 If the `delete-window' parameter WINDOW equals t, delete WINDOW
2122 ignoring any other window parameters. If the `delete-window'
2123 parameter specifies a function, call that function with WINDOW as
2124 its sole argument. It's the responsibility of that function to
2125 adjust the parameters of all remaining windows.
2127 Otherwise, if WINDOW is part of a compound window, call this
2128 function with the root of the compound window as its argument.
2129 If WINDOW is either the only window on its frame, or a support
2130 window or the last main window of a window group, signal an error
2131 and don't delete WINDOW.
2133 This function makes sure that window parameters are reset or
2134 inherited when WINDOW is part of a combination of two windows."
2135 (interactive)
2136 (setq window (normalize-any-window window))
2137 (let* ((function (window-parameter window 'delete-window))
2138 ;; COMPOSITE non-nil means WINDOW is part of a composite
2139 ;; window.
2140 (composite (window-parameter window 'composite))
2141 ;; TYPE is the type of the composite window (either `compound'
2142 ;; or `group'). ROLE is the role of WINDOW within the
2143 ;; composite window (either `main', `support', or t). ROOT is
2144 ;; the root window of the composite window.
2145 (type (car-safe composite))
2146 (role (cdr-safe composite))
2147 (root (and composite (composite-root-window window)))
2148 parent)
2149 (catch 'done
2150 ;; Handle window parameters.
2151 (cond
2152 ;; Ignore window parameters if `ignore-window-parameters' tells
2153 ;; so or the `delete-window' parameter equals t.
2154 ((or (not (memq ignore-window-parameters '(nil post)))
2155 (eq function t)))
2156 ((functionp function)
2157 ;; The `delete-window' parameter specifies the function to call
2158 ;; instead. If that function is `ignore' nothing is done. It's
2159 ;; up to the function called here to avoid infinite recursion.
2160 (throw 'done (funcall function window)))
2161 (composite
2162 (cond
2163 ((or (not root) (not type) (not role))
2164 ;; Something is broken in this composite window. Signal a
2165 ;; message but let the deletion pass through (we might signal
2166 ;; an error here but for everday work this is too nasty).
2167 (message "Broken component %s of composite window" window))
2168 ((eq type 'compound)
2169 ;; Deleting a component of a compound window deletes the
2170 ;; entire compound window.
2171 (throw 'done (delete-window root)))
2172 ((eq type 'group)
2173 (cond
2174 ((not (eq role 'main))
2175 ;; WINDOW is _not_ a main window of a window group. There's
2176 ;; no rule for deleting such a window so we signal an error.
2177 ;; We might swallow this error silently.
2178 (error "Cannot delete non-main window of a window group"))
2179 ((not (composite-main-sibling window))
2180 ;; WINDOW has no main sibling and we can't delete the last
2181 ;; main window of a window group. We might swallow this
2182 ;; error silently.
2183 (error "Cannot delete last main window of a window group")))))))
2185 ;; Set PARENT to WINDOW's parent in the window tree. If there's
2186 ;; no such parent signal an error.
2187 (unless (setq parent (window-parent window))
2188 (error "Attempt to delete minibuffer or sole ordinary window"))
2190 (let* ((horizontal (window-hchild parent))
2191 (size (window-total-size window horizontal))
2192 (frame (window-frame window))
2193 (frame-selected
2194 (window-or-subwindow-p (frame-selected-window frame) window))
2195 ;; LEFT is WINDOW's _left_ sibling - traditionally LEFT
2196 ;; gets enlarged and is selected after the deletion.
2197 (left (window-left window))
2198 ;; RIGHT is WINDOW's right sibling.
2199 (right (window-right window))
2200 ;; SIBLING is WINDOW's sibling provided they are the only
2201 ;; child windows of PARENT.
2202 (sibling
2203 (or (and left (not right) (not (window-left left)) left)
2204 (and right (not left) (not (window-right right)) right)))
2205 ;; Record some of PARENT's parameters (just in case we have
2206 ;; WINDOW replace it in the window tree).
2207 (parent-compound
2208 (and sibling (window-parameter parent 'compound)))
2209 (parent-group
2210 (and sibling (window-parameter parent 'group)))
2211 (parent-composite
2212 (and sibling (window-parameter parent 'composite))))
2213 (resize-window-reset frame horizontal)
2214 (cond
2215 ((or (and (eq window-splits 'nest)
2216 (or (and left (not (window-left left))
2217 (not (window-right window)))
2218 (and (not left)
2219 (setq left (window-right window))
2220 (not (window-right left))))
2221 (not (window-size-fixed-p left horizontal)))
2222 (and left (not window-splits)
2223 (not (window-size-fixed-p left horizontal))))
2224 ;; Resize WINDOW's left sibling.
2225 (resize-this-window left size horizontal nil t)
2226 (resize-window-normal
2227 left (+ (window-normal-size left horizontal)
2228 (window-normal-size window horizontal))))
2229 ((let ((sub (window-child parent)))
2230 (catch 'found
2231 ;; Look for a non-fixed-size sibling.
2232 (while sub
2233 (when (and (not (eq sub window))
2234 (not (window-size-fixed-p sub horizontal)))
2235 (throw 'found t))
2236 (setq sub (window-right sub)))))
2237 ;; We can do it without resizing fixed-size windows.
2238 (resize-other-windows window (- size) horizontal))
2240 ;; Can't do without resizing fixed-size windows. We really
2241 ;; should signal an error here but who would agree :-(
2242 (resize-other-windows window (- size) horizontal t)))
2243 ;; Actually delete WINDOW.
2244 (delete-window-internal window)
2245 (when (and frame-selected
2246 (window-parameter
2247 (frame-selected-window frame) 'no-other-window))
2248 ;; `delete-window-internal' has selected a window that should
2249 ;; not be selected, fix this here (I hate `other-window').
2250 (other-window -1 frame))
2251 ;; Handle composite windows (unless we ignore window
2252 ;; parameters).
2253 (when (and (memq ignore-window-parameters '(nil pre))
2254 sibling (not (eq parent (window-parent sibling)))
2255 (or parent-compound parent-group))
2256 ;; At this moment we know that WINDOW and SIBLING are part of
2257 ;; a composite window and the _sole_ child windows of PARENT.
2258 ;; SIBLING replaces PARENT.
2259 (when parent-group
2260 ;; SIBLING becomes the new root of the window group earlier
2261 ;; headed by PARENT. If PARENT was the root of a compound
2262 ;; window that compound window gets dissolved.
2263 (set-window-parameter sibling 'group t))
2264 (if parent-composite
2265 ;; `sibling' inherits composite state of `parent'.
2266 (set-window-parameter sibling 'composite parent-composite)
2267 ;; `sibling' is no longer part of a composite window.
2268 (set-window-parameter sibling 'composite nil)))
2269 (run-window-configuration-change-hook frame)
2270 nil))))
2272 (defun delete-other-windows (&optional window)
2273 "Make WINDOW fill its frame.
2274 WINDOW may be any window and defaults to the selected one.
2276 This function respects the variable `ignore-window-parameters'
2277 when processing window parameters so any processing of WINDOW's
2278 parameters may be suppressed.
2280 If the `delete-other-windows' parameter of WINDOW equals t,
2281 delete WINDOW ignoring any other window parameters. If the
2282 `delete-other-windows' parameter specifies a function, call that
2283 function with WINDOW as its sole argument. It's the
2284 responsibility of that function to adjust the parameters of all
2285 remaining windows.
2287 Otherwise, if WINDOW is part of a compound window, call this
2288 function with the root of the compound window as its argument.
2289 If WINDOW is a main window in a window group, make WINDOW the
2290 only main window in this group. Any support windows of the group
2291 are left alone. If WINDOW is a support window of a window group,
2292 signal an error and don't delete any windows."
2293 (interactive)
2294 (setq window (normalize-any-window window))
2295 (let* ((function (window-parameter window 'delete-other-windows))
2296 (composite (window-parameter window 'composite))
2297 ;; COMPOSITE non-nil means WINDOW is part of a composite
2298 ;; window.
2299 (type (car-safe composite))
2300 (role (cdr-safe composite))
2301 (root (and composite (composite-root-window window)))
2302 ;; TYPE is the type of the composite window (either `compound'
2303 ;; or `group'). ROLE is the role of WINDOW within the
2304 ;; composite window (either `main', `support', or t). ROOT is
2305 ;; the root window of the composite window.
2306 main)
2307 (catch 'done
2308 ;; Handle composite window parameter.
2309 (cond
2310 ;; Ignore window parameters if `ignore-window-parameters' tells
2311 ;; so or the `delete-other-windows' parameter equals t.
2312 ((or (not (memq ignore-window-parameters '(nil post)))
2313 (eq function t)))
2314 ((functionp function)
2315 ;; The `delete-other-windows' parameter specifies the function
2316 ;; to call instead. If the function is `ignore' no windows are
2317 ;; deleted. It's up to the function called to avoid infinite
2318 ;; recursion.
2319 (throw 'done (funcall function window)))
2320 (composite
2321 (cond
2322 ((or (not root) (not type) (not role))
2323 ;; Something is broken in this composite window. Signal a
2324 ;; message but let the deletion pass through (we might signal
2325 ;; an error here but for everday work this is too nasty).
2326 (message "Broken composite window"))
2327 ((eq type 'compound)
2328 ;; In a compound window call `delete-other-windows' with the
2329 ;; root window as its argument.
2330 (throw 'done (delete-other-windows root)))
2331 ((eq type 'group)
2332 (if (eq role 'main)
2333 ;; In a window group we are allowed to delete main windows
2334 ;; only. Moreover we need an ancestor which is the last
2335 ;; main window found when following the path to the group
2336 ;; root window.
2337 (progn
2338 (setq main (composite-major-window window))
2339 (when (or (not main) (eq main window))
2340 ;; If we don't find an ancestor or the ancestor is
2341 ;; WINDOW itself there's nothing we can delete.
2342 ;; Swallow this quietly.
2343 (throw 'done nil))
2344 (when (and (eq main root)
2345 (memq ignore-window-parameters '(nil pre)))
2346 ;; If we delete right up to the root of this group
2347 ;; (that is, there are no support windows around) give
2348 ;; WINDOW the parameters of `root'.
2349 (set-window-parameter window 'group t)
2350 (set-window-parameter
2351 window 'composite (window-parameter root 'composite))))
2352 ;; We might swallow this message.
2353 (error
2354 "Cannot delete other windows for non-main window %s" window))))))
2356 (delete-other-windows-internal window main)
2357 (when (and (memq ignore-window-parameters '(nil pre))
2358 (frame-root-window-p window))
2359 ;; Clean up for the case where we did something special.
2360 (set-window-parameter window 'composite nil))
2361 nil)))
2363 (defun delete-other-windows-vertically (&optional window)
2364 "Delete the windows in the same column with WINDOW, but not WINDOW itself.
2365 This may be a useful alternative binding for \\[delete-other-windows]
2366 if you often split windows horizontally."
2367 (interactive)
2368 (let* ((window (or window (selected-window)))
2369 (edges (window-edges window))
2370 (w window) delenda)
2371 (while (not (eq (setq w (next-window w 1)) window))
2372 (let ((e (window-edges w)))
2373 (when (and (= (car e) (car edges))
2374 (= (caddr e) (caddr edges)))
2375 (push w delenda))))
2376 (mapc 'delete-window delenda)))
2378 ;;; Windows and buffers.
2380 ;; `prev-buffers' and `next-buffers' are two reserved window slots used
2381 ;; for (1) determining which buffer to show in the window when its
2382 ;; buffer shall be buried or killed and (2) which buffer to show for
2383 ;; `switch-to-prev-buffer' and `switch-to-next-buffer'.
2385 ;; `prev-buffers' consists of <buffer, window-start, window-point>
2386 ;; triples. The entries on this list are ordered by the time their
2387 ;; buffer has been removed from the window, the most recently removed
2388 ;; buffer's entry being first. The window-start and window-point
2389 ;; components are `window-start' and `window-point' at the time the
2390 ;; buffer was removed from the window which implies that the entry must
2391 ;; be added when `set-window-buffer' removes the buffer from the window.
2393 ;; `next-buffers' is the list of buffers that have been replaced
2394 ;; recently by `switch-to-prev-buffer'. These buffers are the least
2395 ;; preferred candidates of `switch-to-prev-buffer' and the preferred
2396 ;; candidates of `switch-to-next-buffer' to switch to. This list is
2397 ;; reset to nil by any action changing the window's buffer with the
2398 ;; exception of `switch-to-prev-buffer' and `switch-to-next-buffer'.
2399 ;; `switch-to-prev-buffer' pushes the buffer it just replaced on it,
2400 ;; `switch-to-next-buffer' pops the last pushed buffer from it.
2402 ;; Both `prev-buffers' and `next-buffers' may reference killed buffers
2403 ;; if such a buffer was killed while the window was hidden within a
2404 ;; window configuration. Such killed buffers get removed whenever
2405 ;; `switch-to-prev-buffer' or `switch-to-next-buffer' encounter them.
2407 ;; The following function is called by `set-window-buffer' _before_ it
2408 ;; replaces the buffer of the argument window with the new buffer.
2409 (defun record-window-buffer (&optional window)
2410 "Record WINDOW's buffer.
2411 WINDOW must be a live window and defaults to the selected one."
2412 (let* ((window (normalize-live-window window))
2413 (buffer (window-buffer window))
2414 (entry (assq buffer (window-prev-buffers window))))
2415 ;; Reset WINDOW's next buffers. If needed, they are resurrected by
2416 ;; `switch-to-prev-buffer' and `switch-to-next-buffer'.
2417 (set-window-next-buffers window nil)
2419 (when entry
2420 ;; Remove all entries for BUFFER from WINDOW's previous buffers.
2421 (set-window-prev-buffers
2422 window (assq-delete-all buffer (window-prev-buffers window))))
2424 ;; Don't record insignificant buffers.
2425 (unless (eq (aref (buffer-name buffer) 0) ?\s)
2426 ;; Add an entry for buffer to WINDOW's previous buffers.
2427 (with-current-buffer buffer
2428 (let ((start (window-start window))
2429 (point (window-point window)))
2430 (setq entry
2431 (cons buffer
2432 (if entry
2433 ;; We have an entry, update marker positions.
2434 (list (set-marker (nth 1 entry) start)
2435 (set-marker (nth 2 entry) point))
2436 ;; Make new markers.
2437 (list (copy-marker start)
2438 (copy-marker point)))))
2440 (set-window-prev-buffers
2441 window (cons entry (window-prev-buffers window))))))))
2443 (defun unrecord-window-buffer (&optional window buffer)
2444 "Unrecord BUFFER in WINDOW.
2445 WINDOW must be a live window and defaults to the selected one.
2446 BUFFER must be a live buffer and defaults to the buffer of
2447 WINDOW."
2448 (let* ((window (normalize-live-window window))
2449 (buffer (or buffer (window-buffer window))))
2450 (set-window-prev-buffers
2451 window (assq-delete-all buffer (window-prev-buffers window)))
2452 (set-window-next-buffers
2453 window (delq buffer (window-next-buffers window)))))
2455 (defun set-window-buffer-start-and-point (window buffer &optional start point)
2456 "Set WINDOW's buffer to BUFFER.
2457 Optional argument START non-nil means set WINDOW's start position
2458 to START. Optional argument POINT non-nil means set WINDOW's
2459 point to POINT. If WINDOW is selected this also sets BUFFER's
2460 `point' to POINT. If WINDOW is selected and the buffer it showed
2461 before was current this also makes BUFFER the current buffer."
2462 (let ((selected (eq window (selected-window)))
2463 (current (eq (window-buffer window) (current-buffer))))
2464 (set-window-buffer window buffer)
2465 (when (and selected current)
2466 (set-buffer buffer))
2467 (when start
2468 (set-window-start window start))
2469 (when point
2470 (if selected
2471 (with-current-buffer buffer
2472 (goto-char point))
2473 (set-window-point window point)))))
2475 (defun switch-to-prev-buffer (&optional window bury-or-kill)
2476 "In WINDOW switch to previous buffer.
2477 WINDOW must be a live window and defaults to the selected one.
2479 Optional argument BURY-OR-KILL non-nil means the buffer currently
2480 shown in WINDOW is about to be buried or killed and consequently
2481 shall not be switched to in future invocations of this command."
2482 (interactive)
2483 (let* ((window (normalize-live-window window))
2484 (old-buffer (window-buffer window))
2485 ;; Save this since it's destroyed by `set-window-buffer'.
2486 (next-buffers (window-next-buffers window))
2487 entry new-buffer killed-buffers deletable)
2488 (cond
2489 ;; When BURY-OR-KILL is non-nil, there's no previous buffer for
2490 ;; this window, and we can delete the window (or the frame) do
2491 ;; that.
2492 ((and bury-or-kill
2493 (or (not (window-prev-buffers window))
2494 (and (eq (caar (window-prev-buffers window)) old-buffer)
2495 (not (cdr (car (window-prev-buffers window))))))
2496 (setq deletable (window-deletable-p window)))
2497 (if (eq deletable 'frame)
2498 (delete-frame (window-frame window))
2499 (delete-window window)))
2500 ((window-dedicated-p window)
2501 (error "Window %s is dedicated to buffer %s" window old-buffer)))
2503 (unless deletable
2504 (catch 'found
2505 ;; Scan WINDOW's previous buffers first, skipping entries of next
2506 ;; buffers.
2507 (dolist (entry (window-prev-buffers window))
2508 (when (and (setq new-buffer (car entry))
2509 (or (buffer-live-p new-buffer)
2510 (not (setq killed-buffers
2511 (cons new-buffer killed-buffers))))
2512 (not (eq new-buffer old-buffer))
2513 (or bury-or-kill
2514 (not (memq new-buffer next-buffers))))
2515 (set-window-buffer-start-and-point
2516 window new-buffer (nth 1 entry) (nth 2 entry))
2517 (throw 'found t)))
2518 ;; Scan reverted buffer list of WINDOW's frame next, skipping
2519 ;; entries of next buffers. Note that when we bury or kill a
2520 ;; buffer we don't reverse the global buffer list to avoid showing
2521 ;; a buried buffer instead. Otherwise, we must reverse the global
2522 ;; buffer list in order to make sure that switching to the
2523 ;; previous/next buffer traverse it in opposite directions.
2524 (dolist (buffer (if bury-or-kill
2525 (buffer-list (window-frame window))
2526 (nreverse (buffer-list (window-frame window)))))
2527 (when (and (buffer-live-p buffer)
2528 (not (eq buffer old-buffer))
2529 (not (eq (aref (buffer-name buffer) 0) ?\s))
2530 (or bury-or-kill (not (memq buffer next-buffers))))
2531 (setq new-buffer buffer)
2532 (set-window-buffer-start-and-point window new-buffer)
2533 (throw 'found t)))
2534 (unless bury-or-kill
2535 ;; Scan reverted next buffers last (must not use nreverse
2536 ;; here!).
2537 (dolist (buffer (reverse next-buffers))
2538 ;; Actually, buffer _must_ be live here since otherwise it
2539 ;; would have been caught in the scan of previous buffers.
2540 (when (and (or (buffer-live-p buffer)
2541 (not (setq killed-buffers
2542 (cons buffer killed-buffers))))
2543 (not (eq buffer old-buffer))
2544 (setq entry (assq buffer (window-prev-buffers window))))
2545 (setq new-buffer buffer)
2546 (set-window-buffer-start-and-point
2547 window new-buffer (nth 1 entry) (nth 2 entry))
2548 (throw 'found t)))))
2550 (if bury-or-kill
2551 ;; Remove `old-buffer' from WINDOW's previous and (restored list
2552 ;; of) next buffers.
2553 (progn
2554 (set-window-prev-buffers
2555 window (assq-delete-all old-buffer (window-prev-buffers window)))
2556 (set-window-next-buffers window (delq old-buffer next-buffers)))
2557 ;; Move `old-buffer' to head of WINDOW's restored list of next
2558 ;; buffers.
2559 (set-window-next-buffers
2560 window (cons old-buffer (delq old-buffer next-buffers)))))
2562 ;; Remove killed buffers from WINDOW's previous and next buffers.
2563 (when killed-buffers
2564 (dolist (buffer killed-buffers)
2565 (set-window-prev-buffers
2566 window (assq-delete-all buffer (window-prev-buffers window)))
2567 (set-window-next-buffers
2568 window (delq buffer (window-next-buffers window)))))
2570 ;; Return new-buffer.
2571 new-buffer))
2573 (defun switch-to-next-buffer (&optional window)
2574 "In WINDOW switch to next buffer.
2575 WINDOW must be a live window and defaults to the selected one."
2576 (interactive)
2577 (let* ((window (normalize-live-window window))
2578 (old-buffer (window-buffer window))
2579 (next-buffers (window-next-buffers window))
2580 new-buffer entry killed-buffers)
2581 (when (window-dedicated-p window)
2582 (error "Window %s is dedicated to buffer %s" window old-buffer))
2584 (catch 'found
2585 ;; Scan WINDOW's next buffers first.
2586 (dolist (buffer next-buffers)
2587 (when (and (or (buffer-live-p buffer)
2588 (not (setq killed-buffers
2589 (cons buffer killed-buffers))))
2590 (not (eq buffer old-buffer))
2591 (setq entry (assq buffer (window-prev-buffers window))))
2592 (setq new-buffer buffer)
2593 (set-window-buffer-start-and-point
2594 window new-buffer (nth 1 entry) (nth 2 entry))
2595 (throw 'found t)))
2596 ;; Scan the buffer list of WINDOW's frame next, skipping previous
2597 ;; buffers entries.
2598 (dolist (buffer (buffer-list (window-frame window)))
2599 (when (and (buffer-live-p buffer) (not (eq buffer old-buffer))
2600 (not (eq (aref (buffer-name buffer) 0) ?\s))
2601 (not (assq buffer (window-prev-buffers window))))
2602 (setq new-buffer buffer)
2603 (set-window-buffer-start-and-point window new-buffer)
2604 (throw 'found t)))
2605 ;; Scan WINDOW's reverted previous buffers last (must not use
2606 ;; nreverse here!)
2607 (dolist (entry (reverse (window-prev-buffers window)))
2608 (when (and (setq new-buffer (car entry))
2609 (or (buffer-live-p new-buffer)
2610 (not (setq killed-buffers
2611 (cons new-buffer killed-buffers))))
2612 (not (eq new-buffer old-buffer)))
2613 (set-window-buffer-start-and-point
2614 window new-buffer (nth 1 entry) (nth 2 entry))
2615 (throw 'found t))))
2617 ;; Remove `new-buffer' from and restore WINDOW's next buffers.
2618 (set-window-next-buffers window (delq new-buffer next-buffers))
2620 ;; Remove killed buffers from WINDOW's previous and next buffers.
2621 (when killed-buffers
2622 (dolist (buffer killed-buffers)
2623 (set-window-prev-buffers
2624 window (assq-delete-all buffer (window-prev-buffers window)))
2625 (set-window-next-buffers
2626 window (delq buffer (window-next-buffers window)))))
2628 ;; Return new-buffer.
2629 new-buffer))
2631 (defun get-next-valid-buffer (list &optional buffer visible-ok frame)
2632 "Search LIST for a valid buffer to display in FRAME.
2633 Return nil when all buffers in LIST are undesirable for display,
2634 otherwise return the first suitable buffer in LIST.
2636 Buffers not visible in windows are preferred to visible buffers,
2637 unless VISIBLE-OK is non-nil.
2638 If the optional argument FRAME is nil, it defaults to the selected frame.
2639 If BUFFER is non-nil, ignore occurrences of that buffer in LIST."
2640 ;; This logic is more or less copied from other-buffer.
2641 (setq frame (or frame (selected-frame)))
2642 (let ((pred (frame-parameter frame 'buffer-predicate))
2643 found buf)
2644 (while (and (not found) list)
2645 (setq buf (car list))
2646 (if (and (not (eq buffer buf))
2647 (buffer-live-p buf)
2648 (or (null pred) (funcall pred buf))
2649 (not (eq (aref (buffer-name buf) 0) ?\s))
2650 (or visible-ok (null (get-buffer-window buf 'visible))))
2651 (setq found buf)
2652 (setq list (cdr list))))
2653 (car list)))
2655 (defun last-buffer (&optional buffer visible-ok frame)
2656 "Return the last buffer in FRAME's buffer list.
2657 If BUFFER is the last buffer, return the preceding buffer
2658 instead. Buffers not visible in windows are preferred to visible
2659 buffers, unless optional argument VISIBLE-OK is non-nil.
2660 Optional third argument FRAME nil or omitted means use the
2661 selected frame's buffer list. If no such buffer exists, return
2662 the buffer `*scratch*', creating it if necessary."
2663 (setq frame (or frame (selected-frame)))
2664 (or (get-next-valid-buffer (nreverse (buffer-list frame))
2665 buffer visible-ok frame)
2666 (get-buffer "*scratch*")
2667 (let ((scratch (get-buffer-create "*scratch*")))
2668 (set-buffer-major-mode scratch)
2669 scratch)))
2671 (defun bury-buffer (&optional buffer-or-name)
2672 "Put BUFFER-OR-NAME at the end of the list of all buffers.
2673 There it is the least likely candidate for `other-buffer' to
2674 return; thus, the least likely buffer for \\[switch-to-buffer] to
2675 select by default.
2677 You can specify a buffer name as BUFFER-OR-NAME, or an actual
2678 buffer object. If BUFFER-OR-NAME is nil or omitted, bury the
2679 current buffer. Also, if BUFFER-OR-NAME is nil or omitted,
2680 remove the current buffer from the selected window if it is
2681 displayed there."
2682 (interactive)
2683 (let* ((buffer (normalize-live-buffer buffer-or-name)))
2684 ;; If `buffer-or-name' is not on the selected frame we unrecord it
2685 ;; although it's not "here" (call it a feature).
2686 (unrecord-buffer buffer)
2687 ;; Handle case where `buffer-or-name' is nil and the current buffer
2688 ;; is shown in the selected window.
2689 (cond
2690 ((or buffer-or-name (not (eq buffer (window-buffer)))))
2691 ((not (window-dedicated-p))
2692 (switch-to-prev-buffer nil 'bury))
2693 ((frame-root-window-p (selected-window))
2694 (iconify-frame (window-frame (selected-window))))
2695 ((window-deletable-p)
2696 (delete-window)))
2697 ;; Always return nil.
2698 nil))
2700 (defun unbury-buffer ()
2701 "Switch to the last buffer in the buffer list."
2702 (interactive)
2703 (switch-to-buffer (last-buffer)))
2705 (defun next-buffer ()
2706 "In selected window switch to next buffer."
2707 (interactive)
2708 (switch-to-next-buffer))
2710 (defun previous-buffer ()
2711 "In selected window switch to previous buffer."
2712 (interactive)
2713 (switch-to-prev-buffer))
2715 (defun delete-windows-on (&optional buffer-or-name frame)
2716 "Delete all windows showing BUFFER-OR-NAME.
2717 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
2718 and defaults to the current buffer.
2720 The following non-nil values of the optional argument FRAME
2721 have special meanings:
2723 - t means consider all windows on the selected frame only.
2725 - `visible' means consider all windows on all visible frames.
2727 - 0 (the number zero) means consider all windows on all visible
2728 and iconified frames.
2730 - A frame means consider all windows on that frame only.
2732 Any other value of FRAME means consider all windows on all
2733 frames.
2735 When a window showing BUFFER-OR-NAME is dedicated and the only
2736 window of its frame, that frame is deleted when there are other
2737 frames left."
2738 (interactive "BDelete windows on (buffer):\nP")
2739 (let ((buffer (normalize-live-buffer buffer-or-name))
2740 ;; Handle the "inverted" meaning of the FRAME argument wrt other
2741 ;; `window-list-1' based function.
2742 (all-frames (cond ((not frame) t) ((eq frame t) nil) (t frame))))
2743 (dolist (window (window-list-1 nil nil all-frames))
2744 (if (eq (window-buffer window) buffer)
2745 (let ((deletable (window-deletable-p window)))
2746 (cond
2747 ((eq deletable 'frame)
2748 ;; Delete frame.
2749 (delete-frame (window-frame window)))
2750 (deletable
2751 ;; Delete window only.
2752 (delete-window window))
2754 ;; In window switch to previous buffer.
2755 (set-window-dedicated-p window nil)
2756 (switch-to-prev-buffer window 'bury))))
2757 ;; If a window doesn't show BUFFER, unrecord it nevertheless.
2758 (unrecord-window-buffer window buffer)))))
2760 (defun replace-buffer-in-windows (&optional buffer-or-name)
2761 "Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2762 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
2763 and defaults to the current buffer.
2765 When a window showing BUFFER-OR-NAME is dedicated that window is
2766 deleted. If that window is the only window on its frame, that
2767 frame is deleted too when there are other frames left. If there
2768 are no other frames left, some other buffer is displayed in that
2769 window.
2771 This function removes the buffer denoted by BUFFER-OR-NAME from
2772 all window-local buffer lists."
2773 (let ((buffer (normalize-live-buffer buffer-or-name)))
2774 (dolist (window (window-list-1 nil nil t))
2775 (if (eq (window-buffer window) buffer)
2776 (let ((deletable (window-deletable-p window)))
2777 (cond
2778 ((eq deletable 'frame)
2779 ;; Delete frame.
2780 (delete-frame (window-frame window)))
2781 ((and (window-dedicated-p window) deletable)
2782 ;; Delete window.
2783 (delete-window window))
2785 ;; Switch to another buffer in window.
2786 (set-window-dedicated-p window nil)
2787 (switch-to-prev-buffer window 'kill))))
2788 ;; Unrecord BUFFER in WINDOW.
2789 (unrecord-window-buffer window buffer)))))
2791 (defun quit-restore-window (&optional window kill)
2792 "Quit WINDOW in some way.
2793 WINDOW must be a live window and defaults to the selected window.
2794 Return nil.
2796 According to information stored in WINDOW's `quit-restore' window
2797 parameter either \(1) delete WINDOW and its frame, \(2) delete
2798 WINDOW, \(3) restore the buffer previously displayed in WINDOW,
2799 or \(4) make WINDOW display some other buffer than the present
2800 one. If non-nil, reset `quit-restore' parameter to nil.
2802 Optional argument KILL non-nil means in addition kill WINDOW's
2803 buffer. If KILL is nil, put WINDOW's buffer at the end of the
2804 buffer list. Interactively, KILL is the prefix argument."
2805 (interactive "i\nP")
2806 (setq window (normalize-live-window window))
2807 (let ((buffer (window-buffer window))
2808 (parameters (window-parameter window 'quit-restore))
2809 deletable)
2810 (cond
2811 ((and (eq (car-safe parameters) t)
2812 (setq deletable (window-deletable-p window)))
2813 (unrecord-buffer buffer)
2814 ;; WINDOW is deletable.
2815 (if (eq deletable 'frame)
2816 ;; WINDOW's frame can be deleted.
2817 (delete-frame (window-frame window))
2818 ;; Just delete WINDOW.
2819 (delete-window window))
2820 (when (window-live-p (nth 1 parameters))
2821 (select-window (nth 1 parameters))))
2822 ((and (buffer-live-p (nth 0 parameters))
2823 ;; The buffer currently shown in WINDOW must still be the
2824 ;; buffer shown when the `quit-restore' parameter was
2825 ;; created in the first place.
2826 (eq (window-buffer window) (nth 3 parameters)))
2827 ;; Unrecord buffer.
2828 (unrecord-buffer buffer)
2829 (unrecord-window-buffer window buffer)
2830 ;; The `quit-restore' parameters tell us the buffer to display in
2831 ;; WINDOW and how to do that.
2832 (set-window-dedicated-p window nil)
2833 (set-window-buffer window (nth 0 parameters))
2834 (set-window-start window (nth 1 parameters))
2835 (set-window-point window (nth 2 parameters))
2836 (unless (= (nth 4 parameters) (window-total-size window))
2837 (resize-window
2838 window (- (nth 4 parameters) (window-total-size window))))
2839 (set-window-parameter window 'quit-restore nil)
2840 (when (window-live-p (nth 5 parameters))
2841 (select-window (nth 5 parameters))))
2842 ((and (window-dedicated-p window)
2843 (setq deletable (window-deletable-p window)))
2844 (unrecord-buffer buffer)
2845 ;; WINDOW is dedicated and deletable.
2846 (if (eq deletable 'frame)
2847 ;; WINDOW's frame can be deleted.
2848 (delete-frame (window-frame window))
2849 ;; Just delete WINDOW.
2850 (delete-window window)))
2852 ;; Otherwise, show another buffer in WINDOW.
2853 (set-window-parameter window 'quit-restore nil)
2854 (unrecord-buffer buffer)
2855 (switch-to-prev-buffer window 'bury-or-kill)))
2857 ;; Kill WINDOW's old-buffer if requested
2858 (when kill (kill-buffer buffer))
2859 nil))
2861 ;;; Splitting windows.
2862 (defsubst window-split-min-size (&optional horflag)
2863 "Return minimum height of any window.
2864 Optional argument HORFLAG non-nil means return minimum width."
2865 (if horflag
2866 (max window-min-width window-safe-min-width)
2867 (max window-min-height window-safe-min-height)))
2869 (defun window-children-count (window)
2870 "Return number of child windows of WINDOW."
2871 (let ((count 0)
2872 (sub (window-child window)))
2873 (while sub
2874 (setq count (1+ count))
2875 (setq sub (window-right sub)))
2876 count))
2878 (defun split-window (&optional window size horizontal)
2879 "Create a new window adjacent to WINDOW.
2880 WINDOW can be any window and defaults to the selected one. If
2881 WINDOW was selected before invoking this function, it remains
2882 selected. Return the new window which is always a live window.
2884 Optional argument SIZE a positive number means make WINDOW SIZE
2885 lines/columns tall. If SIZE is negative, make the new window
2886 -SIZE lines/columns tall. If and only if SIZE is negative, its
2887 absolute value can be less than `window-min-height' or
2888 `window-min-width'; so this command can make a new window as
2889 small as one line or two columns. SIZE defaults to half of
2890 WINDOW's size. The variable `window-splits' determines how the
2891 size of other windows is affected by this function.
2893 Optional third argument HORIZONTAL nil (or `below') specifies
2894 that the new window shall be located below WINDOW. HORIZONTAL
2895 `above' means the new window shall be located above WINDOW. In
2896 both cases SIZE specifies the new number of lines for WINDOW \(or
2897 the new window if SIZE is negative) including space reserved for
2898 the mode and/or header line.
2900 HORIZONTAL t (or `right') specifies that the new window shall be
2901 located on the right side of WINDOW. HORIZONTAL `left' means the
2902 new window shall be located on the left of WINDOW. In both cases
2903 SIZE specifies the new number of columns for WINDOW \(or the new
2904 window provided SIZE is negative) including space reserved for
2905 fringes and the scrollbar or a divider column. Any other non-nil
2906 value for HORIZONTAL is currently handled like t (or `right').
2908 If WINDOW is a component of a compound window \"split\" the root
2909 of the compound window instead. The new window does not become a
2910 member of the compound window. If WINDOW is a main window of a
2911 window group, the new window becomes a main window in that window
2912 group. If WINDOW is a non-main component of a window group
2913 signal an error.
2915 If you split a live window, properties of the new window like
2916 margins and scrollbars are inherited from WINDOW. If you split
2917 an internal window, these properties as well as the buffer
2918 displayed in the new window are inherited from the selected
2919 window on WINDOW's frame."
2920 (interactive "i")
2921 (setq window (normalize-any-window window))
2922 (let* ((horflag (and horizontal (not (memq horizontal '(below above)))))
2923 (function (window-parameter window 'split-window))
2924 ;; Rebind this locally since in some cases we do have to nest.
2925 (window-splits window-splits)
2926 ;; COMPOSITE non-nil means WINDOW is part of a composite
2927 ;; window. TYPE is the type of the composite window (either
2928 ;; `compound' or `group'). ROLE is the role of WINDOW within
2929 ;; the composite window (either `main', `support', or t). ROOT
2930 ;; is the root window of the composite window.
2931 (composite (window-parameter window 'composite))
2932 (type (car-safe composite))
2933 (role (cdr-safe composite))
2934 (root (and composite (composite-root-window window)))
2935 old-composite new-root new-main)
2936 (catch 'done
2937 (cond
2938 ;; Ignore window parameters if `ignore-window-parameters' tells
2939 ;; so or the `split-window' window parameter equals t.
2940 ((or (not (memq ignore-window-parameters '(nil post)))
2941 (eq function t)))
2942 ((functionp function)
2943 ;; The `split-window' parameter specifies the function to call
2944 ;; instead. If this is `ignore', WINDOW won't be split.
2945 (throw 'done (funcall function window size horizontal)))
2946 ((and (not composite) (window-parameter window 'group)
2947 (window-live-p window))
2948 ;; WINDOW is a live group root window and not part of a
2949 ;; composite window so we need a new group root window. Note
2950 ;; that if WINDOW is also the root of a compound window, that
2951 ;; part remains unaffected by what we do here - WINDOW remains
2952 ;; root of the compound window which is now a component of a
2953 ;; window group.
2954 (setq window-splits 'nest)
2955 (setq new-root t))
2956 (composite
2957 (cond
2958 ((or (not root) (not type) (not role))
2959 ;; Something is broken in this composite window. Signal a
2960 ;; message but let the split pass through (we might signal
2961 ;; an error here but for everday work this is too nasty).
2962 (message "Broken component %s of composite window" window))
2963 ((eq type 'compound)
2964 ;; In a compound window split the root window.
2965 (throw 'done (split-window root size horizontal)))
2966 ((eq type 'group)
2967 (cond
2968 ((not (eq role 'main))
2969 ;; In a window group we are only allowed to split main
2970 ;; windows. We might swallow this error silently.
2971 (error "Cannot split non-main window %s in a window group" window))
2972 ((or (not (window-parent window)) ; Should have been handled above.
2973 (not (eq (composite-lowest-child-role (window-parent window))
2974 'main)))
2975 (setq new-main t)
2976 ;; We must nest since otherwise we might end up with a
2977 ;; window group having two dominating main windows.
2978 (setq window-splits 'nest)))))))
2979 ;; The following line is hopefully not needed ...
2980 ;; (setq window-splits (if (eq window root) 'nest window-splits))
2981 (let* ((frame (window-frame window))
2982 (parent (window-parent window))
2983 ;; Size calculations.
2984 (parent-size (window-total-size parent horflag))
2985 ;; Bind `old-size' to the current size of WINDOW and
2986 ;; `new-size' to the size of the new window.
2987 (old-size (window-total-size window horflag))
2988 (resize
2989 (and (eq window-splits 'resize)
2990 ;; Resize makes sense in iso-combinations only.
2991 (window-iso-combined-p window horflag)))
2992 (new-size
2993 (cond
2994 ((not size)
2995 (max (window-split-min-size horflag)
2996 (if resize
2997 ;; For a "resize" split try to give the new
2998 ;; window a fitting size (which must be at least
2999 ;; as large as what we can get at all).
3000 (min (- parent-size
3001 (window-min-size parent horflag))
3002 (/ parent-size
3003 (1+ (window-children-count parent))))
3004 ;; Else try to give the new window half the size of
3005 ;; WINDOW.
3006 (/ old-size 2))))
3007 ((>= size 0)
3008 ;; SIZE non-negative specifies the new size of WINDOW.
3009 (- old-size size))
3011 ;; SIZE negative specifies the size of the new window.
3012 (- size))))
3013 (root (window-parameter window 'root)))
3014 (cond
3015 ((and resize (not (window-sizable-p parent (- new-size) horflag))
3016 ;; Try agin with minimum acceptable size.
3017 (setq new-size
3018 (max new-size
3019 (window-split-min-size horflag)))
3020 (not (window-sizable-p parent (- new-size) horflag)))
3021 (error "Cannot resize %s" window))
3022 ((and (not resize)
3023 (> (+ new-size (window-min-size window horflag))
3024 old-size))
3025 (error "Cannot resize %s" window))
3026 ((< new-size
3027 (if (and size (< size 0))
3028 ;; If SIZE explicitly specifies a negative value, respect
3029 ;; that.
3030 (if horflag window-safe-min-width window-safe-min-height)
3031 (if horflag window-min-width window-min-height)))
3032 (error "New window too small")))
3034 (resize-window-reset (window-frame window) horflag)
3035 (cond
3036 (resize
3037 ;; Try to get space from OLD's siblings. We could go "up" and
3038 ;; try getting additional space from surrounding windows but we
3039 ;; won't be able to return space to those windows when we delete
3040 ;; the one we create here. Hence we do not go up.
3041 (resize-subwindows parent (- new-size) horflag)
3042 (let* ((parent-size (window-total-size parent horflag))
3043 (sub (window-child parent)))
3044 ;; Assign new normal sizes.
3045 (while sub
3046 (resize-window-normal
3047 sub (/ (* (float (window-normal-size sub horflag))
3048 (- parent-size new-size))
3049 parent-size))
3050 (setq sub (window-right sub)))))
3051 ((eq window-splits 'nest)
3052 ;; Get entire space from WINDOW making sure that a new parent
3053 ;; windows gets created.
3054 (resize-window-total window (- old-size new-size))
3055 (resize-this-window window (- new-size) horflag)
3056 (resize-window-normal
3057 window (/ (float (window-new-total-size window)) old-size)))
3059 ;; Get entire space from WINDOW making a new parent window only
3060 ;; if we need one.
3061 (resize-window-total window (- old-size new-size))
3062 (resize-this-window window (- new-size) horflag)
3063 (resize-window-normal
3064 window (/ (float (window-new-total-size window))
3065 (window-total-size (window-parent window) horflag)))))
3067 (let* ((new (split-window-internal window new-size horizontal))
3068 (new-parent (window-parent new)))
3069 (when (memq ignore-window-parameters '(nil pre))
3070 (cond
3071 ((and new-root (not (eq parent new-parent)))
3072 ;; `new-parent' becomes the new group root window
3073 ;; inheriting WINDOW's composite status. WINDOW and `new'
3074 ;; become main windows of that group.
3075 (set-window-parameter new-parent 'group t)
3076 (set-window-parameter new-parent 'composite composite)
3077 (set-window-parameter window 'group nil)
3078 (set-window-parameter window 'composite (cons 'group 'main))
3079 (set-window-parameter new 'composite (cons 'group 'main)))
3080 ((and new-main (not (eq parent new-parent)))
3081 ;; `new-parent' becomes the new dominating main window of
3082 ;; WINDOW's group.
3083 (set-window-parameter new-parent 'composite (cons 'group 'main))
3084 (set-window-parameter window 'composite (cons 'group 'main))
3085 (set-window-parameter new 'composite (cons 'group 'main)))
3086 (composite
3087 ;; `new' inherits parameters from WINDOW.
3088 (set-window-parameter new 'composite composite)
3089 (when (not (eq parent new-parent))
3090 ;; `new-parent' "inherits" the parameters as well
3091 (set-window-parameter new-parent 'composite composite)))))
3092 ;; We have to check once more how often these hooks are run.
3093 (run-window-configuration-change-hook frame)
3094 ;; Return the new window.
3095 new)))))
3097 ;; I think this should be the default; I think people will prefer it--rms.
3098 (defcustom split-window-keep-point t
3099 "If non-nil, \\[split-window-vertically] keeps the original point \
3100 in both children.
3101 This is often more convenient for editing.
3102 If nil, adjust point in each of the two windows to minimize redisplay.
3103 This is convenient on slow terminals, but point can move strangely.
3105 This option applies only to `split-window-vertically' and
3106 functions that call it. `split-window' always keeps the original
3107 point in both children."
3108 :type 'boolean
3109 :group 'windows)
3111 (defun split-window-quit-restore (new-window old-window)
3112 "Copy `quit-restore' parameter from OLD-WINDOW to NEW-WINDOW.
3113 Do this if and only if NEW-WINDOW's buffer is in `view-mode'."
3114 (let ((parameter (window-parameter old-window 'quit-restore)))
3115 (when (and parameter
3116 (with-current-buffer (window-buffer new-window)
3117 view-mode))
3118 (set-window-parameter new-window 'quit-restore parameter))))
3120 (defun split-window-vertically (&optional size)
3121 "Split selected window into two windows, one above the other.
3122 The upper window gets SIZE lines and the lower one gets the rest.
3123 SIZE negative means the lower window gets -SIZE lines and the
3124 upper one the rest. With no argument, split windows equally or
3125 close to it. Both windows display the same buffer, now current.
3127 If the variable `split-window-keep-point' is non-nil, both new
3128 windows will get the same value of point as the selected window.
3129 This is often more convenient for editing. The upper window is
3130 the selected window.
3132 Otherwise, we choose window starts so as to minimize the amount of
3133 redisplay; this is convenient on slow terminals. The new selected
3134 window is the one that the current value of point appears in. The
3135 value of point can change if the text around point is hidden by the
3136 new mode line.
3138 Regardless of the value of `split-window-keep-point', the upper
3139 window is the original one and the return value is the new, lower
3140 window."
3141 (interactive "P")
3142 (let ((old-window (selected-window))
3143 (old-point (point))
3144 (size (and size (prefix-numeric-value size)))
3145 moved-by-window-height moved new-window bottom)
3146 (when (and size (< size 0) (< (- size) window-min-height))
3147 ;; `split-window' would not signal an error here.
3148 (error "Size of new window too small"))
3149 (setq new-window (split-window nil size))
3150 (unless split-window-keep-point
3151 (with-current-buffer (window-buffer)
3152 (goto-char (window-start))
3153 (setq moved (vertical-motion (window-height)))
3154 (set-window-start new-window (point))
3155 (when (> (point) (window-point new-window))
3156 (set-window-point new-window (point)))
3157 (when (= moved (window-height))
3158 (setq moved-by-window-height t)
3159 (vertical-motion -1))
3160 (setq bottom (point)))
3161 (and moved-by-window-height
3162 (<= bottom (point))
3163 (set-window-point old-window (1- bottom)))
3164 (and moved-by-window-height
3165 (<= (window-start new-window) old-point)
3166 (set-window-point new-window old-point)
3167 (select-window new-window)))
3168 (split-window-quit-restore new-window old-window)
3169 new-window))
3171 (defun split-window-horizontally (&optional size)
3172 "Split selected window into two windows side by side.
3173 The selected window becomes the left one and gets SIZE columns.
3174 SIZE negative means the right window gets -SIZE lines.
3176 SIZE includes the width of the window's scroll bar; if there are
3177 no scroll bars, it includes the width of the divider column to
3178 the window's right, if any. SIZE omitted or nil means split
3179 window equally.
3181 The selected window remains selected. Return the new window."
3182 (interactive "P")
3183 (let ((old-window (selected-window))
3184 (size (and size (prefix-numeric-value size)))
3185 new-window)
3186 (when (and size (< size 0) (< (- size) window-min-width))
3187 ;; `split-window' would not signal an error here.
3188 (error "Size of new window too small"))
3189 (setq new-window (split-window nil size t))
3190 (split-window-quit-restore new-window old-window)
3191 new-window))
3193 ;;; Composite windows.
3194 (defun make-compound-window (&optional window main size horizontal)
3195 "Make WINDOW the main window of a new compound window.
3196 This function creates a new internal window with WINDOW and a new
3197 leaf window as its only children. WINDOW must be a leaf window
3198 and defaults to the selected window.
3200 Optional argument MAIN non-nil makes the new leaf window a main
3201 window. MAIN nil or not provided means the new leaf window
3202 becomes a support window. WINDOW itself becomes a main window.
3204 Optional arguments SIZE and HORIZONTAL are as for `split-window'.
3206 Return the new leaf window."
3207 (setq window (normalize-any-window window))
3208 (unless (or (window-live-p window) (composite-root-window-p window))
3209 (error "Window %s must be live or a composite root window" window))
3210 (let* ((composite (window-parameter window 'composite))
3211 ;; FORCE and NEST.
3212 (ignore-window-parameters t)
3213 (window-splits 'nest)
3214 (new (split-window window size horizontal))
3215 (new-parent (window-parent new)))
3216 (set-window-parameter new-parent 'compound t)
3217 (when composite (set-window-parameter new-parent 'composite composite))
3218 (set-window-parameter window 'composite (cons 'compound 'main))
3219 (set-window-parameter
3220 new 'composite (cons 'compound (if main 'main 'support)))
3221 new))
3223 (defun make-window-group (&optional window)
3224 "Make WINDOW main and root window of a new window group.
3225 WINDOW must be a live window and defaults to the selected one.
3226 Return WINDOW."
3227 (setq window (normalize-live-window window))
3228 (set-window-parameter window 'composite (cons 'group 'main)))
3230 (defun make-support-window (window support &optional size horizontal)
3231 "Add support window of type SUPPORT to WINDOW."
3232 (let* ((compound (window-parameter window 'compound))
3233 (group (window-parameter window 'group))
3234 (composite (window-parameter window 'composite))
3235 (type (car-safe composite))
3236 (role (cdr-safe composite))
3237 ;; `type' is the type of the composite window (either
3238 ;; `compound' or `group'). `role' is the role of WINDOW within
3239 ;; the composite window (either `main', `support', or t).
3240 (root (when composite (composite-root-window window)))
3241 (parent (window-parent window))
3242 (ignore-window-parameters t)
3243 (window-splits 'nest)
3244 new new-parent)
3245 (cond
3246 ((not (memq support '(compound group)))
3247 (error "Invalid support argument %s" support))
3248 ((and (eq support 'compound) (not compound) (not (eq type 'compound)))
3249 (error "Window %s is not a component of a compound window" window))
3250 ((and (eq support 'group) (not group) (not (eq type 'group)))
3251 (error "Window %s is not a component of a window group" window))
3252 ((and (eq type 'main) (not (eq window (composite-major-window window))))
3253 (error "Can't embed support window in main window")))
3254 (setq new (split-window window size horizontal))
3255 (unless (eq parent (window-parent window))
3256 (setq new-parent (window-parent window)))
3257 (cond
3258 ;; This conditional looks incredibly tedious but let's keep the
3259 ;; distinct cases self-contained to avoid further confusion.
3260 ((and compound (eq support 'compound))
3261 (when new-parent
3262 ;; `new-parent' inherits the compound status of `window'
3263 (set-window-parameter new-parent 'compound t)
3264 (set-window-parameter window 'compound nil)
3265 (when composite
3266 ;; `new-parent' inherits the composite status of `window'.
3267 (set-window-parameter new-parent 'composite composite)
3268 (set-window-parameter
3269 ;; Give `window' the highest role of its children.
3270 window 'composite (cons 'compound
3271 (composite-lowest-child-role window)))))
3272 (when group
3273 ;; `new-parent' does not inherit the group status of `window'
3274 ;; (but make sure `window' retains it).
3275 (set-window-parameter window 'group t))
3276 (set-window-parameter new 'composite (cons 'compound 'support)))
3277 ((and group (eq support 'group))
3278 (when new-parent
3279 ;; `new-parent' inherits the group status of `window'
3280 (set-window-parameter new-parent 'group t)
3281 (set-window-parameter window 'group nil)
3282 (when composite
3283 ;; `new-parent' inherits the composite status of `window'.
3284 (set-window-parameter new-parent 'composite composite)
3285 (set-window-parameter
3286 ;; Give `window' the highest role of its children.
3287 window 'composite (cons 'group
3288 (composite-lowest-child-role window)))))
3289 (when compound
3290 ;; `new-parent' does not inherit the compound status of `window'
3291 ;; (but make sure `window' retains it).
3292 (set-window-parameter window 'compound t))
3293 (set-window-parameter new 'composite (cons 'group 'support)))
3294 ((and (eq type 'compound) (eq support 'compound))
3295 (cond
3296 (new-parent
3297 (let ((role (if (eq role 'support) 'support t)))
3298 (set-window-parameter new-parent 'composite (cons 'compound role))))
3299 ((not (compound-window-p parent))
3300 (let ((role (if (composite-support-window-p parent) 'support t)))
3301 (set-window-parameter parent 'composite (cons 'compound role)))))
3302 (when group
3303 ;; `new-parent' does not inherit the group status of `window'
3304 ;; (but make sure `window' retains it).
3305 (set-window-parameter window 'group t))
3306 (set-window-parameter window 'composite composite)
3307 (set-window-parameter new 'composite (cons 'compound 'support)))
3308 ((and (eq type 'group) (eq support 'group))
3309 (cond
3310 (new-parent
3311 (let ((role (if (eq role 'support) 'support t)))
3312 (set-window-parameter new-parent 'composite (cons 'group role))))
3313 ((not (compound-window-p parent))
3314 (let ((role (if (composite-support-window-p parent) 'support t)))
3315 (set-window-parameter parent 'composite (cons 'group role)))))
3316 (when compound
3317 ;; `new-parent' does not inherit the compound status of `window'
3318 ;; (but make sure `window' retains it).
3319 (set-window-parameter window 'compound t))
3320 (set-window-parameter window 'composite composite)
3321 (set-window-parameter new 'composite (cons 'group 'support))))
3322 new))
3324 ;;; Balancing windows.
3325 (defun balance-windows (&optional window-or-frame)
3326 "Balance the sizes of subwindows of WINDOW-OR-FRAME.
3327 WINDOW-OR-FRAME is optional and defaults to the selected frame.
3328 If WINDOW-OR-FRAME denotes a frame, balance the sizes of all
3329 subwindows of that frame's root window. If WINDOW-OR-FRAME
3330 denots a window, balance the sizes of all subwindows of that
3331 window."
3332 (interactive)
3333 (let* ((window
3334 (cond
3335 ((or (not window-or-frame)
3336 (frame-live-p window-or-frame))
3337 (frame-root-window window-or-frame))
3338 ((or (window-live-p window-or-frame)
3339 (window-child window-or-frame))
3340 window-or-frame)
3342 (error "Not a window or frame %s" window-or-frame))))
3343 (frame (window-frame window)))
3344 ;; Balance vertically.
3345 (resize-window-reset (window-frame window))
3346 (balance-windows-1 window)
3347 (resize-window-apply frame)
3348 ;; Balance horizontally.
3349 (resize-window-reset (window-frame window) t)
3350 (balance-windows-1 window t)
3351 (resize-window-apply frame t)))
3353 (defun balance-windows-1 (window &optional horizontal)
3354 "Subroutine of `balance-windows'."
3355 (if (window-child window)
3356 (let ((sub (window-child window)))
3357 (if (window-iso-combined-p sub horizontal)
3358 (balance-windows-2 window horizontal)
3359 (let ((size (window-new-total-size window)))
3360 (while sub
3361 (resize-window-total sub size)
3362 (balance-windows-1 sub horizontal)
3363 (setq sub (window-right sub))))))))
3365 (defun balance-windows-2 (window horizontal)
3366 "Subroutine of `balance-windows-1'.
3367 WINDOW must be an iso-combination."
3368 (let* ((first (window-child window))
3369 (sub first)
3370 (number-of-children 0)
3371 (parent-size (window-new-total-size window))
3372 (total-sum parent-size)
3373 found failed size sub-total sub-delta sub-amount rest)
3374 (while sub
3375 (setq number-of-children (1+ number-of-children))
3376 (when (window-size-fixed-p sub horizontal)
3377 (setq total-sum
3378 (- total-sum (window-total-size sub horizontal)))
3379 (resize-window-normal sub 'ignore))
3380 (setq sub (window-right sub)))
3382 (setq failed t)
3383 (while (and failed (> number-of-children 0))
3384 (setq size (/ total-sum number-of-children))
3385 (setq failed nil)
3386 (setq sub first)
3387 (while (and sub (not failed))
3388 ;; Ignore subwindows that should be ignored or are stuck.
3389 (unless (resize-subwindows-skip-p sub)
3390 (setq found t)
3391 (setq sub-total (window-total-size sub horizontal))
3392 (setq sub-delta (- size sub-total))
3393 (setq sub-amount
3394 (window-sizable sub sub-delta horizontal))
3395 ;; Register the new total size for this subwindow.
3396 (resize-window-total sub (+ sub-total sub-amount))
3397 (unless (= sub-amount sub-delta)
3398 (setq total-sum (- total-sum sub-total sub-amount))
3399 (setq number-of-children (1- number-of-children))
3400 ;; We failed and need a new round.
3401 (setq failed t)
3402 (resize-window-normal sub 'skip)))
3403 (setq sub (window-right sub))))
3405 (setq rest (% total-sum number-of-children))
3406 ;; Fix rounding by trying to enlarge non-stuck windows by one line
3407 ;; (column) until `rest' is zero.
3408 (setq sub first)
3409 (while (and sub (> rest 0))
3410 (unless (resize-subwindows-skip-p window)
3411 (resize-window-total sub 1 t)
3412 (setq rest (1- rest)))
3413 (setq sub (window-right sub)))
3415 ;; Fix rounding by trying to enlarge stuck windows by one line
3416 ;; (column) until `rest' equals zero.
3417 (setq sub first)
3418 (while (and sub (> rest 0))
3419 (unless (eq (window-new-normal-size sub) 'ignore)
3420 (resize-window-total sub 1 t)
3421 (setq rest (1- rest)))
3422 (setq sub (window-right sub)))
3424 (setq sub first)
3425 (while sub
3426 ;; Record new normal sizes.
3427 (resize-window-normal
3428 sub (/ (if (eq (window-new-normal-size sub) 'ignore)
3429 (window-total-size sub horizontal)
3430 (window-new-total-size sub))
3431 (float parent-size)))
3432 ;; Recursively balance each subwindow's subwindows.
3433 (balance-windows-1 sub horizontal)
3434 (setq sub (window-right sub)))))
3436 (defun window-fixed-size-p (&optional window direction)
3437 "Return t if WINDOW cannot be resized in DIRECTION.
3438 WINDOW defaults to the selected window. DIRECTION can be
3439 nil (i.e. any), `height' or `width'."
3440 (with-current-buffer (window-buffer window)
3441 (when (and (boundp 'window-size-fixed) window-size-fixed)
3442 (not (and direction
3443 (member (cons direction window-size-fixed)
3444 '((height . width) (width . height))))))))
3446 ;;; A different solution to balance-windows.
3447 (defvar window-area-factor 1
3448 "Factor by which the window area should be over-estimated.
3449 This is used by `balance-windows-area'.
3450 Changing this globally has no effect.")
3451 (make-variable-buffer-local 'window-area-factor)
3453 (defun balance-windows-area-adjust (window delta horizontal)
3454 "Wrapper around `resize-window' with error checking.
3455 Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
3456 ;; `resize-window' may fail if delta is too large.
3457 (while (>= (abs delta) 1)
3458 (condition-case err
3459 (progn
3460 (resize-window window delta horizontal)
3461 (setq delta 0))
3462 (error
3463 ;;(message "adjust: %s" (error-message-string err))
3464 (setq delta (/ delta 2))))))
3466 (defun balance-windows-area ()
3467 "Make all visible windows the same area (approximately).
3468 See also `window-area-factor' to change the relative size of
3469 specific buffers."
3470 (interactive)
3471 (let* ((unchanged 0) (carry 0) (round 0)
3472 ;; Remove fixed-size windows.
3473 (wins (delq nil (mapcar (lambda (win)
3474 (if (not (window-fixed-size-p win)) win))
3475 (window-list nil 'nomini))))
3476 (changelog nil)
3477 next)
3478 ;; Resizing a window changes the size of surrounding windows in complex
3479 ;; ways, so it's difficult to balance them all. The introduction of
3480 ;; `adjust-window-trailing-edge' made it a bit easier, but it is still
3481 ;; very difficult to do. `balance-window' above takes an off-line
3482 ;; approach: get the whole window tree, then balance it, then try to
3483 ;; adjust the windows so they fit the result.
3484 ;; Here, instead, we take a "local optimization" approach, where we just
3485 ;; go through all the windows several times until nothing needs to be
3486 ;; changed. The main problem with this approach is that it's difficult
3487 ;; to make sure it terminates, so we use some heuristic to try and break
3488 ;; off infinite loops.
3489 ;; After a round without any change, we allow a second, to give a chance
3490 ;; to the carry to propagate a minor imbalance from the end back to
3491 ;; the beginning.
3492 (while (< unchanged 2)
3493 ;; (message "New round")
3494 (setq unchanged (1+ unchanged) round (1+ round))
3495 (dolist (win wins)
3496 (setq next win)
3497 (while (progn (setq next (next-window next))
3498 (window-fixed-size-p next)))
3499 ;; (assert (eq next (or (cadr (member win wins)) (car wins))))
3500 (let* ((horiz
3501 (< (car (window-edges win)) (car (window-edges next))))
3502 (areadiff (/ (- (* (window-height next) (window-width next)
3503 (buffer-local-value 'window-area-factor
3504 (window-buffer next)))
3505 (* (window-height win) (window-width win)
3506 (buffer-local-value 'window-area-factor
3507 (window-buffer win))))
3508 (max (buffer-local-value 'window-area-factor
3509 (window-buffer win))
3510 (buffer-local-value 'window-area-factor
3511 (window-buffer next)))))
3512 (edgesize (if horiz
3513 (+ (window-height win) (window-height next))
3514 (+ (window-width win) (window-width next))))
3515 (diff (/ areadiff edgesize)))
3516 (when (zerop diff)
3517 ;; Maybe diff is actually closer to 1 than to 0.
3518 (setq diff (/ (* 3 areadiff) (* 2 edgesize))))
3519 (when (and (zerop diff) (not (zerop areadiff)))
3520 (setq diff (/ (+ areadiff carry) edgesize))
3521 ;; Change things smoothly.
3522 (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2))))
3523 (if (zerop diff)
3524 ;; Make sure negligible differences don't accumulate to
3525 ;; become significant.
3526 (setq carry (+ carry areadiff))
3527 ;; This used `adjust-window-trailing-edge' before and uses
3528 ;; `resize-window' now. Error wrapping is still needed.
3529 (balance-windows-area-adjust win diff horiz)
3530 ;; (sit-for 0.5)
3531 (let ((change (cons win (window-edges win))))
3532 ;; If the same change has been seen already for this window,
3533 ;; we're most likely in an endless loop, so don't count it as
3534 ;; a change.
3535 (unless (member change changelog)
3536 (push change changelog)
3537 (setq unchanged 0 carry 0)))))))
3538 ;; We've now basically balanced all the windows.
3539 ;; But there may be some minor off-by-one imbalance left over,
3540 ;; so let's do some fine tuning.
3541 ;; (bw-finetune wins)
3542 ;; (message "Done in %d rounds" round)
3546 ;;; Displaying buffers.
3547 (defgroup display-buffer nil
3548 "Displaying buffers in windows."
3549 :version "24.1"
3550 :group 'windows)
3552 (defcustom display-buffer-function nil
3553 "If non-nil, function to call to display a buffer.
3554 `display-buffer' calls this function with two arguments, the
3555 buffer to display and a flag which if non-nil means that the
3556 selected window is not acceptable for displaying the buffer. It
3557 should choose or create a window, display the specified buffer in
3558 it, and return the window.
3560 Commands such as `switch-to-buffer-other-window' and
3561 `find-file-other-window' work using this function."
3562 :type '(choice
3563 (const nil)
3564 (function :tag "function"))
3565 :group 'display-buffer)
3567 (defcustom special-display-buffer-names nil
3568 "List of names of buffers that should be displayed specially.
3569 Displaying a buffer with `display-buffer' or `pop-to-buffer', if
3570 its name is in this list, displays the buffer in a way specified
3571 by `special-display-function'. `special-display-popup-frame'
3572 \(the default for `special-display-function') usually displays
3573 the buffer in a separate frame made with the parameters specified
3574 by `special-display-frame-alist'. If `special-display-function'
3575 has been set to some other function, that function is called with
3576 the buffer as first, and nil as second argument.
3578 Alternatively, an element of this list can be specified as
3579 \(BUFFER-NAME FRAME-PARAMETERS), where BUFFER-NAME is a buffer
3580 name and FRAME-PARAMETERS an alist of \(PARAMETER . VALUE) pairs.
3581 `special-display-popup-frame' will interpret such pairs as frame
3582 parameters when it creates a special frame, overriding the
3583 corresponding values from `special-display-frame-alist'.
3585 As a special case, if FRAME-PARAMETERS contains (same-window . t)
3586 `special-display-popup-frame' displays that buffer in the
3587 selected window. If FRAME-PARAMETERS contains (same-frame . t),
3588 it displays that buffer in a window on the selected frame.
3590 If `special-display-function' specifies some other function than
3591 `special-display-popup-frame', that function is called with the
3592 buffer named BUFFER-NAME as first, and FRAME-PARAMETERS as second
3593 argument.
3595 Finally, an element of this list can be also specified as
3596 \(BUFFER-NAME FUNCTION OTHER-ARGS). In that case,
3597 `special-display-popup-frame' will call FUNCTION with the buffer
3598 named BUFFER-NAME as first argument, and OTHER-ARGS as the
3599 second. If `special-display-function' specifies some other
3600 function, that function is called with the buffer named
3601 BUFFER-NAME as first, and the element's cdr as second argument.
3603 If this variable appears \"not to work\", because you added a
3604 name to it but the corresponding buffer is displayed in the
3605 selected window, look at the values of `same-window-buffer-names'
3606 and `same-window-regexps'. Those variables take precedence over
3607 this one.
3609 See also `special-display-regexps'."
3610 :type '(repeat
3611 (choice :tag "Buffer"
3612 :value ""
3613 (string :format "%v")
3614 (cons :tag "With parameters"
3615 :format "%v"
3616 :value ("" . nil)
3617 (string :format "%v")
3618 (repeat :tag "Parameters"
3619 (cons :format "%v"
3620 (symbol :tag "Parameter")
3621 (sexp :tag "Value"))))
3622 (list :tag "With function"
3623 :format "%v"
3624 :value ("" . nil)
3625 (string :format "%v")
3626 (function :tag "Function")
3627 (repeat :tag "Arguments" (sexp)))))
3628 :group 'display-buffer
3629 :group 'frames)
3631 ;;;###autoload
3632 (put 'special-display-buffer-names 'risky-local-variable t)
3634 (defcustom special-display-regexps nil
3635 "List of regexps saying which buffers should be displayed specially.
3636 Displaying a buffer with `display-buffer' or `pop-to-buffer', if
3637 any regexp in this list matches its name, displays it specially
3638 using `special-display-function'.
3640 The function `special-display-popup-frame' \(the default for
3641 `special-display-function') usually displays the buffer in a
3642 separate frame made with the parameters specified by
3643 `special-display-frame-alist'. If `special-display-function' has
3644 been set to some other function, that function is called with the
3645 buffer as first, and nil as second argument.
3647 Alternatively, an element of this list can be specified as
3648 \(REGEXP FRAME-PARAMETERS), where REGEXP is a regexp as above and
3649 FRAME-PARAMETERS an alist of (PARAMETER . VALUE) pairs.
3650 `special-display-popup-frame' will then interpret these pairs as
3651 frame parameters when creating a special frame for a buffer whose
3652 name matches REGEXP, overriding the corresponding values from
3653 `special-display-frame-alist'.
3655 As a special case, if FRAME-PARAMETERS contains (same-window . t)
3656 `special-display-popup-frame' displays buffers matching REGEXP in
3657 the selected window. \(same-frame . t) in FRAME-PARAMETERS means
3658 to display such buffers in a window on the selected frame.
3660 If `special-display-function' specifies some other function than
3661 `special-display-popup-frame', that function is called with the
3662 buffer whose name matched REGEXP as first, and FRAME-PARAMETERS
3663 as second argument.
3665 Finally, an element of this list can be also specified as
3666 \(REGEXP FUNCTION OTHER-ARGS). `special-display-popup-frame'
3667 will then call FUNCTION with the buffer whose name matched
3668 REGEXP as first, and OTHER-ARGS as second argument. If
3669 `special-display-function' specifies some other function, that
3670 function is called with the buffer whose name matched REGEXP
3671 as first, and the element's cdr as second argument.
3673 If this variable appears \"not to work\", because you added a
3674 name to it but the corresponding buffer is displayed in the
3675 selected window, look at the values of `same-window-buffer-names'
3676 and `same-window-regexps'. Those variables take precedence over
3677 this one.
3679 See also `special-display-buffer-names'."
3680 :type '(repeat
3681 (choice :tag "Buffer"
3682 :value ""
3683 (regexp :format "%v")
3684 (cons :tag "With parameters"
3685 :format "%v"
3686 :value ("" . nil)
3687 (regexp :format "%v")
3688 (repeat :tag "Parameters"
3689 (cons :format "%v"
3690 (symbol :tag "Parameter")
3691 (sexp :tag "Value"))))
3692 (list :tag "With function"
3693 :format "%v"
3694 :value ("" . nil)
3695 (regexp :format "%v")
3696 (function :tag "Function")
3697 (repeat :tag "Arguments" (sexp)))))
3698 :group 'display-buffer
3699 :group 'frames)
3701 (defun special-display-p (buffer-name)
3702 "Return non-nil if a buffer named BUFFER-NAME is displayed specially.
3703 More precisely, return t if `special-display-buffer-names' or
3704 `special-display-regexps' contain a string entry equaling or
3705 matching BUFFER-NAME. If `special-display-buffer-names' or
3706 `special-display-regexps' contain a list entry whose car equals
3707 or matches BUFFER-NAME, the return value is the cdr of that
3708 entry."
3709 (let (tmp)
3710 (cond
3711 ((not (stringp buffer-name)))
3712 ((member buffer-name special-display-buffer-names)
3714 ((setq tmp (assoc buffer-name special-display-buffer-names))
3715 (cdr tmp))
3716 ((catch 'found
3717 (dolist (regexp special-display-regexps)
3718 (cond
3719 ((stringp regexp)
3720 (when (string-match-p regexp buffer-name)
3721 (throw 'found t)))
3722 ((and (consp regexp) (stringp (car regexp))
3723 (string-match-p (car regexp) buffer-name))
3724 (throw 'found (cdr regexp))))))))))
3726 (defcustom special-display-function 'special-display-popup-frame
3727 "Function to call for displaying special buffers.
3728 This function is called with two arguments - the buffer and,
3729 optionally, a list - and should return a window displaying that
3730 buffer. The default value usually makes a separate frame for the
3731 buffer using `special-display-frame-alist' to specify the frame
3732 parameters. See the definition of `special-display-popup-frame'
3733 for how to specify such a function.
3735 A buffer is special when its name is either listed in
3736 `special-display-buffer-names' or matches a regexp in
3737 `special-display-regexps'."
3738 :type 'function
3739 :group 'frames)
3741 (defcustom same-window-buffer-names nil
3742 "List of names of buffers that should appear in the \"same\" window.
3743 `display-buffer' and `pop-to-buffer' show a buffer whose name is
3744 on this list in the selected rather than some other window.
3746 An element of this list can be a cons cell instead of just a
3747 string. In that case, the cell's car must be a string specifying
3748 the buffer name. This is for compatibility with
3749 `special-display-buffer-names'; the cdr of the cons cell is
3750 ignored.
3752 See also `same-window-regexps'."
3753 :type '(repeat (string :format "%v"))
3754 :group 'display-buffer)
3756 (defcustom same-window-regexps nil
3757 "List of regexps saying which buffers should appear in the \"same\" window.
3758 `display-buffer' and `pop-to-buffer' show a buffer whose name
3759 matches a regexp on this list in the selected rather than some
3760 other window.
3762 An element of this list can be a cons cell instead of just a
3763 string. In that case, the cell's car must be a regexp matching
3764 the buffer name. This is for compatibility with
3765 `special-display-regexps'; the cdr of the cons cell is ignored.
3767 See also `same-window-buffer-names'."
3768 :type '(repeat (regexp :format "%v"))
3769 :group 'display-buffer)
3771 (defun same-window-p (buffer-name)
3772 "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window.
3773 This function returns non-nil if `display-buffer' or
3774 `pop-to-buffer' would show a buffer named BUFFER-NAME in the
3775 selected rather than \(as usual\) some other window. See
3776 `same-window-buffer-names' and `same-window-regexps'."
3777 (cond
3778 ((not (stringp buffer-name)))
3779 ;; The elements of `same-window-buffer-names' can be buffer
3780 ;; names or cons cells whose cars are buffer names.
3781 ((member buffer-name same-window-buffer-names))
3782 ((assoc buffer-name same-window-buffer-names))
3783 ((catch 'found
3784 (dolist (regexp same-window-regexps)
3785 ;; The elements of `same-window-regexps' can be regexps
3786 ;; or cons cells whose cars are regexps.
3787 (when (or (and (stringp regexp)
3788 (string-match regexp buffer-name))
3789 (and (consp regexp) (stringp (car regexp))
3790 (string-match-p (car regexp) buffer-name)))
3791 (throw 'found t)))))))
3793 (defcustom pop-up-frames nil
3794 "Whether `display-buffer' should make a separate frame.
3795 If nil, never make a separate frame.
3796 If the value is `graphic-only', make a separate frame
3797 on graphic displays only.
3798 Any other non-nil value means always make a separate frame."
3799 :type '(choice
3800 (const :tag "Never" nil)
3801 (const :tag "On graphic displays only" graphic-only)
3802 (const :tag "Always" t))
3803 :group 'display-buffer
3804 :group 'frames)
3806 (defcustom display-buffer-reuse-frames nil
3807 "Non-nil means `display-buffer' should reuse frames.
3808 If the buffer in question is already displayed in a frame, raise
3809 that frame."
3810 :type 'boolean
3811 :version "21.1"
3812 :group 'display-buffer
3813 :group 'frames)
3815 (defcustom pop-up-windows t
3816 "Non-nil means `display-buffer' is allowed to make a new window.
3817 A non-empty list specifies the windows `display-buffer' will
3818 consider for splitting. The following entries are supported
3819 where \"frame\" refers to the frame chosen to display the buffer:
3821 largest ...... largest window
3822 lru .......... least recently used window
3823 selected ..... frame's selected window
3824 root ......... frame's root window
3826 The default value t stands for the list `(largest lru)'. This
3827 means that `display-buffer' will first try to split the largest
3828 window and, if that fails, the least recently used window."
3829 :type '(choice
3830 (const :tag "Disallow" nil)
3831 (const :tag "Allow" t)
3832 (repeat :tag "Preferences"
3833 (choice
3834 (const :tag "Largest" largest)
3835 (const :tag "Least Recently Used" lru)
3836 (const :tag "Selected" selected)
3837 (const :tag "Frame Root Window" root))))
3838 :group 'display-buffer)
3840 (defcustom split-window-preferred-function 'split-window-sensibly
3841 "Function called by `display-buffer' to split a window.
3842 This function is called with a window as single argument and is
3843 supposed to split that window and return the new window. If the
3844 window can (or shall) not be split, it is supposed to return nil.
3846 The default is to call the function `split-window-sensibly' which
3847 tries to split the window in a way which seems most suitable.
3848 You can customize the options `split-height-threshold' and/or
3849 `split-width-threshold' in order to have `split-window-sensibly'
3850 prefer either vertical or horizontal splitting.
3852 If you set this to any other function, bear in mind that
3853 `display-buffer' may call that function repeatedly; the option
3854 `pop-up-windows' controls which windows may become the argument
3855 of this function.
3857 The window selected at the time `display-buffer' was invoked is
3858 still selected when this function is called. Hence you can
3859 compare the window argument with the value of `selected-window'
3860 if you intend to split the selected window instead or if you do
3861 not want to split the selected window."
3862 :type 'function
3863 :version "23.1"
3864 :group 'display-buffer)
3866 (defcustom split-height-threshold 80
3867 "Minimum height for splitting a window to display a buffer.
3868 If this is an integer, `display-buffer' can split a window
3869 vertically only if it has at least this many lines. If this is
3870 nil, `display-buffer' does not split windows vertically. If a
3871 window is the only window on its frame, `display-buffer' may
3872 split it vertically disregarding the value of this variable."
3873 :type '(choice (const nil) (integer :tag "lines"))
3874 :version "23.1"
3875 :group 'display-buffer)
3877 (defcustom split-width-threshold 160
3878 "Minimum width for splitting a window to display a buffer.
3879 If this is an integer, `display-buffer' can split a window
3880 horizontally only if it has at least this many columns. If this
3881 is nil, `display-buffer' cannot split windows horizontally."
3882 :type '(choice (const nil) (integer :tag "columns"))
3883 :version "23.1"
3884 :group 'display-buffer)
3886 (defun window-sensibly-splittable-p (window &optional horizontal)
3887 "Return non-nil if `split-window-sensibly' may split WINDOW.
3888 Optional argument HORIZONTAL nil or omitted means check whether
3889 `split-window-sensibly' may split WINDOW vertically. HORIZONTAL
3890 non-nil means check whether WINDOW may be split horizontally.
3892 WINDOW may be split vertically when the following conditions
3893 hold:
3894 - `window-size-fixed' is either nil or equals `width' for the
3895 buffer of WINDOW.
3896 - `split-height-threshold' is an integer and WINDOW is at least as
3897 high as `split-height-threshold'.
3898 - When WINDOW is split evenly, the emanating windows are at least
3899 `window-min-height' lines tall and can accommodate at least one
3900 line plus - if WINDOW has one - a mode line.
3902 WINDOW may be split horizontally when the following conditions
3903 hold:
3904 - `window-size-fixed' is either nil or equals `height' for the
3905 buffer of WINDOW.
3906 - `split-width-threshold' is an integer and WINDOW is at least as
3907 wide as `split-width-threshold'.
3908 - When WINDOW is split evenly, the emanating windows are at least
3909 `window-min-width' or two (whichever is larger) columns wide."
3910 (let* ((min-size
3911 ;; The minimum size of any popped-up window.
3912 (if horizontal
3913 (and (numberp split-width-threshold)
3914 (max (/ split-width-threshold 2)
3915 window-min-width))
3916 (and (numberp split-height-threshold)
3917 (max (/ split-height-threshold 2)
3918 window-min-height))))
3919 (parent (window-parent window))
3920 ;; Bind both of these to min-size, only one will matter.
3921 (window-min-width min-size)
3922 (window-min-height min-size))
3923 (when min-size
3924 ;; `display-buffer' is not allowed to override `window-splits'.
3925 (if (and parent (eq window-splits 'resize)
3926 (window-iso-combined-p window horizontal))
3927 (>= (- (window-total-size parent horizontal)
3928 (window-min-size parent horizontal))
3929 min-size)
3930 (and (not (window-size-fixed-p window horizontal))
3931 (>= (window-total-size window horizontal)
3932 (+ (max (window-min-size window horizontal)
3933 min-size)
3934 min-size)))))))
3936 (defun split-window-sensibly (window)
3937 "Split WINDOW in a way suitable for `display-buffer'.
3938 If `split-height-threshold' specifies an integer, WINDOW is at
3939 least `split-height-threshold' lines tall and can be split
3940 vertically, split WINDOW into two windows one above the other and
3941 return the lower window. Otherwise, if `split-width-threshold'
3942 specifies an integer, WINDOW is at least `split-width-threshold'
3943 columns wide and can be split horizontally, split WINDOW into two
3944 windows side by side and return the window on the right. If this
3945 can't be done either and WINDOW is the only window on its frame,
3946 try to split WINDOW vertically disregarding any value specified
3947 by `split-height-threshold'. If that succeeds, return the lower
3948 window. Return nil otherwise.
3950 By default `display-buffer' routines call this function to split
3951 the largest or least recently used window. To change the default
3952 beahvior customize the option `split-window-preferred-function'."
3953 (or (and (window-sensibly-splittable-p window)
3954 ;; Split window vertically.
3955 (if (window-live-p window)
3956 (with-selected-window window
3957 (split-window-vertically))
3958 (split-window
3959 window (- (max window-min-height 1
3960 (/ split-height-threshold 2))))))
3961 (and (window-sensibly-splittable-p window t)
3962 ;; Split window horizontally.
3963 (if (window-live-p window)
3964 (with-selected-window window
3965 (split-window-horizontally))
3966 (split-window
3967 window (- (max window-min-width 2
3968 (/ split-width-threshold 2)))
3969 t)))
3970 (and (frame-root-window-p window)
3971 (not (window-minibuffer-p window))
3972 ;; If WINDOW is the only window on its frame and is not the
3973 ;; minibuffer window, try to split it vertically disregarding
3974 ;; the value of `split-height-threshold'.
3975 (let ((split-height-threshold 0))
3976 (when (window-sensibly-splittable-p window)
3977 (with-selected-window window
3978 (split-window-vertically)))))))
3980 ;; Minibuffer-only frames should be documented better. They really
3981 ;; deserve a separate section in the manual. Also
3982 ;; `last-nonminibuffer-frame' is nowhere documented in the manual.
3983 (defun window--usable-frame (frame)
3984 "Return FRAME if it is live and not a minibuffer-only frame."
3985 (and (frame-live-p frame)
3986 (not (window-minibuffer-p (frame-root-window frame)))
3987 frame))
3989 (defcustom even-window-heights t
3990 "If non-nil `display-buffer' will try to even window heights.
3991 Otherwise `display-buffer' will leave the window configuration
3992 alone. Heights are evened only when `display-buffer' reuses a
3993 window that appears above or below the selected window."
3994 :type 'boolean
3995 :group 'display-buffer)
3997 (defvar display-buffer-window-and-buffer nil
3998 "Window used by `display-buffer' and related information.
3999 After `display-buffer' displays a buffer in some window this
4000 variable is a cons cell whose car denotes the window used to
4001 display the buffer. The cdr is either nil \(which means the same
4002 buffer was displayed before in that window), t \(which means that
4003 window was created by `display-buffer'), or the buffer displayed
4004 previously in that window.
4006 This variable holds the value produced by the last invocation of
4007 `display-buffer' and is nil if there was no such invocation.")
4009 (defsubst display-buffer-window-and-buffer (window &optional value)
4010 "Set `display-buffer-window-and-buffer' to cons of WINDOW and VALUE.
4011 VALUE defaults to nil."
4012 (setq display-buffer-window-and-buffer (cons window value)))
4014 (defun window--display-buffer-in-window (buffer window &optional dedicated)
4015 "Display BUFFER in WINDOW and maybe raise its frame.
4016 If DEDICATED is non-nil, use it to set the `window-dedicated-p'
4017 flag of WINDOW. Return WINDOW."
4018 (when (and (buffer-live-p buffer) (window-live-p window))
4019 (set-window-buffer window buffer)
4020 (when dedicated
4021 (set-window-dedicated-p window dedicated))
4022 (window--raise-window-frame window)))
4024 (defun window--reuse-window (window buffer not-this-window)
4025 "Reuse WINDOW for displaying BUFFER.
4026 If NOT-THIS-WINDOW is non-nil and WINDOW is the selected window
4027 do nothing and return nil. Return nil also if WINDOW is
4028 dedicated to its buffer. Otherwise, display buffer in WINDOW,
4029 even window heights if requested, and return WINDOW."
4030 (unless (or (and not-this-window (eq window (selected-window)))
4031 (and (window-dedicated-p window)
4032 (not (eq (window-buffer window) buffer))))
4033 ;; Save `quit-restore' information: It's absolutely necessary to do
4034 ;; this _before_ handling `even-window-heights'. Do not overwrite
4035 ;; an existing value.
4036 (unless (window-parameter window 'quit-restore)
4037 (set-window-parameter
4038 window 'quit-restore
4039 (list (window-buffer window) (window-start window)
4040 (window-point window) buffer (window-total-size window)
4041 (selected-window))))
4042 ;; Handle `even-window-heights' option.
4043 (when (and even-window-heights
4044 ;; Not needed (but often WINDOW is the selected window):
4045 (not (eq window (selected-window)))
4046 ;; Don't resize minibuffer windows.
4047 (not (window-minibuffer-p))
4048 ;; Resize iff the selected window is higher than WINDOW.
4049 (> (window-total-size) (window-total-size window))
4050 ;; Resize vertical combinations only.
4051 (and (window-parent) (window-iso-combined-p (window-parent))
4052 ;; WINDOW must be adjacent to the selected one.
4053 (or (eq window (window-prev)) (eq window (window-next)))))
4054 ;; Don't throw an error if we can't even window heights for
4055 ;; whatever reason. In any case, enlarging the selected window
4056 ;; might fail anyway if there are other windows above or below
4057 ;; WINDOW and the selected one. But for a simple two windows
4058 ;; configuration the present behavior is good enough so why care?
4059 (condition-case nil
4060 (resize-window
4061 window (/ (- (window-total-size window) (window-total-size)) 2))
4062 (error nil)))
4063 (display-buffer-window-and-buffer window (window-buffer window))
4064 ;; Display BUFFER in WINDOW.
4065 (window--display-buffer-in-window buffer window)))
4067 ;; This variable should be probably documented in the manual.
4068 (defvar display-buffer-mark-dedicated nil
4069 "If non-nil, `display-buffer' marks the windows it creates as dedicated.
4070 The actual non-nil value of this variable will be copied to the
4071 `window-dedicated-p' flag.")
4073 (defun window--pop-up-window (buffer frame)
4074 "Pop up a new window for BUFFER on FRAME.
4075 If FRAME cannot be split, try to pop up a window on the last
4076 nonminibuffer frame instead. Return the new window if splitting
4077 succeeded, nil otherwise.
4079 See the documentation of the variable `pop-up-windows' how to
4080 choose the window to be split for popping up the new one."
4081 (when (or (and (window--usable-frame frame)
4082 (not (frame-parameter frame 'unsplittable)))
4083 (and (setq frame (last-nonminibuffer-frame))
4084 (window--usable-frame frame)
4085 (not (frame-parameter frame 'unsplittable))))
4086 (let* ((selected-window (selected-window))
4087 (windows (window-list-1 (frame-first-window frame) 'nomini frame))
4088 (probes (if (eq pop-up-windows t) '(largest lru) pop-up-windows))
4089 window new-window)
4090 (catch 'done
4091 ;; Try to find a window suiting `pop-up-windows'.
4092 (dolist (probe probes)
4093 (setq window
4094 (cond
4095 ((eq probe 'selected)
4096 (frame-selected-window frame))
4097 ((eq probe 'largest)
4098 (get-largest-window frame t))
4099 ((eq probe 'lru)
4100 (get-lru-window frame t))
4101 ((eq probe 'root)
4102 (frame-root-window frame))))
4103 ;; Do not consider `window' again.
4104 (setq windows (remq window windows))
4105 (when (and (eq (window-frame window) frame)
4106 (not (window-minibuffer-p window))
4107 (not (frame-parameter frame 'unsplittable))
4108 (setq new-window
4109 ;; Since `split-window-preferred-function' might
4110 ;; throw an error use `condition-case'.
4111 (condition-case nil
4112 (funcall split-window-preferred-function window)
4113 (error nil))))
4114 (set-window-parameter
4115 new-window 'quit-restore (list t selected-window))
4116 (display-buffer-window-and-buffer new-window t)
4117 (window--display-buffer-in-window
4118 buffer new-window display-buffer-mark-dedicated)
4119 (throw 'done new-window)))))))
4121 (defun window--pop-up-frame (buffer)
4122 "Pop up a new frame for displaying BUFFER.
4123 Return the window displaying BUFFER if creating the new frame was
4124 successful, nil otherwise."
4125 (let* ((selected-window (selected-window))
4126 (frame (funcall pop-up-frame-function))
4127 (window (when frame (frame-selected-window frame))))
4128 (when window
4129 (display-buffer-window-and-buffer window t)
4130 (window--display-buffer-in-window
4131 buffer window display-buffer-mark-dedicated)
4132 ;; Make sure that quitting is allowed to delete the frame.
4133 (set-window-parameter
4134 window 'quit-restore (list t selected-window))
4135 window)))
4137 (defun window--raise-window-frame (&optional window)
4138 "Raise the frame containing WINDOW.
4139 WINDOW must be a live window and defaults to the selected one.
4140 Return WINDOW.
4142 This function does not raise the selected or an invisible frame."
4143 (setq window (normalize-live-window window))
4144 (let* ((frame (window-frame window))
4145 (visible (frame-visible-p frame)))
4146 (unless (or (not visible)
4147 ;; Assume the selected frame is already visible enough.
4148 (eq frame (selected-frame))
4149 ;; Assume the frame from which we invoked the minibuffer
4150 ;; is visible.
4151 (and (minibuffer-window-active-p (selected-window))
4152 (eq frame (window-frame (minibuffer-selected-window)))))
4153 (raise-frame frame))
4154 window))
4156 (defun display-buffer (buffer-or-name &optional not-this-window frame)
4157 "Make buffer BUFFER-OR-NAME appear in some window but don't select it.
4158 BUFFER-OR-NAME must be a buffer or the name of an existing
4159 buffer. Return the window chosen to display BUFFER-OR-NAME or
4160 nil if no such window is found.
4162 Optional argument NOT-THIS-WINDOW non-nil means display the
4163 buffer in a window other than the selected one, even if it is
4164 already displayed in the selected window.
4166 Optional argument FRAME specifies which frames to investigate
4167 when the specified buffer is already displayed. If the buffer is
4168 already displayed in some window on one of these frames simply
4169 return that window. Possible values of FRAME are:
4171 `visible' - consider windows on all visible frames.
4173 0 - consider windows on all visible or iconified frames.
4175 t - consider windows on all frames.
4177 A specific frame - consider windows on that frame only.
4179 nil - consider windows on the selected frame \(actually the
4180 last non-minibuffer frame\) only. If, however, either
4181 `display-buffer-reuse-frames' or `pop-up-frames' is non-nil
4182 \(non-nil and not graphic-only on a text-only terminal),
4183 consider all visible or iconified frames."
4184 (interactive "BDisplay buffer:\nP")
4185 (let* ((buffer (normalize-live-buffer buffer-or-name))
4186 (buffer-name (buffer-name buffer))
4187 (can-use-selected-window
4188 ;; We can reuse the selected window unless NOT-THIS-WINDOW is
4189 ;; non-nil, or the selected window is either dedicated to its
4190 ;; buffer, or it is a `minibuffer-window'.
4191 (not (or not-this-window
4192 (window-dedicated-p)
4193 (window-minibuffer-p))))
4194 ;; On text-only terminals do not pop up a new frame when
4195 ;; `pop-up-frames' equals graphic-only.
4196 (pop-up-frame (if (eq pop-up-frames 'graphic-only)
4197 (display-graphic-p)
4198 pop-up-frames))
4199 ;; `frame-to-use' is the frame where to show `buffer' - either
4200 ;; the selected frame or the last nonminibuffer frame.
4201 (frame-to-use
4202 (or (window--usable-frame (selected-frame))
4203 (window--usable-frame (last-nonminibuffer-frame))))
4204 ;; `window-to-use' is the window we use for showing `buffer'.
4205 window-to-use)
4206 (cond
4207 (display-buffer-function
4208 ;; Let `display-buffer-function' do the job.
4209 (funcall display-buffer-function buffer not-this-window))
4210 ((and (not not-this-window) (eq (window-buffer) buffer))
4211 ;; The selected window already displays BUFFER and NOT-THIS-WINDOW
4212 ;; is nil, so reuse the selected window.
4213 (selected-window))
4214 ((and can-use-selected-window (same-window-p buffer-name))
4215 ;; If the buffer's name tells us to use the selected window do so.
4216 (display-buffer-window-and-buffer (selected-window))
4217 (window--display-buffer-in-window buffer (selected-window)))
4218 ((let ((frames (or frame
4219 (and (or pop-up-frame
4220 display-buffer-reuse-frames
4221 (not (last-nonminibuffer-frame)))
4223 (last-nonminibuffer-frame))))
4224 (setq window-to-use
4225 (catch 'found
4226 ;; Search frames for a window displaying BUFFER. Return
4227 ;; the selected window only if we are allowed to do so.
4228 (dolist (window (get-buffer-window-list buffer 'nomini frames))
4229 (when (or can-use-selected-window
4230 (not (eq (selected-window) window)))
4231 (throw 'found window))))))
4232 ;; The buffer is already displayed in some window; use that.
4233 (display-buffer-window-and-buffer window-to-use)
4234 (window--raise-window-frame window-to-use))
4235 ((and special-display-function
4236 ;; `special-display-p' returns either t or a list of frame
4237 ;; parameters to pass to `special-display-function'.
4238 (let ((pars (special-display-p buffer-name)))
4239 (when pars
4240 (funcall
4241 special-display-function buffer (and (listp pars) pars))))))
4242 ((and (or pop-up-frame (not frame-to-use))
4243 (window--pop-up-frame buffer)))
4244 ((and pop-up-windows
4245 ;; Try popping up a new window.
4246 (window--pop-up-window buffer frame-to-use)))
4247 ((window--reuse-window
4248 ;; Try reusing least recently used window.
4249 (get-lru-window frame-to-use) buffer not-this-window))
4250 ((window--reuse-window
4251 ;; Try reusing some visible window showing BUFFER.
4252 (get-buffer-window buffer 'visible) buffer not-this-window))
4253 ((window--reuse-window
4254 ;; Try reusing largest visible window.
4255 (get-largest-window 'visible) buffer not-this-window))
4256 ((window--reuse-window
4257 ;; Try reusing some window showing BUFFER on any visible or
4258 ;; iconified frame.
4259 (get-buffer-window buffer 0) buffer not-this-window))
4260 ((window--reuse-window
4261 ;; Try reusing largest window on any visible or iconified frame.
4262 (get-largest-window 0) buffer not-this-window))
4263 ;; As a last resort try popping up a new frame.
4264 ((window--pop-up-frame buffer)))))
4266 (defun pop-to-buffer (buffer-or-name &optional other-window norecord)
4267 "Select buffer BUFFER-OR-NAME in some window, preferably a different one.
4268 BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
4269 nil. If BUFFER-OR-NAME is a string not naming an existent
4270 buffer, create a buffer with that name. If BUFFER-OR-NAME is
4271 nil, choose some other buffer. Return the buffer specified by
4272 BUFFER-OR-NAME.
4274 If optional second arg OTHER-WINDOW is non-nil, insist on finding
4275 another window even if the specified buffer is already visible in
4276 the selected window, and ignore the options `same-window-regexps'
4277 and `same-window-buffer-names'.
4279 Optional argument NORECORD non-nil means do not put the buffer
4280 specified by BUFFER-OR-NAME at the front of the buffer list and
4281 do not make the window displaying it the most recently selected
4282 one.
4284 This uses the function `display-buffer' as a subroutine; see the
4285 documentation of `display-buffer' for additional customization
4286 information."
4287 (let ((buffer
4288 ;; FIXME: This behavior is carried over from the previous C
4289 ;; version of pop-to-buffer, but really we should use just
4290 ;; `get-buffer' here.
4291 (if (null buffer-or-name)
4292 (other-buffer (current-buffer))
4293 (or (get-buffer buffer-or-name)
4294 (let ((buf (get-buffer-create buffer-or-name)))
4295 (set-buffer-major-mode buf)
4296 buf))))
4297 (old-frame (selected-frame))
4298 new-window new-frame)
4299 (set-buffer buffer)
4300 (setq new-window (display-buffer buffer other-window))
4301 ;; Select the window chosen.
4302 (select-window new-window norecord)
4303 (setq new-frame (window-frame new-window))
4304 (unless (eq new-frame old-frame)
4305 ;; `display-buffer' has chosen another frame, make sure it gets
4306 ;; input focus and is risen.
4307 (select-frame-set-input-focus new-frame))
4308 buffer))
4310 (defun read-buffer-to-switch (prompt)
4311 "Read the name of a buffer to switch to and return as a string.
4312 It is intended for `switch-to-buffer' family of commands since they
4313 need to omit the name of current buffer from the list of completions
4314 and default values."
4315 (let ((rbts-completion-table (internal-complete-buffer-except)))
4316 (minibuffer-with-setup-hook
4317 (lambda ()
4318 (setq minibuffer-completion-table rbts-completion-table)
4319 ;; Since rbts-completion-table is built dynamically, we
4320 ;; can't just add it to the default value of
4321 ;; icomplete-with-completion-tables, so we add it
4322 ;; here manually.
4323 (if (and (boundp 'icomplete-with-completion-tables)
4324 (listp icomplete-with-completion-tables))
4325 (set (make-local-variable 'icomplete-with-completion-tables)
4326 (cons rbts-completion-table
4327 icomplete-with-completion-tables))))
4328 (read-buffer prompt (other-buffer (current-buffer))
4329 (confirm-nonexistent-file-or-buffer)))))
4331 (defun switch-to-buffer (buffer-or-name &optional norecord)
4332 "Switch to buffer BUFFER-OR-NAME in the selected window.
4333 If BUFFER-OR-NAME does not identify an existing buffer, then this
4334 function creates a buffer with that name.
4336 If called interactively, prompt for the buffer name using the
4337 minibuffer. The variable `confirm-nonexistent-file-or-buffer'
4338 determines whether to request confirmation before creating a new
4339 buffer.
4341 When called from Lisp, BUFFER-OR-NAME may be a buffer, a string
4342 \(a buffer name), or nil. If BUFFER-OR-NAME is nil, then this
4343 function chooses a buffer using `other-buffer'.
4345 Optional argument NORECORD non-nil means do not put the buffer
4346 specified by BUFFER-OR-NAME at the front of the buffer list and
4347 do not make the window displaying it the most recently selected
4348 one.
4350 WARNING: Do NOT use this function to work on another buffer
4351 temporarily within a Lisp program! Use `with-current-buffer'
4352 instead. That avoids messing with the window-buffer
4353 correspondences."
4354 (interactive
4355 (list (read-buffer-to-switch "Switch to buffer: ")))
4356 (let ((buffer (when buffer-or-name (get-buffer buffer-or-name))))
4357 (cond
4358 ((eq buffer (window-buffer))
4359 (unless norecord
4360 (select-window (selected-window)))
4361 (set-buffer buffer))
4362 ((or (window-minibuffer-p) (eq (window-dedicated-p) t))
4363 ;; Cannot switch to another buffer in a minibuffer or strongly
4364 ;; dedicated window. Call `pop-to-buffer' instead.
4365 (pop-to-buffer buffer nil norecord))
4367 (unless buffer
4368 (if buffer-or-name
4369 ;; Create a buffer named BUFFER-OR-NAME.
4370 (progn
4371 (setq buffer (get-buffer-create buffer-or-name))
4372 (set-buffer-major-mode buffer))
4373 ;; Use other buffer.
4374 (setq buffer (other-buffer (current-buffer)))))
4375 (set-window-buffer nil buffer)
4376 (unless norecord
4377 (select-window (selected-window)))
4378 (set-buffer buffer)))))
4380 (defun switch-to-buffer-other-window (buffer-or-name &optional norecord)
4381 "Switch to buffer BUFFER-OR-NAME in another window.
4382 BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
4383 nil. Return the buffer switched to.
4385 If called interactively, prompt for the buffer name using the
4386 minibuffer. The variable `confirm-nonexistent-file-or-buffer'
4387 determines whether to request confirmation before creating a new
4388 buffer.
4390 If BUFFER-OR-NAME is a string and does not identify an existing
4391 buffer, create a new buffer with that name. If BUFFER-OR-NAME is
4392 nil, switch to the buffer returned by `other-buffer'.
4394 Optional argument NORECORD non-nil means do not put the buffer
4395 specified by BUFFER-OR-NAME at the front of the buffer list and
4396 do not make the window displaying it the most recently selected
4397 one.
4399 This uses the function `display-buffer' as a subroutine; see its
4400 documentation for additional customization information."
4401 (interactive
4402 (list (read-buffer-to-switch "Switch to buffer in other window: ")))
4403 (let ((pop-up-windows (or pop-up-windows t))
4404 same-window-buffer-names same-window-regexps)
4405 (pop-to-buffer buffer-or-name t norecord)))
4407 (defun switch-to-buffer-other-frame (buffer-or-name &optional norecord)
4408 "Switch to buffer BUFFER-OR-NAME in another frame.
4409 BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
4410 nil. Return the buffer switched to.
4412 If called interactively, prompt for the buffer name using the
4413 minibuffer. The variable `confirm-nonexistent-file-or-buffer'
4414 determines whether to request confirmation before creating a new
4415 buffer.
4417 If BUFFER-OR-NAME is a string and does not identify an existing
4418 buffer, create a new buffer with that name. If BUFFER-OR-NAME is
4419 nil, switch to the buffer returned by `other-buffer'.
4421 Optional argument NORECORD non-nil means do not put the buffer
4422 specified by BUFFER-OR-NAME at the front of the buffer list and
4423 do not make the window displaying it the most recently selected
4424 one.
4426 This uses the function `display-buffer' as a subroutine; see its
4427 documentation for additional customization information."
4428 (interactive
4429 (list (read-buffer-to-switch "Switch to buffer in other frame: ")))
4430 (let ((pop-up-frames t)
4431 same-window-buffer-names same-window-regexps)
4432 (pop-to-buffer buffer-or-name t norecord)))
4434 (defun set-window-text-height (window height)
4435 "Set the height in lines of the text display area of WINDOW to HEIGHT.
4436 WINDOW must be a live window. HEIGHT doesn't include the mode
4437 line or header line, if any, or any partial-height lines in the
4438 text display area.
4440 Note that the current implementation of this function cannot
4441 always set the height exactly, but attempts to be conservative,
4442 by allocating more lines than are actually needed in the case
4443 where some error may be present."
4444 (setq window (normalize-live-window window))
4445 (let ((delta (- height (window-text-height window))))
4446 (unless (zerop delta)
4447 ;; Setting window-min-height to a value like 1 can lead to very
4448 ;; bizarre displays because it also allows Emacs to make *other*
4449 ;; windows 1-line tall, which means that there's no more space for
4450 ;; the modeline.
4451 (let ((window-min-height (min 2 height))) ; One text line plus a modeline.
4452 (resize-window window delta)))))
4454 (defun enlarge-window-horizontally (delta)
4455 "Make selected window DELTA wider.
4456 Interactively, if no argument is given, make selected window one
4457 column wider."
4458 (interactive "p")
4459 (enlarge-window delta t))
4461 (defun shrink-window-horizontally (delta)
4462 "Make selected window DELTA narrower.
4463 Interactively, if no argument is given, make selected window one
4464 column narrower."
4465 (interactive "p")
4466 (shrink-window delta t))
4468 (defun count-screen-lines (&optional beg end count-final-newline window)
4469 "Return the number of screen lines in the region.
4470 The number of screen lines may be different from the number of actual lines,
4471 due to line breaking, display table, etc.
4473 Optional arguments BEG and END default to `point-min' and `point-max'
4474 respectively.
4476 If region ends with a newline, ignore it unless optional third argument
4477 COUNT-FINAL-NEWLINE is non-nil.
4479 The optional fourth argument WINDOW specifies the window used for obtaining
4480 parameters such as width, horizontal scrolling, and so on. The default is
4481 to use the selected window's parameters.
4483 Like `vertical-motion', `count-screen-lines' always uses the current buffer,
4484 regardless of which buffer is displayed in WINDOW. This makes possible to use
4485 `count-screen-lines' in any buffer, whether or not it is currently displayed
4486 in some window."
4487 (unless beg
4488 (setq beg (point-min)))
4489 (unless end
4490 (setq end (point-max)))
4491 (if (= beg end)
4493 (save-excursion
4494 (save-restriction
4495 (widen)
4496 (narrow-to-region (min beg end)
4497 (if (and (not count-final-newline)
4498 (= ?\n (char-before (max beg end))))
4499 (1- (max beg end))
4500 (max beg end)))
4501 (goto-char (point-min))
4502 (1+ (vertical-motion (buffer-size) window))))))
4504 (defun window-buffer-height (window)
4505 "Return the height (in screen lines) of the buffer that WINDOW is displaying."
4506 (with-current-buffer (window-buffer window)
4507 (max 1
4508 (count-screen-lines (point-min) (point-max)
4509 ;; If buffer ends with a newline, ignore it when
4510 ;; counting height unless point is after it.
4511 (eobp)
4512 window))))
4514 ;;; Resizing buffers to fit their contents exactly.
4515 (defun fit-window-to-buffer (&optional window max-height min-height ignore)
4516 "Adjust height of WINDOW to display its buffer's contents exactly.
4517 WINDOW can be any live window and defaults to the selected one.
4519 Optional argument MAX-HEIGHT specifies the maximum height of
4520 WINDOW and defaults to the height of WINDOW's frame. Optional
4521 argument MIN-HEIGHT specifies the minimum height of WINDOW and
4522 defaults to `window-min-height'. Both, MAX-HEIGHT and MIN-HEIGHT
4523 are specified in lines and include the mode line and header line,
4524 if any.
4526 Optional argument IGNORE non-nil means ignore restrictions
4527 imposed by `window-min-height' and `window-min-width' on the size
4528 of WINDOW.
4530 Return the number of lines by which WINDOW was enlarged or
4531 shrunk. If an error occurs during resizing, return nil but don't
4532 signal an error.
4534 Note that even if this function makes WINDOW large enough to show
4535 _all_ lines of its buffer you might not see the first lines when
4536 WINDOW was scrolled."
4537 (interactive)
4538 ;; Do all the work in WINDOW and its buffer and restore the selected
4539 ;; window and the current buffer when we're done.
4540 (setq window (normalize-live-window window))
4541 ;; Can't resize a full height or fixed-size window.
4542 (unless (or (window-size-fixed-p window)
4543 (window-full-height-p window))
4544 ;; `with-selected-window' should orderly restore the current buffer.
4545 (with-selected-window window
4546 ;; We are in WINDOW's buffer now.
4547 (let* ( ;; Adjust MIN-HEIGHT.
4548 (min-height
4549 (if ignore
4550 (window-min-size window nil window)
4551 (max (or min-height window-min-height)
4552 window-safe-min-height)))
4553 (max-window-height
4554 (window-total-size (frame-root-window window)))
4555 ;; Adjust MAX-HEIGHT.
4556 (max-height
4557 (if (or ignore (not max-height))
4558 max-window-height
4559 (min max-height max-window-height)))
4560 ;; Make `desired-height' the height necessary to show
4561 ;; all of WINDOW's buffer, constrained by MIN-HEIGHT
4562 ;; and MAX-HEIGHT.
4563 (desired-height
4564 (max
4565 (min
4566 (+ (count-screen-lines)
4567 ;; For non-minibuffers count the mode line, if any.
4568 (if (and (not (window-minibuffer-p window))
4569 mode-line-format)
4572 ;; Count the header line, if any.
4573 (if header-line-format 1 0))
4574 max-height)
4575 min-height))
4576 (desired-delta
4577 (- desired-height (window-total-size window)))
4578 (delta
4579 (if (> desired-delta 0)
4580 (min desired-delta
4581 (window-max-delta window nil window))
4582 (max desired-delta
4583 (- (window-min-delta window nil window))))))
4584 ;; This `condition-case' shouldn't be necessary, but who knows?
4585 (condition-case nil
4586 (if (zerop delta)
4587 ;; Return zero if DELTA became zero in the proces.
4589 ;; Don't try to redisplay with the cursor at the end on its
4590 ;; own line--that would force a scroll and spoil things.
4591 (when (and (eobp) (bolp) (not (bobp)))
4592 ;; It's silly to put `point' at the end of the previous
4593 ;; line and so maybe force horizontal scrolling.
4594 (set-window-point window (line-beginning-position 0)))
4595 ;; Call `resize-window' with IGNORE argument equal WINDOW.
4596 (resize-window window delta nil window)
4597 ;; Check if the last line is surely fully visible. If
4598 ;; not, enlarge the window.
4599 (let ((end (save-excursion
4600 (goto-char (point-max))
4601 (when (and (bolp) (not (bobp)))
4602 ;; Don't include final newline.
4603 (backward-char 1))
4604 (when truncate-lines
4605 ;; If line-wrapping is turned off, test the
4606 ;; beginning of the last line for
4607 ;; visibility instead of the end, as the
4608 ;; end of the line could be invisible by
4609 ;; virtue of extending past the edge of the
4610 ;; window.
4611 (forward-line 0))
4612 (point))))
4613 (set-window-vscroll window 0)
4614 ;; This loop might in some rare pathological cases raise
4615 ;; an error - another reason for the `condition-case'.
4616 (while (and (< desired-height max-height)
4617 (= desired-height (window-total-size))
4618 (not (pos-visible-in-window-p end)))
4619 (resize-window window 1 nil window)
4620 (setq desired-height (1+ desired-height)))))
4621 (error (setq delta nil)))
4622 delta))))
4624 (defun window-safely-shrinkable-p (&optional window)
4625 "Return t if WINDOW can be shrunk without shrinking other windows.
4626 WINDOW defaults to the selected window."
4627 (with-selected-window (or window (selected-window))
4628 (let ((edges (window-edges)))
4629 (or (= (nth 2 edges) (nth 2 (window-edges (previous-window))))
4630 (= (nth 0 edges) (nth 0 (window-edges (next-window))))))))
4632 (defun shrink-window-if-larger-than-buffer (&optional window)
4633 "Shrink height of WINDOW if its buffer doesn't need so many lines.
4634 More precisely, shrink WINDOW vertically to be as small as
4635 possible, while still showing the full contents of its buffer.
4636 WINDOW defaults to the selected window.
4638 Do not shrink WINDOW to less than `window-min-height' lines. Do
4639 nothing if the buffer contains more lines than the present window
4640 height, or if some of the window's contents are scrolled out of
4641 view, or if shrinking this window would also shrink another
4642 window, or if the window is the only window of its frame.
4644 Return non-nil if the window was shrunk, nil otherwise."
4645 (interactive)
4646 (setq window (normalize-live-window window))
4647 ;; Make sure that WINDOW is vertically combined and `point-min' is
4648 ;; visible (for whatever reason that's needed). The remaining issues
4649 ;; should be taken care of by `fit-window-to-buffer'.
4650 (when (and (window-iso-combined-p window)
4651 (pos-visible-in-window-p (point-min) window))
4652 (fit-window-to-buffer window (window-total-size window))))
4654 (defun kill-buffer-and-window ()
4655 "Kill the current buffer and delete the selected window."
4656 (interactive)
4657 (let ((window-to-delete (selected-window))
4658 (buffer-to-kill (current-buffer))
4659 (delete-window-hook (lambda ()
4660 (condition-case nil
4661 (delete-window)
4662 (error nil)))))
4663 (unwind-protect
4664 (progn
4665 (add-hook 'kill-buffer-hook delete-window-hook t t)
4666 (if (kill-buffer (current-buffer))
4667 ;; If `delete-window' failed before, we rerun it to regenerate
4668 ;; the error so it can be seen in the echo area.
4669 (when (eq (selected-window) window-to-delete)
4670 (delete-window))))
4671 ;; If the buffer is not dead for some reason (probably because
4672 ;; of a `quit' signal), remove the hook again.
4673 (condition-case nil
4674 (with-current-buffer buffer-to-kill
4675 (remove-hook 'kill-buffer-hook delete-window-hook t))
4676 (error nil)))))
4678 (defun quit-window (&optional kill window)
4679 "Quit WINDOW and bury its buffer.
4680 With a prefix argument, kill the buffer instead. WINDOW defaults
4681 to the selected window.
4683 If WINDOW is non-nil, dedicated, or a minibuffer window, delete
4684 it and, if it's alone on its frame, its frame too. Otherwise, or
4685 if deleting WINDOW fails in any of the preceding cases, display
4686 another buffer in WINDOW using `switch-to-buffer'.
4688 Optional argument KILL non-nil means kill WINDOW's buffer.
4689 Otherwise, bury WINDOW's buffer, see `bury-buffer'."
4690 (interactive "P")
4691 (let ((buffer (window-buffer window)))
4692 (if (or window
4693 (window-minibuffer-p window)
4694 (window-dedicated-p window))
4695 ;; WINDOW is either non-nil, a minibuffer window, or dedicated;
4696 ;; try to delete it.
4697 (let* ((window (or window (selected-window)))
4698 (frame (window-frame window)))
4699 (if (frame-root-window-p window)
4700 ;; WINDOW is alone on its frame.
4701 (delete-frame frame)
4702 ;; There are other windows on its frame, delete WINDOW.
4703 (delete-window window)))
4704 ;; Otherwise, switch to another buffer in the selected window.
4705 (switch-to-buffer nil))
4707 ;; Deal with the buffer.
4708 (if kill
4709 (kill-buffer buffer)
4710 (bury-buffer buffer))))
4712 (defvar recenter-last-op nil
4713 "Indicates the last recenter operation performed.
4714 Possible values: `top', `middle', `bottom', integer or float numbers.")
4716 (defcustom recenter-positions '(middle top bottom)
4717 "Cycling order for `recenter-top-bottom'.
4718 A list of elements with possible values `top', `middle', `bottom',
4719 integer or float numbers that define the cycling order for
4720 the command `recenter-top-bottom'.
4722 Top and bottom destinations are `scroll-margin' lines the from true
4723 window top and bottom. Middle redraws the frame and centers point
4724 vertically within the window. Integer number moves current line to
4725 the specified absolute window-line. Float number between 0.0 and 1.0
4726 means the percentage of the screen space from the top. The default
4727 cycling order is middle -> top -> bottom."
4728 :type '(repeat (choice
4729 (const :tag "Top" top)
4730 (const :tag "Middle" middle)
4731 (const :tag "Bottom" bottom)
4732 (integer :tag "Line number")
4733 (float :tag "Percentage")))
4734 :version "23.2"
4735 :group 'windows)
4737 (defun recenter-top-bottom (&optional arg)
4738 "Move current buffer line to the specified window line.
4739 With no prefix argument, successive calls place point according
4740 to the cycling order defined by `recenter-positions'.
4742 A prefix argument is handled like `recenter':
4743 With numeric prefix ARG, move current line to window-line ARG.
4744 With plain `C-u', move current line to window center."
4745 (interactive "P")
4746 (cond
4747 (arg (recenter arg)) ; Always respect ARG.
4749 (setq recenter-last-op
4750 (if (eq this-command last-command)
4751 (car (or (cdr (member recenter-last-op recenter-positions))
4752 recenter-positions))
4753 (car recenter-positions)))
4754 (let ((this-scroll-margin
4755 (min (max 0 scroll-margin)
4756 (truncate (/ (window-body-height) 4.0)))))
4757 (cond ((eq recenter-last-op 'middle)
4758 (recenter))
4759 ((eq recenter-last-op 'top)
4760 (recenter this-scroll-margin))
4761 ((eq recenter-last-op 'bottom)
4762 (recenter (- -1 this-scroll-margin)))
4763 ((integerp recenter-last-op)
4764 (recenter recenter-last-op))
4765 ((floatp recenter-last-op)
4766 (recenter (round (* recenter-last-op (window-height))))))))))
4768 (define-key global-map [?\C-l] 'recenter-top-bottom)
4770 (defun move-to-window-line-top-bottom (&optional arg)
4771 "Position point relative to window.
4773 With a prefix argument ARG, acts like `move-to-window-line'.
4775 With no argument, positions point at center of window.
4776 Successive calls position point at positions defined
4777 by `recenter-positions'."
4778 (interactive "P")
4779 (cond
4780 (arg (move-to-window-line arg)) ; Always respect ARG.
4782 (setq recenter-last-op
4783 (if (eq this-command last-command)
4784 (car (or (cdr (member recenter-last-op recenter-positions))
4785 recenter-positions))
4786 (car recenter-positions)))
4787 (let ((this-scroll-margin
4788 (min (max 0 scroll-margin)
4789 (truncate (/ (window-body-height) 4.0)))))
4790 (cond ((eq recenter-last-op 'middle)
4791 (call-interactively 'move-to-window-line))
4792 ((eq recenter-last-op 'top)
4793 (move-to-window-line this-scroll-margin))
4794 ((eq recenter-last-op 'bottom)
4795 (move-to-window-line (- -1 this-scroll-margin)))
4796 ((integerp recenter-last-op)
4797 (move-to-window-line recenter-last-op))
4798 ((floatp recenter-last-op)
4799 (move-to-window-line (round (* recenter-last-op (window-height))))))))))
4801 (define-key global-map [?\M-r] 'move-to-window-line-top-bottom)
4803 ;;; Scrolling commands.
4805 ;;; Scrolling commands which does not signal errors at top/bottom
4806 ;;; of buffer at first key-press (instead moves to top/bottom
4807 ;;; of buffer).
4809 (defcustom scroll-error-top-bottom nil
4810 "Move point to top/bottom of buffer before signalling a scrolling error.
4811 A value of nil means just signal an error if no more scrolling possible.
4812 A value of t means point moves to the beginning or the end of the buffer
4813 \(depending on scrolling direction) when no more scrolling possible.
4814 When point is already on that position, then signal an error."
4815 :type 'boolean
4816 :group 'scrolling
4817 :version "24.1")
4819 (defun scroll-up-command (&optional arg)
4820 "Scroll text of selected window upward ARG lines; or near full screen if no ARG.
4821 If `scroll-error-top-bottom' is non-nil and `scroll-up' cannot
4822 scroll window further, move cursor to the bottom line.
4823 When point is already on that position, then signal an error.
4824 A near full screen is `next-screen-context-lines' less than a full screen.
4825 Negative ARG means scroll downward.
4826 If ARG is the atom `-', scroll downward by nearly full screen."
4827 (interactive "^P")
4828 (cond
4829 ((null scroll-error-top-bottom)
4830 (scroll-up arg))
4831 ((eq arg '-)
4832 (scroll-down-command nil))
4833 ((< (prefix-numeric-value arg) 0)
4834 (scroll-down-command (- (prefix-numeric-value arg))))
4835 ((eobp)
4836 (scroll-up arg)) ; signal error
4838 (condition-case nil
4839 (scroll-up arg)
4840 (end-of-buffer
4841 (if arg
4842 ;; When scrolling by ARG lines can't be done,
4843 ;; move by ARG lines instead.
4844 (forward-line arg)
4845 ;; When ARG is nil for full-screen scrolling,
4846 ;; move to the bottom of the buffer.
4847 (goto-char (point-max))))))))
4849 (put 'scroll-up-command 'scroll-command t)
4851 (defun scroll-down-command (&optional arg)
4852 "Scroll text of selected window down ARG lines; or near full screen if no ARG.
4853 If `scroll-error-top-bottom' is non-nil and `scroll-down' cannot
4854 scroll window further, move cursor to the top line.
4855 When point is already on that position, then signal an error.
4856 A near full screen is `next-screen-context-lines' less than a full screen.
4857 Negative ARG means scroll upward.
4858 If ARG is the atom `-', scroll upward by nearly full screen."
4859 (interactive "^P")
4860 (cond
4861 ((null scroll-error-top-bottom)
4862 (scroll-down arg))
4863 ((eq arg '-)
4864 (scroll-up-command nil))
4865 ((< (prefix-numeric-value arg) 0)
4866 (scroll-up-command (- (prefix-numeric-value arg))))
4867 ((bobp)
4868 (scroll-down arg)) ; signal error
4870 (condition-case nil
4871 (scroll-down arg)
4872 (beginning-of-buffer
4873 (if arg
4874 ;; When scrolling by ARG lines can't be done,
4875 ;; move by ARG lines instead.
4876 (forward-line (- arg))
4877 ;; When ARG is nil for full-screen scrolling,
4878 ;; move to the top of the buffer.
4879 (goto-char (point-min))))))))
4881 (put 'scroll-down-command 'scroll-command t)
4883 ;;; Scrolling commands which scroll a line instead of full screen.
4885 (defun scroll-up-line (&optional arg)
4886 "Scroll text of selected window upward ARG lines; or one line if no ARG.
4887 If ARG is omitted or nil, scroll upward by one line.
4888 This is different from `scroll-up-command' that scrolls a full screen."
4889 (interactive "p")
4890 (scroll-up (or arg 1)))
4892 (put 'scroll-up-line 'scroll-command t)
4894 (defun scroll-down-line (&optional arg)
4895 "Scroll text of selected window down ARG lines; or one line if no ARG.
4896 If ARG is omitted or nil, scroll down by one line.
4897 This is different from `scroll-down-command' that scrolls a full screen."
4898 (interactive "p")
4899 (scroll-down (or arg 1)))
4901 (put 'scroll-down-line 'scroll-command t)
4904 (defun scroll-other-window-down (lines)
4905 "Scroll the \"other window\" down.
4906 For more details, see the documentation for `scroll-other-window'."
4907 (interactive "P")
4908 (scroll-other-window
4909 ;; Just invert the argument's meaning.
4910 ;; We can do that without knowing which window it will be.
4911 (if (eq lines '-) nil
4912 (if (null lines) '-
4913 (- (prefix-numeric-value lines))))))
4915 (defun beginning-of-buffer-other-window (arg)
4916 "Move point to the beginning of the buffer in the other window.
4917 Leave mark at previous position.
4918 With arg N, put point N/10 of the way from the true beginning."
4919 (interactive "P")
4920 (let ((orig-window (selected-window))
4921 (window (other-window-for-scrolling)))
4922 ;; We use unwind-protect rather than save-window-excursion
4923 ;; because the latter would preserve the things we want to change.
4924 (unwind-protect
4925 (progn
4926 (select-window window)
4927 ;; Set point and mark in that window's buffer.
4928 (with-no-warnings
4929 (beginning-of-buffer arg))
4930 ;; Set point accordingly.
4931 (recenter '(t)))
4932 (select-window orig-window))))
4934 (defun end-of-buffer-other-window (arg)
4935 "Move point to the end of the buffer in the other window.
4936 Leave mark at previous position.
4937 With arg N, put point N/10 of the way from the true end."
4938 (interactive "P")
4939 ;; See beginning-of-buffer-other-window for comments.
4940 (let ((orig-window (selected-window))
4941 (window (other-window-for-scrolling)))
4942 (unwind-protect
4943 (progn
4944 (select-window window)
4945 (with-no-warnings
4946 (end-of-buffer arg))
4947 (recenter '(t)))
4948 (select-window orig-window))))
4950 (defvar mouse-autoselect-window-timer nil
4951 "Timer used by delayed window autoselection.")
4953 (defvar mouse-autoselect-window-position nil
4954 "Last mouse position recorded by delayed window autoselection.")
4956 (defvar mouse-autoselect-window-window nil
4957 "Last window recorded by delayed window autoselection.")
4959 (defvar mouse-autoselect-window-state nil
4960 "When non-nil, special state of delayed window autoselection.
4961 Possible values are `suspend' \(suspend autoselection after a menu or
4962 scrollbar interaction\) and `select' \(the next invocation of
4963 'handle-select-window' shall select the window immediately\).")
4965 (defun mouse-autoselect-window-cancel (&optional force)
4966 "Cancel delayed window autoselection.
4967 Optional argument FORCE means cancel unconditionally."
4968 (unless (and (not force)
4969 ;; Don't cancel for select-window or select-frame events
4970 ;; or when the user drags a scroll bar.
4971 (or (memq this-command
4972 '(handle-select-window handle-switch-frame))
4973 (and (eq this-command 'scroll-bar-toolkit-scroll)
4974 (memq (nth 4 (event-end last-input-event))
4975 '(handle end-scroll)))))
4976 (setq mouse-autoselect-window-state nil)
4977 (when (timerp mouse-autoselect-window-timer)
4978 (cancel-timer mouse-autoselect-window-timer))
4979 (remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel)))
4981 (defun mouse-autoselect-window-start (mouse-position &optional window suspend)
4982 "Start delayed window autoselection.
4983 MOUSE-POSITION is the last position where the mouse was seen as returned
4984 by `mouse-position'. Optional argument WINDOW non-nil denotes the
4985 window where the mouse was seen. Optional argument SUSPEND non-nil
4986 means suspend autoselection."
4987 ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND.
4988 (setq mouse-autoselect-window-position mouse-position)
4989 (when window (setq mouse-autoselect-window-window window))
4990 (setq mouse-autoselect-window-state (when suspend 'suspend))
4991 ;; Install timer which runs `mouse-autoselect-window-select' after
4992 ;; `mouse-autoselect-window' seconds.
4993 (setq mouse-autoselect-window-timer
4994 (run-at-time
4995 (abs mouse-autoselect-window) nil 'mouse-autoselect-window-select)))
4997 (defun mouse-autoselect-window-select ()
4998 "Select window with delayed window autoselection.
4999 If the mouse position has stabilized in a non-selected window, select
5000 that window. The minibuffer window is selected only if the minibuffer is
5001 active. This function is run by `mouse-autoselect-window-timer'."
5002 (condition-case nil
5003 (let* ((mouse-position (mouse-position))
5004 (window
5005 (condition-case nil
5006 (window-at (cadr mouse-position) (cddr mouse-position)
5007 (car mouse-position))
5008 (error nil))))
5009 (cond
5010 ((or (menu-or-popup-active-p)
5011 (and window
5012 (not (coordinates-in-window-p (cdr mouse-position) window))))
5013 ;; A menu / popup dialog is active or the mouse is on the scroll-bar
5014 ;; of WINDOW, temporarily suspend delayed autoselection.
5015 (mouse-autoselect-window-start mouse-position nil t))
5016 ((eq mouse-autoselect-window-state 'suspend)
5017 ;; Delayed autoselection was temporarily suspended, reenable it.
5018 (mouse-autoselect-window-start mouse-position))
5019 ((and window (not (eq window (selected-window)))
5020 (or (not (numberp mouse-autoselect-window))
5021 (and (> mouse-autoselect-window 0)
5022 ;; If `mouse-autoselect-window' is positive, select
5023 ;; window if the window is the same as before.
5024 (eq window mouse-autoselect-window-window))
5025 ;; Otherwise select window if the mouse is at the same
5026 ;; position as before. Observe that the first test after
5027 ;; starting autoselection usually fails since the value of
5028 ;; `mouse-autoselect-window-position' recorded there is the
5029 ;; position where the mouse has entered the new window and
5030 ;; not necessarily where the mouse has stopped moving.
5031 (equal mouse-position mouse-autoselect-window-position))
5032 ;; The minibuffer is a candidate window if it's active.
5033 (or (not (window-minibuffer-p window))
5034 (eq window (active-minibuffer-window))))
5035 ;; Mouse position has stabilized in non-selected window: Cancel
5036 ;; delayed autoselection and try to select that window.
5037 (mouse-autoselect-window-cancel t)
5038 ;; Select window where mouse appears unless the selected window is the
5039 ;; minibuffer. Use `unread-command-events' in order to execute pre-
5040 ;; and post-command hooks and trigger idle timers. To avoid delaying
5041 ;; autoselection again, set `mouse-autoselect-window-state'."
5042 (unless (window-minibuffer-p (selected-window))
5043 (setq mouse-autoselect-window-state 'select)
5044 (setq unread-command-events
5045 (cons (list 'select-window (list window))
5046 unread-command-events))))
5047 ((or (and window (eq window (selected-window)))
5048 (not (numberp mouse-autoselect-window))
5049 (equal mouse-position mouse-autoselect-window-position))
5050 ;; Mouse position has either stabilized in the selected window or at
5051 ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
5052 (mouse-autoselect-window-cancel t))
5054 ;; Mouse position has not stabilized yet, resume delayed
5055 ;; autoselection.
5056 (mouse-autoselect-window-start mouse-position window))))
5057 (error nil)))
5059 (defun handle-select-window (event)
5060 "Handle select-window events."
5061 (interactive "e")
5062 (let ((window (posn-window (event-start event))))
5063 (unless (or (not (window-live-p window))
5064 ;; Don't switch if we're currently in the minibuffer.
5065 ;; This tries to work around problems where the
5066 ;; minibuffer gets unselected unexpectedly, and where
5067 ;; you then have to move your mouse all the way down to
5068 ;; the minibuffer to select it.
5069 (window-minibuffer-p (selected-window))
5070 ;; Don't switch to minibuffer window unless it's active.
5071 (and (window-minibuffer-p window)
5072 (not (minibuffer-window-active-p window)))
5073 ;; Don't switch when autoselection shall be delayed.
5074 (and (numberp mouse-autoselect-window)
5075 (not (zerop mouse-autoselect-window))
5076 (not (eq mouse-autoselect-window-state 'select))
5077 (progn
5078 ;; Cancel any delayed autoselection.
5079 (mouse-autoselect-window-cancel t)
5080 ;; Start delayed autoselection from current mouse
5081 ;; position and window.
5082 (mouse-autoselect-window-start (mouse-position) window)
5083 ;; Executing a command cancels delayed autoselection.
5084 (add-hook
5085 'pre-command-hook 'mouse-autoselect-window-cancel))))
5086 (when mouse-autoselect-window
5087 ;; Reset state of delayed autoselection.
5088 (setq mouse-autoselect-window-state nil)
5089 ;; Run `mouse-leave-buffer-hook' when autoselecting window.
5090 (run-hooks 'mouse-leave-buffer-hook))
5091 (select-window window))))
5093 (defun truncated-partial-width-window-p (&optional window)
5094 "Return non-nil if lines in WINDOW are specifically truncated due to its width.
5095 WINDOW defaults to the selected window.
5096 Return nil if WINDOW is not a partial-width window
5097 (regardless of the value of `truncate-lines').
5098 Otherwise, consult the value of `truncate-partial-width-windows'
5099 for the buffer shown in WINDOW."
5100 (unless window
5101 (setq window (selected-window)))
5102 (unless (window-full-width-p window)
5103 (let ((t-p-w-w (buffer-local-value 'truncate-partial-width-windows
5104 (window-buffer window))))
5105 (if (integerp t-p-w-w)
5106 (< (window-width window) t-p-w-w)
5107 t-p-w-w))))
5109 (define-key ctl-x-map "0" 'delete-window)
5110 (define-key ctl-x-map "1" 'delete-other-windows)
5111 (define-key ctl-x-map "2" 'split-window-vertically)
5112 (define-key ctl-x-map "3" 'split-window-horizontally)
5113 (define-key ctl-x-map "9" 'maximize-window)
5114 (define-key ctl-x-map "o" 'other-window)
5115 (define-key ctl-x-map "^" 'enlarge-window)
5116 (define-key ctl-x-map "}" 'enlarge-window-horizontally)
5117 (define-key ctl-x-map "{" 'shrink-window-horizontally)
5118 (define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer)
5119 (define-key ctl-x-map "+" 'balance-windows)
5120 (define-key ctl-x-4-map "0" 'kill-buffer-and-window)
5122 ;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9
5123 ;;; window.el ends here