+ (function :tag "Function"))
+ :group 'windows)
+
+;; The following is a global variable which is used externally (by
+;; help.el) to (1) know which window was used for displaying a buffer
+;; and (2) whether the window was new or reused.
+(defvar display-buffer-window nil
+ "Window used by `display-buffer' and related information.
+After `display-buffer' displays a buffer in some window this
+variable is a cons cell whose car denotes the window used to
+display the buffer. The cdr is supposed to be one of the symbols
+`reuse-buffer-window', `reuse-other-window', `new-window' or
+`new-frame'.
+
+If the buffer display location specifier is one of 'same-window,
+'same-frame, or 'other-frame, the `display-buffer' routines
+assign the value of this variable. If the location specifier is
+a function, that function becomes responsible for assigning a
+meaningful value to this variable. See the functions
+`display-buffer-reuse-window', `display-buffer-pop-up-window' and
+`display-buffer-pop-up-frame' for how this can be done.")
+
+(defun display-buffer-even-window-sizes (window specifiers)
+ "Even sizes of WINDOW and selected window according to SPECIFIERS.
+SPECIFIERS must be a list of buffer display specifiers, see the
+documentation of `display-buffer-alist' for a description.
+
+Sizes are evened out if and only if WINDOW and the selected
+window appear next to each other and the selected window is
+larger than WINDOW."
+ (cond
+ ((or (not (cdr (assq 'reuse-window-even-sizes specifiers)))
+ ;; Don't resize minibuffer windows.
+ (window-minibuffer-p)
+ ;; WINDOW must be adjacent to the selected one.
+ (not (or (eq window (window-prev-sibling))
+ (eq window (window-next-sibling))))))
+ ((and (window-iso-combined-p window)
+ ;; Resize iff the selected window is higher than WINDOW.
+ (> (window-total-height) (window-total-height window)))
+ ;; Don't throw an error if we can't even window heights for
+ ;; whatever reason. In any case, enlarging the selected window
+ ;; might fail anyway if there are other windows above or below
+ ;; WINDOW and the selected one. But for a simple two windows
+ ;; configuration the present behavior is good enough so why care?
+ (ignore-errors
+ (window-resize
+ window (/ (- (window-total-height) (window-total-height window))
+ 2))))
+ ((and (window-iso-combined-p window t)
+ ;; Resize iff the selected window is wider than WINDOW.
+ (> (window-total-width) (window-total-width window)))
+ ;; Don't throw an error if we can't even window widths, see
+ ;; comment above.
+ (ignore-errors
+ (window-resize
+ window (/ (- (window-total-width) (window-total-width window))
+ 2) t)))))
+
+(defun display-buffer-set-height (window specifiers)
+ "Adjust height of WINDOW according to SPECIFIERS.
+SPECIFIERS must be a list of buffer display specifiers, see the
+documentation of `display-buffer-alist' for a description."
+ (let ((set-height (cdr (assq 'pop-up-window-set-height specifiers))))
+ (cond
+ ((numberp set-height)
+ (let* ((height (if (integerp set-height)
+ set-height
+ (round
+ (* (window-total-size (frame-root-window window))
+ set-height))))
+ (delta (- height (window-total-size window))))
+ (when (and (window-resizable-p window delta nil 'safe)
+ (window-iso-combined-p window))
+ (window-resize window delta nil 'safe))))
+ ((functionp set-height)
+ (ignore-errors (funcall set-height window))))))
+
+(defun display-buffer-set-width (window specifiers)
+ "Adjust width of WINDOW according to SPECIFIERS.
+SPECIFIERS must be a list of buffer display specifiers, see the
+documentation of `display-buffer-alist' for a description."
+ (let ((set-width (cdr (assq 'pop-up-window-set-width specifiers))))
+ (cond
+ ((numberp set-width)
+ (let* ((width (if (integerp set-width)
+ set-width
+ (round
+ (* (window-total-size (frame-root-window window) t)
+ set-width))))
+ (delta (- width (window-total-size window t))))
+ (when (and (window-resizable-p window delta t 'safe)
+ (window-iso-combined-p window t))
+ (window-resize window delta t 'safe))))
+ ((functionp set-width)
+ (ignore-errors (funcall set-width window))))))
+
+(defun display-buffer-in-window (buffer window specifiers)
+ "Display BUFFER in WINDOW and raise its frame if needed.
+WINDOW must be a live window and defaults to the selected one.
+Return WINDOW.
+
+SPECIFIERS must be a list of buffer display specifiers, see the
+documentation of `display-buffer-alist' for a description."
+ (setq buffer (window-normalize-buffer buffer))
+ (setq window (window-normalize-live-window window))
+ (let* ((old-frame (selected-frame))
+ (new-frame (window-frame window))
+ (dedicated (cdr (assq 'dedicated specifiers)))
+ (no-other-window (cdr (assq 'no-other-window specifiers))))
+ ;; Show BUFFER in WINDOW.
+ (unless (eq buffer (window-buffer window))
+ ;; If we show another buffer in WINDOW, undedicate it first.
+ (set-window-dedicated-p window nil))
+ (set-window-buffer window buffer)
+ (when dedicated
+ (set-window-dedicated-p window dedicated))
+ (when no-other-window
+ (set-window-parameter window 'no-other-window t))
+ (unless (or (eq old-frame new-frame)
+ (not (frame-visible-p new-frame))
+ ;; Assume the selected frame is already visible enough.
+ (eq new-frame (selected-frame))
+ ;; Assume the frame from which we invoked the minibuffer
+ ;; is visible.
+ (and (minibuffer-window-active-p (selected-window))
+ (eq new-frame
+ (window-frame (minibuffer-selected-window)))))
+ (raise-frame new-frame))
+ ;; Return window.
+ window))
+
+(defun display-buffer-reuse-window (buffer method &optional specifiers)
+ "Display BUFFER in an existing window.
+METHOD must be a list in the form of the cdr of a `reuse-window'
+buffer display specifier, see `display-buffer-alist' for an
+explanation. The first element must specifiy the window to use,
+and can be either nil, `same', `other', or a live window. The
+second element must specify the window's buffer and can be either
+nil, `same', `other', or a live buffer. The third element is the
+frame to use - either nil, 0, `visible', `other', t, or a live
+frame.
+
+Optional argument SPECIFIERS must be a list of valid display
+specifiers. Return the window chosen to display BUFFER, nil if
+none was found."
+ (let* ((method-window (nth 0 method))
+ (method-buffer (nth 1 method))
+ (method-frame (nth 2 method))
+ (reuse-dedicated (cdr (assq 'reuse-window-dedicated specifiers)))
+ windows other-frame dedicated time best-window best-time)
+ (when (eq method-frame 'other)
+ ;; `other' is not handled by `window-list-1'.
+ (setq other-frame t)
+ (setq method-frame t))
+ (dolist (window (window-list-1 nil 'nomini method-frame))
+ (let ((window-buffer (window-buffer window)))
+ (when (and (not (window-minibuffer-p window))
+ ;; Don't reuse a side window.
+ (or (not (eq (window-parameter window 'window-side) 'side))
+ (eq window-buffer buffer))
+ (or (not method-window)
+ (and (eq method-window 'same)
+ (eq window (selected-window)))
+ (and (eq method-window 'other)
+ (not (eq window (selected-window))))
+ ;; Special case for applications that specifiy
+ ;; the window explicitly.
+ (eq method-window window))
+ (or (not method-buffer)
+ (and (eq method-buffer 'same)
+ (eq window-buffer buffer))
+ (and (eq method-buffer 'other)
+ (not (eq window-buffer buffer)))
+ ;; Special case for applications that specifiy
+ ;; the window's buffer explicitly.
+ (eq method-buffer window-buffer))
+ (or (not other-frame)
+ (not (eq (window-frame window) (selected-frame))))
+ ;; Handle dedicatedness.
+ (or (eq window-buffer buffer)
+ ;; The window does not show the same buffer.
+ (not (setq dedicated (window-dedicated-p window)))
+ ;; If the window is weakly dedicated to its
+ ;; buffer, reuse-dedicated must be non-nil.
+ (and (not (eq dedicated t)) reuse-dedicated)
+ ;; If the window is strongly dedicated to its
+ ;; buffer, reuse-dedicated must be t.
+ (eq reuse-dedicated t)))
+ (setq windows (cons window windows)))))
+
+ (if (eq method-buffer 'same)
+ ;; When reusing a window on the same buffer use the lru one.
+ (dolist (window windows)
+ (setq time (window-use-time window))
+ (when (or (not best-window) (< time best-time))
+ (setq best-window window)
+ (setq best-time time)))
+ ;; Otherwise, sort windows according to their use-time.
+ (setq windows
+ (sort windows
+ #'(lambda (window-1 window-2)
+ (<= (window-use-time window-1)
+ (window-use-time window-2)))))
+ (setq best-window
+ ;; Try to get a full-width window (this is silly and can
+ ;; get us to another frame but let's ignore these issues
+ ;; for the moment).
+ (catch 'found
+ (dolist (window windows)
+ (when (window-full-width-p window)
+ (throw 'found window)))
+ ;; If there's no full-width window return the lru window.
+ (car windows))))
+
+ (when best-window
+ (display-buffer-even-window-sizes best-window specifiers)
+ ;; Never change the quit-restore parameter of a window here.
+ (if (eq (window-buffer best-window) buffer)
+ (setq display-buffer-window
+ (cons best-window 'reuse-buffer-window))
+ (setq display-buffer-window
+ (cons best-window 'reuse-other-window))
+ (unless (window-parameter best-window 'quit-restore)
+ ;; Don't overwrite an existing quit-restore entry.
+ (set-window-parameter
+ best-window 'quit-restore
+ (list (window-buffer best-window) (window-start best-window)
+ (window-point best-window) buffer
+ (window-total-size best-window) (selected-window)))))
+
+ (display-buffer-in-window buffer best-window specifiers))))
+
+(defconst display-buffer-split-specifiers '(largest lru selected root left top right bottom)
+ "List of symbols identifying window that shall be split.")
+
+(defconst display-buffer-side-specifiers '(below right above left nil)
+ "List of symbols identifying side of split-off window.")
+
+(defun display-buffer-split-window-1 (window side min-size)
+ "Subroutine of `display-buffer-split-window'."
+ (let* ((horizontal (memq side '(left right)))
+ (parent (window-parent window))
+ (resize (and window-splits (window-iso-combined-p window horizontal)))
+ (old-size
+ ;; We either resize WINDOW or its parent.
+ (window-total-size (if resize parent window) horizontal))
+ new-size)
+ ;; We don't call split-window-vertically/-horizontally any more
+ ;; here. If for some reason it's needed we can always do so
+ ;; (provided we give it an optional SIDE argument).
+ (cond
+ (resize
+ ;; When we resize a combination, the new window must be at least
+ ;; MIN-SIZE large after the split.
+ (setq new-size
+ (max min-size
+ (min (- old-size (window-min-size parent horizontal))
+ (/ old-size
+ ;; Try to make the size of the new window
+ ;; proportional to the number of iso-arranged
+ ;; windows in the combination.
+ (1+ (window-iso-combinations parent horizontal))))))
+ (when (window-sizable-p parent (- new-size) horizontal)
+ (split-window window (- new-size) side)))
+ ((window-live-p window)
+ (setq new-size (/ old-size 2))
+ ;; When WINDOW is live, the old _and_ the new window must be at
+ ;; least MIN-SIZE large after the split.
+ (when (and (>= new-size min-size)
+ (window-sizable-p window (- new-size) horizontal))
+ ;; Do an even split to make Stepan happy.
+ (split-window window nil side)))
+ (t
+ ;; When WINDOW is internal, the new window must be at least
+ ;; MIN-SIZE large after the split.
+ (setq new-size
+ (max min-size
+ (/ old-size
+ ;; Try to make the size of the new window
+ ;; proportional to the number of iso-arranged
+ ;; subwindows of WINDOW.
+ (1+ (window-iso-combinations window horizontal)))))
+ (when (window-sizable-p window (- new-size) horizontal)
+ (split-window window (- new-size) side))))))
+
+(defun display-buffer-split-window (window &optional side specifiers)
+ "Split WINDOW in a way suitable for `display-buffer'.
+Optional argument SIDE must be a side specifier \(one of the
+symbols below, right, above, left, or nil). SPECIFIERS must be a
+list of buffer display specifiers, see the documentation of
+`display-buffer-alist' for a description.
+
+Return the new window, nil if it could not be created."
+ (let ((min-height (cdr (assq 'pop-up-window-min-height specifiers)))
+ (min-width (cdr (assq 'pop-up-window-min-width specifiers)))
+ size)
+ ;; Normalize min-height and min-width, we might need both.
+ (setq min-height
+ ;; If min-height is specified, it can be as small as
+ ;; `window-safe-min-height'.
+ (cond
+ ((and (integerp min-height)
+ (>= min-height window-safe-min-height))
+ min-height)
+ ((and (floatp min-height)
+ (<= min-height 1)
+ (let* ((root-height (window-total-height
+ (frame-root-window
+ (window-frame window))))
+ (height (round (* min-height root-height))))
+ (when (>= height window-safe-min-height)
+ height))))
+ (t window-min-height)))
+ (setq min-width
+ ;; If min-width is specified, it can be as small as
+ ;; `window-safe-min-width'.
+ (cond
+ ((and (integerp min-width)
+ (>= min-width window-safe-min-width))
+ min-width)
+ ((and (floatp min-width)
+ (<= min-width 1)
+ (let* ((root-width (window-total-width
+ (frame-root-window
+ (window-frame window))))
+ (width (round (* min-width root-width))))
+ (when (>= width window-safe-min-width)
+ width))))
+ (t window-min-width)))
+
+ (or (and (memq side '(nil above below))
+ (display-buffer-split-window-1
+ window (or side 'below) min-height))
+ ;; If SIDE is nil and vertical splitting failed, we try again
+ ;; splitting horizontally this time.
+ (and (memq side '(nil left right))
+ (display-buffer-split-window-1
+ window (or side 'right) min-width))
+ ;; If WINDOW is live and the root window of its frame, try once
+ ;; more splitting vertically, disregarding the min-height
+ ;; specifier this time and using `window-min-height' instead.
+ (and (memq side '(nil above below))
+ (<= window-min-height min-height)
+ (window-live-p window)
+ (eq window (frame-root-window window))
+ (display-buffer-split-window-1
+ window (or side 'below) window-min-height)))))
+
+(defun display-buffer-split-atom-window (window &optional side nest specifiers)
+ "Make WINDOW part of an atomic window."
+ (let ((ignore-window-parameters t)
+ (window-nest t)
+ (selected-window (selected-window))
+ root new new-parent)
+
+ ;; We are in an atomic window.
+ (when (and (window-parameter window 'window-atom) (not nest))
+ ;; Split the root window.
+ (setq window (window-atom-root window)))
+
+ (when (setq new (display-buffer-split-window window side specifiers))
+ (setq new-parent (window-parent window))
+ ;; WINDOW is or becomes atomic.
+ (unless (window-parameter window 'window-atom)
+ (walk-window-subtree
+ (lambda (window)
+ (set-window-parameter window 'window-atom t))
+ window t))
+ ;; New window and any new parent get their window-atom parameter
+ ;; set too.
+ (set-window-parameter new 'window-atom t)
+ (set-window-parameter new-parent 'window-atom t)
+ new)))
+
+(defun display-buffer-pop-up-window (buffer methods &optional specifiers)
+ "Display BUFFER in a new window.
+Return the window displaying BUFFER, nil if popping up the window
+failed. METHODS must be a list of window/side tuples like those
+forming the cdr of the `pop-up-window' buffer display specifier.
+As a special case, the car of such a tuple can be also a live
+window.
+
+Optional argument SPECIFIERS must be a list of buffer display
+specifiers, see the doc-string of `display-buffer-alist' for a
+description."
+ (let* ((frame (display-buffer-frame))
+ (selected-window (frame-selected-window frame))
+ cand window side atomic)
+ (unless (and (cdr (assq 'unsplittable (frame-parameters frame)))
+ ;; Don't split an unsplittable frame unless
+ ;; SPECIFIERS allow it.
+ (not (cdr (assq 'split-unsplittable-frame specifiers))))
+ (catch 'done
+ (dolist (method methods)
+ (setq cand (car method))
+ (setq side (cdr method))
+ (setq window
+ (cond
+ ((eq cand 'largest)
+ ;; The largest window.
+ (get-largest-window frame t))
+ ((eq cand 'lru)
+ ;; The least recently used window.
+ (get-lru-window frame t))
+ ((eq cand 'selected)
+ ;; The selected window.
+ (frame-selected-window frame))
+ ((eq cand 'root)
+ ;; If there are side windows, split the main window
+ ;; else the frame's root window.
+ (or (window-with-parameter 'window-side 'none nil t)
+ (frame-root-window frame)))
+ ((memq cand window-sides)
+ ;; This should gets us the "root" side window if there
+ ;; exists more than one window on that side.
+ (window-with-parameter 'window-side cand nil t))
+ ((windowp cand)
+ ;; A window, directly specified.
+ cand)))
+
+ (when (and (window-live-p window)
+ ;; The window must be on the correct frame,
+ (eq (window-frame window) frame)
+ ;; and must be neither a minibuffer window
+ (not (window-minibuffer-p window))
+ ;; nor a side window.
+ (not (eq (window-parameter window 'window-side) 'side)))
+ (setq window
+ (cond
+ ((memq side display-buffer-side-specifiers)
+ (if (and (window-buffer window)
+ (setq atomic (cdr (assq 'atomic specifiers))))
+ (display-buffer-split-atom-window
+ window side (eq atomic 'nest) specifiers)
+ (display-buffer-split-window window side specifiers)))
+ ((functionp side)
+ (ignore-errors
+ ;; Don't pass any specifiers to this function.
+ (funcall side window)))))
+
+ (when window
+ ;; Adjust sizes if asked for.
+ (display-buffer-set-height window specifiers)
+ (display-buffer-set-width window specifiers)
+ (set-window-parameter
+ window 'quit-restore (list 'new-window buffer selected-window))
+ (setq display-buffer-window (cons window 'new-window))
+ (display-buffer-in-window buffer window specifiers)
+ (set-window-prev-buffers window nil)
+ (throw 'done window))))))))
+
+(defun display-buffer-pop-up-frame (buffer &optional graphic-only specifiers)
+ "Make a new frame for displaying BUFFER.
+Return the window displaying BUFFER if creating the new frame was
+successful, nil otherwise. Optional argument GRAPHIC-ONLY
+non-nil means to make a new frame on graphic displays only.
+
+SPECIFIERS must be a list of buffer display specifiers, see the
+documentation of `display-buffer-alist' for a description."
+ (unless (or (and graphic-only (not (display-graphic-p)))
+ noninteractive)
+ (let* ((selected-window (selected-window))
+ (function (or (cdr (assq 'pop-up-frame-function specifiers))
+ 'make-frame))
+ (parameters
+ (when (symbolp function)
+ (cdr (assq 'pop-up-frame-alist specifiers))))
+ (frame
+ (if (symbolp function)
+ (funcall function parameters)
+ (funcall function))))
+ (when frame
+ (let ((window (frame-selected-window frame)))
+ (set-window-parameter
+ window 'quit-restore (list 'new-frame buffer selected-window))
+ (setq display-buffer-window (cons window 'new-frame))
+ (display-buffer-in-window buffer window specifiers))))))
+
+(defun display-buffer-pop-up-side-window (buffer side slot &optional specifiers)
+ "Display BUFFER in a new window on SIDE of the selected frame.
+SLOT specifies the slot to use. SPECIFIERS must be a list of
+buffer display specifiers.
+
+Return the window displaying BUFFER, nil if popping up the window
+failed."
+ (let* ((root (frame-root-window))
+ (main (window-with-parameter 'window-side 'none nil t))
+ (left-or-right (memq side '(left right)))
+ (main-or-root
+ (if (and main
+ (or (and left-or-right (not window-sides-vertical))
+ (and (not left-or-right) window-sides-vertical)))
+ main
+ root))
+ (selected-window (selected-window))
+ (on-side (cond
+ ((eq side 'top) 'above)
+ ((eq side 'bottom) 'below)
+ (t side)))
+ (window
+ (display-buffer-split-window main-or-root on-side specifiers))
+ fun)
+ (when window
+ (unless main
+ (walk-window-subtree
+ (lambda (window)
+ ;; Make all main-or-root subwindows main windows.
+ (set-window-parameter window 'window-side 'none))
+ main-or-root t))
+ ;; Make sure that parent's window-side is nil.
+ (set-window-parameter (window-parent window) 'window-side nil)
+ ;; Initialize side.
+ (set-window-parameter window 'window-side side)
+ ;; Adjust sizes if asked for.
+ (display-buffer-set-height window specifiers)
+ (display-buffer-set-width window specifiers)
+ ;; Set window parameters.
+ (set-window-parameter
+ window 'quit-restore (list 'new-window buffer selected-window))
+ (setq display-buffer-window (cons window 'new-window))
+ (set-window-parameter window 'window-slot slot)
+ (display-buffer-in-window buffer window specifiers)
+ (set-window-prev-buffers window nil)
+ window)))
+
+(defun display-buffer-in-side-window (buffer side &optional slot specifiers)
+ "Display BUFFER in a window on SIDE of the selected frame.
+SLOT, if non-nil, specifies the window slot where to display the
+BUFFER. SLOT zero or nil means use the central slot on SIDE.
+SLOT negative means use a slot preceding the central window.
+SLOT positive means use a slot following the central window.
+
+SPECIFIERS must be a list of buffer display specifiers."
+ (unless (memq side window-sides)
+ (error "Invalid side %s specified" side))
+ (let* ((major (window-with-parameter 'window-side side nil t))
+ ;; `major' is the major window on SIDE, `windows' the life
+ ;; windows on SIDE.
+ (windows (when major (windows-with-parameter 'window-side side)))
+ (reuse-dedicated (cdr (assq 'reuse-window-dedicated specifiers)))
+ (slots (when major (window-child-count major)))
+ (max-slots
+ (nth (cond
+ ((eq side 'left) 0)
+ ((eq side 'top) 1)
+ ((eq side 'right) 2)
+ ((eq side 'bottom) 3))
+ window-sides-slots))
+ (selected-window (selected-window))
+ window this-window this-slot prev-window next-window
+ best-window best-slot abs-slot dedicated)
+
+ (unless (numberp slot)
+ (setq slot 0))
+ (if (not windows)
+ ;; No suitable side window exists, make one.
+ (display-buffer-pop-up-side-window buffer side slot specifiers)
+ ;; Scan windows on SIDE.
+ (catch 'found
+ (dolist (window windows)
+ (setq this-slot (window-parameter window 'window-slot))
+ (cond
+ ((not (numberp this-slot)))
+ ((and (= this-slot slot)
+ ;; Dedicatedness check.
+ (or (not (setq dedicated (window-dedicated-p window)))
+ ;; If the window is weakly dedicated to its
+ ;; buffer, reuse-dedicated must be non-nil.
+ (and (not (eq dedicated t)) reuse-dedicated)
+ ;; If the window is strongly dedicated to its
+ ;; buffer, reuse-dedicated must be t.
+ (eq reuse-dedicated t)))
+ ;; Window with matching SLOT, use it.
+ (setq this-window window)
+ (throw 'found t))
+ (t
+ (setq abs-slot (abs (- (abs slot) (abs this-slot))))
+ (unless (and best-slot (<= best-slot abs-slot))
+ (setq best-window window)
+ (setq best-slot abs-slot))
+ (cond
+ ((<= this-slot slot)
+ (setq prev-window window))
+ ((not next-window)
+ (setq next-window window)))))))
+
+ ;; `this-window' is the first window with the same SLOT.
+ ;; `prev-window' is the window with the largest slot < SLOT. A new
+ ;; window will be created after it.
+ ;; `next-window' is the window with the smallest slot > SLOT. A new
+ ;; window will be created before it.
+ ;; `best-window' is the window with the smallest absolute difference
+ ;; of its slot and SLOT.
+ (or (and this-window
+ ;; Reuse this window.
+ (prog1
+ (setq window this-window)
+ (if (eq (window-buffer window) buffer)
+ (setq display-buffer-window
+ (cons window 'reuse-buffer-window))
+ (setq display-buffer-window
+ (cons window 'reuse-other-window))
+ (unless (window-parameter window 'quit-restore)
+ ;; Don't overwrite an existing quit-restore entry.
+ (set-window-parameter
+ window 'quit-restore
+ (list (window-buffer window) (window-start window)
+ (window-point window) buffer
+ (window-total-size window) (selected-window)))))))
+ (and (or (not max-slots) (< slots max-slots))
+ (or (and next-window
+ ;; Make new window before next-window.
+ (let ((next-side
+ (if (memq side '(left right)) 'above 'left)))
+ (setq window (display-buffer-split-window
+ next-window next-side specifiers))))
+ (and prev-window
+ ;; Make new window after prev-window.
+ (let ((prev-side
+ (if (memq side '(left right)) 'below 'right)))
+ (setq window (display-buffer-split-window
+ prev-window prev-side specifiers)))))
+ (progn
+ (display-buffer-set-height window specifiers)
+ (display-buffer-set-width window specifiers)
+ (set-window-parameter
+ window 'quit-restore
+ (list 'new-window buffer selected-window))
+ (setq display-buffer-window (cons window 'new-window))
+ window))
+ (and best-window
+ (setq window best-window)
+ ;; Reuse best window (the window nearest to SLOT).
+ (if (eq (window-buffer window) buffer)
+ (setq display-buffer-window
+ (cons window 'reuse-buffer-window))
+ (setq display-buffer-window
+ (cons window 'reuse-other-window))
+
+ (unless (window-parameter window 'quit-restore)
+ ;; Don't overwrite an existing quit-restore entry.
+ (set-window-parameter
+ window 'quit-restore
+ (list (window-buffer window) (window-start window)
+ (window-point window) buffer
+ (window-total-size window) (selected-window)))))
+ window))
+
+ (when window
+ (unless (window-parameter window 'window-slot)
+ ;; Don't change exisiting slot value.
+ (set-window-parameter window 'window-slot slot))
+ (display-buffer-in-window buffer window specifiers)))))
+
+(defun window-normalize-buffer-to-display (buffer-or-name)
+ "Normalize BUFFER-OR-NAME argument for buffer display functions.
+If BUFFER-OR-NAME is nil, return the curent buffer. Else, if a
+buffer specified by BUFFER-OR-NAME exists, return that buffer.
+If no such buffer exists, create a buffer with the name
+BUFFER-OR-NAME and return that buffer."
+ (if buffer-or-name
+ (or (get-buffer buffer-or-name)
+ (let ((buffer (get-buffer-create buffer-or-name)))
+ (set-buffer-major-mode buffer)
+ buffer))
+ (current-buffer)))
+
+(defun display-buffer-other-window-means-other-frame (buffer-or-name &optional label)
+ "Return non-nil if BUFFER shall be preferably displayed in another frame.
+BUFFER must be a live buffer or the name of a live buffer.
+
+Return nil if BUFFER shall be preferably displayed in another
+window on the selected frame. Return non-nil if BUFFER shall be
+preferably displayed in a window on any but the selected frame.
+
+Optional argument LABEL is like the same argument of
+`display-buffer'.
+
+The calculation of the return value is exclusively based on the
+user preferences expressed in `display-buffer-alist'."
+ (let* ((buffer (window-normalize-buffer buffer-or-name))
+ (list (display-buffer-normalize-alist (buffer-name buffer) label))
+ (value (assq 'other-window-means-other-frame
+ (or (car list) (cdr list)))))
+ (when value (cdr value))))
+
+(defun display-buffer-normalize-arguments (buffer-name specifiers label other-frame)
+ "Normalize second and third argument of `display-buffer'.
+BUFFER-NAME is the name of the buffer that shall be displayed,
+SPECIFIERS is the second argument of `display-buffer'. LABEL is
+the same argument of `display-buffer'. OTHER-FRAME non-nil means
+use other-frame for other-window."
+ (let (normalized entry specifier pars)
+ (setq specifier
+ (cond
+ ((not specifiers)
+ nil)
+ ((listp specifiers)
+ ;; If SPECIFIERS is a list, we assume it is a list of specifiers.
+ (dolist (specifier specifiers)
+ (cond
+ ((consp specifier)
+ (setq normalized (cons specifier normalized)))
+ ((eq specifier 'other-window)
+ ;; `other-window' must be treated separately.
+ (let ((entry (assq (if other-frame
+ 'other-frame
+ 'same-frame-other-window)
+ display-buffer-macro-specifiers)))
+ (dolist (item (cdr entry))
+ (setq normalized (cons item normalized)))))
+ ((symbolp specifier)
+ ;; Might be a macro specifier, try to expand it (the cdr is a
+ ;; list and we have to reverse it later, so do it one at a
+ ;; time).
+ (let ((entry (assq specifier display-buffer-macro-specifiers)))
+ (dolist (item (cdr entry))
+ (setq normalized (cons item normalized)))))))
+ ;; Reverse list.
+ (nreverse normalized))
+ ((setq entry (assq specifiers display-buffer-macro-specifiers))
+ ;; A macro specifier.
+ (cdr entry))
+ ((or other-frame (with-no-warnings pop-up-frames))
+ ;; `special-display-p' group.
+ (if (and (with-no-warnings special-display-function)
+ ;; `special-display-p' returns either t or a list
+ ;; of frame parameters to pass to
+ ;; `special-display-function'.
+ (setq pars (with-no-warnings
+ (special-display-p buffer-name))))
+ (list (list 'function
+ (with-no-warnings special-display-function)
+ (when (listp pars) pars)))
+ ;; Pop up another frame.
+ (cddr (assq 'other-frame display-buffer-macro-specifiers))))
+ (t
+ ;; In any other case pop up a new window.
+ (cdr (assq 'same-frame-other-window
+ display-buffer-macro-specifiers)))))
+
+ ;; Handle the old meaning of the LABEL argument of `display-buffer'.
+ (cond
+ ((or (memq label '(visible 0 t)) (frame-live-p label))
+ ;; LABEL must be one of visible (and visible frame), 0 (any
+ ;; visible or iconfied frame), t (any frame), or a live frame.
+ (cons `(reuse-window nil same ,label) specifier))
+ ((or other-frame
+ (with-no-warnings pop-up-frames)
+ (with-no-warnings display-buffer-reuse-frames))
+ (cons '(reuse-window nil same 0) specifier))
+ (t
+ specifier))))
+
+(defun display-buffer-normalize-options (buffer-or-name)
+ "Subroutine of `display-buffer-normalize-specifiers'.
+BUFFER-OR-NAME is the buffer to display. This routine provides a
+compatibility layer for the now obsolete Emacs 23 buffer display
+options."
+ (with-no-warnings
+ (let* ((buffer (window-normalize-buffer buffer-or-name))
+ (buffer-name (buffer-name buffer))
+ (use-pop-up-frames
+ (or (and (eq pop-up-frames 'graphic-only)
+ (display-graphic-p))
+ pop-up-frames))
+ specifiers)
+ ;; `even-window-heights', unless nil or unset.
+ (unless (memq even-window-heights '(nil unset))
+ (setq specifiers
+ (cons (cons 'reuse-window-even-sizes t) specifiers)))
+
+ ;; `display-buffer-mark-dedicated'
+ (when display-buffer-mark-dedicated
+ (setq specifiers
+ (cons (cons 'dedicate display-buffer-mark-dedicated)
+ specifiers)))
+
+ ;; `pop-up-window' group. Anything is added here iff
+ ;; `pop-up-windows' is neither nil nor unset.
+ (let ((pop-up-window (not (memq pop-up-windows '(nil unset))))
+ (fun (unless (eq split-window-preferred-function
+ 'split-window-sensibly)
+ split-window-preferred-function))
+ (min-height (if (numberp split-height-threshold)
+ (/ split-height-threshold 2)
+ 1.0))
+ (min-width (if (numberp split-width-threshold)
+ (/ split-width-threshold 2)
+ 1.0)))
+ ;; Create an entry only if a default value was changed.
+ (when (or pop-up-window
+ (not (equal split-height-threshold 80))
+ (not (equal split-width-threshold 160)))
+ ;; `reuse-window' (needed as fallback when popping up the new
+ ;; window fails).
+ (setq specifiers
+ (cons (list 'reuse-window 'other nil nil)
+ specifiers))
+ ;; `split-width-threshold'
+ (setq specifiers
+ (cons (cons 'pop-up-window-min-width min-width)
+ specifiers))
+ ;; `split-height-threshold'
+ (setq specifiers
+ (cons (cons 'pop-up-window-min-height min-height)
+ specifiers))
+ ;; `pop-up-window'
+ (setq specifiers
+ (cons (list 'pop-up-window
+ (cons 'largest fun) (cons 'lru fun))
+ specifiers))))
+
+ ;; `pop-up-frame' group.
+ (when use-pop-up-frames
+ ;; `pop-up-frame-function'. If `pop-up-frame-function' uses the
+ ;; now obsolete `pop-up-frame-alist' it will continue to do so.
+ (setq specifiers
+ (cons (cons 'pop-up-frame-function pop-up-frame-function)
+ specifiers))
+ ;; `pop-up-frame'
+ (setq specifiers
+ (cons (list 'pop-up-frame t) specifiers)))
+
+ ;; `pop-up-windows' and `use-pop-up-frames' both nil means means
+ ;; we are supposed to reuse any window on the same frame (unless
+ ;; we find one showing the same buffer already).
+ (unless (or pop-up-windows use-pop-up-frames)
+ ;; `reuse-window' showing any buffer on same frame.
+ (setq specifiers
+ (cons (list 'reuse-window nil nil nil)
+ specifiers)))
+
+ ;; `special-display-p' group.
+ (when special-display-function
+ ;; `special-display-p' returns either t or a list of frame
+ ;; parameters to pass to `special-display-function'.
+ (let ((pars (special-display-p buffer-name)))
+ (when pars
+ (setq specifiers
+ (cons (list 'function special-display-function
+ (when (listp pars) pars))
+ specifiers)))))
+
+ ;; `pop-up-frames', `display-buffer-reuse-frames' means search for
+ ;; a window showing the buffer on some visible or iconfied frame.
+ ;; `last-nonminibuffer-frame' set and not the same frame means
+ ;; search that frame.
+ (let ((frames (or (and (or use-pop-up-frames
+ display-buffer-reuse-frames
+ (not (last-nonminibuffer-frame)))
+ ;; All visible or iconfied frames.
+ 0)
+ ;; Same frame.
+ (last-nonminibuffer-frame))))
+ (when frames
+ (setq specifiers
+ (cons (list 'reuse-window 'other 'same frames)
+ specifiers))))
+
+ ;; `same-window-p' group.
+ (when (same-window-p buffer-name)
+ ;; Try to reuse the same (selected) window.
+ (setq specifiers
+ (cons (list 'reuse-window 'same nil nil)
+ specifiers)))
+
+ ;; Prepend "reuse window on same frame if showing the buffer
+ ;; already" specifier. It will be overriden by the application
+ ;; supplied 'other-window specifier.
+ (setq specifiers (cons (list 'reuse-window nil 'same nil)
+ specifiers))
+
+ specifiers)))
+
+(defun display-buffer-normalize-alist-1 (specifiers label)
+ "Subroutine of `display-buffer-normalize-alist'.
+SPECIFIERS is a list of buffer display specfiers. LABEL is the
+same argument of `display-buffer'."
+ (let (normalized entry)
+ (cond
+ ((not specifiers)
+ nil)
+ ((listp specifiers)
+ ;; If SPECIFIERS is a list, we assume it is a list of specifiers.
+ (dolist (specifier specifiers)
+ (cond
+ ((consp specifier)
+ (setq normalized (cons specifier normalized)))
+ ((symbolp specifier)
+ ;; Might be a macro specifier, try to expand it (the cdr is a
+ ;; list and we have to reverse it later, so do it one at a
+ ;; time).
+ (let ((entry (assq specifier display-buffer-macro-specifiers)))
+ (dolist (item (cdr entry))
+ (setq normalized (cons item normalized)))))))
+ ;; Reverse list.
+ (nreverse normalized))
+ ((setq entry (assq specifiers display-buffer-macro-specifiers))
+ ;; A macro specifier.
+ (cdr entry)))))
+
+(defun display-buffer-normalize-alist (buffer-name label)
+ "Normalize `display-buffer-alist'.
+BUFFER-NAME must be the name of the buffer that shall be displayed.
+LABEL the corresponding argument of `display-buffer'."
+ (let (list-1 list-2)
+ (dolist (entry display-buffer-alist)
+ (when (and (listp entry)
+ (catch 'match
+ (dolist (id (car entry))
+ (when (consp id)
+ (let ((type (car id))
+ (value (cdr id)))
+ (when (or (and (eq type 'name) (stringp value)
+ (equal value buffer-name))
+ (and (eq type 'regexp) (stringp value)
+ (string-match-p value buffer-name))
+ (and (eq type 'label) (eq value label)))
+ (throw 'match t)))))))
+ (let* ((specifiers (cdr entry))
+ (normalized
+ (display-buffer-normalize-alist-1 specifiers label)))
+ (if (cdr (assq 'override specifiers))
+ (setq list-1
+ (if list-1
+ (append list-1 normalized)
+ normalized))
+ (setq list-2
+ (if list-2
+ (append list-2 normalized)
+ normalized))))))
+
+ (cons list-1 list-2)))
+
+(defvar display-buffer-normalize-options-inhibit nil
+ "If non-nil, `display-buffer' doesn't process obsolete options.")
+
+(defun display-buffer-normalize-specifiers (buffer-name specifiers label)
+ "Return normalized specifiers for a buffer matching BUFFER-NAME or LABEL.
+BUFFER-NAME must be a string specifying a valid buffer name.
+SPECIFIERS and LABEL are the homonymous arguments of
+`display-buffer'.
+
+The method for displaying the buffer specified by BUFFER-NAME or
+LABEL is established by appending the following four lists of
+specifiers:
+
+- The specifiers in `display-buffer-alist' whose buffer
+ identifier matches BUFFER-NAME or LABEL and whose 'override
+ component is set.
+
+- SPECIFIERS.
+
+- The specifiers in `display-buffer-alist' whose buffer
+ identifier matches BUFFER-NAME or LABEL and whose 'override
+ component is not set.
+
+- `display-buffer-default-specifiers'."
+ (let* ((list (display-buffer-normalize-alist buffer-name label))
+ (other-frame (cdr (assq 'other-window-means-other-frame
+ (or (car list) (cdr list))))))
+ (append
+ ;; Overriding user specifiers.
+ (car list)
+ ;; Application specifiers.
+ (display-buffer-normalize-arguments
+ buffer-name specifiers label other-frame)
+ ;; Emacs 23 compatibility specifiers.
+ (unless display-buffer-normalize-options-inhibit
+ (display-buffer-normalize-options buffer-name))
+ ;; Non-overriding user specifiers.
+ (cdr list)
+ ;; Default specifiers.
+ display-buffer-default-specifiers)))
+
+;; Minibuffer-only frames should be documented better. They really
+;; deserve a separate section in the manual. Also
+;; `last-nonminibuffer-frame' is nowhere documented in the manual.
+(defun display-buffer-frame (&optional frame)
+ "Return FRAME if it is live and not a minibuffer-only frame.
+Return the value of `last-nonminibuffer-frame' otherwise."
+ (setq frame (window-normalize-frame frame))
+ (if (and (frame-live-p frame)
+ ;; A not very nice way to get that information.
+ (not (window-minibuffer-p (frame-root-window frame))))
+ frame
+ (last-nonminibuffer-frame)))
+
+(defun display-buffer (&optional buffer-or-name specifiers label)
+ "Make the buffer specified by BUFFER-OR-NAME appear in some window.
+Optional argument BUFFER-OR-NAME may be a buffer, a string \(a
+buffer name), or nil. If BUFFER-OR-NAME is a string not naming
+an existent buffer, create a buffer with that name. If
+BUFFER-OR-NAME is nil or omitted, display the current buffer.
+Interactively, prompt for the buffer name using the minibuffer.
+
+Return the window chosen to display the buffer or nil if no such
+window is found. Do not change the selected window unless the
+buffer is shown on a different frame than the selected one.
+
+Optional argument SPECIFIERS must be a list of buffer display
+specifiers, see the documentation of `display-buffer-alist' for a
+description.
+
+For convenience, SPECIFIERS may also consist of a single buffer
+display location specifier or t, where the latter means to
+display the buffer in any but the selected window. If SPECIFIERS
+is nil or omitted, this means to exclusively use the specifiers
+provided by `display-buffer-alist'. If the value of the latter
+is nil too, all specifiers are provided by the constant
+`display-buffer-default-specifiers'.
+
+As a special case, the `reuse-window' specifier allows to specify
+as second element an arbitrary window, as third element an
+arbitrary buffer, and as fourth element an arbitrary frame. As
+first element of a window/side pair of the `pop-up-window'
+specifier you can specifiy an arbitrary window.
+
+The optional third argument LABEL, if non-nil, must be a symbol
+specifiying the buffer display label. Applications should set
+this when the buffer shall be displayed in some special way but
+BUFFER-OR-NAME does not identify the buffer as special. Typical
+buffers that fit into this category are those whose names are
+derived from the name of the file they are visiting. A user can
+override SPECIFIERS by adding an entry to `display-buffer-alist'
+whose car contains LABEL and whose cdr specifies the preferred
+alternative display method.
+
+The following values of LABEL have a special meaning and allow to
+specify the set of frames to investigate when the buffer already
+appears in a window:
+
+`visible' - the set of visible frames.
+
+0 - the set of visible or iconified frames.
+
+t - the set of all frames.
+
+A live frame - the set containing that frame as its only element.
+
+If the buffer is already displayed in a window on a frame in the
+specified set, return that window.
+
+The method to display the buffer is derived by combining the
+values of `display-buffer-alist' and SPECIFIERS. Highest
+priority is given to overriding elements of
+`display-buffer-alist'. Next come the elements specified by
+SPECIFIERS, followed by the non-overriding elements of
+`display-buffer-alist'.
+
+The result must be a list of valid buffer display specifiers. If
+`display-buffer-function' is non-nil, call it with the buffer and
+this list as arguments."
+ (interactive "BDisplay buffer:\nP")
+ (let* ((buffer (window-normalize-buffer-to-display buffer-or-name))
+ (buffer-name (buffer-name buffer))
+ (normalized
+ ;; Normalize specifiers.
+ (display-buffer-normalize-specifiers buffer-name specifiers label))
+ ;; Don't use a minibuffer frame.
+ (frame (display-buffer-frame))
+ ;; `window' is the window we use for showing `buffer'.
+ window specifier method)
+ ;; Reset this.
+ (setq display-buffer-window nil)
+ (if display-buffer-function
+ ;; Let `display-buffer-function' do the job.
+ (funcall display-buffer-function buffer specifiers)
+ ;; Retrieve the next location specifier while there a specifiers
+ ;; left and we don't have a valid window.
+ (while (and normalized (not (window-live-p window)))
+ (setq specifier (car normalized))
+ (setq normalized (cdr normalized))
+ (setq method (car specifier))
+ (setq window
+ (cond
+ ((eq method 'reuse-window)
+ (display-buffer-reuse-window
+ buffer (cdr specifier) normalized))
+ ((eq method 'pop-up-window)
+ (display-buffer-pop-up-window
+ buffer (cdr specifier) normalized))
+ ((eq method 'pop-up-frame)
+ (display-buffer-pop-up-frame
+ buffer (cdr specifier) normalized))
+ ((eq method 'use-side-window)
+ (display-buffer-in-side-window
+ buffer (nth 1 specifier) (nth 2 specifier) normalized))
+ ((eq method 'function)
+ (funcall (nth 1 specifier) buffer (nth 2 specifier))))))
+
+ ;; If we don't have a window yet, try a fallback method. All
+ ;; specifiers have been used up by now.
+ (or (and (window-live-p window) window)
+ ;; Try reusing a window showing BUFFER on any visible or
+ ;; iconfied frame.
+ (display-buffer-reuse-window buffer `(nil ,buffer 0))
+ ;; Try reusing a window not showing BUFFER on any visible or
+ ;; iconified frame.
+ (display-buffer-reuse-window buffer '(nil other 0))
+ ;; Eli says it's better to never try making a new frame.
+ ;; (display-buffer-pop-up-frame buffer)
+ ;; Try using a weakly dedicated window.
+ (display-buffer-reuse-window
+ buffer '(nil nil t) '((reuse-window-dedicated . weak)))
+ ;; Try using a strongly dedicated window.
+ (display-buffer-reuse-window
+ buffer '(nil nil t) '((reuse-window-dedicated . t)))))))
+
+(defsubst display-buffer-same-window (&optional buffer-or-name label)
+ "Display buffer specified by BUFFER-OR-NAME in the selected window.
+Another window will be used only if the buffer can't be shown in
+the selected window, usually because it is dedicated to another
+buffer. Optional argument BUFFER-OR-NAME and LABEL are as for
+`display-buffer'."
+ (interactive "BDisplay buffer in same window:\nP")
+ (display-buffer buffer-or-name 'same-window label))
+
+(defsubst display-buffer-same-frame (&optional buffer-or-name label)
+ "Display buffer specified by BUFFER-OR-NAME in a window on the same frame.
+Another frame will be used only if there is no other choice.
+Optional argument BUFFER-OR-NAME and LABEL are as for
+`display-buffer'."
+ (interactive "BDisplay buffer on same frame:\nP")
+ (display-buffer buffer-or-name 'same-frame label))
+
+(defsubst display-buffer-other-window (&optional buffer-or-name label)
+ "Display buffer specified by BUFFER-OR-NAME in another window.
+The selected window will be used only if there is no other
+choice. Windows on the selected frame are preferred to windows
+on other frames. Optional argument BUFFER-OR-NAME and LABEL are as
+for `display-buffer'."
+ (interactive "BDisplay buffer in another window:\nP")
+ (display-buffer buffer-or-name 'other-window label))
+
+(defun display-buffer-same-frame-other-window (&optional buffer-or-name label)
+ "Display buffer specified by BUFFER-OR-NAME in another window on the same frame.
+The selected window or another frame will be used only if there
+is no other choice. Optional argument BUFFER-OR-NAME and LABEL are
+as for `display-buffer'."
+ (interactive "BDisplay buffer in another window on same frame:\nP")
+ (display-buffer buffer-or-name 'same-frame-other-window label))
+
+(defun display-buffer-other-frame (&optional buffer-or-name label)
+ "Display buffer specified by BUFFER-OR-NAME on another frame.
+The selected frame will be used only if there is no other choice.
+Optional argument BUFFER-OR-NAME and LABEL are as for
+`display-buffer'.
+
+If this command uses another frame, it will also select that frame."
+ (interactive "BDisplay buffer in other frame: ")
+ (display-buffer buffer-or-name 'other-frame label))
+
+(defun pop-to-buffer (&optional buffer-or-name specifiers norecord label)
+ "Display buffer specified by BUFFER-OR-NAME and select the window used.
+Optional argument BUFFER-OR-NAME may be a buffer, a string \(a
+buffer name), or nil. If BUFFER-OR-NAME is a string naming a buffer
+that does not exist, create a buffer with that name. If
+BUFFER-OR-NAME is nil or omitted, display the current buffer.
+Interactively, prompt for the buffer name using the minibuffer.
+
+Optional second argument SPECIFIERS can be: a list of buffer
+display specifiers (see `display-buffer-alist'); a single
+location specifier; t, which means to display the buffer in any
+but the selected window; or nil, which means to exclusively apply
+the specifiers customized by the user. See `display-buffer' for
+more details.
+
+Optional argument NORECORD non-nil means do not put the displayed
+buffer at the front of the buffer list, and do not make the window
+displaying it the most recently selected one.
+
+The optional argument LABEL, if non-nil, is a symbol specifying the
+display purpose. Applications should set this when the buffer
+should be displayed in a special way but BUFFER-OR-NAME does not
+identify the buffer as special. Buffers that typically fit into
+this category are those whose names have been derived from the
+name of the file they are visiting.
+
+Returns the displayed buffer, or nil if displaying the buffer failed.
+
+This uses the function `display-buffer' as a subroutine; see the
+documentations of `display-buffer' and `display-buffer-alist' for
+additional information."
+ (interactive "BPop to buffer:\nP")
+ (let ((buffer (window-normalize-buffer-to-display buffer-or-name))
+ (old-window (selected-window))
+ (old-frame (selected-frame))
+ new-window new-frame)
+ (set-buffer buffer)
+ (setq new-window (display-buffer buffer specifiers label))
+ (unless (eq new-window old-window)
+ ;; `display-buffer' has chosen another window, select it.
+ (select-window new-window norecord)
+ (setq new-frame (window-frame new-window))
+ (unless (eq new-frame old-frame)
+ ;; `display-buffer' has chosen another frame, make sure it gets
+ ;; input focus and is risen.
+ (select-frame-set-input-focus new-frame)))
+
+ buffer))
+
+(defsubst pop-to-buffer-same-window (&optional buffer-or-name norecord label)
+ "Pop to buffer specified by BUFFER-OR-NAME in the selected window.
+Another window will be used only if the buffer can't be shown in
+the selected window, usually because it is dedicated to another
+buffer. Optional arguments BUFFER-OR-NAME, NORECORD and LABEL are
+as for `pop-to-buffer'."
+ (interactive "BPop to buffer in selected window:\nP")
+ (pop-to-buffer buffer-or-name 'same-window norecord label))
+
+(defsubst pop-to-buffer-same-frame (&optional buffer-or-name norecord label)
+ "Pop to buffer specified by BUFFER-OR-NAME in a window on the selected frame.
+Another frame will be used only if there is no other choice.
+Optional arguments BUFFER-OR-NAME, NORECORD and LABEL are as for
+`pop-to-buffer'."
+ (interactive "BPop to buffer on same frame:\nP")
+ (pop-to-buffer buffer-or-name 'same-frame norecord label))
+
+(defsubst pop-to-buffer-other-window (&optional buffer-or-name norecord label)
+ "Pop to buffer specified by BUFFER-OR-NAME in another window.
+The selected window will be used only if there is no other
+choice. Windows on the selected frame are preferred to windows
+on other frames. Optional arguments BUFFER-OR-NAME, NORECORD and
+LABEL are as for `pop-to-buffer'."
+ (interactive "BPop to buffer in another window:\nP")
+ (pop-to-buffer buffer-or-name 'other-window norecord))
+
+(defsubst pop-to-buffer-same-frame-other-window (&optional buffer-or-name norecord label)
+ "Pop to buffer specified by BUFFER-OR-NAME in another window on the selected frame.
+The selected window or another frame will be used only if there
+is no other choice. Optional arguments BUFFER-OR-NAME, NORECORD
+and LABEL are as for `pop-to-buffer'."
+ (interactive "BPop to buffer in another window on same frame:\nP")
+ (pop-to-buffer buffer-or-name 'same-frame-other-window norecord label))
+
+(defsubst pop-to-buffer-other-frame (&optional buffer-or-name norecord label)
+ "Pop to buffer specified by BUFFER-OR-NAME on another frame.
+The selected frame will be used only if there's no other choice.
+Optional arguments BUFFER-OR-NAME, NORECORD and LABEL are as for
+`pop-to-buffer'."
+ (interactive "BPop to buffer on another frame:\nP")
+ (pop-to-buffer buffer-or-name 'other-frame norecord label))
+
+(defun read-buffer-to-switch (prompt)
+ "Read the name of a buffer to switch to, prompting with PROMPT.
+Return the neame of the buffer as a string.
+
+This function is intended for the `switch-to-buffer' family of
+commands since these need to omit the name of the current buffer
+from the list of completions and default values."
+ (let ((rbts-completion-table (internal-complete-buffer-except)))
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (setq minibuffer-completion-table rbts-completion-table)
+ ;; Since rbts-completion-table is built dynamically, we
+ ;; can't just add it to the default value of
+ ;; icomplete-with-completion-tables, so we add it
+ ;; here manually.
+ (if (and (boundp 'icomplete-with-completion-tables)
+ (listp icomplete-with-completion-tables))
+ (set (make-local-variable 'icomplete-with-completion-tables)
+ (cons rbts-completion-table
+ icomplete-with-completion-tables))))
+ (read-buffer prompt (other-buffer (current-buffer))
+ (confirm-nonexistent-file-or-buffer)))))
+
+(defun window-normalize-buffer-to-switch-to (buffer-or-name)
+ "Normalize BUFFER-OR-NAME argument of buffer switching functions.
+If BUFFER-OR-NAME is nil, return the buffer returned by
+`other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME
+exists, return that buffer. If no such buffer exists, create a
+buffer with the name BUFFER-OR-NAME and return that buffer."
+ (if buffer-or-name
+ (or (get-buffer buffer-or-name)
+ (let ((buffer (get-buffer-create buffer-or-name)))
+ (set-buffer-major-mode buffer)
+ buffer))
+ (other-buffer)))
+
+(defun switch-to-buffer (buffer-or-name &optional norecord)
+ "Switch to buffer BUFFER-OR-NAME in the selected window.
+If called interactively, prompt for the buffer name using the
+minibuffer. The variable `confirm-nonexistent-file-or-buffer'
+determines whether to request confirmation before creating a new
+buffer.
+
+BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
+nil. If BUFFER-OR-NAME is a string that does not identify an
+existing buffer, create a buffer with that name. If
+BUFFER-OR-NAME is nil, switch to the buffer returned by
+`other-buffer'.
+
+Optional argument NORECORD non-nil means do not put the buffer
+specified by BUFFER-OR-NAME at the front of the buffer list and
+do not make the window displaying it the most recently selected
+one. Return the buffer switched to.
+
+This function is intended for interactive use only. Lisp
+functions should call `pop-to-buffer-same-window' instead."
+ (interactive
+ (list (read-buffer-to-switch "Switch to buffer: ")))
+ (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)))
+ (cond
+ ;; Don't call set-window-buffer if it's not needed since it
+ ;; might signal an error (e.g. if the window is dedicated).
+ ((eq buffer (window-buffer)) nil)
+ ((window-minibuffer-p)
+ (error "Cannot switch buffers in minibuffer window"))
+ ((eq (window-dedicated-p) t)
+ (error "Cannot switch buffers in a dedicated window"))
+ (t (set-window-buffer nil buffer)))
+ (unless norecord
+ (select-window (selected-window)))
+ (set-buffer buffer)))
+
+(defun switch-to-buffer-same-frame (buffer-or-name &optional norecord)
+ "Switch to buffer BUFFER-OR-NAME in a window on the selected frame.
+Another frame will be used only if there is no other choice.
+Arguments BUFFER-OR-NAME and NORECORD have the same meaning as
+for `switch-to-buffer'.
+
+This function is intended for interactive use only. Lisp
+functions should call `pop-to-buffer-same-frame' instead."
+ (interactive
+ (list (read-buffer-to-switch "Switch to buffer in other window: ")))
+ (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)))
+ (pop-to-buffer buffer 'same-frame norecord)))
+
+(defun switch-to-buffer-other-window (buffer-or-name &optional norecord)
+ "Switch to buffer BUFFER-OR-NAME in another window.
+The selected window will be used only if there is no other
+choice. Windows on the selected frame are preferred to windows
+on other frames. Arguments BUFFER-OR-NAME and NORECORD have the
+same meaning as for `switch-to-buffer'.
+
+This function is intended for interactive use only. Lisp
+functions should call `pop-to-buffer-other-window' instead."
+ (interactive
+ (list (read-buffer-to-switch "Switch to buffer in other window: ")))
+ (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)))
+ (pop-to-buffer buffer 'other-window norecord)))
+
+(defun switch-to-buffer-other-window-same-frame (buffer-or-name &optional norecord)
+ "Switch to buffer BUFFER-OR-NAME in another window on the selected frame.
+The selected window or another frame will be used only if there
+is no other choice. Arguments BUFFER-OR-NAME and NORECORD have
+the same meaning as for `switch-to-buffer'.
+
+This function is intended for interactive use only. Lisp
+functions should call `pop-to-buffer-other-window-same-frame'
+instead."
+ (interactive
+ (list (read-buffer-to-switch "Switch to buffer in other window: ")))
+ (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)))
+ (pop-to-buffer buffer 'same-frame-other-window norecord)))
+
+(defun switch-to-buffer-other-frame (buffer-or-name &optional norecord)
+ "Switch to buffer BUFFER-OR-NAME on another frame.
+The same frame will be used only if there is no other choice.
+Arguments BUFFER-OR-NAME and NORECORD have the same meaning
+as for `switch-to-buffer'.
+
+This function is intended for interactive use only. Lisp
+functions should call `pop-to-buffer-other-frame' instead."
+ (interactive
+ (list (read-buffer-to-switch "Switch to buffer in other frame: ")))
+ (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)))
+ (pop-to-buffer buffer 'other-frame norecord)))
+
+;;; Obsolete definitions of `display-buffer' below.
+(defcustom same-window-buffer-names nil
+ "List of names of buffers that should appear in the \"same\" window.
+`display-buffer' and `pop-to-buffer' show a buffer whose name is
+on this list in the selected rather than some other window.
+
+An element of this list can be a cons cell instead of just a
+string. In that case, the cell's car must be a string specifying
+the buffer name. This is for compatibility with
+`special-display-buffer-names'; the cdr of the cons cell is
+ignored.
+
+See also `same-window-regexps'."
+ :type '(repeat (string :format "%v"))
+ :group 'windows)
+;; (make-obsolete-variable
+ ;; 'same-window-buffer-names
+ ;; "use 2nd arg of `display-buffer' instead." "24.1")
+
+(defcustom same-window-regexps nil
+ "List of regexps saying which buffers should appear in the \"same\" window.
+`display-buffer' and `pop-to-buffer' show a buffer whose name
+matches a regexp on this list in the selected rather than some
+other window.
+
+An element of this list can be a cons cell instead of just a
+string. In that case, the cell's car must be a regexp matching
+the buffer name. This is for compatibility with
+`special-display-regexps'; the cdr of the cons cell is ignored.
+
+See also `same-window-buffer-names'."
+ :type '(repeat (regexp :format "%v"))