comparison lisp/prim/window.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 0293115a14e9
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; window.el --- XEmacs window commands aside from those written in C.
2 ;; Keywords: extensions
3
4 ;; Copyright (C) 1985, 1989, 1993, 1994 Free Software Foundation, Inc.
5 ;; Copyright (C) 1995, 1996 Ben Wing.
6
7 ;; This file is part of XEmacs.
8
9 ;; XEmacs is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; XEmacs is distributed in the hope that it will be useful, but
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ;; General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with XEmacs; see the file COPYING. If not, write to the Free
21 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 ;;; Synched up with: FSF 19.30.
24
25 ;;;; Window tree functions.
26
27 (defun one-window-p (&optional nomini all-frames device)
28 "Returns non-nil if the selected window is the only window (in its frame).
29 Optional arg NOMINI non-nil means don't count the minibuffer
30 even if it is active.
31
32 The optional arg ALL-FRAMES t means count windows on all frames.
33 If it is `visible', count windows on all visible frames.
34 ALL-FRAMES nil or omitted means count only the selected frame,
35 plus the minibuffer it uses (which may be on another frame).
36 ALL-FRAMES = 0 means count windows on all visible and iconified frames.
37 If ALL-FRAMES is any other value, count only the selected frame.
38
39 If optional third argument DEVICE is nil or omitted, count frames
40 on all devices.
41 If a device, count frames only on that device.
42 If a device type, count frames only on devices of that type.
43 Otherwise, count frames only on the selected device."
44 (let ((base-window (selected-window)))
45 (if (and nomini (eq base-window (minibuffer-window)))
46 (setq base-window (next-window base-window)))
47 (eq base-window
48 (next-window base-window (if nomini 'arg) all-frames device))))
49
50 (defun walk-windows (proc &optional minibuf all-frames device)
51 "Cycle through all visible windows, calling PROC for each one.
52 PROC is called with a window as argument.
53
54 Optional second arg MINIBUF t means count the minibuffer window even
55 if not active. MINIBUF nil or omitted means count the minibuffer iff
56 it is active. MINIBUF neither t nor nil means not to count the
57 minibuffer even if it is active.
58
59 Several frames may share a single minibuffer; if the minibuffer
60 counts, all windows on all frames that share that minibuffer count
61 too. Therefore, when a separate minibuffer frame is active,
62 `walk-windows' includes the windows in the frame from which you
63 entered the minibuffer, as well as the minibuffer window. But if the
64 minibuffer does not count, only windows from WINDOW's frame count.
65
66 ALL-FRAMES is the optional third argument.
67 ALL-FRAMES nil or omitted means cycle within the frames as specified above.
68 ALL-FRAMES = `visible' means include windows on all visible frames.
69 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
70 ALL-FRAMES = t means include windows on all frames including invisible frames.
71 Anything else means restrict to WINDOW's frame.
72
73 If optional fourth argument DEVICE is nil or omitted, include frames
74 on all devices.
75 If a device, include frames only on that device.
76 If a device type, include frames only on devices of that type.
77 Otherwise, include frames only on the selected device."
78 ;; If we start from the minibuffer window, don't fail to come back to it.
79 (if (window-minibuffer-p (selected-window))
80 (setq minibuf t))
81 ;; Note that, like next-window & previous-window, this behaves a little
82 ;; strangely if the selected window is on an invisible frame: it hits
83 ;; some of the windows on that frame, and all windows on visible frames.
84 (let* ((walk-windows-start (selected-window))
85 (walk-windows-current walk-windows-start))
86 (while (progn
87 (setq walk-windows-current
88 (next-window walk-windows-current minibuf all-frames
89 device))
90 (funcall proc walk-windows-current)
91 (not (eq walk-windows-current walk-windows-start))))))
92 ;; The old XEmacs definition of the above clause. It's more correct in
93 ;; that it will never hit a window that's already been hit even if you
94 ;; do something odd like `delete-other-windows', but has the problem
95 ;; that it conses. (This may be called repeatedly, from lazy-lock
96 ;; for example.)
97 ; (let* ((walk-windows-history nil)
98 ; (walk-windows-current (selected-window)))
99 ; (while (progn
100 ; (setq walk-windows-current
101 ; (next-window walk-windows-current minibuf all-frames
102 ; device))
103 ; (not (memq walk-windows-current walk-windows-history)))
104 ; (setq walk-windows-history (cons walk-windows-current
105 ; walk-windows-history))
106 ; (funcall proc walk-windows-current))))
107
108 (defun minibuffer-window-active-p (window)
109 "Return t if WINDOW (a minibuffer window) is now active."
110 (eq window (active-minibuffer-window)))
111
112 (defmacro save-selected-window (&rest body)
113 "Execute BODY, then select the window that was selected before BODY."
114 (list 'let
115 '((save-selected-window-window (selected-window)))
116 (list 'unwind-protect
117 (cons 'progn body)
118 (list 'and
119 (list 'window-live-p 'save-selected-window-window)
120 (list 'select-window 'save-selected-window-window)))))
121
122 (defun count-windows (&optional minibuf)
123 "Returns the number of visible windows.
124 Optional arg NO-MINI non-nil means don't count the minibuffer
125 even if it is active."
126 (let ((count 0))
127 (walk-windows (function (lambda (w)
128 (setq count (+ count 1))))
129 minibuf)
130 count))
131
132 (defun balance-windows ()
133 "Makes all visible windows the same height (approximately)."
134 (interactive)
135 (let ((count -1) levels newsizes size)
136 ;FSFmacs
137 ;;; Don't count the lines that are above the uppermost windows.
138 ;;; (These are the menu bar lines, if any.)
139 ;(mbl (nth 1 (window-edges (frame-first-window (selected-frame))))))
140 ;; Find all the different vpos's at which windows start,
141 ;; then count them. But ignore levels that differ by only 1.
142 (save-window-excursion
143 (let (tops (prev-top -2))
144 (walk-windows (function (lambda (w)
145 (setq tops (cons (nth 1 (window-pixel-edges w))
146 tops))))
147 'nomini)
148 (setq tops (sort tops '<))
149 (while tops
150 (if (> (car tops) (1+ prev-top))
151 (setq prev-top (car tops)
152 count (1+ count)))
153 (setq levels (cons (cons (car tops) count) levels))
154 (setq tops (cdr tops)))
155 (setq count (1+ count))))
156 ;; Subdivide the frame into that many vertical levels.
157 ;FSFmacs (setq size (/ (- (frame-height) mbl) count))
158 (setq size (/ (window-pixel-height (frame-root-window)) count))
159 (walk-windows (function (lambda (w)
160 (select-window w)
161 (let ((newtop (cdr (assq (nth 1 (window-pixel-edges))
162 levels)))
163 (newbot (or (cdr (assq
164 (+ (window-pixel-height)
165 (nth 1 (window-pixel-edges)))
166 levels))
167 count)))
168 (setq newsizes
169 (cons (cons w (* size (- newbot newtop)))
170 newsizes)))))
171 'nomini)
172 (walk-windows (function (lambda (w)
173 (select-window w)
174 (let ((newsize (cdr (assq w newsizes))))
175 (enlarge-window
176 (/ (- newsize (window-pixel-height))
177 (face-height 'default))))))
178 'nomini)))
179
180 ;;; I think this should be the default; I think people will prefer it--rms.
181 (defvar split-window-keep-point t
182 "*If non-nil, split windows keeps the original point in both children.
183 This is often more convenient for editing.
184 If nil, adjust point in each of the two windows to minimize redisplay.
185 This is convenient on slow terminals, but point can move strangely.")
186
187 (defun split-window-vertically (&optional arg)
188 "Split current window into two windows, one above the other.
189 The uppermost window gets ARG lines and the other gets the rest.
190 Negative arg means select the size of the lowermost window instead.
191 With no argument, split equally or close to it.
192 Both windows display the same buffer now current.
193
194 If the variable split-window-keep-point is non-nil, both new windows
195 will get the same value of point as the current window. This is often
196 more convenient for editing.
197
198 Otherwise, we chose window starts so as to minimize the amount of
199 redisplay; this is convenient on slow terminals. The new selected
200 window is the one that the current value of point appears in. The
201 value of point can change if the text around point is hidden by the
202 new modeline.
203
204 Programs should probably use split-window instead of this."
205 (interactive "P")
206 (let ((old-w (selected-window))
207 (old-point (point))
208 (size (and arg (prefix-numeric-value arg)))
209 new-w bottom)
210 (and size (< size 0) (setq size (+ (window-height) size)))
211 (setq new-w (split-window nil size))
212 (or split-window-keep-point
213 (progn
214 (save-excursion
215 (set-buffer (window-buffer))
216 (goto-char (window-start))
217 (vertical-motion (window-height))
218 (set-window-start new-w (point))
219 (if (> (point) (window-point new-w))
220 (set-window-point new-w (point)))
221 (vertical-motion -1)
222 (setq bottom (point)))
223 (if (<= bottom (point))
224 (set-window-point old-w (1- bottom)))
225 (if (< (window-start new-w) old-point)
226 (progn
227 (set-window-point new-w old-point)
228 (select-window new-w)))))
229 new-w))
230
231 (defun split-window-horizontally (&optional arg)
232 "Split current window into two windows side by side.
233 This window becomes the leftmost of the two, and gets ARG columns.
234 Negative arg means select the size of the rightmost window instead.
235 No arg means split equally."
236 (interactive "P")
237 (let ((size (and arg (prefix-numeric-value arg))))
238 (and size (< size 0)
239 (setq size (+ (window-width) size)))
240 (split-window nil size t)))
241
242 (defun enlarge-window-horizontally (arg)
243 "Make current window ARG columns wider."
244 (interactive "p")
245 (enlarge-window arg t))
246
247 (defun shrink-window-horizontally (arg)
248 "Make current window ARG columns narrower."
249 (interactive "p")
250 (shrink-window arg t))
251
252 (defun shrink-window-if-larger-than-buffer (&optional window)
253 "Shrink the WINDOW to be as small as possible to display its contents.
254 Do not shrink to less than `window-min-height' lines.
255 Do nothing if the buffer contains more lines than the present window height,
256 or if some of the window's contents are scrolled out of view,
257 or if the window is not the full width of the frame,
258 or if the window is the only window of its frame."
259 (interactive)
260 (or window (setq window (selected-window)))
261 (save-excursion
262 (set-buffer (window-buffer window))
263 (let* ((w (selected-window)) ;save-window-excursion can't win
264 (buffer-file-name buffer-file-name)
265 (p (point))
266 (n 0)
267 (ignore-final-newline
268 ;; If buffer ends with a newline, ignore it when counting height
269 ;; unless point is after it.
270 (and (not (eobp))
271 (eq ?\n (char-after (1- (point-max))))))
272 (buffer-read-only nil)
273 (modified (buffer-modified-p))
274 (buffer (current-buffer))
275 (mini (frame-property (window-frame window) 'minibuffer))
276 (edges (window-pixel-edges (selected-window))))
277 (if (and (< 1 (let ((frame (selected-frame)))
278 (select-frame (window-frame window))
279 (unwind-protect
280 (count-windows)
281 (select-frame frame))))
282 ;; check to make sure that we don't have horizontally
283 ;; split windows
284 (eq (frame-highest-window (window-frame window) 0)
285 (frame-highest-window (window-frame window) -1))
286 (pos-visible-in-window-p (point-min) window)
287 (not (eq mini 'only))
288 (or (not mini) (eq mini t)
289 (< (nth 3 edges)
290 (nth 1 (window-pixel-edges mini)))
291 (> (nth 1 edges)
292 ;FSFmacs (frame-property (window-frame window)
293 ; 'menu-bar-lines params)
294 0)))
295 (unwind-protect
296 (progn
297 (select-window (or window w))
298 (goto-char (point-min))
299 (while (pos-visible-in-window-p
300 (- (point-max)
301 (if ignore-final-newline 1 0)))
302 ;; defeat file locking... don't try this at home, kids!
303 (setq buffer-file-name nil)
304 (insert ?\n) (setq n (1+ n)))
305 (if (> n 0)
306 (shrink-window (min (1- n)
307 (- (window-height)
308 window-min-height)))))
309 (delete-region (point-min) (point))
310 (set-buffer-modified-p modified)
311 (goto-char p)
312 (select-window w)
313 ;; Make sure we unbind buffer-read-only
314 ;; with the proper current buffer.
315 (set-buffer buffer))))))
316
317 (defun backward-other-window (arg &optional all-frames device)
318 "Select the ARG'th different window on this frame, going backwards.
319 This is just like calling `other-window' with the arg negated."
320 (interactive "p")
321 (other-window (- arg) all-frames device))
322
323 (defun windows-of-buffer (&optional buffer)
324 "Returns a list of windows that have BUFFER in them.
325 If BUFFER is not specified, the current buffer will be used."
326 (or (bufferp buffer)
327 (if (stringp buffer)
328 (setq buffer (or (get-buffer buffer)
329 (get-file-buffer buffer)))
330 (setq buffer (current-buffer))))
331 (let* ((firstwin (next-window nil nil t))
332 (wind firstwin)
333 (done nil)
334 window-list)
335 (while (not done)
336 (if (eq (window-buffer wind) buffer)
337 (setq window-list (append window-list (list wind))))
338 (setq wind (next-window wind nil t))
339 (setq done (eq wind firstwin)))
340 window-list))
341
342 (defun buffer-in-multiple-windows-p (&optional buffer)
343 "Returns t if BUFFER is in multiple windows.
344 If BUFFER is not specified, the current buffer will be used."
345 (setq buffer (or buffer
346 (get-buffer buffer)
347 (get-file-buffer buffer)
348 (current-buffer)))
349 (> (length (windows-of-buffer buffer)) 1))
350
351 (defun window-list (&optional frame minibuf window)
352 "Return a list of windows on FRAME, beginning with WINDOW.
353 FRAME and WINDOW default to the selected ones.
354 Optional second arg MINIBUF t means count the minibuffer window
355 even if not active. If MINIBUF is neither t nor nil it means
356 not to count the minibuffer even if it is active."
357 (setq window (or window (selected-window))
358 frame (or frame (selected-frame)))
359 (if (not (eq (window-frame window) frame))
360 (error "Window must be on frame."))
361 (let ((current-frame (selected-frame))
362 list)
363 (unwind-protect
364 (save-window-excursion
365 (select-frame frame)
366 (walk-windows
367 (function (lambda (cur-window)
368 (if (not (eq window cur-window))
369 (setq list (cons cur-window list)))))
370 minibuf)
371 (setq list (cons window list)))
372 (select-frame current-frame))))
373
374 ;; We used to have set-window-dedicated-p as an obsolete version
375 ;; of set-window-buffer-dedicated, but it really makes more sense
376 ;; this way.
377
378 (make-obsolete 'set-window-buffer-dedicated 'set-window-dedicated-p)
379 (defun set-window-buffer-dedicated (window buffer)
380 "Make WINDOW display BUFFER and be dedicated to that buffer.
381 Then Emacs will not automatically change which buffer appears in WINDOW.
382 If BUFFER is nil, make WINDOW not be dedicated (but don't change which
383 buffer appears in it currently)."
384 (if (bufferp buffer)
385 (set-window-buffer window (get-buffer-create buffer)))
386 (set-window-dedicated-p window (not (null buffer))))
387
388
389 ;; The window-config stack is stored as a list in frame property
390 ;; 'window-config-stack, with the most recent element at the front.
391 ;; When you pop off an element, the popped off element gets put at the
392 ;; front of frame property 'window-config-unpop-stack, so you can
393 ;; retrieve it using unpop-window-configuration.
394
395 (defvar window-config-stack-max 16
396 "*Maximum size of window configuration stack.
397 Start discarding off end if it gets this big.")
398
399 (defun window-config-stack (&optional frame)
400 (or frame (setq frame (selected-frame)))
401 (let ((stack (frame-property frame 'window-config-stack)))
402 (if stack
403 (set-undoable-stack-max stack window-config-stack-max)
404 (progn
405 (setq stack (make-undoable-stack window-config-stack-max))
406 (set-frame-property frame 'window-config-stack stack)))
407 stack))
408
409 (defun push-window-configuration (&optional config)
410 "Push the current window configuration onto the window-config stack.
411 If CONFIG is specified, push it instead of the current window configuration.
412 Each frame has its own window-config stack."
413 (interactive)
414 (let ((wc (or config (current-window-configuration)))
415 (stack (window-config-stack)))
416 (if (or (= 0 (undoable-stack-a-length stack))
417 (not (equal (undoable-stack-a-top stack) wc)))
418 (progn
419 (undoable-stack-push stack wc)
420 ;; kludge.
421 (if (featurep 'toolbar)
422 (set-specifier-dirty-flag default-toolbar))))))
423
424 (defun pop-window-configuration ()
425 "Pop the top window configuration off the window-config stack and set it.
426 Before setting the new window configuration, the current window configuration
427 is pushed onto the \"unpop\" stack.
428 `unpop-window-configuration' undoes what this function does.
429 Each frame has its own window-config and \"unpop\" stack."
430 (interactive)
431 (let ((stack (window-config-stack))
432 (wc (current-window-configuration))
433 popped)
434 (condition-case nil
435 (progn
436 (setq popped (undoable-stack-pop stack))
437 (while (equal popped wc)
438 (setq popped (undoable-stack-pop stack)))
439 (undoable-stack-push stack wc)
440 (undoable-stack-undo stack)
441 (set-window-configuration popped)
442 ;; probably not necessary:
443 (if (featurep 'toolbar)
444 (set-specifier-dirty-flag default-toolbar))
445 popped)
446 (trunc-stack-bottom
447 (error "Bottom of window config stack")))))
448
449 (defun unpop-window-configuration ()
450 "Undo the effect of the most recent `pop-window-configuration'.
451 This does exactly the inverse of what `pop-window-configuration' does:
452 i.e. it pops a window configuration off of the \"unpop\" stack and
453 pushes the current window configuration onto the window-config stack.
454 Each frame has its own window-config and \"unpop\" stack."
455 (interactive)
456 (let ((stack (window-config-stack))
457 (wc (current-window-configuration))
458 popped)
459 (condition-case nil
460 (progn
461 (setq popped
462 (progn
463 (undoable-stack-redo stack)
464 (undoable-stack-pop stack)))
465 (while (equal popped wc)
466 (setq popped
467 (progn
468 (undoable-stack-redo stack)
469 (undoable-stack-pop stack))))
470 (undoable-stack-push stack wc)
471 (set-window-configuration popped)
472 ;; probably not necessary:
473 (if (featurep 'toolbar)
474 (set-specifier-dirty-flag default-toolbar))
475 popped)
476 (trunc-stack-bottom
477 (error "Top of window config stack")))))
478
479
480 ;;;;;;;;;;;;; display-buffer, moved here from C. Hallelujah.
481
482 (defvar display-buffer-function nil
483 "If non-nil, function to call to handle `display-buffer'.
484 It will receive three args: the same as those to `display-buffer'.")
485
486 (defvar pre-display-buffer-function nil
487 "If non-nil, function that will be called from `display-buffer'
488 as the first action. It will receive three args: the same as those
489 to `display-buffer'.
490 This function may be used to select an appropriate frame for the buffer,
491 for example. See also the variable `display-buffer-function', which may
492 be used to completely replace the `display-buffer' function.
493 If the return value of this function is non-nil, it should be a frame,
494 and that frame will be used to display the buffer.")
495
496 (defvar pop-up-frames nil
497 "*Non-nil means `display-buffer' should make a separate frame.")
498
499 (defvar pop-up-frame-function nil
500 "Function to call to handle automatic new frame creation.
501 It is called with no arguments and should return a newly created frame.
502
503 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
504 where `pop-up-frame-alist' would hold the default frame parameters.")
505
506 (defvar special-display-buffer-names nil
507 "*List of buffer names that should have their own special frames.
508 Displaying a buffer whose name is in this list makes a special frame for it
509 using `special-display-function'.
510
511 An element of the list can be a cons cell instead of just a string.
512 Then the car should be a buffer name, and the cdr specifies frame
513 parameters for creating the frame for that buffer.
514 More precisely, the cdr is passed as the second argument to
515 the function found in `special-display-function', when making that frame.
516 See also `special-display-regexps'.")
517
518 (defvar special-display-regexps nil
519 "*List of regexps saying which buffers should have their own special frames.
520 If a buffer name matches one of these regexps, it gets its own frame.
521 Displaying a buffer whose name is in this list makes a special frame for it
522 using `special-display-function'.
523
524 An element of the list can be a cons cell instead of just a string.
525 Then the car should be the regexp, and the cdr specifies frame
526 parameters for creating the frame for buffers that match.
527 More precisely, the cdr is passed as the second argument to
528 the function found in `special-display-function', when making that frame.
529 See also `special-display-buffer-names'.")
530
531 (defvar special-display-function nil
532 "Function to call to make a new frame for a special buffer.
533 It is called with two arguments, the buffer and optional buffer specific
534 data, and should return a window displaying that buffer.
535 The default value makes a separate frame for the buffer,
536 using `special-display-frame-alist' to specify the frame parameters.
537
538 A buffer is special if its is listed in `special-display-buffer-names'
539 or matches a regexp in `special-display-regexps'.")
540
541 (defvar same-window-buffer-names nil
542 "*List of buffer names that should appear in the selected window.
543 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
544 switches to it in the selected window, rather than making it appear
545 in some other window.
546
547 An element of the list can be a cons cell instead of just a string.
548 Then the car must be a string, which specifies the buffer name.
549 This is for compatibility with `special-display-buffer-names';
550 the cdr of the cons cell is ignored.
551
552 See also `same-window-regexps'.")
553
554 (defvar same-window-regexps nil
555 "*List of regexps saying which buffers should appear in the selected window.
556 If a buffer name matches one of these regexps, then displaying it
557 using `display-buffer' or `pop-to-buffer' switches to it
558 in the selected window, rather than making it appear in some other window.
559
560 An element of the list can be a cons cell instead of just a string.
561 Then the car must be a string, which specifies the buffer name.
562 This is for compatibility with `special-display-buffer-names';
563 the cdr of the cons cell is ignored.
564
565 See also `same-window-buffer-names'.")
566
567 (defvar pop-up-windows t
568 "*Non-nil means display-buffer should make new windows.")
569
570 (defvar split-height-threshold 500
571 "*display-buffer would prefer to split the largest window if this large.
572 If there is only one window, it is split regardless of this value.")
573
574 (defvar split-width-threshold 500
575 "*display-buffer would prefer to split the largest window if this large.
576 If there is only one window, it is split regardless of this value.")
577
578 ;; Deiconify the frame containing the window WINDOW, then return WINDOW.
579
580 (defun display-buffer-1 (window)
581 (if (frame-iconified-p (window-frame window))
582 (make-frame-visible (window-frame window)))
583 window)
584
585 ;; Can you believe that all of this crap was formerly in C?
586 ;; Praise Jesus that it's not there any more.
587
588 (defun display-buffer (buffer &optional not-this-window-p override-frame)
589 "Make BUFFER appear in some window on the current frame, but don't select it.
590 BUFFER can be a buffer or a buffer name.
591 If BUFFER is shown already in some window in the current frame,
592 just uses that one, unless the window is the selected window and
593 NOT-THIS-WINDOW-P is non-nil (interactively, with prefix arg).
594
595 If BUFFER has a dedicated frame, display on that frame instead of
596 the current frame, unless OVERRIDE-FRAME is non-nil.
597
598 If OVERRIDE-FRAME is non-nil, display on that frame instead of
599 the current frame (or the dedicated frame).
600
601 If `pop-up-windows' is non-nil, always use the
602 current frame and create a new window regardless of whether the
603 buffer has a dedicated frame, and regardless of whether
604 OVERRIDE-FRAME was specified.
605
606 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
607
608 Returns the window displaying BUFFER."
609 (interactive "BDisplay buffer:\nP")
610
611 (let ((wconfig (current-window-configuration))
612 (result
613 ;; We just simulate a `return' in C. This function is way ugly
614 ;; and does `returns' all over the place and there's no sense
615 ;; in trying to rewrite it to be more Lispy.
616 (catch 'done
617 (let (window old-frame target-frame explicit-frame)
618 (setq old-frame (or (last-nonminibuf-frame) (selected-frame)))
619 (setq buffer (get-buffer buffer))
620 (check-argument-type 'bufferp buffer)
621
622 (setq explicit-frame
623 (if pre-display-buffer-function
624 (funcall pre-display-buffer-function buffer
625 not-this-window-p
626 override-frame)))
627
628 ;; Give the user the ability to completely reimplement
629 ;; this function via the `display-buffer-function'.
630 (if display-buffer-function
631 (throw 'done
632 (funcall display-buffer-function buffer
633 not-this-window-p
634 override-frame)))
635
636 ;; If the buffer has a dedicated frame, that takes
637 ;; precedence over the current frame, and over what the
638 ;; pre-display-buffer-function did.
639 (let ((dedi (buffer-dedicated-frame buffer)))
640 (if (frame-live-p dedi) (setq explicit-frame dedi)))
641
642 ;; if override-frame is supplied, that takes precedence over
643 ;; everything. This is gonna look bad if the
644 ;; pre-display-buffer-function raised some other frame
645 ;; already.
646 (if override-frame
647 (progn
648 (check-argument-type 'frame-live-p override-frame)
649 (setq explicit-frame override-frame)))
650
651 (setq target-frame
652 (or explicit-frame
653 (last-nonminibuf-frame)
654 (selected-frame)))
655
656 ;; If we have switched frames, then set not-this-window-p
657 ;; to false. Switching frames means that selected-window
658 ;; is no longer the same as it was on entry -- it's the
659 ;; selected-window of target_frame instead of old_frame,
660 ;; so it's a fine candidate for display.
661 (if (not (eq old-frame target-frame))
662 (setq not-this-window-p nil))
663
664 ;; if it's in the selected window, and that's ok, then we're done.
665 (if (and (not not-this-window-p)
666 (eq buffer (window-buffer (selected-window))))
667 (throw 'done (display-buffer-1 (selected-window))))
668
669 ;; See if the user has specified this buffer should appear
670 ;; in the selected window.
671
672 (if not-this-window-p
673 nil
674
675 (if (or (member (buffer-name buffer) same-window-buffer-names)
676 (assoc (buffer-name buffer) same-window-buffer-names))
677 (progn
678 (switch-to-buffer buffer)
679 (throw 'done (display-buffer-1 (selected-window)))))
680
681 (let ((tem same-window-regexps))
682 (while tem
683 (let ((car (car tem)))
684 (if (or
685 (and (stringp car)
686 (string-match car (buffer-name buffer)))
687 (and (consp car) (stringp (car car))
688 (string-match (car car) (buffer-name buffer))))
689 (progn
690 (switch-to-buffer buffer)
691 (throw 'done (display-buffer-1
692 (selected-window))))))
693 (setq tem (cdr tem)))))
694
695 ;; If pop-up-frames, look for a window showing BUFFER on
696 ;; any visible or iconified frame. Otherwise search only
697 ;; the current frame.
698 (if (and (not explicit-frame)
699 (or pop-up-frames (not (last-nonminibuf-frame))))
700 (setq target-frame 0))
701
702 ;; Otherwise, find some window that it's already in, and
703 ;; return that, unless that window is the selected window
704 ;; and that isn't ok. What a contorted mess!
705 (setq window (get-buffer-window buffer target-frame))
706 (if (and window
707 (or (not not-this-window-p)
708 (not (eq window (selected-window)))))
709 (throw 'done (display-buffer-1 window)))
710
711 ;; Certain buffer names get special handling.
712 (if special-display-function
713 (progn
714 (if (member (buffer-name buffer)
715 special-display-buffer-names)
716 (throw 'done (funcall special-display-function buffer)))
717
718 (let ((tem (assoc (buffer-name buffer)
719 special-display-buffer-names)))
720 (if tem
721 (throw 'done (funcall special-display-function
722 buffer (cdr tem)))))
723
724 (let ((tem special-display-regexps))
725 (while tem
726 (let ((car (car tem)))
727 (if (and (stringp car)
728 (string-match car (buffer-name buffer)))
729 (throw 'done
730 (funcall special-display-function buffer)))
731 (if (and (consp car)
732 (stringp (car car))
733 (string-match (car car)
734 (buffer-name buffer)))
735 (throw 'done (funcall
736 special-display-function buffer
737 (cdr car)))))
738 (setq tem (cdr tem))))))
739
740 ;; If there are no frames open that have more than a minibuffer,
741 ;; we need to create a new frame.
742 (if (or pop-up-frames
743 (null (last-nonminibuf-frame)))
744 (progn
745 (setq window (frame-selected-window
746 (funcall pop-up-frame-function)))
747 (set-window-buffer window buffer)
748 (throw 'done (display-buffer-1 window))))
749
750 ;; Otherwise, make it be in some window, splitting if
751 ;; appropriate/possible. Do not split a window if we are
752 ;; displaying the buffer in a different frame than that which
753 ;; was current when we were called. (It is already in a
754 ;; different window by virtue of being in another frame.)
755 (if (or (and pop-up-windows (eq target-frame old-frame))
756 (eq 'only (frame-property (selected-frame) 'minibuffer))
757 ;; If the current frame is a special display frame,
758 ;; don't try to reuse its windows.
759 (window-dedicated-p (frame-root-window (selected-frame))))
760 (progn
761 (if (eq 'only (frame-property (selected-frame) 'minibuffer))
762 (setq target-frame (last-nonminibuf-frame)))
763
764 ;; Don't try to create a window if would get an error with
765 ;; height.
766 (if (< split-height-threshold (* 2 window-min-height))
767 (setq split-height-threshold (* 2 window-min-height)))
768
769 ;; Same with width.
770 (if (< split-width-threshold (* 2 window-min-width))
771 (setq split-width-threshold (* 2 window-min-width)))
772
773 ;; If the frame we would try to split cannot be split,
774 ;; try other frames.
775 (if (frame-property (if (null target-frame)
776 (selected-frame)
777 (last-nonminibuf-frame))
778 'unsplittable)
779 (setq window
780 ;; Try visible frames first.
781 (or (get-largest-window 'visible)
782 ;; If that didn't work, try iconified frames.
783 (get-largest-window 0)
784 (get-largest-window t)))
785 (setq window (get-largest-window target-frame)))
786
787 ;; If we got a tall enough full-width window that
788 ;; can be split, split it.
789 (if (and window
790 (not (frame-property (window-frame window)
791 'unsplittable))
792 (>= (window-height window) split-height-threshold)
793 (or (>= (window-width window)
794 split-width-threshold)
795 (and (window-leftmost-p window)
796 (window-rightmost-p window))))
797 (setq window (split-window window))
798 (let (upper lower other)
799 (setq window (get-lru-window target-frame))
800 ;; If the LRU window is selected, and big enough,
801 ;; and can be split, split it.
802 (if (and window
803 (not (frame-property (window-frame window)
804 'unsplittable))
805 (or (eq window (selected-window))
806 (not (window-parent window)))
807 (>= (window-height window)
808 (* 2 window-min-height)))
809 (setq window (split-window window)))
810 ;; If get-lru-window returned nil, try other approaches.
811 ;; Try visible frames first.
812 (or window
813 (setq window (or (get-largest-window 'visible)
814 ;; If that didn't work, try
815 ;; iconified frames.
816 (get-largest-window 0)
817 ;; Try invisible frames.
818 (get-largest-window t)
819 ;; As a last resort, make
820 ;; a new frame.
821 (frame-selected-window
822 (funcall
823 pop-up-frame-function)))))
824 ;; If window appears above or below another,
825 ;; even out their heights.
826 (if (window-previous-child window)
827 (setq other (window-previous-child window)
828 upper other
829 lower window))
830 (if (window-next-child window)
831 (setq other (window-next-child window)
832 lower other
833 upper window))
834 ;; Check that OTHER and WINDOW are vertically arrayed.
835 (if (and other
836 (not (= (nth 1 (window-pixel-edges other))
837 (nth 1 (window-pixel-edges window))))
838 (> (window-pixel-height other)
839 (window-pixel-height window)))
840 (enlarge-window (- (/ (+ (window-height other)
841 (window-height window))
842 2)
843 (window-height upper))
844 nil upper)))))
845
846 (setq window (get-lru-window target-frame)))
847
848 ;; Bring the window's previous buffer to the top of the MRU chain.
849 (if (window-buffer window)
850 (save-excursion
851 (save-selected-window
852 (select-window window)
853 (record-buffer (window-buffer window)))))
854
855 (set-window-buffer window buffer)
856
857 (display-buffer-1 window)))))
858 (or (equal wconfig (current-window-configuration))
859 (push-window-configuration wconfig))
860 result))