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