Fix sizing in display-buffer-split-window-1. Use quit-restore-window in compile.el.
[emacs.git] / lisp / window.el
blob684f375179e4f45602a6da9dc29db45dfb4bc4dc
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 ;;; Code:
28 (eval-when-compile (require 'cl))
30 (defmacro save-selected-window (&rest body)
31 "Execute BODY, then select the previously selected window.
32 The value returned is the value of the last form in BODY.
34 This macro saves and restores the selected window, as well as the
35 selected window in each frame. If the previously selected window
36 is no longer live, then whatever window is selected at the end of
37 BODY remains selected. If the previously selected window of some
38 frame is no longer live at the end of BODY, that frame's selected
39 window is left alone.
41 This macro saves and restores the current buffer, since otherwise
42 its normal operation could make a different buffer current. The
43 order of recently selected windows and the buffer list ordering
44 are not altered by this macro (unless they are altered in BODY)."
45 (declare (indent 0) (debug t))
46 `(let ((save-selected-window-window (selected-window))
47 ;; It is necessary to save all of these, because calling
48 ;; select-window changes frame-selected-window for whatever
49 ;; frame that window is in.
50 (save-selected-window-alist
51 (mapcar (lambda (frame) (cons frame (frame-selected-window frame)))
52 (frame-list))))
53 (save-current-buffer
54 (unwind-protect
55 (progn ,@body)
56 (dolist (elt save-selected-window-alist)
57 (and (frame-live-p (car elt))
58 (window-live-p (cdr elt))
59 (set-frame-selected-window (car elt) (cdr elt) 'norecord)))
60 (when (window-live-p save-selected-window-window)
61 (select-window save-selected-window-window 'norecord))))))
63 ;; The following two functions are like `window-next' and `window-prev'
64 ;; but the WINDOW argument is _not_ optional (so they don't substitute
65 ;; the selected window for nil), and they return nil when WINDOW doesn't
66 ;; have a parent (like a frame's root window or a minibuffer window).
67 (defsubst window-right (window)
68 "Return WINDOW's right sibling.
69 Return nil if WINDOW is the root window of its frame. WINDOW can
70 be any window."
71 (and window (window-parent window) (window-next window)))
73 (defsubst window-left (window)
74 "Return WINDOW's left sibling.
75 Return nil if WINDOW is the root window of its frame. WINDOW can
76 be any window."
77 (and window (window-parent window) (window-prev window)))
79 (defsubst window-child (window)
80 "Return WINDOW's first child window."
81 (or (window-vchild window) (window-hchild window)))
83 (defsubst window-internal-p (object)
84 "Return t if OBJECT is an internal window and nil otherwise.
85 An internal window is a window that has either a vertical or a
86 horizontal child window."
87 (and (windowp object) (window-child object) t))
89 (defsubst window-any-p (object)
90 "Return t if OBJECT denotes a live or internal window."
91 (and (windowp object)
92 (or (window-buffer object) (window-child object))
93 t))
95 (defsubst normalize-live-buffer (buffer-or-name)
96 "Return buffer specified by BUFFER-OR-NAME.
97 BUFFER-OR-NAME must be either a buffer or a string naming a live
98 buffer and defaults to the current buffer."
99 (cond
100 ((not buffer-or-name)
101 (current-buffer))
102 ((bufferp buffer-or-name)
103 (if (buffer-live-p buffer-or-name)
104 buffer-or-name
105 (error "Buffer %s is not a live buffer" buffer-or-name)))
106 ((get-buffer buffer-or-name))
108 (error "No such buffer %s" buffer-or-name))))
110 ;; This should probably go to frame.el.
111 (defsubst normalize-live-frame (frame)
112 "Return normalized FRAME argument for live frames."
113 (if frame
114 (if (frame-live-p frame)
115 frame
116 (error "%s is not a live frame" frame))
117 (selected-frame)))
119 (defsubst normalize-any-window (window)
120 "Return normalized WINDOW argument for any window.
121 WINDOW defaults to the selected window."
122 (if window
123 (if (window-any-p window)
124 window
125 (error "%s is not a window" window))
126 (selected-window)))
128 (defsubst normalize-live-window (window)
129 "Return normalized WINDOW argument for live windows.
130 WINDOW defaults to the selected window."
131 (if window
132 (if (and (windowp window) (window-buffer window))
133 window
134 (error "%s is not a live window" window))
135 (selected-window)))
137 (defvar ignore-window-parameters nil
138 "If non-nil standard functions ignore window parameters.
139 The functions currently affected by this are `split-window',
140 `delete-window', `delete-other-windows' and `other-window'.
142 When this variable equals `pre', parameters are not consulted
143 before but are updated after performing the requested operation.
144 When this variable equals `post', parameters are consulted before
145 but are not updated after performing the requested operation.
147 The value t means parameters are not consulted before and not
148 updated after performing the requested operation. Currently any
149 other non-nil value is handled like t.
151 An application may bind this to a non-nil value around calls to
152 these functions. If it does so and the value is not `pre', the
153 application is fully responsible for correctly setting the
154 parameters of all windows participating in the function called.")
156 (defconst window-safe-min-height 1
157 "The absolut minimum number of lines of a window.
158 Anything less might crash Emacs.")
160 (defcustom window-min-height 4
161 "The minimum number of lines of any window.
162 The value has to accomodate a mode- or header-line if present. A
163 value less than `window-safe-min-height' is ignored. The value
164 of this variable is honored when windows are resized or split.
166 Applications should never rebind this variable. To resize a
167 window to a height less than the one specified here, an
168 application should instead call `resize-window' with a non-nil
169 IGNORE argument. In order to have `split-window' make a window
170 shorter, explictly specify the SIZE argument of that function."
171 :type 'integer
172 :version "24.1"
173 :group 'windows)
175 (defconst window-safe-min-width 2
176 "The absolut minimum number of columns of a window.
177 Anything less might crash Emacs.")
179 (defcustom window-min-width 10
180 "The minimum number of columns of any window.
181 The value has to accomodate margins, fringes, or scrollbars if
182 present. A value less than `window-safe-min-width' is ignored.
183 The value of this variable is honored when windows are resized or
184 split.
186 Applications should never rebind this variable. To resize a
187 window to a width less than the one specified here, an
188 application should instead call `resize-window' with a non-nil
189 IGNORE argument. In order to have `split-window' make a window
190 narrower, explictly specify the SIZE argument of that function."
191 :type 'integer
192 :version "24.1"
193 :group 'windows)
195 (defun window-iso-combination-p (&optional window horizontal)
196 "If WINDOW is a vertical combination return WINDOW's first child.
197 WINDOW can be any window and defaults to the selected one.
198 Optional argument HORIZONTAL non-nil means return WINDOW's first
199 child if WINDOW is a horizontal combination."
200 (setq window (normalize-any-window window))
201 (if horizontal
202 (window-hchild window)
203 (window-vchild window)))
205 (defsubst window-iso-combined-p (&optional window horizontal)
206 "Return non-nil if and only if WINDOW is vertically combined.
207 WINDOW can be any window and defaults to the selected one.
208 Optional argument HORIZONTAL non-nil means return non-nil if and
209 only if WINDOW is horizontally combined."
210 (setq window (normalize-any-window window))
211 (let ((parent (window-parent window)))
212 (and parent (window-iso-combination-p parent horizontal))))
214 (defun window-iso-combinations (&optional window horizontal)
215 "Return largest number of vertically arranged subwindows of WINDOW.
216 WINDOW can be any window and defaults to the selected one.
217 Optional argument HORIZONTAL non-nil means to return the largest
218 number of horizontally arranged subwindows of WINDOW."
219 (setq window (normalize-any-window window))
220 (cond
221 ((window-live-p window)
222 ;; If WINDOW is live, return 1.
224 ((window-iso-combination-p window horizontal)
225 ;; If WINDOW is iso-combined, return the sum of the values for all
226 ;; subwindows of WINDOW.
227 (let ((child (window-child window))
228 (count 0))
229 (while child
230 (setq count
231 (+ (window-iso-combinations child horizontal)
232 count))
233 (setq child (window-right child)))
234 count))
236 ;; If WINDOW is not iso-combined, return the maximum value of any
237 ;; subwindow of WINDOW.
238 (let ((child (window-child window))
239 (count 1))
240 (while child
241 (setq count
242 (max (window-iso-combinations child horizontal)
243 count))
244 (setq child (window-right child)))
245 count))))
247 (defvar window-size-fixed nil
248 "Non-nil in a buffer means windows displaying the buffer are fixed-size.
249 If the value is `height', then only the window's height is fixed.
250 If the value is `width', then only the window's width is fixed.
251 Any other non-nil value fixes both the width and the height.
252 Emacs won't change the size of any window displaying that buffer,
253 unless you explicitly change the size, or Emacs has no other
254 choice \(like when deleting a neighboring window).")
255 (make-variable-buffer-local 'window-size-fixed)
257 (defsubst window-size-ignore (window ignore)
258 "Return non-nil if IGNORE says to ignore size restrictions for WINDOW."
259 (if (window-any-p ignore) (eq window ignore) ignore))
261 (defun window-min-size (&optional window horizontal ignore)
262 "Return the minimum number of lines of WINDOW.
263 WINDOW can be an arbitrary window and defaults to the selected
264 one. Optional argument HORIZONTAL non-nil means return the
265 minimum number of columns of WINDOW.
267 Optional argument IGNORE non-nil means ignore any restrictions
268 imposed by fixed size windows, `window-min-height' or
269 `window-min-width' settings. IGNORE equal `safe' means live
270 windows may get as small as `window-safe-min-height' lines and
271 `window-safe-min-width' columns. IGNORE a window means ignore
272 restrictions for that window only."
273 (window-min-size-1
274 (normalize-any-window window) horizontal ignore))
276 (defun window-min-size-1 (window horizontal ignore)
277 "Internal function of `window-min-size'."
278 (let ((sub (window-child window)))
279 (if sub
280 (let ((value 0))
281 ;; WINDOW is an internal window.
282 (if (window-iso-combined-p sub horizontal)
283 ;; The minimum size of an iso-combination is the sum of
284 ;; the minimum sizes of its subwindows.
285 (while sub
286 (setq value (+ value
287 (window-min-size-1 sub horizontal ignore)))
288 (setq sub (window-right sub)))
289 ;; The minimum size of an ortho-combination is the maximum of
290 ;; the minimum sizes of its subwindows.
291 (while sub
292 (setq value (max value
293 (window-min-size-1 sub horizontal ignore)))
294 (setq sub (window-right sub))))
295 value)
296 (with-current-buffer (window-buffer window)
297 (cond
298 ((and (not (window-size-ignore window ignore))
299 (window-size-fixed-p window horizontal))
300 ;; The minimum size of a fixed size window is its size.
301 (window-total-size window horizontal))
302 ((or (eq ignore 'safe) (eq ignore window))
303 ;; If IGNORE equals `safe' or WINDOW return the safe values.
304 (if horizontal window-safe-min-width window-safe-min-height))
305 (horizontal
306 ;; For the minimum width of a window take fringes and
307 ;; scroll-bars into account. This is questionable and should
308 ;; be removed as soon as we are able to split (and resize)
309 ;; windows such that the new (or resized) windows can get a
310 ;; size less than the user-specified `window-min-height' and
311 ;; `window-min-width'.
312 (let ((frame (window-frame window))
313 (fringes (window-fringes window))
314 (scroll-bars (window-scroll-bars window)))
315 (max
316 (+ window-safe-min-width
317 (ceiling (car fringes) (frame-char-width frame))
318 (ceiling (cadr fringes) (frame-char-width frame))
319 (cond
320 ((memq (nth 2 scroll-bars) '(left right))
321 (nth 1 scroll-bars))
322 ((memq (frame-parameter frame 'vertical-scroll-bars)
323 '(left right))
324 (ceiling (or (frame-parameter frame 'scroll-bar-width) 14)
325 (frame-char-width)))
326 (t 0)))
327 (if (and (not (window-size-ignore window ignore))
328 (numberp window-min-width))
329 window-min-width
330 0))))
332 ;; For the minimum height of a window take any mode- or
333 ;; header-line into account.
334 (max (+ window-safe-min-height
335 (if header-line-format 1 0)
336 (if mode-line-format 1 0))
337 (if (and (not (window-size-ignore window ignore))
338 (numberp window-min-height))
339 window-min-height
340 0))))))))
342 (defun window-sizable (window delta &optional horizontal ignore)
343 "Return DELTA if DELTA lines can be added to WINDOW.
344 Optional argument HORIZONTAL non-nil means return DELTA if DELTA
345 columns can be added to WINDOW. A return value of zero means
346 that no lines (or columns) can be added to WINDOW.
348 This function looks only at WINDOW and its subwindows. The
349 function `window-resizable' looks at other windows as well.
351 DELTA positive means WINDOW shall be enlarged by DELTA lines or
352 columns. If WINDOW cannot be enlarged by DELTA lines or columns
353 return the maximum value in the range 0..DELTA by which WINDOW
354 can be enlarged.
356 DELTA negative means WINDOW shall be shrunk by -DELTA lines or
357 columns. If WINDOW cannot be shrunk by -DELTA lines or columns,
358 return the minimum value in the range DELTA..0 by which WINDOW
359 can be shrunk.
361 Optional argument IGNORE non-nil means ignore any restrictions
362 imposed by fixed size windows, `window-min-height' or
363 `window-min-width' settings. IGNORE equal `safe' means live
364 windows may get as small as `window-safe-min-height' lines and
365 `window-safe-min-width' columns. IGNORE any window means ignore
366 restrictions for that window only."
367 (setq window (normalize-any-window window))
368 (cond
369 ((< delta 0)
370 (max (- (window-min-size window horizontal ignore)
371 (window-total-size window horizontal))
372 delta))
373 ((window-size-ignore window ignore)
374 delta)
375 ((> delta 0)
376 (if (window-size-fixed-p window horizontal)
378 delta))
379 (t 0)))
381 (defsubst window-sizable-p (window delta &optional horizontal ignore)
382 "Return t if WINDOW can have DELTA lines.
383 For the meaning of the arguments of this function see the
384 doc-string of `window-sizable'."
385 (setq window (normalize-any-window window))
386 (if (> delta 0)
387 (>= (window-sizable window delta horizontal ignore) delta)
388 (<= (window-sizable window delta horizontal ignore) delta)))
390 (defun window-size-fixed-p (&optional window horizontal)
391 "Return non-nil if WINDOW's height is fixed.
392 WINDOW can be an arbitrary window and defaults to the selected
393 window. Optional argument HORIZONTAL non-nil means return
394 non-nil if WINDOW's width is fixed.
396 If this function returns nil, this does not necessarily mean that
397 WINDOW can be resized in the desired direction. The functions
398 `window-resizable' and `window-resizable-p' will tell that."
399 (window-size-fixed-1
400 (normalize-any-window window) horizontal))
402 (defun window-size-fixed-1 (window horizontal)
403 "Internal function for `window-size-fixed-p'."
404 (let ((sub (window-child window)))
405 (catch 'fixed
406 (if sub
407 ;; WINDOW is an internal window.
408 (if (window-iso-combined-p sub horizontal)
409 ;; An iso-combination is fixed size if all its subwindows
410 ;; are fixed-size.
411 (progn
412 (while sub
413 (unless (window-size-fixed-1 sub horizontal)
414 ;; We found a non-fixed-size subwindow, so WINDOW's
415 ;; size is not fixed.
416 (throw 'fixed nil))
417 (setq sub (window-right sub)))
418 ;; All subwindows are fixed-size, so WINDOW's size is
419 ;; fixed.
420 (throw 'fixed t))
421 ;; An ortho-combination is fixed-size if at least one of its
422 ;; subwindows is fixed-size.
423 (while sub
424 (when (window-size-fixed-1 sub horizontal)
425 ;; We found a fixed-size subwindow, so WINDOW's size is
426 ;; fixed.
427 (throw 'fixed t))
428 (setq sub (window-right sub))))
429 ;; WINDOW is a live window.
430 (with-current-buffer (window-buffer window)
431 (if horizontal
432 (memq window-size-fixed '(width t))
433 (memq window-size-fixed '(height t))))))))
435 (defun window-min-delta (&optional window horizontal ignore side noup nodown)
436 "Return number of lines by which WINDOW can be shrunk.
437 WINDOW can be an arbitrary window and defaults to the selected
438 window. Return zero if WINDOW cannot be shrunk.
440 Optional argument HORIZONTAL non-nil means return number of
441 columns by which WINDOW can be shrunk.
443 Optional argument IGNORE non-nil means ignore any restrictions
444 imposed by fixed size windows, `window-min-height' or
445 `window-min-width' settings. IGNORE a window means ignore
446 restrictions for that window only. IGNORE equal `safe' means
447 live windows may get as small as `window-safe-min-height' lines
448 and `window-safe-min-width' columns.
450 Optional argument SIDE `left' means assume only windows to the
451 left of or above WINDOW can be enlarged. Optional argument SIDE
452 `right' means assumes only windows to the right of or below
453 WINDOW can be enlarged.
455 Optional argument NOUP non-nil means don't go up in the window
456 tree but try to enlarge windows within WINDOW's combination only.
458 Optional argument NODOWN non-nil means don't check whether WINDOW
459 and its subwindows can be shrunk."
460 (setq window (normalize-any-window window))
461 (let ((size (window-total-size window horizontal))
462 (minimum (window-min-size window horizontal ignore)))
463 (if (and (not nodown) (= size minimum))
464 ;; Nothing to recover.
466 (window-min-delta-1
467 ;; Think positive.
468 window (- size minimum) horizontal ignore side noup))))
470 (defun window-min-delta-1 (window delta &optional horizontal ignore side noup)
471 "Internal function for `window-min-delta'."
472 (if (not (window-parent window))
473 0 ; delta
474 ;;; (min delta
475 ;;; (- (window-total-size window horizontal)
476 ;;; (window-min-size window horizontal ignore)))
477 (let* ((parent (window-parent window))
478 (sub (window-child parent)))
479 (catch 'done
480 (if (window-iso-combined-p sub horizontal)
481 ;; In an iso-combination throw DELTA if we find at least one
482 ;; subwindow and that subwindow is either non-fixed-size or
483 ;; we can ignore fixed-sizeness.
484 (let ((skip (eq side 'right)))
485 (while sub
486 (cond
487 ((eq sub window)
488 (setq skip (eq side 'left)))
489 (skip)
490 ((and (not (window-size-ignore window ignore))
491 (window-size-fixed-p sub horizontal)))
493 ;; We found a non-fixed-size subwindow.
494 (throw 'done delta)))
495 (setq sub (window-right sub))))
496 ;; In an ortho-combination set DELTA to the minimum value by
497 ;; which other subwindows can shrink.
498 (while sub
499 (unless (eq sub window)
500 (setq delta
501 (min delta
502 (- (window-total-size sub horizontal)
503 (window-min-size sub horizontal ignore)))))
504 (setq sub (window-right sub))))
505 (if noup
506 delta
507 (window-min-delta-1 parent delta horizontal ignore side))))))
509 (defun window-max-delta (&optional window horizontal ignore side noup nodown)
510 "Return maximum number of lines WINDOW by which WINDOW can be enlarged.
511 WINDOW can be an arbitrary window and defaults to the selected
512 window. The return value is zero if WINDOW cannot be enlarged.
514 Optional argument HORIZONTAL non-nil means return maximum number
515 of columns by which WINDOW can be enlarged.
517 Optional argument IGNORE non-nil means ignore any restrictions
518 imposed by fixed size windows, `window-min-height' or
519 `window-min-width' settings. IGNORE a window means ignore
520 restrictions for that window only. IGNORE equal `safe' means
521 live windows may get as small as `window-safe-min-height' lines
522 and `window-safe-min-width' columns.
524 Optional argument SIDE `left' means assume only windows to the
525 left of or below WINDOW can be shrunk. Optional argument SIDE
526 `right' means assumes only windows to the right of or above
527 WINDOW can be shrunk.
529 Optional argument NOUP non-nil means don't go up in the window
530 tree but try to obtain the entire space from windows within
531 WINDOW's combination.
533 Optional argument NODOWN non-nil means do not check whether
534 WINDOW and its subwindows can be enlarged."
535 (setq window (normalize-any-window window))
536 (if (and (not (window-size-ignore window ignore))
537 (not nodown) (window-size-fixed-p window horizontal))
539 (window-max-delta-1 window 0 horizontal ignore side noup)))
541 (defun window-max-delta-1 (window delta &optional horizontal ignore side noup)
542 "Internal function of `window-max-delta'."
543 (if (not (window-parent window))
544 ;; Can't go up. Return DELTA.
545 delta
546 (let* ((parent (window-parent window))
547 (sub (window-child parent)))
548 (catch 'fixed
549 (if (window-iso-combined-p sub horizontal)
550 ;; For an iso-combination calculate how much we can get from
551 ;; other subwindows.
552 (let ((skip (eq side 'right)))
553 (while sub
554 (cond
555 ((eq sub window)
556 (setq skip (eq side 'left)))
557 (skip)
559 (setq delta
560 (+ delta
561 (- (window-total-size sub horizontal)
562 (window-min-size sub horizontal ignore))))))
563 (setq sub (window-right sub))))
564 ;; For an ortho-combination throw DELTA when at least one
565 ;; subwindow is fixed-size.
566 (while sub
567 (when (and (not (eq sub window))
568 (not (window-size-ignore sub ignore))
569 (window-size-fixed-p sub horizontal))
570 (throw 'fixed delta))
571 (setq sub (window-right sub))))
572 (if noup
573 delta
574 ;; Try to go up.
575 (window-max-delta-1 parent delta horizontal ignore side))))))
577 ;; Make NOUP also inhibit the min-size check.
578 (defun window-resizable (window delta &optional horizontal ignore side noup nodown)
579 "Return DELTA if WINDOW can be resized vertically by DELTA lines.
580 Optional argument HORIZONTAL non-nil means return DELTA if WINDOW
581 can be resized horizontally by DELTA columns. A return value of
582 zero means that WINDOW is not resizable.
584 DELTA positive means WINDOW shall be enlarged by DELTA lines or
585 columns. If WINDOW cannot be enlarged by DELTA lines or columns
586 return the maximum value in the range 0..DELTA by which WINDOW
587 can be enlarged.
589 DELTA negative means WINDOW shall be shrunk by -DELTA lines or
590 columns. If WINDOW cannot be shrunk by -DELTA lines or columns,
591 return the minimum value in the range DELTA..0 that can be used
592 for shrinking WINDOW.
594 Optional argument IGNORE non-nil means ignore any restrictions
595 imposed by fixed size windows, `window-min-height' or
596 `window-min-width' settings. IGNORE a window means ignore
597 restrictions for that window only. IGNORE equal `safe' means
598 live windows may get as small as `window-safe-min-height' lines
599 and `window-safe-min-width' columns.
601 Optional argument NOUP non-nil means don't go up in the window
602 tree but try to distribute the space among the other windows
603 within WINDOW's combination.
605 Optional argument NODOWN non-nil means don't check whether WINDOW
606 and its subwindows can be resized."
607 (setq window (normalize-any-window window))
608 (cond
609 ((< delta 0)
610 (max (- (window-min-delta window horizontal ignore side noup nodown))
611 delta))
612 ((> delta 0)
613 (min (window-max-delta window horizontal ignore side noup nodown)
614 delta))
615 (t 0)))
617 (defun window-resizable-p (window delta &optional horizontal ignore side noup nodown)
618 "Return t if WINDOW can be resized vertically by DELTA lines.
619 For the meaning of the arguments of this function see the
620 doc-string of `window-resizable'."
621 (setq window (normalize-any-window window))
622 (if (> delta 0)
623 (>= (window-resizable window delta horizontal ignore side noup nodown)
624 delta)
625 (<= (window-resizable window delta horizontal ignore side noup nodown)
626 delta)))
628 (defsubst window-total-height (&optional window)
629 "Return the total number of lines of WINDOW.
630 WINDOW can be any window and defaults to the selected one. The
631 return value includes WINDOW's mode line and header line, if any.
632 If WINDOW is internal the return value is the sum of the total
633 number of lines of WINDOW's child windows if these are vertically
634 combined and the height of WINDOW's first child otherwise.
636 Note: This function does not take into account the value of
637 `line-spacing' when calculating the number of lines in WINDOW."
638 (window-total-size window))
640 ;; Eventually we should make `window-height' obsolete.
641 (defalias 'window-height 'window-total-height)
643 ;; See discussion in bug#4543.
644 (defsubst window-full-height-p (&optional window)
645 "Return t if WINDOW is as high as the containing frame.
646 More precisely, return t if and only if the total height of
647 WINDOW equals the total height of the root window of WINDOW's
648 frame. WINDOW can be any window and defaults to the selected
649 one."
650 (setq window (normalize-any-window window))
651 (= (window-total-size window)
652 (window-total-size (frame-root-window window))))
654 (defsubst window-total-width (&optional window)
655 "Return the total number of columns of WINDOW.
656 WINDOW can be any window and defaults to the selected one. The
657 return value includes any vertical dividers or scrollbars of
658 WINDOW. If WINDOW is internal, the return value is the sum of
659 the total number of columns of WINDOW's child windows if these
660 are horizontally combined and the width of WINDOW's first child
661 otherwise."
662 (window-total-size window t))
664 (defsubst window-full-width-p (&optional window)
665 "Return t if WINDOW is as wide as the containing frame.
666 More precisely, return t if and only if the total width of WINDOW
667 equals the total width of the root window of WINDOW's frame.
668 WINDOW can be any window and defaults to the selected one."
669 (setq window (normalize-any-window window))
670 (= (window-total-size window t)
671 (window-total-size (frame-root-window window) t)))
673 (defsubst window-body-height (&optional window)
674 "Return the number of lines of WINDOW's body.
675 WINDOW must be a live window and defaults to the selected one.
677 The return value does not include WINDOW's mode line and header
678 line, if any. If a line at the bottom of the window is only
679 partially visible, that line is included in the return value. If
680 you do not want to include a partially visible bottom line in the
681 return value, use `window-text-height' instead."
682 (window-body-size window))
684 (defsubst window-body-width (&optional window)
685 "Return the number of columns of WINDOW's body.
686 WINDOW must be a live window and defaults to the selected one.
688 The return value does not include any vertical dividers or scroll
689 bars owned by WINDOW. On a window-system the return value does
690 not include the number of columns used for WINDOW's fringes or
691 display margins either."
692 (window-body-size window t))
694 ;; Eventually we should make `window-height' obsolete.
695 (defalias 'window-width 'window-body-width)
697 (defun window-current-scroll-bars (&optional window)
698 "Return the current scroll bar settings for WINDOW.
699 WINDOW must be a live window and defaults to the selected one.
701 The return value is a cons cell (VERTICAL . HORIZONTAL) where
702 VERTICAL specifies the current location of the vertical scroll
703 bars (`left', `right', or nil), and HORIZONTAL specifies the
704 current location of the horizontal scroll bars (`top', `bottom',
705 or nil).
707 Unlike `window-scroll-bars', this function reports the scroll bar
708 type actually used, once frame defaults and `scroll-bar-mode' are
709 taken into account."
710 (setq window (normalize-live-window window))
711 (let ((vert (nth 2 (window-scroll-bars window)))
712 (hor nil))
713 (when (or (eq vert t) (eq hor t))
714 (let ((fcsb (frame-current-scroll-bars (window-frame window))))
715 (if (eq vert t)
716 (setq vert (car fcsb)))
717 (if (eq hor t)
718 (setq hor (cdr fcsb)))))
719 (cons vert hor)))
721 (defun walk-windows (proc &optional minibuf all-frames)
722 "Cycle through all live windows, calling PROC for each one.
723 PROC must specify a function with a window as its sole argument.
724 The optional arguments MINIBUF and ALL-FRAMES specify the set of
725 windows to include in the walk.
727 MINIBUF t means include the minibuffer window even if the
728 minibuffer is not active. MINIBUF nil or omitted means include
729 the minibuffer window only if the minibuffer is active. Any
730 other value means do not include the minibuffer window even if
731 the minibuffer is active.
733 ALL-FRAMES nil or omitted means consider all windows on the
734 selected frame, plus the minibuffer window if specified by the
735 MINIBUF argument. If the minibuffer counts, consider all windows
736 on all frames that share that minibuffer too. The following
737 non-nil values of ALL-FRAMES have special meanings:
739 - t means consider all windows on all existing frames.
741 - `visible' means consider all windows on all visible frames.
743 - 0 (the number zero) means consider all windows on all visible
744 and iconified frames.
746 - A frame means consider all windows on that frame only.
748 Anything else means consider all windows on the selected frame
749 and no others.
751 This function changes neither the order of recently selected
752 windows nor the buffer list."
753 ;; If we start from the minibuffer window, don't fail to come
754 ;; back to it.
755 (when (window-minibuffer-p (selected-window))
756 (setq minibuf t))
757 ;; Make sure to not mess up the order of recently selected
758 ;; windows. Use `save-selected-window' and `select-window'
759 ;; with second argument non-nil for this purpose.
760 (save-selected-window
761 (when (framep all-frames)
762 (select-window (frame-first-window all-frames) 'norecord))
763 (dolist (walk-windows-window (window-list-1 nil minibuf all-frames))
764 (funcall proc walk-windows-window))))
766 (defun walk-window-tree-1 (proc walk-window-tree-window any)
767 "Helper function for `walk-window-tree'."
768 (let (walk-window-tree-buffer)
769 (while walk-window-tree-window
770 (setq walk-window-tree-buffer
771 (window-buffer walk-window-tree-window))
772 (when (or walk-window-tree-buffer any)
773 (funcall proc walk-window-tree-window))
774 (unless walk-window-tree-buffer
775 (walk-window-tree-1
776 proc (window-hchild walk-window-tree-window) any)
777 (walk-window-tree-1
778 proc (window-vchild walk-window-tree-window) any))
779 (setq walk-window-tree-window
780 (window-right walk-window-tree-window)))))
782 (defun walk-window-tree (proc &optional frame any)
783 "Run function PROC on each live window of FRAME.
784 PROC must be a function with one argument - a window. FRAME must
785 be a live frame and defaults to the selected one. ANY, if
786 non-nil means to run PROC on all live and internal windows of
787 FRAME.
789 This function performs a pre-order, depth-first traversal of the
790 window tree. If PROC changes the window tree, the result is
791 unpredictable."
792 (let ((walk-window-tree-frame (normalize-live-frame frame)))
793 (walk-window-tree-1
794 proc (frame-root-window walk-window-tree-frame) any)))
796 (defun window-in-direction-2 (window posn &optional horizontal)
797 "Support function for `window-in-direction'."
798 (if horizontal
799 (let ((top (window-top-line window)))
800 (if (> top posn)
801 (- top posn)
802 (- posn top (window-total-height window))))
803 (let ((left (window-left-column window)))
804 (if (> left posn)
805 (- left posn)
806 (- posn left (window-total-width window))))))
808 (defun window-in-direction (direction &optional window ignore)
809 "Return window in DIRECTION as seen from WINDOW.
810 DIRECTION must be one of `above', `below', `left' or `right'.
811 WINDOW must be a live window and defaults to the selected one.
812 IGNORE, when non-nil means a window can be returned even if its
813 `no-other-window' parameter is non-nil."
814 (setq window (normalize-live-window window))
815 (unless (memq direction '(above below left right))
816 (error "Wrong direction %s" direction))
817 (let* ((frame (window-frame window))
818 (hor (memq direction '(left right)))
819 (first (if hor
820 (window-left-column window)
821 (window-top-line window)))
822 (last (+ first (if hor
823 (window-total-width window)
824 (window-total-height window))))
825 (posn-cons (nth 6 (posn-at-point (window-point window) window)))
826 ;; The column / row value of `posn-at-point' can be nil for the
827 ;; mini-window, guard against that.
828 (posn (if hor
829 (+ (or (cdr posn-cons) 1) (window-top-line window))
830 (+ (or (car posn-cons) 1) (window-left-column window))))
831 (best-edge
832 (cond
833 ((eq direction 'below) (frame-height frame))
834 ((eq direction 'right) (frame-width frame))
835 (t -1)))
836 (best-edge-2 best-edge)
837 (best-diff-2 (if hor (frame-height frame) (frame-width frame)))
838 best best-2 best-diff-2-new)
839 (walk-window-tree
840 (lambda (w)
841 (let* ((w-top (window-top-line w))
842 (w-left (window-left-column w)))
843 (cond
844 ((or (eq window w)
845 ;; Ignore ourselves.
846 (and (window-parameter w 'no-other-window)
847 ;; Ignore W unless IGNORE is non-nil.
848 (not ignore))))
849 (hor
850 (cond
851 ((and (<= w-top posn)
852 (< posn (+ w-top (window-total-height w))))
853 ;; W is to the left or right of WINDOW and covers POSN.
854 (when (or (and (eq direction 'left)
855 (<= w-left first) (> w-left best-edge))
856 (and (eq direction 'right)
857 (>= w-left last) (< w-left best-edge)))
858 (setq best-edge w-left)
859 (setq best w)))
860 ((and (or (and (eq direction 'left)
861 (<= (+ w-left (window-total-width w)) first))
862 (and (eq direction 'right) (<= last w-left)))
863 ;; W is to the left or right of WINDOW but does not
864 ;; cover POSN.
865 (setq best-diff-2-new
866 (window-in-direction-2 w posn hor))
867 (or (< best-diff-2-new best-diff-2)
868 (and (= best-diff-2-new best-diff-2)
869 (if (eq direction 'left)
870 (> w-left best-edge-2)
871 (< w-left best-edge-2)))))
872 (setq best-edge-2 w-left)
873 (setq best-diff-2 best-diff-2-new)
874 (setq best-2 w))))
876 (cond
877 ((and (<= w-left posn)
878 (< posn (+ w-left (window-total-width w))))
879 ;; W is above or below WINDOW and covers POSN.
880 (when (or (and (eq direction 'above)
881 (<= w-top first) (> w-top best-edge))
882 (and (eq direction 'below)
883 (>= w-top first) (< w-top best-edge)))
884 (setq best-edge w-top)
885 (setq best w)))
886 ((and (or (and (eq direction 'above)
887 (<= (+ w-top (window-total-height w)) first))
888 (and (eq direction 'below) (<= last w-top)))
889 ;; W is above or below WINDOW but does not cover POSN.
890 (setq best-diff-2-new
891 (window-in-direction-2 w posn hor))
892 (or (< best-diff-2-new best-diff-2)
893 (and (= best-diff-2-new best-diff-2)
894 (if (eq direction 'above)
895 (> w-top best-edge-2)
896 (< w-top best-edge-2)))))
897 (setq best-edge-2 w-top)
898 (setq best-diff-2 best-diff-2-new)
899 (setq best-2 w)))))))
900 (window-frame window))
901 (or best best-2)))
903 (defun get-window-with-predicate (predicate &optional minibuf
904 all-frames default)
905 "Return a live window satisfying PREDICATE.
906 More precisely, cycle through all windows calling the function
907 PREDICATE on each one of them with the window as its sole
908 argument. Return the first window for which PREDICATE returns
909 non-nil. If no window satisfies PREDICATE, return DEFAULT.
911 ALL-FRAMES nil or omitted means consider all windows on the selected
912 frame, plus the minibuffer window if specified by the MINIBUF
913 argument. If the minibuffer counts, consider all windows on all
914 frames that share that minibuffer too. The following non-nil
915 values of ALL-FRAMES have special meanings:
917 - t means consider all windows on all existing frames.
919 - `visible' means consider all windows on all visible frames.
921 - 0 (the number zero) means consider all windows on all visible
922 and iconified frames.
924 - A frame means consider all windows on that frame only.
926 Anything else means consider all windows on the selected frame
927 and no others."
928 (catch 'found
929 (dolist (window (window-list-1 nil minibuf all-frames))
930 (when (funcall predicate window)
931 (throw 'found window)))
932 default))
934 (defalias 'some-window 'get-window-with-predicate)
936 (defun get-lru-window (&optional all-frames dedicated)
937 "Return the least recently used window on frames specified by ALL-FRAMES.
938 Return a full-width window if possible. A minibuffer window is
939 never a candidate. A dedicated window is never a candidate
940 unless DEDICATED is non-nil, so if all windows are dedicated, the
941 value is nil. Avoid returning the selected window if possible.
943 The following non-nil values of the optional argument ALL-FRAMES
944 have special meanings:
946 - t means consider all windows on all existing frames.
948 - `visible' means consider all windows on all visible frames.
950 - 0 (the number zero) means consider all windows on all visible
951 and iconified frames.
953 - A frame means consider all windows on that frame only.
955 Any other value of ALL-FRAMES means consider all windows on the
956 selected frame and no others."
957 (let (best-window best-time second-best-window second-best-time time)
958 (dolist (window (window-list-1 nil nil all-frames))
959 (when (or dedicated (not (window-dedicated-p window)))
960 (setq time (window-use-time window))
961 (if (or (eq window (selected-window))
962 (not (window-full-width-p window)))
963 (when (or (not second-best-time) (< time second-best-time))
964 (setq second-best-time time)
965 (setq second-best-window window))
966 (when (or (not best-time) (< time best-time))
967 (setq best-time time)
968 (setq best-window window)))))
969 (or best-window second-best-window)))
971 (defun get-mru-window (&optional all-frames)
972 "Return the most recently used window on frames specified by ALL-FRAMES.
973 Do not return a minibuffer window.
975 The following non-nil values of the optional argument ALL-FRAMES
976 have special meanings:
978 - t means consider all windows on all existing frames.
980 - `visible' means consider all windows on all visible frames.
982 - 0 (the number zero) means consider all windows on all visible
983 and iconified frames.
985 - A frame means consider all windows on that frame only.
987 Any other value of ALL-FRAMES means consider all windows on the
988 selected frame and no others."
989 (let (best-window best-time time)
990 (dolist (window (window-list-1 nil nil all-frames))
991 (setq time (window-use-time window))
992 (when (or (not best-time) (> time best-time))
993 (setq best-time time)
994 (setq best-window window)))
995 best-window))
997 (defun get-largest-window (&optional all-frames dedicated)
998 "Return the largest window on frames specified by ALL-FRAMES.
999 A minibuffer window is never a candidate. A dedicated window is
1000 never a candidate unless DEDICATED is non-nil, so if all windows
1001 are dedicated, the value is nil.
1003 The following non-nil values of the optional argument ALL-FRAMES
1004 have special meanings:
1006 - t means consider all windows on all existing frames.
1008 - `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.
1013 - A frame means consider all windows on that frame only.
1015 Any other value of ALL-FRAMES means consider all windows on the
1016 selected frame and no others."
1017 (let ((best-size 0)
1018 best-window size)
1019 (dolist (window (window-list-1 nil nil all-frames))
1020 (when (or dedicated (not (window-dedicated-p window)))
1021 (setq size (* (window-total-size window)
1022 (window-total-size window t)))
1023 (when (> size best-size)
1024 (setq best-size size)
1025 (setq best-window window))))
1026 best-window))
1028 ;; The following is what `get-buffer-window' would look like if it were
1029 ;; implemented in Elisp. Since this function is needed for dumping,
1030 ;; leave it in C.
1032 ;; (defun get-buffer-window (&optional buffer-or-name all-frames)
1033 ;; "Return a window currently displaying BUFFER-OR-NAME, or nil if none.
1034 ;; BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
1035 ;; the current buffer.
1037 ;; The following non-nil values of the optional argument ALL-FRAMES
1038 ;; have special meanings:
1039 ;; - t means consider all windows on all existing frames.
1040 ;; - `visible' means consider all windows on all visible frames.
1041 ;; - 0 (the number zero) means consider all windows on all visible
1042 ;; and iconified frames.
1043 ;; - A frame means consider all windows on that frame only.
1044 ;; Any other value of ALL-FRAMES means consider all windows on the
1045 ;; selected frame and no others."
1046 ;; (let ((buffer (get-buffer buffer-or-name))
1047 ;; best-window)
1048 ;; (when (bufferp buffer)
1049 ;; (dolist (window (window-list-1 nil t all-frames))
1050 ;; (when (and (eq (window-buffer window) buffer)
1051 ;; ;; The following SHOULD have been handled by
1052 ;; ;; `window-list-1' already ...
1053 ;; (or (not (window-minibuffer-p window))
1054 ;; ;; Don't find any minibuffer window except the
1055 ;; ;; one that is currently in use.
1056 ;; (eq window (minibuffer-window)))
1057 ;; (or (not best-window)
1058 ;; ;; Prefer to return selected window.
1059 ;; (eq window (selected-window))
1060 ;; ;; Prefer windows on selected frame.
1061 ;; (eq (window-frame window) (selected-frame))))
1062 ;; (setq best-window window))))
1063 ;; best-window))
1065 (defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames)
1066 "Return list of all windows displaying BUFFER-OR-NAME, or nil if none.
1067 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
1068 and defaults to the current buffer.
1070 Any windows showing BUFFER-OR-NAME on the selected frame are listed
1071 first.
1073 MINIBUF t means include the minibuffer window even if the
1074 minibuffer is not active. MINIBUF nil or omitted means include
1075 the minibuffer window only if the minibuffer is active. Any
1076 other value means do not include the minibuffer window even if
1077 the minibuffer is active.
1079 ALL-FRAMES nil or omitted means consider all windows on the
1080 selected frame, plus the minibuffer window if specified by the
1081 MINIBUF argument. If the minibuffer counts, consider all windows
1082 on all frames that share that minibuffer too. The following
1083 non-nil values of ALL-FRAMES have special meanings:
1085 - t means consider all windows on all existing frames.
1087 - `visible' means consider all windows on all visible frames.
1089 - 0 (the number zero) means consider all windows on all visible
1090 and iconified frames.
1092 - A frame means consider all windows on that frame only.
1094 Anything else means consider all windows on the selected frame
1095 and no others."
1096 (let ((buffer (normalize-live-buffer buffer-or-name))
1097 windows)
1098 (dolist (window (window-list-1 (frame-first-window) minibuf all-frames))
1099 (when (eq (window-buffer window) buffer)
1100 (setq windows (cons window windows))))
1101 (nreverse windows)))
1103 (defun minibuffer-window-active-p (window)
1104 "Return t if WINDOW is the currently active minibuffer window."
1105 (eq window (active-minibuffer-window)))
1107 (defun count-windows (&optional minibuf)
1108 "Return the number of live windows on the selected frame.
1109 The optional argument MINIBUF specifies whether the minibuffer
1110 window shall be counted. See `walk-windows' for the precise
1111 meaning of this argument."
1112 (length (window-list-1 nil minibuf)))
1114 ;;; Resizing windows.
1115 (defun resize-window-reset (&optional frame horizontal)
1116 "Reset resize values for all windows on FRAME.
1117 FRAME defaults to the selected frame.
1119 This function stores the current value of `window-total-size' applied
1120 with argument HORIZONTAL in the new total size of all windows on
1121 FRAME. It also resets the new normal size of each of these
1122 windows."
1123 (resize-window-reset-1
1124 (frame-root-window (normalize-live-frame frame)) horizontal))
1126 (defun resize-window-reset-1 (window horizontal)
1127 "Internal function of `resize-window-reset'."
1128 ;; Register old size in the new total size.
1129 (resize-window-total window (window-total-size window horizontal))
1130 ;; Reset new normal size.
1131 (resize-window-normal window)
1132 (when (window-child window)
1133 (resize-window-reset-1 (window-child window) horizontal))
1134 (when (window-right window)
1135 (resize-window-reset-1 (window-right window) horizontal)))
1137 ;; The following routine is needed to manually resize the minibuffer
1138 ;; window and is currently used, for example, by ispell.el.
1139 (defun resize-mini-window (window delta)
1140 "Resize minibuffer window WINDOW by DELTA lines.
1141 If WINDOW cannot be resized by DELTA lines make it as large \(or
1142 as small) as possible but don't signal an error."
1143 (when (window-minibuffer-p window)
1144 (let* ((frame (window-frame window))
1145 (root (frame-root-window frame))
1146 (height (window-total-size window))
1147 (min-delta
1148 (- (window-total-size root)
1149 (window-min-size root))))
1150 ;; Sanitize DELTA.
1151 (cond
1152 ((<= (+ height delta) 0)
1153 (setq delta (- (- height 1))))
1154 ((> delta min-delta)
1155 (setq delta min-delta)))
1156 ;; Resize now.
1157 (resize-window-reset frame)
1158 (resize-this-window root (- delta) nil nil t)
1159 (resize-window-total window (+ height delta))
1160 ;; The following routine catches the case where we want to resize
1161 ;; a minibuffer-only frame.
1162 (resize-mini-window-internal window))))
1164 (defvar resize-window-safe-window nil
1165 "Internal variable bound by `resize-window'.")
1167 (defun resize-window (window delta &optional horizontal ignore)
1168 "Resize WINDOW vertically by DELTA lines.
1169 WINDOW can be an arbitrary window and defaults to the selected
1170 one. An attempt to resize the root window of a frame will raise
1171 an error though.
1173 DELTA a positive number means WINDOW shall be enlarged by DELTA
1174 lines. DELTA negative means WINDOW shall be shrunk by -DELTA
1175 lines.
1177 Optional argument HORIZONTAL non-nil means resize WINDOW
1178 horizontally by DELTA columns. In this case a positive DELTA
1179 means enlarge WINDOW by DELTA columns. DELTA negative means
1180 WINDOW shall be shrunk by -DELTA columns.
1182 Optional argument IGNORE non-nil means ignore any restrictions
1183 imposed by fixed size windows, `window-min-height' or
1184 `window-min-width' settings. IGNORE any window means ignore
1185 restrictions for that window only. IGNORE equal `safe' means
1186 live windows may get as small as `window-safe-min-height' lines
1187 and `window-safe-min-width' columns.
1189 This function resizes other windows proportionally and never
1190 deletes any windows. If you want to move only the low (right)
1191 edge of WINDOW consider using `adjust-window-trailing-edge'
1192 instead."
1193 (setq window (normalize-any-window window))
1194 (let* ((frame (window-frame window))
1195 right)
1196 (cond
1197 ((eq window (frame-root-window frame))
1198 (error "Cannot resize root window of frame"))
1199 ((window-minibuffer-p window)
1200 (resize-mini-window window delta))
1201 ((window-resizable-p window delta horizontal ignore)
1202 (resize-window-reset frame horizontal)
1203 (resize-this-window window delta horizontal ignore t)
1204 (if (and (not (eq window-splits 'resize))
1205 (window-iso-combined-p window horizontal)
1206 (setq right (window-right window))
1207 (or (window-size-ignore window ignore)
1208 (not (window-size-fixed-p right)))
1209 (or (< delta 0)
1210 (> (- (window-total-size right horizontal)
1211 (window-min-size right horizontal))
1212 delta)))
1213 ;; Resize window below/on the right of WINDOW - this is the
1214 ;; classic Emacs behavior, so retain it for `window-splits'
1215 ;; not 'resize, iso-combined windows. It's a PITA, though.
1216 (let ((parent-size
1217 (window-total-size (window-parent window) horizontal)))
1218 (resize-this-window right (- delta) horizontal nil t)
1219 (resize-window-normal
1220 window (/ (float (window-new-total-size window)) parent-size))
1221 (resize-window-normal
1222 right (/ (float (window-new-total-size right)) parent-size)))
1223 (resize-other-windows window delta horizontal ignore))
1224 (resize-window-apply frame horizontal))
1226 (error "Cannot resize window %s" window)))))
1228 (defsubst resize-subwindows-skip-p (window)
1229 "Return non-nil if WINDOW shall be skipped by resizing routines."
1230 (memq (window-new-normal-size window) '(ignore stuck skip)))
1232 (defun resize-subwindows-normal (parent horizontal window delta side)
1233 "Set new normal height of all subwindows of window PARENT.
1234 HORIZONTAL non-nil means set normal width of these windows.
1235 WINDOW has to specify a subwindow of PARENT that has been resized
1236 by DELTA lines \(columns). SIDE non-nil means set values for
1237 windows on the specified side of WINDOW only."
1238 (let* ((parent-new-total (window-new-total-size parent))
1239 (window-new-total
1240 (+ (window-total-size window horizontal) delta))
1241 (window-new-normal
1242 (/ (float window-new-total) parent-new-total))
1243 (others-old-normal
1244 (- 1 (window-normal-size window horizontal)))
1245 (others-new-normal (- 1 window-new-normal))
1246 (sub (window-child parent))
1247 (skip (eq side 'right)))
1249 (when (memq side '(left right))
1250 (while sub
1251 (cond
1252 ((eq sub window)
1253 (setq skip (eq side 'left)))
1254 (skip
1255 (setq others-old-normal
1256 (- others-old-normal
1257 (window-normal-size sub horizontal)))
1258 (setq others-new-normal
1259 (- others-new-normal
1260 (window-normal-size sub horizontal)))))
1261 (setq sub (window-right sub)))
1262 (setq sub (window-child parent))
1263 (setq skip (eq side 'right)))
1265 (setq sub (window-child parent))
1266 (while sub
1267 (cond
1268 ((eq sub window)
1269 (resize-window-normal sub window-new-normal)
1270 (setq skip (eq side 'left)))
1271 (skip)
1273 (resize-window-normal
1274 sub (if (zerop others-old-normal)
1276 (/ (* (window-normal-size sub horizontal)
1277 others-new-normal)
1278 others-old-normal)))))
1279 (setq sub (window-right sub)))))
1281 ;; Calling the following has
1282 ;; 1. SIDE non-nil => WINDOW nil.
1283 ;; 2. WINDOW non-nil => resize PARENT and WINDOW by DELTA.
1284 ;; 3. WINDOW nil => resize PARENT by DELTA.
1285 (defun resize-subwindows (parent delta &optional horizontal ignore side)
1286 "Resize subwindows of window PARENT vertically by DELTA lines.
1287 PARENT must be a vertically combined internal window.
1289 Optional argument HORIZONTAL non-nil means resize subwindows of
1290 PARENT horizontally by DELTA columns. In this case PARENT must
1291 be a horizontally combined internal window.
1293 Optional argument IGNORE non-nil means ignore any restrictions
1294 imposed by fixed size windows, `window-min-height' or
1295 `window-min-width' settings. IGNORE equal `safe' means live
1296 windows may get as small as `window-safe-min-height' lines and
1297 `window-safe-min-width' columns. IGNORE any window means ignore
1298 restrictions for that window only.
1300 Optional argument SIDE `left' means try to resize only the last
1301 subwindow of PARENT provided DELTA is greater zero. SIDE `right'
1302 means try to only resize the first subwindow of PARENT provided
1303 DELTA is greater zero. Any other value of SIDE is ignored."
1304 (let* ((first (window-child parent))
1305 (sub first)
1306 (normal-sum 0.0)
1307 (total-sum delta)
1308 (failed t)
1309 (amount 0)
1310 found sub-total sub-normal sub-int sub-float sub-delta sub-amount
1311 sub-rest best best-rest)
1312 ;; `normal-sum' is the sum of the normal sizes of all resizable
1313 ;; subwindows of PARENT. `total-sum' is the sum of the total
1314 ;; sizes of all resizable subwindows of PARENT plus DELTA.
1315 (catch 'done
1316 (while sub
1317 (unless (or (resize-subwindows-skip-p sub)
1318 (and (not ignore)
1319 ;; Ignore fixed-size subwindows.
1320 (window-size-fixed-p sub horizontal)
1321 (resize-window-normal sub 'ignore)))
1322 (setq normal-sum (+ normal-sum
1323 (window-normal-size sub horizontal)))
1324 (setq total-sum (+ total-sum
1325 (window-total-size sub horizontal)))
1326 ;; `found' non-nil tells that there is at least one subwindow
1327 ;; left that can be resized (should stay `t' now ;-().
1328 (setq found t))
1329 (setq sub (window-right sub)))
1331 ;; When SIDE is non-nil and DELTA is greater zero try to resize
1332 ;; the first subwindow (when SIDE is `right') or the last
1333 ;; subwindow (when SIDE is `left') first. This is the behavior
1334 ;; needed by `adjust-window-trailing-edge' when the edge-adjacent
1335 ;; subwindow the user wants to enlarge is nested in a combination.
1336 (when (and (> delta 0)
1337 ;; Skip a fixed-size window: This is inherently not
1338 ;; TRT because a fixed-size internal window might
1339 ;; still have a resizable subwindow which we could
1340 ;; enlarge. But DTRT here is quite non-trivial :-(
1341 (or (and (eq side 'left)
1342 (progn
1343 (setq sub first)
1344 (while (window-right sub)
1345 (setq sub (window-right sub)))
1346 sub))
1347 (and (eq side 'right) (setq sub first)))
1348 (not (resize-subwindows-skip-p sub)))
1349 ;; DELTA > 0 guarantees that resizing SUB always succeeds.
1350 (resize-this-window sub delta horizontal ignore t side)
1351 ;; Assign new normal sizes.
1352 (resize-subwindows-normal parent horizontal sub delta side)
1353 (throw 'done 0))
1355 ;; We resize subwindows in "rounds". We assume that usually a
1356 ;; resize request succeeds in the first round. If it fails -
1357 ;; which means at least one subwindow cannot be resized as desired
1358 ;; - we need another round. Failures are recorded in the variable
1359 ;; `failed' and, for the failed subwindow, by setting that
1360 ;; window's new normal size to a negative value.
1362 ;; Note that in each round we record (via `resize-window-total')
1363 ;; only the amount by which the window shall be resized. Only
1364 ;; when we know how each inidvidual subwindow shall be resized
1365 ;; (that is after the final round) we add the current size of the
1366 ;; window to the amount recorded previously.
1367 (while (and failed found)
1368 ;; We try to resize each resizable subwindow `sub' by a value
1369 ;; `sub-delta' individually calculated for `sub'. `sub-amount'
1370 ;; specifies the actual amount `sub' can be resized to in the
1371 ;; present round. `amount' represents the sum of the
1372 ;; `sub-amount' for all subwindows we are able to resize in the
1373 ;; present round. `delta' is de-/increased by the sum of
1374 ;; `sub-amount' for all subwindows we we're not able to resize
1375 ;; completely in the present round. So `amount' and `delta'
1376 ;; grow/shrink towards each other and we are done when the have
1377 ;; the same value. `sub-rest' is the remainder when calculating
1378 ;; `sub-delta' and is used when calculating the new normal
1379 ;; sizes.
1380 (setq amount 0)
1381 (setq found nil)
1382 (setq failed nil)
1383 (setq sub first)
1384 ;; The following loop represents one round.
1385 (while (and sub (not failed))
1386 ;; Ignore subwindows that should be ignored or are stuck.
1387 (unless (resize-subwindows-skip-p sub)
1388 ;; Set `found' to t to make sure that if this round fails we
1389 ;; make another round.
1390 (setq found t)
1391 ;; `sub-total' records the total size of this subwindow.
1392 (setq sub-total (window-total-size sub horizontal))
1393 ;; `sub-normal' records the normal of this subwindow.
1394 (setq sub-normal (window-normal-size sub horizontal))
1395 ;; `sub-delta' records the number of lines or columns by
1396 ;; which this subwindow should grow or shrink. `sub-float'
1397 ;; and `sub-int' record the new ideal total size as a float
1398 ;; and integer value.
1399 (setq sub-float (/ (* sub-normal total-sum) normal-sum))
1400 (setq sub-int (floor sub-float))
1401 (setq sub-delta (- sub-int sub-total))
1402 ;; `sub-rest' is the remainder.
1403 (setq sub-rest (abs (- sub-float sub-int)))
1404 (if (and side (< delta 0) (>= sub-delta 0))
1405 ;; With `adjust-window-trailing-edge' some window can
1406 ;; get penalized such that its normal size exceeds its
1407 ;; fractional total size considerably. In that case
1408 ;; dragging a divider in the opposite direction in order
1409 ;; to enlarge some other window may cause this window
1410 ;; get _enlarged_ which looks silly. We try to avoid
1411 ;; such behavior here.
1412 (resize-window-total sub sub-total)
1413 ;; `sub-amount' records the number of lines or columns by
1414 ;; which this subwindow can grow or shrink.
1415 (setq sub-amount
1416 (window-sizable sub sub-delta horizontal ignore))
1417 ;; Register the new total size for this subwindow.
1418 (resize-window-total sub (+ sub-total sub-amount))
1419 (if (= sub-amount sub-delta)
1420 ;; We succeeded to get this subwindow's share.
1421 (progn
1422 (if (and (< delta 0) (zerop sub-amount))
1423 ;; When shrinking avoid that a window that has
1424 ;; not shrunk gets a remainder before a window
1425 ;; that has shrunk.
1426 (resize-window-normal sub 'rest)
1427 ;; Record remainder.
1428 (resize-window-normal sub sub-rest))
1429 (setq amount (+ amount sub-amount)))
1430 ;; We failed and need a new round.
1431 (setq failed t)
1432 ;; Don't consider this subwindow again when calculating
1433 ;; desired sizes.
1434 (setq normal-sum (- normal-sum sub-normal))
1435 (setq total-sum (- total-sum sub-total sub-amount))
1436 (setq delta (- delta sub-amount))
1437 (resize-window-normal sub 'stuck))))
1438 (setq sub (window-right sub))))
1440 ;; Fix rounding by trying to enlarge non-stuck, non-rest windows
1441 ;; by one line (column) until `amount' equals `delta'.
1442 (when found
1443 (catch 'found
1444 (while (< amount delta)
1445 (setq sub first)
1446 (setq best nil)
1447 (setq best-rest 0)
1448 (while sub
1449 (setq sub-normal (window-new-normal-size sub))
1450 (when (and (numberp sub-normal) (>= sub-normal best-rest))
1451 (setq best sub)
1452 (setq best-rest sub-normal)
1453 (setq found t))
1454 (setq sub (window-right sub)))
1455 (if (not best)
1456 (throw 'found nil)
1457 (resize-window-total best 1 'add)
1458 (resize-window-normal best (max 0 (1- best-rest)))
1459 (setq amount (1+ amount))))))
1461 ;; Fix rounding by trying to enlarge "rest" windows by one line
1462 ;; (column) until `amount' equals `delta'.
1463 (catch 'found
1464 (while (< amount delta)
1465 (setq sub first)
1466 (setq best nil)
1467 (when (eq (window-new-normal-size sub) 'rest)
1468 (setq best t)
1469 (resize-window-total sub 1 'add)
1470 (setq amount (1+ amount))
1471 (setq sub (window-right sub)))
1472 (unless best
1473 (throw 'found nil))))
1475 ;; Fix rounding by trying to enlarge stuck windows by one line
1476 ;; (column) until `amount' equals `delta'.
1477 (catch 'found
1478 (while (< amount delta)
1479 (setq sub first)
1480 (setq best nil)
1481 (when (eq (window-new-normal-size sub) 'stuck)
1482 (setq best t)
1483 (resize-window-total sub 1 'add)
1484 (setq amount (1+ amount))
1485 (setq sub (window-right sub)))
1486 (unless best
1487 (throw 'found nil))))
1489 ;; Reset new normal size fields so `resize-window-apply' won't use
1490 ;; them to apply new sizes.
1491 (setq sub first)
1492 (while sub
1493 (when (numberp (window-new-normal-size sub))
1494 (resize-window-normal sub))
1495 (setq sub (window-right sub)))
1497 ;; Now recursively resize each resized subwindow's subwindows.
1498 (setq sub first)
1499 (while sub
1500 (unless (eq (window-new-normal-size sub) 'ignore)
1501 ;; Resize this subwindow's subwindows. Note that above we
1502 ;; recorded (via `resize-window-total') only the amount by
1503 ;; which this subwindow had to be resized. Now we add the old
1504 ;; total size.
1505 (let ((delta (- (window-new-total-size sub)
1506 (window-total-size sub horizontal))))
1507 (unless (and (zerop delta) (not side))
1508 (resize-this-window sub delta horizontal ignore nil side))))
1509 (setq sub (window-right sub))))))
1511 (defun resize-other-windows (window delta &optional horizontal ignore side)
1512 "Resize other windows when WINDOW is resized vertically by DELTA lines.
1513 Optional argument HORIZONTAL non-nil means resize other windows
1514 when WINDOW is resized horizontally by DELTA columns. WINDOW
1515 itself is not resized by this function.
1517 Optional argument IGNORE non-nil means ignore any restrictions
1518 imposed by fixed size windows, `window-min-height' or
1519 `window-min-width' settings. IGNORE equal `safe' means live
1520 windows may get as small as `window-safe-min-height' lines and
1521 `window-safe-min-width' columns. IGNORE any window means ignore
1522 restrictions for that window only.
1524 Optional argument SIDE `left' means resize other windows above
1525 \(on left of) WINDOW only. SIDE `right' means resize other
1526 windows below \(on right of) WINDOW only. Any other value of
1527 SIDE is ignored."
1528 (when (window-parent window)
1529 (let* ((parent (window-parent window))
1530 (sub (window-child parent))
1531 non-fixed)
1532 (if (window-iso-combined-p sub horizontal)
1533 ;; In an iso-combination resize WINDOW's siblings.
1534 (let ((first sub)
1535 (skip (eq side 'right))
1536 this-delta)
1537 ;; Decide which windows shall be left alone.
1538 (while sub
1539 (cond
1540 ((eq sub window)
1541 ;; Make sure WINDOW is left alone when
1542 ;; resizing its siblings.
1543 (resize-window-normal sub 'ignore)
1544 (setq skip (eq side 'left)))
1545 (skip
1546 ;; Make sure this sibling is left alone when
1547 ;; resizing its siblings.
1548 (resize-window-normal sub 'ignore))
1549 ((or (window-size-ignore sub ignore)
1550 (not (window-size-fixed-p sub horizontal)))
1551 (setq non-fixed t)))
1552 (setq sub (window-right sub)))
1553 (if (= (- delta) (window-total-size window horizontal))
1554 ;; A deletion, presumably.
1555 (if non-fixed
1556 ;; There's at least on resizable sibling.
1557 (setq this-delta delta)
1558 ;; No resizable sibling present.
1559 (setq this-delta 0))
1560 (setq this-delta
1561 (window-resizable
1562 window delta horizontal ignore side t)))
1563 (unless (= delta this-delta)
1564 (resize-window-total parent (- delta this-delta) 'add))
1565 (unless (zerop this-delta)
1566 (resize-window-normal window 'ignore)
1567 (resize-subwindows
1568 parent (- this-delta) horizontal ignore side)
1569 ;; Now set the normal sizes.
1570 (resize-subwindows-normal
1571 parent horizontal window this-delta side)
1572 (setq delta (- delta this-delta))))
1574 ;; In an ortho-combination all siblings of WINDOW must be
1575 ;; resized by DELTA. Store the new total size of parent first.
1576 (resize-window-total parent delta 'add)
1577 (while sub
1578 (unless (eq sub window)
1579 (resize-this-window sub delta horizontal ignore t))
1580 (setq sub (window-right sub))))
1582 (unless (zerop delta)
1583 ;; "Go up."
1584 (resize-other-windows parent delta horizontal ignore side)))))
1586 (defun resize-this-window (window delta &optional horizontal ignore add-total side)
1587 "Resize WINDOW vertically by DELTA lines.
1588 Optional argument HORIZONTAL non-nil means resize WINDOW
1589 horizontally by DELTA columns.
1591 Optional argument IGNORE non-nil means ignore any restrictions
1592 imposed by fixed size windows, `window-min-height' or
1593 `window-min-width' settings. IGNORE equal `safe' means live
1594 windows may get as small as `window-safe-min-height' lines and
1595 `window-safe-min-width' columns. IGNORE any window means ignore
1596 restrictions for that window only.
1598 Optional argument ADD-TOTAL non-nil means add DELTA to the new
1599 total size of WINDOW.
1601 Optional argument SIDE `left' means resize other windows above
1602 \(on left of) WINDOW only. SIDE `right' means resize other
1603 windows below \(on right of) WINDOW only. Any other value of
1604 SIDE is ignored.
1606 This function recursively resizes WINDOW's subwindows to fit the
1607 new size. Make sure that WINDOW is `window-resizable' before
1608 calling this function. Note that this function does not resize
1609 siblings of WINDOW or WINDOW's parent window. You have to
1610 eventually call `resize-window-apply' in order to make resizing
1611 actually take effect."
1612 (when add-total
1613 ;; Add DELTA to the new total size of WINDOW.
1614 (resize-window-total window delta t))
1616 (let ((sub (window-child window)))
1617 (cond
1618 ((not sub))
1619 ((window-iso-combined-p sub horizontal)
1620 ;; In an iso-combination resize subwindows according to their
1621 ;; fractions.
1622 (resize-subwindows window delta horizontal ignore side))
1623 ;; In an ortho-combination resize each subwindow by DELTA.
1625 (while sub
1626 (resize-this-window sub delta horizontal ignore t side)
1627 (setq sub (window-right sub)))))))
1629 (defun resize-root-window (window delta horizontal ignore)
1630 "Resize root window WINDOW vertically by DELTA lines.
1631 HORIZONTAL non-nil means resize root window WINDOW horizontally
1632 by DELTA columns.
1634 IGNORE non-nil means ignore any restrictions imposed by fixed
1635 size windows, `window-min-height' or `window-min-width' settings.
1637 This function is called by Emacs' frame resizing routines. It
1638 resizes windows proportionally and never deletes any windows."
1639 (when (and (windowp window) (numberp delta)
1640 (window-sizable-p window delta horizontal ignore))
1641 (resize-window-reset (window-frame window) horizontal)
1642 (resize-this-window window delta horizontal ignore t)))
1644 (defun resize-root-window-vertically (window delta)
1645 "Resize root window WINDOW vertically by DELTA lines.
1646 If DELTA is less than zero and we can't shrink WINDOW by DELTA
1647 lines, shrink it as much as possible. If DELTA is greater than
1648 zero, this function can resize fixed-size subwindows in order to
1649 recover the necessary lines.
1651 Return the number of lines that were recovered.
1653 This function is called by Emacs' minibuffer resizing routines.
1654 It resizes windows proportionally and never deletes any windows."
1655 (when (numberp delta)
1656 (let (ignore)
1657 (cond
1658 ((< delta 0)
1659 (setq delta (window-sizable window delta)))
1660 ((> delta 0)
1661 (unless (window-sizable window delta)
1662 (setq ignore t))))
1663 (resize-window-reset (window-frame window))
1664 (resize-this-window window delta nil ignore t)
1665 delta)))
1667 (defun adjust-window-trailing-edge (window delta &optional horizontal)
1668 "Move WINDOW's bottom edge by DELTA lines.
1669 Optional argument HORIZONTAL non-nil means move WINDOW's right
1670 edge by DELTA columns. WINDOW defaults to the selected window.
1672 If the edge can't be moved by DELTA lines, move it as far as
1673 possible in the desired direction."
1674 (setq window (normalize-any-window window))
1675 (let ((frame (window-frame window))
1676 (right window)
1677 left this-delta min-delta max-delta failed)
1678 ;; Find the edge we want to move.
1679 (while (and (or (not (window-iso-combined-p right horizontal))
1680 (not (window-right right)))
1681 (setq right (window-parent right))))
1682 (unless (and (setq left right) (setq right (window-right right)))
1683 (error "No window following this one"))
1685 ;; Set LEFT to the first resizable window on the left. This step is
1686 ;; needed to handle fixed-size windows.
1687 (while (and left (window-size-fixed-p left horizontal))
1688 (setq left
1689 (or (window-left left)
1690 (progn
1691 (while (and (setq left (window-parent left))
1692 (not (window-iso-combined-p left horizontal))))
1693 (window-left left)))))
1694 (unless left
1695 (error "No resizable window preceding this one"))
1697 ;; Set RIGHT to the first resizable window on the right. This step
1698 ;; is needed to handle fixed-size windows.
1699 (while (and right (window-size-fixed-p right horizontal))
1700 (setq right
1701 (or (window-right right)
1702 (progn
1703 (while (and (setq right (window-parent right))
1704 (not (window-iso-combined-p right horizontal))))
1705 (window-right right)))))
1706 (unless right
1707 (error "No resizable window following this one"))
1709 ;; LEFT and RIGHT (which might be both internal windows) are now the
1710 ;; two windows we want to resize.
1711 (cond
1712 ((> delta 0)
1713 (setq max-delta (window-max-delta-1 left 0 horizontal nil 'right))
1714 (setq min-delta (window-min-delta-1 right (- delta) horizontal nil 'left))
1715 (when (or (< max-delta delta) (> min-delta (- delta)))
1716 ;; We can't get the whole DELTA - move as far as possible.
1717 (setq delta (min max-delta (- min-delta))))
1718 (unless (zerop delta)
1719 ;; Start resizing.
1720 (resize-window-reset frame horizontal)
1721 ;; Try to enlarge LEFT first.
1722 (setq this-delta (window-resizable left delta horizontal))
1723 (unless (zerop this-delta)
1724 (resize-this-window left this-delta horizontal nil t 'left))
1725 (unless (= this-delta delta)
1726 ;; We didn't get it all from LEFT, enlarge windows on left of
1727 ;; LEFT (for this purpose make `resize-other-windows' believe
1728 ;; that we shrink LEFT).
1729 (resize-other-windows
1730 left (- this-delta delta) horizontal nil 'left))
1731 ;; Shrink windows on right of LEFT.
1732 (resize-other-windows left delta horizontal nil 'right)))
1733 ((< delta 0)
1734 (setq max-delta (window-max-delta-1 right 0 horizontal nil 'left))
1735 (setq min-delta (window-min-delta-1 left delta horizontal nil 'right))
1736 (when (or (< max-delta (- delta)) (> min-delta delta))
1737 ;; We can't get the whole DELTA - move as far as possible.
1738 (setq delta (max (- max-delta) min-delta)))
1739 (unless (zerop delta)
1740 ;; Start resizing.
1741 (resize-window-reset frame horizontal)
1742 ;; Try to enlarge RIGHT.
1743 (setq this-delta (window-resizable right (- delta) horizontal))
1744 (unless (zerop this-delta)
1745 (resize-this-window right this-delta horizontal nil t 'right))
1746 (unless (= (- this-delta) delta)
1747 ;; We didn't get it all from RIGHT, enlarge windows on right of
1748 ;; RIGHT (for this purpose make `resize-other-windows' believe
1749 ;; that we grow RIGHT).
1750 (resize-other-windows
1751 right (- this-delta delta) horizontal nil 'right))
1752 ;; Shrink windows on left of RIGHT.
1753 (resize-other-windows right (- delta) horizontal nil 'left))))
1754 (unless (zerop delta)
1755 ;; Don't report an error in the standard case.
1756 (unless (resize-window-apply frame horizontal)
1757 ;; But do report an error it applying the changes fails.
1758 (error "Failed adjusting window %s" window)))))
1760 (defun enlarge-window (delta &optional horizontal)
1761 "Make selected window DELTA lines taller.
1762 Interactively, if no argument is given, make the selected window
1763 one line taller. If optional argument HORIZONTAL is non-nil,
1764 make selected window wider by DELTA columns. If DELTA is
1765 negative, shrink selected window by -DELTA lines or columns.
1766 Return nil."
1767 (interactive "p")
1768 (resize-window (selected-window) delta horizontal))
1770 (defun shrink-window (delta &optional horizontal)
1771 "Make selected window DELTA lines smaller.
1772 Interactively, if no argument is given, make the selected window
1773 one line smaller. If optional argument HORIZONTAL is non-nil,
1774 make selected window narrower by DELTA columns. If DELTA is
1775 negative, enlarge selected window by -DELTA lines or columns.
1776 Return nil."
1777 (interactive "p")
1778 (resize-window (selected-window) (- delta) horizontal))
1780 (defun maximize-window (&optional window)
1781 "Maximize WINDOW.
1782 Make WINDOW as large as possible without deleting any windows.
1783 WINDOW can be any window and defaults to the selected window."
1784 (interactive)
1785 (setq window (normalize-any-window window))
1786 (resize-window window (window-max-delta window))
1787 (resize-window window (window-max-delta window t) t))
1789 (defun minimize-window (&optional window)
1790 "Minimize WINDOW.
1791 Make WINDOW as small as possible without deleting any windows.
1792 WINDOW can be any window and defaults to the selected window."
1793 (interactive)
1794 (setq window (normalize-any-window window))
1795 (resize-window window (- (window-min-delta window)))
1796 (resize-window window (- (window-min-delta window t)) t))
1798 (defsubst frame-root-window-p (window)
1799 "Return non-nil if WINDOW is the root window of its frame."
1800 (eq window (frame-root-window window)))
1802 (defun window-tree-1 (window &optional next)
1803 "Return window tree rooted at WINDOW.
1804 Optional argument NEXT non-nil means include windows right
1805 siblings in the return value.
1807 See the documentation of `window-tree' for a description of the
1808 return value."
1809 (let (list)
1810 (while window
1811 (setq list
1812 (cons
1813 (cond
1814 ((window-vchild window)
1815 (cons t (cons (window-edges window)
1816 (window-tree-1 (window-vchild window) t))))
1817 ((window-hchild window)
1818 (cons nil (cons (window-edges window)
1819 (window-tree-1 (window-hchild window) t))))
1820 (t window))
1821 list))
1822 (setq window (when next (window-next window))))
1823 (nreverse list)))
1825 (defun window-tree (&optional frame)
1826 "Return the window tree of frame FRAME.
1827 FRAME must be a live frame and defaults to the selected frame.
1828 The return value is a list of the form (ROOT MINI), where ROOT
1829 represents the window tree of the frame's root window, and MINI
1830 is the frame's minibuffer window.
1832 If the root window is not split, ROOT is the root window itself.
1833 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil
1834 for a horizontal split, and t for a vertical split. EDGES gives
1835 the combined size and position of the subwindows in the split,
1836 and the rest of the elements are the subwindows in the split.
1837 Each of the subwindows may again be a window or a list
1838 representing a window split, and so on. EDGES is a list \(LEFT
1839 TOP RIGHT BOTTOM) as returned by `window-edges'."
1840 (setq frame (normalize-live-frame frame))
1841 (window-tree-1 (frame-root-window frame) t))
1843 ;;; Composite Windows
1845 ;; The basic invariant of the composite window code is:
1847 ;; \A window \in Windows:
1848 ;; \A sibling \in Siblings [window]:
1849 ;; composite-window-p [window] =>
1850 ;; /\ composite-window-p [sibling]
1851 ;; /\ composite-root-window [window] = composite-root-window [sibling]
1853 ;; that is, for any window that is part of a composite window, any
1854 ;; sibling of that window is a subwindow of the same composite window.
1856 ;; This is usually not called as a "predicate" but it's more consistent
1857 ;; to maintain our defsubsts as predicate.
1858 (defsubst composite-window-p (window)
1859 "Return non-nil if WINDOW is a subwindow of a composite window.
1860 The return value is the value of the `composite' window parameter
1861 of WINDOW."
1862 (window-parameter window 'composite))
1864 (defsubst composite-root-window-p (window)
1865 "Return non-nil if WINDOW is the root of a composite window.
1866 The return value is the type of that composite window, either
1867 `compound' or `group'."
1868 (or (window-parameter window 'compound)
1869 (window-parameter window 'group)))
1871 (defsubst composite-main-window-p (window)
1872 "Return t if WINDOW is a main window of a composite window."
1873 (eq (cdr-safe (composite-window-p window)) 'main))
1875 (defsubst composite-support-window-p (window)
1876 "Return t if WINDOW is a support window of a composite window."
1877 (eq (cdr-safe (composite-window-p window)) 'support))
1879 (defun composite-root-window (window)
1880 "Return root window of the composite window WINDOW is a part of.
1881 Return nil if WINDOW is not part of a composite window or the
1882 path from WINDOW to the root of the composite window is broken."
1883 (let ((type (car-safe (window-parameter window 'composite))))
1884 (when type
1885 (setq window (window-parent window))
1886 (catch 'done
1887 (while window
1888 (cond
1889 ((window-parameter window type)
1890 (throw 'done window))
1891 ((eq (car-safe (window-parameter window 'composite)) type))
1893 ;; Broken path.
1894 (throw 'done nil)))
1895 (setq window (window-parent window)))))))
1897 (defun composite-major-window (window)
1898 "Return major window of composite window WINDOW belongs to.
1899 The major window is the last main or root window found by
1900 following the path from WINDOW to the root of the composite
1901 window WINDOW belongs to. Each composite window should have one
1902 and only one major window to make sure that functions on its
1903 component windows behave \"as intended\".
1905 This function returns a meaningful result if and only if WINDOW
1906 is a main window."
1907 (let ((main window))
1908 (setq window (window-parent window))
1909 (while (and window (composite-main-window-p window)
1910 (not (composite-root-window-p window)))
1911 (setq main window)
1912 (setq window (window-parent window)))
1913 ;; We can't go up any further but maybe the window we're looking at
1914 ;; is the root window.
1915 (when (composite-root-window-p window)
1916 (let ((sibling (window-child window)))
1917 ;; Make sure that all children of the group root window are main
1918 ;; windows.
1919 (catch 'done
1920 (while sibling
1921 (if (not (composite-main-window-p sibling))
1922 (throw 'done nil)
1923 (setq sibling (window-right sibling))))
1924 (setq main window))))
1925 main))
1927 (defun composite-main-sibling (window)
1928 "Return first \"main\" sibling of WINDOW.
1929 A main sibling is a main window of a composite window. Both,
1930 WINDOW and the main sibling must have the same parent window and
1931 thus be part of one and the same composite window. Return nil if
1932 no such window can be found."
1933 (let ((parent (window-parent window))
1934 sibling)
1935 (when parent
1936 (setq sibling (window-child parent))
1937 (catch 'done
1938 (while sibling
1939 (if (and (not (eq sibling window))
1940 (eq (cdr-safe (window-parameter sibling 'composite)) 'main))
1941 (throw 'done sibling)
1942 (setq sibling (window-right sibling))))))))
1944 (defun composite-lowest-child-role (window)
1945 "Return lowest \"non-main\" role among WINDOW's children."
1946 (let ((sibling (window-child window))
1947 (highest 'main)
1948 role)
1949 (catch 'done
1950 (while sibling
1951 (setq role (cdr-safe (window-parameter sibling 'composite)))
1952 (cond
1953 ((eq role t)
1954 (setq highest t))
1955 ((eq role 'support)
1956 (throw 'done 'support)))
1957 (setq sibling (window-right sibling)))
1958 highest)))
1960 (defsubst compound-window-p (window)
1961 "Return non-nil if WINDOW is a subwindow of a compound window."
1962 (eq (car-safe (window-parameter window 'composite)) 'compound))
1964 (defsubst compound-main-window-p (window)
1965 "Return non-nil if WINDOW is a main window of a compound window."
1966 (let ((composite (composite-window-p window)))
1967 (and (eq (car-safe composite) 'compound)
1968 (eq (cdr-safe composite) 'main))))
1970 (defun compound-root-window (window)
1971 "Return topmost root window of compound window WINDOW belongs to."
1972 (while (and window (compound-window-p window))
1973 (setq window (window-parent window)))
1974 (when (window-parameter window 'compound)
1975 window))
1977 (defsubst group-window-p (window)
1978 "Return non-nil if WINDOW is a subwindow of a window group."
1979 (eq (car-safe (window-parameter window 'composite)) 'group))
1981 (defsubst group-window-main-p (window)
1982 "Return non-nil if WINDOW is a main window of a window group."
1983 (let ((composite (composite-window-p window)))
1984 (and (eq (car-safe composite) 'group)
1985 (eq (cdr-safe composite) 'main))))
1987 (defun group-root-window (window)
1988 "Return root window of window group WINDOW belongs to.
1989 If WINDOW is part of a compound window, return the root window of
1990 the group the root of the compound window belongs too."
1991 (while (and window (compound-window-p window))
1992 (setq window (window-parent window)))
1993 (while (and window (group-window-p window)
1994 (not (composite-root-window-p window)))
1995 (setq window (window-parent window)))
1996 (when (window-parameter window 'group)
1997 window))
1999 ;;; Getting the "other" window.
2000 ;; FIXME: Handle `ignore-window-parameters' and some other things maybe.
2001 (defun other-window (count &optional all-frames)
2002 "Select another window in cyclic ordering of windows.
2003 COUNT specifies the number of windows to skip, starting with the
2004 selected window, before making the selection. If COUNT is
2005 positive, skip COUNT windows forwards. If COUNT is negative,
2006 skip -COUNT windows backwards. COUNT zero means do not skip any
2007 window, so select the selected window. In an interactive call,
2008 COUNT is the numeric prefix argument. Return nil.
2010 This function does not select a window whose `no-other-window'
2011 parameter is non-nil. Also, this function never selects the
2012 support window of a composite window unless the support window's
2013 `maybe-other-window' parameter is non-nil.
2015 This function uses `next-window' for finding the window to
2016 select. The argument ALL-FRAMES has the same meaning as in
2017 `next-window', but the MINIBUF argument of `next-window' is
2018 always effectively nil."
2019 (interactive "p")
2020 (let* ((window (selected-window))
2021 (function (window-parameter window 'other-window))
2022 old-window old-count)
2023 (if (functionp function)
2024 (funcall function count all-frames)
2025 ;; `next-window' and `previous-window' may return a window we are
2026 ;; not allowed to select. Hence we need an exit strategy in case
2027 ;; all windows are non-selectable.
2028 (catch 'exit
2029 (while (> count 0)
2030 (setq window (next-window window nil all-frames))
2031 (cond
2032 ((eq window old-window)
2033 (when (= count old-count)
2034 ;; Keep out of infinite loops. When COUNT has not changed
2035 ;; since we last looked at `window' we're probably in one.
2036 (throw 'exit nil)))
2037 ((or (and (composite-support-window-p window)
2038 (not (window-parameter window 'maybe-other-window)))
2039 (window-parameter window 'no-other-window))
2040 ;; The first non-selectable window `next-window' got us:
2041 ;; Remember it and the current value of COUNT.
2042 (unless old-window
2043 (setq old-window window)
2044 (setq old-count count)))
2046 (setq count (1- count)))))
2047 (while (< count 0)
2048 (setq window (previous-window window nil all-frames))
2049 (cond
2050 ((eq window old-window)
2051 (when (= count old-count)
2052 ;; Keep out of infinite loops. When COUNT has not changed
2053 ;; since we last looked at `window' we're probably in one.
2054 (throw 'exit nil)))
2055 ((or (and (composite-support-window-p window)
2056 (not (window-parameter window 'maybe-other-window)))
2057 (window-parameter window 'no-other-window))
2058 ;; The first non-selectable window `previous-window' got us:
2059 ;; Remember it and the current value of COUNT.
2060 (unless old-window
2061 (setq old-window window)
2062 (setq old-count count)))
2064 (setq count (1+ count)))))
2065 (select-window window)
2066 nil))))
2068 ;; This should probably return non-nil when the selected window is part
2069 ;; of a compound window whose root is the frame's root window.
2070 (defun one-window-p (&optional nomini all-frames)
2071 "Return non-nil if the selected window is the only window.
2072 Optional arg NOMINI non-nil means don't count the minibuffer
2073 even if it is active. Otherwise, the minibuffer is counted
2074 when it is active.
2076 Optional argument ALL-FRAMES specifies the set of frames to
2077 consider, see also `next-window'. ALL-FRAMES nil or omitted
2078 means consider windows on the selected frame only, plus the
2079 minibuffer window if specified by the NOMINI argument. If the
2080 minibuffer counts, consider all windows on all frames that share
2081 that minibuffer too. The remaining non-nil values of ALL-FRAMES
2082 with a special meaning are:
2084 - t means consider all windows on all existing frames.
2086 - `visible' means consider all windows on all visible frames.
2088 - 0 (the number zero) means consider all windows on all visible
2089 and iconified frames.
2091 - A frame means consider all windows on that frame only.
2093 Anything else means consider all windows on the selected frame
2094 and no others."
2095 (let ((base-window (selected-window)))
2096 (if (and nomini (eq base-window (minibuffer-window)))
2097 (setq base-window (next-window base-window)))
2098 (eq base-window
2099 (next-window base-window (if nomini 'arg) all-frames))))
2101 ;;; Deleting windows.
2102 (defun window-deletable-p (&optional window)
2103 "Return t if WINDOW can be safely deleted from its frame.
2104 Return `frame' if deleting WINDOW should delete its frame
2105 instead."
2106 (setq window (normalize-any-window window))
2107 (let ((frame (window-frame window))
2108 (dedicated (and (window-buffer window) (window-dedicated-p window)))
2109 (quit-restore (window-parameter window 'quit-restore))
2110 composite type role root)
2111 (cond
2112 ((frame-root-window-p window)
2113 (when (and (or dedicated
2114 (and (eq (car-safe quit-restore) 'new-frame)
2115 (eq (nth 1 quit-restore) (window-buffer window))))
2116 (other-visible-frames-p frame))
2117 ;; WINDOW is the root window of its frame. Return `frame' but
2118 ;; only if WINDOW is (1) either dedicated or quit-restore's car
2119 ;; is new-frame and the window still displays the same buffer
2120 ;; and (2) there are other frames left.
2121 'frame))
2122 ((setq composite (window-parameter window 'composite))
2123 (setq type (car-safe composite))
2124 (setq role (cdr-safe composite))
2125 (setq root (composite-root-window window))
2126 (cond
2127 ;; When `ignore-window-parameters' or the `delete-window'
2128 ;; parameter say or WINDOW is part of a broken composite window,
2129 ;; WINDOW is deletable. We cannot handle the case where WINDOW's
2130 ;; `delete-window' parameter is a function (that's impossible).
2131 ((or (not (memq ignore-window-parameters '(nil post)))
2132 (eq (window-parameter window 'delete-window) t)
2133 (not root) (not type) (not role))
2135 ((eq type 'compound)
2136 ;; A component of a compound window is deletable if and only if
2137 ;; its root is deletable.
2138 (window-deletable-p root))
2139 ((eq type 'group)
2140 ;; In a window group only a main window with a main sibling is
2141 ;; deletable.
2142 (and (eq role 'main) (composite-main-sibling window)))))
2143 (t))))
2145 (defun window-or-subwindow-p (subwindow window)
2146 "Return t if SUBWINDOW is either WINDOW or a subwindow of WINDOW."
2147 (or (eq subwindow window)
2148 (let ((parent (window-parent subwindow)))
2149 (catch 'done
2150 (while parent
2151 (if (eq parent window)
2152 (throw 'done t)
2153 (setq parent (window-parent parent))))))))
2155 (defun delete-window (&optional window)
2156 "Delete WINDOW.
2157 WINDOW can be an arbitrary window and defaults to the selected
2158 one. Return nil.
2160 This function respects the variable `ignore-window-parameters'
2161 when processing window parameters so any processing of WINDOW's
2162 parameters may be suppressed.
2164 If the `delete-window' parameter WINDOW equals t, delete WINDOW
2165 ignoring any other window parameters. If the `delete-window'
2166 parameter specifies a function, call that function with WINDOW as
2167 its sole argument. It's the responsibility of that function to
2168 adjust the parameters of all remaining windows.
2170 Otherwise, if WINDOW is part of a compound window, call this
2171 function with the root of the compound window as its argument.
2172 If WINDOW is either the only window on its frame, or a support
2173 window or the last main window of a window group, signal an error
2174 and don't delete WINDOW.
2176 This function makes sure that window parameters are reset or
2177 inherited when WINDOW is part of a combination of two windows."
2178 (interactive)
2179 (setq window (normalize-any-window window))
2180 (let* ((function (window-parameter window 'delete-window))
2181 ;; COMPOSITE non-nil means WINDOW is part of a composite
2182 ;; window.
2183 (composite (window-parameter window 'composite))
2184 ;; TYPE is the type of the composite window (either `compound'
2185 ;; or `group'). ROLE is the role of WINDOW within the
2186 ;; composite window (either `main', `support', or t). ROOT is
2187 ;; the root window of the composite window.
2188 (type (car-safe composite))
2189 (role (cdr-safe composite))
2190 (root (and composite (composite-root-window window)))
2191 parent)
2192 (catch 'done
2193 ;; Handle window parameters.
2194 (cond
2195 ;; Ignore window parameters if `ignore-window-parameters' tells
2196 ;; so or the `delete-window' parameter equals t.
2197 ((or (not (memq ignore-window-parameters '(nil post)))
2198 (eq function t)))
2199 ((functionp function)
2200 ;; The `delete-window' parameter specifies the function to call
2201 ;; instead. If that function is `ignore' nothing is done. It's
2202 ;; up to the function called here to avoid infinite recursion.
2203 (throw 'done (funcall function window)))
2204 (composite
2205 (cond
2206 ((or (not root) (not type) (not role))
2207 ;; Something is broken in this composite window. Signal a
2208 ;; message but let the deletion pass through (we might signal
2209 ;; an error here but for everday work this is too nasty).
2210 (message "Broken component %s of composite window" window))
2211 ((eq type 'compound)
2212 ;; Deleting a component of a compound window deletes the
2213 ;; entire compound window.
2214 (throw 'done (delete-window root)))
2215 ((eq type 'group)
2216 (cond
2217 ((not (eq role 'main))
2218 ;; WINDOW is _not_ a main window of a window group. There's
2219 ;; no rule for deleting such a window so we signal an error.
2220 ;; We might swallow this error silently.
2221 (error "Cannot delete non-main window of a window group"))
2222 ((not (composite-main-sibling window))
2223 ;; WINDOW has no main sibling and we can't delete the last
2224 ;; main window of a window group. We might swallow this
2225 ;; error silently.
2226 (error "Cannot delete last main window of a window group")))))))
2228 ;; Set PARENT to WINDOW's parent in the window tree. If there's
2229 ;; no such parent signal an error.
2230 (unless (setq parent (window-parent window))
2231 (error "Attempt to delete minibuffer or sole ordinary window"))
2233 (let* ((horizontal (window-hchild parent))
2234 (size (window-total-size window horizontal))
2235 (frame (window-frame window))
2236 (frame-selected
2237 (window-or-subwindow-p (frame-selected-window frame) window))
2238 ;; LEFT is WINDOW's _left_ sibling - traditionally LEFT
2239 ;; gets enlarged and is selected after the deletion.
2240 (left (window-left window))
2241 ;; RIGHT is WINDOW's right sibling.
2242 (right (window-right window))
2243 ;; SIBLING is WINDOW's sibling provided they are the only
2244 ;; child windows of PARENT.
2245 (sibling
2246 (or (and left (not right) (not (window-left left)) left)
2247 (and right (not left) (not (window-right right)) right)))
2248 ;; Record some of PARENT's parameters (just in case we have
2249 ;; WINDOW replace it in the window tree).
2250 (parent-compound
2251 (and sibling (window-parameter parent 'compound)))
2252 (parent-group
2253 (and sibling (window-parameter parent 'group)))
2254 (parent-composite
2255 (and sibling (window-parameter parent 'composite))))
2256 (resize-window-reset frame horizontal)
2257 (cond
2258 ((or (and (eq window-splits 'nest)
2259 (or (and left (not (window-left left))
2260 (not (window-right window)))
2261 (and (not left)
2262 (setq left (window-right window))
2263 (not (window-right left))))
2264 (not (window-size-fixed-p left horizontal)))
2265 (and left (not window-splits)
2266 (not (window-size-fixed-p left horizontal))))
2267 ;; Resize WINDOW's left sibling.
2268 (resize-this-window left size horizontal nil t)
2269 (resize-window-normal
2270 left (+ (window-normal-size left horizontal)
2271 (window-normal-size window horizontal))))
2272 ((let ((sub (window-child parent)))
2273 (catch 'found
2274 ;; Look for a non-fixed-size sibling.
2275 (while sub
2276 (when (and (not (eq sub window))
2277 (not (window-size-fixed-p sub horizontal)))
2278 (throw 'found t))
2279 (setq sub (window-right sub)))))
2280 ;; We can do it without resizing fixed-size windows.
2281 (resize-other-windows window (- size) horizontal))
2283 ;; Can't do without resizing fixed-size windows. We really
2284 ;; should signal an error here but who would agree :-(
2285 (resize-other-windows window (- size) horizontal t)))
2286 ;; Actually delete WINDOW.
2287 (delete-window-internal window)
2288 (when (and frame-selected
2289 (window-parameter
2290 (frame-selected-window frame) 'no-other-window))
2291 ;; `delete-window-internal' has selected a window that should
2292 ;; not be selected, fix this here (I hate `other-window').
2293 (other-window -1 frame))
2294 ;; Handle composite windows (unless we ignore window
2295 ;; parameters).
2296 (when (and (memq ignore-window-parameters '(nil pre))
2297 sibling (not (eq parent (window-parent sibling)))
2298 (or parent-compound parent-group))
2299 ;; At this moment we know that WINDOW and SIBLING are part of
2300 ;; a composite window and the _sole_ child windows of PARENT.
2301 ;; SIBLING replaces PARENT.
2302 (when parent-group
2303 ;; SIBLING becomes the new root of the window group earlier
2304 ;; headed by PARENT. If PARENT was the root of a compound
2305 ;; window that compound window gets dissolved.
2306 (set-window-parameter sibling 'group t))
2307 (if parent-composite
2308 ;; `sibling' inherits composite state of `parent'.
2309 (set-window-parameter sibling 'composite parent-composite)
2310 ;; `sibling' is no longer part of a composite window.
2311 (set-window-parameter sibling 'composite nil)))
2312 (run-window-configuration-change-hook frame)
2313 nil))))
2315 (defun delete-other-windows (&optional window)
2316 "Make WINDOW fill its frame.
2317 WINDOW may be any window and defaults to the selected one.
2319 This function respects the variable `ignore-window-parameters'
2320 when processing window parameters so any processing of WINDOW's
2321 parameters may be suppressed.
2323 If the `delete-other-windows' parameter of WINDOW equals t,
2324 delete WINDOW ignoring any other window parameters. If the
2325 `delete-other-windows' parameter specifies a function, call that
2326 function with WINDOW as its sole argument. It's the
2327 responsibility of that function to adjust the parameters of all
2328 remaining windows.
2330 Otherwise, if WINDOW is part of a compound window, call this
2331 function with the root of the compound window as its argument.
2332 If WINDOW is a main window in a window group, make WINDOW the
2333 only main window in this group. Any support windows of the group
2334 are left alone. If WINDOW is a support window of a window group,
2335 signal an error and don't delete any windows."
2336 (interactive)
2337 (setq window (normalize-any-window window))
2338 (let* ((function (window-parameter window 'delete-other-windows))
2339 (composite (window-parameter window 'composite))
2340 ;; COMPOSITE non-nil means WINDOW is part of a composite
2341 ;; window.
2342 (type (car-safe composite))
2343 (role (cdr-safe composite))
2344 (root (and composite (composite-root-window window)))
2345 ;; TYPE is the type of the composite window (either `compound'
2346 ;; or `group'). ROLE is the role of WINDOW within the
2347 ;; composite window (either `main', `support', or t). ROOT is
2348 ;; the root window of the composite window.
2349 main)
2350 (catch 'done
2351 ;; Handle composite window parameter.
2352 (cond
2353 ;; Ignore window parameters if `ignore-window-parameters' tells
2354 ;; so or the `delete-other-windows' parameter equals t.
2355 ((or (not (memq ignore-window-parameters '(nil post)))
2356 (eq function t)))
2357 ((functionp function)
2358 ;; The `delete-other-windows' parameter specifies the function
2359 ;; to call instead. If the function is `ignore' no windows are
2360 ;; deleted. It's up to the function called to avoid infinite
2361 ;; recursion.
2362 (throw 'done (funcall function window)))
2363 (composite
2364 (cond
2365 ((or (not root) (not type) (not role))
2366 ;; Something is broken in this composite window. Signal a
2367 ;; message but let the deletion pass through (we might signal
2368 ;; an error here but for everday work this is too nasty).
2369 (message "Broken composite window"))
2370 ((eq type 'compound)
2371 ;; In a compound window call `delete-other-windows' with the
2372 ;; root window as its argument.
2373 (throw 'done (delete-other-windows root)))
2374 ((eq type 'group)
2375 (if (eq role 'main)
2376 ;; In a window group we are allowed to delete main windows
2377 ;; only. Moreover we need an ancestor which is the last
2378 ;; main window found when following the path to the group
2379 ;; root window.
2380 (progn
2381 (setq main (composite-major-window window))
2382 (when (or (not main) (eq main window))
2383 ;; If we don't find an ancestor or the ancestor is
2384 ;; WINDOW itself there's nothing we can delete.
2385 ;; Swallow this quietly.
2386 (throw 'done nil))
2387 (when (and (eq main root)
2388 (memq ignore-window-parameters '(nil pre)))
2389 ;; If we delete right up to the root of this group
2390 ;; (that is, there are no support windows around) give
2391 ;; WINDOW the parameters of `root'.
2392 (set-window-parameter window 'group t)
2393 (set-window-parameter
2394 window 'composite (window-parameter root 'composite))))
2395 ;; We might swallow this message.
2396 (error
2397 "Cannot delete other windows for non-main window %s" window))))))
2399 (delete-other-windows-internal window main)
2400 (when (and (memq ignore-window-parameters '(nil pre))
2401 (frame-root-window-p window))
2402 ;; Clean up for the case where we did something special.
2403 (set-window-parameter window 'composite nil))
2404 nil)))
2406 (defun delete-other-windows-vertically (&optional window)
2407 "Delete the windows in the same column with WINDOW, but not WINDOW itself.
2408 This may be a useful alternative binding for \\[delete-other-windows]
2409 if you often split windows horizontally."
2410 (interactive)
2411 (let* ((window (or window (selected-window)))
2412 (edges (window-edges window))
2413 (w window) delenda)
2414 (while (not (eq (setq w (next-window w 1)) window))
2415 (let ((e (window-edges w)))
2416 (when (and (= (car e) (car edges))
2417 (= (caddr e) (caddr edges)))
2418 (push w delenda))))
2419 (mapc 'delete-window delenda)))
2421 ;;; Windows and buffers.
2423 ;; `prev-buffers' and `next-buffers' are two reserved window slots used
2424 ;; for (1) determining which buffer to show in the window when its
2425 ;; buffer shall be buried or killed and (2) which buffer to show for
2426 ;; `switch-to-prev-buffer' and `switch-to-next-buffer'.
2428 ;; `prev-buffers' consists of <buffer, window-start, window-point>
2429 ;; triples. The entries on this list are ordered by the time their
2430 ;; buffer has been removed from the window, the most recently removed
2431 ;; buffer's entry being first. The window-start and window-point
2432 ;; components are `window-start' and `window-point' at the time the
2433 ;; buffer was removed from the window which implies that the entry must
2434 ;; be added when `set-window-buffer' removes the buffer from the window.
2436 ;; `next-buffers' is the list of buffers that have been replaced
2437 ;; recently by `switch-to-prev-buffer'. These buffers are the least
2438 ;; preferred candidates of `switch-to-prev-buffer' and the preferred
2439 ;; candidates of `switch-to-next-buffer' to switch to. This list is
2440 ;; reset to nil by any action changing the window's buffer with the
2441 ;; exception of `switch-to-prev-buffer' and `switch-to-next-buffer'.
2442 ;; `switch-to-prev-buffer' pushes the buffer it just replaced on it,
2443 ;; `switch-to-next-buffer' pops the last pushed buffer from it.
2445 ;; Both `prev-buffers' and `next-buffers' may reference killed buffers
2446 ;; if such a buffer was killed while the window was hidden within a
2447 ;; window configuration. Such killed buffers get removed whenever
2448 ;; `switch-to-prev-buffer' or `switch-to-next-buffer' encounter them.
2450 ;; The following function is called by `set-window-buffer' _before_ it
2451 ;; replaces the buffer of the argument window with the new buffer.
2452 (defun record-window-buffer (&optional window)
2453 "Record WINDOW's buffer.
2454 WINDOW must be a live window and defaults to the selected one."
2455 (let* ((window (normalize-live-window window))
2456 (buffer (window-buffer window))
2457 (entry (assq buffer (window-prev-buffers window))))
2458 ;; Reset WINDOW's next buffers. If needed, they are resurrected by
2459 ;; `switch-to-prev-buffer' and `switch-to-next-buffer'.
2460 (set-window-next-buffers window nil)
2462 (when entry
2463 ;; Remove all entries for BUFFER from WINDOW's previous buffers.
2464 (set-window-prev-buffers
2465 window (assq-delete-all buffer (window-prev-buffers window))))
2467 ;; Don't record insignificant buffers.
2468 (unless (eq (aref (buffer-name buffer) 0) ?\s)
2469 ;; Add an entry for buffer to WINDOW's previous buffers.
2470 (with-current-buffer buffer
2471 (let ((start (window-start window))
2472 (point (window-point window)))
2473 (setq entry
2474 (cons buffer
2475 (if entry
2476 ;; We have an entry, update marker positions.
2477 (list (set-marker (nth 1 entry) start)
2478 (set-marker (nth 2 entry) point))
2479 ;; Make new markers.
2480 (list (copy-marker start)
2481 (copy-marker point)))))
2483 (set-window-prev-buffers
2484 window (cons entry (window-prev-buffers window))))))))
2486 (defun unrecord-window-buffer (&optional window buffer)
2487 "Unrecord BUFFER in WINDOW.
2488 WINDOW must be a live window and defaults to the selected one.
2489 BUFFER must be a live buffer and defaults to the buffer of
2490 WINDOW."
2491 (let* ((window (normalize-live-window window))
2492 (buffer (or buffer (window-buffer window))))
2493 (set-window-prev-buffers
2494 window (assq-delete-all buffer (window-prev-buffers window)))
2495 (set-window-next-buffers
2496 window (delq buffer (window-next-buffers window)))))
2498 (defun set-window-buffer-start-and-point (window buffer &optional start point)
2499 "Set WINDOW's buffer to BUFFER.
2500 Optional argument START non-nil means set WINDOW's start position
2501 to START. Optional argument POINT non-nil means set WINDOW's
2502 point to POINT. If WINDOW is selected this also sets BUFFER's
2503 `point' to POINT. If WINDOW is selected and the buffer it showed
2504 before was current this also makes BUFFER the current buffer."
2505 (let ((selected (eq window (selected-window)))
2506 (current (eq (window-buffer window) (current-buffer))))
2507 (set-window-buffer window buffer)
2508 (when (and selected current)
2509 (set-buffer buffer))
2510 (when start
2511 (set-window-start window start))
2512 (when point
2513 (if selected
2514 (with-current-buffer buffer
2515 (goto-char point))
2516 (set-window-point window point)))))
2518 (defun switch-to-prev-buffer (&optional window bury-or-kill)
2519 "In WINDOW switch to previous buffer.
2520 WINDOW must be a live window and defaults to the selected one.
2522 Optional argument BURY-OR-KILL non-nil means the buffer currently
2523 shown in WINDOW is about to be buried or killed and consequently
2524 shall not be switched to in future invocations of this command."
2525 (interactive)
2526 (let* ((window (normalize-live-window window))
2527 (old-buffer (window-buffer window))
2528 ;; Save this since it's destroyed by `set-window-buffer'.
2529 (next-buffers (window-next-buffers window))
2530 entry new-buffer killed-buffers deletable)
2531 (cond
2532 ;; When BURY-OR-KILL is non-nil, there's no previous buffer for
2533 ;; this window, and we can delete the window (or the frame) do
2534 ;; that.
2535 ((and bury-or-kill
2536 (or (not (window-prev-buffers window))
2537 (and (eq (caar (window-prev-buffers window)) old-buffer)
2538 (not (cdr (car (window-prev-buffers window))))))
2539 (setq deletable (window-deletable-p window)))
2540 (if (eq deletable 'frame)
2541 (delete-frame (window-frame window))
2542 (delete-window window)))
2543 ((window-dedicated-p window)
2544 (error "Window %s is dedicated to buffer %s" window old-buffer)))
2546 (unless deletable
2547 (catch 'found
2548 ;; Scan WINDOW's previous buffers first, skipping entries of next
2549 ;; buffers.
2550 (dolist (entry (window-prev-buffers window))
2551 (when (and (setq new-buffer (car entry))
2552 (or (buffer-live-p new-buffer)
2553 (not (setq killed-buffers
2554 (cons new-buffer killed-buffers))))
2555 (not (eq new-buffer old-buffer))
2556 (or bury-or-kill
2557 (not (memq new-buffer next-buffers))))
2558 (set-window-buffer-start-and-point
2559 window new-buffer (nth 1 entry) (nth 2 entry))
2560 (throw 'found t)))
2561 ;; Scan reverted buffer list of WINDOW's frame next, skipping
2562 ;; entries of next buffers. Note that when we bury or kill a
2563 ;; buffer we don't reverse the global buffer list to avoid showing
2564 ;; a buried buffer instead. Otherwise, we must reverse the global
2565 ;; buffer list in order to make sure that switching to the
2566 ;; previous/next buffer traverse it in opposite directions.
2567 (dolist (buffer (if bury-or-kill
2568 (buffer-list (window-frame window))
2569 (nreverse (buffer-list (window-frame window)))))
2570 (when (and (buffer-live-p buffer)
2571 (not (eq buffer old-buffer))
2572 (not (eq (aref (buffer-name buffer) 0) ?\s))
2573 (or bury-or-kill (not (memq buffer next-buffers))))
2574 (setq new-buffer buffer)
2575 (set-window-buffer-start-and-point window new-buffer)
2576 (throw 'found t)))
2577 (unless bury-or-kill
2578 ;; Scan reverted next buffers last (must not use nreverse
2579 ;; here!).
2580 (dolist (buffer (reverse next-buffers))
2581 ;; Actually, buffer _must_ be live here since otherwise it
2582 ;; would have been caught in the scan of previous buffers.
2583 (when (and (or (buffer-live-p buffer)
2584 (not (setq killed-buffers
2585 (cons buffer killed-buffers))))
2586 (not (eq buffer old-buffer))
2587 (setq entry (assq buffer (window-prev-buffers window))))
2588 (setq new-buffer buffer)
2589 (set-window-buffer-start-and-point
2590 window new-buffer (nth 1 entry) (nth 2 entry))
2591 (throw 'found t)))))
2593 (if bury-or-kill
2594 ;; Remove `old-buffer' from WINDOW's previous and (restored list
2595 ;; of) next buffers.
2596 (progn
2597 (set-window-prev-buffers
2598 window (assq-delete-all old-buffer (window-prev-buffers window)))
2599 (set-window-next-buffers window (delq old-buffer next-buffers)))
2600 ;; Move `old-buffer' to head of WINDOW's restored list of next
2601 ;; buffers.
2602 (set-window-next-buffers
2603 window (cons old-buffer (delq old-buffer next-buffers)))))
2605 ;; Remove killed buffers from WINDOW's previous and next buffers.
2606 (when killed-buffers
2607 (dolist (buffer killed-buffers)
2608 (set-window-prev-buffers
2609 window (assq-delete-all buffer (window-prev-buffers window)))
2610 (set-window-next-buffers
2611 window (delq buffer (window-next-buffers window)))))
2613 ;; Return new-buffer.
2614 new-buffer))
2616 (defun switch-to-next-buffer (&optional window)
2617 "In WINDOW switch to next buffer.
2618 WINDOW must be a live window and defaults to the selected one."
2619 (interactive)
2620 (let* ((window (normalize-live-window window))
2621 (old-buffer (window-buffer window))
2622 (next-buffers (window-next-buffers window))
2623 new-buffer entry killed-buffers)
2624 (when (window-dedicated-p window)
2625 (error "Window %s is dedicated to buffer %s" window old-buffer))
2627 (catch 'found
2628 ;; Scan WINDOW's next buffers first.
2629 (dolist (buffer next-buffers)
2630 (when (and (or (buffer-live-p buffer)
2631 (not (setq killed-buffers
2632 (cons buffer killed-buffers))))
2633 (not (eq buffer old-buffer))
2634 (setq entry (assq buffer (window-prev-buffers window))))
2635 (setq new-buffer buffer)
2636 (set-window-buffer-start-and-point
2637 window new-buffer (nth 1 entry) (nth 2 entry))
2638 (throw 'found t)))
2639 ;; Scan the buffer list of WINDOW's frame next, skipping previous
2640 ;; buffers entries.
2641 (dolist (buffer (buffer-list (window-frame window)))
2642 (when (and (buffer-live-p buffer) (not (eq buffer old-buffer))
2643 (not (eq (aref (buffer-name buffer) 0) ?\s))
2644 (not (assq buffer (window-prev-buffers window))))
2645 (setq new-buffer buffer)
2646 (set-window-buffer-start-and-point window new-buffer)
2647 (throw 'found t)))
2648 ;; Scan WINDOW's reverted previous buffers last (must not use
2649 ;; nreverse here!)
2650 (dolist (entry (reverse (window-prev-buffers window)))
2651 (when (and (setq new-buffer (car entry))
2652 (or (buffer-live-p new-buffer)
2653 (not (setq killed-buffers
2654 (cons new-buffer killed-buffers))))
2655 (not (eq new-buffer old-buffer)))
2656 (set-window-buffer-start-and-point
2657 window new-buffer (nth 1 entry) (nth 2 entry))
2658 (throw 'found t))))
2660 ;; Remove `new-buffer' from and restore WINDOW's next buffers.
2661 (set-window-next-buffers window (delq new-buffer next-buffers))
2663 ;; Remove killed buffers from WINDOW's previous and next buffers.
2664 (when killed-buffers
2665 (dolist (buffer killed-buffers)
2666 (set-window-prev-buffers
2667 window (assq-delete-all buffer (window-prev-buffers window)))
2668 (set-window-next-buffers
2669 window (delq buffer (window-next-buffers window)))))
2671 ;; Return new-buffer.
2672 new-buffer))
2674 (defun get-next-valid-buffer (list &optional buffer visible-ok frame)
2675 "Search LIST for a valid buffer to display in FRAME.
2676 Return nil when all buffers in LIST are undesirable for display,
2677 otherwise return the first suitable buffer in LIST.
2679 Buffers not visible in windows are preferred to visible buffers,
2680 unless VISIBLE-OK is non-nil.
2681 If the optional argument FRAME is nil, it defaults to the selected frame.
2682 If BUFFER is non-nil, ignore occurrences of that buffer in LIST."
2683 ;; This logic is more or less copied from other-buffer.
2684 (setq frame (or frame (selected-frame)))
2685 (let ((pred (frame-parameter frame 'buffer-predicate))
2686 found buf)
2687 (while (and (not found) list)
2688 (setq buf (car list))
2689 (if (and (not (eq buffer buf))
2690 (buffer-live-p buf)
2691 (or (null pred) (funcall pred buf))
2692 (not (eq (aref (buffer-name buf) 0) ?\s))
2693 (or visible-ok (null (get-buffer-window buf 'visible))))
2694 (setq found buf)
2695 (setq list (cdr list))))
2696 (car list)))
2698 (defun last-buffer (&optional buffer visible-ok frame)
2699 "Return the last buffer in FRAME's buffer list.
2700 If BUFFER is the last buffer, return the preceding buffer
2701 instead. Buffers not visible in windows are preferred to visible
2702 buffers, unless optional argument VISIBLE-OK is non-nil.
2703 Optional third argument FRAME nil or omitted means use the
2704 selected frame's buffer list. If no such buffer exists, return
2705 the buffer `*scratch*', creating it if necessary."
2706 (setq frame (or frame (selected-frame)))
2707 (or (get-next-valid-buffer (nreverse (buffer-list frame))
2708 buffer visible-ok frame)
2709 (get-buffer "*scratch*")
2710 (let ((scratch (get-buffer-create "*scratch*")))
2711 (set-buffer-major-mode scratch)
2712 scratch)))
2714 (defun bury-buffer (&optional buffer-or-name)
2715 "Put BUFFER-OR-NAME at the end of the list of all buffers.
2716 There it is the least likely candidate for `other-buffer' to
2717 return; thus, the least likely buffer for \\[switch-to-buffer] to
2718 select by default.
2720 You can specify a buffer name as BUFFER-OR-NAME, or an actual
2721 buffer object. If BUFFER-OR-NAME is nil or omitted, bury the
2722 current buffer. Also, if BUFFER-OR-NAME is nil or omitted,
2723 remove the current buffer from the selected window if it is
2724 displayed there."
2725 (interactive)
2726 (let* ((buffer (normalize-live-buffer buffer-or-name)))
2727 ;; If `buffer-or-name' is not on the selected frame we unrecord it
2728 ;; although it's not "here" (call it a feature).
2729 (unrecord-buffer buffer)
2730 ;; Handle case where `buffer-or-name' is nil and the current buffer
2731 ;; is shown in the selected window.
2732 (cond
2733 ((or buffer-or-name (not (eq buffer (window-buffer)))))
2734 ((not (window-dedicated-p))
2735 (switch-to-prev-buffer nil 'bury))
2736 ((frame-root-window-p (selected-window))
2737 (iconify-frame (window-frame (selected-window))))
2738 ((window-deletable-p)
2739 (delete-window)))
2740 ;; Always return nil.
2741 nil))
2743 (defun unbury-buffer ()
2744 "Switch to the last buffer in the buffer list."
2745 (interactive)
2746 (switch-to-buffer (last-buffer)))
2748 (defun next-buffer ()
2749 "In selected window switch to next buffer."
2750 (interactive)
2751 (switch-to-next-buffer))
2753 (defun previous-buffer ()
2754 "In selected window switch to previous buffer."
2755 (interactive)
2756 (switch-to-prev-buffer))
2758 (defun delete-windows-on (&optional buffer-or-name frame)
2759 "Delete all windows showing BUFFER-OR-NAME.
2760 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
2761 and defaults to the current buffer.
2763 The following non-nil values of the optional argument FRAME
2764 have special meanings:
2766 - t means consider all windows on the selected frame only.
2768 - `visible' means consider all windows on all visible frames.
2770 - 0 (the number zero) means consider all windows on all visible
2771 and iconified frames.
2773 - A frame means consider all windows on that frame only.
2775 Any other value of FRAME means consider all windows on all
2776 frames.
2778 When a window showing BUFFER-OR-NAME is dedicated and the only
2779 window of its frame, that frame is deleted when there are other
2780 frames left."
2781 (interactive "BDelete windows on (buffer):\nP")
2782 (let ((buffer (normalize-live-buffer buffer-or-name))
2783 ;; Handle the "inverted" meaning of the FRAME argument wrt other
2784 ;; `window-list-1' based function.
2785 (all-frames (cond ((not frame) t) ((eq frame t) nil) (t frame))))
2786 (dolist (window (window-list-1 nil nil all-frames))
2787 (if (eq (window-buffer window) buffer)
2788 (let ((deletable (window-deletable-p window)))
2789 (cond
2790 ((eq deletable 'frame)
2791 ;; Delete frame.
2792 (delete-frame (window-frame window)))
2793 (deletable
2794 ;; Delete window only.
2795 (delete-window window))
2797 ;; In window switch to previous buffer.
2798 (set-window-dedicated-p window nil)
2799 (switch-to-prev-buffer window 'bury))))
2800 ;; If a window doesn't show BUFFER, unrecord it nevertheless.
2801 (unrecord-window-buffer window buffer)))))
2803 (defun replace-buffer-in-windows (&optional buffer-or-name)
2804 "Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2805 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
2806 and defaults to the current buffer.
2808 When a window showing BUFFER-OR-NAME is dedicated that window is
2809 deleted. If that window is the only window on its frame, that
2810 frame is deleted too when there are other frames left. If there
2811 are no other frames left, some other buffer is displayed in that
2812 window.
2814 This function removes the buffer denoted by BUFFER-OR-NAME from
2815 all window-local buffer lists."
2816 (let ((buffer (normalize-live-buffer buffer-or-name)))
2817 (dolist (window (window-list-1 nil nil t))
2818 (if (eq (window-buffer window) buffer)
2819 (let ((deletable (window-deletable-p window)))
2820 (cond
2821 ((eq deletable 'frame)
2822 ;; Delete frame.
2823 (delete-frame (window-frame window)))
2824 ((and (window-dedicated-p window) deletable)
2825 ;; Delete window.
2826 (delete-window window))
2828 ;; Switch to another buffer in window.
2829 (set-window-dedicated-p window nil)
2830 (switch-to-prev-buffer window 'kill))))
2831 ;; Unrecord BUFFER in WINDOW.
2832 (unrecord-window-buffer window buffer)))))
2834 (defun quit-restore-window (&optional window kill)
2835 "Quit WINDOW in some way.
2836 WINDOW must be a live window and defaults to the selected window.
2837 Return nil.
2839 According to information stored in WINDOW's `quit-restore' window
2840 parameter either \(1) delete WINDOW and its frame, \(2) delete
2841 WINDOW, \(3) restore the buffer previously displayed in WINDOW,
2842 or \(4) make WINDOW display some other buffer than the present
2843 one. If non-nil, reset `quit-restore' parameter to nil.
2845 Optional argument KILL non-nil means in addition kill WINDOW's
2846 buffer. If KILL is nil, put WINDOW's buffer at the end of the
2847 buffer list. Interactively, KILL is the prefix argument."
2848 (interactive "i\nP")
2849 (setq window (normalize-live-window window))
2850 (let ((buffer (window-buffer window))
2851 (quit-restore (window-parameter window 'quit-restore))
2852 deletable)
2853 (cond
2854 ((and (or (and (memq (car-safe quit-restore) '(new-window new-frame))
2855 ;; Check that WINDOW's buffer is still the same.
2856 (eq (window-buffer window) (nth 1 quit-restore)))
2857 (window-dedicated-p window))
2858 (setq deletable (window-deletable-p window)))
2859 ;; WINDOW can be deleted.
2860 (unrecord-buffer buffer)
2861 (if (eq deletable 'frame)
2862 ;; WINDOW's frame can be deleted.
2863 (delete-frame (window-frame window))
2864 ;; Just delete WINDOW.
2865 (delete-window window))
2866 ;; If the previously selected window is still alive, select it.
2867 (when (window-live-p (nth 2 quit-restore))
2868 (select-window (nth 2 quit-restore))))
2869 ((and (buffer-live-p (nth 0 quit-restore))
2870 ;; The buffer currently shown in WINDOW must still be the
2871 ;; buffer shown when its `quit-restore' parameter was created
2872 ;; in the first place. Leave WINDOW's quit-restore parameter
2873 ;; alone, it can be reused later.
2874 (eq (window-buffer window) (nth 3 quit-restore)))
2875 ;; Unrecord buffer.
2876 (unrecord-buffer buffer)
2877 (unrecord-window-buffer window buffer)
2878 ;; Display buffer stored in the quit-restore parameter.
2879 (set-window-dedicated-p window nil)
2880 (set-window-buffer window (nth 0 quit-restore))
2881 (set-window-start window (nth 1 quit-restore))
2882 (set-window-point window (nth 2 quit-restore))
2883 (unless (= (nth 4 quit-restore) (window-total-size window))
2884 (resize-window
2885 window (- (nth 4 quit-restore) (window-total-size window))))
2886 (set-window-parameter window 'quit-restore nil)
2887 (when (window-live-p (nth 5 quit-restore))
2888 (select-window (nth 5 quit-restore))))
2890 ;; Otherwise, show another buffer in WINDOW and reset the
2891 ;; quit-restore parameter.
2892 (set-window-parameter window 'quit-restore nil)
2893 (unrecord-buffer buffer)
2894 (switch-to-prev-buffer window 'bury-or-kill)))
2896 ;; Kill WINDOW's old-buffer if requested
2897 (when kill (kill-buffer buffer))
2898 nil))
2900 ;;; Splitting windows.
2901 (defsubst window-split-min-size (&optional horflag)
2902 "Return minimum height of any window.
2903 Optional argument HORFLAG non-nil means return minimum width."
2904 (if horflag
2905 (max window-min-width window-safe-min-width)
2906 (max window-min-height window-safe-min-height)))
2908 (defun split-window (&optional window size horizontal)
2909 "Create a new window adjacent to WINDOW.
2910 WINDOW can be any window and defaults to the selected one. If
2911 WINDOW was selected before invoking this function, it remains
2912 selected. Return the new window which is always a live window.
2914 Optional argument SIZE a positive number means make WINDOW SIZE
2915 lines/columns tall. If SIZE is negative, make the new window
2916 -SIZE lines/columns tall. If and only if SIZE is non-nil, its
2917 absolute value can be less than `window-min-height' or
2918 `window-min-width'; so this command can make a new window as
2919 small as one line or two columns. SIZE defaults to half of
2920 WINDOW's size. The variable `window-splits' determines whether
2921 the size of other windows is affected by this function.
2923 Optional third argument HORIZONTAL nil (or `below') specifies
2924 that the new window shall be located below WINDOW. HORIZONTAL
2925 `above' means the new window shall be located above WINDOW. In
2926 both cases SIZE specifies the new number of lines for WINDOW \(or
2927 the new window if SIZE is negative) including space reserved for
2928 the mode and/or header line.
2930 HORIZONTAL t (or `right') specifies that the new window shall be
2931 located on the right side of WINDOW. HORIZONTAL `left' means the
2932 new window shall be located on the left of WINDOW. In both cases
2933 SIZE specifies the new number of columns for WINDOW \(or the new
2934 window provided SIZE is negative) including space reserved for
2935 fringes and the scrollbar or a divider column. Any other non-nil
2936 value for HORIZONTAL is currently handled like t (or `right').
2938 If WINDOW is a component of a compound window \"split\" the root
2939 of the compound window instead. The new window does not become a
2940 member of the compound window. If WINDOW is a main window of a
2941 window group, the new window becomes a main window in that window
2942 group. If WINDOW is a non-main component of a window group
2943 signal an error.
2945 If you split a live window, properties of the new window like
2946 margins and scrollbars are inherited from WINDOW. If you split
2947 an internal window, these properties as well as the buffer
2948 displayed in the new window are inherited from the selected
2949 window on WINDOW's frame."
2950 (interactive "i")
2951 (setq window (normalize-any-window window))
2952 (let* ((horflag (and horizontal (not (memq horizontal '(below above)))))
2953 (function (window-parameter window 'split-window))
2954 ;; Rebind this locally since in some cases we do have to nest.
2955 (window-splits window-splits)
2956 ;; COMPOSITE non-nil means WINDOW is part of a composite
2957 ;; window. TYPE is the type of the composite window (either
2958 ;; `compound' or `group'). ROLE is the role of WINDOW within
2959 ;; the composite window (either `main', `support', or t). ROOT
2960 ;; is the root window of the composite window.
2961 (composite (window-parameter window 'composite))
2962 (type (car-safe composite))
2963 (role (cdr-safe composite))
2964 (root (and composite (composite-root-window window)))
2965 old-composite new-root new-main)
2966 (catch 'done
2967 (cond
2968 ;; Ignore window parameters if `ignore-window-parameters' tells
2969 ;; so or the `split-window' window parameter equals t.
2970 ((or (not (memq ignore-window-parameters '(nil post)))
2971 (eq function t)))
2972 ((functionp function)
2973 ;; The `split-window' parameter specifies the function to call
2974 ;; instead. If this is `ignore', WINDOW won't be split.
2975 (throw 'done (funcall function window size horizontal)))
2976 ((and (not composite) (window-parameter window 'group)
2977 (window-live-p window))
2978 ;; WINDOW is a live group root window and not part of a
2979 ;; composite window so we need a new group root window. Note
2980 ;; that if WINDOW is also the root of a compound window, that
2981 ;; part remains unaffected by what we do here - WINDOW remains
2982 ;; root of the compound window which is now a component of a
2983 ;; window group.
2984 (setq window-splits 'nest)
2985 (setq new-root t))
2986 (composite
2987 (cond
2988 ((or (not root) (not type) (not role))
2989 ;; Something is broken in this composite window. Signal a
2990 ;; message but let the split pass through (we might signal
2991 ;; an error here but for everday work this is too nasty).
2992 (message "Broken component %s of composite window" window))
2993 ((eq type 'compound)
2994 ;; In a compound window split the root window.
2995 (throw 'done (split-window root size horizontal)))
2996 ((eq type 'group)
2997 (cond
2998 ((not (eq role 'main))
2999 ;; In a window group we are only allowed to split main
3000 ;; windows. We might swallow this error silently.
3001 (error "Cannot split non-main window %s in a window group" window))
3002 ((or (not (window-parent window)) ; Should have been handled above.
3003 (not (eq (composite-lowest-child-role (window-parent window))
3004 'main)))
3005 (setq new-main t)
3006 ;; We must nest since otherwise we might end up with a
3007 ;; window group having two dominating main windows.
3008 (setq window-splits 'nest)))))))
3010 ;; The following line is hopefully not needed ...
3011 ;; (setq window-splits (if (eq window root) 'nest window-splits))
3012 (let* ((frame (window-frame window))
3013 (parent (window-parent window))
3014 ;; Size calculations.
3015 (parent-size
3016 (when parent (window-total-size parent horflag)))
3017 ;; Bind `old-size' to the current size of WINDOW and
3018 ;; `new-size' to the size of the new window.
3019 (old-size (window-total-size window horflag))
3020 (resize
3021 (and (eq window-splits 'resize)
3022 ;; Resize makes sense in iso-combinations only.
3023 (window-iso-combined-p window horflag)
3024 (or (not size) (< size 0)
3025 ;; If SIZE is a non-negative integer, we cannot
3026 ;; resize, bind `window-splits' to 'nest instead
3027 ;; to make sure that subsequent window deletions
3028 ;; are handled correctly.
3029 (and (setq window-splits 'nest) nil))))
3030 (new-size
3031 (cond
3032 ((not size)
3033 (max (window-split-min-size horflag)
3034 (if resize
3035 ;; For a "resize" split try to give the new
3036 ;; window a fitting size (which must be at least
3037 ;; as large as what we can get at all).
3038 (min (- parent-size
3039 (window-min-size parent horflag))
3040 (/ parent-size
3041 (1+ (window-iso-combinations parent horflag))))
3042 ;; Else try to give the new window half the size of
3043 ;; WINDOW.
3044 (/ old-size 2))))
3045 ((>= size 0)
3046 ;; SIZE non-negative specifies the new size of WINDOW.
3048 ;; Note: Specifying a non-negative SIZE is practically
3049 ;; always doen to have a workaround for making the new
3050 ;; window appear above or on the left of the new window
3051 ;; (the ispell window is a typical example of that). In
3052 ;; all these cases the HORIZONTAL argument should be set
3053 ;; to 'above or 'left in order to support the 'resize
3054 ;; option.
3055 (- old-size size))
3057 ;; SIZE negative specifies the size of the new window.
3058 (- size))))
3059 (root (window-parameter window 'root)))
3060 ;; Check the sizes.
3061 (cond
3062 ((not size)
3063 (cond
3064 (resize
3065 ;; Size unspecified, resizing.
3066 (when (and (not (window-sizable-p parent (- new-size) horflag))
3067 ;; Try agin with minimum acceptable size.
3068 (setq new-size
3069 (max new-size
3070 (window-split-min-size horflag)))
3071 (not (window-sizable-p parent (- new-size) horflag)))
3072 (error "Cannot resize %s" parent)))
3073 ((> (+ new-size (window-min-size window horflag)) old-size)
3074 ;; Size unspecified, no resizing.
3075 (error "Cannot resize %s" window))))
3076 ((and (>= size 0)
3077 (or (>= size old-size)
3078 (< new-size (if horflag
3079 window-safe-min-width
3080 window-safe-min-width))))
3081 ;; Size specified as new size of old window. If the new size
3082 ;; is larger than the old size or the size of the new window
3083 ;; would be less than the safe minimum signal an error.
3084 (error "Cannot resize %s" window))
3085 (resize
3086 ;; Size specified, resizing.
3087 (unless (window-sizable-p parent (- new-size) horflag)
3088 ;; If we cannot resize the parent give up.
3089 (error "Cannot resize %s" parent)))
3090 ((or (< new-size
3091 (if horflag window-safe-min-width window-safe-min-height))
3092 (< (- old-size new-size)
3093 (if horflag window-safe-min-width window-safe-min-height)))
3094 (error "Cannot resize %s" window)))
3096 (resize-window-reset (window-frame window) horflag)
3097 (cond
3098 (resize
3099 ;; Try to get space from OLD's siblings. We could go "up" and
3100 ;; try getting additional space from surrounding windows but we
3101 ;; won't be able to return space to those windows when we delete
3102 ;; the one we create here. Hence we do not go up.
3103 (resize-subwindows parent (- new-size) horflag)
3104 (let* ((parent-size (window-total-size parent horflag))
3105 (sub (window-child parent)))
3106 ;; Assign new normal sizes.
3107 (while sub
3108 (resize-window-normal
3109 sub (/ (* (float (window-normal-size sub horflag))
3110 (- parent-size new-size))
3111 parent-size))
3112 (setq sub (window-right sub)))))
3113 ((eq window-splits 'nest)
3114 ;; Get entire space from WINDOW making sure that a new parent
3115 ;; windows gets created.
3116 (resize-window-total window (- old-size new-size))
3117 (resize-this-window window (- new-size) horflag)
3118 (resize-window-normal
3119 window (/ (float (window-new-total-size window)) old-size)))
3121 ;; Get entire space from WINDOW making a new parent window only
3122 ;; if we need one.
3123 (resize-window-total window (- old-size new-size))
3124 (resize-this-window window (- new-size) horflag)
3125 (resize-window-normal
3126 window (/ (float (window-new-total-size window))
3127 (window-total-size (window-parent window) horflag)))))
3129 (let* ((new (split-window-internal window new-size horizontal))
3130 (new-parent (window-parent new)))
3131 (when (memq ignore-window-parameters '(nil pre))
3132 (cond
3133 ((and new-root (not (eq parent new-parent)))
3134 ;; `new-parent' becomes the new group root window
3135 ;; inheriting WINDOW's composite status. WINDOW and `new'
3136 ;; become main windows of that group.
3137 (set-window-parameter new-parent 'group t)
3138 (set-window-parameter new-parent 'composite composite)
3139 (set-window-parameter window 'group nil)
3140 (set-window-parameter window 'composite (cons 'group 'main))
3141 (set-window-parameter new 'composite (cons 'group 'main)))
3142 ((and new-main (not (eq parent new-parent)))
3143 ;; `new-parent' becomes the new dominating main window of
3144 ;; WINDOW's group.
3145 (set-window-parameter new-parent 'composite (cons 'group 'main))
3146 (set-window-parameter window 'composite (cons 'group 'main))
3147 (set-window-parameter new 'composite (cons 'group 'main)))
3148 (composite
3149 ;; `new' inherits parameters from WINDOW.
3150 (set-window-parameter new 'composite composite)
3151 (when (not (eq parent new-parent))
3152 ;; `new-parent' "inherits" the parameters as well
3153 (set-window-parameter new-parent 'composite composite)))))
3154 ;; We have to check once more how often these hooks are run.
3155 (run-window-configuration-change-hook frame)
3156 ;; Return the new window.
3157 new)))))
3159 ;; I think this should be the default; I think people will prefer it--rms.
3160 (defcustom split-window-keep-point t
3161 "If non-nil, \\[split-window-vertically] keeps the original point \
3162 in both children.
3163 This is often more convenient for editing.
3164 If nil, adjust point in each of the two windows to minimize redisplay.
3165 This is convenient on slow terminals, but point can move strangely.
3167 This option applies only to `split-window-vertically' and
3168 functions that call it. `split-window' always keeps the original
3169 point in both children."
3170 :type 'boolean
3171 :group 'windows)
3173 (defun split-window-vertically (&optional size)
3174 "Split selected window into two windows, one above the other.
3175 The upper window gets SIZE lines and the lower one gets the rest.
3176 SIZE negative means the lower window gets -SIZE lines and the
3177 upper one the rest. With no argument, split windows equally or
3178 close to it. Both windows display the same buffer, now current.
3180 If the variable `split-window-keep-point' is non-nil, both new
3181 windows will get the same value of point as the selected window.
3182 This is often more convenient for editing. The upper window is
3183 the selected window.
3185 Otherwise, we choose window starts so as to minimize the amount of
3186 redisplay; this is convenient on slow terminals. The new selected
3187 window is the one that the current value of point appears in. The
3188 value of point can change if the text around point is hidden by the
3189 new mode line.
3191 Regardless of the value of `split-window-keep-point', the upper
3192 window is the original one and the return value is the new, lower
3193 window."
3194 (interactive "P")
3195 (let ((old-window (selected-window))
3196 (old-point (point))
3197 (size (and size (prefix-numeric-value size)))
3198 moved-by-window-height moved new-window bottom)
3199 (when (and size (< size 0) (< (- size) window-min-height))
3200 ;; `split-window' would not signal an error here.
3201 (error "Size of new window too small"))
3202 (setq new-window (split-window nil size))
3203 (unless split-window-keep-point
3204 (with-current-buffer (window-buffer)
3205 (goto-char (window-start))
3206 (setq moved (vertical-motion (window-height)))
3207 (set-window-start new-window (point))
3208 (when (> (point) (window-point new-window))
3209 (set-window-point new-window (point)))
3210 (when (= moved (window-height))
3211 (setq moved-by-window-height t)
3212 (vertical-motion -1))
3213 (setq bottom (point)))
3214 (and moved-by-window-height
3215 (<= bottom (point))
3216 (set-window-point old-window (1- bottom)))
3217 (and moved-by-window-height
3218 (<= (window-start new-window) old-point)
3219 (set-window-point new-window old-point)
3220 (select-window new-window)))
3221 ;; Always copy quit-restore parameter in interactive use.
3222 (let ((quit-restore (window-parameter old-window 'quit-restore)))
3223 (when quit-restore
3224 (set-window-parameter new-window 'quit-restore quit-restore)))
3225 new-window))
3227 (defun split-window-horizontally (&optional size)
3228 "Split selected window into two windows side by side.
3229 The selected window becomes the left one and gets SIZE columns.
3230 SIZE negative means the right window gets -SIZE lines.
3232 SIZE includes the width of the window's scroll bar; if there are
3233 no scroll bars, it includes the width of the divider column to
3234 the window's right, if any. SIZE omitted or nil means split
3235 window equally.
3237 The selected window remains selected. Return the new window."
3238 (interactive "P")
3239 (let ((old-window (selected-window))
3240 (size (and size (prefix-numeric-value size)))
3241 new-window)
3242 (when (and size (< size 0) (< (- size) window-min-width))
3243 ;; `split-window' would not signal an error here.
3244 (error "Size of new window too small"))
3245 (setq new-window (split-window nil size t))
3246 ;; Always copy quit-restore parameter in interactive use.
3247 (let ((quit-restore (window-parameter old-window 'quit-restore)))
3248 (when quit-restore
3249 (set-window-parameter new-window 'quit-restore quit-restore)))
3250 new-window))
3252 ;;; Composite windows.
3253 (defun make-compound-window (&optional window main size horizontal)
3254 "Make WINDOW the main window of a new compound window.
3255 This function creates a new internal window with WINDOW and a new
3256 leaf window as its only children. WINDOW must be a leaf window
3257 and defaults to the selected window.
3259 Optional argument MAIN non-nil makes the new leaf window a main
3260 window. MAIN nil or not provided means the new leaf window
3261 becomes a support window. WINDOW itself becomes a main window.
3263 Optional arguments SIZE and HORIZONTAL are as for `split-window'.
3265 Return the new leaf window."
3266 (setq window (normalize-any-window window))
3267 (unless (or (window-live-p window) (composite-root-window-p window))
3268 (error "Window %s must be live or a composite root window" window))
3269 (let* ((composite (window-parameter window 'composite))
3270 ;; FORCE and NEST.
3271 (ignore-window-parameters t)
3272 (window-splits 'nest)
3273 (new (split-window window size horizontal))
3274 (new-parent (window-parent new)))
3275 (set-window-parameter new-parent 'compound t)
3276 (when composite (set-window-parameter new-parent 'composite composite))
3277 (set-window-parameter window 'composite (cons 'compound 'main))
3278 (set-window-parameter
3279 new 'composite (cons 'compound (if main 'main 'support)))
3280 new))
3282 (defun make-window-group (&optional window)
3283 "Make WINDOW main and root window of a new window group.
3284 WINDOW must be a live window and defaults to the selected one.
3285 Return WINDOW."
3286 (setq window (normalize-live-window window))
3287 (set-window-parameter window 'composite (cons 'group 'main)))
3289 (defun make-support-window (window support &optional size horizontal)
3290 "Add support window of type SUPPORT to WINDOW."
3291 (let* ((compound (window-parameter window 'compound))
3292 (group (window-parameter window 'group))
3293 (composite (window-parameter window 'composite))
3294 (type (car-safe composite))
3295 (role (cdr-safe composite))
3296 ;; `type' is the type of the composite window (either
3297 ;; `compound' or `group'). `role' is the role of WINDOW within
3298 ;; the composite window (either `main', `support', or t).
3299 (root (when composite (composite-root-window window)))
3300 (parent (window-parent window))
3301 (ignore-window-parameters t)
3302 (window-splits 'nest)
3303 new new-parent)
3304 (cond
3305 ((not (memq support '(compound group)))
3306 (error "Invalid support argument %s" support))
3307 ((and (eq support 'compound) (not compound) (not (eq type 'compound)))
3308 (error "Window %s is not a component of a compound window" window))
3309 ((and (eq support 'group) (not group) (not (eq type 'group)))
3310 (error "Window %s is not a component of a window group" window))
3311 ((and (eq type 'main) (not (eq window (composite-major-window window))))
3312 (error "Can't embed support window in main window")))
3313 (setq new (split-window window size horizontal))
3314 (unless (eq parent (window-parent window))
3315 (setq new-parent (window-parent window)))
3316 (cond
3317 ;; This conditional looks incredibly tedious but let's keep the
3318 ;; distinct cases self-contained to avoid further confusion.
3319 ((and compound (eq support 'compound))
3320 (when new-parent
3321 ;; `new-parent' inherits the compound status of `window'
3322 (set-window-parameter new-parent 'compound t)
3323 (set-window-parameter window 'compound nil)
3324 (when composite
3325 ;; `new-parent' inherits the composite status of `window'.
3326 (set-window-parameter new-parent 'composite composite)
3327 (set-window-parameter
3328 ;; Give `window' the highest role of its children.
3329 window 'composite (cons 'compound
3330 (composite-lowest-child-role window)))))
3331 (when group
3332 ;; `new-parent' does not inherit the group status of `window'
3333 ;; (but make sure `window' retains it).
3334 (set-window-parameter window 'group t))
3335 (set-window-parameter new 'composite (cons 'compound 'support)))
3336 ((and group (eq support 'group))
3337 (when new-parent
3338 ;; `new-parent' inherits the group status of `window'
3339 (set-window-parameter new-parent 'group t)
3340 (set-window-parameter window 'group nil)
3341 (when composite
3342 ;; `new-parent' inherits the composite status of `window'.
3343 (set-window-parameter new-parent 'composite composite)
3344 (set-window-parameter
3345 ;; Give `window' the highest role of its children.
3346 window 'composite (cons 'group
3347 (composite-lowest-child-role window)))))
3348 (when compound
3349 ;; `new-parent' does not inherit the compound status of `window'
3350 ;; (but make sure `window' retains it).
3351 (set-window-parameter window 'compound t))
3352 (set-window-parameter new 'composite (cons 'group 'support)))
3353 ((and (eq type 'compound) (eq support 'compound))
3354 (cond
3355 (new-parent
3356 (let ((role (if (eq role 'support) 'support t)))
3357 (set-window-parameter new-parent 'composite (cons 'compound role))))
3358 ((not (compound-window-p parent))
3359 (let ((role (if (composite-support-window-p parent) 'support t)))
3360 (set-window-parameter parent 'composite (cons 'compound role)))))
3361 (when group
3362 ;; `new-parent' does not inherit the group status of `window'
3363 ;; (but make sure `window' retains it).
3364 (set-window-parameter window 'group t))
3365 (set-window-parameter window 'composite composite)
3366 (set-window-parameter new 'composite (cons 'compound 'support)))
3367 ((and (eq type 'group) (eq support 'group))
3368 (cond
3369 (new-parent
3370 (let ((role (if (eq role 'support) 'support t)))
3371 (set-window-parameter new-parent 'composite (cons 'group role))))
3372 ((not (compound-window-p parent))
3373 (let ((role (if (composite-support-window-p parent) 'support t)))
3374 (set-window-parameter parent 'composite (cons 'group role)))))
3375 (when compound
3376 ;; `new-parent' does not inherit the compound status of `window'
3377 ;; (but make sure `window' retains it).
3378 (set-window-parameter window 'compound t))
3379 (set-window-parameter window 'composite composite)
3380 (set-window-parameter new 'composite (cons 'group 'support))))
3381 new))
3383 ;;; Balancing windows.
3384 (defun balance-windows (&optional window-or-frame)
3385 "Balance the sizes of subwindows of WINDOW-OR-FRAME.
3386 WINDOW-OR-FRAME is optional and defaults to the selected frame.
3387 If WINDOW-OR-FRAME denotes a frame, balance the sizes of all
3388 subwindows of that frame's root window. If WINDOW-OR-FRAME
3389 denots a window, balance the sizes of all subwindows of that
3390 window."
3391 (interactive)
3392 (let* ((window
3393 (cond
3394 ((or (not window-or-frame)
3395 (frame-live-p window-or-frame))
3396 (frame-root-window window-or-frame))
3397 ((or (window-live-p window-or-frame)
3398 (window-child window-or-frame))
3399 window-or-frame)
3401 (error "Not a window or frame %s" window-or-frame))))
3402 (frame (window-frame window)))
3403 ;; Balance vertically.
3404 (resize-window-reset (window-frame window))
3405 (balance-windows-1 window)
3406 (resize-window-apply frame)
3407 ;; Balance horizontally.
3408 (resize-window-reset (window-frame window) t)
3409 (balance-windows-1 window t)
3410 (resize-window-apply frame t)))
3412 (defun balance-windows-1 (window &optional horizontal)
3413 "Subroutine of `balance-windows'."
3414 (if (window-child window)
3415 (let ((sub (window-child window)))
3416 (if (window-iso-combined-p sub horizontal)
3417 (balance-windows-2 window horizontal)
3418 (let ((size (window-new-total-size window)))
3419 (while sub
3420 (resize-window-total sub size)
3421 (balance-windows-1 sub horizontal)
3422 (setq sub (window-right sub))))))))
3424 (defun balance-windows-2 (window horizontal)
3425 "Subroutine of `balance-windows-1'.
3426 WINDOW must be an iso-combination."
3427 (let* ((first (window-child window))
3428 (sub first)
3429 (number-of-children 0)
3430 (parent-size (window-new-total-size window))
3431 (total-sum parent-size)
3432 found failed size sub-total sub-delta sub-amount rest)
3433 (while sub
3434 (setq number-of-children (1+ number-of-children))
3435 (when (window-size-fixed-p sub horizontal)
3436 (setq total-sum
3437 (- total-sum (window-total-size sub horizontal)))
3438 (resize-window-normal sub 'ignore))
3439 (setq sub (window-right sub)))
3441 (setq failed t)
3442 (while (and failed (> number-of-children 0))
3443 (setq size (/ total-sum number-of-children))
3444 (setq failed nil)
3445 (setq sub first)
3446 (while (and sub (not failed))
3447 ;; Ignore subwindows that should be ignored or are stuck.
3448 (unless (resize-subwindows-skip-p sub)
3449 (setq found t)
3450 (setq sub-total (window-total-size sub horizontal))
3451 (setq sub-delta (- size sub-total))
3452 (setq sub-amount
3453 (window-sizable sub sub-delta horizontal))
3454 ;; Register the new total size for this subwindow.
3455 (resize-window-total sub (+ sub-total sub-amount))
3456 (unless (= sub-amount sub-delta)
3457 (setq total-sum (- total-sum sub-total sub-amount))
3458 (setq number-of-children (1- number-of-children))
3459 ;; We failed and need a new round.
3460 (setq failed t)
3461 (resize-window-normal sub 'skip)))
3462 (setq sub (window-right sub))))
3464 (setq rest (% total-sum number-of-children))
3465 ;; Fix rounding by trying to enlarge non-stuck windows by one line
3466 ;; (column) until `rest' is zero.
3467 (setq sub first)
3468 (while (and sub (> rest 0))
3469 (unless (resize-subwindows-skip-p window)
3470 (resize-window-total sub 1 t)
3471 (setq rest (1- rest)))
3472 (setq sub (window-right sub)))
3474 ;; Fix rounding by trying to enlarge stuck windows by one line
3475 ;; (column) until `rest' equals zero.
3476 (setq sub first)
3477 (while (and sub (> rest 0))
3478 (unless (eq (window-new-normal-size sub) 'ignore)
3479 (resize-window-total sub 1 t)
3480 (setq rest (1- rest)))
3481 (setq sub (window-right sub)))
3483 (setq sub first)
3484 (while sub
3485 ;; Record new normal sizes.
3486 (resize-window-normal
3487 sub (/ (if (eq (window-new-normal-size sub) 'ignore)
3488 (window-total-size sub horizontal)
3489 (window-new-total-size sub))
3490 (float parent-size)))
3491 ;; Recursively balance each subwindow's subwindows.
3492 (balance-windows-1 sub horizontal)
3493 (setq sub (window-right sub)))))
3495 (defun window-fixed-size-p (&optional window direction)
3496 "Return t if WINDOW cannot be resized in DIRECTION.
3497 WINDOW defaults to the selected window. DIRECTION can be
3498 nil (i.e. any), `height' or `width'."
3499 (with-current-buffer (window-buffer window)
3500 (when (and (boundp 'window-size-fixed) window-size-fixed)
3501 (not (and direction
3502 (member (cons direction window-size-fixed)
3503 '((height . width) (width . height))))))))
3505 ;;; A different solution to balance-windows.
3506 (defvar window-area-factor 1
3507 "Factor by which the window area should be over-estimated.
3508 This is used by `balance-windows-area'.
3509 Changing this globally has no effect.")
3510 (make-variable-buffer-local 'window-area-factor)
3512 (defun balance-windows-area-adjust (window delta horizontal)
3513 "Wrapper around `resize-window' with error checking.
3514 Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
3515 ;; `resize-window' may fail if delta is too large.
3516 (while (>= (abs delta) 1)
3517 (condition-case err
3518 (progn
3519 (resize-window window delta horizontal)
3520 (setq delta 0))
3521 (error
3522 ;;(message "adjust: %s" (error-message-string err))
3523 (setq delta (/ delta 2))))))
3525 (defun balance-windows-area ()
3526 "Make all visible windows the same area (approximately).
3527 See also `window-area-factor' to change the relative size of
3528 specific buffers."
3529 (interactive)
3530 (let* ((unchanged 0) (carry 0) (round 0)
3531 ;; Remove fixed-size windows.
3532 (wins (delq nil (mapcar (lambda (win)
3533 (if (not (window-fixed-size-p win)) win))
3534 (window-list nil 'nomini))))
3535 (changelog nil)
3536 next)
3537 ;; Resizing a window changes the size of surrounding windows in complex
3538 ;; ways, so it's difficult to balance them all. The introduction of
3539 ;; `adjust-window-trailing-edge' made it a bit easier, but it is still
3540 ;; very difficult to do. `balance-window' above takes an off-line
3541 ;; approach: get the whole window tree, then balance it, then try to
3542 ;; adjust the windows so they fit the result.
3543 ;; Here, instead, we take a "local optimization" approach, where we just
3544 ;; go through all the windows several times until nothing needs to be
3545 ;; changed. The main problem with this approach is that it's difficult
3546 ;; to make sure it terminates, so we use some heuristic to try and break
3547 ;; off infinite loops.
3548 ;; After a round without any change, we allow a second, to give a chance
3549 ;; to the carry to propagate a minor imbalance from the end back to
3550 ;; the beginning.
3551 (while (< unchanged 2)
3552 ;; (message "New round")
3553 (setq unchanged (1+ unchanged) round (1+ round))
3554 (dolist (win wins)
3555 (setq next win)
3556 (while (progn (setq next (next-window next))
3557 (window-fixed-size-p next)))
3558 ;; (assert (eq next (or (cadr (member win wins)) (car wins))))
3559 (let* ((horiz
3560 (< (car (window-edges win)) (car (window-edges next))))
3561 (areadiff (/ (- (* (window-height next) (window-width next)
3562 (buffer-local-value 'window-area-factor
3563 (window-buffer next)))
3564 (* (window-height win) (window-width win)
3565 (buffer-local-value 'window-area-factor
3566 (window-buffer win))))
3567 (max (buffer-local-value 'window-area-factor
3568 (window-buffer win))
3569 (buffer-local-value 'window-area-factor
3570 (window-buffer next)))))
3571 (edgesize (if horiz
3572 (+ (window-height win) (window-height next))
3573 (+ (window-width win) (window-width next))))
3574 (diff (/ areadiff edgesize)))
3575 (when (zerop diff)
3576 ;; Maybe diff is actually closer to 1 than to 0.
3577 (setq diff (/ (* 3 areadiff) (* 2 edgesize))))
3578 (when (and (zerop diff) (not (zerop areadiff)))
3579 (setq diff (/ (+ areadiff carry) edgesize))
3580 ;; Change things smoothly.
3581 (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2))))
3582 (if (zerop diff)
3583 ;; Make sure negligible differences don't accumulate to
3584 ;; become significant.
3585 (setq carry (+ carry areadiff))
3586 ;; This used `adjust-window-trailing-edge' before and uses
3587 ;; `resize-window' now. Error wrapping is still needed.
3588 (balance-windows-area-adjust win diff horiz)
3589 ;; (sit-for 0.5)
3590 (let ((change (cons win (window-edges win))))
3591 ;; If the same change has been seen already for this window,
3592 ;; we're most likely in an endless loop, so don't count it as
3593 ;; a change.
3594 (unless (member change changelog)
3595 (push change changelog)
3596 (setq unchanged 0 carry 0)))))))
3597 ;; We've now basically balanced all the windows.
3598 ;; But there may be some minor off-by-one imbalance left over,
3599 ;; so let's do some fine tuning.
3600 ;; (bw-finetune wins)
3601 ;; (message "Done in %d rounds" round)
3605 ;;; Displaying buffers.
3606 (defgroup display-buffer nil
3607 "Displaying buffers in windows."
3608 :version "24.1"
3609 :group 'windows)
3611 (defcustom display-buffer-names nil
3612 "List associating buffer names with buffer display specifiers.
3613 The car of each element of this list specifies a set of buffer
3614 names. `display-buffer' displays a buffer whose name is a member
3615 of that set according to the display specifiers in the element's
3616 cdr \(note that elements are true lists).
3618 Valid display specifiers are symbols, cons cells, or lists.
3619 Buffer display specifiers that are symbols specify the location
3620 for showing the buffer. Three such specifiers are predefined:
3622 - `same-window' to preferably use the selected window,
3624 - `same-frame' to show the buffer on the selected frame, or
3626 - `other-frame' to show the buffer on another frame.
3628 Any other symbol with a function definition means to call that
3629 function to display the buffer. The function is called with two
3630 arguments - the buffer to display and a list of specifiers - and
3631 is supposed to display the buffer and return the window used for
3632 that purpose. The function is also responsible for giving the
3633 variable `display-buffer-window' and the
3634 `quit-restore' parameter of the window used a meaningful value.
3636 The remaining display specifiers are cons cells \(occasionally
3637 also true lists) whose components are listed below. The
3638 specifiers listed below are useful if the location specifier
3639 equals either `same-frame' or `other-frame':
3641 - `not-this-window' with a non-nil cdr can be used to specify
3642 that the selected window must not be used for displaying the
3643 buffer regardless of whether it shows that buffer or any other
3644 buffer.
3646 - `reuse-buffer-window' is used to specify whether a window
3647 currently showing the buffer may be reused and where to look
3648 for such a window. The possible values for the cdr are
3650 - `none', to never reuse a window showing the buffer,
3652 - nil, a reused window must be on the selected frame,
3654 - `visible', any such window must be on a visible frame,
3656 - 0 \(the number zero), meaning that any such window must be on
3657 a visible or iconified frame, and
3659 - t, the window may be on an arbitrary frame, including
3660 invisible ones.
3662 - `reuse-other-window' is used to specify whether a window
3663 currently _not_ showing the buffer may be reused and where to
3664 look for such a window. The possible values for the cdr are
3665 the same as for the `reuse-buffer-window' specifier.
3667 - `even-window-sizes' with a non-nil cdr means even out the sizes
3668 of a reused window and the selected window provided they (1)
3669 appear adjacent to each other and (2) the selected window is
3670 larger than the window chosen.
3672 The following display specifiers are useful if the location
3673 specifier equals 'same-frame:
3675 - `new-window' specifies whether a new window shall be made on
3676 the selected frame. For convenience, this specifier is
3677 represented by a true list. The cdr of the specifier is built
3678 from cons cells representing window/side pairings. The car of
3679 each cell identifies the window that shall be split. Possible
3680 values are `largest', `lru', `selected', `root' and `first' to
3681 split the largest, least recently used, selected, root or first
3682 window of the selected frame.
3684 The cdr specifies on which side of the window to split the new
3685 window shall appear and can be one of `below', `right',
3686 `above', or `left' with the obvious meanings. If the cdr is
3687 nil, the window is split in a fashion suitable for its current
3688 dimensions. If the cdr specifies a function, that function is
3689 called with two arguments - the window to split and a list of
3690 display specifiers. The function is supposed to split that
3691 window and return the new window.
3693 `display-buffer' scans these pairings until it can either
3694 produce a suitable window or fails. The default value for
3695 `display-buffer-regexps' contains (split-largest . nil) and
3696 (split-lru . nil) in order to make `display-buffer' try
3697 splitting the largest window first and, if that fails, the
3698 least recently used one.
3700 - The symbol `split-unsplittable-frame' with a non-nil cdr allows
3701 to make a new window on an unsplittable frame. This specifier
3702 should be used in special cases only since frames are usually
3703 made unsplittable in order to prevent `display-buffer' from
3704 splitting them.
3706 - `min-height' specifies the minimum height of a new window used
3707 for displaying the buffer. An integer number specifies the
3708 minimum number of lines of the window. A floating point number
3709 gives the minimum fraction of the window height with respect to
3710 the frame's root window. A new window will be made if and only
3711 if it can be made at least as high as specified by the number.
3713 - `min-width' specifies the minimum width of a new window used
3714 for displaying the buffer. An integer number specifies the
3715 minimum number of columns of the window. A floating point
3716 number gives the minimum fraction of the window width with
3717 respect to the frame's root window. A new window will be made
3718 if and only if it can be made at least as wide as specified by
3719 the number.
3721 - `adjust-height' with the following interpretations for the cdr:
3723 - nil means do not adjust the height of the new window.
3725 - A number specifying the desided height of the new window. An
3726 integer number specifies the minimum number of lines of the
3727 window. A floating point number gives the minimum fraction
3728 of the window height with respect to the frame's root window.
3730 - `even-window-heights' means to even the height of the new
3731 window with the height of the selected window provided these
3732 windows appear above each other.
3734 - If the cdr specifies a function, that function is called with
3735 one argument - the new window. The function is supposed to
3736 adjust the height of the window, its return value is ignored.
3737 Suitable functions are `shrink-window-if-larger-than-buffer'
3738 and `fit-window-to-buffer'.
3740 - `adjust-width' with the following interpretations for the cdr:
3742 - nil means do not adjust the width of the new window.
3744 - A number specifying the desided width of the new window. An
3745 integer number specifies the minimum number of columns of the
3746 window. A floating point number gives the minimum fraction
3747 of the window width with respect to the frame's root window.
3749 - `even-window-widths' means to even the wdith of the new
3750 window with the width of the selected window provided these
3751 windows appear besides ach other.
3753 - If the cdr specifies a function, that function is called with
3754 one argument - the new window. The function is supposed to
3755 adjust the width of the window, its return value is ignored.
3757 Observe that specifying `adjust-height' or `adjust-width' may
3758 override restrictions given by the `min-height' or `min-width'
3759 specifiers.
3761 The specifiers listed next are useful if the location specifier
3762 equals 'other-frame:
3764 - `not-this-frame' with a non-nil cdr means that the selected
3765 frame shall not be used for displaying the buffer.
3767 - `graphic-only' with a non-nil cdr means that a new frame shall
3768 be made on graphic displays only.
3770 - `popup-frame-function' together with a valid function as cdr
3771 specifies the function for creating a new frame. The default
3772 function is `make-frame'. The function is called with the
3773 parameters and values provided by the specifier described next.
3775 - `popup-frame-alist' followed by an arbitrary number of frame
3776 parameter/value pairs, each given as a cons cell, specifies the
3777 parameters passed to the popup frame function. For
3778 convenience, this specifier is not a cons cell but a list whose
3779 first element is the symbol `popup-frame-alist' and whose
3780 remaining elements are pairs of parameters and values.
3782 One specifier is useful with any of the 'same-window,
3783 'same-frame, 'other-frame location specifiers: `dedicated' with a
3784 non-nil cdr can be used to dedicate a new window to the buffer.
3785 The cdr is either
3787 - nil, to not dedicate the window to the buffer,
3789 - `weak', the window shall be weakly dedicated to its buffer, or
3791 - t, to strongly dedicate the window to the buffer.
3793 Usually, applications are free to override the specifiers of
3794 `display-buffer-names' by passing its own specifiers as second
3795 argument of `display-buffer'. For every `display-buffer-names'
3796 entry you can, however, add a cons cell whose car is the symbol
3797 `override' and whose cdr is non-nil, to explicitly override any
3798 value supplied by the application.
3800 Overriding specifiers supplied by the calling application is, in
3801 general, not advisable. It permits, for example, to change the
3802 semantics of a function like `switch-to-buffer-other-window' by
3803 using the location specifiers `same-window' or `other-frame'."
3804 :risky t
3805 :type
3806 '(repeat
3807 :offset 9
3808 (list
3809 :tag "Association"
3810 (repeat
3811 :tag "Buffer names"
3812 (string :format "%v\n" :size 24))
3813 (repeat
3814 :offset 9
3815 :tag "Display specifiers"
3816 :inline t
3817 (list
3818 :tag "Specifiers"
3819 :inline t
3820 :format "%v"
3821 (choice
3822 :tag "Locations"
3823 :inline t
3824 :help-echo "Choose a location for displaying the buffer(s)."
3825 :value (same-frame
3826 (reuse-buffer-window . nil)
3827 (even-window-sizes . t)
3828 (new-window (largest . nil) (lru . nil))
3829 (min-height . 24) (min-width . 60))
3830 :format "%[Location%] %v" :size 15
3832 ;; Same window.
3833 (list
3834 :tag "Same window"
3835 :format "%t%v"
3836 :inline t
3837 (const :format "\n" same-window)
3838 (set
3839 :format "%v" :inline t
3840 (cons
3841 :format "%v"
3842 (const :format "" dedicated)
3843 (choice
3844 :tag "Dedicate window to buffer" :value nil
3845 :help-echo "Mark window as dedicated to its buffer."
3846 :format "%[%t%] %v\n" :size 15
3847 (const :tag "Off" :format "%t" nil)
3848 (const :tag "Weak" :format "%t" weak)
3849 (const :tag "Strong" :format "%t" t)))))
3851 ;; Same frame.
3852 (list
3853 :tag "Same frame"
3854 :value (same-frame
3855 (reuse-buffer-window . nil)
3856 (even-window-sizes . t)
3857 (new-window (largest . nil) (lru . nil))
3858 (min-height . 24) (min-width . 60))
3859 :format "%t%v"
3860 :inline t
3861 (const :format "\n" same-frame)
3862 (set
3863 :format "%v" :inline t
3864 (cons
3865 :tag "Avoid selected window"
3866 :format "%v%t\n"
3867 (const :format "" not-this-window)
3868 (const :format "" t))
3869 (cons
3870 :format "%v"
3871 (const
3872 :format "" reuse-buffer-window)
3873 (choice
3874 :tag "Reuse buffer window"
3875 :help-echo "Frames to search for a window showing the buffer."
3876 :value nil :format "%[Reuse buffer window%] %v\n" :size 15
3877 (const :tag "None" :format "%t" none)
3878 (const :tag "Selected frame only" :format "%t" nil)
3879 (const :tag "Visible frames" :format "%t" visible)
3880 (const :tag "Visible and iconified frames" :format "%t" 0)
3881 (const :tag "All frames" :format "%t" t)))
3882 (cons
3883 :format "%v"
3884 (const
3885 :format "" reuse-other-window)
3886 (choice
3887 :tag "Reuse other window"
3888 :help-echo "Frames to search for a window not showing the buffer."
3889 :value nil :format "%[Reuse other window%] %v\n" :size 15
3890 (const :tag "None" :format "%t" none)
3891 (const :tag "Selected frame only" :format "%t" nil)
3892 (const :tag "Visible frames" :format "%t" visible)
3893 (const :tag "Visible and iconified frames" :format "%t" 0)
3894 (const :tag "All frames" :format "%t" t)))
3895 (cons
3896 :tag "Even window sizes"
3897 :format "%v%t\n"
3898 (const :format "" even-window-sizes)
3899 (const :format "" t))
3900 (list
3901 :format "%v"
3902 :value (new-window (largest . nil) (lru . nil))
3903 (const :format "" new-window)
3904 (repeat
3905 :inline t
3906 :tag "Window / Side pairings"
3907 (cons
3908 :format "%v"
3909 (choice
3910 :tag "Window" :help-echo "The window to split."
3911 :value largest :format "%[Window%] %v" :size 15
3912 (const :tag "Largest" :format "%t" largest)
3913 (const :tag "Least recently used" :format "%t" lru)
3914 (const :tag "Selected" :format "%t" selected)
3915 (const :tag "Root" :format "%t" root)
3916 (const :tag "First" :format "%t" first))
3917 (choice
3918 :tag "Side"
3919 :help-echo "The position of the new window with respect to the window to split."
3920 :value nil :format " %[Side%] %v" :size 15
3921 (const :tag "Dynamic" nil)
3922 (const :tag "Below" below)
3923 (const :tag "Right" right)
3924 (const :tag "Above" above)
3925 (const :tag "Left" left)
3926 (function
3927 :tag "Function" :format "%v\n" :size 25)))))
3928 (cons
3929 :tag "Make new window even if frame is unsplittable" :size 5
3930 :format "%v%t\n"
3931 (const :format "" split-unsplittable-frame)
3932 (const :format "" t))
3933 (cons
3934 :format "%v\n"
3935 (const :format "" min-height)
3936 (number
3937 :tag "Minimum height of new window" :value 12 :size 5))
3938 (cons
3939 :format "%v\n"
3940 (const :format "" min-width)
3941 (number
3942 :tag "Minimum width of new window" :value 60 :size 5))
3943 (cons
3944 :format "%v"
3945 (const :format "" adjust-height)
3946 (choice
3947 :tag "Adjust window height"
3948 :help-echo "Whether window height shall be adjusted."
3949 :format "%[Adjust height%] %v\n" :size 15
3950 ;; nil matters when we want to override.
3951 (const :tag "Do not adjust heights" :format "%t" nil)
3952 (number :tag "Desired height" :value 60 :size 5)
3953 (function :tag "Function" :size 25)))
3954 (cons
3955 :format "%v"
3956 (const :format "" adjust-width)
3957 (choice
3958 :tag "Adjust window width" :value nil
3959 :help-echo "Whether window width shall be adjusted."
3960 :format "%[Adjust width%] %v\n" :size 15
3961 ;; nil matters when we want to override.
3962 (const :tag "Do not adjust widths" :format "%t" nil)
3963 (number :tag "Desired width" :value 120 :size 5)
3964 (function :tag "Function" :size 25)))
3965 (cons
3966 :format "%v"
3967 :inline t
3968 (const :format "" dedicated)
3969 (choice
3970 :tag "Dedicate window to buffer" :value nil
3971 :help-echo "Mark window as dedicated to its buffer."
3972 :format "%[%t%] %v\n" :size 15
3973 (const :tag "Off" :format "%t" nil)
3974 (const :tag "Weak" :format "%t" weak)
3975 (const :tag "Strong" :format "%t" t)))))
3977 ;; Other frame.
3978 (list
3979 :tag "Other frame"
3980 :value (other-frame
3981 (reuse-buffer-window . visible)
3982 (graphic-only . t)
3983 (popup-frame-alist
3984 (height . 24) (width . 80) (unsplittable . t)))
3985 :format "%t%v"
3986 :inline t
3987 (const :format "\n" other-frame)
3988 (set
3989 :format "%v"
3990 :inline t
3991 (cons
3992 :tag "Avoid selected window"
3993 :format "%v%t\n"
3994 (const :format "" other-window)
3995 (const :format "" t))
3996 (cons
3997 :format "%v"
3998 (const
3999 :format "" reuse-buffer-window)
4000 (choice
4001 :tag "Reuse buffer window"
4002 :help-echo "Frames to search for a window showing the buffer."
4003 :value nil :format "%[Reuse buffer window%] %v\n" :size 15
4004 (const :tag "None" :format "%t" none)
4005 (const :tag "Selected frame only" :format "%t" nil)
4006 (const :tag "Visible frames" :format "%t" visible)
4007 (const :tag "Visible and iconified frames" :format "%t" 0)
4008 (const :tag "All frames" :format "%t" t)))
4009 (cons
4010 :format "%v"
4011 (const
4012 :format "" reuse-other-window)
4013 (choice
4014 :tag "Reuse other window"
4015 :help-echo "Frames to search for a window not showing the buffer."
4016 :value nil :format "%[Reuse other window%] %v\n" :size 15
4017 (const :tag "None" :format "%t" none)
4018 (const :tag "Selected frame only" :format "%t" nil)
4019 (const :tag "Visible frames" :format "%t" visible)
4020 (const :tag "Visible and iconified frames" :format "%t" 0)
4021 (const :tag "All frames" :format "%t" t)))
4022 (cons
4023 :tag "Even window sizes"
4024 :format "%v%t\n"
4025 (const :format "" even-window-sizes)
4026 (const :format "" t))
4027 (cons
4028 :tag "Avoid selected frame"
4029 :format "%v%t\n"
4030 (const :format "" not-this-frame)
4031 (const :format "" t))
4032 (cons
4033 :tag "Switch to another frame on graphic displays only"
4034 :format "%v%t\n"
4035 (const :format "" graphic-only)
4036 (const :format "" t))
4037 (cons
4038 :format "%v"
4039 (const :format "" popup-frame-function)
4040 (function
4041 :tag "Popup frame function"
4042 :value make-frame
4043 :format "%t: %v\n"
4044 :size 25))
4045 (list
4046 :format "%v"
4047 :value (popup-frame-alist (height . 24) (width . 80) (unsplittable . t))
4048 (const :format "" popup-frame-alist)
4049 (repeat
4050 :tag "Parameter / Value pairings"
4051 :inline t
4052 (cons
4053 :format "%v\n"
4054 (symbol
4055 :tag "Parameter"
4056 :format "Parameter: %v"
4057 :size 16)
4058 (sexp
4059 :tag "Value"
4060 :format " Value: %v"
4061 :size 8))))
4062 (cons
4063 :format "%v"
4064 (const :format "" dedicated)
4065 (choice
4066 :tag "Dedicate window to buffer" :value nil
4067 :help-echo "Mark window as dedicated to its buffer."
4068 :format "%[%t%] %v\n" :size 15
4069 (const :tag "Off" :format "%t" nil)
4070 (const :tag "Weak" :format "%t" weak)
4071 (const :tag "Strong" :format "%t" t)))))
4073 ;; Function.
4074 (list
4075 :tag "Function"
4076 :format "%t%v\n"
4077 :inline t
4078 (function
4079 :tag ""
4080 :size 25)))))
4082 ;; Specifiers that are not location specific.
4083 (set
4084 :format "%v"
4085 :inline t
4086 (cons
4087 :tag "Override other specifiers"
4088 :format "%v%t\n"
4089 (const :format "" override)
4090 (const :format "" t)))))
4091 :group 'windows
4092 :group 'frames)
4094 (defcustom display-buffer-regexps
4095 '(((".*")
4096 same-frame
4097 (reuse-buffer-window . nil)
4098 (new-window (largest . nil) (lru . nil))
4099 (min-height . 24) (min-width . 60)
4100 (even-window-sizes . t)
4101 other-frame
4102 (reuse-buffer-window . visible)
4103 (graphic-only . t)
4104 (popup-frame-alist
4105 (height . 24) (width . 80) (unsplittable . t))))
4106 "List associating regexps with buffer display specifiers.
4107 The car of each element of this list is a list of regular
4108 expressions. Buffers whose name matches that expression are
4109 displayed according to the list of buffer display specifiers
4110 constituting the cdr of the element. Consult the documentation
4111 of the variable `display-buffer-names' for a description of valid
4112 display specifiers.
4114 The default value of this variable provides one element matching
4115 all buffers. It states that any buffer shall be displayed
4116 preferably on the selected frame. If, however, there already
4117 exists a window showing the buffer on the selected frame,
4118 `display-buffer' returns that window. Otherwise, it tries to
4119 split either the largest or the least recently used window with
4120 the new window below or on the right of the window that is split.
4121 The minimum height of the new window shall be 24 lines, its
4122 minimum width 60 columns. If a window above or below the
4123 selected window is used, the heights of both windows shall be
4124 evened out.
4126 If these specifiers fail to produce a suitable window and a
4127 graphic display is used, then the buffer shall be displayed on a
4128 new frame unless a window showing the buffer can be found on some
4129 visible. The function to pop up a new frame is given three
4130 parameters: A frame height of 24 lines, a frame width of 80
4131 lines, and a non-nil unsplittable property."
4132 :risky t
4133 :type
4134 '(repeat
4135 :offset 9
4136 (list
4137 :tag "Association"
4138 (repeat
4139 :tag "Regular expressions that match buffer names"
4140 (string :format "%v\n" :size 48))
4141 (repeat
4142 :offset 9
4143 :tag "Display specifiers"
4144 :inline t
4145 (list
4146 :tag "Specifiers"
4147 :inline t
4148 :format "%v"
4149 (choice
4150 :tag "Locations"
4151 :inline t
4152 :help-echo "Choose a location for displaying the buffer(s)."
4153 :value (same-frame
4154 (reuse-buffer-window . nil)
4155 (even-window-sizes . t)
4156 (new-window (largest . nil) (lru . nil))
4157 (min-height . 24) (min-width . 60))
4158 :format "%[Location%] %v" :size 15
4160 ;; Same window.
4161 (list
4162 :tag "Same window"
4163 :format "%t%v"
4164 :inline t
4165 (const :format "\n" same-window)
4166 (set
4167 :format "%v" :inline t
4168 (cons
4169 :format "%v"
4170 (const :format "" dedicated)
4171 (choice
4172 :tag "Dedicate window to buffer" :value nil
4173 :help-echo "Mark window as dedicated to its buffer."
4174 :format "%[%t%] %v\n" :size 15
4175 (const :tag "Off" :format "%t" nil)
4176 (const :tag "Weak" :format "%t" weak)
4177 (const :tag "Strong" :format "%t" t)))))
4179 ;; Same frame.
4180 (list
4181 :tag "Same frame"
4182 :value (same-frame
4183 (reuse-buffer-window . nil)
4184 (even-window-sizes . t)
4185 (new-window (largest . nil) (lru . nil))
4186 (min-height . 24) (min-width . 60))
4187 :format "%t%v"
4188 :inline t
4189 (const :format "\n" same-frame)
4190 (set
4191 :format "%v" :inline t
4192 (cons
4193 :tag "Avoid selected window"
4194 :format "%v%t\n"
4195 (const :format "" not-this-window)
4196 (const :format "" t))
4197 (cons
4198 :format "%v"
4199 (const
4200 :format "" reuse-buffer-window)
4201 (choice
4202 :tag "Reuse buffer window"
4203 :help-echo "Frames to search for a window showing the buffer."
4204 :value nil :format "%[Reuse buffer window%] %v\n" :size 15
4205 (const :tag "None" :format "%t" none)
4206 (const :tag "Selected frame only" :format "%t" nil)
4207 (const :tag "Visible frames" :format "%t" visible)
4208 (const :tag "Visible and iconified frames" :format "%t" 0)
4209 (const :tag "All frames" :format "%t" t)))
4210 (cons
4211 :format "%v"
4212 (const
4213 :format "" reuse-other-window)
4214 (choice
4215 :tag "Reuse other window"
4216 :help-echo "Frames to search for a window not showing the buffer."
4217 :value nil :format "%[Reuse other window%] %v\n" :size 15
4218 (const :tag "None" :format "%t" none)
4219 (const :tag "Selected frame only" :format "%t" nil)
4220 (const :tag "Visible frames" :format "%t" visible)
4221 (const :tag "Visible and iconified frames" :format "%t" 0)
4222 (const :tag "All frames" :format "%t" t)))
4223 (cons
4224 :tag "Even window sizes"
4225 :format "%v%t\n"
4226 (const :format "" even-window-sizes)
4227 (const :format "" t))
4228 (list
4229 :format "%v"
4230 :value (new-window (largest . nil) (lru . nil))
4231 (const :format "" new-window)
4232 (repeat
4233 :inline t
4234 :tag "Window / Side pairings"
4235 (cons
4236 :format "%v"
4237 (choice
4238 :tag "Window" :help-echo "The window to split."
4239 :value largest :format "%[Window%] %v" :size 15
4240 (const :tag "Largest" :format "%t" largest)
4241 (const :tag "Least recently used" :format "%t" lru)
4242 (const :tag "Selected" :format "%t" selected)
4243 (const :tag "Root" :format "%t" root)
4244 (const :tag "First" :format "%t" first))
4245 (choice
4246 :tag "Side"
4247 :help-echo "The position of the new window with respect to the window to split."
4248 :value nil :format " %[Side%] %v" :size 15
4249 (const :tag "Dynamic" nil)
4250 (const :tag "Below" below)
4251 (const :tag "Right" right)
4252 (const :tag "Above" above)
4253 (const :tag "Left" left)
4254 (function
4255 :tag "Function" :format "%v\n" :size 25)))))
4256 (cons
4257 :tag "Make new window even if frame is unsplittable" :size 5
4258 :format "%v%t\n"
4259 (const :format "" split-unsplittable-frame)
4260 (const :format "" t))
4261 (cons
4262 :format "%v\n"
4263 (const :format "" min-height)
4264 (number
4265 :tag "Minimum height of new window" :value 12 :size 5))
4266 (cons
4267 :format "%v\n"
4268 (const :format "" min-width)
4269 (number
4270 :tag "Minimum width of new window" :value 60 :size 5))
4271 (cons
4272 :format "%v"
4273 (const :format "" adjust-height)
4274 (choice
4275 :tag "Adjust window height"
4276 :help-echo "Whether window height shall be adjusted."
4277 :format "%[Adjust height%] %v\n" :size 15
4278 ;; nil matters when we want to override.
4279 (const :tag "Do not adjust heights" :format "%t" nil)
4280 (number :tag "Desired height" :value 60 :size 5)
4281 (function :tag "Function" :size 25)))
4282 (cons
4283 :format "%v"
4284 (const :format "" adjust-width)
4285 (choice
4286 :tag "Adjust window width" :value nil
4287 :help-echo "Whether window width shall be adjusted."
4288 :format "%[Adjust width%] %v\n" :size 15
4289 ;; nil matters when we want to override.
4290 (const :tag "Do not adjust widths" :format "%t" nil)
4291 (number :tag "Desired width" :value 120 :size 5)
4292 (function :tag "Function" :size 25)))
4293 (cons
4294 :format "%v"
4295 :inline t
4296 (const :format "" dedicated)
4297 (choice
4298 :tag "Dedicate window to buffer" :value nil
4299 :help-echo "Mark window as dedicated to its buffer."
4300 :format "%[%t%] %v\n" :size 15
4301 (const :tag "Off" :format "%t" nil)
4302 (const :tag "Weak" :format "%t" weak)
4303 (const :tag "Strong" :format "%t" t)))))
4305 ;; Other frame.
4306 (list
4307 :tag "Other frame"
4308 :value (other-frame
4309 (reuse-buffer-window . visible)
4310 (graphic-only . t)
4311 (popup-frame-alist
4312 (height . 24) (width . 80) (unsplittable . t)))
4313 :format "%t%v"
4314 :inline t
4315 (const :format "\n" other-frame)
4316 (set
4317 :format "%v"
4318 :inline t
4319 (cons
4320 :tag "Avoid selected window"
4321 :format "%v%t\n"
4322 (const :format "" other-window)
4323 (const :format "" t))
4324 (cons
4325 :format "%v"
4326 (const
4327 :format "" reuse-buffer-window)
4328 (choice
4329 :tag "Reuse buffer window"
4330 :help-echo "Frames to search for a window showing the buffer."
4331 :value nil :format "%[Reuse buffer window%] %v\n" :size 15
4332 (const :tag "None" :format "%t" none)
4333 (const :tag "Selected frame only" :format "%t" nil)
4334 (const :tag "Visible frames" :format "%t" visible)
4335 (const :tag "Visible and iconified frames" :format "%t" 0)
4336 (const :tag "All frames" :format "%t" t)))
4337 (cons
4338 :format "%v"
4339 (const
4340 :format "" reuse-other-window)
4341 (choice
4342 :tag "Reuse other window"
4343 :help-echo "Frames to search for a window not showing the buffer."
4344 :value nil :format "%[Reuse other window%] %v\n" :size 15
4345 (const :tag "None" :format "%t" none)
4346 (const :tag "Selected frame only" :format "%t" nil)
4347 (const :tag "Visible frames" :format "%t" visible)
4348 (const :tag "Visible and iconified frames" :format "%t" 0)
4349 (const :tag "All frames" :format "%t" t)))
4350 (cons
4351 :tag "Even window sizes"
4352 :format "%v%t\n"
4353 (const :format "" even-window-sizes)
4354 (const :format "" t))
4355 (cons
4356 :tag "Avoid selected frame"
4357 :format "%v%t\n"
4358 (const :format "" not-this-frame)
4359 (const :format "" t))
4360 (cons
4361 :tag "Switch to another frame on graphic displays only"
4362 :format "%v%t\n"
4363 (const :format "" graphic-only)
4364 (const :format "" t))
4365 (cons
4366 :format "%v"
4367 (const :format "" popup-frame-function)
4368 (function
4369 :tag "Popup frame function"
4370 :value make-frame
4371 :format "%t: %v\n"
4372 :size 25))
4373 (list
4374 :format "%v"
4375 :value (popup-frame-alist (height . 24) (width . 80) (unsplittable . t))
4376 (const :format "" popup-frame-alist)
4377 (repeat
4378 :tag "Parameter / Value pairings"
4379 :inline t
4380 (cons
4381 :format "%v\n"
4382 (symbol
4383 :tag "Parameter"
4384 :format "Parameter: %v"
4385 :size 16)
4386 (sexp
4387 :tag "Value"
4388 :format " Value: %v"
4389 :size 8))))
4390 (cons
4391 :format "%v"
4392 (const :format "" dedicated)
4393 (choice
4394 :tag "Dedicate window to buffer" :value nil
4395 :help-echo "Mark window as dedicated to its buffer."
4396 :format "%[%t%] %v\n" :size 15
4397 (const :tag "Off" :format "%t" nil)
4398 (const :tag "Weak" :format "%t" weak)
4399 (const :tag "Strong" :format "%t" t)))))
4401 ;; Function.
4402 (list
4403 :tag "Function"
4404 :format "%t%v\n"
4405 :inline t
4406 (function
4407 :tag ""
4408 :size 25)))))
4410 ;; Specifiers that are not location specific.
4411 (set
4412 :format "%v"
4413 :inline t
4414 (cons
4415 :tag "Override other specifiers"
4416 :format "%v%t\n"
4417 (const :format "" override)
4418 (const :format "" t)))))
4419 :group 'windows
4420 :group 'frames)
4422 ;; Minibuffer-only frames should be documented better. They really
4423 ;; deserve a separate section in the manual. Also
4424 ;; `last-nonminibuffer-frame' is nowhere documented in the manual.
4425 (defun display-buffer-frame (&optional frame)
4426 "Return FRAME if it is live and not a minibuffer-only frame.
4427 Return the value of `last-nonminibuffer-frame' otherwise."
4428 (setq frame (normalize-live-frame frame))
4429 (if (and (frame-live-p frame)
4430 ;; A not very nice way to get that information.
4431 (not (window-minibuffer-p (frame-root-window frame))))
4432 frame
4433 (last-nonminibuffer-frame)))
4435 (defconst display-buffer-locations '(same-window same-frame other-frame)
4436 "Buffer display location specifiers.")
4438 (defconst display-buffer-default-specifiers
4439 '(same-frame
4440 (reuse-buffer-window . nil)
4441 (new-window (largest . nil) (lru . nil))
4442 (min-height . 24) (min-width . 60)
4443 other-frame
4444 (reuse-buffer-window . visible)
4445 (popup-frame-alist
4446 (height . 24) (width . 80) (unsplittable . t)))
4447 "The default buffer display specifiers.
4448 The value specified here is used when no other specifiers have
4449 been specified by the user or the application. Consult the
4450 documentation of `display-buffer-names' for a description of
4451 buffer display specifiers.")
4453 (defconst display-buffer-other-window-specifiers
4454 '(same-frame (reuse-buffer-window . nil)
4455 other-frame (reuse-buffer-window . visible)
4456 (not-this-window . t))
4457 "Specifiers for displaying a buffer in any but the selected window.
4458 These are the specifiers applied when `display-buffer' is called
4459 with the second argument equal t.")
4461 (defconst display-buffer-other-frame-specifiers
4462 '(other-frame (reuse-buffer-window . visible)
4463 (not-this-window . t) (not-this-frame . t))
4464 "Specifiers for displaying a buffer in any but the selected frame.
4465 These should avoid the selected window and the selected frame.")
4467 (defun display-buffer-normalize-specifiers-1 (specifiers)
4468 "Subroutine of `display-buffer-normalize-specifiers'.
4469 SPECIFIERS is the homonymous argument for `display-buffer'."
4470 (cond
4471 ((memq specifiers '(t other-window))
4472 ;; Historically t means "other window". 'other-window is
4473 ;; occasionally used with the same meaning.
4474 display-buffer-other-window-specifiers)
4475 ((or (memq specifiers display-buffer-locations)
4476 (functionp specifiers))
4477 ;; A single specifier à la 'same-window - make it a list.
4478 (list specifiers))
4479 ((or (not specifiers) (not (listp specifiers)))
4480 ;; Not a valid specifier.
4481 nil)
4482 (t specifiers)))
4484 (defun display-buffer-normalize-specifiers (buffer-name specifiers)
4485 "Return normalized specifiers for displaying a buffer called BUFFER-NAME.
4486 BUFFER-NAME must be a string specifying a valid buffer name.
4487 SPECIFIERS is the homonymous argument of `display-buffer'.
4489 The method for displaying the buffer specified by BUFFER-NAME is
4490 established by appending the following five lists of specifiers:
4492 - The specifiers in `display-buffer-names' whose name component
4493 contains BUFFER-NAME and whose 'override component is set.
4495 - The specifiers in `display-buffer-regexps' whose name component
4496 matches BUFFER-NAME and whose 'override component is set.
4498 - SPECIFIERS.
4500 - The list of specifiers in `display-buffer-names' whose name
4501 component contains BUFFER-NAME and whose 'override component is
4502 not set.
4504 - The list of specifiers in `display-buffer-regexps' whose name
4505 component matches BUFFER-NAME and whose 'override component is
4506 not set.
4508 The return value is always a list. The first element of that
4509 list is not necessarily a location specifier."
4510 (let (names-over regexps-over names-no regexps-no)
4511 (dolist (entry display-buffer-names)
4512 (when (and (listp entry) (member buffer-name (car entry)))
4513 (let ((specifier (cdr entry)))
4514 (if (assq 'override specifier)
4515 (setq names-over
4516 (if names-over
4517 (append names-over specifier)
4518 specifier))
4519 (setq names-no
4520 (if names-no
4521 (append names-no specifier)
4522 specifier))))))
4523 (dolist (entry display-buffer-regexps)
4524 (when (and (listp entry)
4525 (catch 'match
4526 (dolist (regexp (car entry))
4527 (when (and (stringp regexp)
4528 (string-match-p regexp buffer-name))
4529 (throw 'match t)))))
4530 (let ((specifier (cdr entry)))
4531 (if (assq 'override specifier)
4532 (setq regexps-over
4533 (if regexps-over
4534 (append regexps-over specifier)
4535 specifier))
4536 (setq regexps-no
4537 (if regexps-no
4538 (append regexps-no specifier)
4539 specifier))))))
4540 (append
4541 names-over regexps-over
4542 (display-buffer-normalize-specifiers-1 specifiers)
4543 names-no regexps-no
4544 ;; Append the default specifiers.
4545 display-buffer-default-specifiers)))
4547 ;; The following is a global variable which is used externally (by
4548 ;; help.el) to (1) know which window was used for displaying a buffer
4549 ;; and (2) whether the window was new or reused.
4550 (defvar display-buffer-window nil
4551 "Window used by `display-buffer' and related information.
4552 After `display-buffer' displays a buffer in some window this
4553 variable is a cons cell whose car denotes the window used to
4554 display the buffer. The cdr is supposed to be one of the symbols
4555 `reuse-buffer-window', `reuse-other-window', `new-window' or
4556 `new-frame'.
4558 If the buffer display location specifier is one of 'same-window,
4559 'same-frame, or 'other-frame, the `display-buffer' routines
4560 assign the value of this variable. If the location specifier is
4561 a function, that function becomes responsible for assigning a
4562 meaningful value to this variable. See the functions
4563 `display-buffer-in-lru-buffer-window',
4564 `display-buffer-in-lru-window', `display-buffer-in-new-window'
4565 and `display-buffer-in-new-frame' for how this is done.")
4567 (defun display-buffer-even-sizes (window specifiers)
4568 "Even sizes of WINDOW and selected window according to SPECIFIERS.
4569 SPECIFIERS must be a list of buffer display specifiers, see the
4570 documentation of `display-buffer-names' for a description.
4572 Sizes are evened out if and only if WINDOW and the selected
4573 window appear next to each other and the selected window is
4574 larger than WINDOW."
4575 (let ((even-window-sizes (cdr (assq 'even-window-sizes specifiers))))
4576 (cond
4577 ((or (not even-window-sizes)
4578 ;; Don't resize minibuffer windows.
4579 (window-minibuffer-p)
4580 ;; WINDOW must be adjacent to the selected one.
4581 (not (or (eq window (window-prev))
4582 (eq window (window-next))))))
4583 ((and (window-iso-combined-p window)
4584 ;; Resize iff the selected window is higher than WINDOW.
4585 (> (window-total-height) (window-total-height window)))
4586 ;; Don't throw an error if we can't even window heights for
4587 ;; whatever reason. In any case, enlarging the selected window
4588 ;; might fail anyway if there are other windows above or below
4589 ;; WINDOW and the selected one. But for a simple two windows
4590 ;; configuration the present behavior is good enough so why care?
4591 (ignore-errors
4592 (resize-window
4593 window (/ (- (window-total-height) (window-total-height window))
4594 2))))
4595 ((and (window-iso-combined-p window t)
4596 ;; Resize iff the selected window is wider than WINDOW.
4597 (> (window-total-width) (window-total-width window)))
4598 ;; Don't throw an error if we can't even window widths, see
4599 ;; comment above.
4600 (ignore-errors
4601 (resize-window
4602 window (/ (- (window-total-width) (window-total-width window))
4603 2) t))))))
4605 (defun display-buffer-adjust-height (window specifiers)
4606 "Adjust height of WINDOW according to SPECIFIERS.
4607 SPECIFIERS must be a list of buffer display specifiers, see the
4608 documentation of `display-buffer-names' for a description."
4609 (let ((adjust-height (cdr (assq 'adjust-height specifiers))))
4610 (cond
4611 ((numberp adjust-height)
4612 (let* ((height (if (integerp adjust-height)
4613 adjust-height
4614 (* (window-total-size (frame-root-window window))
4615 adjust-height)))
4616 (delta (- height (window-total-size window))))
4617 (when (and (window-resizable-p window delta)
4618 (window-iso-combined-p window))
4619 (resize-window window delta))))
4620 ((functionp adjust-height)
4621 (ignore-errors (funcall adjust-height window))))))
4623 (defun display-buffer-adjust-width (window specifiers)
4624 "Adjust width of WINDOW according to SPECIFIERS.
4625 SPECIFIERS must be a list of buffer display specifiers, see the
4626 documentation of `display-buffer-names' for a description."
4627 (let ((adjust-width (cdr (assq 'adjust-width specifiers))))
4628 (cond
4629 ((numberp adjust-width)
4630 (let* ((width (if (integerp adjust-width)
4631 adjust-width
4632 (* (window-total-size (frame-root-window window) t)
4633 adjust-width)))
4634 (delta (- width (window-total-size window t))))
4635 (when (and (window-resizable-p window delta t)
4636 (window-iso-combined-p window t))
4637 (resize-window window delta t))))
4638 ((functionp adjust-width)
4639 (ignore-errors (funcall adjust-width window))))))
4641 (defun display-buffer-select-window (window &optional norecord)
4642 "Select WINDOW and make sure it's frame is risen."
4643 (let ((old-frame (selected-frame))
4644 (new-frame (window-frame window)))
4645 (select-window window norecord)
4646 (unless (eq old-frame new-frame)
4647 (select-frame-set-input-focus new-frame))))
4649 (defun display-buffer-in-window (buffer window specifiers)
4650 "Display BUFFER in WINDOW and raise its frame.
4651 WINDOW must be a live window and defaults to the selected one.
4652 Return WINDOW.
4654 SPECIFIERS must be a list of buffer display specifiers, see the
4655 documentation of `display-buffer-names' for a description."
4656 (setq buffer (normalize-live-buffer buffer))
4657 (setq window (normalize-live-window window))
4658 (let* ((old-frame (selected-frame))
4659 (new-frame (window-frame window))
4660 (dedicated (cdr (assq 'dedicated specifiers))))
4661 ;; Show BUFFER in WINDOW.
4662 (set-window-dedicated-p window nil)
4663 (set-window-buffer window buffer)
4664 (when dedicated
4665 (set-window-dedicated-p window dedicated))
4666 ;; Raise the frame if it's new (no use to check all sorts of things
4667 ;; as we did earlier). I'm not sure what gets broken by this but at
4668 ;; least the case where the buffer is already shown on another frame
4669 ;; should be handled correctly this time (Emacs 23 apparently always
4670 ;; raises the frame and selects the window).
4672 ;; The "do not raise new frame" case is too difficult to handle (see
4673 ;; also the problems with the old `display-buffer-other-frame').
4674 (unless (eq old-frame new-frame)
4675 ;; Maybe we should call this with NORECORD non-nil.
4676 (display-buffer-select-window window))
4677 ;; Return window.
4678 window))
4680 (defun display-buffer-in-lru-buffer-window (buffer frames &optional specifiers)
4681 "Display BUFFER in least recently used window showing BUFFER.
4682 FRAMES specifies the set of frames to consider. Return the
4683 window displaying BUFFER if done, nil otherwise.
4685 Optional argument SPECIFIERS must be a list of buffer display
4686 specifiers, see the documentation of `display-buffer-names' for a
4687 description."
4688 ;; Try to return the least recently used window showing BUFFER
4689 ;; avoiding the selected window. `get-buffer-window-list' starts with
4690 ;; the first window on the selected frame showing BUFFER (provided
4691 ;; there is such a window).
4692 (let ((windows (get-buffer-window-list buffer 'nomini frames))
4693 (not-this-window
4694 (let ((spec-cdr (cdr (assq 'not-this-window specifiers))))
4695 (cond
4696 ((eq spec-cdr t)
4697 (selected-window))
4698 (spec-cdr))))
4699 (not-this-frame
4700 (let ((spec-cdr (cdr (assq 'not-this-frame specifiers))))
4701 (cond
4702 ((eq spec-cdr t)
4703 (selected-frame))
4704 (spec-cdr))))
4705 best-window best-time time)
4706 (dolist (window windows)
4707 ;; Take care of `not-this-window' and `not-this-frame' specifiers.
4708 (unless (or (eq window not-this-window)
4709 (eq (window-frame window) not-this-frame)
4710 (window-minibuffer-p window))
4711 (setq time (window-use-time window))
4712 (when (or (not best-window) (< time best-time))
4713 (setq best-window window)
4714 (setq best-time time))))
4716 (when best-window
4717 (display-buffer-even-sizes best-window specifiers)
4718 ;; Never change the quit-restore parameter of a window here.
4719 (setq display-buffer-window
4720 (cons best-window 'reuse-buffer-window))
4721 (display-buffer-in-window buffer best-window specifiers))))
4723 (defun display-buffer-in-lru-window (buffer frames &optional specifiers)
4724 "Display BUFFER in least recently used window.
4725 FRAMES specifies the set of frames to consider. Return the
4726 window displaying BUFFER if done, nil otherwise.
4728 Optional argument SPECIFIERS must be a list of buffer display
4729 specifiers, see the documentation of `display-buffer-names' for a
4730 description."
4731 (let ((window
4732 (catch 'found
4733 (let ((windows
4734 (window-list-1
4735 (frame-first-window (display-buffer-frame)) 'nomini frames))
4736 (not-this-window
4737 (let ((spec-cdr (cdr (assq 'not-this-window specifiers))))
4738 (cond
4739 ((eq spec-cdr t)
4740 (selected-window))
4741 (spec-cdr))))
4742 (not-this-frame
4743 (let ((spec-cdr (cdr (assq 'not-this-frame specifiers))))
4744 (cond
4745 ((eq spec-cdr t)
4746 (selected-frame))
4747 (spec-cdr))))
4748 ;; lru-windows is a list of (window . use-time) pairs.
4749 lru-windows)
4750 (dolist (window windows)
4751 ;; Take care of `not-this-window' and `not-this-frame'
4752 ;; specifiers.
4753 (unless (or (eq window not-this-window)
4754 (eq (window-frame window) not-this-frame)
4755 (window-minibuffer-p window)
4756 (window-dedicated-p window))
4757 (setq lru-windows (cons (cons window (window-use-time window))
4758 lru-windows))))
4759 ;; Sort pairs according to their use-time.
4760 (setq lru-windows
4761 (sort lru-windows '(lambda (pair1 pair2)
4762 (<= (cdr pair1) (cdr pair2)))))
4763 ;; Try to get a full-width window.
4764 (dolist (pair lru-windows)
4765 (when (window-full-width-p (car pair))
4766 (throw 'found (car pair))))
4768 ;; If there's no full-width window return the lru window.
4769 (caar lru-windows)))))
4770 (when window
4771 (display-buffer-even-sizes window specifiers)
4772 (unless (window-parameter window 'quit-restore)
4773 ;; Don't overwrite an existing quit-restore entry.
4774 (set-window-parameter
4775 window 'quit-restore
4776 (list (window-buffer window) (window-start window)
4777 (window-point window) buffer
4778 (window-total-size window) (selected-window))))
4779 (setq display-buffer-window
4780 (cons window 'reuse-other-window))
4781 (display-buffer-in-window buffer window specifiers))))
4783 (defun display-buffer-split-window-1 (window side min-size)
4784 "Subroutine of `display-buffer-split-window'."
4785 (let* ((horflag (memq side '(left right)))
4786 (parent (window-parent window))
4787 (resize (and (eq window-splits 'resize)
4788 (window-iso-combined-p window horflag)))
4789 (old-size
4790 ;; We either resize WINDOW or its parent.
4791 (window-total-size (if resize parent window) horflag))
4792 new-size)
4793 ;; We don't call split-window-vertically/-horizontally any more
4794 ;; here. If for some reason it's needed we can always do so
4795 ;; (provided we give it an optional SIDE argument).
4796 (cond
4797 (resize
4798 ;; When we resize a combination, the new window must be at least
4799 ;; MIN-SIZE large after the split.
4800 (setq new-size
4801 (max min-size
4802 (min (- old-size (window-min-size parent horflag))
4803 (/ old-size
4804 ;; Try to make the size of the new window
4805 ;; proportional to the number of iso-arranged
4806 ;; windows in the combination.
4807 (1+ (window-iso-combinations parent horflag))))))
4808 (when (window-sizable-p parent (- new-size) horflag)
4809 (split-window window (- new-size) side)))
4810 ((window-live-p window)
4811 (setq new-size (/ old-size 2))
4812 ;; When WINDOW is live, the old _and_ the new window must be at
4813 ;; least MIN-SIZE large after the split.
4814 (when (and (>= new-size min-size)
4815 (window-sizable-p window (- new-size) horflag))
4816 ;; Do an even split to make Stepan happy.
4817 (split-window window nil side)))
4819 ;; When WINDOW is internal, the new window must be at least
4820 ;; MIN-SIZE large after the split.
4821 (setq new-size
4822 (max min-size
4823 (/ old-size
4824 ;; Try to make the size of the new window
4825 ;; proportional to the number of iso-arranged
4826 ;; subwindows of WINDOW.
4827 (1+ (window-iso-combinations window horflag)))))
4828 (when (window-sizable-p window (- new-size) horflag)
4829 (split-window window (- new-size) side))))))
4831 (defun display-buffer-split-window (window &optional side specifiers)
4832 "Split WINDOW in a way suitable for `display-buffer'.
4833 Optional argument SIDE must be a side specifier \(one of the
4834 symbols below, right, above, left, or nil). SPECIFIERS must be a
4835 list of buffer display specifiers, see the documentation of
4836 `display-buffer-names' for a description.
4838 Return the new window, nil if it could not be created."
4839 (let ((min-height (cdr (assq 'min-height specifiers)))
4840 (min-width (cdr (assq 'min-width specifiers)))
4841 size)
4842 ;; Normalize min-height and min-width, we might need both.
4843 (setq min-height
4844 ;; If min-height is specified, it can be as small as
4845 ;; `window-safe-min-height'.
4846 (cond
4847 ((and (integerp min-height)
4848 (>= min-height window-safe-min-height))
4849 min-height)
4850 ((and (floatp min-height)
4851 (<= min-height 1)
4852 (let* ((root-height (window-total-height
4853 (frame-root-window
4854 (window-frame window))))
4855 (height (round (* min-height root-height))))
4856 (when (>= height window-safe-min-height)
4857 height))))
4858 (t window-min-height)))
4859 (setq min-width
4860 ;; If min-width is specified, it can be as small as
4861 ;; `window-safe-min-width'.
4862 (cond
4863 ((and (integerp min-width)
4864 (>= min-width window-safe-min-width))
4865 min-width)
4866 ((and (floatp min-width)
4867 (<= min-width 1)
4868 (let* ((root-width (window-total-width
4869 (frame-root-window
4870 (window-frame window))))
4871 (width (round (* min-width root-width))))
4872 (when (>= width window-safe-min-width)
4873 width))))
4874 (t window-min-width)))
4876 (or (and (memq side '(nil above below))
4877 (display-buffer-split-window-1
4878 window (or side 'below) min-height))
4879 ;; If SIDE is nil and vertical splitting failed, we try again
4880 ;; splitting horizontally this time.
4881 (and (memq side '(nil left right))
4882 (display-buffer-split-window-1
4883 window (or side 'right) min-width))
4884 ;; If WINDOW is live and the root window of its frame, try once
4885 ;; more splitting vertically, disregarding the min-height
4886 ;; specifier this time and using `window-min-height' instead.
4887 (and (memq side '(nil above below))
4888 (<= window-min-height min-height)
4889 (window-live-p window)
4890 (eq window (frame-root-window window))
4891 (display-buffer-split-window-1
4892 window (or side 'below) window-min-height)))))
4894 (defconst display-buffer-split-specifiers '(largest lru selected root first)
4895 "Buffer display window split specifiers.")
4897 (defconst display-buffer-side-specifiers '(below right above left nil)
4898 "Buffer display window side specifiers.")
4900 (defun display-buffer-in-new-window (buffer specifiers)
4901 "Display BUFFER in a new window.
4902 Return the window displaying BUFFER if creating the new window
4903 was successful, nil otherwise.
4905 SPECIFIERS must be a list of buffer display specifiers, see the
4906 documentation of `display-buffer-names' for a description."
4907 (let* ((frame (display-buffer-frame))
4908 (selected-window (frame-selected-window frame))
4909 window window-specifier side-specifier)
4910 (unless (or (and (cdr (assq 'unsplittable (frame-parameters frame)))
4911 ;; Don't split an unsplittable frame unless
4912 ;; SPECIFIERS allow it.
4913 (not (cdr (assq 'split-unsplittable-frame specifiers))))
4914 (let ((spec-cdr (cdr (assq 'not-this-frame specifiers))))
4915 ;; Don't split a window on the selected frame if
4916 ;; `not-this-frame' disallows it.
4917 (or (eq spec-cdr t) (eq spec-cdr (selected-frame)))))
4918 (catch 'done
4919 (dolist (specifier specifiers)
4920 (when (and (consp specifier) (eq (car specifier) 'new-window))
4921 (dolist (window-side-specifier (cdr specifier))
4922 (setq window-specifier (car window-side-specifier))
4923 (setq side-specifier (cdr window-side-specifier))
4924 (setq window
4925 (cond
4926 ((eq window-specifier 'largest)
4927 (get-largest-window frame t))
4928 ((eq window-specifier 'lru)
4929 (get-lru-window frame t))
4930 ((eq window-specifier 'selected)
4931 (frame-selected-window frame))
4932 ((eq window-specifier 'root)
4933 (frame-root-window frame))
4934 ((eq window-specifier 'first)
4935 (frame-first-window frame))))
4936 (and window (eq (window-frame window) frame)
4937 (not (window-minibuffer-p window))
4938 (setq window
4939 (cond
4940 ((memq
4941 side-specifier display-buffer-side-specifiers)
4942 (display-buffer-split-window
4943 window side-specifier specifiers))
4944 ((functionp side-specifier)
4945 (ignore-errors
4946 (funcall side-specifier window (cdr specifiers))))))
4947 (throw 'done window))))))
4948 (when window
4949 ;; Adjust sizes if asked for.
4950 (display-buffer-adjust-height window specifiers)
4951 (display-buffer-adjust-width window specifiers)
4952 (set-window-parameter
4953 window 'quit-restore (list 'new-window buffer selected-window))
4954 (setq display-buffer-window (cons window 'new-window))
4955 (display-buffer-in-window buffer window specifiers)))))
4957 (defun display-buffer-in-new-frame (buffer specifiers)
4958 "Make a new frame for displaying BUFFER.
4959 Return the window displaying BUFFER if creating the new frame was
4960 successful, nil otherwise.
4962 SPECIFIERS must be a list of buffer display specifiers, see the
4963 documentation of `display-buffer-names' for a description."
4964 (unless (and (cdr (assq 'graphic-only specifiers))
4965 (not (display-graphic-p)))
4966 (let* ((selected-window (selected-window))
4967 (function (or (cdr (assq 'popup-frame-function specifiers))
4968 'make-frame))
4969 (parameters (cdr (assq 'popup-frame-alist specifiers)))
4970 (frame (funcall function parameters)))
4971 (when frame
4972 (let ((window (frame-selected-window frame)))
4973 (set-window-parameter
4974 window 'quit-restore (list 'new-frame buffer selected-window))
4975 (setq display-buffer-window (cons window 'new-frame))
4976 (display-buffer-in-window buffer window specifiers))))))
4978 (defun normalize-buffer-to-display (buffer-or-name)
4979 "Normalize BUFFER-OR-NAME argument for buffer display functions.
4980 If BUFFER-OR-NAME is nil, return the curent buffer. Else, if a
4981 buffer specified by BUFFER-OR-NAME exists, return that buffer.
4982 If no such buffer exists, create a buffer with the name
4983 BUFFER-OR-NAME and return that buffer."
4984 (if buffer-or-name
4985 (or (get-buffer buffer-or-name)
4986 (let ((buffer (get-buffer-create buffer-or-name)))
4987 (set-buffer-major-mode buffer)
4988 buffer))
4989 (current-buffer)))
4991 (defun display-buffer (&optional buffer-or-name specifiers ignore)
4992 "Make the buffer specified by BUFFER-OR-NAME appear in some window.
4993 Optional argument BUFFER-OR-NAME may be a buffer, a string \(a
4994 buffer name), or nil. If BUFFER-OR-NAME is a string not naming
4995 an existent buffer, create a buffer with that name. If
4996 BUFFER-OR-NAME is nil or omitted, display the current buffer.
4997 Interactively, prompt for the buffer name using the minibuffer.
4999 Return the window chosen to display the buffer or nil if no such
5000 window is found. Do not change the selected window unless a new
5001 frame is created.
5003 Optional argument SPECIFIERS must be a list of buffer display
5004 specifiers, see the documentation of `display-buffer-names' for a
5005 description.
5007 For convenience, SPECIFIERS may also consist of a single buffer
5008 display location specifier or t, where the latter means to
5009 display the buffer in any but the selected window. If SPECIFIERS
5010 is nil or omitted, this means to exclusively use the values
5011 provided by `display-buffer-names' and `display-buffer-regexps'.
5012 If these values are nil too, all specifiers are provided by the
5013 constant `display-buffer-default-specifiers'.
5015 In addition, the `not-this-window' specifier allows as cdr to
5016 specify an arbitrary window in order to not use that window for
5017 displaying the buffer. The `not-this-frame' specifier allows as
5018 cdr to also specify an arbitrary frame in order to not use that
5019 frame for displaying the buffer.
5021 The optional third argument IGNORE is ignored.
5023 The method to display a buffer is derived by combining the values
5024 of `display-buffer-names', `display-buffer-regexps', and
5025 SPECIFIERS. Highest priority is given to overriding elements of
5026 `display-buffer-names' followed by overriding elements of
5027 `display-buffer-regexps'. Next come the elements specified by
5028 SPECIFIERS, followed by the non-overriding elements of
5029 `display-buffer-names' and the non-overriding elements of
5030 `display-buffer-regexps'.
5032 The result must be a list of valid buffer display specifiers.
5033 `display-buffer' scans this list from front to back until it
5034 finds a location specifier and attempts to use that specifier in
5035 order to produce a suitable window. For this purpose, all
5036 non-symbolic specifiers following the location specifier in the
5037 list are considered additional specifiers. If an attempt fails
5038 to produce a window, `display-buffer' continues with the next
5039 location specifier on the list. Additional specifiers preceding
5040 the currently chosen location specifier in the list are ignored."
5041 (interactive "BDisplay buffer:\nP")
5042 (let* ((buffer (normalize-buffer-to-display buffer-or-name))
5043 (buffer-name (buffer-name buffer))
5044 (specifiers
5045 ;; Normalize specifiers.
5046 (display-buffer-normalize-specifiers buffer-name specifiers))
5047 ;; Don't use a minibuffer frame.
5048 (frame (display-buffer-frame))
5049 ;; `window' is the window we use for showing `buffer'.
5050 specifier location window type
5051 reuse-buffer-window reuse-other-window)
5052 ;; Reset this.
5053 (setq display-buffer-window nil)
5054 ;; Retrieve the next location specifier while there a specifiers left
5055 ;; and we don't have a valid window.
5056 (while (and specifiers (or (not window) (not (window-live-p window))))
5057 (setq location (car specifiers))
5058 (setq specifiers (cdr specifiers))
5059 (when (symbolp location)
5060 (setq window
5061 (or (and (eq location 'same-window)
5062 (or (not (window-dedicated-p))
5063 (eq (window-buffer) buffer))
5064 (let ((selected-window
5065 ;; If the selected window is a minibuffer
5066 ;; window, use the selected window of the
5067 ;; last nonminibuffer frame instead.
5068 (if (window-minibuffer-p)
5069 (frame-selected-window
5070 (last-nonminibuffer-frame))
5071 (selected-window))))
5072 (display-buffer-in-window
5073 buffer selected-window specifiers)))
5074 (and (memq location '(same-frame other-frame))
5075 (not (eq (setq reuse-buffer-window
5076 (cdr (assq
5077 'reuse-buffer-window specifiers)))
5078 'never))
5079 ;; Try to reuse a window showing BUFFER. If
5080 ;; reuse-buffer-window was set, it will specify
5081 ;; the frames to consider, otherwise look at the
5082 ;; selected frame's windows only.
5083 (display-buffer-in-lru-buffer-window
5084 buffer reuse-buffer-window specifiers))
5085 (and (eq location 'same-frame)
5086 (not (frame-parameter frame 'unsplittable))
5087 (cdr (assq 'new-window specifiers))
5088 ;; Try making a new window.
5089 (display-buffer-in-new-window buffer specifiers))
5090 (and (eq location 'other-frame)
5091 ;; Try making a new frame.
5092 (display-buffer-in-new-frame buffer specifiers))
5093 (and (eq location 'same-frame)
5094 (not (eq (setq reuse-other-window
5095 (cdr (assq 'reuse-other-window specifiers)))
5096 'never))
5097 ;; Try to reuse a window not showing BUFFER. If
5098 ;; reuse-buffer-window was set, it will specify
5099 ;; the frames to consider, otherwise look at the
5100 ;; selected frame's windows only.
5101 (display-buffer-in-lru-window
5102 buffer reuse-other-window specifiers))
5103 (and (not (memq location display-buffer-locations))
5104 (functionp location)
5105 ;; Separate function.
5106 (funcall location buffer specifiers))))))
5108 ;; If we don't have a window yet, try a fallback method. Note: All
5109 ;; specifiers have been used up by now.
5110 (or (and (window-live-p window) window)
5111 ;; Try reusing any window showing BUFFER on a visible or
5112 ;; iconfied frame.
5113 (display-buffer-in-lru-buffer-window buffer 0)
5114 ;; Try reusing a window on the selected frame.
5115 (display-buffer-in-lru-window buffer nil)
5116 ;; Try reusing a window on a visible frame.
5117 (display-buffer-in-lru-window buffer 'visible)
5118 ;; Try reusing a window on a visible or iconified frame.
5119 (display-buffer-in-lru-window buffer 0)
5120 ;; Try reusing any window showing BUFFER on any frame.
5121 (display-buffer-in-lru-buffer-window buffer t)
5122 ;; Try reusing a window on any frame.
5123 (display-buffer-in-lru-window buffer t)
5124 ;; Try making a new window.
5125 (display-buffer-in-new-window buffer nil)
5126 ;; Try making a new frame
5127 (display-buffer-in-new-frame buffer nil)
5128 ;; Use the selected window and let errors show trough.
5129 (display-buffer-in-window buffer (selected-window) nil))))
5131 (defun display-buffer-same-window (&optional buffer-or-name)
5132 "Display buffer specified by BUFFER-OR-NAME in the selected window.
5133 Another window will be used only if the buffer can't be shown in
5134 the selected window, usualy because it is dedicated to another
5135 buffer.
5137 Optional argument BUFFER-OR-NAME may be a buffer, a string \(a
5138 buffer name), or nil. If BUFFER-OR-NAME is a string not naming
5139 an existent buffer, create a buffer with that name. If
5140 BUFFER-OR-NAME is nil or omitted, display the current buffer.
5142 Return the window chosen to display BUFFER-OR-NAME or
5143 nil if no such window is found. Do not change the selected
5144 window unless a new frame is created."
5145 (display-buffer buffer-or-name 'same-window))
5147 (defun display-buffer-other-window (&optional buffer-or-name)
5148 "Display buffer specified by BUFFER-OR-NAME in another window.
5149 The selected window will be used if and only if there is no other
5150 choice. Windows on the selected frame are preferred to windows
5151 on other frames.
5153 Optional argument BUFFER-OR-NAME may be a buffer, a string \(a
5154 buffer name), or nil. If BUFFER-OR-NAME is a string not naming
5155 an existent buffer, create a buffer with that name. If
5156 BUFFER-OR-NAME is nil or omitted, display the current buffer.
5158 Return the window chosen to display BUFFER-OR-NAME or
5159 nil if no such window is found. Do not change the selected
5160 window unless a new frame is created."
5161 (display-buffer
5162 buffer-or-name display-buffer-other-window-specifiers))
5164 (defun pop-to-buffer (&optional buffer-or-name specifiers norecord)
5165 "Display buffer specified by BUFFER-OR-NAME and select the window used.
5166 Optional argument BUFFER-OR-NAME may be a buffer, a string \(a
5167 buffer name), or nil. If BUFFER-OR-NAME is a string not naming
5168 an existent buffer, create a buffer with that name. If
5169 BUFFER-OR-NAME is nil or omitted, display the current buffer.
5170 Interactively, prompt for the buffer name using the minibuffer.
5172 Optional second argument SPECIFIERS must be a list of buffer
5173 display specifiers, a single location specifier, `t' which means
5174 the latter means to display the buffer in any but the selected
5175 window, or nil which means to exclusively apply the specifiers
5176 customized by the user.
5178 Optional argument NORECORD non-nil means do not put the buffer
5179 specified by BUFFER-OR-NAME at the front of the buffer list and
5180 do not make the window displaying it the most recently selected
5181 one.
5183 Return the buffer specified by BUFFER-OR-NAME or nil if
5184 displaying the buffer failed.
5186 This uses the function `display-buffer' as a subroutine; see the
5187 documentations of `display-buffer', `display-buffer-names' and
5188 `display-buffer-regexps' for additional information."
5189 (interactive "BPop to buffer:\nP")
5190 (let ((buffer (normalize-buffer-to-display buffer-or-name))
5191 window)
5192 (set-buffer buffer)
5193 (when (setq window (display-buffer buffer specifiers))
5194 (display-buffer-select-window window norecord)
5195 buffer)))
5197 (defun pop-to-buffer-same-window (&optional buffer-or-name norecord)
5198 "Pop to buffer specified by BUFFER-OR-NAME in the selected window.
5199 Another window will be used only if the buffer can't be shown in
5200 the selected window, usually because it is dedicated to another
5201 buffer. Select the window used for displaying the buffer and
5202 return the buffer specified by BUFFER-OR-NAME or nil if
5203 displaying the buffer failed.
5205 Optional arguments BUFFER-OR-NAME and NORECORD are as for
5206 `pop-to-buffer'."
5207 (interactive "BPop to buffer in selected window:\nP")
5208 (pop-to-buffer buffer-or-name 'same-window norecord))
5210 (defun pop-to-buffer-other-window (&optional buffer-or-name norecord)
5211 "Pop to buffer specified by BUFFER-OR-NAME in another window.
5212 The selected window will be used if and only if there is no other
5213 choice. Windows on the selected frame are preferred to windows
5214 on other frames. Select the window used for displaying the
5215 buffer and return the buffer specified by BUFFER-OR-NAME or nil
5216 if displaying the buffer failed.
5218 Optional arguments BUFFER-OR-NAME and NORECORD are as for
5219 `pop-to-buffer'."
5220 (interactive "BPop to buffer in another window:\nP")
5221 (pop-to-buffer
5222 buffer-or-name display-buffer-other-window-specifiers norecord))
5224 (defun pop-to-buffer-other-frame (&optional buffer-or-name norecord)
5225 "Pop to buffer specified by BUFFER-OR-NAME on another frame.
5226 The selected frame will be used only if there's no other choice.
5227 Select the window used for displaying the buffer and return the
5228 buffer specified by BUFFER-OR-NAME or nil if displaying the
5229 buffer failed.
5231 Optional arguments BUFFER-OR-NAME and NORECORD are as for
5232 `pop-to-buffer'."
5233 (interactive "BPop to buffer on another frame:\nP")
5234 (pop-to-buffer
5235 buffer-or-name display-buffer-other-frame-specifiers norecord))
5237 (defun read-buffer-to-switch (prompt)
5238 "Read the name of a buffer to switch to, prompting with PROMPT.
5239 Return the neame of the buffer as a string.
5241 This function is intended for the `switch-to-buffer' family of
5242 commands since these need to omit the name of the current buffer
5243 from the list of completions and default values."
5244 (let ((rbts-completion-table (internal-complete-buffer-except)))
5245 (minibuffer-with-setup-hook
5246 (lambda ()
5247 (setq minibuffer-completion-table rbts-completion-table)
5248 ;; Since rbts-completion-table is built dynamically, we
5249 ;; can't just add it to the default value of
5250 ;; icomplete-with-completion-tables, so we add it
5251 ;; here manually.
5252 (if (and (boundp 'icomplete-with-completion-tables)
5253 (listp icomplete-with-completion-tables))
5254 (set (make-local-variable 'icomplete-with-completion-tables)
5255 (cons rbts-completion-table
5256 icomplete-with-completion-tables))))
5257 (read-buffer prompt (other-buffer (current-buffer))
5258 (confirm-nonexistent-file-or-buffer)))))
5260 (defun normalize-buffer-to-switch-to (buffer-or-name)
5261 "Normalize BUFFER-OR-NAME argument of buffer switching functions.
5262 If BUFFER-OR-NAME is nil, return the buffer returned by
5263 `other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME
5264 exists, return that buffer. If no such buffer exists, create a
5265 buffer with the name BUFFER-OR-NAME and return that buffer."
5266 (if buffer-or-name
5267 (or (get-buffer buffer-or-name)
5268 (let ((buffer (get-buffer-create buffer-or-name)))
5269 (set-buffer-major-mode buffer)
5270 buffer))
5271 (other-buffer)))
5273 (defun switch-to-buffer (buffer-or-name &optional norecord)
5274 "Switch to buffer BUFFER-OR-NAME in the selected window.
5275 If called interactively, prompt for the buffer name using the
5276 minibuffer. The variable `confirm-nonexistent-file-or-buffer'
5277 determines whether to request confirmation before creating a new
5278 buffer.
5280 BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
5281 nil. If BUFFER-OR-NAME is a string that does not identify an
5282 existing buffer, create a buffer with that name. If
5283 BUFFER-OR-NAME is nil, switch to the buffer returned by
5284 `other-buffer'.
5286 Optional argument NORECORD non-nil means do not put the buffer
5287 specified by BUFFER-OR-NAME at the front of the buffer list and
5288 do not make the window displaying it the most recently selected
5289 one. Return the buffer switched to.
5291 This function is intended for interactive use. Lisp functions
5292 should call `pop-to-buffer-same-window' instead."
5293 (interactive
5294 (list (read-buffer-to-switch "Switch to buffer: ")))
5295 (let ((buffer (normalize-buffer-to-switch-to buffer-or-name)))
5296 (if (and (or (window-minibuffer-p) (eq (window-dedicated-p) t))
5297 (not (eq buffer (window-buffer))))
5298 ;; Cannot switch to another buffer in a minibuffer or strongly
5299 ;; dedicated window that does not show the buffer already. Call
5300 ;; `pop-to-buffer' instead.
5301 (pop-to-buffer buffer 'same-window norecord)
5302 (unless (eq buffer (window-buffer))
5303 ;; I'm not sure why we should NOT call `set-window-buffer' here,
5304 ;; but let's keep things as they are (otherwise we could always
5305 ;; call `pop-to-buffer-same-window' here).
5306 (set-window-buffer nil buffer))
5307 (unless norecord
5308 (select-window (selected-window)))
5309 (set-buffer buffer))))
5311 (defun switch-to-buffer-other-window (buffer-or-name &optional norecord)
5312 "Switch to buffer BUFFER-OR-NAME in another window.
5313 The selected window will be used if and only if there is no other
5314 choice. Windows on the selected frame are preferred to windows
5315 on other frames.
5317 If called interactively, prompt for the buffer name using the
5318 minibuffer. The variable `confirm-nonexistent-file-or-buffer'
5319 determines whether to request confirmation before creating a new
5320 buffer.
5322 When called from Lisp, BUFFER-OR-NAME may be a buffer, a string
5323 \(a buffer name), or nil. If BUFFER-OR-NAME is a string that
5324 does not identify an existing buffer, create a buffer with that
5325 name. If BUFFER-OR-NAME is nil, switch to the buffer returned by
5326 `other-buffer'.
5328 Optional argument NORECORD non-nil means do not put the buffer
5329 specified by BUFFER-OR-NAME at the front of the buffer list and
5330 do not make the window displaying it the most recently selected
5331 one. Return the buffer switched to.
5333 This uses the function `display-buffer' as a subroutine; see the
5334 documentations of `display-buffer', `display-buffer-names' and
5335 `display-buffer-regexps' for additional information.
5337 This function is intended for interactive use. Lisp functions
5338 should call `pop-to-buffer-other-window' instead."
5339 (interactive
5340 (list (read-buffer-to-switch "Switch to buffer in other window: ")))
5341 (let ((buffer (normalize-buffer-to-switch-to buffer-or-name)))
5342 (pop-to-buffer
5343 buffer display-buffer-other-window-specifiers norecord)))
5345 (defun switch-to-buffer-other-frame (buffer-or-name &optional norecord)
5346 "Switch to buffer BUFFER-OR-NAME on another frame.
5347 If called interactively, prompt for the buffer name using the
5348 minibuffer. The variable `confirm-nonexistent-file-or-buffer'
5349 determines whether to request confirmation before creating a new
5350 buffer.
5352 When called from Lisp, BUFFER-OR-NAME may be a buffer, a string
5353 \(a buffer name), or nil. If BUFFER-OR-NAME is a string that
5354 does not identify an existing buffer, create a buffer with that
5355 name. If BUFFER-OR-NAME is nil, switch to the buffer returned by
5356 `other-buffer'.
5358 Optional argument NORECORD non-nil means do not put the buffer
5359 specified by BUFFER-OR-NAME at the front of the buffer list and
5360 do not make the window displaying it the most recently selected
5361 one. Return the buffer switched to.
5363 This uses the function `display-buffer' as a subroutine; see the
5364 documentations of `display-buffer', `display-buffer-names' and
5365 `display-buffer-regexps' for additional information.
5367 This function is intended for interactive use. Lisp functions
5368 should call `pop-to-buffer-other-frame' instead."
5369 (interactive
5370 (list (read-buffer-to-switch "Switch to buffer in other frame: ")))
5371 (let ((buffer (normalize-buffer-to-switch-to buffer-or-name)))
5372 (pop-to-buffer buffer display-buffer-other-frame-specifiers norecord)))
5374 ;;; Obsolete definitions of `display-buffer' below.
5375 (defcustom display-buffer-function nil
5376 "If non-nil, function to call to display a buffer.
5377 `display-buffer' calls this function with two arguments, the
5378 buffer to display and a flag which if non-nil means that the
5379 selected window is not acceptable for displaying the buffer. It
5380 should choose or create a window, display the specified buffer in
5381 it, and return the window.
5383 Commands such as `switch-to-buffer-other-window' and
5384 `find-file-other-window' work using this function."
5385 :type '(choice
5386 (const nil)
5387 (function :tag "function"))
5388 :group 'display-buffer)
5389 (make-obsolete-variable
5390 'display-buffer-function
5391 "use `display-buffer-names' or `display-buffer-regexps' instead."
5392 "24.1")
5394 (defcustom special-display-buffer-names nil
5395 "List of names of buffers that should be displayed specially.
5396 Displaying a buffer with `display-buffer' or `pop-to-buffer', if
5397 its name is in this list, displays the buffer in a way specified
5398 by `special-display-function'. `special-display-popup-frame'
5399 \(the default for `special-display-function') usually displays
5400 the buffer in a separate frame made with the parameters specified
5401 by `special-display-frame-alist'. If `special-display-function'
5402 has been set to some other function, that function is called with
5403 the buffer as first, and nil as second argument.
5405 Alternatively, an element of this list can be specified as
5406 \(BUFFER-NAME FRAME-PARAMETERS), where BUFFER-NAME is a buffer
5407 name and FRAME-PARAMETERS an alist of \(PARAMETER . VALUE) pairs.
5408 `special-display-popup-frame' will interpret such pairs as frame
5409 parameters when it creates a special frame, overriding the
5410 corresponding values from `special-display-frame-alist'.
5412 As a special case, if FRAME-PARAMETERS contains (same-window . t)
5413 `special-display-popup-frame' displays that buffer in the
5414 selected window. If FRAME-PARAMETERS contains (same-frame . t),
5415 it displays that buffer in a window on the selected frame.
5417 If `special-display-function' specifies some other function than
5418 `special-display-popup-frame', that function is called with the
5419 buffer named BUFFER-NAME as first, and FRAME-PARAMETERS as second
5420 argument.
5422 Finally, an element of this list can be also specified as
5423 \(BUFFER-NAME FUNCTION OTHER-ARGS). In that case,
5424 `special-display-popup-frame' will call FUNCTION with the buffer
5425 named BUFFER-NAME as first argument, and OTHER-ARGS as the
5426 second. If `special-display-function' specifies some other
5427 function, that function is called with the buffer named
5428 BUFFER-NAME as first, and the element's cdr as second argument.
5430 If this variable appears \"not to work\", because you added a
5431 name to it but the corresponding buffer is displayed in the
5432 selected window, look at the values of `same-window-buffer-names'
5433 and `same-window-regexps'. Those variables take precedence over
5434 this one.
5436 See also `special-display-regexps'."
5437 :type '(repeat
5438 (choice :tag "Buffer"
5439 :value ""
5440 (string :format "%v")
5441 (cons :tag "With parameters"
5442 :format "%v"
5443 :value ("" . nil)
5444 (string :format "%v")
5445 (repeat :tag "Parameters"
5446 (cons :format "%v"
5447 (symbol :tag "Parameter")
5448 (sexp :tag "Value"))))
5449 (list :tag "With function"
5450 :format "%v"
5451 :value ("" . nil)
5452 (string :format "%v")
5453 (function :tag "Function")
5454 (repeat :tag "Arguments" (sexp)))))
5455 :group 'display-buffer
5456 :group 'frames)
5457 (make-obsolete-variable
5458 'special-display-buffer-names
5459 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5460 "24.1")
5462 ;;;###autoload
5463 (put 'special-display-buffer-names 'risky-local-variable t)
5465 (defcustom special-display-regexps nil
5466 "List of regexps saying which buffers should be displayed specially.
5467 Displaying a buffer with `display-buffer' or `pop-to-buffer', if
5468 any regexp in this list matches its name, displays it specially
5469 using `special-display-function'.
5471 The function `special-display-popup-frame' \(the default for
5472 `special-display-function') usually displays the buffer in a
5473 separate frame made with the parameters specified by
5474 `special-display-frame-alist'. If `special-display-function' has
5475 been set to some other function, that function is called with the
5476 buffer as first, and nil as second argument.
5478 Alternatively, an element of this list can be specified as
5479 \(REGEXP FRAME-PARAMETERS), where REGEXP is a regexp as above and
5480 FRAME-PARAMETERS an alist of (PARAMETER . VALUE) pairs.
5481 `special-display-popup-frame' will then interpret these pairs as
5482 frame parameters when creating a special frame for a buffer whose
5483 name matches REGEXP, overriding the corresponding values from
5484 `special-display-frame-alist'.
5486 As a special case, if FRAME-PARAMETERS contains (same-window . t)
5487 `special-display-popup-frame' displays buffers matching REGEXP in
5488 the selected window. \(same-frame . t) in FRAME-PARAMETERS means
5489 to display such buffers in a window on the selected frame.
5491 If `special-display-function' specifies some other function than
5492 `special-display-popup-frame', that function is called with the
5493 buffer whose name matched REGEXP as first, and FRAME-PARAMETERS
5494 as second argument.
5496 Finally, an element of this list can be also specified as
5497 \(REGEXP FUNCTION OTHER-ARGS). `special-display-popup-frame'
5498 will then call FUNCTION with the buffer whose name matched
5499 REGEXP as first, and OTHER-ARGS as second argument. If
5500 `special-display-function' specifies some other function, that
5501 function is called with the buffer whose name matched REGEXP
5502 as first, and the element's cdr as second argument.
5504 If this variable appears \"not to work\", because you added a
5505 name to it but the corresponding buffer is displayed in the
5506 selected window, look at the values of `same-window-buffer-names'
5507 and `same-window-regexps'. Those variables take precedence over
5508 this one.
5510 See also `special-display-buffer-names'."
5511 :type '(repeat
5512 (choice :tag "Buffer"
5513 :value ""
5514 (regexp :format "%v")
5515 (cons :tag "With parameters"
5516 :format "%v"
5517 :value ("" . nil)
5518 (regexp :format "%v")
5519 (repeat :tag "Parameters"
5520 (cons :format "%v"
5521 (symbol :tag "Parameter")
5522 (sexp :tag "Value"))))
5523 (list :tag "With function"
5524 :format "%v"
5525 :value ("" . nil)
5526 (regexp :format "%v")
5527 (function :tag "Function")
5528 (repeat :tag "Arguments" (sexp)))))
5529 :group 'display-buffer
5530 :group 'frames)
5531 (make-obsolete-variable
5532 'special-display-regexps
5533 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5534 "24.1")
5536 (defun special-display-p (buffer-name)
5537 "Return non-nil if a buffer named BUFFER-NAME gets a special frame.
5538 More precisely, return t if `special-display-buffer-names' or
5539 `special-display-regexps' contain a string entry equaling or
5540 matching BUFFER-NAME. If `special-display-buffer-names' or
5541 `special-display-regexps' contain a list entry whose car equals
5542 or matches BUFFER-NAME, the return value is the cdr of that
5543 entry."
5544 (let (tmp)
5545 (cond
5546 ((not (stringp buffer-name)))
5547 ((member buffer-name special-display-buffer-names)
5549 ((setq tmp (assoc buffer-name special-display-buffer-names))
5550 (cdr tmp))
5551 ((catch 'found
5552 (dolist (regexp special-display-regexps)
5553 (cond
5554 ((stringp regexp)
5555 (when (string-match-p regexp buffer-name)
5556 (throw 'found t)))
5557 ((and (consp regexp) (stringp (car regexp))
5558 (string-match-p (car regexp) buffer-name))
5559 (throw 'found (cdr regexp))))))))))
5560 (make-obsolete 'special-display-p "pass argument to buffer display function instead." "24.1")
5562 (defcustom special-display-function 'special-display-popup-frame
5563 "Function to call for displaying special buffers.
5564 This function is called with two arguments - the buffer and,
5565 optionally, a list - and should return a window displaying that
5566 buffer. The default value usually makes a separate frame for the
5567 buffer using `special-display-frame-alist' to specify the frame
5568 parameters. See the definition of `special-display-popup-frame'
5569 for how to specify such a function.
5571 A buffer is special when its name is either listed in
5572 `special-display-buffer-names' or matches a regexp in
5573 `special-display-regexps'."
5574 :type 'function
5575 :group 'frames)
5576 (make-obsolete-variable
5577 'special-display-function
5578 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5579 "24.1")
5581 (defcustom same-window-buffer-names nil
5582 "List of names of buffers that should appear in the \"same\" window.
5583 `display-buffer' and `pop-to-buffer' show a buffer whose name is
5584 on this list in the selected rather than some other window.
5586 An element of this list can be a cons cell instead of just a
5587 string. In that case, the cell's car must be a string specifying
5588 the buffer name. This is for compatibility with
5589 `special-display-buffer-names'; the cdr of the cons cell is
5590 ignored.
5592 See also `same-window-regexps'."
5593 :type '(repeat (string :format "%v"))
5594 :group 'display-buffer)
5595 (make-obsolete-variable
5596 'same-window-buffer-names
5597 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5598 "24.1")
5600 (defcustom same-window-regexps nil
5601 "List of regexps saying which buffers should appear in the \"same\" window.
5602 `display-buffer' and `pop-to-buffer' show a buffer whose name
5603 matches a regexp on this list in the selected rather than some
5604 other window.
5606 An element of this list can be a cons cell instead of just a
5607 string. In that case, the cell's car must be a regexp matching
5608 the buffer name. This is for compatibility with
5609 `special-display-regexps'; the cdr of the cons cell is ignored.
5611 See also `same-window-buffer-names'."
5612 :type '(repeat (regexp :format "%v"))
5613 :group 'display-buffer)
5614 (make-obsolete-variable
5615 'same-window-regexps
5616 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5617 "24.1")
5619 (defun same-window-p (buffer-name)
5620 "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window.
5621 This function returns non-nil if `display-buffer' or
5622 `pop-to-buffer' would show a buffer named BUFFER-NAME in the
5623 selected rather than \(as usual\) some other window. See
5624 `same-window-buffer-names' and `same-window-regexps'."
5625 (cond
5626 ((not (stringp buffer-name)))
5627 ;; The elements of `same-window-buffer-names' can be buffer
5628 ;; names or cons cells whose cars are buffer names.
5629 ((member buffer-name same-window-buffer-names))
5630 ((assoc buffer-name same-window-buffer-names))
5631 ((catch 'found
5632 (dolist (regexp same-window-regexps)
5633 ;; The elements of `same-window-regexps' can be regexps
5634 ;; or cons cells whose cars are regexps.
5635 (when (or (and (stringp regexp)
5636 (string-match regexp buffer-name))
5637 (and (consp regexp) (stringp (car regexp))
5638 (string-match-p (car regexp) buffer-name)))
5639 (throw 'found t)))))))
5640 (make-obsolete 'same-window-p "pass argument to buffer display function instead." "24.1")
5642 (defcustom pop-up-frames nil
5643 "Whether `display-buffer' should make a separate frame.
5644 If nil, never make a separate frame.
5645 If the value is `graphic-only', make a separate frame
5646 on graphic displays only.
5647 Any other non-nil value means always make a separate frame."
5648 :type '(choice
5649 (const :tag "Never" nil)
5650 (const :tag "On graphic displays only" graphic-only)
5651 (const :tag "Always" t))
5652 :group 'display-buffer
5653 :group 'frames)
5654 (make-obsolete-variable
5655 'pop-up-frames
5656 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5657 "24.1")
5659 (defcustom display-buffer-reuse-frames nil
5660 "Non-nil means `display-buffer' should reuse frames.
5661 If the buffer in question is already displayed in a frame, raise
5662 that frame."
5663 :type 'boolean
5664 :version "21.1"
5665 :group 'display-buffer
5666 :group 'frames)
5667 (make-obsolete-variable
5668 'display-buffer-reuse-frames
5669 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5670 "24.1")
5672 (defcustom pop-up-windows t
5673 "Non-nil means `display-buffer' is allowed to make a new window.
5674 A non-empty list specifies the windows `display-buffer' will
5675 consider for splitting. The following entries are supported
5676 where \"frame\" refers to the frame chosen to display the buffer:
5678 largest ...... largest window
5679 lru .......... least recently used window
5680 selected ..... frame's selected window
5681 root ......... frame's root window
5683 The default value t stands for the list `(largest lru)'. This
5684 means that `display-buffer' will first try to split the largest
5685 window and, if that fails, the least recently used window."
5686 :type '(choice
5687 (const :tag "Disallow" nil)
5688 (const :tag "Allow" t)
5689 (repeat :tag "Preferences"
5690 (choice
5691 (const :tag "Largest" largest)
5692 (const :tag "Least Recently Used" lru)
5693 (const :tag "Selected" selected)
5694 (const :tag "Frame Root Window" root))))
5695 :group 'display-buffer)
5696 (make-obsolete-variable
5697 'pop-up-windows
5698 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5699 "24.1")
5701 (defcustom split-window-preferred-function 'split-window-sensibly
5702 "Function called by `display-buffer' to split a window.
5703 This function is called with a window as single argument and is
5704 supposed to split that window and return the new window. If the
5705 window can (or shall) not be split, it is supposed to return nil.
5707 The default is to call the function `split-window-sensibly' which
5708 tries to split the window in a way which seems most suitable.
5709 You can customize the options `split-height-threshold' and/or
5710 `split-width-threshold' in order to have `split-window-sensibly'
5711 prefer either vertical or horizontal splitting.
5713 If you set this to any other function, bear in mind that
5714 `display-buffer' may call that function repeatedly; the option
5715 `pop-up-windows' controls which windows may become the argument
5716 of this function.
5718 The window selected at the time `display-buffer' was invoked is
5719 still selected when this function is called. Hence you can
5720 compare the window argument with the value of `selected-window'
5721 if you intend to split the selected window instead or if you do
5722 not want to split the selected window."
5723 :type 'function
5724 :version "23.1"
5725 :group 'display-buffer)
5726 (make-obsolete-variable
5727 'split-window-preferred-function
5728 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5729 "24.1")
5731 (defcustom split-height-threshold 80
5732 "Minimum height for splitting a window to display a buffer.
5733 If this is an integer, `display-buffer' can split a window
5734 vertically only if it has at least this many lines. If this is
5735 nil, `display-buffer' does not split windows vertically. If a
5736 window is the only window on its frame, `display-buffer' may
5737 split it vertically disregarding the value of this variable."
5738 :type '(choice (const nil) (integer :tag "lines"))
5739 :version "23.1"
5740 :group 'display-buffer)
5741 (make-obsolete-variable
5742 'split-height-threshold
5743 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5744 "24.1")
5746 (defcustom split-width-threshold 160
5747 "Minimum width for splitting a window to display a buffer.
5748 If this is an integer, `display-buffer' can split a window
5749 horizontally only if it has at least this many columns. If this
5750 is nil, `display-buffer' cannot split windows horizontally."
5751 :type '(choice (const nil) (integer :tag "columns"))
5752 :version "23.1"
5753 :group 'display-buffer)
5754 (make-obsolete-variable
5755 'split-width-threshold
5756 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5757 "24.1")
5759 (defcustom even-window-heights t
5760 "If non-nil `display-buffer' will try to even window heights.
5761 Otherwise `display-buffer' will leave the window configuration
5762 alone. Heights are evened only when `display-buffer' reuses a
5763 window that appears above or below the selected window."
5764 :type 'boolean
5765 :group 'display-buffer)
5766 (make-obsolete-variable
5767 'even-window-heights
5768 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5769 "24.1")
5771 (defvar display-buffer-mark-dedicated nil
5772 "If non-nil, `display-buffer' marks the windows it creates as dedicated.
5773 The actual non-nil value of this variable will be copied to the
5774 `window-dedicated-p' flag.")
5775 (make-obsolete-variable
5776 'display-buffer-mark-dedicated
5777 "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead."
5778 "24.1")
5780 (defun set-window-text-height (window height)
5781 "Set the height in lines of the text display area of WINDOW to HEIGHT.
5782 WINDOW must be a live window. HEIGHT doesn't include the mode
5783 line or header line, if any, or any partial-height lines in the
5784 text display area.
5786 Note that the current implementation of this function cannot
5787 always set the height exactly, but attempts to be conservative,
5788 by allocating more lines than are actually needed in the case
5789 where some error may be present."
5790 (setq window (normalize-live-window window))
5791 (let ((delta (- height (window-text-height window))))
5792 (unless (zerop delta)
5793 ;; Setting window-min-height to a value like 1 can lead to very
5794 ;; bizarre displays because it also allows Emacs to make *other*
5795 ;; windows 1-line tall, which means that there's no more space for
5796 ;; the modeline.
5797 (let ((window-min-height (min 2 height))) ; One text line plus a modeline.
5798 (resize-window window delta)))))
5800 (defun enlarge-window-horizontally (delta)
5801 "Make selected window DELTA wider.
5802 Interactively, if no argument is given, make selected window one
5803 column wider."
5804 (interactive "p")
5805 (enlarge-window delta t))
5807 (defun shrink-window-horizontally (delta)
5808 "Make selected window DELTA narrower.
5809 Interactively, if no argument is given, make selected window one
5810 column narrower."
5811 (interactive "p")
5812 (shrink-window delta t))
5814 (defun count-screen-lines (&optional beg end count-final-newline window)
5815 "Return the number of screen lines in the region.
5816 The number of screen lines may be different from the number of actual lines,
5817 due to line breaking, display table, etc.
5819 Optional arguments BEG and END default to `point-min' and `point-max'
5820 respectively.
5822 If region ends with a newline, ignore it unless optional third argument
5823 COUNT-FINAL-NEWLINE is non-nil.
5825 The optional fourth argument WINDOW specifies the window used for obtaining
5826 parameters such as width, horizontal scrolling, and so on. The default is
5827 to use the selected window's parameters.
5829 Like `vertical-motion', `count-screen-lines' always uses the current buffer,
5830 regardless of which buffer is displayed in WINDOW. This makes possible to use
5831 `count-screen-lines' in any buffer, whether or not it is currently displayed
5832 in some window."
5833 (unless beg
5834 (setq beg (point-min)))
5835 (unless end
5836 (setq end (point-max)))
5837 (if (= beg end)
5839 (save-excursion
5840 (save-restriction
5841 (widen)
5842 (narrow-to-region (min beg end)
5843 (if (and (not count-final-newline)
5844 (= ?\n (char-before (max beg end))))
5845 (1- (max beg end))
5846 (max beg end)))
5847 (goto-char (point-min))
5848 (1+ (vertical-motion (buffer-size) window))))))
5850 (defun window-buffer-height (window)
5851 "Return the height (in screen lines) of the buffer that WINDOW is displaying."
5852 (with-current-buffer (window-buffer window)
5853 (max 1
5854 (count-screen-lines (point-min) (point-max)
5855 ;; If buffer ends with a newline, ignore it when
5856 ;; counting height unless point is after it.
5857 (eobp)
5858 window))))
5860 ;;; Resizing buffers to fit their contents exactly.
5861 (defun fit-window-to-buffer (&optional window max-height min-height override)
5862 "Adjust height of WINDOW to display its buffer's contents exactly.
5863 WINDOW can be any live window and defaults to the selected one.
5865 Optional argument MAX-HEIGHT specifies the maximum height of
5866 WINDOW and defaults to the height of WINDOW's frame. Optional
5867 argument MIN-HEIGHT specifies the minimum height of WINDOW and
5868 defaults to `window-min-height'. Both, MAX-HEIGHT and MIN-HEIGHT
5869 are specified in lines and include the mode line and header line,
5870 if any.
5872 Optional argument OVERRIDE non-nil means override restrictions
5873 imposed by `window-min-height' and `window-min-width' on the size
5874 of WINDOW.
5876 Return the number of lines by which WINDOW was enlarged or
5877 shrunk. If an error occurs during resizing, return nil but don't
5878 signal an error.
5880 Note that even if this function makes WINDOW large enough to show
5881 _all_ lines of its buffer you might not see the first lines when
5882 WINDOW was scrolled."
5883 (interactive)
5884 ;; Do all the work in WINDOW and its buffer and restore the selected
5885 ;; window and the current buffer when we're done.
5886 (setq window (normalize-live-window window))
5887 ;; Can't resize a full height or fixed-size window.
5888 (unless (or (window-size-fixed-p window)
5889 (window-full-height-p window))
5890 ;; `with-selected-window' should orderly restore the current buffer.
5891 (with-selected-window window
5892 ;; We are in WINDOW's buffer now.
5893 (let* ( ;; Adjust MIN-HEIGHT.
5894 (min-height
5895 (if override
5896 (window-min-size window nil window)
5897 (max (or min-height window-min-height)
5898 window-safe-min-height)))
5899 (max-window-height
5900 (window-total-size (frame-root-window window)))
5901 ;; Adjust MAX-HEIGHT.
5902 (max-height
5903 (if (or override (not max-height))
5904 max-window-height
5905 (min max-height max-window-height)))
5906 ;; Make `desired-height' the height necessary to show
5907 ;; all of WINDOW's buffer, constrained by MIN-HEIGHT
5908 ;; and MAX-HEIGHT.
5909 (desired-height
5910 (max
5911 (min
5912 (+ (count-screen-lines)
5913 ;; For non-minibuffers count the mode line, if any.
5914 (if (and (not (window-minibuffer-p window))
5915 mode-line-format)
5918 ;; Count the header line, if any.
5919 (if header-line-format 1 0))
5920 max-height)
5921 min-height))
5922 (desired-delta
5923 (- desired-height (window-total-size window)))
5924 (delta
5925 (if (> desired-delta 0)
5926 (min desired-delta
5927 (window-max-delta window nil window))
5928 (max desired-delta
5929 (- (window-min-delta window nil window))))))
5930 ;; This `condition-case' shouldn't be necessary, but who knows?
5931 (condition-case nil
5932 (if (zerop delta)
5933 ;; Return zero if DELTA became zero in the proces.
5935 ;; Don't try to redisplay with the cursor at the end on its
5936 ;; own line--that would force a scroll and spoil things.
5937 (when (and (eobp) (bolp) (not (bobp)))
5938 ;; It's silly to put `point' at the end of the previous
5939 ;; line and so maybe force horizontal scrolling.
5940 (set-window-point window (line-beginning-position 0)))
5941 ;; Call `resize-window' with OVERRIDE argument equal WINDOW.
5942 (resize-window window delta nil window)
5943 ;; Check if the last line is surely fully visible. If
5944 ;; not, enlarge the window.
5945 (let ((end (save-excursion
5946 (goto-char (point-max))
5947 (when (and (bolp) (not (bobp)))
5948 ;; Don't include final newline.
5949 (backward-char 1))
5950 (when truncate-lines
5951 ;; If line-wrapping is turned off, test the
5952 ;; beginning of the last line for
5953 ;; visibility instead of the end, as the
5954 ;; end of the line could be invisible by
5955 ;; virtue of extending past the edge of the
5956 ;; window.
5957 (forward-line 0))
5958 (point))))
5959 (set-window-vscroll window 0)
5960 ;; This loop might in some rare pathological cases raise
5961 ;; an error - another reason for the `condition-case'.
5962 (while (and (< desired-height max-height)
5963 (= desired-height (window-total-size))
5964 (not (pos-visible-in-window-p end)))
5965 (resize-window window 1 nil window)
5966 (setq desired-height (1+ desired-height)))))
5967 (error (setq delta nil)))
5968 delta))))
5970 (defun window-safely-shrinkable-p (&optional window)
5971 "Return t if WINDOW can be shrunk without shrinking other windows.
5972 WINDOW defaults to the selected window."
5973 (with-selected-window (or window (selected-window))
5974 (let ((edges (window-edges)))
5975 (or (= (nth 2 edges) (nth 2 (window-edges (previous-window))))
5976 (= (nth 0 edges) (nth 0 (window-edges (next-window))))))))
5978 (defun shrink-window-if-larger-than-buffer (&optional window)
5979 "Shrink height of WINDOW if its buffer doesn't need so many lines.
5980 More precisely, shrink WINDOW vertically to be as small as
5981 possible, while still showing the full contents of its buffer.
5982 WINDOW defaults to the selected window.
5984 Do not shrink WINDOW to less than `window-min-height' lines. Do
5985 nothing if the buffer contains more lines than the present window
5986 height, or if some of the window's contents are scrolled out of
5987 view, or if shrinking this window would also shrink another
5988 window, or if the window is the only window of its frame.
5990 Return non-nil if the window was shrunk, nil otherwise."
5991 (interactive)
5992 (setq window (normalize-live-window window))
5993 ;; Make sure that WINDOW is vertically combined and `point-min' is
5994 ;; visible (for whatever reason that's needed). The remaining issues
5995 ;; should be taken care of by `fit-window-to-buffer'.
5996 (when (and (window-iso-combined-p window)
5997 (pos-visible-in-window-p (point-min) window))
5998 (fit-window-to-buffer window (window-total-size window))))
6000 (defun kill-buffer-and-window ()
6001 "Kill the current buffer and delete the selected window."
6002 (interactive)
6003 (let ((window-to-delete (selected-window))
6004 (buffer-to-kill (current-buffer))
6005 (delete-window-hook (lambda () (ignore-errors (delete-window)))))
6006 (unwind-protect
6007 (progn
6008 (add-hook 'kill-buffer-hook delete-window-hook t t)
6009 (if (kill-buffer (current-buffer))
6010 ;; If `delete-window' failed before, we rerun it to regenerate
6011 ;; the error so it can be seen in the echo area.
6012 (when (eq (selected-window) window-to-delete)
6013 (delete-window))))
6014 ;; If the buffer is not dead for some reason (probably because
6015 ;; of a `quit' signal), remove the hook again.
6016 (ignore-errors
6017 (with-current-buffer buffer-to-kill
6018 (remove-hook 'kill-buffer-hook delete-window-hook t))))))
6020 (defun quit-window (&optional kill window)
6021 "Quit WINDOW and bury its buffer.
6022 With a prefix argument, kill the buffer instead. WINDOW defaults
6023 to the selected window.
6025 If WINDOW is non-nil, dedicated, or a minibuffer window, delete
6026 it and, if it's alone on its frame, its frame too. Otherwise, or
6027 if deleting WINDOW fails in any of the preceding cases, display
6028 another buffer in WINDOW using `switch-to-buffer'.
6030 Optional argument KILL non-nil means kill WINDOW's buffer.
6031 Otherwise, bury WINDOW's buffer, see `bury-buffer'."
6032 (interactive "P")
6033 (let ((buffer (window-buffer window)))
6034 (if (or window
6035 (window-minibuffer-p window)
6036 (window-dedicated-p window))
6037 ;; WINDOW is either non-nil, a minibuffer window, or dedicated;
6038 ;; try to delete it.
6039 (let* ((window (or window (selected-window)))
6040 (frame (window-frame window)))
6041 (if (frame-root-window-p window)
6042 ;; WINDOW is alone on its frame.
6043 (delete-frame frame)
6044 ;; There are other windows on its frame, delete WINDOW.
6045 (delete-window window)))
6046 ;; Otherwise, switch to another buffer in the selected window.
6047 (switch-to-buffer nil))
6049 ;; Deal with the buffer.
6050 (if kill
6051 (kill-buffer buffer)
6052 (bury-buffer buffer))))
6054 (defvar recenter-last-op nil
6055 "Indicates the last recenter operation performed.
6056 Possible values: `top', `middle', `bottom', integer or float numbers.")
6058 (defcustom recenter-positions '(middle top bottom)
6059 "Cycling order for `recenter-top-bottom'.
6060 A list of elements with possible values `top', `middle', `bottom',
6061 integer or float numbers that define the cycling order for
6062 the command `recenter-top-bottom'.
6064 Top and bottom destinations are `scroll-margin' lines the from true
6065 window top and bottom. Middle redraws the frame and centers point
6066 vertically within the window. Integer number moves current line to
6067 the specified absolute window-line. Float number between 0.0 and 1.0
6068 means the percentage of the screen space from the top. The default
6069 cycling order is middle -> top -> bottom."
6070 :type '(repeat (choice
6071 (const :tag "Top" top)
6072 (const :tag "Middle" middle)
6073 (const :tag "Bottom" bottom)
6074 (integer :tag "Line number")
6075 (float :tag "Percentage")))
6076 :version "23.2"
6077 :group 'windows)
6079 (defun recenter-top-bottom (&optional arg)
6080 "Move current buffer line to the specified window line.
6081 With no prefix argument, successive calls place point according
6082 to the cycling order defined by `recenter-positions'.
6084 A prefix argument is handled like `recenter':
6085 With numeric prefix ARG, move current line to window-line ARG.
6086 With plain `C-u', move current line to window center."
6087 (interactive "P")
6088 (cond
6089 (arg (recenter arg)) ; Always respect ARG.
6091 (setq recenter-last-op
6092 (if (eq this-command last-command)
6093 (car (or (cdr (member recenter-last-op recenter-positions))
6094 recenter-positions))
6095 (car recenter-positions)))
6096 (let ((this-scroll-margin
6097 (min (max 0 scroll-margin)
6098 (truncate (/ (window-body-height) 4.0)))))
6099 (cond ((eq recenter-last-op 'middle)
6100 (recenter))
6101 ((eq recenter-last-op 'top)
6102 (recenter this-scroll-margin))
6103 ((eq recenter-last-op 'bottom)
6104 (recenter (- -1 this-scroll-margin)))
6105 ((integerp recenter-last-op)
6106 (recenter recenter-last-op))
6107 ((floatp recenter-last-op)
6108 (recenter (round (* recenter-last-op (window-height))))))))))
6110 (define-key global-map [?\C-l] 'recenter-top-bottom)
6112 (defun move-to-window-line-top-bottom (&optional arg)
6113 "Position point relative to window.
6115 With a prefix argument ARG, acts like `move-to-window-line'.
6117 With no argument, positions point at center of window.
6118 Successive calls position point at positions defined
6119 by `recenter-positions'."
6120 (interactive "P")
6121 (cond
6122 (arg (move-to-window-line arg)) ; Always respect ARG.
6124 (setq recenter-last-op
6125 (if (eq this-command last-command)
6126 (car (or (cdr (member recenter-last-op recenter-positions))
6127 recenter-positions))
6128 (car recenter-positions)))
6129 (let ((this-scroll-margin
6130 (min (max 0 scroll-margin)
6131 (truncate (/ (window-body-height) 4.0)))))
6132 (cond ((eq recenter-last-op 'middle)
6133 (call-interactively 'move-to-window-line))
6134 ((eq recenter-last-op 'top)
6135 (move-to-window-line this-scroll-margin))
6136 ((eq recenter-last-op 'bottom)
6137 (move-to-window-line (- -1 this-scroll-margin)))
6138 ((integerp recenter-last-op)
6139 (move-to-window-line recenter-last-op))
6140 ((floatp recenter-last-op)
6141 (move-to-window-line (round (* recenter-last-op (window-height))))))))))
6143 (define-key global-map [?\M-r] 'move-to-window-line-top-bottom)
6145 ;;; Scrolling commands.
6147 ;;; Scrolling commands which does not signal errors at top/bottom
6148 ;;; of buffer at first key-press (instead moves to top/bottom
6149 ;;; of buffer).
6151 (defcustom scroll-error-top-bottom nil
6152 "Move point to top/bottom of buffer before signalling a scrolling error.
6153 A value of nil means just signal an error if no more scrolling possible.
6154 A value of t means point moves to the beginning or the end of the buffer
6155 \(depending on scrolling direction) when no more scrolling possible.
6156 When point is already on that position, then signal an error."
6157 :type 'boolean
6158 :group 'scrolling
6159 :version "24.1")
6161 (defun scroll-up-command (&optional arg)
6162 "Scroll text of selected window upward ARG lines; or near full screen if no ARG.
6163 If `scroll-error-top-bottom' is non-nil and `scroll-up' cannot
6164 scroll window further, move cursor to the bottom line.
6165 When point is already on that position, then signal an error.
6166 A near full screen is `next-screen-context-lines' less than a full screen.
6167 Negative ARG means scroll downward.
6168 If ARG is the atom `-', scroll downward by nearly full screen."
6169 (interactive "^P")
6170 (cond
6171 ((null scroll-error-top-bottom)
6172 (scroll-up arg))
6173 ((eq arg '-)
6174 (scroll-down-command nil))
6175 ((< (prefix-numeric-value arg) 0)
6176 (scroll-down-command (- (prefix-numeric-value arg))))
6177 ((eobp)
6178 (scroll-up arg)) ; signal error
6180 (condition-case nil
6181 (scroll-up arg)
6182 (end-of-buffer
6183 (if arg
6184 ;; When scrolling by ARG lines can't be done,
6185 ;; move by ARG lines instead.
6186 (forward-line arg)
6187 ;; When ARG is nil for full-screen scrolling,
6188 ;; move to the bottom of the buffer.
6189 (goto-char (point-max))))))))
6191 (put 'scroll-up-command 'scroll-command t)
6193 (defun scroll-down-command (&optional arg)
6194 "Scroll text of selected window down ARG lines; or near full screen if no ARG.
6195 If `scroll-error-top-bottom' is non-nil and `scroll-down' cannot
6196 scroll window further, move cursor to the top line.
6197 When point is already on that position, then signal an error.
6198 A near full screen is `next-screen-context-lines' less than a full screen.
6199 Negative ARG means scroll upward.
6200 If ARG is the atom `-', scroll upward by nearly full screen."
6201 (interactive "^P")
6202 (cond
6203 ((null scroll-error-top-bottom)
6204 (scroll-down arg))
6205 ((eq arg '-)
6206 (scroll-up-command nil))
6207 ((< (prefix-numeric-value arg) 0)
6208 (scroll-up-command (- (prefix-numeric-value arg))))
6209 ((bobp)
6210 (scroll-down arg)) ; signal error
6212 (condition-case nil
6213 (scroll-down arg)
6214 (beginning-of-buffer
6215 (if arg
6216 ;; When scrolling by ARG lines can't be done,
6217 ;; move by ARG lines instead.
6218 (forward-line (- arg))
6219 ;; When ARG is nil for full-screen scrolling,
6220 ;; move to the top of the buffer.
6221 (goto-char (point-min))))))))
6223 (put 'scroll-down-command 'scroll-command t)
6225 ;;; Scrolling commands which scroll a line instead of full screen.
6227 (defun scroll-up-line (&optional arg)
6228 "Scroll text of selected window upward ARG lines; or one line if no ARG.
6229 If ARG is omitted or nil, scroll upward by one line.
6230 This is different from `scroll-up-command' that scrolls a full screen."
6231 (interactive "p")
6232 (scroll-up (or arg 1)))
6234 (put 'scroll-up-line 'scroll-command t)
6236 (defun scroll-down-line (&optional arg)
6237 "Scroll text of selected window down ARG lines; or one line if no ARG.
6238 If ARG is omitted or nil, scroll down by one line.
6239 This is different from `scroll-down-command' that scrolls a full screen."
6240 (interactive "p")
6241 (scroll-down (or arg 1)))
6243 (put 'scroll-down-line 'scroll-command t)
6246 (defun scroll-other-window-down (lines)
6247 "Scroll the \"other window\" down.
6248 For more details, see the documentation for `scroll-other-window'."
6249 (interactive "P")
6250 (scroll-other-window
6251 ;; Just invert the argument's meaning.
6252 ;; We can do that without knowing which window it will be.
6253 (if (eq lines '-) nil
6254 (if (null lines) '-
6255 (- (prefix-numeric-value lines))))))
6257 (defun beginning-of-buffer-other-window (arg)
6258 "Move point to the beginning of the buffer in the other window.
6259 Leave mark at previous position.
6260 With arg N, put point N/10 of the way from the true beginning."
6261 (interactive "P")
6262 (let ((orig-window (selected-window))
6263 (window (other-window-for-scrolling)))
6264 ;; We use unwind-protect rather than save-window-excursion
6265 ;; because the latter would preserve the things we want to change.
6266 (unwind-protect
6267 (progn
6268 (select-window window)
6269 ;; Set point and mark in that window's buffer.
6270 (with-no-warnings
6271 (beginning-of-buffer arg))
6272 ;; Set point accordingly.
6273 (recenter '(t)))
6274 (select-window orig-window))))
6276 (defun end-of-buffer-other-window (arg)
6277 "Move point to the end of the buffer in the other window.
6278 Leave mark at previous position.
6279 With arg N, put point N/10 of the way from the true end."
6280 (interactive "P")
6281 ;; See beginning-of-buffer-other-window for comments.
6282 (let ((orig-window (selected-window))
6283 (window (other-window-for-scrolling)))
6284 (unwind-protect
6285 (progn
6286 (select-window window)
6287 (with-no-warnings
6288 (end-of-buffer arg))
6289 (recenter '(t)))
6290 (select-window orig-window))))
6292 (defvar mouse-autoselect-window-timer nil
6293 "Timer used by delayed window autoselection.")
6295 (defvar mouse-autoselect-window-position nil
6296 "Last mouse position recorded by delayed window autoselection.")
6298 (defvar mouse-autoselect-window-window nil
6299 "Last window recorded by delayed window autoselection.")
6301 (defvar mouse-autoselect-window-state nil
6302 "When non-nil, special state of delayed window autoselection.
6303 Possible values are `suspend' \(suspend autoselection after a menu or
6304 scrollbar interaction\) and `select' \(the next invocation of
6305 'handle-select-window' shall select the window immediately\).")
6307 (defun mouse-autoselect-window-cancel (&optional force)
6308 "Cancel delayed window autoselection.
6309 Optional argument FORCE means cancel unconditionally."
6310 (unless (and (not force)
6311 ;; Don't cancel for select-window or select-frame events
6312 ;; or when the user drags a scroll bar.
6313 (or (memq this-command
6314 '(handle-select-window handle-switch-frame))
6315 (and (eq this-command 'scroll-bar-toolkit-scroll)
6316 (memq (nth 4 (event-end last-input-event))
6317 '(handle end-scroll)))))
6318 (setq mouse-autoselect-window-state nil)
6319 (when (timerp mouse-autoselect-window-timer)
6320 (cancel-timer mouse-autoselect-window-timer))
6321 (remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel)))
6323 (defun mouse-autoselect-window-start (mouse-position &optional window suspend)
6324 "Start delayed window autoselection.
6325 MOUSE-POSITION is the last position where the mouse was seen as returned
6326 by `mouse-position'. Optional argument WINDOW non-nil denotes the
6327 window where the mouse was seen. Optional argument SUSPEND non-nil
6328 means suspend autoselection."
6329 ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND.
6330 (setq mouse-autoselect-window-position mouse-position)
6331 (when window (setq mouse-autoselect-window-window window))
6332 (setq mouse-autoselect-window-state (when suspend 'suspend))
6333 ;; Install timer which runs `mouse-autoselect-window-select' after
6334 ;; `mouse-autoselect-window' seconds.
6335 (setq mouse-autoselect-window-timer
6336 (run-at-time
6337 (abs mouse-autoselect-window) nil 'mouse-autoselect-window-select)))
6339 (defun mouse-autoselect-window-select ()
6340 "Select window with delayed window autoselection.
6341 If the mouse position has stabilized in a non-selected window, select
6342 that window. The minibuffer window is selected only if the minibuffer is
6343 active. This function is run by `mouse-autoselect-window-timer'."
6344 (condition-case nil
6345 (let* ((mouse-position (mouse-position))
6346 (window
6347 (condition-case nil
6348 (window-at (cadr mouse-position) (cddr mouse-position)
6349 (car mouse-position))
6350 (error nil))))
6351 (cond
6352 ((or (menu-or-popup-active-p)
6353 (and window
6354 (not (coordinates-in-window-p (cdr mouse-position) window))))
6355 ;; A menu / popup dialog is active or the mouse is on the scroll-bar
6356 ;; of WINDOW, temporarily suspend delayed autoselection.
6357 (mouse-autoselect-window-start mouse-position nil t))
6358 ((eq mouse-autoselect-window-state 'suspend)
6359 ;; Delayed autoselection was temporarily suspended, reenable it.
6360 (mouse-autoselect-window-start mouse-position))
6361 ((and window (not (eq window (selected-window)))
6362 (or (not (numberp mouse-autoselect-window))
6363 (and (> mouse-autoselect-window 0)
6364 ;; If `mouse-autoselect-window' is positive, select
6365 ;; window if the window is the same as before.
6366 (eq window mouse-autoselect-window-window))
6367 ;; Otherwise select window if the mouse is at the same
6368 ;; position as before. Observe that the first test after
6369 ;; starting autoselection usually fails since the value of
6370 ;; `mouse-autoselect-window-position' recorded there is the
6371 ;; position where the mouse has entered the new window and
6372 ;; not necessarily where the mouse has stopped moving.
6373 (equal mouse-position mouse-autoselect-window-position))
6374 ;; The minibuffer is a candidate window if it's active.
6375 (or (not (window-minibuffer-p window))
6376 (eq window (active-minibuffer-window))))
6377 ;; Mouse position has stabilized in non-selected window: Cancel
6378 ;; delayed autoselection and try to select that window.
6379 (mouse-autoselect-window-cancel t)
6380 ;; Select window where mouse appears unless the selected window is the
6381 ;; minibuffer. Use `unread-command-events' in order to execute pre-
6382 ;; and post-command hooks and trigger idle timers. To avoid delaying
6383 ;; autoselection again, set `mouse-autoselect-window-state'."
6384 (unless (window-minibuffer-p (selected-window))
6385 (setq mouse-autoselect-window-state 'select)
6386 (setq unread-command-events
6387 (cons (list 'select-window (list window))
6388 unread-command-events))))
6389 ((or (and window (eq window (selected-window)))
6390 (not (numberp mouse-autoselect-window))
6391 (equal mouse-position mouse-autoselect-window-position))
6392 ;; Mouse position has either stabilized in the selected window or at
6393 ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
6394 (mouse-autoselect-window-cancel t))
6396 ;; Mouse position has not stabilized yet, resume delayed
6397 ;; autoselection.
6398 (mouse-autoselect-window-start mouse-position window))))
6399 (error nil)))
6401 (defun handle-select-window (event)
6402 "Handle select-window events."
6403 (interactive "e")
6404 (let ((window (posn-window (event-start event))))
6405 (unless (or (not (window-live-p window))
6406 ;; Don't switch if we're currently in the minibuffer.
6407 ;; This tries to work around problems where the
6408 ;; minibuffer gets unselected unexpectedly, and where
6409 ;; you then have to move your mouse all the way down to
6410 ;; the minibuffer to select it.
6411 (window-minibuffer-p (selected-window))
6412 ;; Don't switch to minibuffer window unless it's active.
6413 (and (window-minibuffer-p window)
6414 (not (minibuffer-window-active-p window)))
6415 ;; Don't switch when autoselection shall be delayed.
6416 (and (numberp mouse-autoselect-window)
6417 (not (zerop mouse-autoselect-window))
6418 (not (eq mouse-autoselect-window-state 'select))
6419 (progn
6420 ;; Cancel any delayed autoselection.
6421 (mouse-autoselect-window-cancel t)
6422 ;; Start delayed autoselection from current mouse
6423 ;; position and window.
6424 (mouse-autoselect-window-start (mouse-position) window)
6425 ;; Executing a command cancels delayed autoselection.
6426 (add-hook
6427 'pre-command-hook 'mouse-autoselect-window-cancel))))
6428 (when mouse-autoselect-window
6429 ;; Reset state of delayed autoselection.
6430 (setq mouse-autoselect-window-state nil)
6431 ;; Run `mouse-leave-buffer-hook' when autoselecting window.
6432 (run-hooks 'mouse-leave-buffer-hook))
6433 (select-window window))))
6435 (defun truncated-partial-width-window-p (&optional window)
6436 "Return non-nil if lines in WINDOW are specifically truncated due to its width.
6437 WINDOW defaults to the selected window.
6438 Return nil if WINDOW is not a partial-width window
6439 (regardless of the value of `truncate-lines').
6440 Otherwise, consult the value of `truncate-partial-width-windows'
6441 for the buffer shown in WINDOW."
6442 (unless window
6443 (setq window (selected-window)))
6444 (unless (window-full-width-p window)
6445 (let ((t-p-w-w (buffer-local-value 'truncate-partial-width-windows
6446 (window-buffer window))))
6447 (if (integerp t-p-w-w)
6448 (< (window-width window) t-p-w-w)
6449 t-p-w-w))))
6451 (define-key ctl-x-map "0" 'delete-window)
6452 (define-key ctl-x-map "1" 'delete-other-windows)
6453 (define-key ctl-x-map "2" 'split-window-vertically)
6454 (define-key ctl-x-map "3" 'split-window-horizontally)
6455 (define-key ctl-x-map "9" 'maximize-window)
6456 (define-key ctl-x-map "o" 'other-window)
6457 (define-key ctl-x-map "^" 'enlarge-window)
6458 (define-key ctl-x-map "}" 'enlarge-window-horizontally)
6459 (define-key ctl-x-map "{" 'shrink-window-horizontally)
6460 (define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer)
6461 (define-key ctl-x-map "+" 'balance-windows)
6462 (define-key ctl-x-4-map "0" 'kill-buffer-and-window)
6464 ;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9
6465 ;;; window.el ends here