]> code.delx.au - gnu-emacs/blobdiff - lisp/window.el
defun fix for cl declarations + interactive forms
[gnu-emacs] / lisp / window.el
index 66b86f45e77def156e7d2fbe4cf63a11733ce46b..63d75f60e1ee4d10347c6c7eada666efb90144d0 100644 (file)
@@ -1,7 +1,7 @@
 ;;; 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
 
 ;;; Code:
 
+(defun internal--before-save-selected-window ()
+  (cons (selected-window)
+        ;; We save and restore all frames' selected windows, because
+        ;; `select-window' can change the frame-selected-window of
+        ;; whatever frame that window is in.  Each text terminal's
+        ;; top-frame is preserved by putting it last in the list.
+        (apply #'append
+               (mapcar (lambda (terminal)
+                         (let ((frames (frames-on-display-list terminal))
+                               (top-frame (tty-top-frame terminal))
+                               alist)
+                           (if top-frame
+                               (setq frames
+                                     (cons top-frame
+                                           (delq top-frame frames))))
+                           (dolist (f frames)
+                             (push (cons f (frame-selected-window f))
+                                   alist))
+                           alist))
+                       (terminal-list)))))
+
+(defun internal--after-save-selected-window (state)
+  (dolist (elt (cdr state))
+    (and (frame-live-p (car elt))
+         (window-live-p (cdr elt))
+         (set-frame-selected-window (car elt) (cdr elt) 'norecord)))
+  (when (window-live-p (car state))
+    (select-window (car state) 'norecord)))
+
 (defmacro save-selected-window (&rest body)
   "Execute BODY, then select the previously selected window.
 The value returned is the value of the last form in BODY.
@@ -44,34 +73,11 @@ its normal operation could make a different buffer current.  The
 order of recently selected windows and the buffer list ordering
 are not altered by this macro (unless they are altered in BODY)."
   (declare (indent 0) (debug t))
-  `(let ((save-selected-window-window (selected-window))
-        ;; We save and restore all frames' selected windows, because
-        ;; `select-window' can change the frame-selected-window of
-        ;; whatever frame that window is in.  Each text terminal's
-        ;; top-frame is preserved by putting it last in the list.
-        (save-selected-window-alist
-         (apply 'append
-                (mapcar (lambda (terminal)
-                          (let ((frames (frames-on-display-list terminal))
-                                (top-frame (tty-top-frame terminal))
-                                alist)
-                            (if top-frame
-                                (setq frames
-                                      (cons top-frame
-                                            (delq top-frame frames))))
-                            (dolist (f frames)
-                              (push (cons f (frame-selected-window f))
-                                    alist))))
-                        (terminal-list)))))
+  `(let ((save-selected-window--state (internal--before-save-selected-window)))
      (save-current-buffer
        (unwind-protect
           (progn ,@body)
-        (dolist (elt save-selected-window-alist)
-          (and (frame-live-p (car elt))
-               (window-live-p (cdr elt))
-               (set-frame-selected-window (car elt) (cdr elt) 'norecord)))
-        (when (window-live-p save-selected-window-window)
-          (select-window save-selected-window-window 'norecord))))))
+         (internal--after-save-selected-window save-selected-window--state)))))
 
 (defvar temp-buffer-window-setup-hook nil
   "Normal hook run by `with-temp-buffer-window' before buffer display.
@@ -84,7 +90,7 @@ This hook is run by `with-temp-buffer-window' with the buffer
 displayed and current and its window selected.")
 
 (defun temp-buffer-window-setup (buffer-or-name)
-  "Set up temporary buffer specified by BUFFER-OR-NAME 
+  "Set up temporary buffer specified by BUFFER-OR-NAME.
 Return the buffer."
   (let ((old-dir default-directory)
        (buffer (get-buffer-create buffer-or-name)))
@@ -111,7 +117,19 @@ to `display-buffer'."
       (set-buffer-modified-p nil)
       (setq buffer-read-only t)
       (goto-char (point-min))
-      (when (setq window (display-buffer buffer action))
+      (when (let ((window-combination-limit
+                  ;; When `window-combination-limit' equals
+                  ;; `temp-buffer' or `temp-buffer-resize' and
+                  ;; `temp-buffer-resize-mode' is enabled in this
+                  ;; buffer bind it to t so resizing steals space
+                  ;; preferably from the window that was split.
+                  (if (or (eq window-combination-limit 'temp-buffer)
+                          (and (eq window-combination-limit
+                                   'temp-buffer-resize)
+                               temp-buffer-resize-mode))
+                      t
+                    window-combination-limit)))
+             (setq window (display-buffer buffer action)))
        (setq frame (window-frame window))
        (unless (eq frame (selected-frame))
          (raise-frame frame))
@@ -124,42 +142,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 buffer specified by BUFFER-OR-NAME.
-BUFFER-OR-NAME must specify either a live buffer or the name of a
-buffer.  If no buffer with such a name exists, create one.
-
-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.
-
-After evaluating BODY, mark the specified buffer unmodified and
-read-only, and display it in a window via `display-buffer'.  Pass
-ACTION as action argument to `display-buffer'.  Automatically
-shrink the window used if `temp-buffer-resize-mode' is enabled.
-
-Return the value returned by BODY unless QUIT-FUNCTION specifies
-a function.  In that case, run the function with two arguments -
+  "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).
+
+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.
+
+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.
+
+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 return the value returned by that function.
+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 neither put the buffer in help mode nor does it 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"))
@@ -496,7 +518,7 @@ failed."
       (window-make-atom (window-parent window))
       ;; Display BUFFER in NEW and return NEW.
       (window--display-buffer
-       buffer new 'window display-buffer-mark-dedicated))))
+       buffer new 'window alist display-buffer-mark-dedicated))))
 
 (defun window--atom-check-1 (window)
   "Subroutine of `window--atom-check'."
@@ -665,12 +687,6 @@ 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)))
-        (size (or (assq 'size alist)
-                  (/ (window-total-size (frame-root-window) left-or-right)
-                     ;; By default use a fourth of the size of the
-                     ;; frame's root window.  This has to be made
-                     ;; customizable via ALIST.
-                     4)))
         (major (window--major-side-window side))
         (selected-window (selected-window))
         (on-side (cond
@@ -682,7 +698,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 (- size) on-side))
+        (new (split-window major nil on-side))
         fun)
     (when new
       ;; Initialize `window-side' parameter of new window to SIDE.
@@ -693,8 +709,22 @@ SIDE.  Return the new window, nil if its creation window failed."
       ;; the new window is deleted, a side window on the opposite side
       ;; does not get resized.
       (set-window-parameter new 'delete-window 'delete-side-window)
+      ;; Auto-adjust height/width of new window unless a size has been
+      ;; explicitly requested.
+      (unless (if left-or-right
+                 (cdr (assq 'window-width alist))
+               (cdr (assq 'window-height alist)))
+       (setq alist
+             (cons
+              (cons
+               (if left-or-right 'window-width 'window-height)
+               (/ (window-total-size (frame-root-window) left-or-right)
+                  ;; By default use a fourth of the size of the
+                  ;; frame's root window.
+                  4))
+              alist)))
       ;; Install BUFFER in new window and return NEW.
-      (window--display-buffer buffer new 'window 'side))))
+      (window--display-buffer buffer new 'window alist 'side))))
 
 (defun delete-side-window (window)
   "Delete side window WINDOW."
@@ -802,7 +832,7 @@ following symbols can be used:
        ;; ALIST (or, better, avoided in the "other" functions).
        (or (and this-window
                 ;; Reuse `this-window'.
-                (window--display-buffer buffer this-window 'reuse 'side))
+                (window--display-buffer buffer this-window 'reuse alist 'side))
            (and (or (not max-slots) (< slots max-slots))
                 (or (and next-window
                          ;; Make new window before `next-window'.
@@ -827,13 +857,14 @@ following symbols can be used:
                             window 'delete-window 'delete-side-window)
                            window)))
                   (set-window-parameter window 'window-slot slot)
-                  (window--display-buffer buffer window 'window 'side))
+                  (window--display-buffer buffer window 'window alist 'side))
            (and best-window
                 ;; Reuse `best-window'.
                 (progn
                   ;; Give best-window the new slot value.
                   (set-window-parameter best-window 'window-slot slot)
-                  (window--display-buffer buffer best-window 'reuse 'side)))))))))
+                  (window--display-buffer
+                   buffer best-window 'reuse alist 'side)))))))))
 
 (defun window--side-check (&optional frame)
   "Check the side window configuration of FRAME.
@@ -891,7 +922,7 @@ of all windows on FRAME to nil."
                     (if right (throw 'reset t) (setq right t)))
                    ((eq side 'bottom)
                     (if bottom (throw 'reset t) (setq bottom t)))
-                   (t 
+                   (t
                     (throw 'reset t))))
                 frame t))
              ;; If there's a side window, there must be at least one
@@ -2067,9 +2098,9 @@ preferably only resize windows adjacent to EDGE.
 Return the symbol `normalized' if new normal sizes have been
 already set by this routine."
   (let* ((first (window-child parent))
-        (sub first)
+        (last (window-last-child parent))
         (parent-total (+ (window-total-size parent horizontal) delta))
-        best-window best-value)
+        sub best-window best-value)
 
     (if (and edge (memq trail '(before after))
             (progn
@@ -2113,7 +2144,7 @@ already set by this routine."
          ;; normal sizes have been already set.
          'normalized)
       ;; Resize all windows proportionally.
-      (setq sub first)
+      (setq sub last)
       (while sub
        (cond
         ((or (window--resize-child-windows-skip-p sub)
@@ -2142,14 +2173,14 @@ already set by this routine."
                 parent-total)
              (window-normal-size sub horizontal)))))
 
-       (setq sub (window-right sub)))
+       (setq sub (window-left sub)))
 
       (cond
        ((< delta 0)
        ;; Shrink windows by delta.
        (setq best-window t)
        (while (and best-window (not (zerop delta)))
-         (setq sub first)
+         (setq sub last)
          (setq best-window nil)
          (setq best-value most-negative-fixnum)
          (while sub
@@ -2159,7 +2190,7 @@ already set by this routine."
              (setq best-window sub)
              (setq best-value (cdr (window-new-normal sub))))
 
-           (setq sub (window-right sub)))
+           (setq sub (window-left sub)))
 
          (when best-window
            (setq delta (1+ delta)))
@@ -2176,7 +2207,7 @@ already set by this routine."
        ;; Enlarge windows by delta.
        (setq best-window t)
        (while (and best-window (not (zerop delta)))
-         (setq sub first)
+         (setq sub last)
          (setq best-window nil)
          (setq best-value most-positive-fixnum)
          (while sub
@@ -2185,7 +2216,7 @@ already set by this routine."
              (setq best-window sub)
              (setq best-value (window-new-normal sub)))
 
-           (setq sub (window-right sub)))
+           (setq sub (window-left sub)))
 
          (when best-window
            (setq delta (1- delta)))
@@ -2197,7 +2228,7 @@ already set by this routine."
              (window-normal-size best-window horizontal))))))
 
       (when best-window
-       (setq sub first)
+       (setq sub last)
        (while sub
          (when (or (consp (window-new-normal sub))
                    (numberp (window-new-normal sub)))
@@ -2215,7 +2246,7 @@ already set by this routine."
                ;; recursively even if it's size does not change.
                (window--resize-this-window
                 sub delta horizontal ignore nil trail edge))))
-         (setq sub (window-right sub)))))))
+         (setq sub (window-left sub)))))))
 
 (defun window--resize-siblings (window delta &optional horizontal ignore trail edge)
   "Resize other windows when WINDOW is resized vertically by DELTA lines.
@@ -2394,27 +2425,33 @@ Return the number of lines that were recovered.
 This function is only called by the minibuffer window resizing
 routines.  It resizes windows proportionally and never deletes
 any windows."
-  (when (numberp delta)
-    (let (ignore)
-      (cond
-       ((< delta 0)
-       (setq delta (window-sizable window delta)))
-       ((> delta 0)
-       (unless (window-sizable window delta)
-         (setq ignore t))))
-
-      (window--resize-reset (window-frame window))
-      ;; Ideally, we would resize just the last window in a combination
-      ;; but that's not feasible for the following reason: If we grow
-      ;; the minibuffer window and the last window cannot be shrunk any
-      ;; more, we shrink another window instead.  But if we then shrink
-      ;; the minibuffer window again, the last window might get enlarged
-      ;; and the state after shrinking is not the state before growing.
-      ;; So, in practice, we'd need a history variable to record how to
-      ;; proceed.  But I'm not sure how such a variable could work with
-      ;; repeated minibuffer window growing steps.
-      (window--resize-this-window window delta nil ignore t)
-      delta)))
+  (let ((frame (window-frame window))
+       ignore)
+    (cond
+     ((not (numberp delta))
+      (setq delta 0))
+     ((zerop delta))
+     ((< delta 0)
+      (setq delta (window-sizable window delta))
+      (window--resize-reset frame)
+      ;; When shrinking the root window, emulate an edge drag in order
+      ;; to not resize other windows if we can avoid it (Bug#12419).
+      (window--resize-this-window
+       window delta nil ignore t 'before
+       (+ (window-top-line window) (window-total-size window)))
+      ;; Don't record new normal sizes to make sure that shrinking back
+      ;; proportionally works as intended.
+      (walk-window-tree
+       (lambda (window) (set-window-new-normal window 'ignore)) frame t))
+     ((> delta 0)
+      (window--resize-reset frame)
+      (unless (window-sizable window delta)
+       (setq ignore t))
+      ;; When growing the root window, resize proportionally.  This
+      ;; should give windows back their original sizes (hopefully).
+      (window--resize-this-window window delta nil ignore t)))
+     ;; Return the possibly adjusted DELTA.
+     delta))
 
 (defun adjust-window-trailing-edge (window delta &optional horizontal)
   "Move WINDOW's bottom edge by DELTA lines.
@@ -2539,8 +2576,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
@@ -2573,8 +2609,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
@@ -3017,8 +3052,10 @@ 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))))))))
 
@@ -3058,10 +3095,11 @@ before was current this also makes BUFFER the current buffer."
   "If non-nil, allow switching to an already visible buffer.
 If this variable is non-nil, `switch-to-prev-buffer' and
 `switch-to-next-buffer' may switch to an already visible buffer
-provided the buffer was shown in the argument window before.  If
-this variable is nil, `switch-to-prev-buffer' and
-`switch-to-next-buffer' always try to avoid switching to a buffer
-that is already visible in another window on the same frame."
+provided the buffer was shown before in the window specified as
+argument to those functions.  If this variable is nil,
+`switch-to-prev-buffer' and `switch-to-next-buffer' always try to
+avoid switching to a buffer that is already visible in another
+window on the same frame."
   :type 'boolean
   :version "24.1"
   :group 'windows)
@@ -3523,7 +3561,12 @@ the buffer of WINDOW.  The following values are handled:
         quad entry)
     (cond
      ((and (not prev-buffer)
-          (memq (nth 1 quit-restore) '(window frame))
+          (or (eq (nth 1 quit-restore) 'frame)
+              (and (eq (nth 1 quit-restore) 'window)
+                   ;; If the window has been created on an existing
+                   ;; frame and ended up as the sole window on that
+                   ;; frame, do not delete it (Bug#12764).
+                   (not (eq window (frame-root-window window)))))
           (eq (nth 3 quit-restore) buffer)
           ;; Delete WINDOW if possible.
           (window--delete window nil (eq bury-or-kill 'kill)))
@@ -3678,9 +3721,8 @@ frame.  The selected window is not changed by this function."
         (parent (window-parent window))
         (function (window-parameter window 'split-window))
         (window-side (window-parameter window 'window-side))
-        ;; Rebind `window-combination-limit' and
-        ;; `window-combination-resize' since in some cases we may have
-        ;; to override their value.
+        ;; Rebind the following two variables since in some cases we
+        ;; have to override their value.
         (window-combination-limit window-combination-limit)
         (window-combination-resize window-combination-resize)
         atom-root)
@@ -3738,7 +3780,7 @@ frame.  The selected window is not changed by this function."
              (and window-combination-resize
                   (or (window-parameter window 'window-side)
                       (not (eq window-combination-resize 'side)))
-                  (not window-combination-limit)
+                  (not (eq window-combination-limit t))
                   ;; Resize makes sense in iso-combinations only.
                   (window-combined-p window horizontal)))
             ;; `old-size' is the current size of WINDOW.
@@ -3818,7 +3860,7 @@ frame.  The selected window is not changed by this function."
              ;; Make new-parent non-nil if we need a new parent window;
              ;; either because we want to nest or because WINDOW is not
              ;; iso-combined.
-             (or window-combination-limit
+             (or (eq window-combination-limit t)
                  (not (window-combined-p window horizontal))))
        (setq new-normal
              ;; Make new-normal the normal size of the new window.
@@ -4518,13 +4560,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
@@ -4551,6 +4597,9 @@ of the window used."
          (function :tag "function"))
   :group 'windows)
 
+(make-obsolete-variable 'display-buffer-function
+                       'display-buffer-alist "24.3")
+
 ;; Eventually, we want to turn this into a defvar; instead of
 ;; customizing this, the user should use a `pop-up-frame-parameters'
 ;; alist entry in `display-buffer-base-action'.
@@ -4768,8 +4817,8 @@ the selected window.  If they contain (same-frame . t), display
 BUFFER in a window of the selected frame.
 
 If ARGS is a list whose car is a symbol, use (car ARGS) as a
-function to do the work.  Pass it BUFFER as first argument,
-and (cdr ARGS) as second."
+function to do the work.  Pass it BUFFER as first argument, and
+pass the elements of (cdr ARGS) as the remaining arguments."
   (if (and args (symbolp (car args)))
       (apply (car args) buffer (cdr args))
     (let ((window (get-buffer-window buffer 0)))
@@ -5057,18 +5106,30 @@ split."
                 (with-selected-window window
                   (split-window-below))))))))
 
-(defun window--try-to-split-window (window)
+(defun window--try-to-split-window (window &optional alist)
   "Try to split WINDOW.
 Return value returned by `split-window-preferred-function' if it
 represents a live window, nil otherwise."
       (and (window-live-p window)
           (not (frame-parameter (window-frame window) 'unsplittable))
-          (let ((new-window
-                 ;; Since `split-window-preferred-function' might
-                 ;; throw an error use `condition-case'.
-                 (condition-case nil
-                     (funcall split-window-preferred-function window)
-                   (error nil))))
+          (let* ((window-combination-limit
+                  ;; When `window-combination-limit' equals
+                  ;; `display-buffer' or equals `resize-window' and a
+                  ;; `window-height' or `window-width' alist entry are
+                  ;; present, bind it to t so resizing steals space
+                  ;; preferably from the window that was split.
+                  (if (or (eq window-combination-limit 'display-buffer)
+                          (and (eq window-combination-limit 'window-size)
+                               (or (cdr (assq 'window-height alist))
+                                   (cdr (assq 'window-width alist)))))
+                      t
+                    window-combination-limit))
+                 (new-window
+                  ;; Since `split-window-preferred-function' might
+                  ;; throw an error use `condition-case'.
+                  (condition-case nil
+                      (funcall split-window-preferred-function window)
+                    (error nil))))
             (and (window-live-p new-window) new-window))))
 
 (defun window--frame-usable-p (frame)
@@ -5117,12 +5178,13 @@ is higher than WINDOW."
         (/ (- (window-total-height window) (window-total-height)) 2))
       (error nil))))
 
-(defun window--display-buffer (buffer window type &optional dedicated)
-  "Display BUFFER in WINDOW and make its frame visible.
+(defun window--display-buffer (buffer window type &optional alist dedicated)
+  "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))
@@ -5132,6 +5194,45 @@ BUFFER and WINDOW are live."
        (set-window-dedicated-p window dedicated))
       (when (memq type '(window frame))
        (set-window-prev-buffers window nil)))
+    (let ((parameter (window-parameter window 'quit-restore))
+         (height (cdr (assq 'window-height alist)))
+         (width (cdr (assq 'window-width alist))))
+      (when (or (eq type 'window)
+               (and (eq (car parameter) 'same)
+                    (eq (nth 1 parameter) 'window)))
+       ;; Adjust height of window if asked for.
+       (cond
+        ((not height))
+        ((numberp height)
+         (let* ((new-height
+                 (if (integerp height)
+                     height
+                   (round
+                    (* (window-total-size (frame-root-window window))
+                       height))))
+                (delta (- new-height (window-total-size window))))
+           (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 window if asked for.
+       (cond
+        ((not width))
+        ((numberp width)
+         (let* ((new-width
+                 (if (integerp width)
+                     width
+                   (round
+                    (* (window-total-size (frame-root-window window) t)
+                       width))))
+                (delta (- new-width (window-total-size window t))))
+           (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)
@@ -5191,13 +5292,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
@@ -5231,15 +5338,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
@@ -5262,8 +5370,16 @@ BUFFER-OR-NAME must be a buffer or the name of an existing
 buffer.  Return the window chosen for displaying BUFFER-OR-NAME,
 or nil if no such window is found.
 
-Optional argument ACTION should have the form (FUNCTION . ALIST).
-FUNCTION is either a function or a list of functions.
+Optional argument ACTION, if non-nil, should specify a display
+action.  Its form is described below.
+
+Optional argument FRAME, if non-nil, acts like an additional
+ALIST entry (reusable-frames . FRAME) to the action list of ACTION,
+specifying the frame(s) to search for a window that is already
+displaying the buffer.  See `display-buffer-reuse-window'
+
+If ACTION is non-nil, it should have the form (FUNCTION . ALIST),
+where FUNCTION is either a function or a list of functions, and
 ALIST is an arbitrary association list (alist).
 
 Each such FUNCTION should accept two arguments: the buffer to
@@ -5280,6 +5396,9 @@ function in the combined function list in turn, passing the
 buffer as the first argument and the combined alist as the second
 argument, until one of the functions returns non-nil.
 
+If ACTION is nil, the function list and the alist are built using
+only the other variables mentioned above.
+
 Available action functions include:
  `display-buffer-same-window'
  `display-buffer-reuse-window'
@@ -5304,16 +5423,27 @@ Recognized alist entries include:
                               parameters to give a new frame, if
                               one is created.
 
+ `window-height' -- Value specifies either an integer (the number
+    of lines of a new window), a floating point number (the
+    fraction of a new window with respect to the height of the
+    frame's root window) or a function to be called with one
+    argument - a new window.  The function is supposed to adjust
+    the height of the window; its return value is ignored.
+    Suitable functions are `shrink-window-if-larger-than-buffer'
+    and `fit-window-to-buffer'.
+
+ `window-width' -- Value specifies either an integer (the number
+    of columns of a new window), a floating point number (the
+    fraction of a new window with respect to the width of the
+    frame's root window) or a function to be called with one
+    argument - a new window.  The function is supposed to adjust
+    the width of the window; its return value is ignored.
+
 The ACTION argument to `display-buffer' can also have a non-nil
 and non-list value.  This means to display the buffer in a window
 other than the selected one, even if it is already displayed in
 the selected window.  If called interactively with a prefix
-argument, ACTION is t.
-
-Optional argument FRAME, if non-nil, acts like an additional
-ALIST entry (reusable-frames . FRAME), specifying the frame(s) to
-search for a window that is already displaying the buffer.  See
-`display-buffer-reuse-window'."
+argument, ACTION is t."
   (interactive (list (read-buffer "Display buffer: " (other-buffer))
                     (if current-prefix-arg t)))
   (let ((buffer (if (bufferp buffer-or-name)
@@ -5327,8 +5457,8 @@ search for a window that is already displaying the buffer.  See
        (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
@@ -5373,7 +5503,7 @@ selected window."
   (unless (or (cdr (assq 'inhibit-same-window alist))
              (window-minibuffer-p)
              (window-dedicated-p))
-    (window--display-buffer buffer (selected-window) 'reuse)))
+    (window--display-buffer buffer (selected-window) 'reuse alist)))
 
 (defun display-buffer--maybe-same-window (buffer alist)
   "Conditionally display BUFFER in the selected window.
@@ -5421,7 +5551,7 @@ that frame."
                              (get-buffer-window-list buffer 'nomini
                                                      frames))))))
     (when (window-live-p window)
-      (prog1 (window--display-buffer buffer window 'reuse)
+      (prog1 (window--display-buffer buffer window 'reuse alist)
        (unless (cdr (assq 'inhibit-switch-frame alist))
          (window--maybe-raise-frame (window-frame window)))))))
 
@@ -5458,8 +5588,8 @@ new frame."
     (when (and fun
               (setq frame (funcall fun))
               (setq window (frame-selected-window frame)))
-      (prog1 (window--display-buffer buffer window
-                                    'frame display-buffer-mark-dedicated)
+      (prog1 (window--display-buffer
+             buffer window 'frame alist display-buffer-mark-dedicated)
        (unless (cdr (assq 'inhibit-switch-frame alist))
          (window--maybe-raise-frame frame))))))
 
@@ -5484,11 +5614,11 @@ raising the frame."
                        (not (frame-parameter frame 'unsplittable))))
               ;; Attempt to split largest or least recently used window.
               (setq window (or (window--try-to-split-window
-                                (get-largest-window frame t))
+                                (get-largest-window frame t) alist)
                                (window--try-to-split-window
-                                (get-lru-window frame t)))))
-      (prog1 (window--display-buffer buffer window
-                                    'window display-buffer-mark-dedicated)
+                                (get-lru-window frame t) alist))))
+      (prog1 (window--display-buffer
+             buffer window 'window alist display-buffer-mark-dedicated)
        (unless (cdr (assq 'inhibit-switch-frame alist))
          (window--maybe-raise-frame (window-frame window)))))))
 
@@ -5507,19 +5637,98 @@ again with `display-buffer-pop-up-window'."
       (and pop-up-windows
           (display-buffer-pop-up-window buffer alist))))
 
-(defun display-buffer-below-selected (buffer _alist)
+(defun display-buffer-below-selected (buffer alist)
   "Try displaying BUFFER in a window below the selected window.
 This either splits the selected window or reuses the window below
 the selected one."
   (let (window)
     (or (and (not (frame-parameter nil 'unsplittable))
-            (setq window (window--try-to-split-window (selected-window)))
+            (setq window (window--try-to-split-window (selected-window) alist))
             (window--display-buffer
-             buffer window 'window display-buffer-mark-dedicated))
+             buffer window 'window alist display-buffer-mark-dedicated))
        (and (setq window (window-in-direction 'below))
             (not (window-dedicated-p window))
             (window--display-buffer
-             buffer window 'reuse display-buffer-mark-dedicated)))))
+             buffer window 'reuse alist display-buffer-mark-dedicated)))))
+
+(defun display-buffer-at-bottom (buffer alist)
+  "Try displaying BUFFER in a window at the bottom of the selected frame.
+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)))
+    (or (and (not (frame-parameter nil 'unsplittable))
+            (setq window (window--try-to-split-window bottom-window alist))
+            (window--display-buffer
+             buffer window 'window alist display-buffer-mark-dedicated))
+       (and (not (frame-parameter nil 'unsplittable))
+            (setq window
+                  (condition-case nil
+                      (split-window (frame-root-window))
+                    (error nil)))
+            (window--display-buffer
+             buffer window 'window alist display-buffer-mark-dedicated))
+       (and (setq window bottom-window)
+            (not (window-dedicated-p window))
+            (window--display-buffer
+             buffer window 'reuse alist display-buffer-mark-dedicated)))))
+
+(defun display-buffer-in-previous-window (buffer alist)
+  "Display BUFFER in a window previously showing it.
+If ALIST has a non-nil `inhibit-same-window' entry, the selected
+window is not eligible for reuse.
+
+If ALIST contains a `reusable-frames' entry, its value determines
+which frames to search for a reusable window:
+  nil -- the selected frame (actually the last non-minibuffer frame)
+  A frame   -- just that frame
+  `visible' -- all visible frames
+  0   -- all frames on the current terminal
+  t   -- all frames.
+
+If ALIST contains no `reusable-frames' entry, search just the
+selected frame if `display-buffer-reuse-frames' and
+`pop-up-frames' are both nil; search all frames on the current
+terminal if either of those variables is non-nil.
+
+If ALIST has a `previous-window' entry, the window specified by
+that entry will override any other window found by the methods
+above, even if that window never showed BUFFER before."
+  (let* ((alist-entry (assq 'reusable-frames alist))
+        (inhibit-same-window
+         (cdr (assq 'inhibit-same-window alist)))
+        (frames (cond
+                 (alist-entry (cdr alist-entry))
+                 ((if (eq pop-up-frames 'graphic-only)
+                      (display-graphic-p)
+                    pop-up-frames)
+                  0)
+                 (display-buffer-reuse-frames 0)
+                 (t (last-nonminibuffer-frame))))
+        entry 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))
+       (when (and (assq buffer (window-prev-buffers window))
+                  (not (window-dedicated-p window)))
+         (if (eq window (selected-window))
+             (unless inhibit-same-window
+               (setq second-best-window window))
+           (setq best-window window)
+           (throw 'best t)))))
+    ;; When ALIST has a `previous-window' entry, that entry may override
+    ;; anything we found so far.
+    (when (and (setq window (cdr (assq 'previous-window alist)))
+              (window-live-p window)
+              (not (window-dedicated-p window)))
+      (if (eq window (selected-window))
+         (unless inhibit-same-window
+           (setq second-best-window window))
+       (setq best-window window)))
+    ;; Return best or second best window found.
+    (when (setq window (or best-window second-best-window))
+      (window--display-buffer buffer window 'reuse alist))))
 
 (defun display-buffer-use-some-window (buffer alist)
   "Display BUFFER in an existing window.
@@ -5547,7 +5756,7 @@ that frame."
              (get-largest-window 0 not-this-window))))
     (when (window-live-p window)
       (prog1
-         (window--display-buffer buffer window 'reuse)
+         (window--display-buffer buffer window 'reuse alist)
        (window--even-window-heights window)
        (unless (cdr (assq 'inhibit-switch-frame alist))
          (window--maybe-raise-frame (window-frame window)))))))
@@ -5640,28 +5849,59 @@ buffer with the name BUFFER-OR-NAME and return that buffer."
            buffer))
     (other-buffer)))
 
+(defcustom switch-to-buffer-preserve-window-point nil
+  "If non-nil, `switch-to-buffer' tries to preserve `window-point'.
+If this is nil, `switch-to-buffer' displays the buffer at that
+buffer's `point'.  If this is `already-displayed', it tries to
+display the buffer at its previous position in the selected
+window, provided the buffer is currently displayed in some other
+window on any visible or iconified frame.  If this is t, it
+unconditionally tries to display the buffer at its previous
+position in the selected window.
+
+This variable is ignored if the buffer is already displayed in
+the selected window or never appeared in it before, or if
+`switch-to-buffer' calls `pop-to-buffer' to display the buffer."
+  :type '(choice
+         (const :tag "Never" nil)
+         (const :tag "If already displayed elsewhere" already-displayed)
+         (const :tag "Always" t))
+  :group 'windows
+  :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.
-If called interactively, prompt for the buffer name using the
+  "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
+another window.
+
+If called interactively, read 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'.
+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.
+If optional argument NORECORD is non-nil, do not put the buffer
+at the front of the buffer list, and do not make the window
+displaying it the most recently selected one.
 
-If FORCE-SAME-WINDOW is non-nil, BUFFER-OR-NAME must be displayed
-in the selected window; signal an error if that is
-impossible (e.g. if the selected window is minibuffer-only).  If
-nil, BUFFER-OR-NAME may be displayed in another window.
+If optional argument FORCE-SAME-WINDOW is non-nil, the buffer
+must be displayed in the selected window; if that is impossible,
+signal an error rather than calling `pop-to-buffer'.
+
+The option `switch-to-buffer-preserve-window-point' can be used
+to make the buffer appear at its last position in the selected
+window.
 
 Return the buffer switched to."
   (interactive
@@ -5679,7 +5919,19 @@ Return the buffer switched to."
       (if force-same-window
           (user-error "Cannot switch buffers in a dedicated window")
         (pop-to-buffer buffer norecord)))
-     (t (set-window-buffer nil buffer)))
+     (t
+      (let* ((entry (assq buffer (window-prev-buffers)))
+            (displayed (and (eq switch-to-buffer-preserve-window-point
+                                'already-displayed)
+                            (get-buffer-window buffer 0))))
+       (set-window-buffer nil buffer)
+       (when (and entry
+                  (or (eq switch-to-buffer-preserve-window-point t)
+                      displayed))
+         ;; Try to restore start and point of buffer in the selected
+         ;; window (Bug#4041).
+         (set-window-start (selected-window) (nth 1 entry) t)
+         (set-window-point nil (nth 2 entry))))))
 
     (unless norecord
       (select-window (selected-window)))
@@ -5815,6 +6067,101 @@ WINDOW must be a live window and defaults to the selected one."
                             window))))
 
 ;;; Resizing buffers to fit their contents exactly.
+(defcustom fit-frame-to-buffer nil
+  "Non-nil means `fit-window-to-buffer' can resize frames.
+A frame can be resized if and only if its root window is a live
+window.  The height of the root window is subject to the values
+of `fit-frame-to-buffer-max-height' and `window-min-height'."
+  :type 'boolean
+  :version "24.3"
+  :group 'help)
+
+(defcustom fit-frame-to-buffer-bottom-margin 4
+  "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)
+
+(defun fit-frame-to-buffer (&optional frame max-height min-height)
+  "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.
+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)
+  (setq frame (window-normalize-frame frame))
+  (let* ((root (frame-root-window frame))
+        (frame-min-height
+         (+ (- (frame-height frame) (window-total-size root))
+            window-min-height))
+        (frame-top (frame-parameter frame 'top))
+        (top (if (consp frame-top)
+                 (funcall (car frame-top) (cadr frame-top))
+               frame-top))
+        (frame-max-height
+         (- (/ (- (x-display-pixel-height frame) top)
+               (frame-char-height frame))
+            fit-frame-to-buffer-bottom-margin))
+        (compensate 0)
+        delta)
+    (when (and (window-live-p root) (not (window-size-fixed-p root)))
+      (with-selected-window root
+       (cond
+        ((not max-height)
+         (setq max-height frame-max-height))
+        ((numberp max-height)
+         (setq max-height (min max-height frame-max-height)))
+        (t
+         (error "%s is an invalid maximum height" max-height)))
+       (cond
+        ((not min-height)
+         (setq min-height frame-min-height))
+        ((numberp min-height)
+         (setq min-height (min min-height frame-min-height)))
+        (t
+         (error "%s is an invalid minimum height" min-height)))
+       ;; When tool-bar-mode is enabled and we have just created a new
+       ;; frame, reserve lines for toolbar resizing.  This is needed
+       ;; because for reasons unknown to me Emacs (1) reserves one line
+       ;; for the toolbar when making the initial frame and toolbars
+       ;; are enabled, and (2) later adds the remaining lines needed.
+       ;; Our code runs IN BETWEEN (1) and (2).  YMMV when you're on a
+       ;; system that behaves differently.
+       (let ((quit-restore (window-parameter root 'quit-restore))
+             (lines (tool-bar-lines-needed frame)))
+         (when (and quit-restore (eq (car quit-restore) 'frame)
+                    (not (zerop lines)))
+           (setq compensate (1- lines))))
+       (message "%s" compensate)
+       (setq delta
+             ;; Always count a final newline - we don't do any
+             ;; post-processing, so let's play safe.
+             (+ (count-screen-lines nil nil t)
+                (- (window-body-size))
+                compensate)))
+      ;; Move away from final newline.
+      (when (and (eobp) (bolp) (not (bobp)))
+       (set-window-point root (line-beginning-position 0)))
+      (set-window-start root (point-min))
+      (set-window-vscroll root 0)
+      (condition-case nil
+         (set-frame-height
+          frame
+          (min (max (+ (frame-height frame) delta)
+                    min-height)
+               max-height))
+       (error (setq delta nil))))
+    delta))
+
 (defun fit-window-to-buffer (&optional window max-height min-height)
   "Adjust height of WINDOW to display its buffer's contents exactly.
 WINDOW must be a live window and defaults to the selected one.
@@ -5826,6 +6173,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.
@@ -5835,9 +6186,12 @@ _all_ lines of its buffer you might not see the first lines when
 WINDOW was scrolled."
   (interactive)
   (setq window (window-normalize-window window t))
-  ;; Can't resize a full height or fixed-size window.
-  (unless (or (window-size-fixed-p window)
-             (window-full-height-p window))
+  (cond
+   ((window-size-fixed-p window))
+   ((window-full-height-p window)
+    (when fit-frame-to-buffer
+      (fit-frame-to-buffer (window-frame window))))
+   (t
     (with-selected-window window
       (let* ((height (window-total-size))
             (min-height
@@ -5853,7 +6207,7 @@ WINDOW was scrolled."
                  ;; Can't get larger than height of frame.
                  (min max-height
                       (window-total-size (frame-root-window window)))
-               ;, Don't delete other windows.
+               ;; Don't delete other windows.
                (+ height (window-max-delta nil nil window))))
             ;; Make `desired-height' the height necessary to show
             ;; all of WINDOW's buffer, constrained by MIN-HEIGHT
@@ -5916,89 +6270,7 @@ WINDOW was scrolled."
                  (window-resize window 1 nil window)
                  (setq desired-height (1+ desired-height)))))
          (error (setq delta nil)))
-       delta))))
-
-(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."
-  :type 'integer
-  :version "24.2"
-  :group 'windows)
-
-(defun fit-frame-to-buffer (&optional frame max-height min-height)
-  "Adjust height of FRAME to display its buffer's 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."
-  (interactive)
-  (setq frame (window-normalize-frame frame))
-  (let* ((root (frame-root-window frame))
-        (frame-min-height
-         (+ (- (frame-height frame) (window-total-size root))
-            window-min-height))
-        (frame-top (frame-parameter frame 'top))
-        (top (if (consp frame-top)
-                 (funcall (car frame-top) (cadr frame-top))
-               frame-top))
-        (frame-max-height
-         (- (/ (- (x-display-pixel-height frame) top)
-               (frame-char-height frame))
-            fit-frame-to-buffer-bottom-margin))
-        (compensate 0)
-        delta)
-    (when (and (window-live-p root) (not (window-size-fixed-p root)))
-      (with-selected-window root
-       (cond
-        ((not max-height)
-         (setq max-height frame-max-height))
-        ((numberp max-height)
-         (setq max-height (min max-height frame-max-height)))
-        (t
-         (error "%s is an invalid maximum height" max-height)))
-       (cond
-        ((not min-height)
-         (setq min-height frame-min-height))
-        ((numberp min-height)
-         (setq min-height (min min-height frame-min-height)))
-        (t
-         (error "%s is an invalid minimum height" min-height)))
-       ;; When tool-bar-mode is enabled and we have just created a new
-       ;; frame, reserve lines for toolbar resizing.  This is needed
-       ;; because for reasons unknown to me Emacs (1) reserves one line
-       ;; for the toolbar when making the initial frame and toolbars
-       ;; are enabled, and (2) later adds the remaining lines needed.
-       ;; Our code runs IN BETWEEN (1) and (2).  YMMV when you're on a
-       ;; system that behaves differently.
-       (let ((quit-restore (window-parameter root 'quit-restore))
-             (lines (tool-bar-lines-needed frame)))
-         (when (and quit-restore (eq (car quit-restore) 'frame)
-                    (not (zerop lines)))
-           (setq compensate (1- lines))))
-       (message "%s" compensate)
-       (setq delta
-             ;; Always count a final newline - we don't do any
-             ;; post-processing, so let's play safe.
-             (+ (count-screen-lines nil nil t)
-                (- (window-body-size))
-                compensate)))
-      ;; Move away from final newline.
-      (when (and (eobp) (bolp) (not (bobp)))
-       (set-window-point root (line-beginning-position 0)))
-      (set-window-start root (point-min))
-      (set-window-vscroll root 0)
-      (condition-case nil
-         (set-frame-height
-          frame
-          (min (max (+ (frame-height frame) delta)
-                    min-height)
-               max-height))
-       (error (setq delta nil))))
-    delta))
+       delta)))))
 
 (defun window-safely-shrinkable-p (&optional window)
   "Return t if WINDOW can be shrunk without shrinking other windows.
@@ -6243,7 +6515,7 @@ This is different from `scroll-down-command' that scrolls a full screen."
 (put 'scroll-down-line 'scroll-command t)
 
 \f
-(defun scroll-other-window-down (lines)
+(defun scroll-other-window-down (&optional lines)
   "Scroll the \"other window\" down.
 For more details, see the documentation for `scroll-other-window'."
   (interactive "P")