(when (and selected current)
(set-buffer buffer))
(when start
- (set-window-start window start))
+ ;; Don't force window-start here (even if POINT is nil).
+ (set-window-start window start t))
(when point
(if selected
(with-current-buffer buffer
(defun quit-window (&optional kill window)
"Quit WINDOW and bury its buffer.
-WINDOW defaults to the selected window.
-With a prefix argument, kill the buffer instead.
+WINDOW must be a live window and defaults to the selected one.
+With prefix argument KILL non-nil, kill the buffer instead of
+burying it.
According to information stored in WINDOW's `quit-restore' window
parameter either \(1) delete WINDOW and its frame, \(2) delete
one. If non-nil, reset `quit-restore' parameter to nil."
(interactive "P")
(setq window (window-normalize-live-window window))
- (let ((buffer (window-buffer window))
- (quit-restore (window-parameter window 'quit-restore))
- resize)
+ (let* ((buffer (window-buffer window))
+ (quit-restore (window-parameter window 'quit-restore))
+ (prev-buffer
+ (let* ((prev-buffers (window-prev-buffers window))
+ (prev-buffer (caar prev-buffers)))
+ (and (or (not (eq prev-buffer buffer))
+ (and (cdr prev-buffers)
+ (not (eq (setq prev-buffer (cadr prev-buffers))
+ buffer))))
+ prev-buffer)))
+ quad resize)
(cond
- ((and (eq (car-safe quit-restore) 'new-frame)
- (eq (nth 1 quit-restore) (window-buffer window))
- (eq (window-deletable-p window) 'frame))
+ ((and (not prev-buffer)
+ (eq (nth 1 quit-restore) 'frame)
+ (eq (window-deletable-p window) 'frame)
+ (eq (nth 3 quit-restore) buffer))
;; WINDOW's frame can be deleted.
(delete-frame (window-frame window))
;; If the previously selected window is still alive, select it.
(when (window-live-p (nth 2 quit-restore))
(select-window (nth 2 quit-restore))))
- ((and (eq (car-safe quit-restore) 'new-window)
- (eq (nth 1 quit-restore) (window-buffer window))
- (eq (window-deletable-p window) t))
- ;; WINDOW's can be deleted.
+ ((and (not prev-buffer)
+ (eq (nth 1 quit-restore) 'window)
+ (eq (window-deletable-p window) t)
+ (eq (nth 3 quit-restore) buffer))
+ ;; WINDOW can be deleted.
(delete-window window)
;; If the previously selected window is still alive, select it.
(when (window-live-p (nth 2 quit-restore))
(select-window (nth 2 quit-restore))))
- ((and (buffer-live-p (nth 0 quit-restore))
- ;; The buffer currently shown in WINDOW must still be the
- ;; buffer shown when its `quit-restore' parameter was created
- ;; in the first place.
- (eq (window-buffer window) (nth 3 quit-restore)))
- (setq resize (with-current-buffer buffer temp-buffer-resize-mode))
+ ((and (listp (setq quad (nth 1 quit-restore)))
+ (buffer-live-p (car quad))
+ (eq (nth 3 quit-restore) buffer))
+ ;; Show another buffer stored in quit-restore parameter.
+ (setq resize (with-current-buffer buffer
+ (and temp-buffer-resize-mode
+ (/= (nth 3 quad) (window-total-size window)))))
(unrecord-window-buffer window buffer)
- ;; Display buffer stored in the quit-restore parameter.
(set-window-dedicated-p window nil)
- (set-window-buffer window (nth 0 quit-restore))
- (set-window-start window (nth 1 quit-restore))
- (set-window-point window (nth 2 quit-restore))
- (and resize
- (/= (nth 4 quit-restore) (window-total-size window))
- (window-resize window
- (- (nth 4 quit-restore)
- (window-total-size window))))
+ (when resize
+ ;; Try to resize WINDOW to its old height but don't signal an
+ ;; error.
+ (condition-case nil
+ (window-resize window (- (nth 3 quad) (window-total-size window)))
+ (error nil)))
+ ;; Restore WINDOW's previous buffer, window start and point.
+ (set-window-buffer-start-and-point
+ window (nth 0 quad) (nth 1 quad) (nth 2 quad))
;; Reset the quit-restore parameter.
(set-window-parameter window 'quit-restore nil)
- (when (window-live-p (nth 5 quit-restore))
- (select-window (nth 5 quit-restore))))
+ ;; Select old window.
+ (when (window-live-p (nth 2 quit-restore))
+ (select-window (nth 2 quit-restore))))
(t
- ;; Otherwise, show another buffer in WINDOW and reset the
- ;; quit-restore parameter.
+ ;; Show some other buffer in WINDOW and reset the quit-restore
+ ;; parameter.
(set-window-parameter window 'quit-restore nil)
+ ;; Make sure that WINDOW is no more dedicated.
+ (set-window-dedicated-p window nil)
(switch-to-prev-buffer window 'bury-or-kill)))
;; Kill WINDOW's old-buffer if requested
\f
(defun display-buffer-record-window (type window buffer)
"Record information for window used by `display-buffer'.
-TYPE must be one of the symbols reuse-window, pop-up-window, or
-pop-up-frame. WINDOW is the window used for or created by the
-`display-buffer' routines. BUFFER is the buffer that shall be
-displayed."
+TYPE specifies the type of the calling operation and must be one
+of the symbols 'reuse \(when WINDOW existed already and was
+reused for displaying BUFFER), 'window \(when WINDOW was created
+on an already existing frame), or 'frame \(when WINDOW was
+created on a new frame). WINDOW is the window used for or created
+by the `display-buffer' routines. BUFFER is the buffer that
+shall be displayed.
+
+This function installs or updates the quit-restore parameter of
+WINDOW. The quit-restore parameter is a list of four elements:
+The first element is one of the symbols 'window, 'frame, 'same or
+'other. The second element is either one of the symbols 'window
+or 'frame or a list whose elements are the buffer previously
+shown in the window, that buffer's window start and window point,
+and the window's height. The third element is the window
+selected at the time the parameter was created. The fourth
+element is BUFFER."
(cond
- ((eq type 'reuse-window)
- ;; In `help-setup' window parameter record whether we used a window
- ;; on the same buffer or another one.
- (set-window-parameter
- window 'help-setup
- (if (eq (window-buffer window) buffer) 'reuse-same 'reuse-other))
- ;; In `quit-restore' parameter record information about the old
- ;; buffer unless such information exists already.
- (unless (window-parameter window 'quit-restore)
+ ((eq type 'reuse)
+ (if (eq (window-buffer window) buffer)
+ ;; WINDOW shows BUFFER already.
+ (when (consp (window-parameter window 'quit-restore))
+ ;; If WINDOW has a quit-restore parameter, reset its car.
+ (setcar (window-parameter window 'quit-restore) 'same))
+ ;; WINDOW shows another buffer.
(set-window-parameter
window 'quit-restore
- (list (window-buffer window) (window-start window)
- (window-point window) buffer
- (window-total-size window) (selected-window)))))
- ((eq type 'pop-up-window)
- ;; In `help-setup' window parameter record window as new.
- (set-window-parameter window 'help-setup 'new-window)
- ;; In `quit-restore' parameter record that we popped up this window,
- ;; its buffer, and which window was selected before.
+ (list 'other
+ ;; A quadruple of WINDOW's buffer, start, point and height.
+ (list (window-buffer window) (window-start window)
+ (window-point window) (window-total-size window))
+ (selected-window) buffer))))
+ ((eq type 'window)
+ ;; WINDOW has been created on an existing frame.
(set-window-parameter
- window 'quit-restore (list 'new-window buffer (selected-window))))
- ((eq type 'pop-up-frame)
- ;; In `help-setup' window parameter record window as on new frame.
- (set-window-parameter window 'help-setup 'new-frame)
- ;; In `quit-restore' parameter record that we popped up this window
- ;; on a new frame, the buffer, and which window was selected before.
+ window 'quit-restore
+ (list 'window 'window (selected-window) buffer)))
+ ((eq type 'frame)
+ ;; WINDOW has been created on a new frame.
(set-window-parameter
- window 'quit-restore (list 'new-frame buffer (selected-window))))))
+ window 'quit-restore
+ (list 'frame 'frame (selected-window) buffer)))))
(defcustom display-buffer-function nil
"If non-nil, function to call to handle `display-buffer'.
(let ((frame (window-frame window)))
(make-frame-visible frame)
(raise-frame frame)
- (display-buffer-record-window 'reuse-window window buffer)
+ (display-buffer-record-window 'reuse window buffer)
window))
;; Reuse the current window if the user requested it.
(when (cdr (assq 'same-window args))
special-display-buffer-names special-display-regexps)
(display-buffer buffer)))
;; If no window yet, make one in a new frame.
- (let ((frame
- (with-current-buffer buffer
- (make-frame (append args special-display-frame-alist)))))
- (display-buffer-record-window
- 'pop-up-frame (frame-selected-window frame) buffer)
- (set-window-buffer (frame-selected-window frame) buffer)
- (set-window-dedicated-p (frame-selected-window frame) t)
- (frame-selected-window frame))))))
+ (let* ((frame
+ (with-current-buffer buffer
+ (make-frame (append args special-display-frame-alist))))
+ (window (frame-selected-window frame)))
+ (display-buffer-record-window 'frame window buffer)
+ (set-window-buffer window buffer)
+ ;; Reset list of WINDOW's previous buffers to nil.
+ (set-window-prev-buffers window nil)
+ (set-window-dedicated-p window t)
+ window)))))
(defcustom special-display-function 'special-display-popup-frame
"Function to call for displaying special buffers.
(unless (or (cdr (assq 'inhibit-same-window alist))
(window-minibuffer-p)
(window-dedicated-p))
- (display-buffer-record-window 'reuse-window (selected-window) buffer)
+ (display-buffer-record-window 'reuse (selected-window) buffer)
(window--display-buffer-2 buffer (selected-window))))
(defun display-buffer--maybe-same-window (buffer alist)
(get-buffer-window-list buffer 'nomini
frames))))))
(when window
- (display-buffer-record-window 'reuse-window window buffer)
+ (display-buffer-record-window 'reuse window buffer)
(window--display-buffer-1 window))))
(defun display-buffer--special (buffer alist)
(when (and fun
(setq frame (funcall fun))
(setq window (frame-selected-window frame)))
- (display-buffer-record-window 'pop-up-frame window buffer)
+ (display-buffer-record-window 'frame window buffer)
(window--display-buffer-2 buffer window)
;; Reset list of WINDOW's previous buffers to nil.
(set-window-prev-buffers window nil)
(get-largest-window frame t))
(window--try-to-split-window
(get-lru-window frame t)))))
- (display-buffer-record-window 'pop-up-window window buffer)
+ (display-buffer-record-window 'window window buffer)
(window--display-buffer-2 buffer window)
;; Reset list of WINDOW's previous buffers to nil.
(set-window-prev-buffers window nil)
;; Restore dedicated status of selected window.
(set-window-dedicated-p window-to-undedicate nil)))
(when window
- (display-buffer-record-window 'reuse-window window buffer)
+ (display-buffer-record-window 'reuse window buffer)
(window--even-window-heights window)
(window--display-buffer-2 buffer window))))
(old-frame (selected-frame))
(window (display-buffer buffer action))
(frame (window-frame window)))
- (if (eq frame old-frame)
- ;; Make sure new window is selected (Bug#8615), (Bug#6954).
- (select-window window norecord)
- ;; If `display-buffer' has chosen another frame, make sure it
- ;; gets input focus.
+ ;; If we chose another frame, make sure it gets input focus.
+ (unless (eq frame old-frame)
(select-frame-set-input-focus frame norecord))
+ ;; Make sure new window is selected (Bug#8615), (Bug#6954).
+ (select-window window norecord)
buffer))
+(defun pop-to-buffer-same-window (buffer &optional norecord)
+ "Select buffer BUFFER in some window, preferably the same one.
+This function behaves much like `switch-to-buffer', except it
+displays with `special-display-function' if BUFFER has a match in
+`special-display-buffer-names' or `special-display-regexps'.
+
+Unlike `pop-to-buffer', this function prefers using the selected
+window over popping up a new window or frame.
+
+BUFFER may be a buffer, a string (a buffer name), or nil. If it
+is a string not naming an existent buffer, create a buffer with
+that name. If BUFFER is nil, choose some other buffer. Return
+the buffer.
+
+NORECORD, if non-nil means do not put this buffer at the front of
+the list of recently selected ones."
+ (pop-to-buffer buffer
+ '((display-buffer--special
+ display-buffer-same-window)
+ (inhibit-same-window . nil))
+ norecord))
+
(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.