emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r104562: Window configuration, balanc


From: martin rudalics
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r104562: Window configuration, balancing and fit-to-buffer rewrites.
Date: Sat, 11 Jun 2011 16:06:16 +0200
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 104562
committer: martin rudalics <address@hidden>
branch nick: trunk
timestamp: Sat 2011-06-11 16:06:16 +0200
message:
  Window configuration, balancing and fit-to-buffer rewrites.
  
  * window.c (delete_deletable_window): Re-add.
  (Fset_window_configuration): Rewrite to handle dead buffers and
  consequently deletable windows.
  (window_tree, Fwindow_tree): Remove.  Supply functionality in
  window.el.
  (compare_window_configurations): Simplify code.
  
  * window.el (window-tree-1, window-tree): New functions, moving
  the latter to window.el.
  (bw-get-tree, bw-get-tree-1, bw-find-tree-sub)
  (bw-find-tree-sub-1, bw-l, bw-t, bw-r, bw-b, bw-dir, bw-eqdir)
  (bw-refresh-edges): Remove.
  (balance-windows-1, balance-windows-2): New functions.
  (balance-windows): Rewrite in terms of window tree functions,
  balance-windows-1 and balance-windows-2.
  (bw-adjust-window): Remove.
  (balance-windows-area-adjust): New function with functionality of
  bw-adjust-window but using resize-window.
  (set-window-text-height): Rewrite doc-string.  Use
  normalize-live-window and resize-window.
  (enlarge-window-horizontally, shrink-window-horizontally): Rename
  argument to DELTA.
  (window-buffer-height): New function.
  (fit-window-to-buffer, shrink-window-if-larger-than-buffer):
  Rewrite using new window resize routines.
  (kill-buffer-and-window, mouse-autoselect-window-select): Use
  ignore-errors instead of condition-case.
  (quit-window): Call delete-frame instead of delete-windows-on
  for the only buffer on frame.
modified:
  lisp/ChangeLog
  lisp/window.el
  src/ChangeLog
  src/window.c
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2011-06-11 09:50:37 +0000
+++ b/lisp/ChangeLog    2011-06-11 14:06:16 +0000
@@ -1,3 +1,28 @@
+2011-06-11  Martin Rudalics  <address@hidden>
+
+       * window.el (window-tree-1, window-tree): New functions, moving
+       the latter to window.el.
+       (bw-get-tree, bw-get-tree-1, bw-find-tree-sub)
+       (bw-find-tree-sub-1, bw-l, bw-t, bw-r, bw-b, bw-dir, bw-eqdir)
+       (bw-refresh-edges): Remove.
+       (balance-windows-1, balance-windows-2): New functions.
+       (balance-windows): Rewrite in terms of window tree functions,
+       balance-windows-1 and balance-windows-2.
+       (bw-adjust-window): Remove.
+       (balance-windows-area-adjust): New function with functionality of
+       bw-adjust-window but using resize-window.
+       (set-window-text-height): Rewrite doc-string.  Use
+       normalize-live-window and resize-window.
+       (enlarge-window-horizontally, shrink-window-horizontally): Rename
+       argument to DELTA.
+       (window-buffer-height): New function.
+       (fit-window-to-buffer, shrink-window-if-larger-than-buffer):
+       Rewrite using new window resize routines.
+       (kill-buffer-and-window, mouse-autoselect-window-select): Use
+       ignore-errors instead of condition-case.
+       (quit-window): Call delete-frame instead of delete-windows-on
+       for the only buffer on frame.
+
 2011-06-10  Martin Rudalics  <address@hidden>
 
        * loadup.el (top-level): Load window before files for the sake

=== modified file 'lisp/window.el'
--- a/lisp/window.el    2011-06-11 09:50:37 +0000
+++ b/lisp/window.el    2011-06-11 14:06:16 +0000
@@ -2077,6 +2077,47 @@
 (defsubst frame-root-window-p (window)
   "Return non-nil if WINDOW is the root window of its frame."
   (eq window (frame-root-window window)))
+
+(defun window-tree-1 (window &optional next)
+  "Return window tree rooted at WINDOW.
+Optional argument NEXT non-nil means include windows right
+siblings in the return value.
+
+See the documentation of `window-tree' for a description of the
+return value."
+  (let (list)
+    (while window
+      (setq list
+           (cons
+            (cond
+             ((window-vchild window)
+              (cons t (cons (window-edges window)
+                            (window-tree-1 (window-vchild window) t))))
+             ((window-hchild window)
+              (cons nil (cons (window-edges window)
+                              (window-tree-1 (window-hchild window) t))))
+             (t window))
+            list))
+      (setq window (when next (window-next window))))
+    (nreverse list)))
+
+(defun window-tree (&optional frame)
+  "Return the window tree of frame FRAME.
+FRAME must be a live frame and defaults to the selected frame.
+The return value is a list of the form (ROOT MINI), where ROOT
+represents the window tree of the frame's root window, and MINI
+is the frame's minibuffer window.
+
+If the root window is not split, ROOT is the root window itself.
+Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil
+for a horizontal split, and t for a vertical split.  EDGES gives
+the combined size and position of the subwindows in the split,
+and the rest of the elements are the subwindows in the split.
+Each of the subwindows may again be a window or a list
+representing a window split, and so on.  EDGES is a list \(LEFT
+TOP RIGHT BOTTOM) as returned by `window-edges'."
+  (setq frame (normalize-live-frame frame))
+  (window-tree-1 (frame-root-window frame) t))
 
 (defun other-window (count &optional all-frames)
   "Select another window in cyclic ordering of windows.
@@ -3184,201 +3225,125 @@
 
 (defalias 'split-window-horizontally 'split-window-side-by-side)
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; `balance-windows' subroutines using `window-tree'
-
-;;; Translate from internal window tree format
-
-(defun bw-get-tree (&optional window-or-frame)
-  "Get a window split tree in our format.
-
-WINDOW-OR-FRAME must be nil, a frame, or a window.  If it is nil,
-then the whole window split tree for `selected-frame' is returned.
-If it is a frame, then this is used instead.  If it is a window,
-then the smallest tree containing that window is returned."
-  (when window-or-frame
-    (unless (or (framep window-or-frame)
-                (windowp window-or-frame))
-      (error "Not a frame or window: %s" window-or-frame)))
-  (let ((subtree (bw-find-tree-sub window-or-frame)))
-    (when subtree
-      (if (integerp subtree)
-         nil
-       (bw-get-tree-1 subtree)))))
-
-(defun bw-get-tree-1 (split)
-  (if (windowp split)
-      split
-    (let ((dir (car split))
-          (edges (car (cdr split)))
-          (childs (cdr (cdr split))))
-      (list
-       (cons 'dir (if dir 'ver 'hor))
-       (cons 'b (nth 3 edges))
-       (cons 'r (nth 2 edges))
-       (cons 't (nth 1 edges))
-       (cons 'l (nth 0 edges))
-       (cons 'childs (mapcar #'bw-get-tree-1 childs))))))
-
-(defun bw-find-tree-sub (window-or-frame &optional get-parent)
-  (let* ((window (when (windowp window-or-frame) window-or-frame))
-         (frame (when (windowp window) (window-frame window)))
-         (wt (car (window-tree frame))))
-    (when (< 1 (length (window-list frame 0)))
-      (if window
-          (bw-find-tree-sub-1 wt window get-parent)
-        wt))))
-
-(defun bw-find-tree-sub-1 (tree win &optional get-parent)
-  (unless (windowp win) (error "Not a window: %s" win))
-  (if (memq win tree)
-      (if get-parent
-          get-parent
-        tree)
-    (let ((childs (cdr (cdr tree)))
-          child
-          subtree)
-      (while (and childs (not subtree))
-        (setq child (car childs))
-        (setq childs (cdr childs))
-        (when (and child (listp child))
-          (setq subtree (bw-find-tree-sub-1 child win get-parent))))
-      (if (integerp subtree)
-          (progn
-            (if (= 1 subtree)
-                tree
-              (1- subtree)))
-        subtree
-        ))))
-
-;;; Window or object edges
-
-(defun bw-l (obj)
-  "Left edge of OBJ."
-  (if (windowp obj) (nth 0 (window-edges obj)) (cdr (assq 'l obj))))
-(defun bw-t (obj)
-  "Top edge of OBJ."
-  (if (windowp obj) (nth 1 (window-edges obj)) (cdr (assq 't obj))))
-(defun bw-r (obj)
-  "Right edge of OBJ."
-  (if (windowp obj) (nth 2 (window-edges obj)) (cdr (assq 'r obj))))
-(defun bw-b (obj)
-  "Bottom edge of OBJ."
-  (if (windowp obj) (nth 3 (window-edges obj)) (cdr (assq 'b obj))))
-
-;;; Split directions
-
-(defun bw-dir (obj)
-  "Return window split tree direction if OBJ.
-If OBJ is a window return 'both.  If it is a window split tree
-then return its direction."
-  (if (symbolp obj)
-      obj
-    (if (windowp obj)
-        'both
-      (let ((dir (cdr (assq 'dir obj))))
-        (unless (memq dir '(hor ver both))
-          (error "Can't find dir in %s" obj))
-        dir))))
-
-(defun bw-eqdir (obj1 obj2)
-  "Return t if window split tree directions are equal.
-OBJ1 and OBJ2 should be either windows or window split trees in
-our format.  The directions returned by `bw-dir' are compared and
-t is returned if they are `eq' or one of them is 'both."
-  (let ((dir1 (bw-dir obj1))
-        (dir2 (bw-dir obj2)))
-    (or (eq dir1 dir2)
-        (eq dir1 'both)
-        (eq dir2 'both))))
-
-;;; Building split tree
-
-(defun bw-refresh-edges (obj)
-  "Refresh the edge information of OBJ and return OBJ."
-  (unless (windowp obj)
-    (let ((childs (cdr (assq 'childs obj)))
-          (ol 1000)
-          (ot 1000)
-          (or -1)
-          (ob -1))
-      (dolist (o childs)
-        (when (> ol (bw-l o)) (setq ol (bw-l o)))
-        (when (> ot (bw-t o)) (setq ot (bw-t o)))
-        (when (< or (bw-r o)) (setq or (bw-r o)))
-        (when (< ob (bw-b o)) (setq ob (bw-b o))))
-      (setq obj (delq 'l obj))
-      (setq obj (delq 't obj))
-      (setq obj (delq 'r obj))
-      (setq obj (delq 'b obj))
-      (add-to-list 'obj (cons 'l ol))
-      (add-to-list 'obj (cons 't ot))
-      (add-to-list 'obj (cons 'r or))
-      (add-to-list 'obj (cons 'b ob))
-      ))
-  obj)
-
-;;; Balance windows
+;;; Balancing windows.
+
+;; The following routine uses the recycled code from an old version of
+;; `resize-subwindows'.  It's not very pretty, but coding it the way the
+;; new `resize-subwindows' code does would hardly make it any shorter or
+;; more readable (FWIW we'd need three loops - one to calculate the
+;; minimum sizes per window, one to enlarge or shrink windows until the
+;; new parent-size matches, and one where we shrink the largest/enlarge
+;; the smallest window).
+(defun balance-windows-2 (window horizontal)
+  "Subroutine of `balance-windows-1'.
+WINDOW must be an iso-combination."
+  (let* ((first (window-child window))
+        (sub first)
+        (number-of-children 0)
+        (parent-size (window-new-total window))
+        (total-sum parent-size)
+        found failed size sub-total sub-delta sub-amount rest)
+    (while sub
+      (setq number-of-children (1+ number-of-children))
+      (when (window-size-fixed-p sub horizontal)
+       (setq total-sum
+             (- total-sum (window-total-size sub horizontal)))
+       (set-window-new-normal sub 'ignore))
+      (setq sub (window-right sub)))
+
+    (setq failed t)
+    (while (and failed (> number-of-children 0))
+      (setq size (/ total-sum number-of-children))
+      (setq failed nil)
+      (setq sub first)
+      (while (and sub (not failed))
+       ;; Ignore subwindows that should be ignored or are stuck.
+       (unless (resize-subwindows-skip-p sub)
+         (setq found t)
+         (setq sub-total (window-total-size sub horizontal))
+         (setq sub-delta (- size sub-total))
+         (setq sub-amount
+               (window-sizable sub sub-delta horizontal))
+         ;; Register the new total size for this subwindow.
+         (set-window-new-total sub (+ sub-total sub-amount))
+         (unless (= sub-amount sub-delta)
+           (setq total-sum (- total-sum sub-total sub-amount))
+           (setq number-of-children (1- number-of-children))
+           ;; We failed and need a new round.
+           (setq failed t)
+           (set-window-new-normal sub 'skip)))
+       (setq sub (window-right sub))))
+
+    (setq rest (% total-sum number-of-children))
+    ;; Fix rounding by trying to enlarge non-stuck windows by one line
+    ;; (column) until `rest' is zero.
+    (setq sub first)
+    (while (and sub (> rest 0))
+      (unless (resize-subwindows-skip-p window)
+       (set-window-new-total sub 1 t)
+       (setq rest (1- rest)))
+      (setq sub (window-right sub)))
+
+    ;; Fix rounding by trying to enlarge stuck windows by one line
+    ;; (column) until `rest' equals zero.
+    (setq sub first)
+    (while (and sub (> rest 0))
+      (unless (eq (window-new-normal sub) 'ignore)
+       (set-window-new-total sub 1 t)
+       (setq rest (1- rest)))
+      (setq sub (window-right sub)))
+
+    (setq sub first)
+    (while sub
+      ;; Record new normal sizes.
+      (set-window-new-normal
+       sub (/ (if (eq (window-new-normal sub) 'ignore)
+                 (window-total-size sub horizontal)
+               (window-new-total sub))
+             (float parent-size)))
+      ;; Recursively balance each subwindow's subwindows.
+      (balance-windows-1 sub horizontal)
+      (setq sub (window-right sub)))))
+
+(defun balance-windows-1 (window &optional horizontal)
+  "Subroutine of `balance-windows'."
+  (if (window-child window)
+      (let ((sub (window-child window)))
+       (if (window-iso-combined-p sub horizontal)
+           (balance-windows-2 window horizontal)
+         (let ((size (window-new-total window)))
+           (while sub
+             (set-window-new-total sub size) 
+             (balance-windows-1 sub horizontal)
+             (setq sub (window-right sub))))))))
 
 (defun balance-windows (&optional window-or-frame)
-  "Make windows the same heights or widths in window split subtrees.
-
-When called non-interactively WINDOW-OR-FRAME may be either a
-window or a frame.  It then balances the windows on the implied
-frame.  If the parameter is a window only the corresponding window
-subtree is balanced."
+  "Balance the sizes of subwindows of WINDOW-OR-FRAME.
+WINDOW-OR-FRAME is optional and defaults to the selected frame.
+If WINDOW-OR-FRAME denotes a frame, balance the sizes of all
+subwindows of that frame's root window.  If WINDOW-OR-FRAME
+denots a window, balance the sizes of all subwindows of that
+window."
   (interactive)
-  (let (
-        (wt (bw-get-tree window-or-frame))
-        (w)
-        (h)
-        (tried-sizes)
-        (last-sizes)
-        (windows (window-list nil 0)))
-    (when wt
-      (while (not (member last-sizes tried-sizes))
-        (when last-sizes (setq tried-sizes (cons last-sizes tried-sizes)))
-        (setq last-sizes (mapcar (lambda (w)
-                                   (window-edges w))
-                                 windows))
-        (when (eq 'hor (bw-dir wt))
-          (setq w (- (bw-r wt) (bw-l wt))))
-        (when (eq 'ver (bw-dir wt))
-          (setq h (- (bw-b wt) (bw-t wt))))
-        (bw-balance-sub wt w h)))))
-
-(defun bw-adjust-window (window delta horizontal)
-  "Wrapper around `adjust-window-trailing-edge' with error checking.
-Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
-  ;; `adjust-window-trailing-edge' may fail if delta is too large.
-  (while (>= (abs delta) 1)
-    (condition-case nil
-        (progn
-          (adjust-window-trailing-edge window delta horizontal)
-          (setq delta 0))
-      (error
-       ;;(message "adjust: %s" (error-message-string err))
-       (setq delta (/ delta 2))))))
-
-(defun bw-balance-sub (wt w h)
-  (setq wt (bw-refresh-edges wt))
-  (unless w (setq w (- (bw-r wt) (bw-l wt))))
-  (unless h (setq h (- (bw-b wt) (bw-t wt))))
-  (if (windowp wt)
-      (progn
-        (when w
-          (let ((dw (- w (- (bw-r wt) (bw-l wt)))))
-            (when (/= 0 dw)
-              (bw-adjust-window wt dw t))))
-        (when h
-          (let ((dh (- h (- (bw-b wt) (bw-t wt)))))
-            (when (/= 0 dh)
-              (bw-adjust-window wt dh nil)))))
-    (let* ((childs (cdr (assq 'childs wt)))
-           (cw (when w (/ w (if (bw-eqdir 'hor wt) (length childs) 1))))
-           (ch (when h (/ h (if (bw-eqdir 'ver wt) (length childs) 1)))))
-      (dolist (c childs)
-        (bw-balance-sub c cw ch)))))
+  (let* ((window
+         (cond
+          ((or (not window-or-frame)
+               (frame-live-p window-or-frame))
+           (frame-root-window window-or-frame))
+          ((or (window-live-p window-or-frame)
+               (window-child window-or-frame))
+           window-or-frame)
+          (t
+           (error "Not a window or frame %s" window-or-frame))))
+        (frame (window-frame window)))
+    ;; Balance vertically.
+    (resize-window-reset (window-frame window))
+    (balance-windows-1 window)
+    (resize-window-apply frame)
+    ;; Balance horizontally.
+    (resize-window-reset (window-frame window) t)
+    (balance-windows-1 window t)
+    (resize-window-apply frame t)))
 
 (defun window-fixed-size-p (&optional window direction)
   "Return t if WINDOW cannot be resized in DIRECTION.
@@ -3391,13 +3356,25 @@
                        '((height . width) (width . height))))))))
 
 ;;; A different solution to balance-windows.
-
 (defvar window-area-factor 1
   "Factor by which the window area should be over-estimated.
 This is used by `balance-windows-area'.
 Changing this globally has no effect.")
 (make-variable-buffer-local 'window-area-factor)
 
+(defun balance-windows-area-adjust (window delta horizontal)
+  "Wrapper around `resize-window' with error checking.
+Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
+  ;; `resize-window' may fail if delta is too large.
+  (while (>= (abs delta) 1)
+    (condition-case nil
+        (progn
+          (resize-window window delta horizontal)
+          (setq delta 0))
+      (error
+       ;;(message "adjust: %s" (error-message-string err))
+       (setq delta (/ delta 2))))))
+
 (defun balance-windows-area ()
   "Make all visible windows the same area (approximately).
 See also `window-area-factor' to change the relative size of
@@ -3459,7 +3436,9 @@
               ;; Make sure negligible differences don't accumulate to
               ;; become significant.
               (setq carry (+ carry areadiff))
-            (bw-adjust-window win diff horiz)
+           ;; This used `adjust-window-trailing-edge' before and uses
+           ;; `resize-window' now.  Error wrapping is still needed.
+           (balance-windows-area-adjust win diff horiz)
             ;; (sit-for 0.5)
             (let ((change (cons win (window-edges win))))
               ;; If the same change has been seen already for this window,
@@ -4314,13 +4293,15 @@
 
 (defun set-window-text-height (window height)
   "Set the height in lines of the text display area of WINDOW to HEIGHT.
-HEIGHT doesn't include the mode line or header line, if any, or
-any partial-height lines in the text display area.
+WINDOW must be a live window.  HEIGHT doesn't include the mode
+line or header line, if any, or any partial-height lines in the
+text display area.
 
 Note that the current implementation of this function cannot
 always set the height exactly, but attempts to be conservative,
 by allocating more lines than are actually needed in the case
 where some error may be present."
+  (setq window (normalize-live-window window))
   (let ((delta (- height (window-text-height window))))
     (unless (zerop delta)
       ;; Setting window-min-height to a value like 1 can lead to very
@@ -4328,36 +4309,21 @@
       ;; windows 1-line tall, which means that there's no more space for
       ;; the modeline.
       (let ((window-min-height (min 2 height))) ; One text line plus a 
modeline.
-       (if (and window (not (eq window (selected-window))))
-           (save-selected-window
-             (select-window window 'norecord)
-             (enlarge-window delta))
-         (enlarge-window delta))))))
+       (resize-window window delta)))))
 
-
-(defun enlarge-window-horizontally (columns)
-  "Make selected window COLUMNS wider.
+(defun enlarge-window-horizontally (delta)
+  "Make selected window DELTA columns wider.
 Interactively, if no argument is given, make selected window one
 column wider."
   (interactive "p")
-  (enlarge-window columns t))
+  (enlarge-window delta t))
 
-(defun shrink-window-horizontally (columns)
-  "Make selected window COLUMNS narrower.
+(defun shrink-window-horizontally (delta)
+  "Make selected window DELTA columns narrower.
 Interactively, if no argument is given, make selected window one
 column narrower."
   (interactive "p")
-  (shrink-window columns t))
-
-(defun window-buffer-height (window)
-  "Return the height (in screen lines) of the buffer that WINDOW is 
displaying."
-  (with-current-buffer (window-buffer window)
-    (max 1
-        (count-screen-lines (point-min) (point-max)
-                            ;; If buffer ends with a newline, ignore it when
-                            ;; counting height unless point is after it.
-                            (eobp)
-                            window))))
+  (shrink-window delta t))
 
 (defun count-screen-lines (&optional beg end count-final-newline window)
   "Return the number of screen lines in the region.
@@ -4395,80 +4361,99 @@
         (goto-char (point-min))
         (1+ (vertical-motion (buffer-size) window))))))
 
-(defun fit-window-to-buffer (&optional window max-height min-height)
+(defun window-buffer-height (window)
+  "Return the height (in screen lines) of the buffer that WINDOW is 
displaying."
+  (with-current-buffer (window-buffer window)
+    (max 1
+        (count-screen-lines (point-min) (point-max)
+                            ;; If buffer ends with a newline, ignore it when
+                            ;; counting height unless point is after it.
+                            (eobp)
+                            window))))
+
+;;; Resizing buffers to fit their contents exactly.
+(defun fit-window-to-buffer (&optional window max-height min-height override)
   "Adjust height of WINDOW to display its buffer's contents exactly.
-WINDOW defaults to the selected window.
-Optional argument MAX-HEIGHT specifies the maximum height of the
-window and defaults to the maximum permissible height of a window
-on WINDOW's frame.
-Optional argument MIN-HEIGHT specifies the minimum height of the
-window and defaults to `window-min-height'.
-Both, MAX-HEIGHT and MIN-HEIGHT are specified in lines and
-include the mode line and header line, if any.
-
-Return non-nil if height was orderly adjusted, nil otherwise.
-
-Caution: This function can delete WINDOW and/or other windows
-when their height shrinks to less than MIN-HEIGHT."
+WINDOW can be any live window and defaults to the selected one.
+
+Optional argument MAX-HEIGHT specifies the maximum height of
+WINDOW and defaults to the height of WINDOW's frame.  Optional
+argument MIN-HEIGHT specifies the minimum height of WINDOW and
+defaults to `window-min-height'.  Both, MAX-HEIGHT and MIN-HEIGHT
+are specified in lines and include the mode line and header line,
+if any.
+
+Optional argument OVERRIDE non-nil means override restrictions
+imposed by `window-min-height' and `window-min-width' on the size
+of WINDOW.
+
+Return the number of lines by which WINDOW was enlarged or
+shrunk.  If an error occurs during resizing, return nil but don't
+signal an error.
+
+Note that even if this function makes WINDOW large enough to show
+_all_ lines of its buffer you might not see the first lines when
+WINDOW was scrolled."
   (interactive)
   ;; Do all the work in WINDOW and its buffer and restore the selected
   ;; window and the current buffer when we're done.
-  (let ((old-buffer (current-buffer))
-       value)
-    (with-selected-window (or window (setq window (selected-window)))
-      (set-buffer (window-buffer))
-      ;; Use `condition-case' to handle any fixed-size windows and other
-      ;; pitfalls nearby.
-      (condition-case nil
-         (let* (;; MIN-HEIGHT must not be less than 1 and defaults to
-                ;; `window-min-height'.
-                (min-height (max (or min-height window-min-height) 1))
-                (max-window-height
-                 ;; Maximum height of any window on this frame.
-                 (min (window-height (frame-root-window)) (frame-height)))
-                ;; MAX-HEIGHT must not be larger than max-window-height and
-                ;; defaults to max-window-height.
-                (max-height
-                 (min (or max-height max-window-height) max-window-height))
-                (desired-height
-                 ;; The height necessary to show all of WINDOW's buffer,
-                 ;; constrained by MIN-HEIGHT and MAX-HEIGHT.
-                 (max
-                  (min
-                   ;; For an empty buffer `count-screen-lines' returns zero.
-                   ;; Even in that case we need one line for the cursor.
-                   (+ (max (count-screen-lines) 1)
-                      ;; For non-minibuffers count the mode line, if any.
-                      (if (and (not (window-minibuffer-p)) mode-line-format)
-                          1 0)
-                      ;; Count the header line, if any.
-                      (if header-line-format 1 0))
-                   max-height)
-                  min-height))
-                (delta
-                 ;; How much the window height has to change.
-                 (if (= (window-height) (window-height (frame-root-window)))
-                     ;; Don't try to resize a full-height window.
-                     0
-                   (- desired-height (window-height))))
-                ;; Do something reasonable so `enlarge-window' can make
-                ;; windows as small as MIN-HEIGHT.
-                (window-min-height (min min-height window-min-height)))
-           ;; Don't try to redisplay with the cursor at the end on its
-           ;; own line--that would force a scroll and spoil things.
-           (when (and (eobp) (bolp) (not (bobp)))
-             (set-window-point window (1- (window-point))))
-           ;; Adjust WINDOW's height to the nominally correct one
-           ;; (which may actually be slightly off because of variable
-           ;; height text, etc).
-           (unless (zerop delta)
-             (enlarge-window delta))
-           ;; `enlarge-window' might have deleted WINDOW, so make sure
-           ;; WINDOW's still alive for the remainder of this.
-           ;; Note: Deleting WINDOW is clearly counter-intuitive in
-           ;; this context, but we can't do much about it given the
-           ;; current semantics of `enlarge-window'.
-           (when (window-live-p window)
+  (setq window (normalize-live-window window))
+  ;; Can't resize a full height or fixed-size window.
+  (unless (or (window-size-fixed-p window) 
+             (window-full-height-p window))
+    ;; `with-selected-window' should orderly restore the current buffer.
+    (with-selected-window window
+      ;; We are in WINDOW's buffer now.
+      (let* ( ;; Adjust MIN-HEIGHT.
+            (min-height
+             (if override
+                 (window-min-size window nil window)
+               (max (or min-height window-min-height)
+                    window-safe-min-height)))
+            (max-window-height
+             (window-total-size (frame-root-window window)))
+            ;; Adjust MAX-HEIGHT.
+            (max-height
+             (if (or override (not max-height))
+                 max-window-height
+               (min max-height max-window-height)))
+            ;; Make `desired-height' the height necessary to show
+            ;; all of WINDOW's buffer, constrained by MIN-HEIGHT
+            ;; and MAX-HEIGHT.
+            (desired-height
+             (max
+              (min
+               (+ (count-screen-lines)
+                  ;; For non-minibuffers count the mode line, if any.
+                  (if (and (not (window-minibuffer-p window))
+                           mode-line-format)
+                      1
+                    0)
+                  ;; Count the header line, if any.
+                  (if header-line-format 1 0))
+               max-height)
+              min-height))
+            (desired-delta
+             (- desired-height (window-total-size window)))
+            (delta
+             (if (> desired-delta 0)
+                 (min desired-delta
+                      (window-max-delta window nil window))
+               (max desired-delta
+                    (- (window-min-delta window nil window))))))
+       ;; This `condition-case' shouldn't be necessary, but who knows?
+       (condition-case nil
+           (if (zerop delta)
+               ;; Return zero if DELTA became zero in the proces.
+               0
+             ;; Don't try to redisplay with the cursor at the end on its
+             ;; own line--that would force a scroll and spoil things.
+             (when (and (eobp) (bolp) (not (bobp)))
+               ;; It's silly to put `point' at the end of the previous
+               ;; line and so maybe force horizontal scrolling.
+               (set-window-point window (line-beginning-position 0)))
+             ;; Call `resize-window' with OVERRIDE argument equal WINDOW.
+             (resize-window window delta nil window)
              ;; Check if the last line is surely fully visible.  If
              ;; not, enlarge the window.
              (let ((end (save-excursion
@@ -4486,25 +4471,15 @@
                             (forward-line 0))
                           (point))))
                (set-window-vscroll window 0)
+               ;; This loop might in some rare pathological cases raise
+               ;; an error - another reason for the `condition-case'.
                (while (and (< desired-height max-height)
-                           (= desired-height (window-height))
+                           (= desired-height (window-total-size))
                            (not (pos-visible-in-window-p end)))
-                 (enlarge-window 1)
-                 (setq desired-height (1+ desired-height))))
-             ;; Return non-nil only if nothing "bad" happened.
-             (setq value t)))
-       (error nil)))
-    (when (buffer-live-p old-buffer)
-      (set-buffer old-buffer))
-    value))
-
-(defun window-safely-shrinkable-p (&optional window)
-  "Return t if WINDOW can be shrunk without shrinking other windows.
-WINDOW defaults to the selected window."
-  (with-selected-window (or window (selected-window))
-    (let ((edges (window-edges)))
-      (or (= (nth 2 edges) (nth 2 (window-edges (previous-window))))
-         (= (nth 0 edges) (nth 0 (window-edges (next-window))))))))
+                 (resize-window window 1 nil window)
+                 (setq desired-height (1+ desired-height)))))
+         (error (setq delta nil)))
+       delta))))
 
 (defun shrink-window-if-larger-than-buffer (&optional window)
   "Shrink height of WINDOW if its buffer doesn't need so many lines.
@@ -4512,42 +4487,28 @@
 possible, while still showing the full contents of its buffer.
 WINDOW defaults to the selected window.
 
-Do not shrink to less than `window-min-height' lines.  Do nothing
-if the buffer contains more lines than the present window height,
-or if some of the window's contents are scrolled out of view, or
-if shrinking this window would also shrink another window, or if
-the window is the only window of its frame.
+Do not shrink WINDOW to less than `window-min-height' lines.  Do
+nothing if the buffer contains more lines than the present window
+height, or if some of the window's contents are scrolled out of
+view, or if shrinking this window would also shrink another
+window, or if the window is the only window of its frame.
 
 Return non-nil if the window was shrunk, nil otherwise."
   (interactive)
-  (when (null window)
-    (setq window (selected-window)))
-  (let* ((frame (window-frame window))
-        (mini (frame-parameter frame 'minibuffer))
-        (edges (window-edges window)))
-    (if (and (not (eq window (frame-root-window frame)))
-            (window-safely-shrinkable-p window)
-            (pos-visible-in-window-p (point-min) window)
-            (not (eq mini 'only))
-            (or (not mini)
-                (let ((mini-window (minibuffer-window frame)))
-                  (or (null mini-window)
-                      (not (eq frame (window-frame mini-window)))
-                      (< (nth 3 edges)
-                         (nth 1 (window-edges mini-window)))
-                      (> (nth 1 edges)
-                         (frame-parameter frame 'menu-bar-lines))))))
-       (fit-window-to-buffer window (window-height window)))))
-
+  (setq window (normalize-live-window window))
+  ;; Make sure that WINDOW is vertically combined and `point-min' is
+  ;; visible (for whatever reason that's needed).  The remaining issues
+  ;; should be taken care of by `fit-window-to-buffer'.
+  (when (and (window-iso-combined-p window)
+            (pos-visible-in-window-p (point-min) window))
+    (fit-window-to-buffer window (window-total-size window))))
+
 (defun kill-buffer-and-window ()
   "Kill the current buffer and delete the selected window."
   (interactive)
   (let ((window-to-delete (selected-window))
        (buffer-to-kill (current-buffer))
-       (delete-window-hook (lambda ()
-                             (condition-case nil
-                                 (delete-window)
-                               (error nil)))))
+       (delete-window-hook (lambda () (ignore-errors (delete-window)))))
     (unwind-protect
        (progn
          (add-hook 'kill-buffer-hook delete-window-hook t t)
@@ -4558,10 +4519,9 @@
                (delete-window))))
       ;; If the buffer is not dead for some reason (probably because
       ;; of a `quit' signal), remove the hook again.
-      (condition-case nil
-         (with-current-buffer buffer-to-kill
-           (remove-hook 'kill-buffer-hook delete-window-hook t))
-       (error nil)))))
+      (ignore-errors
+       (with-current-buffer buffer-to-kill
+        (remove-hook 'kill-buffer-hook delete-window-hook t))))))
 
 (defun quit-window (&optional kill window)
   "Quit WINDOW and bury its buffer.
@@ -4584,10 +4544,9 @@
        ;; try to delete it.
        (let* ((window (or window (selected-window)))
               (frame (window-frame window)))
-         (if (eq window (frame-root-window frame))
-             ;; WINDOW is alone on its frame.  `delete-windows-on'
-             ;; knows how to handle that case.
-             (delete-windows-on buffer frame)
+         (if (frame-root-window-p window)
+             ;; WINDOW is alone on its frame.
+             (delete-frame frame)
            ;; There are other windows on its frame, delete WINDOW.
            (delete-window window)))
       ;; Otherwise, switch to another buffer in the selected window.
@@ -4597,7 +4556,6 @@
     (if kill
        (kill-buffer buffer)
       (bury-buffer buffer))))
-
 
 (defvar recenter-last-op nil
   "Indicates the last recenter operation performed.
@@ -4689,7 +4647,6 @@
             (move-to-window-line (round (* recenter-last-op 
(window-height))))))))))
 
 (define-key global-map [?\M-r] 'move-to-window-line-top-bottom)
-
 
 ;;; Scrolling commands.
 
@@ -4837,7 +4794,6 @@
           (end-of-buffer arg))
          (recenter '(t)))
       (select-window orig-window))))
-
 
 (defvar mouse-autoselect-window-timer nil
   "Timer used by delayed window autoselection.")
@@ -4891,62 +4847,60 @@
 If the mouse position has stabilized in a non-selected window, select
 that window.  The minibuffer window is selected only if the minibuffer is
 active.  This function is run by `mouse-autoselect-window-timer'."
-  (condition-case nil
-      (let* ((mouse-position (mouse-position))
-            (window
-             (condition-case nil
-                 (window-at (cadr mouse-position) (cddr mouse-position)
-                            (car mouse-position))
-               (error nil))))
-       (cond
-        ((or (menu-or-popup-active-p)
-             (and window
-                  (not (coordinates-in-window-p (cdr mouse-position) window))))
-         ;; A menu / popup dialog is active or the mouse is on the scroll-bar
-         ;; of WINDOW, temporarily suspend delayed autoselection.
-         (mouse-autoselect-window-start mouse-position nil t))
-        ((eq mouse-autoselect-window-state 'suspend)
-         ;; Delayed autoselection was temporarily suspended, reenable it.
-         (mouse-autoselect-window-start mouse-position))
-        ((and window (not (eq window (selected-window)))
-              (or (not (numberp mouse-autoselect-window))
-                  (and (> mouse-autoselect-window 0)
-                       ;; If `mouse-autoselect-window' is positive, select
-                       ;; window if the window is the same as before.
-                       (eq window mouse-autoselect-window-window))
-                  ;; Otherwise select window if the mouse is at the same
-                  ;; position as before.  Observe that the first test after
-                  ;; starting autoselection usually fails since the value of
-                  ;; `mouse-autoselect-window-position' recorded there is the
-                  ;; position where the mouse has entered the new window and
-                  ;; not necessarily where the mouse has stopped moving.
-                  (equal mouse-position mouse-autoselect-window-position))
-              ;; The minibuffer is a candidate window if it's active.
-              (or (not (window-minibuffer-p window))
-                  (eq window (active-minibuffer-window))))
-         ;; Mouse position has stabilized in non-selected window: Cancel
-         ;; delayed autoselection and try to select that window.
-         (mouse-autoselect-window-cancel t)
-         ;; Select window where mouse appears unless the selected window is the
-         ;; minibuffer.  Use `unread-command-events' in order to execute pre-
-         ;; and post-command hooks and trigger idle timers.  To avoid delaying
-         ;; autoselection again, set `mouse-autoselect-window-state'."
-         (unless (window-minibuffer-p (selected-window))
-           (setq mouse-autoselect-window-state 'select)
-           (setq unread-command-events
-                 (cons (list 'select-window (list window))
-                       unread-command-events))))
-        ((or (and window (eq window (selected-window)))
-             (not (numberp mouse-autoselect-window))
-             (equal mouse-position mouse-autoselect-window-position))
-         ;; Mouse position has either stabilized in the selected window or at
-         ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
-         (mouse-autoselect-window-cancel t))
-        (t
-         ;; Mouse position has not stabilized yet, resume delayed
-         ;; autoselection.
-         (mouse-autoselect-window-start mouse-position window))))
-    (error nil)))
+  (ignore-errors
+   (let* ((mouse-position (mouse-position))
+         (window
+          (ignore-errors
+           (window-at (cadr mouse-position) (cddr mouse-position)
+                      (car mouse-position)))))
+     (cond
+      ((or (menu-or-popup-active-p)
+          (and window
+               (not (coordinates-in-window-p (cdr mouse-position) window))))
+       ;; A menu / popup dialog is active or the mouse is on the scroll-bar
+       ;; of WINDOW, temporarily suspend delayed autoselection.
+       (mouse-autoselect-window-start mouse-position nil t))
+      ((eq mouse-autoselect-window-state 'suspend)
+       ;; Delayed autoselection was temporarily suspended, reenable it.
+       (mouse-autoselect-window-start mouse-position))
+      ((and window (not (eq window (selected-window)))
+           (or (not (numberp mouse-autoselect-window))
+               (and (> mouse-autoselect-window 0)
+                    ;; If `mouse-autoselect-window' is positive, select
+                    ;; window if the window is the same as before.
+                    (eq window mouse-autoselect-window-window))
+               ;; Otherwise select window if the mouse is at the same
+               ;; position as before.  Observe that the first test after
+               ;; starting autoselection usually fails since the value of
+               ;; `mouse-autoselect-window-position' recorded there is the
+               ;; position where the mouse has entered the new window and
+               ;; not necessarily where the mouse has stopped moving.
+               (equal mouse-position mouse-autoselect-window-position))
+           ;; The minibuffer is a candidate window if it's active.
+           (or (not (window-minibuffer-p window))
+               (eq window (active-minibuffer-window))))
+       ;; Mouse position has stabilized in non-selected window: Cancel
+       ;; delayed autoselection and try to select that window.
+       (mouse-autoselect-window-cancel t)
+       ;; Select window where mouse appears unless the selected window is the
+       ;; minibuffer.  Use `unread-command-events' in order to execute pre-
+       ;; and post-command hooks and trigger idle timers.  To avoid delaying
+       ;; autoselection again, set `mouse-autoselect-window-state'."
+       (unless (window-minibuffer-p (selected-window))
+        (setq mouse-autoselect-window-state 'select)
+        (setq unread-command-events
+              (cons (list 'select-window (list window))
+                    unread-command-events))))
+      ((or (and window (eq window (selected-window)))
+          (not (numberp mouse-autoselect-window))
+          (equal mouse-position mouse-autoselect-window-position))
+       ;; Mouse position has either stabilized in the selected window or at
+       ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
+       (mouse-autoselect-window-cancel t))
+      (t
+       ;; Mouse position has not stabilized yet, resume delayed
+       ;; autoselection.
+       (mouse-autoselect-window-start mouse-position window))))))
 
 (defun handle-select-window (event)
   "Handle select-window events."

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-06-11 10:11:07 +0000
+++ b/src/ChangeLog     2011-06-11 14:06:16 +0000
@@ -1,3 +1,12 @@
+2011-06-11  Martin Rudalics  <address@hidden>
+
+       * window.c (delete_deletable_window): Re-add.
+       (Fset_window_configuration): Rewrite to handle dead buffers and
+       consequently deletable windows.
+       (window_tree, Fwindow_tree): Remove.  Supply functionality in
+       window.el.
+       (compare_window_configurations): Simplify code.
+
 2011-06-11  Andreas Schwab  <address@hidden>
 
        * image.c (imagemagick_load_image): Fix type mismatch.

=== modified file 'src/window.c'
--- a/src/window.c      2011-06-11 09:50:37 +0000
+++ b/src/window.c      2011-06-11 14:06:16 +0000
@@ -1974,6 +1974,14 @@
        }
     }
 }
+
+/* If WINDOW can be deleted, delete it.  */
+static Lisp_Object
+delete_deletable_window (Lisp_Object window)
+{
+  if (!NILP (call1 (Qwindow_deletable_p, window)))
+    call1 (Qdelete_window, window);
+}
 
 /***********************************************************************
                             Window List
@@ -5388,6 +5396,7 @@
   struct Lisp_Vector *saved_windows;
   Lisp_Object new_current_buffer;
   Lisp_Object frame;
+  Lisp_Object auto_buffer_name;
   FRAME_PTR f;
   EMACS_INT old_point = -1;
 
@@ -5443,6 +5452,8 @@
      However, there is other stuff we should still try to do below.  */
   if (FRAME_LIVE_P (f))
     {
+      Lisp_Object window;
+      Lisp_Object dead_windows = Qnil;
       register struct window *w;
       register struct saved_window *p;
       struct window *root_window;
@@ -5519,7 +5530,8 @@
       for (k = 0; k < saved_windows->header.size; k++)
        {
          p = SAVED_WINDOW_N (saved_windows, k);
-         w = XWINDOW (p->window);
+         window = p->window;
+         w = XWINDOW (window);
          w->next = Qnil;
 
          if (!NILP (p->parent))
@@ -5582,55 +5594,70 @@
 
          /* Reinstall the saved buffer and pointers into it.  */
          if (NILP (p->buffer))
+           /* An internal window.  */
            w->buffer = p->buffer;
+         else if (!NILP (BVAR (XBUFFER (p->buffer), name)))
+           /* If saved buffer is alive, install it.  */
+           {
+             w->buffer = p->buffer;
+             w->start_at_line_beg = p->start_at_line_beg;
+             set_marker_restricted (w->start, p->start, w->buffer);
+             set_marker_restricted (w->pointm, p->pointm, w->buffer);
+             Fset_marker (BVAR (XBUFFER (w->buffer), mark),
+                          p->mark, w->buffer);
+
+             /* As documented in Fcurrent_window_configuration, don't
+                restore the location of point in the buffer which was
+                current when the window configuration was recorded.  */
+             if (!EQ (p->buffer, new_current_buffer)
+                 && XBUFFER (p->buffer) == current_buffer)
+               Fgoto_char (w->pointm);
+           }
+         else if (!NILP (w->buffer) && !NILP (BVAR (XBUFFER (w->buffer), 
name)))
+           /* Keep window's old buffer; make sure the markers are
+              real.  */
+           {
+             /* Set window markers at start of visible range.  */
+             if (XMARKER (w->start)->buffer == 0)
+               set_marker_restricted (w->start, make_number (0),
+                                      w->buffer);
+             if (XMARKER (w->pointm)->buffer == 0)
+               set_marker_restricted_both (w->pointm, w->buffer,
+                                           BUF_PT (XBUFFER (w->buffer)),
+                                           BUF_PT_BYTE (XBUFFER (w->buffer)));
+             w->start_at_line_beg = Qt;
+           }
+         else if (STRINGP (auto_buffer_name =
+                           Fwindow_parameter (window, Qauto_buffer_name))
+                  && SCHARS (auto_buffer_name) != 0
+                  && !NILP (w->buffer = Fget_buffer_create (auto_buffer_name)))
+           {
+             set_marker_restricted (w->start, make_number (0), w->buffer);
+             set_marker_restricted (w->pointm, make_number (0), w->buffer);
+             w->start_at_line_beg = Qt;
+           }
          else
+           /* Window has no live buffer, get one.  */
            {
-             if (!NILP (BVAR (XBUFFER (p->buffer), name)))
-               /* If saved buffer is alive, install it.  */
-               {
-                 w->buffer = p->buffer;
-                 w->start_at_line_beg = p->start_at_line_beg;
-                 set_marker_restricted (w->start, p->start, w->buffer);
-                 set_marker_restricted (w->pointm, p->pointm, w->buffer);
-                 Fset_marker (BVAR (XBUFFER (w->buffer), mark),
-                              p->mark, w->buffer);
-
-                 /* As documented in Fcurrent_window_configuration, don't
-                    restore the location of point in the buffer which was
-                    current when the window configuration was recorded.  */
-                 if (!EQ (p->buffer, new_current_buffer)
-                     && XBUFFER (p->buffer) == current_buffer)
-                   Fgoto_char (w->pointm);
-               }
-             else if (NILP (w->buffer) || NILP (BVAR (XBUFFER (w->buffer), 
name)))
-               /* Else unless window has a live buffer, get one.  */
-               {
-                 w->buffer = Fcdr (Fcar (Vbuffer_alist));
-                 /* This will set the markers to beginning of visible
-                    range.  */
-                 set_marker_restricted (w->start, make_number (0), w->buffer);
-                 set_marker_restricted (w->pointm, make_number (0),w->buffer);
-                 w->start_at_line_beg = Qt;
-               }
-             else
-               /* Keeping window's old buffer; make sure the markers
-                  are real.  */
-               {
-                 /* Set window markers at start of visible range.  */
-                 if (XMARKER (w->start)->buffer == 0)
-                   set_marker_restricted (w->start, make_number (0),
-                                          w->buffer);
-                 if (XMARKER (w->pointm)->buffer == 0)
-                   set_marker_restricted_both (w->pointm, w->buffer,
-                                               BUF_PT (XBUFFER (w->buffer)),
-                                               BUF_PT_BYTE (XBUFFER 
(w->buffer)));
-                 w->start_at_line_beg = Qt;
-               }
+             /* Get the buffer via other_buffer_safely in order to
+             avoid showing an unimportant buffer and, if necessary, to
+             recreate *scratch* in the course (part of Juanma's bs-show
+             scenario from March 2011).  */
+             w->buffer = other_buffer_safely (Fcurrent_buffer ());
+             /* This will set the markers to beginning of visible
+                range.  */
+             set_marker_restricted (w->start, make_number (0), w->buffer);
+             set_marker_restricted (w->pointm, make_number (0), w->buffer);
+             w->start_at_line_beg = Qt;
+             if (!NILP (w->dedicated))
+               /* Record this window as dead.  */
+               dead_windows = Fcons (window, dead_windows);
+             /* Make sure window is no more dedicated.  */
+             w->dedicated = Qnil;
            }
        }
 
       FRAME_ROOT_WINDOW (f) = data->root_window;
-
       /* Arrange *not* to restore point in the buffer that was
         current when the window configuration was saved.  */
       if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
@@ -5638,10 +5665,10 @@
                               make_number (old_point),
                               XWINDOW (data->current_window)->buffer);
 
-      /* In the following call to `select-window, prevent "swapping
-        out point" in the old selected window using the buffer that
-        has been restored into it.  We already swapped out that point
-        from that window's old buffer.  */
+      /* In the following call to `select-window', prevent "swapping out
+        point" in the old selected window using the buffer that has
+        been restored into it.  We already swapped out that point from
+        that window's old buffer.  */
       select_window (data->current_window, Qnil, 1);
       BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
        = selected_window;
@@ -5682,9 +5709,16 @@
        }
 
       adjust_glyphs (f);
-
       UNBLOCK_INPUT;
 
+      /* Scan dead buffer windows.  */
+      for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
+       {
+         window = XCAR (dead_windows);
+         if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
+           delete_deletable_window (window);
+       }
+
       /* Fselect_window will have made f the selected frame, so we
         reselect the proper frame here.  Fhandle_switch_frame will change the
         selected window too, but that doesn't make the call to
@@ -5930,82 +5964,6 @@
   XSETWINDOW_CONFIGURATION (tem, data);
   return (tem);
 }
-
-
-/***********************************************************************
-                           Window Split Tree
- ***********************************************************************/
-
-static Lisp_Object
-window_tree (struct window *w)
-{
-  Lisp_Object tail = Qnil;
-  Lisp_Object result = Qnil;
-
-  while (w)
-    {
-      Lisp_Object wn;
-
-      XSETWINDOW (wn, w);
-      if (!NILP (w->hchild))
-       wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
-                                window_tree (XWINDOW (w->hchild))));
-      else if (!NILP (w->vchild))
-       wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
-                              window_tree (XWINDOW (w->vchild))));
-
-      if (NILP (result))
-       {
-         result = tail = Fcons (wn, Qnil);
-       }
-      else
-       {
-         XSETCDR (tail, Fcons (wn, Qnil));
-         tail = XCDR (tail);
-       }
-
-      w = NILP (w->next) ? 0 : XWINDOW (w->next);
-    }
-
-  return result;
-}
-
-
-
-DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
-       0, 1, 0,
-       doc: /* Return the window tree for frame FRAME.
-
-The return value is a list of the form (ROOT MINI), where ROOT
-represents the window tree of the frame's root window, and MINI
-is the frame's minibuffer window.
-
-If the root window is not split, ROOT is the root window itself.
-Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
-horizontal split, and t for a vertical split, EDGES gives the combined
-size and position of the subwindows in the split, and the rest of the
-elements are the subwindows in the split.  Each of the subwindows may
-again be a window or a list representing a window split, and so on.
-EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
-
-If FRAME is nil or omitted, return information on the currently
-selected frame.  */)
-  (Lisp_Object frame)
-{
-  FRAME_PTR f;
-
-  if (NILP (frame))
-    frame = selected_frame;
-
-  CHECK_FRAME (frame);
-  f = XFRAME (frame);
-
-  if (!FRAME_LIVE_P (f))
-    return Qnil;
-
-  return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
-}
-
 
 /***********************************************************************
                            Marginal Areas
@@ -6365,116 +6323,82 @@
                            Initialization
  ***********************************************************************/
 
-/* Return 1 if window configurations C1 and C2
-   describe the same state of affairs.  This is used by Fequal.  */
+/* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
+   describe the same state of affairs.  This is used by Fequal.
+
+   ignore_positions non-zero means ignore non-matching scroll positions
+   and the like.
+
+   This ignores a couple of things like the dedicatedness status of
+   window, splits, nest and the like.  This might have to be fixed.  */
 
 int
-compare_window_configurations (Lisp_Object c1, Lisp_Object c2, int 
ignore_positions)
+compare_window_configurations (Lisp_Object configuration1, Lisp_Object 
configuration2, int ignore_positions)
 {
   register struct save_window_data *d1, *d2;
-  struct Lisp_Vector *sw1, *sw2;
+  struct Lisp_Vector *sws1, *sws2;
   int i;
 
-  CHECK_WINDOW_CONFIGURATION (c1);
-  CHECK_WINDOW_CONFIGURATION (c2);
-
-  d1 = (struct save_window_data *) XVECTOR (c1);
-  d2 = (struct save_window_data *) XVECTOR (c2);
-  sw1 = XVECTOR (d1->saved_windows);
-  sw2 = XVECTOR (d2->saved_windows);
-
-  if (d1->frame_cols != d2->frame_cols)
-    return 0;
-  if (d1->frame_lines != d2->frame_lines)
-    return 0;
-  if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
-    return 0;
-  if (! EQ (d1->selected_frame, d2->selected_frame))
-    return 0;
-  /* Don't compare the current_window field directly.
-     Instead see w1_is_current and w2_is_current, below.  */
-  if (! EQ (d1->current_buffer, d2->current_buffer))
-    return 0;
-  if (! ignore_positions)
-    {
-      if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
-       return 0;
-      if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
-       return 0;
-    }
-  /* Don't compare the root_window field.
-     We don't require the two configurations
-     to use the same window object,
-     and the two root windows must be equivalent
-     if everything else compares equal.  */
-  if (! EQ (d1->focus_frame, d2->focus_frame))
-    return 0;
-
-  /* Verify that the two confis have the same number of windows.  */
-  if (sw1->header.size != sw2->header.size)
-    return 0;
-
-  for (i = 0; i < sw1->header.size; i++)
-    {
-      struct saved_window *p1, *p2;
+  CHECK_WINDOW_CONFIGURATION (configuration1);
+  CHECK_WINDOW_CONFIGURATION (configuration2);
+
+  d1 = (struct save_window_data *) XVECTOR (configuration1);
+  d2 = (struct save_window_data *) XVECTOR (configuration2);
+  sws1 = XVECTOR (d1->saved_windows);
+  sws2 = XVECTOR (d2->saved_windows);
+
+  /* Frame settings must match.  */
+  if (d1->frame_cols != d2->frame_cols
+      || d1->frame_lines != d2->frame_lines
+      || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
+      || !EQ (d1->selected_frame, d2->selected_frame)
+      || !EQ (d1->current_buffer, d2->current_buffer)
+      || (!ignore_positions
+         && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
+             || !EQ (d1->minibuf_selected_window, 
d2->minibuf_selected_window)))
+      || !EQ (d1->focus_frame, d2->focus_frame)
+      /* Verify that the two configurations have the same number of windows.  
*/
+      || sws1->header.size != sws2->header.size)
+    return 0;
+
+  for (i = 0; i < sws1->header.size; i++)
+    {
+      struct saved_window *sw1, *sw2;
       int w1_is_current, w2_is_current;
 
-      p1 = SAVED_WINDOW_N (sw1, i);
-      p2 = SAVED_WINDOW_N (sw2, i);
-
-      /* Verify that the current windows in the two
-        configurations correspond to each other.  */
-      w1_is_current = EQ (d1->current_window, p1->window);
-      w2_is_current = EQ (d2->current_window, p2->window);
-
-      if (w1_is_current != w2_is_current)
-       return 0;
-
-      /* Verify that the corresponding windows do match.  */
-      if (! EQ (p1->buffer, p2->buffer))
-       return 0;
-      if (! EQ (p1->left_col, p2->left_col))
-       return 0;
-      if (! EQ (p1->top_line, p2->top_line))
-       return 0;
-      if (! EQ (p1->total_cols, p2->total_cols))
-       return 0;
-      if (! EQ (p1->total_lines, p2->total_lines))
-       return 0;
-      if (! EQ (p1->display_table, p2->display_table))
-       return 0;
-      if (! EQ (p1->parent, p2->parent))
-       return 0;
-      if (! EQ (p1->prev, p2->prev))
-       return 0;
-      if (! ignore_positions)
-       {
-         if (! EQ (p1->hscroll, p2->hscroll))
-           return 0;
-         if (!EQ (p1->min_hscroll, p2->min_hscroll))
-           return 0;
-         if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
-           return 0;
-         if (NILP (Fequal (p1->start, p2->start)))
-           return 0;
-         if (NILP (Fequal (p1->pointm, p2->pointm)))
-           return 0;
-         if (NILP (Fequal (p1->mark, p2->mark)))
-           return 0;
-       }
-      if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
-       return 0;
-      if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
-       return 0;
-      if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
-       return 0;
-      if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
-       return 0;
-      if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
-       return 0;
-      if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
-       return 0;
-      if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
+      sw1 = SAVED_WINDOW_N (sws1, i);
+      sw2 = SAVED_WINDOW_N (sws2, i);
+
+      if (
+          /* The "current" windows in the two configurations must
+             correspond to each other.  */
+         EQ (d1->current_window, sw1->window)
+         != EQ (d2->current_window, sw2->window)
+         /* Windows' buffers must match.  */
+         || !EQ (sw1->buffer, sw2->buffer)
+         || !EQ (sw1->left_col, sw2->left_col)
+         || !EQ (sw1->top_line, sw2->top_line)
+         || !EQ (sw1->total_cols, sw2->total_cols)
+         || !EQ (sw1->total_lines, sw2->total_lines)
+         || !EQ (sw1->display_table, sw2->display_table)
+         /* The next two disjuncts check the window structure for
+            equality.  */
+         || !EQ (sw1->parent, sw2->parent)
+         || !EQ (sw1->prev, sw2->prev)
+         || (!ignore_positions
+             && (!EQ (sw1->hscroll, sw2->hscroll)
+                 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
+                 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
+                 || NILP (Fequal (sw1->start, sw2->start))
+                 || NILP (Fequal (sw1->pointm, sw2->pointm))
+                 || NILP (Fequal (sw1->mark, sw2->mark))))
+         || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
+         || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
+         || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
+         || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
+         || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
+         || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
+         || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
        return 0;
     }
 
@@ -6768,7 +6692,6 @@
   defsubr (&Swindow_configuration_frame);
   defsubr (&Sset_window_configuration);
   defsubr (&Scurrent_window_configuration);
-  defsubr (&Swindow_tree);
   defsubr (&Sset_window_margins);
   defsubr (&Swindow_margins);
   defsubr (&Sset_window_fringes);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]