Move window resize code from window.c to window.el.
authorMartin Rudalics <rudalics@gmx.at>
Fri, 10 Jun 2011 06:55:18 +0000 (08:55 +0200)
committerMartin Rudalics <rudalics@gmx.at>
Fri, 10 Jun 2011 06:55:18 +0000 (08:55 +0200)
* window.c: Remove declarations of Qwindow_size_fixed,
window_min_size_1, window_min_size_2, window_min_size,
size_window, window_fixed_size_p, enlarge_window, delete_window.
Remove static from declaration of Qdelete_window, it's
temporarily needed by Fbury_buffer.
(replace_window): Don't assign orig_top_line and
orig_total_lines.
(Fdelete_window, delete_window): Remove.  Window deletion is
handled by window.el.
(window_loop): Remove DELETE_OTHER_WINDOWS case.  Replace
Fdelete_window calls with calls to Qdelete_window.
(Fdelete_other_windows): Remove.  Deleting other windows is
handled by window.el.
(window_fixed_size_p): Remove.  Fixed-sizeness of windows is
handled in window.el.
(window_min_size_2, window_min_size_1, window_min_size): Remove.
Window minimum sizes are handled in window.el.
(shrink_windows, size_window, set_window_height)
(set_window_width, change_window_heights, window_height)
(window_width, CURBEG, CURSIZE, enlarge_window)
(adjust_window_trailing_edge, Fadjust_window_trailing_edge)
(Fenlarge_window, Fshrink_window): Remove.  Window resizing is
handled in window.el.
(make_dummy_parent): Rename to make_parent_window and give it a
second argument horflag.
(make_window): Don't set resize_proportionally any more.
(Fsplit_window): Remove.  Windows are split in window.el.
(save_restore_action, save_restore_orig_size)
(shrink_window_lowest_first, save_restore_orig_size): Remove.
Resize mini windows in window.el.
(grow_mini_window, shrink_mini_window): Implement by calling
Qresize_root_window_vertically, resize_window_check and
resize_window_apply.
(saved_window, Fset_window_configuration, save_window_save): Do
not handle orig_top_line, orig_total_lines, and
resize_proportionally.
(window_min_height, window_min_width): Move to window.el.
(keys_of_window): Move bindings for delete-other-windows,
split-window, delete-window and enlarge-window to window.el.

* buffer.c: Temporarily extern Qdelete_window.
(Fbury_buffer): Temporarily call Qdelete_window instead of
Fdelete_window (Fbury_buffer will move to window.el soon).

* frame.c (set_menu_bar_lines_1): Remove code handling
orig_top_line and orig_total_lines.

* dispnew.c (adjust_frame_glyphs_initially): Don't use
set_window_height but set heights directly.
(change_frame_size_1): Use resize_frame_windows.

* xdisp.c (init_xdisp): Don't use set_window_height but set
heights directly.

* xfns.c (x_set_menu_bar_lines, x_set_tool_bar_lines): Use
resize_frame_windows instead of change_window_heights and run
run_window_configuration_change_hook.

* w32fns.c (x_set_tool_bar_lines): Use resize_frame_windows
instead of change_window_heights and run
run_window_configuration_change_hook.

* window.el (window-min-height, window-min-width): Move here
from window.c.  Add defcustoms and rewrite doc-strings.
(resize-mini-window, resize-window): New functions.
(adjust-window-trailing-edge, enlarge-window, shrink-window):
Move here from window.c.
(maximize-window, minimize-window): New functions.
(delete-window, delete-other-windows, split-window): Move here
from window.c.
(window-split-min-size): New function.
(split-window-keep-point): Mention split-window-above-each-other
instead of split-window-vertically.
(split-window-above-each-other, split-window-vertically): Rename
split-window-vertically to split-window-above-each-other and
provide defalias for old definition.
(split-window-side-by-side, split-window-horizontally): Rename
split-window-horizontally to split-window-side-by-side and provide
defalias for the old definition.
(ctl-x-map): Move bindings for delete-window,
delete-other-windows and enlarge-window here from window.c.
Replace bindings for split-window-vertically and
split-window-horizontally by bindings for
split-window-above-each-other and split-window-side-by-side.

* cus-start.el (all): Remove entries for window-min-height and
window-min-width.  Add entries for window-splits and
window-nest.

lisp/ChangeLog
lisp/cus-start.el
lisp/window.el
src/ChangeLog
src/buffer.c
src/dispnew.c
src/frame.c
src/w32fns.c
src/window.c
src/xdisp.c
src/xfns.c

index ae1da48..1ac216d 100644 (file)
@@ -1,3 +1,32 @@
+2011-06-10  Martin Rudalics  <rudalics@gmx.at>
+
+       * window.el (window-min-height, window-min-width): Move here
+       from window.c.  Add defcustoms and rewrite doc-strings.
+       (resize-mini-window, resize-window): New functions.
+       (adjust-window-trailing-edge, enlarge-window, shrink-window):
+       Move here from window.c.
+       (maximize-window, minimize-window): New functions.
+       (delete-window, delete-other-windows, split-window): Move here
+       from window.c.
+       (window-split-min-size): New function.
+       (split-window-keep-point): Mention split-window-above-each-other
+       instead of split-window-vertically.
+       (split-window-above-each-other, split-window-vertically): Rename
+       split-window-vertically to split-window-above-each-other and
+       provide defalias for old definition.
+       (split-window-side-by-side, split-window-horizontally): Rename
+       split-window-horizontally to split-window-side-by-side and provide
+       defalias for the old definition.
+       (ctl-x-map): Move bindings for delete-window,
+       delete-other-windows and enlarge-window here from window.c.
+       Replace bindings for split-window-vertically and
+       split-window-horizontally by bindings for
+       split-window-above-each-other and split-window-side-by-side.
+
+       * cus-start.el (all): Remove entries for window-min-height and
+       window-min-width.  Add entries for window-splits and
+       window-nest.
+
 2011-06-09  Glenn Morris  <rgm@gnu.org>
 
        * calendar/appt.el (appt-mode-line): New function.
index 6113a43..389716b 100644 (file)
@@ -388,19 +388,18 @@ since it could result in memory overflow and make Emacs crash."
             ;; window.c
             (temp-buffer-show-function windows (choice (const nil) function))
             (next-screen-context-lines windows integer)
-            (window-min-height windows integer)
-            (window-min-width windows integer)
             (scroll-preserve-screen-position
              windows (choice
                       (const :tag "Off (nil)" :value nil)
                       (const :tag "Full screen (t)" :value t)
                       (other :tag "Always" 1)) "22.1")
-            (recenter-redisplay windows
-                                (choice
-                                 (const :tag "Never (nil)" :value nil)
-                                 (const :tag "Only on ttys" :value tty)
-                                 (other :tag "Always" t))
-                                "23.1")
+            (recenter-redisplay
+             windows (choice
+                      (const :tag "Never (nil)" :value nil)
+                      (const :tag "Only on ttys" :value tty)
+                      (other :tag "Always" t)) "23.1")
+            (window-splits windows boolean "24.1")
+            (window-nest windows boolean "24.1")
             ;; xdisp.c
             (show-trailing-whitespace whitespace-faces boolean nil
                                       :safe booleanp)
index 566577c..a88e56b 100644 (file)
@@ -161,10 +161,41 @@ these functions to inhibit processing of window parameters.")
   "The absolut minimum number of lines of a window.
 Anything less might crash Emacs.")
 
+(defcustom window-min-height 4
+  "The minimum number of lines of any window.
+The value has to accomodate a mode- or header-line if present.  A
+value less than `window-safe-min-height' is ignored.  The value
+of this variable is honored when windows are resized or split.
+
+Applications should never rebind this variable.  To resize a
+window to a height less than the one specified here, an
+application should instead call `resize-window' with a non-nil
+IGNORE argument.  In order to have `split-window' make a window
+shorter, explictly specify the SIZE argument of that function."
+  :type 'integer
+  :version "24.1"
+  :group 'windows)
+
 (defconst window-safe-min-width 2
   "The absolut minimum number of columns of a window.
 Anything less might crash Emacs.")
 
+(defcustom window-min-width 10
+  "The minimum number of columns of any window.
+The value has to accomodate margins, fringes, or scrollbars if
+present.  A value less than `window-safe-min-width' is ignored.
+The value of this variable is honored when windows are resized or
+split.
+
+Applications should never rebind this variable.  To resize a
+window to a width less than the one specified here, an
+application should instead call `resize-window' with a non-nil
+IGNORE argument.  In order to have `split-window' make a window
+narrower, explictly specify the SIZE argument of that function."
+  :type 'integer
+  :version "24.1"
+  :group 'windows)
+
 (defun window-iso-combination-p (&optional window horizontal)
   "If WINDOW is a vertical combination return WINDOW's first child.
 WINDOW can be any window and defaults to the selected one.
@@ -1336,6 +1367,97 @@ windows."
   (when (window-right window)
     (resize-window-reset-1 (window-right window) horizontal)))
 
+;; The following routine is used to manually resize the minibuffer
+;; window and is currently used, for example, by ispell.el.
+(defun resize-mini-window (window delta)
+  "Resize minibuffer window WINDOW by DELTA lines.
+If WINDOW cannot be resized by DELTA lines make it as large \(or
+as small) as possible but don't signal an error."
+  (when (window-minibuffer-p window)
+    (let* ((frame (window-frame window))
+          (root (frame-root-window frame))
+          (height (window-total-size window))
+          (min-delta
+           (- (window-total-size root)
+              (window-min-size root))))
+      ;; Sanitize DELTA.
+      (cond
+       ((<= (+ height delta) 0)
+       (setq delta (- (- height 1))))
+       ((> delta min-delta)
+       (setq delta min-delta)))
+
+      ;; Resize now.
+      (resize-window-reset frame)
+      ;; Ideally we should be able to resize just the last subwindow of
+      ;; root here.  See the comment in `resize-root-window-vertically'
+      ;; for why we do not do that.
+      (resize-this-window root (- delta) nil nil t)
+      (set-window-new-total window (+ height delta))
+      ;; The following routine catches the case where we want to resize
+      ;; a minibuffer-only frame.
+      (resize-mini-window-internal window))))
+
+(defun resize-window (window delta &optional horizontal ignore)
+  "Resize WINDOW vertically by DELTA lines.
+WINDOW can be an arbitrary window and defaults to the selected
+one.  An attempt to resize the root window of a frame will raise
+an error though.
+
+DELTA a positive number means WINDOW shall be enlarged by DELTA
+lines.  DELTA negative means WINDOW shall be shrunk by -DELTA
+lines.
+
+Optional argument HORIZONTAL non-nil means resize WINDOW
+horizontally by DELTA columns.  In this case a positive DELTA
+means enlarge WINDOW by DELTA columns.  DELTA negative means
+WINDOW shall be shrunk by -DELTA columns.
+
+Optional argument IGNORE non-nil means ignore any restrictions
+imposed by fixed size windows, `window-min-height' or
+`window-min-width' settings.  IGNORE any window means ignore
+restrictions for that window only.  IGNORE equal `safe' means
+live windows may get as small as `window-safe-min-height' lines
+and `window-safe-min-width' columns.
+
+This function resizes other windows proportionally and never
+deletes any windows.  If you want to move only the low (right)
+edge of WINDOW consider using `adjust-window-trailing-edge'
+instead."
+  (setq window (normalize-any-window window))
+  (let* ((frame (window-frame window))
+        sibling)
+    (cond
+     ((eq window (frame-root-window frame))
+      (error "Cannot resize the root window of a frame"))
+     ((window-minibuffer-p window)
+      (resize-mini-window window delta))
+     ((window-resizable-p window delta horizontal ignore)
+      (resize-window-reset frame horizontal)
+      (resize-this-window window delta horizontal ignore t)
+      (if (and (not (window-splits window))
+              (window-iso-combined-p window horizontal)
+              (setq sibling (or (window-right window) (window-left window)))
+              (window-sizable-p sibling (- delta) horizontal ignore))
+         ;; If window-splits returns nil for WINDOW, WINDOW is part of
+         ;; an iso-combination, and WINDOW's neighboring right or left
+         ;; sibling can be resized as requested, resize that sibling.
+         (let ((normal-delta
+                (/ (float delta)
+                   (window-total-size (window-parent window) horizontal))))
+           (resize-this-window sibling (- delta) horizontal nil t)
+           (set-window-new-normal
+            window (+ (window-normal-size window horizontal)
+                      normal-delta))
+           (set-window-new-normal
+            sibling (- (window-normal-size sibling horizontal)
+                       normal-delta)))
+       ;; Otherwise, resize all other windows in the same combination.
+       (resize-other-windows window delta horizontal ignore))
+      (resize-window-apply frame horizontal))
+     (t
+      (error "Cannot resize window %s" window)))))
+
 (defsubst resize-subwindows-skip-p (window)
   "Return non-nil if WINDOW shall be skipped by resizing routines."
   (memq (window-new-normal window) '(ignore stuck skip)))
@@ -1805,6 +1927,153 @@ any windows."
       (resize-this-window window delta nil ignore t)
       delta)))
 
+(defun adjust-window-trailing-edge (window delta &optional horizontal)
+  "Move WINDOW's bottom edge by DELTA lines.
+Optional argument HORIZONTAL non-nil means move WINDOW's right
+edge by DELTA columns.  WINDOW defaults to the selected window.
+
+If DELTA is greater zero, then move the edge downwards or to the
+right.  If DELTA is less than zero, move the edge upwards or to
+the left.  If the edge can't be moved by DELTA lines or columns,
+move it as far as possible in the desired direction."
+  (setq window (normalize-any-window window))
+  (let ((frame (window-frame window))
+       (right window)
+       left this-delta min-delta max-delta failed)
+    ;; Find the edge we want to move.
+    (while (and (or (not (window-iso-combined-p right horizontal))
+                   (not (window-right right)))
+               (setq right (window-parent right))))
+    (cond
+     ((and (not right) (not horizontal) (not resize-mini-windows)
+          (eq (window-frame (minibuffer-window frame)) frame))
+      (resize-mini-window (minibuffer-window frame) (- delta)))
+     ((or (not (setq left right)) (not (setq right (window-right right))))
+      (if horizontal
+         (error "No window on the right of this one")
+       (error "No window below this one")))
+     (t
+      ;; Set LEFT to the first resizable window on the left.  This step is
+      ;; needed to handle fixed-size windows.
+      (while (and left (window-size-fixed-p left horizontal))
+       (setq left
+             (or (window-left left)
+                 (progn
+                   (while (and (setq left (window-parent left))
+                               (not (window-iso-combined-p left horizontal))))
+                   (window-left left)))))
+      (unless left
+       (if horizontal
+           (error "No resizable window on the left of this one")
+         (error "No resizable window above this one")))
+
+      ;; Set RIGHT to the first resizable window on the right.  This step
+      ;; is needed to handle fixed-size windows.
+      (while (and right (window-size-fixed-p right horizontal))
+       (setq right
+             (or (window-right right)
+                 (progn
+                   (while (and (setq right (window-parent right))
+                               (not (window-iso-combined-p right horizontal))))
+                   (window-right right)))))
+      (unless right
+       (if horizontal
+           (error "No resizable window on the right of this one")
+         (error "No resizable window below this one")))
+
+      ;; LEFT and RIGHT (which might be both internal windows) are now the
+      ;; two windows we want to resize.
+      (cond
+       ((> delta 0)
+       (setq max-delta (window-max-delta-1 left 0 horizontal nil 'after))
+       (setq min-delta (window-min-delta-1 right (- delta) horizontal nil 'before))
+       (when (or (< max-delta delta) (> min-delta (- delta)))
+         ;; We can't get the whole DELTA - move as far as possible.
+         (setq delta (min max-delta (- min-delta))))
+       (unless (zerop delta)
+         ;; Start resizing.
+         (resize-window-reset frame horizontal)
+         ;; Try to enlarge LEFT first.
+         (setq this-delta (window-resizable left delta horizontal))
+         (unless (zerop this-delta)
+           (resize-this-window
+            left this-delta horizontal nil t 'before
+            (if horizontal
+                (+ (window-left-column left) (window-total-size left t))
+              (+ (window-top-line left) (window-total-size left)))))
+         ;; Shrink windows on right of LEFT.
+         (resize-other-windows
+          left delta horizontal nil 'after
+          (if horizontal
+              (window-left-column right)
+            (window-top-line right)))))
+       ((< delta 0)
+       (setq max-delta (window-max-delta-1 right 0 horizontal nil 'before))
+       (setq min-delta (window-min-delta-1 left delta horizontal nil 'after))
+       (when (or (< max-delta (- delta)) (> min-delta delta))
+         ;; We can't get the whole DELTA - move as far as possible.
+         (setq delta (max (- max-delta) min-delta)))
+       (unless (zerop delta)
+         ;; Start resizing.
+         (resize-window-reset frame horizontal)
+         ;; Try to enlarge RIGHT.
+         (setq this-delta (window-resizable right (- delta) horizontal))
+         (unless (zerop this-delta)
+           (resize-this-window
+            right this-delta horizontal nil t 'after
+            (if horizontal
+                (window-left-column right)
+              (window-top-line right))))
+         ;; Shrink windows on left of RIGHT.
+         (resize-other-windows
+          right (- delta) horizontal nil 'before
+          (if horizontal
+              (+ (window-left-column left) (window-total-size left t))
+            (+ (window-top-line left) (window-total-size left)))))))
+      (unless (zerop delta)
+       ;; Don't report an error in the standard case.
+       (unless (resize-window-apply frame horizontal)
+         ;; But do report an error if applying the changes fails.
+         (error "Failed adjusting window %s" window)))))))
+
+(defun enlarge-window (delta &optional horizontal)
+  "Make selected window DELTA lines taller.
+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."
+  (interactive "p")
+  (resize-window (selected-window) delta horizontal))
+
+(defun shrink-window (delta &optional horizontal)
+  "Make selected window DELTA lines smaller.
+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.
+Return nil."
+  (interactive "p")
+  (resize-window (selected-window) (- delta) horizontal))
+
+(defun maximize-window (&optional window)
+  "Maximize WINDOW.
+Make WINDOW as large as possible without deleting any windows.
+WINDOW can be any window and defaults to the selected window."
+  (interactive)
+  (setq window (normalize-any-window window))
+  (resize-window window (window-max-delta window))
+  (resize-window window (window-max-delta window t) t))
+
+(defun minimize-window (&optional window)
+  "Minimize WINDOW.
+Make WINDOW as small as possible without deleting any windows.
+WINDOW can be any window and defaults to the selected window."
+  (interactive)
+  (setq window (normalize-any-window window))
+  (resize-window window (- (window-min-delta window)))
+  (resize-window window (- (window-min-delta window t)) t))
+\f
 (defsubst frame-root-window-p (window)
   "Return non-nil if WINDOW is the root window of its frame."
   (eq window (frame-root-window window)))
@@ -1886,6 +2155,458 @@ instead."
                (throw 'done t)
              (setq parent (window-parent parent))))))))
 
+(defun delete-window (&optional window)
+  "Delete WINDOW.
+WINDOW can be an arbitrary window and defaults to the selected
+one.  Return nil.
+
+If the variable `ignore-window-parameters' is non-nil or the
+`delete-window' parameter of WINDOW equals t, do not process any
+parameters of WINDOW.  Otherwise, if the `delete-window'
+parameter of WINDOW specifies a function, call that function with
+WINDOW as its sole argument and return the value returned by that
+function.
+
+Otherwise, if WINDOW is part of an atomic window, call
+`delete-window' with the root of the atomic window as its
+argument.  If WINDOW is the only window on its frame or the last
+non-side window, signal an error."
+  (interactive)
+  (setq window (normalize-any-window window))
+  (let* ((frame (window-frame window))
+        (function (window-parameter window 'delete-window))
+        (parent (window-parent window))
+        atom-root)
+    (window-check frame)
+    (catch 'done
+      ;; Handle window parameters.
+      (cond
+       ;; Ignore window parameters if `ignore-window-parameters' tells
+       ;; us so or `delete-window' equals t.
+       ((or ignore-window-parameters (eq function t)))
+       ((functionp function)
+       ;; The `delete-window' parameter specifies the function to call.
+       ;; If that function is `ignore' nothing is done.  It's up to the
+       ;; function called here to avoid infinite recursion.
+       (throw 'done (funcall function window)))
+       ((and (window-parameter window 'window-atom)
+            (setq atom-root (window-atom-root window))
+            (not (eq atom-root window)))
+       (throw 'done (delete-window atom-root)))
+       ((and (eq (window-parameter window 'window-side) 'none)
+            (or (not parent)
+                (not (eq (window-parameter parent 'window-side) 'none))))
+       (error "Attempt to delete last non-side window"))
+       ((not parent)
+       (error "Attempt to delete minibuffer or sole ordinary window")))
+
+      (let* ((horizontal (window-hchild parent))
+            (size (window-total-size window horizontal))
+            (frame-selected
+             (window-or-subwindow-p (frame-selected-window frame) window))
+            ;; Emacs 23 preferably gives WINDOW's space to its left
+            ;; sibling.
+            (sibling (or (window-left window) (window-right window))))
+       (resize-window-reset frame horizontal)
+       (cond
+        ((and (not (window-splits window))
+              sibling (window-sizable-p sibling size))
+         ;; Resize WINDOW's sibling.
+         (resize-this-window sibling size horizontal nil t)
+         (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)
+         ;; Can do without resizing fixed-size windows.
+         (resize-other-windows window (- size) horizontal))
+        (t
+         ;; Can't do without resizing fixed-size windows.
+         (resize-other-windows window (- size) horizontal t)))
+       ;; Actually delete WINDOW.
+       (delete-window-internal window)
+       (when (and frame-selected
+                  (window-parameter
+                   (frame-selected-window frame) 'no-other-window))
+         ;; `delete-window-internal' has selected a window that should
+         ;; not be selected, fix this here.
+         (other-window -1 frame))
+       (run-window-configuration-change-hook frame)
+       (window-check frame)
+       ;; Always return nil.
+       nil))))
+
+(defun delete-other-windows (&optional window)
+  "Make WINDOW fill its frame.
+WINDOW may be any window and defaults to the selected one.
+Return nil.
+
+If the variable `ignore-window-parameters' is non-nil or the
+`delete-other-windows' parameter of WINDOW equals t, do not
+process any parameters of WINDOW.  Otherwise, if the
+`delete-other-windows' parameter of WINDOW specifies a function,
+call that function with WINDOW as its sole argument and return
+the value returned by that function.
+
+Otherwise, if WINDOW is part of an atomic window, call this
+function with the root of the atomic window as its argument.  If
+WINDOW is a non-side window, make WINDOW the only non-side window
+on the frame.  Side windows are not deleted. If WINDOW is a side
+window signal an error."
+  (interactive)
+  (setq window (normalize-any-window window))
+  (let* ((frame (window-frame window))
+        (function (window-parameter window 'delete-other-windows))
+        (window-side (window-parameter window 'window-side))
+        atom-root side-main)
+    (window-check frame)
+    (catch 'done
+      (cond
+       ;; Ignore window parameters if `ignore-window-parameters' is t or
+       ;; `delete-other-windows' is t.
+       ((or ignore-window-parameters (eq function t)))
+       ((functionp function)
+       ;; The `delete-other-windows' parameter specifies the function
+       ;; to call.  If the function is `ignore' no windows are deleted.
+       ;; It's up to the function called to avoid infinite recursion.
+       (throw 'done (funcall function window)))
+       ((and (window-parameter window 'window-atom)
+            (setq atom-root (window-atom-root window))
+            (not (eq atom-root window)))
+       (throw 'done (delete-other-windows atom-root)))
+       ((eq window-side 'none)
+       ;; Set side-main to the major non-side window.
+       (setq side-main (window-with-parameter 'window-side 'none nil t)))
+       ((memq window-side window-sides)
+       (error "Cannot make side window the only window")))
+      ;; If WINDOW is the main non-side window, do nothing.
+      (unless (eq window side-main)
+       (delete-other-windows-internal window side-main)
+       (run-window-configuration-change-hook frame)
+       (window-check frame))
+      ;; Always return nil.
+      nil)))
+\f
+;;; Splitting windows.
+(defsubst window-split-min-size (&optional horizontal)
+  "Return minimum height of any window when splitting windows.
+Optional argument HORIZONTAL non-nil means return minimum width."
+  (if horizontal
+      (max window-min-width window-safe-min-width)
+    (max window-min-height window-safe-min-height)))
+
+(defun split-window (&optional window size side)
+  "Make a new window adjacent to WINDOW.
+WINDOW can be any window and defaults to the selected one.
+Return the new window which is always a live window.
+
+Optional argument SIZE a positive number means make WINDOW SIZE
+lines or columns tall.  If SIZE is negative, make the new window
+-SIZE lines or columns tall.  If and only if SIZE is non-nil, its
+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.
+
+Optional third argument SIDE nil (or `below') specifies that the
+new window shall be located below WINDOW.  SIDE `above' means the
+new window shall be located above WINDOW.  In both cases SIZE
+specifies the new number of lines for WINDOW \(or the new window
+if SIZE is negative) including space reserved for the mode and/or
+header line.
+
+SIDE t (or `right') specifies that the new window shall be
+located on the right side of WINDOW.  SIDE `left' means the new
+window shall be located on the left of WINDOW.  In both cases
+SIZE specifies the new number of columns for WINDOW \(or the new
+window provided SIZE is negative) including space reserved for
+fringes and the scrollbar or a divider column.  Any other non-nil
+value for SIDE is currently handled like t (or `right').
+
+If the variable `ignore-window-parameters' is non-nil or the
+`split-window' parameter of WINDOW equals t, do not process any
+parameters of WINDOW.  Otherwise, if the `split-window' parameter
+of WINDOW specifies a function, call that function with all three
+arguments and return the value returned by that function.
+
+Otherwise, if WINDOW is part of an atomic window, \"split\" the
+root of that atomic window.  The new window does not become a
+member of that atomic window.
+
+If WINDOW is live, properties of the new window like margins and
+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 (normalize-any-window window))
+  (let* ((horizontal (not (memq side '(nil below above))))
+        (frame (window-frame window))
+        (parent (window-parent window))
+        (function (window-parameter window 'split-window))
+        (window-side (window-parameter window 'window-side))
+        ;; Rebind `window-nest' since in some cases we may have to
+        ;; override its value.
+        (window-nest window-nest)
+        atom-root)
+
+    (window-check frame)
+    (catch 'done
+      (cond
+       ;; Ignore window parameters if either `ignore-window-parameters'
+       ;; is t or the `split-window' parameter equals t.
+       ((or ignore-window-parameters (eq function t)))
+       ((functionp function)
+       ;; The `split-window' parameter specifies the function to call.
+       ;; If that function is `ignore', do nothing.
+       (throw 'done (funcall function window size side)))
+       ;; If WINDOW is a subwindow of an atomic window, split the root
+       ;; window of that atomic window instead.
+       ((and (window-parameter window 'window-atom)
+            (setq atom-root (window-atom-root window))
+            (not (eq atom-root window)))
+       (throw 'done (split-window atom-root size side))))
+
+      (when (and window-side
+                (or (not parent)
+                    (not (window-parameter parent 'window-side))))
+       ;; WINDOW is a side root window.  To make sure that a new parent
+       ;; window gets created set `window-nest' to t.
+       (setq window-nest t))
+
+      (when (and window-splits size (> size 0))
+       ;; If `window-splits' is non-nil and SIZE is a non-negative
+       ;; integer, we cannot reasonably resize other windows.  Rather
+       ;; bind `window-nest' to t to make sure that subsequent window
+       ;; deletions are handled correctly.
+       (setq window-nest t))
+
+      (let* ((parent-size
+             ;; `parent-size' is the size of WINDOW's parent, provided
+             ;; it has one.
+             (when parent (window-total-size parent horizontal)))
+            ;; `resize' non-nil means we are supposed to resize other
+            ;; windows in WINDOW's combination.
+            (resize
+             (and window-splits (not window-nest)
+                  ;; Resize makes sense in iso-combinations only.
+                  (window-iso-combined-p window horizontal)))
+            ;; `old-size' is the current size of WINDOW.
+            (old-size (window-total-size window horizontal))
+            ;; `new-size' is the specified or calculated size of the
+            ;; new window.
+            (new-size
+             (cond
+              ((not size)
+               (max (window-split-min-size horizontal)
+                    (if resize
+                        ;; When resizing try to give the new window the
+                        ;; average size of a window in its combination.
+                        (min (- parent-size
+                                (window-min-size parent horizontal))
+                             (/ parent-size
+                                (1+ (window-iso-combinations
+                                     parent horizontal))))
+                      ;; Else try to give the new window half the size
+                      ;; of WINDOW (plus an eventual odd line).
+                      (+ (/ old-size 2) (% old-size 2)))))
+              ((>= size 0)
+               ;; SIZE non-negative specifies the new size of WINDOW.
+
+               ;; Note: Specifying a non-negative SIZE is practically
+               ;; always done as workaround for making the new window
+               ;; appear above or on the left of the new window (the
+               ;; ispell window is a typical example of that).  In all
+               ;; these cases the SIDE argument should be set to 'above
+               ;; or 'left in order to support the 'resize option.
+               ;; Here we have to nest the windows instead, see above.
+               (- old-size size))
+              (t
+               ;; SIZE negative specifies the size of the new window.
+               (- size))))
+            new-parent new-normal)
+
+       ;; Check SIZE.
+       (cond
+        ((not size)
+         (cond
+          (resize
+           ;; SIZE unspecified, resizing.
+           (when (and (not (window-sizable-p parent (- new-size) horizontal))
+                      ;; Try again with minimum split size.
+                      (setq new-size
+                            (max new-size (window-split-min-size horizontal)))
+                      (not (window-sizable-p parent (- new-size) horizontal)))
+             (error "Window %s too small for splitting" parent)))
+          ((> (+ new-size (window-min-size window horizontal)) old-size)
+           ;; SIZE unspecified, no resizing.
+           (error "Window %s too small for splitting" window))))
+        ((and (>= size 0)
+              (or (>= size old-size)
+                  (< new-size (if horizontal
+                                  window-safe-min-width
+                                window-safe-min-width))))
+         ;; SIZE specified as new size of old window.  If the new size
+         ;; is larger than the old size or the size of the new window
+         ;; would be less than the safe minimum, signal an error.
+         (error "Window %s too small for splitting" window))
+        (resize
+         ;; SIZE specified, resizing.
+         (unless (window-sizable-p parent (- new-size) horizontal)
+           ;; If we cannot resize the parent give up.
+           (error "Window %s too small for splitting" parent)))
+        ((or (< new-size
+                (if horizontal window-safe-min-width window-safe-min-height))
+             (< (- old-size new-size)
+                (if horizontal window-safe-min-width window-safe-min-height)))
+         ;; SIZE specification violates minimum size restrictions.
+         (error "Window %s too small for splitting" window)))
+
+       (resize-window-reset frame horizontal)
+
+       (setq new-parent
+             ;; 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-nest (not (window-iso-combined-p window horizontal))))
+       (setq new-normal
+             ;; Make new-normal the normal size of the new window.
+             (cond
+              (size (/ (float new-size) (if new-parent old-size parent-size)))
+              (new-parent 0.5)
+              (resize (/ 1.0 (1+ (window-iso-combinations parent horizontal))))
+              (t (/ (window-normal-size window horizontal) 2.0))))
+
+       (if resize
+           ;; Try to get space from OLD's siblings.  We could go "up" and
+           ;; try getting additional space from surrounding windows but
+           ;; we won't be able to return space to those windows when we
+           ;; delete the one we create here.  Hence we do not go up.
+           (progn
+             (resize-subwindows parent (- new-size) horizontal)
+             (let* ((normal (- 1.0 new-normal))
+                    (sub (window-child parent)))
+               (while sub
+                 (set-window-new-normal
+                  sub (* (window-normal-size sub horizontal) normal))
+                 (setq sub (window-right sub)))))
+         ;; Get entire space from WINDOW.
+         (set-window-new-total window (- old-size new-size))
+         (resize-this-window window (- new-size) horizontal)
+         (set-window-new-normal
+          window (- (if new-parent 1.0 (window-normal-size window horizontal))
+                    new-normal)))
+
+       (let* ((new (split-window-internal window new-size side new-normal)))
+         ;; Inherit window-side parameters, if any.
+         (when (and window-side new-parent)
+           (set-window-parameter (window-parent new) 'window-side window-side)
+           (set-window-parameter new 'window-side window-side))
+
+         (run-window-configuration-change-hook frame)
+         (window-check frame)
+         ;; Always return the new window.
+         new)))))
+
+;; I think this should be the default; I think people will prefer it--rms.
+(defcustom split-window-keep-point t
+  "If non-nil, \\[split-window-above-each-other] keeps the original point \
+in both children.
+This is often more convenient for editing.
+If nil, adjust point in each of the two windows to minimize redisplay.
+This is convenient on slow terminals, but point can move strangely.
+
+This option applies only to `split-window-above-each-other' and
+functions that call it.  `split-window' always keeps the original
+point in both children."
+  :type 'boolean
+  :group 'windows)
+
+(defun split-window-above-each-other (&optional size)
+  "Split selected window into two windows, one above the other.
+The upper window gets SIZE lines and the lower one gets the rest.
+SIZE negative means the lower window gets -SIZE lines and the
+upper one the rest.  With no argument, split windows equally or
+close to it.  Both windows display the same buffer, now current.
+
+If the variable `split-window-keep-point' is non-nil, both new
+windows will get the same value of point as the selected window.
+This is often more convenient for editing.  The upper window is
+the selected window.
+
+Otherwise, we choose window starts so as to minimize the amount of
+redisplay; this is convenient on slow terminals.  The new selected
+window is the one that the current value of point appears in.  The
+value of point can change if the text around point is hidden by the
+new mode line.
+
+Regardless of the value of `split-window-keep-point', the upper
+window is the original one and the return value is the new, lower
+window."
+  (interactive "P")
+  (let ((old-window (selected-window))
+       (old-point (point))
+       (size (and size (prefix-numeric-value size)))
+        moved-by-window-height moved new-window bottom)
+    (when (and size (< size 0) (< (- size) window-min-height))
+      ;; `split-window' would not signal an error here.
+      (error "Size of new window too small"))
+    (setq new-window (split-window nil size))
+    (unless split-window-keep-point
+      (with-current-buffer (window-buffer)
+       (goto-char (window-start))
+       (setq moved (vertical-motion (window-height)))
+       (set-window-start new-window (point))
+       (when (> (point) (window-point new-window))
+         (set-window-point new-window (point)))
+       (when (= moved (window-height))
+         (setq moved-by-window-height t)
+         (vertical-motion -1))
+       (setq bottom (point)))
+      (and moved-by-window-height
+          (<= bottom (point))
+          (set-window-point old-window (1- bottom)))
+      (and moved-by-window-height
+          (<= (window-start new-window) old-point)
+          (set-window-point new-window old-point)
+          (select-window new-window)))
+    (split-window-save-restore-data new-window old-window)))
+
+(defalias 'split-window-vertically 'split-window-above-each-other)
+
+;; This is to avoid compiler warnings.
+(defvar view-return-to-alist)
+
+(defun split-window-save-restore-data (new-window old-window)
+  (with-current-buffer (window-buffer)
+    (when view-mode
+      (let ((old-info (assq old-window view-return-to-alist)))
+       (when old-info
+         (push (cons new-window (cons (car (cdr old-info)) t))
+               view-return-to-alist))))
+    new-window))
+
+(defun split-window-side-by-side (&optional size)
+  "Split selected window into two windows side by side.
+The selected window becomes the left one and gets SIZE columns.
+SIZE negative means the right window gets -SIZE lines.
+
+SIZE includes the width of the window's scroll bar; if there are
+no scroll bars, it includes the width of the divider column to
+the window's right, if any.  SIZE omitted or nil means split
+window equally.
+
+The selected window remains selected.  Return the new window."
+  (interactive "P")
+  (let ((old-window (selected-window))
+       (size (and size (prefix-numeric-value size)))
+       new-window)
+    (when (and size (< size 0) (< (- size) window-min-width))
+      ;; `split-window' would not signal an error here.
+      (error "Size of new window too small"))
+    (split-window-save-restore-data (split-window nil size t) old-window)))
+
+(defalias 'split-window-horizontally 'split-window-side-by-side)
+\f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; `balance-windows' subroutines using `window-tree'
 
@@ -2866,102 +3587,6 @@ at the front of the list of recently selected ones."
       ;; input focus and is risen.
       (select-frame-set-input-focus new-frame))
     buffer))
-
-;; I think this should be the default; I think people will prefer it--rms.
-(defcustom split-window-keep-point t
-  "If non-nil, \\[split-window-vertically] keeps the original point \
-in both children.
-This is often more convenient for editing.
-If nil, adjust point in each of the two windows to minimize redisplay.
-This is convenient on slow terminals, but point can move strangely.
-
-This option applies only to `split-window-vertically' and
-functions that call it.  `split-window' always keeps the original
-point in both children."
-  :type 'boolean
-  :group 'windows)
-
-(defun split-window-vertically (&optional size)
-  "Split selected window into two windows, one above the other.
-The upper window gets SIZE lines and the lower one gets the rest.
-SIZE negative means the lower window gets -SIZE lines and the
-upper one the rest.  With no argument, split windows equally or
-close to it.  Both windows display the same buffer, now current.
-
-If the variable `split-window-keep-point' is non-nil, both new
-windows will get the same value of point as the selected window.
-This is often more convenient for editing.  The upper window is
-the selected window.
-
-Otherwise, we choose window starts so as to minimize the amount of
-redisplay; this is convenient on slow terminals.  The new selected
-window is the one that the current value of point appears in.  The
-value of point can change if the text around point is hidden by the
-new mode line.
-
-Regardless of the value of `split-window-keep-point', the upper
-window is the original one and the return value is the new, lower
-window."
-  (interactive "P")
-  (let ((old-window (selected-window))
-       (old-point (point))
-       (size (and size (prefix-numeric-value size)))
-        moved-by-window-height moved new-window bottom)
-    (and size (< size 0)
-        ;; Handle negative SIZE value.
-        (setq size (+ (window-height) size)))
-    (setq new-window (split-window nil size))
-    (unless split-window-keep-point
-      (with-current-buffer (window-buffer)
-       (goto-char (window-start))
-       (setq moved (vertical-motion (window-height)))
-       (set-window-start new-window (point))
-       (when (> (point) (window-point new-window))
-         (set-window-point new-window (point)))
-       (when (= moved (window-height))
-         (setq moved-by-window-height t)
-         (vertical-motion -1))
-       (setq bottom (point)))
-      (and moved-by-window-height
-          (<= bottom (point))
-          (set-window-point old-window (1- bottom)))
-      (and moved-by-window-height
-          (<= (window-start new-window) old-point)
-          (set-window-point new-window old-point)
-          (select-window new-window)))
-    (split-window-save-restore-data new-window old-window)))
-
-;; This is to avoid compiler warnings.
-(defvar view-return-to-alist)
-
-(defun split-window-save-restore-data (new-window old-window)
-  (with-current-buffer (window-buffer)
-    (when view-mode
-      (let ((old-info (assq old-window view-return-to-alist)))
-       (when old-info
-         (push (cons new-window (cons (car (cdr old-info)) t))
-               view-return-to-alist))))
-    new-window))
-
-(defun split-window-horizontally (&optional size)
-  "Split selected window into two windows side by side.
-The selected window becomes the left one and gets SIZE columns.
-SIZE negative means the right window gets -SIZE lines.
-
-SIZE includes the width of the window's scroll bar; if there are
-no scroll bars, it includes the width of the divider column to
-the window's right, if any.  SIZE omitted or nil means split
-window equally.
-
-The selected window remains selected.  Return the new window."
-  (interactive "P")
-  (let ((old-window (selected-window))
-       (size (and size (prefix-numeric-value size))))
-    (and size (< size 0)
-        ;; Handle negative SIZE value.
-        (setq size (+ (window-width) size)))
-    (split-window-save-restore-data (split-window nil size t) old-window)))
-
 \f
 (defun set-window-text-height (window height)
   "Set the height in lines of the text display area of WINDOW to HEIGHT.
@@ -3663,9 +4288,12 @@ Otherwise, consult the value of `truncate-partial-width-windows'
       (if (integerp t-p-w-w)
          (< (window-width window) t-p-w-w)
        t-p-w-w))))
-
-(define-key ctl-x-map "2" 'split-window-vertically)
-(define-key ctl-x-map "3" 'split-window-horizontally)
+\f
+(define-key ctl-x-map "0" 'delete-window)
+(define-key ctl-x-map "1" 'delete-other-windows)
+(define-key ctl-x-map "2" 'split-window-above-each-other)
+(define-key ctl-x-map "3" 'split-window-side-by-side)
+(define-key ctl-x-map "^" 'enlarge-window)
 (define-key ctl-x-map "}" 'enlarge-window-horizontally)
 (define-key ctl-x-map "{" 'shrink-window-horizontally)
 (define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer)
index 01c102c..1643be4 100644 (file)
@@ -1,3 +1,67 @@
+2011-06-10  Martin Rudalics  <rudalics@gmx.at>
+
+       * window.c: Remove declarations of Qwindow_size_fixed,
+       window_min_size_1, window_min_size_2, window_min_size,
+       size_window, window_fixed_size_p, enlarge_window, delete_window.
+       Remove static from declaration of Qdelete_window, it's
+       temporarily needed by Fbury_buffer.
+       (replace_window): Don't assign orig_top_line and
+       orig_total_lines.
+       (Fdelete_window, delete_window): Remove.  Window deletion is
+       handled by window.el.
+       (window_loop): Remove DELETE_OTHER_WINDOWS case.  Replace
+       Fdelete_window calls with calls to Qdelete_window.
+       (Fdelete_other_windows): Remove.  Deleting other windows is
+       handled by window.el.
+       (window_fixed_size_p): Remove.  Fixed-sizeness of windows is
+       handled in window.el.
+       (window_min_size_2, window_min_size_1, window_min_size): Remove.
+       Window minimum sizes are handled in window.el.
+       (shrink_windows, size_window, set_window_height)
+       (set_window_width, change_window_heights, window_height)
+       (window_width, CURBEG, CURSIZE, enlarge_window)
+       (adjust_window_trailing_edge, Fadjust_window_trailing_edge)
+       (Fenlarge_window, Fshrink_window): Remove.  Window resizing is
+       handled in window.el.
+       (make_dummy_parent): Rename to make_parent_window and give it a
+       second argument horflag.
+       (make_window): Don't set resize_proportionally any more.
+       (Fsplit_window): Remove.  Windows are split in window.el.
+       (save_restore_action, save_restore_orig_size)
+       (shrink_window_lowest_first, save_restore_orig_size): Remove.
+       Resize mini windows in window.el.
+       (grow_mini_window, shrink_mini_window): Implement by calling
+       Qresize_root_window_vertically, resize_window_check and
+       resize_window_apply.
+       (saved_window, Fset_window_configuration, save_window_save): Do
+       not handle orig_top_line, orig_total_lines, and
+       resize_proportionally.
+       (window_min_height, window_min_width): Move to window.el.
+       (keys_of_window): Move bindings for delete-other-windows,
+       split-window, delete-window and enlarge-window to window.el.
+
+       * buffer.c: Temporarily extern Qdelete_window.
+       (Fbury_buffer): Temporarily call Qdelete_window instead of
+       Fdelete_window (Fbury_buffer will move to window.el soon).
+
+       * frame.c (set_menu_bar_lines_1): Remove code handling
+       orig_top_line and orig_total_lines.
+
+       * dispnew.c (adjust_frame_glyphs_initially): Don't use
+       set_window_height but set heights directly.
+       (change_frame_size_1): Use resize_frame_windows.
+
+       * xdisp.c (init_xdisp): Don't use set_window_height but set
+       heights directly.
+
+       * xfns.c (x_set_menu_bar_lines, x_set_tool_bar_lines): Use
+       resize_frame_windows instead of change_window_heights and run
+       run_window_configuration_change_hook.
+
+       * w32fns.c (x_set_tool_bar_lines): Use resize_frame_windows
+       instead of change_window_heights and run
+       run_window_configuration_change_hook.
+
 2011-06-09  Martin Rudalics  <rudalics@gmx.at>
 
        * window.c (replace_window): Rename second argument REPLACEMENT to
index e9ff8f4..0862de9 100644 (file)
@@ -1938,6 +1938,8 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
   return Qnil;
 }
 
+extern Lisp_Object Qdelete_window;
+
 DEFUN ("bury-buffer", Fbury_buffer, Sbury_buffer, 0, 1, "",
        doc: /* Put BUFFER-OR-NAME at the end of the list of all buffers.
 There it is the least likely candidate for `other-buffer' to return;
@@ -1969,7 +1971,7 @@ its frame, iconify that frame.  */)
          else if (NILP (XWINDOW (selected_window)->parent))
            Ficonify_frame (Fwindow_frame (selected_window));
          else
-           Fdelete_window (selected_window);
+           call1 (Qdelete_window, selected_window);
        }
     }
   else
index 501dc4f..2dffc0d 100644 (file)
@@ -1933,13 +1933,13 @@ adjust_frame_glyphs_initially (void)
 
   /* Do it for the root window.  */
   XSETFASTINT (root->top_line, top_margin);
+  XSETFASTINT (root->total_lines, frame_lines - 1 - top_margin);
   XSETFASTINT (root->total_cols, frame_cols);
-  set_window_height (sf->root_window, frame_lines - 1 - top_margin, 0);
 
   /* Do it for the mini-buffer window.  */
   XSETFASTINT (mini->top_line, frame_lines - 1);
+  XSETFASTINT (mini->total_lines, 1);
   XSETFASTINT (mini->total_cols, frame_cols);
-  set_window_height (root->next, 1, 0);
 
   adjust_frame_glyphs (sf);
   glyphs_initialized_initially_p = 1;
@@ -5715,24 +5715,7 @@ change_frame_size_1 (register struct frame *f, int newheight, int newwidth, int
 
   if (newheight != FRAME_LINES (f))
     {
-      if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
-       {
-         /* Frame has both root and mini-buffer.  */
-         XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (f))->top_line,
-                      FRAME_TOP_MARGIN (f));
-         set_window_height (FRAME_ROOT_WINDOW (f),
-                            (newheight
-                             - 1
-                             - FRAME_TOP_MARGIN (f)),
-                            2);
-         XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top_line,
-                      newheight - 1);
-         set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0);
-       }
-      else
-       /* Frame has just one top-level window.  */
-       set_window_height (FRAME_ROOT_WINDOW (f),
-                          newheight - FRAME_TOP_MARGIN (f), 2);
+      resize_frame_windows (f, newheight, 0);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
@@ -5742,9 +5725,7 @@ change_frame_size_1 (register struct frame *f, int newheight, int newwidth, int
 
   if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
     {
-      set_window_width (FRAME_ROOT_WINDOW (f), new_frame_total_cols, 2);
-      if (FRAME_HAS_MINIBUF_P (f))
-       set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0);
+      resize_frame_windows (f, new_frame_total_cols, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
index 7188126..6baf2d0 100644 (file)
@@ -135,11 +135,6 @@ set_menu_bar_lines_1 (Lisp_Object window, int n)
   XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
   XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
 
-  if (INTEGERP (w->orig_top_line))
-    XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
-  if (INTEGERP (w->orig_total_lines))
-    XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
-
   /* Handle just the top child in a vertical split.  */
   if (!NILP (w->vchild))
     set_menu_bar_lines_1 (w->vchild, n);
index bdf9dce..823dbe3 100644 (file)
@@ -1596,7 +1596,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     }
 
   FRAME_TOOL_BAR_LINES (f) = nlines;
-  change_window_heights (root_window, delta);
+  resize_frame_windows (f, FRAME_LINES (f), 0);
   adjust_glyphs (f);
 
   /* We also have to make sure that the internal border at the top of
@@ -1631,6 +1631,9 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
       if (WINDOWP (f->tool_bar_window))
        clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
     }
+
+  run_window_configuration_change_hook (f);
+
 }
 
 
@@ -5822,8 +5825,6 @@ Value is t if tooltip was open, nil otherwise.  */)
   UNGCPRO;
   return unbind_to (count, deleted);
 }
-
-
 \f
 /***********************************************************************
                        File selection dialog
index dd8cdab..3ee220e 100644 (file)
@@ -50,17 +50,15 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "nsterm.h"
 #endif
 
-Lisp_Object Qwindowp, Qwindow_live_p;
+Lisp_Object Qwindowp, Qwindow_live_p, Qdelete_window;
 static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
-static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
+static Lisp_Object Qwindow_deletable_p, Qdisplay_buffer;
 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
 static Lisp_Object Qresize_root_window, Qresize_root_window_vertically;
 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 static Lisp_Object Qsafe, Qabove, Qbelow;
 static Lisp_Object Qauto_buffer_name;
 
-static Lisp_Object Qwindow_size_fixed;
-
 static int displayed_window_lines (struct window *);
 static struct window *decode_window (Lisp_Object);
 static int count_windows (struct window *);
@@ -68,13 +66,7 @@ static int get_leaf_windows (struct window *, struct window **, int);
 static void window_scroll (Lisp_Object, int, int, int);
 static void window_scroll_pixel_based (Lisp_Object, int, int, int);
 static void window_scroll_line_based (Lisp_Object, int, int, int);
-static int window_min_size_1 (struct window *, int, int);
-static int window_min_size_2 (struct window *, int, int);
-static int window_min_size (struct window *, int, int, int, int *);
-static void size_window (Lisp_Object, int, int, int, int, int);
 static int freeze_window_start (struct window *, void *);
-static int window_fixed_size_p (struct window *, int, int);
-static void enlarge_window (Lisp_Object, int, int);
 static Lisp_Object window_list (void);
 static int add_window_to_list (struct window *, void *);
 static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
@@ -1803,9 +1795,7 @@ DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_displa
   return table;
 }
 \f
-static void delete_window (Lisp_Object);
-
-/* Record info on buffer window w is displaying
+/* Record info on buffer window W is displaying
    when it is about to cease to display that buffer.  */
 static void
 unshow_buffer (register struct window *w)
@@ -1891,7 +1881,6 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag)
       XSETFASTINT (n->window_end_pos, 0);
       n->window_end_valid = Qnil;
       n->frozen_window_start_p = 0;
-      n->orig_top_line = n->orig_total_lines = Qnil;
     }
 
   n->next = tem = o->next;
@@ -1994,232 +1983,6 @@ delete_deletable_window (Lisp_Object window)
     call1 (Qdelete_window, window);
 }
 \f
-DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
-       doc: /* Remove WINDOW from its frame.
-WINDOW defaults to the selected window.  Return nil.
-Signal an error when WINDOW is the only window on its frame.  */)
-  (register Lisp_Object window)
-{
-  struct frame *f;
-  if (NILP (window))
-    window = selected_window;
-  else
-    CHECK_LIVE_WINDOW (window);
-
-  f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-  delete_window (window);
-
-  run_window_configuration_change_hook (f);
-
-  return Qnil;
-}
-
-static void
-delete_window (register Lisp_Object window)
-{
-  register Lisp_Object tem, parent, sib;
-  register struct window *p;
-  register struct window *par;
-  struct frame *f;
-
-  /* Because this function is called by other C code on non-leaf
-     windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
-     so we can't decode_window here.  */
-  CHECK_WINDOW (window);
-  p = XWINDOW (window);
-
-  /* It's a no-op to delete an already-deleted window.  */
-  if (NILP (p->buffer)
-      && NILP (p->hchild)
-      && NILP (p->vchild))
-    return;
-
-  parent = p->parent;
-  if (NILP (parent))
-    error ("Attempt to delete minibuffer or sole ordinary window");
-  par = XWINDOW (parent);
-
-  windows_or_buffers_changed++;
-  Vwindow_list = Qnil;
-  f = XFRAME (WINDOW_FRAME (p));
-  FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-
-  /* Are we trying to delete any frame's selected window?  */
-  {
-    Lisp_Object swindow, pwindow;
-
-    /* See if the frame's selected window is either WINDOW
-       or any subwindow of it, by finding all that window's parents
-       and comparing each one with WINDOW.  */
-    swindow = FRAME_SELECTED_WINDOW (f);
-
-    while (1)
-      {
-       pwindow = swindow;
-       while (!NILP (pwindow))
-         {
-           if (EQ (window, pwindow))
-             break;
-           pwindow = XWINDOW (pwindow)->parent;
-         }
-
-       /* If the window being deleted is not a parent of SWINDOW,
-          then SWINDOW is ok as the new selected window.  */
-       if (!EQ (window, pwindow))
-         break;
-       /* Otherwise, try another window for SWINDOW.  */
-       swindow = Fnext_window (swindow, Qlambda, Qnil);
-
-       /* If we get back to the frame's selected window,
-          it means there was no acceptable alternative,
-          so we cannot delete.  */
-       if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
-         error ("Cannot delete window");
-      }
-
-    /* If we need to change SWINDOW, do it.  */
-    if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
-      {
-       /* If we're about to delete the selected window on the
-          selected frame, then we should use Fselect_window to select
-          the new window.  On the other hand, if we're about to
-          delete the selected window on any other frame, we shouldn't do
-          anything but set the frame's selected_window slot.  */
-       if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
-         Fselect_window (swindow, Qnil);
-       else
-         FRAME_SELECTED_WINDOW (f) = swindow;
-      }
-  }
-
-  /* Now we know we can delete this one.  */
-  window_deletion_count++;
-
-  tem = p->buffer;
-  /* tem is null for dummy parent windows
-     (which have inferiors but not any contents themselves) */
-  if (!NILP (tem))
-    {
-      unshow_buffer (p);
-      unchain_marker (XMARKER (p->pointm));
-      unchain_marker (XMARKER (p->start));
-    }
-
-  /* Free window glyph matrices.  It is sure that they are allocated
-     again when ADJUST_GLYPHS is called.  Block input so that expose
-     events and other events that access glyph matrices are not
-     processed while we are changing them.  */
-  BLOCK_INPUT;
-  free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
-
-  tem = p->next;
-  if (!NILP (tem))
-    XWINDOW (tem)->prev = p->prev;
-
-  tem = p->prev;
-  if (!NILP (tem))
-    XWINDOW (tem)->next = p->next;
-
-  if (EQ (window, par->hchild))
-    par->hchild = p->next;
-  if (EQ (window, par->vchild))
-    par->vchild = p->next;
-
-  /* Find one of our siblings to give our space to.  */
-  sib = p->prev;
-  if (NILP (sib))
-    {
-      /* If p gives its space to its next sibling, that sibling needs
-        to have its top/left side pulled back to where p's is.
-        set_window_{height,width} will re-position the sibling's
-        children.  */
-      sib = p->next;
-      XWINDOW (sib)->top_line = p->top_line;
-      XWINDOW (sib)->left_col = p->left_col;
-    }
-
-  /* Stretch that sibling.  */
-  if (!NILP (par->vchild))
-    set_window_height (sib,
-                      XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
-                      1);
-  if (!NILP (par->hchild))
-    set_window_width (sib,
-                     XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
-                     1);
-
-  /* If parent now has only one child,
-     put the child into the parent's place.  */
-  tem = par->hchild;
-  if (NILP (tem))
-    tem = par->vchild;
-  if (NILP (XWINDOW (tem)->next)) {
-    replace_window (parent, tem, 1);
-    par = XWINDOW (tem);
-  }
-
-  /* Since we may be deleting combination windows, we must make sure that
-     not only p but all its children have been marked as deleted.  */
-  if (! NILP (p->hchild))
-    delete_all_subwindows (p->hchild);
-  else if (! NILP (p->vchild))
-    delete_all_subwindows (p->vchild);
-
-  /* Mark this window as deleted.  */
-  p->buffer = p->hchild = p->vchild = Qnil;
-
-  if (! NILP (par->parent))
-    par = XWINDOW (par->parent);
-
-  /* Check if we have a v/hchild with a v/hchild.  In that case remove
-     one of them.  */
-
-  if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
-    {
-      p = XWINDOW (par->vchild);
-      par->vchild = p->vchild;
-      tem = p->vchild;
-    }
-  else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
-    {
-      p = XWINDOW (par->hchild);
-      par->hchild = p->hchild;
-      tem = p->hchild;
-    }
-  else
-    p = 0;
-
-  if (p)
-    {
-      while (! NILP (tem)) {
-        XWINDOW (tem)->parent = p->parent;
-        if (NILP (XWINDOW (tem)->next))
-          break;
-        tem = XWINDOW (tem)->next;
-      }
-      if (! NILP (tem)) {
-        /* The next of the v/hchild we are removing is now the next of the
-           last child for the v/hchild:
-           Before v/hchild -> v/hchild -> next1 -> next2
-                    |
-                     -> next3
-           After:  v/hchild -> next1 -> next2 -> next3
-        */
-        XWINDOW (tem)->next = p->next;
-        if (! NILP (p->next))
-          XWINDOW (p->next)->prev = tem;
-      }
-      p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
-    }
-
-
-  /* Adjust glyph matrices. */
-  adjust_glyphs (f);
-  UNBLOCK_INPUT;
-}
-
-
-\f
 /***********************************************************************
                             Window List
  ***********************************************************************/
@@ -2645,7 +2408,6 @@ enum window_loop
 {
   WINDOW_LOOP_UNUSED,
   GET_BUFFER_WINDOW,           /* Arg is buffer */
-  DELETE_OTHER_WINDOWS,                /* Arg is window not to delete */
   DELETE_BUFFER_WINDOWS,       /* Arg is buffer */
   UNSHOW_BUFFER,               /* Arg is buffer */
   REDISPLAY_BUFFER_WINDOWS,    /* Arg is buffer */
@@ -2729,11 +2491,6 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
              }
            break;
 
-         case DELETE_OTHER_WINDOWS:
-           if (!EQ (window, obj))
-             Fdelete_window (window);
-           break;
-
          case DELETE_BUFFER_WINDOWS:
            if (EQ (w->buffer, obj))
              {
@@ -2769,7 +2526,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
                      Fset_buffer (w->buffer);
                  }
                else
-                 Fdelete_window (window);
+                 call1 (Qdelete_window, window);
              }
            break;
 
@@ -2804,7 +2561,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
                    XSETWINDOW (window_to_delete, w);
                    /* If this window is dedicated and not the only window
                       in its frame, then kill it.  */
-                   Fdelete_window (window_to_delete);
+                       call1 (Qdelete_window, window_to_delete);
                  }
                else
                  {
@@ -3128,68 +2885,6 @@ window-start value is reasonable when this function is called.  */)
 }
 
 
-DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
-       0, 1, "",
-       doc: /* Make WINDOW (or the selected window) fill its frame.
-Only the frame WINDOW is on is affected.
-This function tries to reduce display jumps by keeping the text
-previously visible in WINDOW in the same place on the frame.  Doing this
-depends on the value of (window-start WINDOW), so if calling this
-function in a program gives strange scrolling, make sure the
-window-start value is reasonable when this function is called.  */)
-  (Lisp_Object window)
-{
-  struct window *w;
-  EMACS_INT startpos;
-  int top, new_top;
-
-  if (NILP (window))
-    window = selected_window;
-  else
-    CHECK_LIVE_WINDOW (window);
-  w = XWINDOW (window);
-
-  startpos = marker_position (w->start);
-  top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
-
-  if (MINI_WINDOW_P (w) && top > 0)
-    error ("Can't expand minibuffer to full frame");
-
-  window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
-
-  /* Try to minimize scrolling, by setting the window start to the point
-     will cause the text at the old window start to be at the same place
-     on the frame.  But don't try to do this if the window start is
-     outside the visible portion (as might happen when the display is
-     not current, due to typeahead).  */
-  new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
-  if (new_top != top
-      && startpos >= BUF_BEGV (XBUFFER (w->buffer))
-      && startpos <= BUF_ZV (XBUFFER (w->buffer)))
-    {
-      struct position pos;
-      struct buffer *obuf = current_buffer;
-
-      Fset_buffer (w->buffer);
-      /* This computation used to temporarily move point, but that can
-        have unwanted side effects due to text properties.  */
-      pos = *vmotion (startpos, -top, w);
-
-      set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
-      w->window_end_valid = Qnil;
-      w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
-                              || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
-                             : Qnil);
-      /* We need to do this, so that the window-scroll-functions
-        get called.  */
-      w->optional_new_start = Qt;
-
-      set_buffer_internal (obuf);
-    }
-
-  return Qnil;
-}
-
 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
        0, 2, "bDelete windows on (buffer): ",
        doc: /* Delete all windows showing BUFFER-OR-NAME.
@@ -3271,8 +2966,6 @@ replace_buffer_in_all_windows (Lisp_Object buffer)
     window_loop (UNSHOW_BUFFER, buffer, 1, frame);
 }
 \f
-/* Set the height of WINDOW and all its inferiors.  */
-
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 
@@ -3296,243 +2989,6 @@ check_frame_size (FRAME_PTR frame, int *rows, int *cols)
     *cols = MIN_SAFE_WINDOW_WIDTH;
 }
 
-/* Value is non-zero if window W is fixed-size.  WIDTH_P non-zero means
-   check if W's width can be changed, otherwise check W's height.
-   CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
-   siblings, too.  If none of the siblings is resizable, WINDOW isn't
-   either.  */
-
-static int
-window_fixed_size_p (struct window *w, int width_p, int check_siblings_p)
-{
-  int fixed_p;
-  struct window *c;
-
-  if (!NILP (w->hchild))
-    {
-      c = XWINDOW (w->hchild);
-
-      if (width_p)
-       {
-         /* A horizontal combination is fixed-width if all of if its
-            children are.  */
-         while (c && window_fixed_size_p (c, width_p, 0))
-           c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-         fixed_p = c == NULL;
-       }
-      else
-       {
-         /* A horizontal combination is fixed-height if one of if its
-            children is.  */
-         while (c && !window_fixed_size_p (c, width_p, 0))
-           c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-         fixed_p = c != NULL;
-       }
-    }
-  else if (!NILP (w->vchild))
-    {
-      c = XWINDOW (w->vchild);
-
-      if (width_p)
-       {
-         /* A vertical combination is fixed-width if one of if its
-            children is.  */
-         while (c && !window_fixed_size_p (c, width_p, 0))
-           c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-         fixed_p = c != NULL;
-       }
-      else
-       {
-         /* A vertical combination is fixed-height if all of if its
-            children are.  */
-         while (c && window_fixed_size_p (c, width_p, 0))
-           c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-         fixed_p = c == NULL;
-       }
-    }
-  else if (BUFFERP (w->buffer))
-    {
-      struct buffer *old = current_buffer;
-      Lisp_Object val;
-
-      current_buffer = XBUFFER (w->buffer);
-      val = find_symbol_value (Qwindow_size_fixed);
-      current_buffer = old;
-
-      fixed_p = 0;
-      if (!EQ (val, Qunbound))
-       {
-         fixed_p = !NILP (val);
-
-         if (fixed_p
-             && ((EQ (val, Qheight) && width_p)
-                 || (EQ (val, Qwidth) && !width_p)))
-           fixed_p = 0;
-       }
-
-      /* Can't tell if this one is resizable without looking at
-        siblings.  If all siblings are fixed-size this one is too.  */
-      if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
-       {
-         Lisp_Object child;
-
-         for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
-           if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
-             break;
-
-         if (NILP (child))
-           for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
-             if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
-               break;
-
-         if (NILP (child))
-           fixed_p = 1;
-       }
-    }
-  else
-    fixed_p = 1;
-
-  return fixed_p;
-}
-
-/* Return minimum size of leaf window W.  WIDTH_P non-zero means return
-   the minimum width of W, WIDTH_P zero means return the minimum height
-   of W.  SAFE_P non-zero means ignore window-min-height|width but just
-   return values that won't crash Emacs and don't hide components like
-   fringes, scrollbars, or modelines.  If WIDTH_P is zero and W is the
-   minibuffer window, always return 1.  */
-
-static int
-window_min_size_2 (struct window *w, int width_p, int safe_p)
-{
-  /* We should consider buffer-local values of window_min_height and
-     window_min_width here.  */
-  if (width_p)
-    {
-      int safe_size = (MIN_SAFE_WINDOW_WIDTH
-                      + WINDOW_FRINGE_COLS (w)
-                      + WINDOW_SCROLL_BAR_COLS (w));
-
-      return safe_p ? safe_size : max (window_min_width, safe_size);
-    }
-  else if (MINI_WINDOW_P (w))
-    return 1;
-  else
-    {
-      int safe_size = (MIN_SAFE_WINDOW_HEIGHT
-                      + ((BUFFERP (w->buffer)
-                          && !NILP (BVAR (XBUFFER (w->buffer), mode_line_format)))
-                         ? 1 : 0));
-
-      return safe_p ? safe_size : max (window_min_height, safe_size);
-    }
-}
-
-/* Return minimum size of window W, not taking fixed-width windows into
-   account.  WIDTH_P non-zero means return the minimum width, otherwise
-   return the minimum height.  SAFE_P non-zero means ignore
-   window-min-height|width but just return values that won't crash Emacs
-   and don't hide components like fringes, scrollbars, or modelines.  If
-   W is a combination window, compute the minimum size from the minimum
-   sizes of W's children.  */
-
-static int
-window_min_size_1 (struct window *w, int width_p, int safe_p)
-{
-  struct window *c;
-  int size;
-
-  if (!NILP (w->hchild))
-    {
-      /* W is a horizontal combination.  */
-      c = XWINDOW (w->hchild);
-      size = 0;
-
-      if (width_p)
-       {
-         /* The minimum width of a horizontal combination is the sum of
-            the minimum widths of its children.  */
-         while (c)
-           {
-             size += window_min_size_1 (c, 1, safe_p);
-             c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-           }
-       }
-      else
-       {
-         /* The minimum height of a horizontal combination is the
-            maximum of the minimum heights of its children.  */
-         while (c)
-           {
-             size = max (window_min_size_1 (c, 0, safe_p), size);
-             c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-           }
-       }
-    }
-  else if (!NILP (w->vchild))
-    {
-      /* W is a vertical combination.  */
-      c = XWINDOW (w->vchild);
-      size = 0;
-
-      if (width_p)
-       {
-         /* The minimum width of a vertical combination is the maximum
-            of the minimum widths of its children.  */
-         while (c)
-           {
-             size = max (window_min_size_1 (c, 1, safe_p), size);
-             c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-           }
-       }
-      else
-       {
-         /* The minimum height of a vertical combination is the sum of
-            the minimum height of its children.  */
-         while (c)
-           {
-             size += window_min_size_1 (c, 0, safe_p);
-             c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
-           }
-       }
-    }
-  else
-    /* W is a leaf window.  */
-    size = window_min_size_2 (w, width_p, safe_p);
-
-  return size;
-}
-
-/* Return the minimum size of window W, taking fixed-size windows into
-   account.  WIDTH_P non-zero means return the minimum width, otherwise
-   return the minimum height.  SAFE_P non-zero means ignore
-   window-min-height|width but just return values that won't crash Emacs
-   and don't hide components like fringes, scrollbars, or modelines.
-   IGNORE_FIXED_P non-zero means ignore if W is fixed-size.  Set *FIXED
-   to 1 if W is fixed-size unless FIXED is null.  */
-
-static int
-window_min_size (struct window *w, int width_p, int safe_p, int ignore_fixed_p, int *fixed)
-{
-  int size, fixed_p;
-
-  if (ignore_fixed_p)
-    fixed_p = 0;
-  else
-    fixed_p = window_fixed_size_p (w, width_p, 1);
-
-  if (fixed)
-    *fixed = fixed_p;
-
-  if (fixed_p)
-    size = WINDOW_TOTAL_SIZE (w, width_p);
-  else
-    size = window_min_size_1 (w, width_p, safe_p);
-
-  return size;
-}
-
-
 /* Adjust the margins of window W if text area is too small.
    Return 1 if window width is ok after adjustment; 0 if window
    is still too narrow.  */
@@ -3567,448 +3023,44 @@ adjust_window_margins (struct window *w)
     w->left_margin_cols = make_number (margin_cols);
   return 1;
 }
+\f
+int window_select_count;
 
-/* Calculate new sizes for windows in the list FORWARD when their
-   compound size goes from TOTAL to SIZE.  TOTAL must be greater than
-   SIZE.  The number of windows in FORWARD is NCHILDREN, and the number
-   that can shrink is SHRINKABLE.  Fixed-size windows may be shrunk if
-   and only if RESIZE_FIXED_P is non-zero.  WIDTH_P non-zero means
-   shrink columns, otherwise shrink lines.
-
-   SAFE_P zero means windows may be sized down to window-min-height
-   lines (window-min-window columns for WIDTH_P non-zero).  SAFE_P
-   non-zero means windows may be sized down to their minimum safe sizes
-   taking into account the space needed to display modelines, fringes,
-   and scrollbars.
-
-   This function returns an allocated array of new sizes that the caller
-   must free.  A size -1 means the window is fixed and RESIZE_FIXED_P is
-   zero.  A size zero means the window shall be deleted.  Array index 0
-   refers to the first window in FORWARD, 1 to the second, and so on.
-
-   This function resizes windows proportionally to their size.  It also
-   tries to preserve smaller windows by resizing larger windows before
-   resizing any window to zero.  If resize_proportionally is non-nil for
-   a specific window, it will attempt to strictly resize that window
-   proportionally, even at the expense of deleting smaller windows.  */
-static int *
-shrink_windows (int total, int size, int nchildren, int shrinkable,
-               int resize_fixed_p, Lisp_Object forward, int width_p, int safe_p)
-{
-  int available_resize = 0;
-  int *new_sizes, *min_sizes;
-  struct window *c;
-  Lisp_Object child;
-  int smallest = total;
-  int total_removed = 0;
-  int total_shrink = total - size;
-  int i;
+static Lisp_Object Fset_window_margins (Lisp_Object, Lisp_Object, Lisp_Object);
+static Lisp_Object Fset_window_fringes (Lisp_Object, Lisp_Object, Lisp_Object,
+                                       Lisp_Object);
+static Lisp_Object Fset_window_scroll_bars (Lisp_Object, Lisp_Object,
+                                           Lisp_Object, Lisp_Object);
+static Lisp_Object Fset_window_vscroll (Lisp_Object, Lisp_Object, Lisp_Object);
 
-  new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
-  min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
+static void
+run_funs (Lisp_Object funs)
+{
+  for (; CONSP (funs); funs = XCDR (funs))
+    if (!EQ (XCAR (funs), Qt))
+      call0 (XCAR (funs));
+}
 
-  for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
-    {
-      int child_size;
+static Lisp_Object select_window_norecord (Lisp_Object window);
+static Lisp_Object select_frame_norecord (Lisp_Object frame);
 
-      c = XWINDOW (child);
-      child_size = WINDOW_TOTAL_SIZE (c, width_p);
+void
+run_window_configuration_change_hook (struct frame *f)
+{
+  int count = SPECPDL_INDEX ();
+  Lisp_Object frame, global_wcch
+    = Fdefault_value (Qwindow_configuration_change_hook);
+  XSETFRAME (frame, f);
 
-      if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
-        new_sizes[i] = -1;
-      else
-        {
-          new_sizes[i] = child_size;
-          min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
-          if (child_size > min_sizes[i]
-             && NILP (c->resize_proportionally))
-            available_resize += child_size - min_sizes[i];
-        }
-    }
-  /* We might need to shrink some windows to zero.  Find the smallest
-     windows and set them to 0 until we can fulfil the new size.  */
+  if (NILP (Vrun_hooks))
+    return;
 
-  while (shrinkable > 1 && size + available_resize < total)
+  /* Use the right buffer.  Matters when running the local hooks.  */
+  if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
     {
-      for (i = 0; i < nchildren; ++i)
-        if (new_sizes[i] > 0 && smallest > new_sizes[i])
-          smallest = new_sizes[i];
-
-      for (i = 0; i < nchildren; ++i)
-        if (new_sizes[i] == smallest)
-          {
-            /* Resize this window down to zero.  */
-            new_sizes[i] = 0;
-            if (smallest > min_sizes[i])
-              available_resize -= smallest - min_sizes[i];
-            available_resize += smallest;
-            --shrinkable;
-            total_removed += smallest;
-
-            /* We don't know what the smallest is now.  */
-            smallest = total;
-
-            /* Out of for, just remove one window at the time and
-               check again if we have enough space.  */
-            break;
-          }
-    }
-
-  /* Now, calculate the new sizes.  Try to shrink each window
-     proportional to its size.  */
-  for (i = 0; i < nchildren; ++i)
-    {
-      if (new_sizes[i] > min_sizes[i])
-        {
-          int to_shrink = total_shrink * new_sizes[i] / total;
-
-          if (new_sizes[i] - to_shrink < min_sizes[i])
-            to_shrink = new_sizes[i] - min_sizes[i];
-          new_sizes[i] -= to_shrink;
-          total_removed += to_shrink;
-        }
-    }
-
-  /* Any reminder due to rounding, we just subtract from windows
-     that are left and still can be shrunk.  */
-  while (total_shrink > total_removed)
-    {
-      int nonzero_sizes = 0;
-
-      for (i = 0; i < nchildren; ++i)
-        if (new_sizes[i] > 0)
-         ++nonzero_sizes;
-
-      for (i = 0; i < nchildren; ++i)
-        if (new_sizes[i] > min_sizes[i])
-          {
-            --new_sizes[i];
-            ++total_removed;
-
-            /* Out of for, just shrink one window at the time and
-               check again if we have enough space.  */
-            break;
-          }
-
-      /* Special case, only one window left.  */
-      if (nonzero_sizes == 1)
-        break;
-    }
-
-  /* Any surplus due to rounding, we add to windows that are left.  */
-  while (total_shrink < total_removed)
-    {
-      for (i = 0; i < nchildren; ++i)
-        {
-          if (new_sizes[i] != 0 && total_shrink < total_removed)
-            {
-              ++new_sizes[i];
-              --total_removed;
-              break;
-            }
-        }
-    }
-
-  xfree (min_sizes);
-
-  return new_sizes;
-}
-
-/* Set WINDOW's height or width to SIZE.  WIDTH_P non-zero means set
-   WINDOW's width.  Resize WINDOW's children, if any, so that they keep
-   their proportionate size relative to WINDOW.
-
-   If FIRST_ONLY is 1, change only the first of WINDOW's children when
-   they are in series.  If LAST_ONLY is 1, change only the last of
-   WINDOW's children when they are in series.
-
-   Propagate WINDOW's top or left edge position to children.  Delete
-   windows that become too small unless NODELETE_P is 1.  When
-   NODELETE_P equals 2 do not honor settings for window-min-height and
-   window-min-width when resizing windows but use safe defaults instead.
-   This should give better behavior when resizing frames.  */
-
-static void
-size_window (Lisp_Object window, int size, int width_p, int nodelete_p, int first_only, int last_only)
-{
-  struct window *w = XWINDOW (window);
-  struct window *c;
-  Lisp_Object child, *forward, *sideward;
-  int old_size = WINDOW_TOTAL_SIZE (w, width_p);
-
-  size = max (0, size);
-
-  /* Delete WINDOW if it's too small.  */
-  if (nodelete_p != 1 && !NILP (w->parent)
-      && size < window_min_size_1 (w, width_p, nodelete_p == 2))
-    {
-      delete_window (window);
-      return;
-    }
-
-  /* Set redisplay hints.  */
-  w->last_modified = make_number (0);
-  w->last_overlay_modified = make_number (0);
-  windows_or_buffers_changed++;
-  FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
-
-  if (width_p)
-    {
-      sideward = &w->vchild;
-      forward = &w->hchild;
-      w->total_cols = make_number (size);
-      adjust_window_margins (w);
-    }
-  else
-    {
-      sideward = &w->hchild;
-      forward = &w->vchild;
-      w->total_lines = make_number (size);
-      w->orig_total_lines = Qnil;
-    }
-
-  if (!NILP (*sideward))
-    {
-      /* We have a chain of parallel siblings whose size should all change.  */
-      for (child = *sideward; !NILP (child); child = c->next)
-       {
-         c = XWINDOW (child);
-         if (width_p)
-           c->left_col = w->left_col;
-         else
-           c->top_line = w->top_line;
-         size_window (child, size, width_p, nodelete_p,
-                      first_only, last_only);
-       }
-    }
-  else if (!NILP (*forward) && last_only)
-    {
-      /* Change the last in a series of siblings.  */
-      Lisp_Object last_child;
-      int child_size;
-
-      child = *forward;
-      do
-       {
-         c = XWINDOW (child);
-         last_child = child;
-         child = c->next;
-       }
-      while (!NILP (child));
-
-      child_size = WINDOW_TOTAL_SIZE (c, width_p);
-      size_window (last_child, size - old_size + child_size,
-                  width_p, nodelete_p, first_only, last_only);
-    }
-  else if (!NILP (*forward) && first_only)
-    {
-      /* Change the first in a series of siblings.  */
-      int child_size;
-
-      child = *forward;
-      c = XWINDOW (child);
-
-      if (width_p)
-       c->left_col = w->left_col;
-      else
-       c->top_line = w->top_line;
-
-      child_size = WINDOW_TOTAL_SIZE (c, width_p);
-      size_window (child, size - old_size + child_size,
-                  width_p, nodelete_p, first_only, last_only);
-    }
-  else if (!NILP (*forward))
-    {
-      int fixed_size, each IF_LINT (= 0), extra IF_LINT (= 0), n;
-      int resize_fixed_p, nfixed;
-      int last_pos, first_pos, nchildren, total;
-      int *new_sizes = NULL;
-
-      /* Determine the fixed-size portion of this window, and the
-        number of child windows.  */
-      fixed_size = nchildren = nfixed = total = 0;
-      for (child = *forward; !NILP (child); child = c->next, ++nchildren)
-       {
-         int child_size;
-
-         c = XWINDOW (child);
-         child_size = WINDOW_TOTAL_SIZE (c, width_p);
-         total += child_size;
-
-         if (window_fixed_size_p (c, width_p, 0))
-           {
-             fixed_size += child_size;
-             ++nfixed;
-           }
-       }
-
-      /* If the new size is smaller than fixed_size, or if there
-        aren't any resizable windows, allow resizing fixed-size
-        windows.  */
-      resize_fixed_p = nfixed == nchildren || size < fixed_size;
-
-      /* Compute how many lines/columns to add/remove to each child.  The
-        value of extra takes care of rounding errors.  */
-      n = resize_fixed_p ? nchildren : nchildren - nfixed;
-      if (size < total && n > 1)
-        new_sizes = shrink_windows (total, size, nchildren, n,
-                                    resize_fixed_p, *forward, width_p,
-                                   nodelete_p == 2);
-      else
-        {
-          each = (size - total) / n;
-          extra = (size - total) - n * each;
-        }
-
-      /* Compute new children heights and edge positions.  */
-      first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
-      last_pos = first_pos;
-      for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
-       {
-         int new_child_size, old_child_size;
-
-         c = XWINDOW (child);
-         old_child_size = WINDOW_TOTAL_SIZE (c, width_p);
-         new_child_size = old_child_size;
-
-         /* The top or left edge position of this child equals the
-            bottom or right edge of its predecessor.  */
-         if (width_p)
-           c->left_col = make_number (last_pos);
-         else
-           c->top_line = make_number (last_pos);
-
-         /* If this child can be resized, do it.  */
-         if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
-           {
-             new_child_size =
-               new_sizes ? new_sizes[n] : old_child_size + each + extra;
-             extra = 0;
-           }
-
-         /* Set new size.  Note that size_window also propagates
-            edge positions to children, so it's not a no-op if we
-            didn't change the child's size.  */
-         size_window (child, new_child_size, width_p, 1,
-                      first_only, last_only);
-
-         /* Remember the bottom/right edge position of this child; it
-            will be used to set the top/left edge of the next child.  */
-          last_pos += new_child_size;
-       }
-
-      xfree (new_sizes);
-
-      /* We should have covered the parent exactly with child windows.  */
-      xassert (size == last_pos - first_pos);
-
-      /* Now delete any children that became too small.  */
-      if (nodelete_p != 1)
-       for (child = *forward; !NILP (child); child = c->next)
-         {
-           int child_size;
-
-           c = XWINDOW (child);
-           child_size = WINDOW_TOTAL_SIZE (c, width_p);
-           size_window (child, child_size, width_p, nodelete_p,
-                        first_only, last_only);
-         }
-    }
-}
-
-/* Set WINDOW's height to HEIGHT, and recursively change the height of
-   WINDOW's children.  NODELETE zero means windows that have become
-   smaller than window-min-height in the process may be deleted.
-   NODELETE 1 means never delete windows that become too small in the
-   process.  (The caller should check later and do so if appropriate.)
-   NODELETE 2 means delete only windows that have become too small to be
-   displayed correctly.  */
-
-void
-set_window_height (Lisp_Object window, int height, int nodelete)
-{
-  size_window (window, height, 0, nodelete, 0, 0);
-}
-
-/* Set WINDOW's width to WIDTH, and recursively change the width of
-   WINDOW's children.  NODELETE zero means windows that have become
-   smaller than window-min-width in the process may be deleted.
-   NODELETE 1 means never delete windows that become too small in the
-   process.  (The caller should check later and do so if appropriate.)
-   NODELETE 2 means delete only windows that have become too small to be
-   displayed correctly.  */
-
-void
-set_window_width (Lisp_Object window, int width, int nodelete)
-{
-  size_window (window, width, 1, nodelete, 0, 0);
-}
-
-/* Change window heights in windows rooted in WINDOW by N lines.  */
-
-void
-change_window_heights (Lisp_Object window, int n)
-{
-  struct window *w = XWINDOW (window);
-
-  XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
-  XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
-
-  if (INTEGERP (w->orig_top_line))
-    XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
-  if (INTEGERP (w->orig_total_lines))
-    XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
-
-  /* Handle just the top child in a vertical split.  */
-  if (!NILP (w->vchild))
-    change_window_heights (w->vchild, n);
-
-  /* Adjust all children in a horizontal split.  */
-  for (window = w->hchild; !NILP (window); window = w->next)
-    {
-      w = XWINDOW (window);
-      change_window_heights (window, n);
-    }
-}
-
-\f
-int window_select_count;
-
-static Lisp_Object Fset_window_margins (Lisp_Object, Lisp_Object, Lisp_Object);
-static Lisp_Object Fset_window_fringes (Lisp_Object, Lisp_Object, Lisp_Object,
-                                       Lisp_Object);
-static Lisp_Object Fset_window_scroll_bars (Lisp_Object, Lisp_Object,
-                                           Lisp_Object, Lisp_Object);
-static Lisp_Object Fset_window_vscroll (Lisp_Object, Lisp_Object, Lisp_Object);
-
-static void
-run_funs (Lisp_Object funs)
-{
-  for (; CONSP (funs); funs = XCDR (funs))
-    if (!EQ (XCAR (funs), Qt))
-      call0 (XCAR (funs));
-}
-
-static Lisp_Object select_window_norecord (Lisp_Object window);
-static Lisp_Object select_frame_norecord (Lisp_Object frame);
-
-void
-run_window_configuration_change_hook (struct frame *f)
-{
-  int count = SPECPDL_INDEX ();
-  Lisp_Object frame, global_wcch
-    = Fdefault_value (Qwindow_configuration_change_hook);
-  XSETFRAME (frame, f);
-
-  if (NILP (Vrun_hooks))
-    return;
-
-  /* Use the right buffer.  Matters when running the local hooks.  */
-  if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
-    {
-      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
-      Fset_buffer (Fwindow_buffer (Qnil));
-    }
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      Fset_buffer (Fwindow_buffer (Qnil));
+    }
 
   if (SELECTED_FRAME () != f)
     {
@@ -4337,43 +3389,6 @@ DEFUN ("internal-temp-output-buffer-show",
   return Qnil;
 }
 \f
-static void
-make_dummy_parent (Lisp_Object window)
-{
-  Lisp_Object new;
-  register struct window *o, *p;
-  int i;
-
-  o = XWINDOW (window);
-  p = allocate_window ();
-  for (i = 0; i < VECSIZE (struct window); ++i)
-    ((struct Lisp_Vector *) p)->contents[i]
-      = ((struct Lisp_Vector *)o)->contents[i];
-  XSETWINDOW (new, p);
-
-  ++sequence_number;
-  XSETFASTINT (p->sequence_number, sequence_number);
-  XSETFASTINT (p->clone_number, sequence_number);
-
-  /* Put new into window structure in place of window */
-  replace_window (window, new, 1);
-
-  o->next = Qnil;
-  o->prev = Qnil;
-  o->vchild = Qnil;
-  o->hchild = Qnil;
-  o->parent = new;
-
-  p->start = Qnil;
-  p->pointm = Qnil;
-  p->buffer = Qnil;
-
-  p->splits = Qnil;
-  p->nest = Qnil;
-  p->window_parameters = Qnil;
-
-}
-
 /* Make new window, have it replace WINDOW in window-tree, and make
    WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
    horizontal child).   */
@@ -4470,7 +3485,6 @@ make_window (void)
   w->pseudo_window_p = 0;
   w->frozen_window_start_p = 0;
   w->vscroll = 0;
-  w->resize_proportionally = Qnil;
   /* Reset window_list.  */
   Vwindow_list = Qnil;
   /* Return window.  */
@@ -5046,1026 +4060,236 @@ when WINDOW is the only window on its frame.  */)
       sibling = w->prev;
       s = XWINDOW (sibling);
       s->next = w->next;
-      if (!NILP (s->next))
-       XWINDOW (s->next)->prev = sibling;
-    }
-
-  if (resize_window_check (r, horflag)
-      && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
-    /* We can delete WINDOW now.  */
-    {
-      /* Block input.  */
-      BLOCK_INPUT;
-      resize_window_apply (p, horflag);
-
-      windows_or_buffers_changed++;
-      Vwindow_list = Qnil;
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-
-      w->next = Qnil;  /* Don't delete w->next too.  */
-      free_window_matrices (w);
-
-      if (!NILP (w->vchild))
-       {
-         delete_all_subwindows (w->vchild);
-         w->vchild = Qnil;
-       }
-      else if (!NILP (w->hchild))
-       {
-         delete_all_subwindows (w->hchild);
-         w->hchild = Qnil;
-       }
-      else if (!NILP (w->buffer))
-       {
-         unshow_buffer (w);
-         unchain_marker (XMARKER (w->pointm));
-         unchain_marker (XMARKER (w->start));
-         w->buffer = Qnil;
-       }
-
-      if (NILP (s->prev) && NILP (s->next))
-         /* A matrjoshka where SIBLING has become the only child of
-            PARENT.  */
-       {
-         /* Put SIBLING into PARENT's place.  */
-         replace_window (parent, sibling, 0);
-         /* Have SIBLING inherit the following three slot values from
-            PARENT (the nest slot is not inherited).  */
-         s->normal_cols = p->normal_cols;
-         s->normal_lines = p->normal_lines;
-         s->splits = p->splits;
-         /* Mark PARENT as deleted.  */
-         p->vchild = p->hchild = Qnil;
-         /* Try to merge SIBLING into its new parent.  */
-         recombine_windows (sibling);
-       }
-
-      adjust_glyphs (f);
-
-      if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
-       /* We deleted the frame's selected window.  */
-       {
-         /* Use the frame's first window as fallback ...  */
-         Lisp_Object new_selected_window = Fframe_first_window (frame);
-         /* ... but preferably use its most recently used window.  */
-         Lisp_Object mru_window;
-
-         /* `get-mru-window' might fail for some reason so play it safe
-         - promote the first window _without recording it_ first.  */
-         if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
-           Fselect_window (new_selected_window, Qt);
-         else
-           FRAME_SELECTED_WINDOW (f) = new_selected_window;
-
-         UNBLOCK_INPUT;
-
-         /* Now look whether `get-mru-window' gets us something.  */
-         mru_window = call1 (Qget_mru_window, frame);
-         if (WINDOW_LIVE_P (mru_window)
-             && EQ (XWINDOW (mru_window)->frame, frame))
-           new_selected_window = mru_window;
-
-         /* If all ended up well, we now promote the mru window.  */
-         if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
-           Fselect_window (new_selected_window, Qnil);
-         else
-           FRAME_SELECTED_WINDOW (f) = new_selected_window;
-       }
-      else
-       UNBLOCK_INPUT;
-
-      /* Must be run by the caller:
-        run_window_configuration_change_hook (f);  */
-    }
-  else
-    /* We failed: Relink WINDOW into window tree.  */
-    {
-      if (before_sibling)
-       {
-         s->prev = window;
-         if (horflag)
-           p->hchild = window;
-         else
-           p->vchild = window;
-       }
-      else
-       {
-         s->next = window;
-         if (!NILP (w->next))
-           XWINDOW (w->next)->prev = window;
-       }
-      error ("Deletion failed");
-    }
-
-  return Qnil;
-}
-
-DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
-       doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
-WINDOW defaults to selected one and SIZE to half its size.
-If optional third arg HORIZONTAL is non-nil, split side by side and put
-SIZE columns in the first of the pair.  In that case, SIZE includes that
-window's scroll bar, or the divider column to its right.
-Interactively, all arguments are nil.
-Returns the newly created window (which is the lower or rightmost one).
-The upper or leftmost window is the original one, and remains selected
-if it was selected before.
-
-See Info node `(elisp)Splitting Windows' for more details and examples.  */)
-  (Lisp_Object window, Lisp_Object size, Lisp_Object horizontal)
-{
-  register Lisp_Object new;
-  register struct window *o, *p;
-  FRAME_PTR fo;
-  register int size_int;
-
-  if (NILP (window))
-    window = selected_window;
-  else
-    CHECK_LIVE_WINDOW (window);
-
-  o = XWINDOW (window);
-  fo = XFRAME (WINDOW_FRAME (o));
-
-  if (NILP (size))
-    {
-      if (!NILP (horizontal))
-       /* Calculate the size of the left-hand window, by dividing
-          the usable space in columns by two.
-          We round up, since the left-hand window may include
-          a dividing line, while the right-hand may not.  */
-       size_int = (XFASTINT (o->total_cols) + 1) >> 1;
-      else
-       size_int = XFASTINT (o->total_lines) >> 1;
-    }
-  else
-    {
-      CHECK_NUMBER (size);
-      size_int = XINT (size);
-    }
-
-  if (MINI_WINDOW_P (o))
-    error ("Attempt to split minibuffer window");
-  else if (window_fixed_size_p (o, !NILP (horizontal), 0))
-    error ("Attempt to split fixed-size window");
-
-  if (NILP (horizontal))
-    {
-      int window_safe_height = window_min_size_2 (o, 0, 0);
-
-      if (size_int < window_safe_height)
-       error ("Window height %d too small (after splitting)", size_int);
-      if (size_int + window_safe_height > XFASTINT (o->total_lines))
-       error ("Window height %d too small (after splitting)",
-              (int) (XFASTINT (o->total_lines) - size_int));
-      if (NILP (o->parent)
-         || NILP (XWINDOW (o->parent)->vchild))
-       {
-         make_dummy_parent (window);
-         new = o->parent;
-         XWINDOW (new)->vchild = window;
-       }
-    }
-  else
-    {
-      int window_safe_width = window_min_size_2 (o, 1, 0);
-
-      if (size_int < window_safe_width)
-       error ("Window width %d too small (after splitting)", size_int);
-      if (size_int + window_safe_width > XFASTINT (o->total_cols))
-       error ("Window width %d too small (after splitting)",
-              (int) (XFASTINT (o->total_cols) - size_int));
-      if (NILP (o->parent)
-         || NILP (XWINDOW (o->parent)->hchild))
-       {
-         make_dummy_parent (window);
-         new = o->parent;
-         XWINDOW (new)->hchild = window;
-       }
-    }
-
-  /* Now we know that window's parent is a vertical combination
-     if we are dividing vertically, or a horizontal combination
-     if we are making side-by-side windows */
-
-  windows_or_buffers_changed++;
-  FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
-  new = make_window ();
-  p = XWINDOW (new);
-
-  p->frame = o->frame;
-  p->next = o->next;
-  if (!NILP (p->next))
-    XWINDOW (p->next)->prev = new;
-  p->prev = window;
-  o->next = new;
-  p->parent = o->parent;
-  p->buffer = Qt;
-  p->window_end_valid = Qnil;
-  memset (&p->last_cursor, 0, sizeof p->last_cursor);
-
-  /* Duplicate special geometry settings.  */
-
-  p->left_margin_cols = o->left_margin_cols;
-  p->right_margin_cols = o->right_margin_cols;
-  p->left_fringe_width = o->left_fringe_width;
-  p->right_fringe_width = o->right_fringe_width;
-  p->fringes_outside_margins = o->fringes_outside_margins;
-  p->scroll_bar_width = o->scroll_bar_width;
-  p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
-
-  /* Apportion the available frame space among the two new windows */
-
-  if (!NILP (horizontal))
-    {
-      p->total_lines = o->total_lines;
-      p->top_line = o->top_line;
-      XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
-      XSETFASTINT (o->total_cols, size_int);
-      XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
-      adjust_window_margins (p);
-      adjust_window_margins (o);
-    }
-  else
-    {
-      p->left_col = o->left_col;
-      p->total_cols = o->total_cols;
-      XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
-      XSETFASTINT (o->total_lines, size_int);
-      XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
-    }
-
-  /* Adjust glyph matrices.  */
-  adjust_glyphs (fo);
-
-  Fset_window_buffer (new, o->buffer, Qt);
-  return new;
-}
-
-DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
-       doc: /* Resize minibuffer window WINDOW.  */)
-     (Lisp_Object window)
-{
-  struct window *w = XWINDOW (window);
-  struct window *r;
-  struct frame *f;
-  int height;
-
-  CHECK_WINDOW (window);
-  f = XFRAME (w->frame);
-
-  if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
-    error ("Not a valid minibuffer window");
-  else if (FRAME_MINIBUF_ONLY_P (f))
-    error ("Cannot resize a minibuffer-only frame");
-
-  r = XWINDOW (FRAME_ROOT_WINDOW (f));
-  height = XINT (r->total_lines) + XINT (w->total_lines);
-  if (resize_window_check (r, 0)
-      && XINT (w->new_total) > 0
-      && height == XINT (r->new_total) + XINT (w->new_total))
-    {
-      BLOCK_INPUT;
-      resize_window_apply (r, 0);
-
-      w->total_lines = w->new_total;
-      XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines));
-
-      windows_or_buffers_changed++;
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-      adjust_glyphs (f);
-      UNBLOCK_INPUT;
-
-      run_window_configuration_change_hook (f);
-      return Qt;
-    }
-  else error ("Failed to resize minibuffer window");
-}
-\f
-DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
-       doc: /* Make selected window SIZE lines taller.
-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 SIZE columns.  If SIZE is negative, shrink the window by
--SIZE lines or columns.  Return nil.
-
-This function can delete windows if they get too small.  The size of
-fixed size windows is not altered by this function.  */)
-  (Lisp_Object size, Lisp_Object horizontal)
-{
-  CHECK_NUMBER (size);
-  enlarge_window (selected_window, XINT (size), !NILP (horizontal));
-
-  run_window_configuration_change_hook (SELECTED_FRAME ());
-
-  return Qnil;
-}
-
-DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
-       doc: /* Make selected window SIZE lines smaller.
-Interactively, if no argument is given, make the selected window one
-line smaller.  If optional argument HORIZONTAL is non-nil, make the
-window narrower by SIZE columns.  If SIZE is negative, enlarge selected
-window by -SIZE lines or columns.  Return nil.
-
-This function can delete windows if they get too small.  The size of
-fixed size windows is not altered by this function. */)
-  (Lisp_Object size, Lisp_Object horizontal)
-{
-  CHECK_NUMBER (size);
-  enlarge_window (selected_window, -XINT (size), !NILP (horizontal));
-
-  run_window_configuration_change_hook (SELECTED_FRAME ());
-
-  return Qnil;
-}
-
-static int
-window_height (Lisp_Object window)
-{
-  register struct window *p = XWINDOW (window);
-  return WINDOW_TOTAL_LINES (p);
-}
-
-static int
-window_width (Lisp_Object window)
-{
-  register struct window *p = XWINDOW (window);
-  return WINDOW_TOTAL_COLS (p);
-}
-
-
-#define CURBEG(w) \
-  *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
-
-#define CURSIZE(w) \
-  *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
-
-
-/* Enlarge WINDOW by DELTA.  HORIZ_FLAG nonzero means enlarge it
-   horizontally; zero means do it vertically.
-
-   Siblings of the selected window are resized to fulfill the size
-   request.  If they become too small in the process, they may be
-   deleted.  */
-
-static void
-enlarge_window (Lisp_Object window, int delta, int horiz_flag)
-{
-  Lisp_Object parent, next, prev;
-  struct window *p;
-  Lisp_Object *sizep;
-  int maximum;
-  int (*sizefun) (Lisp_Object)
-    = horiz_flag ? window_width : window_height;
-  void (*setsizefun) (Lisp_Object, int, int)
-    = (horiz_flag ? set_window_width : set_window_height);
-
-  /* Give up if this window cannot be resized.  */
-  if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
-    error ("Window is not resizable");
-
-  /* Find the parent of the selected window.  */
-  while (1)
-    {
-      p = XWINDOW (window);
-      parent = p->parent;
-
-      if (NILP (parent))
-       {
-         if (horiz_flag)
-           error ("No other window to side of this one");
-         break;
-       }
-
-      if (horiz_flag
-         ? !NILP (XWINDOW (parent)->hchild)
-         : !NILP (XWINDOW (parent)->vchild))
-       break;
-
-      window = parent;
-    }
-
-  sizep = &CURSIZE (window);
-
-  {
-    register int maxdelta;
-
-    /* Compute the maximum size increment this window can have.  */
-
-    maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
-               /* This is a main window followed by a minibuffer.  */
-               : !NILP (p->next) ? ((*sizefun) (p->next)
-                                    - window_min_size (XWINDOW (p->next),
-                                                       horiz_flag, 0, 0, 0))
-               /* This is a minibuffer following a main window.  */
-               : !NILP (p->prev) ? ((*sizefun) (p->prev)
-                                    - window_min_size (XWINDOW (p->prev),
-                                                       horiz_flag, 0, 0, 0))
-               /* This is a frame with only one window, a minibuffer-only
-                  or a minibufferless frame.  */
-               : (delta = 0));
-
-    if (delta > maxdelta)
-      /* This case traps trying to make the minibuffer
-        the full frame, or make the only window aside from the
-        minibuffer the full frame.  */
-      delta = maxdelta;
-  }
-
-  if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
-                                              horiz_flag, 0, 0, 0))
-    {
-      delete_window (window);
-      return;
-    }
-
-  if (delta == 0)
-    return;
-
-  /* Find the total we can get from other siblings without deleting them.  */
-  maximum = 0;
-  for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
-    maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
-                                                   horiz_flag, 0, 0, 0);
-  for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
-    maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
-                                                   horiz_flag, 0, 0, 0);
-
-  /* If we can get it all from them without deleting them, do so.  */
-  if (delta <= maximum)
-    {
-      Lisp_Object first_unaffected;
-      Lisp_Object first_affected;
-      int fixed_p;
-
-      next = p->next;
-      prev = p->prev;
-      first_affected = window;
-      /* Look at one sibling at a time,
-        moving away from this window in both directions alternately,
-        and take as much as we can get without deleting that sibling.  */
-      while (delta != 0
-            && (!NILP (next) || !NILP (prev)))
-       {
-         if (! NILP (next))
-           {
-             int this_one = ((*sizefun) (next)
-                             - window_min_size (XWINDOW (next), horiz_flag,
-                                                0, 0, &fixed_p));
-             if (!fixed_p)
-               {
-                 if (this_one > delta)
-                   this_one = delta;
-
-                 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
-                 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
-
-                 delta -= this_one;
-               }
-
-             next = XWINDOW (next)->next;
-           }
-
-         if (delta == 0)
-           break;
-
-         if (! NILP (prev))
-           {
-             int this_one = ((*sizefun) (prev)
-                             - window_min_size (XWINDOW (prev), horiz_flag,
-                                                0, 0, &fixed_p));
-             if (!fixed_p)
-               {
-                 if (this_one > delta)
-                   this_one = delta;
-
-                 first_affected = prev;
-
-                 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
-                 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
-
-                 delta -= this_one;
-               }
-
-             prev = XWINDOW (prev)->prev;
-           }
-       }
-
-      xassert (delta == 0);
-
-      /* Now recalculate the edge positions of all the windows affected,
-        based on the new sizes.  */
-      first_unaffected = next;
-      prev = first_affected;
-      for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
-          prev = next, next = XWINDOW (next)->next)
-       {
-         XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
-         /* This does not change size of NEXT,
-            but it propagates the new top edge to its children */
-         (*setsizefun) (next, (*sizefun) (next), 0);
-       }
-    }
-  else
-    {
-      register int delta1;
-      register int opht = (*sizefun) (parent);
-
-      if (opht <= XINT (*sizep) + delta)
-       {
-         /* If trying to grow this window to or beyond size of the parent,
-            just delete all the sibling windows.  */
-         Lisp_Object start, tem;
-
-         start = XWINDOW (parent)->vchild;
-         if (NILP (start))
-           start = XWINDOW (parent)->hchild;
-
-         /* Delete any siblings that come after WINDOW.  */
-         tem = XWINDOW (window)->next;
-         while (! NILP (tem))
-           {
-             Lisp_Object next1 = XWINDOW (tem)->next;
-             delete_window (tem);
-             tem = next1;
-           }
-
-         /* Delete any siblings that come after WINDOW.
-            Note that if START is not WINDOW, then WINDOW still
-            has siblings, so WINDOW has not yet replaced its parent.  */
-         tem = start;
-         while (! EQ (tem, window))
-           {
-             Lisp_Object next1 = XWINDOW (tem)->next;
-             delete_window (tem);
-             tem = next1;
-           }
-       }
-      else
-       {
-         /* Otherwise, make delta1 just right so that if we add
-            delta1 lines to this window and to the parent, and then
-            shrink the parent back to its original size, the new
-            proportional size of this window will increase by delta.
-
-            The function size_window will compute the new height h'
-            of the window from delta1 as:
-
-            e = delta1/n
-            x = delta1 - delta1/n * n for the 1st resizable child
-            h' = h + e + x
-
-            where n is the number of children that can be resized.
-            We can ignore x by choosing a delta1 that is a multiple of
-            n.  We want the height of this window to come out as
-
-            h' = h + delta
-
-            So, delta1 must be
-
-            h + e = h + delta
-            delta1/n = delta
-            delta1 = n * delta.
-
-            The number of children n equals the number of resizable
-            children of this window + 1 because we know window itself
-            is resizable (otherwise we would have signaled an error).
-
-            This reasoning is not correct when other windows become too
-            small and shrink_windows refuses to delete them.  Below we
-            use resize_proportionally to work around this problem.  */
-
-         struct window *w = XWINDOW (window);
-         Lisp_Object s;
-         int n = 1;
-
-         for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
-           if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
-             ++n;
-         for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
-           if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
-             ++n;
-
-         delta1 = n * delta;
-
-         /* Add delta1 lines or columns to this window, and to the parent,
-            keeping things consistent while not affecting siblings.  */
-         XSETINT (CURSIZE (parent), opht + delta1);
-         (*setsizefun) (window, XINT (*sizep) + delta1, 0);
-
-         /* Squeeze out delta1 lines or columns from our parent,
-            shrinking this window and siblings proportionately.  This
-            brings parent back to correct size.  Delta1 was calculated
-            so this makes this window the desired size, taking it all
-            out of the siblings.
-
-            Temporarily set resize_proportionally to Qt to assure that,
-            if necessary, shrink_windows deletes smaller windows rather
-            than shrink this window.  */
-         w->resize_proportionally = Qt;
-         (*setsizefun) (parent, opht, 0);
-         w->resize_proportionally = Qnil;
-       }
+      if (!NILP (s->next))
+       XWINDOW (s->next)->prev = sibling;
     }
 
-  XSETFASTINT (p->last_modified, 0);
-  XSETFASTINT (p->last_overlay_modified, 0);
-
-  /* Adjust glyph matrices. */
-  adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
-}
-
-
-/* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
-   HORIZ_FLAG nonzero means adjust the width, moving the right edge.
-   zero means adjust the height, moving the bottom edge.
-
-   Following siblings of the selected window are resized to fulfill
-   the size request.  If they become too small in the process, they
-   are not deleted; instead, we signal an error.  */
-
-static void
-adjust_window_trailing_edge (Lisp_Object window, int delta, int horiz_flag)
-{
-  Lisp_Object parent, child;
-  struct window *p;
-  Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
-  int delcount = window_deletion_count;
-
-  CHECK_WINDOW (window);
+  if (resize_window_check (r, horflag)
+      && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
+    /* We can delete WINDOW now.  */
+    {
+      /* Block input.  */
+      BLOCK_INPUT;
+      resize_window_apply (p, horflag);
 
-  /* Give up if this window cannot be resized.  */
-  if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
-    error ("Window is not resizable");
+      windows_or_buffers_changed++;
+      Vwindow_list = Qnil;
+      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
-  while (1)
-    {
-      Lisp_Object first_parallel = Qnil;
+      w->next = Qnil;  /* Don't delete w->next too.  */
+      free_window_matrices (w);
 
-      if (NILP (window))
+      if (!NILP (w->vchild))
        {
-         /* This happens if WINDOW on the previous iteration was
-            at top level of the window tree.  */
-         Fset_window_configuration (old_config);
-         error ("Specified window edge is fixed");
+         delete_all_subwindows (w->vchild);
+         w->vchild = Qnil;
        }
-
-      p = XWINDOW (window);
-      parent = p->parent;
-
-      /* See if this level has windows in parallel in the specified
-        direction.  If so, set FIRST_PARALLEL to the first one.  */
-      if (horiz_flag)
+      else if (!NILP (w->hchild))
        {
-         if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
-           first_parallel = XWINDOW (parent)->vchild;
-         else if (NILP (parent) && !NILP (p->next))
-           {
-             /* Handle the vertical chain of main window and minibuffer
-                which has no parent.  */
-             first_parallel = window;
-             while (! NILP (XWINDOW (first_parallel)->prev))
-               first_parallel = XWINDOW (first_parallel)->prev;
-           }
+         delete_all_subwindows (w->hchild);
+         w->hchild = Qnil;
        }
-      else
+      else if (!NILP (w->buffer))
        {
-         if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
-           first_parallel = XWINDOW (parent)->hchild;
+         unshow_buffer (w);
+         unchain_marker (XMARKER (w->pointm));
+         unchain_marker (XMARKER (w->start));
+         w->buffer = Qnil;
        }
 
-      /* If this level's succession is in the desired dimension,
-        and this window is the last one, and there is no higher level,
-        its trailing edge is fixed.  */
-      if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
-         && NILP (parent))
+      if (NILP (s->prev) && NILP (s->next))
+         /* A matrjoshka where SIBLING has become the only child of
+            PARENT.  */
        {
-         Fset_window_configuration (old_config);
-         error ("Specified window edge is fixed");
+         /* Put SIBLING into PARENT's place.  */
+         replace_window (parent, sibling, 0);
+         /* Have SIBLING inherit the following three slot values from
+            PARENT (the nest slot is not inherited).  */
+         s->normal_cols = p->normal_cols;
+         s->normal_lines = p->normal_lines;
+         s->splits = p->splits;
+         /* Mark PARENT as deleted.  */
+         p->vchild = p->hchild = Qnil;
+         /* Try to merge SIBLING into its new parent.  */
+         recombine_windows (sibling);
        }
 
-      /* Don't make this window too small.  */
-      if (XINT (CURSIZE (window)) + delta
-         < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
+      adjust_glyphs (f);
+
+      if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
+       /* We deleted the frame's selected window.  */
        {
-         Fset_window_configuration (old_config);
-         error ("Cannot adjust window size as specified");
-       }
+         /* Use the frame's first window as fallback ...  */
+         Lisp_Object new_selected_window = Fframe_first_window (frame);
+         /* ... but preferably use its most recently used window.  */
+         Lisp_Object mru_window;
 
-      /* Clear out some redisplay caches.  */
-      XSETFASTINT (p->last_modified, 0);
-      XSETFASTINT (p->last_overlay_modified, 0);
+         /* `get-mru-window' might fail for some reason so play it safe
+         - promote the first window _without recording it_ first.  */
+         if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
+           Fselect_window (new_selected_window, Qt);
+         else
+           FRAME_SELECTED_WINDOW (f) = new_selected_window;
 
-      /* Adjust this window's edge.  */
-      XSETINT (CURSIZE (window),
-              XINT (CURSIZE (window)) + delta);
+         UNBLOCK_INPUT;
 
-      /* If this window has following siblings in the desired dimension,
-        make them smaller, and exit the loop.
+         /* Now look whether `get-mru-window' gets us something.  */
+         mru_window = call1 (Qget_mru_window, frame);
+         if (WINDOW_LIVE_P (mru_window)
+             && EQ (XWINDOW (mru_window)->frame, frame))
+           new_selected_window = mru_window;
 
-        (If we reach the top of the tree and can never do this,
-        we will fail and report an error, above.)  */
-      if (NILP (first_parallel))
-       {
-         if (!NILP (p->next))
-           {
-              /* This may happen for the minibuffer.  In that case
-                 the window_deletion_count check below does not work.  */
-              if (XINT (CURSIZE (p->next)) - delta <= 0)
-                {
-                  Fset_window_configuration (old_config);
-                  error ("Cannot adjust window size as specified");
-                }
-
-             XSETINT (CURBEG (p->next),
-                      XINT (CURBEG (p->next)) + delta);
-             size_window (p->next, XINT (CURSIZE (p->next)) - delta,
-                          horiz_flag, 0, 1, 0);
-             break;
-           }
+         /* If all ended up well, we now promote the mru window.  */
+         if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
+           Fselect_window (new_selected_window, Qnil);
+         else
+           FRAME_SELECTED_WINDOW (f) = new_selected_window;
        }
       else
-       /* Here we have a chain of parallel siblings, in the other dimension.
-          Change the size of the other siblings.  */
-       for (child = first_parallel;
-            ! NILP (child);
-            child = XWINDOW (child)->next)
-         if (! EQ (child, window))
-           size_window (child, XINT (CURSIZE (child)) + delta,
-                        horiz_flag, 0, 0, 1);
+       UNBLOCK_INPUT;
 
-      window = parent;
+      /* Must be run by the caller:
+        run_window_configuration_change_hook (f);  */
     }
-
-  /* If we made a window so small it got deleted,
-     we failed.  Report failure.  */
-  if (delcount != window_deletion_count)
+  else
+    /* We failed: Relink WINDOW into window tree.  */
     {
-      Fset_window_configuration (old_config);
-      error ("Cannot adjust window size as specified");
+      if (before_sibling)
+       {
+         s->prev = window;
+         if (horflag)
+           p->hchild = window;
+         else
+           p->vchild = window;
+       }
+      else
+       {
+         s->next = window;
+         if (!NILP (w->next))
+           XWINDOW (w->next)->prev = window;
+       }
+      error ("Deletion failed");
     }
 
-  /* Adjust glyph matrices. */
-  adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
-}
-
-#undef CURBEG
-#undef CURSIZE
-
-DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
-       Sadjust_window_trailing_edge, 3, 3, 0,
-       doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
-If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
-Otherwise, adjust the height, moving the bottom edge.
-
-Following siblings of the selected window are resized to fulfill
-the size request.  If they become too small in the process, they
-are not deleted; instead, we signal an error.  */)
-  (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal)
-{
-  CHECK_NUMBER (delta);
-  if (NILP (window))
-    window = selected_window;
-  adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
-
-  run_window_configuration_change_hook
-    (XFRAME (WINDOW_FRAME (XWINDOW (window))));
-
   return Qnil;
 }
-
-
 \f
 /***********************************************************************
                        Resizing Mini-Windows
  ***********************************************************************/
 
-static void shrink_window_lowest_first (struct window *, int);
-
-enum save_restore_action
-{
-    CHECK_ORIG_SIZES,
-    SAVE_ORIG_SIZES,
-    RESTORE_ORIG_SIZES
-};
-
-static int save_restore_orig_size (struct window *,
-                                   enum save_restore_action);
-
-/* Shrink windows rooted in window W to HEIGHT.  Take the space needed
-   from lowest windows first.  */
-
-static void
-shrink_window_lowest_first (struct window *w, int height)
+/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
+   can.  */
+void
+grow_mini_window (struct window *w, int delta)
 {
-  struct window *c;
-  Lisp_Object child;
-  int old_height;
-
-  xassert (!MINI_WINDOW_P (w));
-
-  /* Set redisplay hints.  */
-  XSETFASTINT (w->last_modified, 0);
-  XSETFASTINT (w->last_overlay_modified, 0);
-  windows_or_buffers_changed++;
-  FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
+  struct frame *f = XFRAME (w->frame);
+  struct window *r;
+  Lisp_Object root, value;
 
-  old_height = XFASTINT (w->total_lines);
-  XSETFASTINT (w->total_lines, height);
+  xassert (MINI_WINDOW_P (w));
+  xassert (delta >= 0);
 
-  if (!NILP (w->hchild))
-    {
-      for (child = w->hchild; !NILP (child); child = c->next)
-       {
-         c = XWINDOW (child);
-         c->top_line = w->top_line;
-         shrink_window_lowest_first (c, height);
-       }
-    }
-  else if (!NILP (w->vchild))
+  root = FRAME_ROOT_WINDOW (f);
+  r = XWINDOW (root);
+  value = call2 (Qresize_root_window_vertically, root, make_number (- delta));
+  if (INTEGERP (value) && resize_window_check (r, 0))
     {
-      Lisp_Object last_child;
-      int delta = old_height - height;
-      int last_top;
-
-      last_child = Qnil;
-
-      /* Find the last child.  We are taking space from lowest windows
-        first, so we iterate over children from the last child
-        backwards.  */
-      for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
-       last_child = child;
-
-      /* Size children down to their safe heights.  */
-      for (child = last_child; delta && !NILP (child); child = c->prev)
-       {
-         int this_one;
-
-         c = XWINDOW (child);
-         this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
-
-         if (this_one > delta)
-           this_one = delta;
+      BLOCK_INPUT;
+      resize_window_apply (r, 0);
 
-         shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
-         delta -= this_one;
-       }
+      /* Grow the mini-window.  */
+      XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines));
+      XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - XINT (value));
+      XSETFASTINT (w->last_modified, 0);
+      XSETFASTINT (w->last_overlay_modified, 0);
 
-      /* Compute new positions.  */
-      last_top = XINT (w->top_line);
-      for (child = w->vchild; !NILP (child); child = c->next)
-       {
-         c = XWINDOW (child);
-         c->top_line = make_number (last_top);
-         shrink_window_lowest_first (c, XFASTINT (c->total_lines));
-         last_top += XFASTINT (c->total_lines);
-       }
+      adjust_glyphs (f);
+      UNBLOCK_INPUT;
     }
 }
 
 
-/* Save, restore, or check positions and sizes in the window tree
-   rooted at W.  ACTION says what to do.
-
-   If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
-   orig_total_lines members are valid for all windows in the window
-   tree.  Value is non-zero if they are valid.
-
-   If ACTION is SAVE_ORIG_SIZES, save members top and height in
-   orig_top_line and orig_total_lines for all windows in the tree.
-
-   If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
-   stored in orig_top_line and orig_total_lines for all windows.  */
-
-static int
-save_restore_orig_size (struct window *w, enum save_restore_action action)
+/* Shrink mini-window W.  */
+void
+shrink_mini_window (struct window *w)
 {
-  int success_p = 1;
+  struct frame *f = XFRAME (w->frame);
+  struct window *r;
+  Lisp_Object root, value;
+  EMACS_INT size;
 
-  while (w)
-    {
-      if (!NILP (w->hchild))
-       {
-         if (!save_restore_orig_size (XWINDOW (w->hchild), action))
-           success_p = 0;
-       }
-      else if (!NILP (w->vchild))
-       {
-         if (!save_restore_orig_size (XWINDOW (w->vchild), action))
-           success_p = 0;
-       }
+  xassert (MINI_WINDOW_P (w));
 
-      switch (action)
+  size = XINT (w->total_lines);
+  if (size > 1)
+    {
+      root = FRAME_ROOT_WINDOW (f);
+      r = XWINDOW (root);
+      value = call2 (Qresize_root_window_vertically,
+                    root, make_number (size - 1));
+      if (INTEGERP (value) && resize_window_check (r, 0))
        {
-       case CHECK_ORIG_SIZES:
-         if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
-           return 0;
-         break;
+         BLOCK_INPUT;
+         resize_window_apply (r, 0);
 
-       case SAVE_ORIG_SIZES:
-         w->orig_top_line = w->top_line;
-         w->orig_total_lines = w->total_lines;
-          XSETFASTINT (w->last_modified, 0);
-          XSETFASTINT (w->last_overlay_modified, 0);
-         break;
+         /* Shrink the mini-window.  */
+         XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines));
+         XSETFASTINT (w->total_lines, 1);
 
-       case RESTORE_ORIG_SIZES:
-         xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
-         w->top_line = w->orig_top_line;
-         w->total_lines = w->orig_total_lines;
-         w->orig_total_lines = w->orig_top_line = Qnil;
-          XSETFASTINT (w->last_modified, 0);
-          XSETFASTINT (w->last_overlay_modified, 0);
-         break;
+         XSETFASTINT (w->last_modified, 0);
+         XSETFASTINT (w->last_overlay_modified, 0);
 
-       default:
-         abort ();
+         adjust_glyphs (f);
+         UNBLOCK_INPUT;
        }
-
-      w = NILP (w->next) ? NULL : XWINDOW (w->next);
+      /* If the above failed for whatever strange reason we must make a
+        one window frame here.  The same routine will be needed when
+        shrinking the frame (and probably when making the initial
+        *scratch* window).  For the moment leave things as they are.  */
     }
-
-  return success_p;
 }
 
-
-/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
-   without deleting other windows.  */
-
-void
-grow_mini_window (struct window *w, int delta)
+DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
+       doc: /* Resize minibuffer window WINDOW.  */)
+     (Lisp_Object window)
 {
-  struct frame *f = XFRAME (w->frame);
-  struct window *root;
+  struct window *w = XWINDOW (window);
+  struct window *r;
+  struct frame *f;
+  int height;
 
-  xassert (MINI_WINDOW_P (w));
-  /* Commenting out the following assertion goes against the stated interface
-     of the function, but it currently does not seem to do anything useful.
-     See discussion of this issue in the thread for bug#4534.
-     xassert (delta >= 0); */
+  CHECK_WINDOW (window);
+  f = XFRAME (w->frame);
 
-  /* Compute how much we can enlarge the mini-window without deleting
-     other windows.  */
-  root = XWINDOW (FRAME_ROOT_WINDOW (f));
-  if (delta > 0)
-    {
-      int min_height = window_min_size (root, 0, 0, 0, 0);
-      if (XFASTINT (root->total_lines) - delta < min_height)
-       /* Note that the root window may already be smaller than
-          min_height.  */
-       delta = max (0, XFASTINT (root->total_lines) - min_height);
-    }
+  if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
+    error ("Not a valid minibuffer window");
+  else if (FRAME_MINIBUF_ONLY_P (f))
+    error ("Cannot resize a minibuffer-only frame");
 
-  if (delta)
+  r = XWINDOW (FRAME_ROOT_WINDOW (f));
+  height = XINT (r->total_lines) + XINT (w->total_lines);
+  if (resize_window_check (r, 0)
+      && XINT (w->new_total) > 0
+      && height == XINT (r->new_total) + XINT (w->new_total))
     {
-      /* Save original window sizes and positions, if not already done.  */
-      if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
-       save_restore_orig_size (root, SAVE_ORIG_SIZES);
-
-      /* Shrink other windows.  */
-      shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
+      BLOCK_INPUT;
+      resize_window_apply (r, 0);
 
-      /* Grow the mini-window.  */
-      w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
-      w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
-      XSETFASTINT (w->last_modified, 0);
-      XSETFASTINT (w->last_overlay_modified, 0);
+      w->total_lines = w->new_total;
+      XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines));
 
+      windows_or_buffers_changed++;
+      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
       adjust_glyphs (f);
-    }
-}
-
-
-/* Shrink mini-window W.  If there is recorded info about window sizes
-   before a call to grow_mini_window, restore recorded window sizes.
-   Otherwise, if the mini-window is higher than 1 line, resize it to 1
-   line.  */
-
-void
-shrink_mini_window (struct window *w)
-{
-  struct frame *f = XFRAME (w->frame);
-  struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
+      UNBLOCK_INPUT;
 
-  if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
-    {
-      save_restore_orig_size (root, RESTORE_ORIG_SIZES);
-      adjust_glyphs (f);
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-      windows_or_buffers_changed = 1;
-    }
-  else if (XFASTINT (w->total_lines) > 1)
-    {
-      /* Distribute the additional lines of the mini-window
-        among the other windows.  */
-      Lisp_Object window;
-      XSETWINDOW (window, w);
-      enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
+      run_window_configuration_change_hook (f);
+      return Qt;
     }
+  else error ("Failed to resize minibuffer window");
 }
-
-
+\f
 \f
 /* Mark window cursors off for all windows in the window tree rooted
    at W by setting their phys_cursor_on_p flag to zero.  Called from
@@ -7252,11 +5476,9 @@ struct saved_window
   Lisp_Object parent, prev;
   Lisp_Object start_at_line_beg;
   Lisp_Object display_table;
-  Lisp_Object orig_top_line, orig_total_lines;
   Lisp_Object left_margin_cols, right_margin_cols;
   Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
-  Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
-  Lisp_Object dedicated, resize_proportionally;
+  Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
   Lisp_Object splits, nest, window_parameters;
 };
 
@@ -7476,8 +5698,6 @@ the return value is nil.  Otherwise the value is t.  */)
          w->hscroll = p->hscroll;
          w->min_hscroll = p->min_hscroll;
          w->display_table = p->display_table;
-         w->orig_top_line = p->orig_top_line;
-         w->orig_total_lines = p->orig_total_lines;
          w->left_margin_cols = p->left_margin_cols;
          w->right_margin_cols = p->right_margin_cols;
          w->left_fringe_width = p->left_fringe_width;
@@ -7489,7 +5709,6 @@ the return value is nil.  Otherwise the value is t.  */)
          w->splits = p->splits;
          w->nest = p->nest;
          w->window_parameters = p->window_parameters;
-         w->resize_proportionally = p->resize_proportionally;
          XSETFASTINT (w->last_modified, 0);
          XSETFASTINT (w->last_overlay_modified, 0);
 
@@ -7618,6 +5837,7 @@ the return value is nil.  Otherwise the value is t.  */)
   return (FRAME_LIVE_P (f) ? Qt : Qnil);
 }
 
+
 /* Delete all subwindows reachable via the next, vchild, and hchild
    slots of WINDOW.  */
 void
@@ -7670,7 +5890,6 @@ count_windows (register struct window *window)
 
 /* Fill vector FLAT with leaf windows under W, starting at index I.
    Value is last index + 1.  */
-
 static int
 get_leaf_windows (struct window *w, struct window **flat, int i)
 {
@@ -7693,7 +5912,6 @@ get_leaf_windows (struct window *w, struct window **flat, int i)
 /* Return a pointer to the glyph W's physical cursor is on.  Value is
    null if W's current matrix is invalid, so that no meaningfull glyph
    can be returned.  */
-
 struct glyph *
 get_phys_cursor_glyph (struct window *w)
 {
@@ -7738,8 +5956,6 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       p->hscroll = w->hscroll;
       p->min_hscroll = w->min_hscroll;
       p->display_table = w->display_table;
-      p->orig_top_line = w->orig_top_line;
-      p->orig_total_lines = w->orig_total_lines;
       p->left_margin_cols = w->left_margin_cols;
       p->right_margin_cols = w->right_margin_cols;
       p->left_fringe_width = w->left_fringe_width;
@@ -7750,7 +5966,6 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       p->dedicated = w->dedicated;
       p->splits = w->splits;
       p->nest = w->nest;
-      p->resize_proportionally = w->resize_proportionally;
       p->window_parameters = w->window_parameters;
       if (!NILP (w->buffer))
        {
@@ -8444,10 +6659,6 @@ syms_of_window (void)
   Fput (Qscroll_up, Qscroll_command, Qt);
   Fput (Qscroll_down, Qscroll_command, Qt);
 
-  Qwindow_size_fixed = intern_c_string ("window-size-fixed");
-  staticpro (&Qwindow_size_fixed);
-  Fset (Qwindow_size_fixed, Qnil);
-
   staticpro (&Qwindow_configuration_change_hook);
   Qwindow_configuration_change_hook
     = intern_c_string ("window-configuration-change-hook");
@@ -8540,24 +6751,6 @@ is displayed in the `mode-line' face.  */);
              doc: /* *Number of lines of continuity when scrolling by screenfuls.  */);
   next_screen_context_lines = 2;
 
-  DEFVAR_INT ("window-min-height", window_min_height,
-             doc: /* Allow deleting windows less than this tall.
-The value is measured in line units.  If a window wants a modeline it
-is counted as one line.
-
-Emacs honors settings of this variable when enlarging or shrinking
-windows vertically.  A value less than 1 is invalid.  */);
-  window_min_height = 4;
-
-  DEFVAR_INT ("window-min-width", window_min_width,
-             doc: /* Allow deleting windows less than this wide.
-The value is measured in characters and includes any fringes or
-the scrollbar.
-
-Emacs honors settings of this variable when enlarging or shrinking
-windows horizontally.  A value less than 2 is invalid.  */);
-  window_min_width = 10;
-
   DEFVAR_LISP ("scroll-preserve-screen-position",
               Vscroll_preserve_screen_position,
               doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
@@ -8684,10 +6877,8 @@ function `window-nest' and altered by the function `set-window-nest'.  */);
   defsubr (&Sprevious_window);
   defsubr (&Sother_window);
   defsubr (&Sget_buffer_window);
-  defsubr (&Sdelete_other_windows);
   defsubr (&Sdelete_windows_on);
   defsubr (&Sreplace_buffer_in_windows);
-  defsubr (&Sdelete_window);
   defsubr (&Sdelete_other_windows_internal);
   defsubr (&Sdelete_window_internal);
   defsubr (&Sresize_mini_window_internal);
@@ -8697,11 +6888,7 @@ function `window-nest' and altered by the function `set-window-nest'.  */);
   defsubr (&Sselect_window);
   defsubr (&Sforce_window_update);
   defsubr (&Stemp_output_buffer_show);
-  defsubr (&Ssplit_window);
   defsubr (&Ssplit_window_internal);
-  defsubr (&Senlarge_window);
-  defsubr (&Sshrink_window);
-  defsubr (&Sadjust_window_trailing_edge);
   defsubr (&Sscroll_up);
   defsubr (&Sscroll_down);
   defsubr (&Sscroll_left);
@@ -8740,11 +6927,7 @@ function `window-nest' and altered by the function `set-window-nest'.  */);
 void
 keys_of_window (void)
 {
-  initial_define_key (control_x_map, '1', "delete-other-windows");
-  initial_define_key (control_x_map, '2', "split-window");
-  initial_define_key (control_x_map, '0', "delete-window");
   initial_define_key (control_x_map, 'o', "other-window");
-  initial_define_key (control_x_map, '^', "enlarge-window");
   initial_define_key (control_x_map, '<', "scroll-left");
   initial_define_key (control_x_map, '>', "scroll-right");
 
index 02467c7..65f6ddd 100644 (file)
@@ -27115,31 +27115,27 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or
 void
 init_xdisp (void)
 {
-  Lisp_Object root_window;
-  struct window *mini_w;
-
   current_header_line_height = current_mode_line_height = -1;
 
   CHARPOS (this_line_start_pos) = 0;
 
-  mini_w = XWINDOW (minibuf_window);
-  root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
-  echo_area_window = minibuf_window;
-
   if (!noninteractive)
     {
-      struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
+      struct window *m = XWINDOW (minibuf_window);
+      Lisp_Object frame = m->frame;
+      struct frame *f = XFRAME (frame);
+      Lisp_Object root = FRAME_ROOT_WINDOW (f);
+      struct window *r = XWINDOW (root);
       int i;
 
-      XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f));
-      set_window_height (root_window,
-                        FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f),
-                        0);
-      mini_w->top_line = make_number (FRAME_LINES (f) - 1);
-      set_window_height (minibuf_window, 1, 0);
+      echo_area_window = minibuf_window;
 
-      XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f));
-      mini_w->total_cols = make_number (FRAME_COLS (f));
+      XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
+      XSETFASTINT (r->total_lines, FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f));
+      XSETFASTINT (r->total_cols, FRAME_COLS (f));
+      XSETFASTINT (m->top_line, FRAME_LINES (f) - 1);
+      XSETFASTINT (m->total_lines, 1);
+      XSETFASTINT (m->total_cols, FRAME_COLS (f));
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
index c307cc3..3d74ead 100644 (file)
@@ -1227,7 +1227,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     }
 #else /* not USE_X_TOOLKIT && not USE_GTK */
   FRAME_MENU_BAR_LINES (f) = nlines;
-  change_window_heights (f->root_window, nlines - olines);
+  resize_frame_windows (f, FRAME_LINES (f), 0);
 
   /* If the menu bar height gets changed, the internal border below
      the top margin has to be cleared.  Also, if the menu bar gets
@@ -1266,6 +1266,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     }
 #endif /* not USE_X_TOOLKIT && not USE_GTK */
   adjust_glyphs (f);
+  run_window_configuration_change_hook (f);
 }
 
 
@@ -1326,7 +1327,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     }
 
   FRAME_TOOL_BAR_LINES (f) = nlines;
-  change_window_heights (root_window, delta);
+  resize_frame_windows (f, FRAME_LINES (f), 0);
   adjust_glyphs (f);
 
   /* We also have to make sure that the internal border at the top of
@@ -1362,6 +1363,9 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
       if (WINDOWP (f->tool_bar_window))
        clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
     }
+
+    run_window_configuration_change_hook (f);
+
 }