]> code.delx.au - gnu-emacs/blobdiff - lisp/window.el
* progmodes/octave.el (inferior-octave-completion-table)
[gnu-emacs] / lisp / window.el
index 30ee622cfe63cf187004dc61b40be644f5278aaa..e4959da3d21b2d43bad87a89bdd5a05cc1d193ae 100644 (file)
@@ -1,7 +1,6 @@
 ;;; window.el --- GNU Emacs window commands aside from those written in C
 
-;; Copyright (C) 1985, 1989, 1992-1994, 2000-2012
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1989, 1992-1994, 2000-2013 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: internal
@@ -142,41 +141,46 @@ to `display-buffer'."
        ;; Return the window.
        window))))
 
+;; Doc is very similar to with-output-to-temp-buffer.
 (defmacro with-temp-buffer-window (buffer-or-name action quit-function &rest body)
-  "Evaluate BODY and display the buffer specified by BUFFER-OR-NAME.
+  "Bind `standard-output' to BUFFER-OR-NAME, eval BODY, show the buffer.
 BUFFER-OR-NAME must specify either a live buffer, or the name of a
 buffer (if it does not exist, this macro creates it).
 
-Make sure the specified buffer is empty before evaluating BODY.
-Do not make that buffer current for BODY.  Instead, bind
-`standard-output' to that buffer, so that output generated with
-`prin1' and similar functions in BODY goes into that buffer.
+This construct makes buffer BUFFER-OR-NAME empty before running BODY.
+It does not make the buffer current for BODY.
+Instead it binds `standard-output' to that buffer, so that output
+generated with `prin1' and similar functions in BODY goes into
+the buffer.
 
-After evaluating BODY, this marks the specified buffer unmodified and
-read-only, and displays it in a window via `display-buffer', passing
-ACTION as the action argument to `display-buffer'.  It automatically
-shrinks the relevant window if `temp-buffer-resize-mode' is enabled.
+At the end of BODY, this marks the specified buffer unmodified and
+read-only, and displays it in a window (but does not select it, or make
+the buffer current).  The display happens by calling `display-buffer'
+with the ACTION argument.  If `temp-buffer-resize-mode' is enabled,
+the relevant window shrinks automatically.
 
-Returns the value returned by BODY, unless QUIT-FUNCTION specifies
-a function.  In that case, runs the function with two arguments -
+This returns the value returned by BODY, unless QUIT-FUNCTION specifies
+a function.  In that case, it runs the function with two arguments -
 the window showing the specified buffer and the value returned by
 BODY - and returns the value returned by that function.
 
 If the buffer is displayed on a new frame, the window manager may
 decide to select that frame.  In that case, it's usually a good
-strategy if the function specified by QUIT-FUNCTION selects the
-window showing the buffer before reading a value from the
-minibuffer; for example, when asking a `yes-or-no-p' question.
-
-This construct is similar to `with-output-to-temp-buffer', but does
-not put the buffer in help mode, or call `temp-buffer-show-function'.
-It also runs different hooks, namely `temp-buffer-window-setup-hook'
-\(with the specified buffer current) and `temp-buffer-window-show-hook'
-\(with the specified buffer current and the window showing it selected).
-
-Since this macro calls `display-buffer', the window displaying
-the buffer is usually not selected and the specified buffer
-usually not made current.  QUIT-FUNCTION can override that."
+strategy if QUIT-FUNCTION selects the window showing the buffer
+before reading any value from the minibuffer; for example, when
+asking a `yes-or-no-p' question.
+
+This runs the hook `temp-buffer-window-setup-hook' before BODY,
+with the specified buffer temporarily current.  It runs the
+hook `temp-buffer-window-show-hook' after displaying the buffer,
+with that buffer temporarily current, and the window that was used to
+display it temporarily selected.
+
+This construct is similar to `with-output-to-temp-buffer', but
+runs different hooks.  In particular, it does not run
+`temp-buffer-setup-hook', which usually puts the buffer in Help mode.
+Also, it does not call `temp-buffer-show-function' (the ACTION
+argument replaces this)."
   (declare (debug t))
   (let ((buffer (make-symbol "buffer"))
        (window (make-symbol "window"))
@@ -472,7 +476,8 @@ WINDOW must be an internal window.  Return WINDOW."
       (error "Window %s is not an internal window" window)
     (walk-window-subtree
      (lambda (window)
-       (set-window-parameter window 'window-atom t))
+       (unless (window-parameter window 'window-atom)
+        (set-window-parameter window 'window-atom t)))
      window t)
     window))
 
@@ -493,24 +498,39 @@ following symbols can be used.
   sibling of an atomic window's root.  If an internal window is
   specified here, all children of that window become part of the
   atomic window too.  If no window is specified, the new window
-  becomes a sibling of the selected window.
+  becomes a sibling of the selected window.  By default, the
+  `window-atom' parameter of the existing window is set to `main'
+  provided it is live and was not set before.
 
 `side' denotes the side of the existing window where the new
   window shall be located.  Valid values are `below', `right',
-  `above' and `left'.  The default is `below'.
+  `above' and `left'.  The default is `below'.  By default, the
+  `window-atom' parameter of the new window is set to this value.
 
 The return value is the new window, nil when creating that window
 failed."
-  (let ((ignore-window-parameters t)
-       (window-combination-limit t)
-       (window (cdr (assq 'window alist)))
-       (side (cdr (assq 'side alist)))
-       new)
+  (let* ((ignore-window-parameters t)
+        (window-combination-limit t)
+        (window-combination-resize 'atom)
+        (window (cdr (assq 'window alist)))
+        (side (cdr (assq 'side alist)))
+        (atom (when window (window-parameter window 'window-atom)))
+        root new)
     (setq window (window-normalize-window window))
-    ;; Split off new window
+    (setq root (window-atom-root window))
+    ;; Split off new window.
     (when (setq new (split-window window nil side))
-      ;; Make sure we have a valid atomic window.
-      (window-make-atom (window-parent window))
+      (window-make-atom
+       (if (and root (not (eq root window)))
+          ;; When WINDOW was part of an atomic window and we did not
+          ;; split its root, root atomic window at old root.
+          root
+        ;; Otherwise, root atomic window at WINDOW's new parent.
+        (window-parent window)))
+      ;; Assign `window-atom' parameters, if needed.
+      (when (and (not atom) (window-live-p window))
+       (set-window-parameter window 'window-atom 'main))
+      (set-window-parameter new 'window-atom side)
       ;; Display BUFFER in NEW and return NEW.
       (window--display-buffer
        buffer new 'window alist display-buffer-mark-dedicated))))
@@ -626,7 +646,7 @@ its root window."
                (and (setq sibling (window-next-sibling window))
                     (window-parameter sibling 'window-side)))
            (setq major window)))
-     frame t)
+     frame t 'nomini)
     (or major (frame-root-window frame))))
 
 (defun window--major-side-window (side)
@@ -680,10 +700,8 @@ symbols and values as passed to `display-buffer-in-side-window'.
 This function may be called only if no window on SIDE exists yet.
 The new window automatically becomes the \"major\" side window on
 SIDE.  Return the new window, nil if its creation window failed."
-  (let* ((root (frame-root-window))
-        (left-or-right (memq side '(left right)))
+  (let* ((left-or-right (memq side '(left right)))
         (major (window--major-side-window side))
-        (selected-window (selected-window))
         (on-side (cond
                   ((eq side 'top) 'above)
                   ((eq side 'bottom) 'below)
@@ -693,8 +711,7 @@ SIDE.  Return the new window, nil if its creation window failed."
         ;; parent window unless needed.
         (window-combination-resize 'side)
         (window-combination-limit nil)
-        (new (split-window major nil on-side))
-        fun)
+        (new (split-window major nil on-side)))
     (when new
       ;; Initialize `window-side' parameter of new window to SIDE.
       (set-window-parameter new 'window-side side)
@@ -744,8 +761,7 @@ following symbols can be used:
   A positive value means use a slot following (that is, below or
   on the right of) the middle slot.  The default is zero."
   (let ((side (or (cdr (assq 'side alist)) 'bottom))
-       (slot (or (cdr (assq 'slot alist)) 0))
-       new)
+       (slot (or (cdr (assq 'slot alist)) 0)))
     (cond
      ((not (memq side '(top bottom left right)))
       (error "Invalid side %s specified" side))
@@ -761,7 +777,8 @@ following symbols can be used:
                (walk-window-tree
                 (lambda (window)
                   (when (eq (window-parameter window 'window-side) side)
-                    (setq windows (cons window windows)))))
+                    (setq windows (cons window windows))))
+                nil nil 'nomini)
                (nreverse windows))))
           (slots (when major (max 1 (window-child-count major))))
           (max-slots
@@ -771,9 +788,8 @@ following symbols can be used:
                  ((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 new-window)
+          best-window best-slot abs-slot)
 
       (cond
        ((and (numberp max-slots) (<= max-slots 0))
@@ -919,14 +935,14 @@ of all windows on FRAME to nil."
                     (if bottom (throw 'reset t) (setq bottom t)))
                    (t
                     (throw 'reset t))))
-                frame t))
+                frame t 'nomini))
              ;; If there's a side window, there must be at least one
              ;; non-side window.
              (and (or left top right bottom) (not none)))
       (walk-window-tree
        (lambda (window)
         (set-window-parameter window 'window-side nil))
-       frame t))))
+       frame t 'nomini))))
 
 (defun window--check (&optional frame)
   "Check atomic and side windows on FRAME.
@@ -980,8 +996,8 @@ means ignore all of the above restrictions for all windows."
                (setq value (+ value
                               (window--min-size-1 sub horizontal ignore)))
                (setq sub (window-right sub)))
-           ;; The minimum size of an ortho-combination is the maximum of
-           ;; the minimum sizes of its child windows.
+           ;; The minimum size of an ortho-combination is the maximum
+           ;; of the minimum sizes of its child windows.
            (while sub
              (setq value (max value
                               (window--min-size-1 sub horizontal ignore)))
@@ -1335,7 +1351,7 @@ violate size restrictions of WINDOW or its child windows."
         delta))
    (t 0)))
 
-(defun window--resizable-p (window delta &optional horizontal ignore trail noup nodown)
+(defun window-resizable-p (window delta &optional horizontal ignore trail noup nodown)
   "Return t if WINDOW can be resized vertically by DELTA lines.
 WINDOW must be a valid window and defaults to the selected one.
 For the meaning of the arguments of this function see the
@@ -1481,7 +1497,7 @@ This function changes neither the order of recently selected
 windows nor the buffer list."
   ;; If we start from the minibuffer window, don't fail to come
   ;; back to it.
-  (when (window-minibuffer-p (selected-window))
+  (when (window-minibuffer-p)
     (setq minibuf t))
   ;; Make sure to not mess up the order of recently selected
   ;; windows.  Use `save-selected-window' and `select-window'
@@ -1938,7 +1954,7 @@ instead."
       ;; nil or the minibuffer window is active, resize the minibuffer
       ;; window.
       (window--resize-mini-window minibuffer-window (- delta)))
-     ((window--resizable-p window delta horizontal ignore)
+     ((window-resizable-p window delta horizontal ignore)
       (window--resize-reset frame horizontal)
       (window--resize-this-window window delta horizontal ignore t)
       (if (and (not window-combination-resize)
@@ -1964,6 +1980,14 @@ instead."
      (t
       (error "Cannot resize window %s" window)))))
 
+(defun window-resize-no-error (window delta &optional horizontal ignore)
+  "Resize WINDOW vertically if it is resizable by DELTA lines.
+This function is like `window-resize' but does not signal an
+error when WINDOW cannot be resized.  For the meaning of the
+optional arguments see the documentation of `window-resize'."
+  (when (window-resizable-p window delta horizontal ignore)
+    (window-resize window delta horizontal ignore)))
+
 (defun window--resize-child-windows-skip-p (window)
   "Return non-nil if WINDOW shall be skipped by resizing routines."
   (memq (window-new-normal window) '(ignore stuck skip)))
@@ -2571,8 +2595,7 @@ move it as far as possible in the desired direction."
 Interactively, if no argument is given, make the selected window
 one line taller.  If optional argument HORIZONTAL is non-nil,
 make selected window wider by DELTA columns.  If DELTA is
-negative, shrink selected window by -DELTA lines or columns.
-Return nil."
+negative, shrink selected window by -DELTA lines or columns."
   (interactive "p")
   (let ((minibuffer-window (minibuffer-window)))
     (cond
@@ -2590,7 +2613,7 @@ Return nil."
       ;; If the selected window is full height and `resize-mini-windows'
       ;; is nil, resize the minibuffer window.
       (window--resize-mini-window minibuffer-window (- delta)))
-     ((window--resizable-p nil delta horizontal)
+     ((window-resizable-p nil delta horizontal)
       (window-resize nil delta horizontal))
      (t
       (window-resize
@@ -2605,8 +2628,7 @@ Interactively, if no argument is given, make the selected window
 one line smaller.  If optional argument HORIZONTAL is non-nil,
 make selected window narrower by DELTA columns.  If DELTA is
 negative, enlarge selected window by -DELTA lines or columns.
-Also see the `window-min-height' variable.
-Return nil."
+Also see the `window-min-height' variable."
   (interactive "p")
   (let ((minibuffer-window (minibuffer-window)))
     (cond
@@ -2624,7 +2646,7 @@ Return nil."
       ;; If the selected window is full height and `resize-mini-windows'
       ;; is nil, resize the minibuffer window.
       (window--resize-mini-window minibuffer-window delta))
-     ((window--resizable-p nil (- delta) horizontal)
+     ((window-resizable-p nil (- delta) horizontal)
       (window-resize nil (- delta) horizontal))
      (t
       (window-resize
@@ -2802,10 +2824,11 @@ and no others."
 (defun window-deletable-p (&optional window)
   "Return t if WINDOW can be safely deleted from its frame.
 WINDOW must be a valid window and defaults to the selected one.
-Return `frame' if deleting WINDOW should also delete its frame."
+Return 'frame if deleting WINDOW should also delete its frame."
   (setq window (window-normalize-window window))
 
-  (unless ignore-window-parameters
+  (unless (or ignore-window-parameters
+             (eq (window-parameter window 'delete-window) t)) 
     ;; Handle atomicity.
     (when (window-parameter window 'window-atom)
       (setq window (window-atom-root window))))
@@ -2817,6 +2840,14 @@ Return `frame' if deleting WINDOW should also delete its frame."
       ;; on the same terminal, and it does not contain the active
       ;; minibuffer.
       (unless (or (eq frame (next-frame frame 0))
+                 ;; We can delete our frame only if no other frame
+                 ;; currently uses our minibuffer window.
+                 (catch 'other
+                   (dolist (other (frame-list))
+                     (when (and (not (eq other frame))
+                                (eq (window-frame (minibuffer-window other))
+                                    frame))
+                       (throw 'other t))))
                  (let ((minibuf (active-minibuffer-window)))
                    (and minibuf (eq frame (window-frame minibuf)))))
        'frame))
@@ -2898,7 +2929,7 @@ that is its frame's root window."
          (set-window-new-normal
           sibling (+ (window-normal-size sibling horizontal)
                      (window-normal-size window horizontal))))
-        ((window--resizable-p window (- size) horizontal nil nil nil t)
+        ((window-resizable-p window (- size) horizontal nil nil nil t)
          ;; Can do without resizing fixed-size windows.
          (window--resize-siblings window (- size) horizontal))
         (t
@@ -3049,10 +3080,14 @@ WINDOW must be a live window and defaults to the selected one."
                                (set-marker (nth 2 entry) point))
                        ;; Make new markers.
                        (list (copy-marker start)
-                             (copy-marker point)))))
-
+                             (copy-marker
+                              ;; Preserve window-point-insertion-type
+                              ;; (Bug#12588).
+                              point window-point-insertion-type)))))
          (set-window-prev-buffers
-          window (cons entry (window-prev-buffers window))))))))
+          window (cons entry (window-prev-buffers window)))))
+
+      (run-hooks 'buffer-list-update-hook))))
 
 (defun unrecord-window-buffer (&optional window buffer)
   "Unrecord BUFFER in WINDOW.
@@ -3673,7 +3708,7 @@ lines or columns tall.  If SIZE is negative, make the new window
 absolute value can be less than `window-min-height' or
 `window-min-width'; so this command can make a new window as
 small as one line or two columns.  SIZE defaults to half of
-WINDOW's size.  Interactively, SIZE is the prefix argument.
+WINDOW's size.
 
 Optional third argument SIDE nil (or `below') specifies that the
 new window shall be located below WINDOW.  SIDE `above' means the
@@ -3705,7 +3740,6 @@ scrollbars are inherited from WINDOW.  If WINDOW is an internal
 window, these properties as well as the buffer displayed in the
 new window are inherited from the window selected on WINDOW's
 frame.  The selected window is not changed by this function."
-  (interactive "i")
   (setq window (window-normalize-window window))
   (let* ((side (cond
                ((not side) 'below)
@@ -3887,7 +3921,8 @@ frame.  The selected window is not changed by this function."
 
        (let* ((new (split-window-internal window new-size side new-normal)))
          ;; Assign window-side parameters, if any.
-         (when (eq window-combination-resize 'side)
+         (cond
+          ((eq window-combination-resize 'side)
            (let ((window-side
                   (cond
                    (window-side window-side)
@@ -3901,6 +3936,14 @@ frame.  The selected window is not changed by this function."
                ;; new parent the same window-side parameter.
                (set-window-parameter
                 (window-parent new) 'window-side window-side))))
+          ((eq window-combination-resize 'atom)
+           ;; Make sure `window--check-frame' won't destroy an existing
+           ;; atomic window in case the new window gets nested inside.
+           (unless (window-parameter window 'window-atom)
+             (set-window-parameter window 'window-atom t))
+           (when new-parent
+             (set-window-parameter (window-parent new) 'window-atom t))
+           (set-window-parameter new 'window-atom t)))
 
          (run-window-configuration-change-hook frame)
          (window--check frame)
@@ -4246,7 +4289,8 @@ specific buffers."
             (total-width . ,(window-total-size window t))
             (normal-height . ,(window-normal-size window))
             (normal-width . ,(window-normal-size window t))
-            (combination-limit . ,(window-combination-limit window))
+            ,@(unless (window-live-p window)
+                `((combination-limit . ,(window-combination-limit window))))
             ,@(let ((parameters (window-parameters window))
                    list)
                ;; Make copies of those window parameters whose
@@ -4334,6 +4378,9 @@ value can be also stored on disk and read back in a new session."
 (defvar window-state-put-list nil
   "Helper variable for `window-state-put'.")
 
+(defvar window-state-put-stale-windows nil
+  "Helper variable for `window-state-put'.")
+
 (defun window--state-put-1 (state &optional window ignore totals)
   "Helper function for `window-state-put'."
   (let ((type (car state)))
@@ -4416,57 +4463,66 @@ value can be also stored on disk and read back in a new session."
          (set-window-parameter window (car parameter) (cdr parameter))))
       ;; Process buffer related state.
       (when state
-       ;; We don't want to raise an error here so we create a buffer if
-       ;; there's none.
-       (set-window-buffer window (get-buffer-create (car state)))
-       (with-current-buffer (window-buffer window)
-         (set-window-hscroll window (cdr (assq 'hscroll state)))
-         (apply 'set-window-fringes
-                (cons window (cdr (assq 'fringes state))))
-         (let ((margins (cdr (assq 'margins state))))
-           (set-window-margins window (car margins) (cdr margins)))
-         (let ((scroll-bars (cdr (assq 'scroll-bars state))))
-           (set-window-scroll-bars
-            window (car scroll-bars) (nth 2 scroll-bars) (nth 3 scroll-bars)))
-         (set-window-vscroll window (cdr (assq 'vscroll state)))
-         ;; Adjust vertically.
-         (if (memq window-size-fixed '(t height))
-             ;; A fixed height window, try to restore the original size.
-             (let ((delta (- (cdr (assq 'total-height item))
-                             (window-total-height window)))
-                   window-size-fixed)
-               (when (window--resizable-p window delta)
-                 (window-resize window delta)))
-           ;; Else check whether the window is not high enough.
-           (let* ((min-size (window-min-size window nil ignore))
-                  (delta (- min-size (window-total-size window))))
-             (when (and (> delta 0)
-                        (window--resizable-p window delta nil ignore))
-               (window-resize window delta nil ignore))))
-         ;; Adjust horizontally.
-         (if (memq window-size-fixed '(t width))
-             ;; A fixed width window, try to restore the original size.
-             (let ((delta (- (cdr (assq 'total-width item))
-                             (window-total-width window)))
-                   window-size-fixed)
-               (when (window--resizable-p window delta)
-                 (window-resize window delta)))
-           ;; Else check whether the window is not wide enough.
-           (let* ((min-size (window-min-size window t ignore))
-                  (delta (- min-size (window-total-size window t))))
-             (when (and (> delta 0)
-                        (window--resizable-p window delta t ignore))
-               (window-resize window delta t ignore))))
-         ;; Set dedicated status.
-         (set-window-dedicated-p window (cdr (assq 'dedicated state)))
-         ;; Install positions (maybe we should do this after all windows
-         ;; have been created and sized).
-         (ignore-errors
-           (set-window-start window (cdr (assq 'start state)))
-           (set-window-point window (cdr (assq 'point state))))
-         ;; Select window if it's the selected one.
-         (when (cdr (assq 'selected state))
-           (select-window window)))))))
+       (let ((buffer (get-buffer (car state))))
+         (if buffer
+             (with-current-buffer buffer
+               (set-window-buffer window buffer)
+               (set-window-hscroll window (cdr (assq 'hscroll state)))
+               (apply 'set-window-fringes
+                      (cons window (cdr (assq 'fringes state))))
+               (let ((margins (cdr (assq 'margins state))))
+                 (set-window-margins window (car margins) (cdr margins)))
+               (let ((scroll-bars (cdr (assq 'scroll-bars state))))
+                 (set-window-scroll-bars
+                  window (car scroll-bars) (nth 2 scroll-bars)
+                  (nth 3 scroll-bars)))
+               (set-window-vscroll window (cdr (assq 'vscroll state)))
+               ;; Adjust vertically.
+               (if (memq window-size-fixed '(t height))
+                   ;; A fixed height window, try to restore the
+                   ;; original size.
+                   (let ((delta (- (cdr (assq 'total-height item))
+                                   (window-total-height window)))
+                         window-size-fixed)
+                     (when (window-resizable-p window delta)
+                       (window-resize window delta)))
+                 ;; Else check whether the window is not high enough.
+                 (let* ((min-size (window-min-size window nil ignore))
+                        (delta (- min-size (window-total-size window))))
+                   (when (and (> delta 0)
+                              (window-resizable-p window delta nil ignore))
+                     (window-resize window delta nil ignore))))
+               ;; Adjust horizontally.
+               (if (memq window-size-fixed '(t width))
+                   ;; A fixed width window, try to restore the original
+                   ;; size.
+                   (let ((delta (- (cdr (assq 'total-width item))
+                                   (window-total-width window)))
+                         window-size-fixed)
+                     (when (window-resizable-p window delta)
+                       (window-resize window delta)))
+                 ;; Else check whether the window is not wide enough.
+                 (let* ((min-size (window-min-size window t ignore))
+                        (delta (- min-size (window-total-size window t))))
+                   (when (and (> delta 0)
+                              (window-resizable-p window delta t ignore))
+                     (window-resize window delta t ignore))))
+               ;; Set dedicated status.
+               (set-window-dedicated-p window (cdr (assq 'dedicated state)))
+               ;; Install positions (maybe we should do this after all
+               ;; windows have been created and sized).
+               (ignore-errors
+                 (set-window-start window (cdr (assq 'start state)))
+                 (set-window-point window (cdr (assq 'point state))))
+               ;; Select window if it's the selected one.
+               (when (cdr (assq 'selected state))
+                 (select-window window)))
+           ;; We don't want to raise an error in case the buffer does
+           ;; not exist anymore, so we switch to a previous one and
+           ;; save the window with the intention of deleting it later
+           ;; if possible.
+           (switch-to-prev-buffer window)
+           (push window window-state-put-stale-windows)))))))
 
 (defun window-state-put (state &optional window ignore)
   "Put window state STATE into WINDOW.
@@ -4478,6 +4534,7 @@ Optional argument IGNORE non-nil means ignore minimum window
 sizes and fixed size restrictions.  IGNORE equal `safe' means
 windows can get as small as `window-safe-min-height' and
 `window-safe-min-width'."
+  (setq window-state-put-stale-windows nil)
   (setq window (window-normalize-window window t))
   (let* ((frame (window-frame window))
         (head (car state))
@@ -4526,6 +4583,10 @@ windows can get as small as `window-safe-min-height' and
        (set-window-buffer window (current-buffer))
        (window--state-put-1 state window nil totals)
        (window--state-put-2 ignore))
+      (while window-state-put-stale-windows
+       (let ((window (pop window-state-put-stale-windows)))
+         (when (eq (window-deletable-p window) t)
+           (delete-window window))))
       (window--check frame))))
 \f
 (defun display-buffer-record-window (type window buffer)
@@ -4555,13 +4616,17 @@ element is BUFFER."
          ;; 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 '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))))
+      (with-current-buffer (window-buffer window)
+       (set-window-parameter
+        window 'quit-restore
+        (list 'other
+              ;; A quadruple of WINDOW's buffer, start, point and height.
+              (list (current-buffer) (window-start window)
+                    ;; Preserve window-point-insertion-type (Bug#12588).
+                    (copy-marker
+                     (window-point window) window-point-insertion-type)
+                    (window-total-size window))
+              (selected-window) buffer)))))
    ((eq type 'window)
     ;; WINDOW has been created on an existing frame.
     (set-window-parameter
@@ -5170,11 +5235,12 @@ is higher than WINDOW."
       (error nil))))
 
 (defun window--display-buffer (buffer window type &optional alist dedicated)
-  "Display BUFFER in WINDOW and make its frame visible.
+  "Display BUFFER in WINDOW.
 TYPE must be one of the symbols `reuse', `window' or `frame' and
-is passed unaltered to `display-buffer-record-window'. Set
-`window-dedicated-p' to DEDICATED if non-nil.  Return WINDOW if
-BUFFER and WINDOW are live."
+is passed unaltered to `display-buffer-record-window'.  ALIST is
+the alist argument of `display-buffer'.  Set `window-dedicated-p'
+to DEDICATED if non-nil.  Return WINDOW if BUFFER and WINDOW are
+live."
   (when (and (buffer-live-p buffer) (window-live-p window))
     (display-buffer-record-window type window buffer)
     (unless (eq buffer (window-buffer window))
@@ -5187,10 +5253,10 @@ BUFFER and WINDOW are live."
     (let ((parameter (window-parameter window 'quit-restore))
          (height (cdr (assq 'window-height alist)))
          (width (cdr (assq 'window-width alist))))
-      (when (or (memq type '(window frame))
+      (when (or (eq type 'window)
                (and (eq (car parameter) 'same)
-                    (memq (nth 1 parameter) '(window frame))))
-       ;; Adjust height of new window or frame.
+                    (eq (nth 1 parameter) 'window)))
+       ;; Adjust height of window if asked for.
        (cond
         ((not height))
         ((numberp height)
@@ -5201,19 +5267,12 @@ BUFFER and WINDOW are live."
                     (* (window-total-size (frame-root-window window))
                        height))))
                 (delta (- new-height (window-total-size window))))
-           (cond
-            ((and (window--resizable-p window delta nil 'safe)
-                  (window-combined-p window))
-             (window-resize window delta nil 'safe))
-            ((or (eq type 'frame)
-                 (and (eq (car parameter) 'same)
-                      (eq (nth 1 parameter) 'frame)))
-             (set-frame-height
-              (window-frame window)
-              (+ (frame-height (window-frame window)) delta))))))
+           (when (and (window-resizable-p window delta nil 'safe)
+                      (window-combined-p window))
+             (window-resize window delta nil 'safe))))
         ((functionp height)
          (ignore-errors (funcall height window))))
-       ;; Adjust width of a window or frame.
+       ;; Adjust width of window if asked for.
        (cond
         ((not width))
         ((numberp width)
@@ -5224,18 +5283,12 @@ BUFFER and WINDOW are live."
                     (* (window-total-size (frame-root-window window) t)
                        width))))
                 (delta (- new-width (window-total-size window t))))
-           (cond
-            ((and (window--resizable-p window delta t 'safe)
-                  (window-combined-p window t))
-             (window-resize window delta t 'safe))
-            ((or (eq type 'frame)
-                 (and (eq (car parameter) 'same)
-                      (eq (nth 1 parameter) 'frame)))
-             (set-frame-width
-              (window-frame window)
-              (+ (frame-width (window-frame window)) delta))))))
+           (when (and (window-resizable-p window delta t 'safe)
+                      (window-combined-p window t))
+             (window-resize window delta t 'safe))))
         ((functionp width)
          (ignore-errors (funcall width window))))))
+
     window))
 
 (defun window--maybe-raise-frame (frame)
@@ -5295,13 +5348,19 @@ See `display-buffer' for details.")
   "Alist of conditional actions for `display-buffer'.
 This is a list of elements (CONDITION . ACTION), where:
 
- CONDITION is either a regexp matching buffer names, or a function
-  that takes a buffer and returns a boolean.
+ CONDITION is either a regexp matching buffer names, or a
+  function that takes two arguments - a buffer name and the
+  ACTION argument of `display-buffer' - and returns a boolean.
 
  ACTION is a cons cell (FUNCTION . ALIST), where FUNCTION is a
   function or a list of functions.  Each such function should
   accept two arguments: a buffer to display and an alist of the
-  same form as ALIST.  See `display-buffer' for details."
+  same form as ALIST.  See `display-buffer' for details.
+
+`display-buffer' scans this alist until it either finds a
+matching regular expression or the function specified by a
+condition returns non-nil.  In any of these cases, it adds the
+associated action to the list of actions it will try."
   :type `(alist :key-type
                (choice :tag "Condition"
                        regexp
@@ -5335,15 +5394,16 @@ specified, e.g. by the user options `display-buffer-alist' or
 `display-buffer-base-action'.  See `display-buffer'.")
 (put 'display-buffer-fallback-action 'risky-local-variable t)
 
-(defun display-buffer-assq-regexp (buffer-name alist)
-  "Retrieve ALIST entry corresponding to BUFFER-NAME."
+(defun display-buffer-assq-regexp (buffer-name alist action)
+  "Retrieve ALIST entry corresponding to BUFFER-NAME.
+ACTION is the action argument passed to `display-buffer'."
   (catch 'match
     (dolist (entry alist)
       (let ((key (car entry)))
        (when (or (and (stringp key)
                       (string-match-p key buffer-name))
-                 (and (symbolp key) (functionp key)
-                      (funcall key buffer-name alist)))
+                 (and (functionp key)
+                      (funcall key buffer-name action)))
          (throw 'match (cdr entry)))))))
 
 (defvar display-buffer--same-window-action
@@ -5445,6 +5505,9 @@ argument, ACTION is t."
   (let ((buffer (if (bufferp buffer-or-name)
                    buffer-or-name
                  (get-buffer buffer-or-name)))
+       ;; Make sure that when we split windows the old window keeps
+       ;; point, bug#14829.
+       (split-window-keep-point t)
        ;; Handle the old form of the first argument.
        (inhibit-same-window (and action (not (listp action)))))
     (unless (listp action) (setq action nil))
@@ -5453,8 +5516,8 @@ argument, ACTION is t."
        (funcall display-buffer-function buffer inhibit-same-window)
       ;; Otherwise, use the defined actions.
       (let* ((user-action
-             (display-buffer-assq-regexp (buffer-name buffer)
-                                         display-buffer-alist))
+             (display-buffer-assq-regexp
+              (buffer-name buffer) display-buffer-alist action))
              (special-action (display-buffer--special-action buffer))
             ;; Extra actions from the arguments to this function:
             (extra-action
@@ -5582,7 +5645,10 @@ new frame."
         (fun pop-up-frame-function)
         frame window)
     (when (and fun
-              (setq frame (funcall fun))
+              ;; Make BUFFER current so `make-frame' will use it as the
+              ;; new frame's buffer (Bug#15133).
+              (with-current-buffer buffer
+                (setq frame (funcall fun)))
               (setq window (frame-selected-window frame)))
       (prog1 (window--display-buffer
              buffer window 'frame alist display-buffer-mark-dedicated)
@@ -5653,7 +5719,8 @@ This either splits the window at the bottom of the frame or the
 frame's root window, or reuses an existing window at the bottom
 of the selected frame."
   (let (bottom-window window)
-    (walk-window-tree (lambda (window) (setq bottom-window window)))
+    (walk-window-tree
+     (lambda (window) (setq bottom-window window)) nil nil 'nomini)
     (or (and (not (frame-parameter nil 'unsplittable))
             (setq window (window--try-to-split-window bottom-window alist))
             (window--display-buffer
@@ -5661,7 +5728,7 @@ of the selected frame."
        (and (not (frame-parameter nil 'unsplittable))
             (setq window
                   (condition-case nil
-                      (split-window (frame-root-window))
+                      (split-window (window--major-non-side-window))
                     (error nil)))
             (window--display-buffer
              buffer window 'window alist display-buffer-mark-dedicated))
@@ -5702,7 +5769,7 @@ above, even if that window never showed BUFFER before."
                   0)
                  (display-buffer-reuse-frames 0)
                  (t (last-nonminibuffer-frame))))
-        entry best-window second-best-window window)
+        best-window second-best-window window)
     ;; Scan windows whether they have shown the buffer recently.
     (catch 'best
       (dolist (window (window-list-1 (frame-first-window) 'nomini frames))
@@ -5749,7 +5816,7 @@ that frame."
                (unless (and not-this-window
                             (eq window (selected-window)))
                  window))
-             (get-largest-window 0 not-this-window))))
+             (get-largest-window 0 nil not-this-window))))
     (when (window-live-p window)
       (prog1
          (window--display-buffer buffer window 'reuse alist)
@@ -5780,7 +5847,8 @@ at the front of the list of recently selected ones."
   (interactive (list (read-buffer "Pop to buffer: " (other-buffer))
                     (if current-prefix-arg t)))
   (setq buffer (window-normalize-buffer-to-switch-to buffer))
-  (set-buffer buffer)
+  ;; This should be done by `select-window' below.
+  ;; (set-buffer buffer)
   (let* ((old-frame (selected-frame))
         (window (display-buffer buffer action))
         (frame (window-frame window)))
@@ -5866,7 +5934,12 @@ the selected window or never appeared in it before, or if
   :version "24.3")
 
 (defun switch-to-buffer (buffer-or-name &optional norecord force-same-window)
-  "Switch to buffer BUFFER-OR-NAME in the selected window.
+  "Display buffer BUFFER-OR-NAME in the selected window.
+
+WARNING: This is NOT the way to work on another buffer temporarily
+within a Lisp program!  Use `set-buffer' instead.  That avoids
+messing with the window-buffer correspondences.
+
 If the selected window cannot display the specified
 buffer (e.g. if it is a minibuffer window or strongly dedicated
 to another buffer), call `pop-to-buffer' to select the buffer in
@@ -6068,23 +6141,32 @@ of `fit-frame-to-buffer-max-height' and `window-min-height'."
   :group 'help)
 
 (defcustom fit-frame-to-buffer-bottom-margin 4
-  "Bottom margin for `fit-frame-to-buffer'.
-This is the number of lines `fit-frame-to-buffer' leaves free at the
-bottom of the display in order to not obscure the system task bar."
+  "Bottom margin for the command `fit-frame-to-buffer'.
+This is the number of lines that function leaves free at the bottom of
+the display, in order to not obscure any system task bar or panel.
+If you do not have one (or if it is vertical) you might want to
+reduce this.  If it is thicker, you might want to increase this."
+  ;; If you set this too small, fit-frame-to-buffer can shift the
+  ;; frame up to avoid the panel.
   :type 'integer
   :version "24.3"
   :group 'windows)
 
+(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
+(declare-function tool-bar-lines-needed "xdisp.c" (&optional frame))
+
 (defun fit-frame-to-buffer (&optional frame max-height min-height)
-  "Adjust height of FRAME to display its buffer's contents exactly.
+  "Adjust height of FRAME to display its buffer contents exactly.
 FRAME can be any live frame and defaults to the selected one.
 
-Optional argument MAX-HEIGHT specifies the maximum height of
-FRAME and defaults to the height of the display below the current
-top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN.
-Optional argument MIN-HEIGHT specifies the minimum height of
-FRAME."
+Optional argument MAX-HEIGHT specifies the maximum height of FRAME.
+It defaults to the height of the display below the current
+top line of FRAME, minus `fit-frame-to-buffer-bottom-margin'.
+Optional argument MIN-HEIGHT specifies the minimum height of FRAME.
+The default corresponds to `window-min-height'."
   (interactive)
+  (or (fboundp 'x-display-pixel-height)
+      (user-error "Cannot resize frame in non-graphic Emacs"))
   (setq frame (window-normalize-frame frame))
   (let* ((root (frame-root-window frame))
         (frame-min-height
@@ -6160,6 +6242,10 @@ defaults to `window-min-height'.  Both MAX-HEIGHT and MIN-HEIGHT
 are specified in lines and include the mode line and header line,
 if any.
 
+If WINDOW is a full height window, then if the option
+`fit-frame-to-buffer' is non-nil, this calls the function
+`fit-frame-to-buffer' to adjust the frame height.
+
 Return the number of lines by which WINDOW was enlarged or
 shrunk.  If an error occurs during resizing, return nil but don't
 signal an error.
@@ -6603,11 +6689,14 @@ is active.  This function is run by `mouse-autoselect-window-timer'."
            (window-at (cadr mouse-position) (cddr mouse-position)
                       (car mouse-position)))))
      (cond
-      ((or (menu-or-popup-active-p)
+      ((or (and (fboundp 'menu-or-popup-active-p) (menu-or-popup-active-p))
           (and window
-               (not (coordinates-in-window-p (cdr mouse-position) window))))
-       ;; A menu / popup dialog is active or the mouse is on the scroll-bar
-       ;; of WINDOW, temporarily suspend delayed autoselection.
+               (let ((coords (coordinates-in-window-p
+                              (cdr mouse-position) window)))
+                 (and (not (consp coords))
+                      (not (memq coords '(left-margin right-margin)))))))
+       ;; A menu / popup dialog is active or the mouse is not on the
+       ;; text region of WINDOW: Suspend autoselection temporarily.
        (mouse-autoselect-window-start mouse-position nil t))
       ((eq mouse-autoselect-window-state 'suspend)
        ;; Delayed autoselection was temporarily suspended, reenable it.
@@ -6635,7 +6724,7 @@ is active.  This function is run by `mouse-autoselect-window-timer'."
        ;; minibuffer.  Use `unread-command-events' in order to execute pre-
        ;; and post-command hooks and trigger idle timers.  To avoid delaying
        ;; autoselection again, set `mouse-autoselect-window-state'."
-       (unless (window-minibuffer-p (selected-window))
+       (unless (window-minibuffer-p)
         (setq mouse-autoselect-window-state 'select)
         (setq unread-command-events
               (cons (list 'select-window (list window))
@@ -6661,7 +6750,7 @@ is active.  This function is run by `mouse-autoselect-window-timer'."
                ;; minibuffer gets unselected unexpectedly, and where
                ;; you then have to move your mouse all the way down to
                ;; the minibuffer to select it.
-               (window-minibuffer-p (selected-window))
+               (window-minibuffer-p)
                ;; Don't switch to minibuffer window unless it's active.
                (and (window-minibuffer-p window)
                     (not (minibuffer-window-active-p window)))