]> git.eshelyaron.com Git - emacs.git/commitdiff
Revise window splitting/nesting. Fix errors reported by Juanma.
authorMartin Rudalics <rudalics@gmx.at>
Sun, 10 Apr 2011 12:38:11 +0000 (14:38 +0200)
committerMartin Rudalics <rudalics@gmx.at>
Sun, 10 Apr 2011 12:38:11 +0000 (14:38 +0200)
* lisp.h: Extern other_buffer_safely.

* buffer.c: New symbol Qbuffer_list_update_hook.
(Fget_buffer_create, Fmake_indirect_buffer, Frename_buffer)
(Fkill_buffer, record_buffer): Run buffer-list-update-hook.
(other_buffer_safely): New function.
(Frecord_buffer): Mention return value in doc-string.
(Funrecord_buffer): Mention return value in doc-string.  Run
buffer-list-update-hook.
(syms_of_buffer): Define Vbuffer_list_update_hook.

* window.h (window): New slot nest.

* window.c: Remove Qsafe, Qabove, Qbelow.  Add Qauto_buffer_name.
(select_window): Restore version from Emacs 23 to avoid
clobbering the current buffer when the selected window is
selected.  Reported by Juanma Barranquero.
(Fwindow_nested, Fset_window_nested): Remove.
(Fwindow_splits, Fset_window_splits, Fwindow_nest)
(Fset_window_nest): New functions.
(recombine_windows): Use ->nest instead of ->nested.
(window_loop): Call other_buffer_safely
(Fdelete_other_windows_internal): Reset splits status of
remaining window.
(make_parent_window, make_window): Initialize splits and nest
status.
(Fsplit_window_internal): Handle splits and nest status.
(Fdelete_window_internal): Remove bflag.  Handle nest status.
(saved_window): Add slots for splits and nest status.
(Fset_window_configuration): Handle auto_buffer_name.  Handle
splits and nest status.  Reorder code.
(save_window_save): Handle splits and nest status.
(syms_of_window): Rewrite doc-string of window-splits.  New
variable window-nest.

* window.el (resize-window): With window-splits nil resize
either left or right sibling to behave more like Emacs 23.
Reported by Juanma Barranquero.
(delete-window, split-window): Simplify code and adapt to new
window-splits/window-nest semantics.
(window-state-get-1, window-state-put-1, window-state-put-2)
(display-buffer-split-window-1)
(display-buffer-split-atom-window): Adapt to new
window-splits/window-nest semantics.
(display-buffer-macro-specifiers, display-buffer-alist): Replace other-visible-frame
by other-frame.
(display-buffer-pop-up-window)
(display-buffer-pop-up-side-window): Reset new window's previous
buffers to nil to avoid that we switch back to the buffer from
the split window when quitting the window.

* menu-bar.el (kill-this-buffer, kill-this-buffer-enabled-p): Do
not offer to kill a buffer when we can't reliably kill it.

* help.el (help-window-display-message): Improve message shown.

* cus-start.el (all): Add entry for window-nest, rework that of
window-splits.

* buff-menu.el (Buffer-menu-select): Bind window-splits to t.

* windows.texi (Splitting Windows): Explain window-splits and
window-nest.
(Displaying Buffers): Replace other-visible-frame by other-frame.

13 files changed:
doc/lispref/ChangeLog
doc/lispref/windows.texi
lisp/ChangeLog
lisp/buff-menu.el
lisp/cus-start.el
lisp/help.el
lisp/menu-bar.el
lisp/window.el
src/ChangeLog
src/buffer.c
src/lisp.h
src/window.c
src/window.h

index 649f078d6e1205b78a74bf9806e5c8565efce704..71a5ce2b7de8a3811a376227b7f21529c82958a2 100644 (file)
@@ -1,3 +1,9 @@
+2011-04-09  Martin Rudalics  <rudalics@gmx.at>
+
+       * windows.texi (Splitting Windows): Explain window-splits and
+       window-nest.
+       (Displaying Buffers): Replace other-visible-frame by other-frame.
+
 2011-02-24  Martin Rudalics  <rudalics@gmx.at>
 
        * windows.texi (Window Configurations): Fix typo.
index d1602213d7a740eda77c0af5c298c3f0c3c65684..6e4d08751ad4e41808218e7ed6c95a52608645d8 100644 (file)
@@ -1276,40 +1276,97 @@ Evaluating now @code{(split-window W4 -3)} or, for example,
 @code{(split-window (window-parent W6) -3)} should produce the desired
 configuration.
 
-  The following option affects the behavior of a number of functions
-operating on a window that is part of a window combination, see
-@ref{Windows and Frames}.
+  The following two option can be used to tune the operation of
+@code{split-window}.
 
 @defopt window-splits
+If this variable is nil, the function @code{split-window} can split a
+window if and only if that window's screen estate is sufficiently large
+to accomodate both itself and the new window.
+
+If this variable is non-@code{nil}, @code{split-window} tries to resize
+all windows belonging to the same combination as the old window in order
+to accomodate the new window.  Hence, the new window can be also created
+if the old window is otherwise too small to split.
+
+In any case, the value of this variable is assigned to the splits status
+of the new window and, provided old and new window form a new
+combination, of the old window as well.  The splits status of a window
+can be retrieved by invoking the function @code{window-splits} and
+altered by the function @code{set-window-splits}, see below.
+
+If @code{window-nest} (see below) is non-@code{nil}, the space for the
+new window is exclusively taken from the old window, but the splits
+status of any involved window is nevertheless set as descibed above.
+@end defopt
+
+@defopt window-nest
 If this variable is @code{nil}, @code{split-window} creates a new parent
-window if and only if either @var{window} has no parent window or
-@var{window} shall be split in another direction than the combination
-@var{window} is part of.  Moreover, @code{resize-window} tries to resize
-@var{window}'s right sibling first and @code{delete-window} preferably
-returns space to @var{window}'s left sibling.
-
-   If this variable equals @code{nest}, @code{split-window} always
-creates a new parent window.  As a consequence, any frame's window tree
-is a binary tree and every window has at most one (left or right)
-sibling.  Also, @code{resize-window} preferably resizes @var{window}'s
-sibling and @code{delete-window} preferably returns space to
-@var{window}'s sibling.  Functions that create atomic windows
-(@pxref{Atomic Windows}) bind this variable temporarily to @code{nest}
-in order to make sure that subwindows stay glued together.
-
-   If this variable equals @code{resize}, @code{split-window} tries to
-resize all windows belonging to the same combination as @var{window} to
-accomodate the new window.  Hence, the new window can be also created if
-@var{window} is too small to be split.  Resizing or deleting any window
-of a combination tries to distribute space proportionally among all
-other windows of the combination.
-
-   As a rule, application should not bind this variable to any value but
-@code{nest}.  Occasionally, it might make sense to bind this variable to
-@code{resize}, for example, when showing a large number of buffers
-simultaneously on the same frame.
+window if and only if the old window has no parent window or shall be
+split orthogonally to the combination it is part of.  If this variable
+is non-@code{nil}, @code{split-window} always creates a new parent
+window.  If this variable is always non-@code{nil}, a frame's window
+tree is a binary tree so every window but the frame's root window has
+exactly one sibling.
+
+The value of this variable is also assigned to the nest status of the
+new parent window.  The nest status of any window can be retrieved via
+the function @code{window-nest} and altered by the function
+@code{set-window-nest}, see below.
 @end defopt
 
+@defun window-splits &optional window
+This function returns the splits status of @var{window}.  The argument
+@var{window} can be any window and defaults to the selected one.
+
+@cindex splits status
+The @dfn{splits status} of a window specifies how resizing and deleting
+that window may affect the size of other windows in the same window
+combination.  The splits status is initially set by @code{split-window}
+to the current value of the variable @code{window-splits} (see above)
+and can be reset by the function @code{set-window-splits} (see below).
+
+More precisely, if @var{window}'s splits status is @code{nil} and
+@var{window} is resized, the corresponding space is preferably taken
+from (or given to) @var{window}'s right sibling.  When @var{window} is
+deleted, its space is given to its left sibling.  If @var{window}'s
+splits status is non-@code{nil}, resizing and deleting @var{window} may
+resize all windows in @var{window}'s combination.
+@end defun
+
+@defun set-window-splits window &optional status
+This function sets the splits status (see above) of @var{window} to
+@var{status}.  The argument @var{window} can be any window and defaults
+to the selected one.  The return value is @var{status}.
+@end defun
+
+@defun window-nest &optional window
+This function returns the nest status of @var{window}.  The argument
+@var{window} can be any window and defaults to the selected one.  Note,
+however, that the nest status is currently meaningful for internal
+windows only.
+
+@cindex nest status
+The @dfn{nest status} of a window secifies whether that window may be
+removed and its subwindows recombined with that window's siblings when
+such a sibling's subwindow is deleted.  The nest status is initially
+assigned by @code{split-window} to the current value of the variable
+@code{window-nest} (see above) and can be reset by the function
+@code{set-window-nest} (see below).
+
+If the return value is @code{nil}, subwindows of @var{window} may be
+recombined with @var{window}'s siblings when a window gets deleted.  A
+return value of @code{nil} means that subwindows of @var{window} are
+never (re-)combined with @var{window}'s siblings in such a case.
+@end defun
+
+@defun set-window-nest window &optional status
+This functions sets the nest status (see above) of @var{window} to
+@var{status}.  The argument @var{window} can be any window and defaults
+to the selected one.  Note that setting the nest status is meaningful
+for internal windows only.  The return value is @var{status}.
+@end defun
+
 @deffn Command split-window-vertically &optional size
 This function splits the selected window into two windows, one above the
 other, leaving the upper of the two windows selected, with @var{size}
@@ -2350,8 +2407,8 @@ provided:
 selected frame with exception of the selected window.
 
 @item
-@code{other-visible-frame} to make sure the window appears on any
-visible frame but the selected one.
+@code{other-frame} to make sure the window appears on any visible frame
+but the selected one.
 
 @item
 @code{default} to use the specifier of the default value of
index 4de9272d9017977de575e2b58bd733dd6cf10b6f..70929780a9762c80bfed895671591fc574dd43bf 100644 (file)
@@ -1,3 +1,31 @@
+2011-04-09  Martin Rudalics  <rudalics@gmx.at>
+
+       * window.el (resize-window): With window-splits nil resize
+       either left or right sibling to behave more like Emacs 23.
+       Reported by Juanma Barranquero.
+       (delete-window, split-window): Simplify code and adapt to new
+       window-splits/window-nest semantics.
+       (window-state-get-1, window-state-put-1, window-state-put-2)
+       (display-buffer-split-window-1)
+       (display-buffer-split-atom-window): Adapt to new
+       window-splits/window-nest semantics.
+       (display-buffer-macro-specifiers, display-buffer-alist): Replace other-visible-frame
+       by other-frame.
+       (display-buffer-pop-up-window)
+       (display-buffer-pop-up-side-window): Reset new window's previous
+       buffers to nil to avoid that we switch back to the buffer from
+       the split window when quitting the window.
+
+       * menu-bar.el (kill-this-buffer, kill-this-buffer-enabled-p): Do
+       not offer to kill a buffer when we can't reliably kill it.
+
+       * help.el (help-window-display-message): Improve message shown.
+
+       * cus-start.el (all): Add entry for window-nest, rework that of
+       window-splits.
+
+       * buff-menu.el (Buffer-menu-select): Bind window-splits to t.
+
 2011-02-24  Glenn Morris  <rgm@gnu.org>
 
        * files-x.el (modify-dir-local-variable): Handle dir-locals from
index 05f3a073bf50cd04e1a5c7f3fcbe0cf6c26b8f62..a6065907054715e4f91b8f2aca05184559e329a2 100644 (file)
@@ -491,8 +491,7 @@ in the selected frame."
     (unless (eq menu buff)
       (bury-buffer menu))
     (when others
-      ;; Never rebind `window-splits' to anything but 'binary ...
-      (let ((window-splits 'resize)
+      (let ((window-splits t)
            (window buff-window)
            other)
        (while (and window others)
index c3e4d899e00138837f46c12460e38df4a3ef3ed2..ce82eef00ae2bb85a3d2cd5f5115523778377472 100644 (file)
@@ -392,11 +392,8 @@ since it could result in memory overflow and make Emacs crash."
                       (const :tag "Never (nil)" :value nil)
                       (const :tag "Only on ttys" :value tty)
                       (other :tag "Always" t)) "23.1")
-            (window-splits
-             windows (choice
-                      (const :tag "Standard" :value nil)
-                      (const :tag "Nest" :value nest)
-                      (const :tag "Resize" :value resize)) "24.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 a5bf93166edb0657ec1e6310f3ef2e84048d0717..5c952f83aca68e67e626aa80611e1711b1e70527 100644 (file)
@@ -1024,10 +1024,14 @@ SCROLL equal `other' means tell how to scroll the \"other\"
 window."
   (let ((scroll-part
         (cond
+         ;; If we don't have QUIT-PART we probably reuse a window
+         ;; showing the same buffer so we don't show any message.
+         ((not quit-part) nil)
          ((pos-visible-in-window-p
            (with-current-buffer (window-buffer window)
-             (point-max)) window)
-          ;; Buffer end is visible.
+             (point-max)) window t)
+          ;; Buffer end is at least partially visible, no need to talk
+          ;; about scrolling.
           ".")
          ((eq scroll 'other)
           ", \\[scroll-other-window] to scroll help.")
index 8a33381b618ddf8450ecac688eb1cebdfe0d5098..41b18f8b66f5298080b9e8ae5df9fba907027e8a 100644 (file)
 
 (defvar menu-bar-edit-menu
   (let ((menu (make-sparse-keymap "Edit")))
-    
+
     (define-key menu [props]
       `(menu-item ,(purecopy "Text Properties") facemenu-menu))
 
@@ -1634,7 +1634,7 @@ key, a click, or a menu-item")))
 
 (defvar menu-bar-search-documentation-menu
   (let ((menu (make-sparse-keymap "Search Documentation")))
-    
+
     (define-key menu [search-documentation-strings]
       `(menu-item ,(purecopy "Search Documentation Strings...") apropos-documentation
                   :help
@@ -1818,19 +1818,21 @@ for the definition of the menu frame."
 When called in the minibuffer, get out of the minibuffer
 using `abort-recursive-edit'."
   (interactive)
-  (if (menu-bar-non-minibuffer-window-p)
-      (kill-buffer (current-buffer))
-    (abort-recursive-edit)))
+  (cond
+   ((not (menu-bar-menu-frame-live-and-visible-p)))
+   ((menu-bar-non-minibuffer-window-p)
+    (kill-buffer))
+   (t (abort-recursive-edit))))
 
 (defun kill-this-buffer-enabled-p ()
-  (let ((count 0)
-       (buffers (buffer-list)))
-    (while buffers
-      (or (string-match "^ " (buffer-name (car buffers)))
-         (setq count (1+ count)))
-      (setq buffers (cdr buffers)))
-    (or (not (menu-bar-non-minibuffer-window-p))
-       (> count 1))))
+  (or (not (menu-bar-non-minibuffer-window-p))
+      (let (found-1)
+       (catch 'found-2
+         (dolist (buffer (buffer-list))
+           (unless (string-match-p "^ " (buffer-name buffer))
+             (if (not found-1)
+                 (setq found-1 t)
+               (throw 'found-2 t))))))))
 
 (put 'dired 'menu-enable '(menu-bar-non-minibuffer-window-p))
 
index e4b3c6174c138a2d638cd2c8b245bad6d031051e..20f7c09af2cda69304b7d95363a90c8a56df268b 100644 (file)
@@ -1586,7 +1586,7 @@ edge of WINDOW consider using `adjust-window-trailing-edge'
 instead."
   (setq window (normalize-any-window window))
   (let* ((frame (window-frame window))
-        right)
+        sibling)
     (cond
      ((eq window (frame-root-window frame))
       (error "Cannot resize root window of frame"))
@@ -1595,25 +1595,20 @@ instead."
      ((window-resizable-p window delta horizontal ignore)
       (resize-window-reset frame horizontal)
       (resize-this-window window delta horizontal ignore t)
-      (if (and (not (eq window-splits 'resize))
+      (if (and (not (window-splits window))
               (window-iso-combined-p window horizontal)
-              (setq right (window-right window))
-              (or (window-size-ignore window ignore)
-                  (not (window-size-fixed-p right)))
-              (or (< delta 0)
-                  (> (- (window-total-size right horizontal)
-                        (window-min-size right horizontal))
-                     delta)))
-         ;; Resize window below/on the right of WINDOW - this is the
-         ;; classic Emacs behavior, so retain it for `window-splits'
-         ;; not 'resize, iso-combined windows.  It's a PITA, though.
+              (setq sibling (or (window-right window) (window-left window)))
+              (window-sizable-p sibling (- delta) horizontal ignore))
+         ;; Resize WINDOW's neighbor, preferably the one on the right,
+         ;; since up to Emacs 23 it was handled this way.
          (let ((parent-size
                 (window-total-size (window-parent window) horizontal)))
-           (resize-this-window right (- delta) horizontal nil t)
+           (resize-this-window sibling (- delta) horizontal nil t)
            (resize-window-normal
             window (/ (float (window-new-total-size window)) parent-size))
            (resize-window-normal
-            right (/ (float (window-new-total-size right)) parent-size)))
+            sibling (/ (float (window-new-total-size sibling)) parent-size)))
+       ;; Resize all other windows in the same combination.
        (resize-other-windows window delta horizontal ignore))
       (resize-window-apply frame horizontal))
      (t
@@ -2426,45 +2421,23 @@ non-side window, signal an error."
             (size (window-total-size window horizontal))
             (frame-selected
              (window-or-subwindow-p (frame-selected-window frame) window))
-            ;; LEFT is WINDOW's _left_ sibling - traditionally LEFT
-            ;; gets enlarged and is selected after the deletion.
-            (left (window-left window))
-            ;; RIGHT is WINDOW's right sibling.
-            (right (window-right window))
-            ;; SIBLING is WINDOW's sibling provided they are the only
-            ;; child windows of PARENT.
-            (sibling
-             (or (and left (not right) (not (window-left left)) left)
-                 (and right (not left) (not (window-right right)) right))))
+            ;; 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
-        ((or (and (eq window-splits 'nest)
-                  (or (and left (not (window-left left))
-                           (not (window-right window)))
-                      (and (not left)
-                           (setq left (window-right window))
-                           (not (window-right left))))
-                  (not (window-size-fixed-p left horizontal)))
-             (and left (not window-splits)
-                  (not (window-size-fixed-p left horizontal))))
-         ;; Resize WINDOW's left sibling.
-         (resize-this-window left size horizontal nil t)
+        ((and (not (window-splits window))
+              sibling (window-sizable-p sibling size))
+         ;; Resize WINDOW's sibling.
+         (resize-this-window sibling size horizontal nil t)
          (resize-window-normal
-          left (+ (window-normal-size left horizontal)
-                  (window-normal-size window horizontal))))
-        ((let ((sub (window-child parent)))
-           (catch 'found
-             ;; Look for a non-fixed-size sibling.
-             (while sub
-               (when (and (not (eq sub window))
-                          (not (window-size-fixed-p sub horizontal)))
-                 (throw 'found t))
-               (setq sub (window-right sub)))))
-         ;; We can do it without resizing fixed-size windows.
+          sibling (+ (window-normal-size sibling horizontal)
+                     (window-normal-size window horizontal))))
+        ((window-resizable-p window (- size) horizontal nil nil nil t)
+         ;; Can do it without resizing fixed-size windows.
          (resize-other-windows window (- size) horizontal))
         (t
-         ;; Can't do without resizing fixed-size windows.  We really
-         ;; should signal an error here but who would agree :-(
+         ;; Can't do without resizing fixed-size windows.
          (resize-other-windows window (- size) horizontal t)))
        ;; Actually delete WINDOW.
        (delete-window-internal window)
@@ -2937,11 +2910,11 @@ frames left."
 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
 and defaults to the current buffer.
 
-When a window showing BUFFER-OR-NAME is dedicated that window is
-deleted.  If that window is the only window on its frame, that
-frame is deleted too when there are other frames left.  If there
-are no other frames left, some other buffer is displayed in that
-window.
+When a window showing BUFFER-OR-NAME is either dedicated, or the
+window has no previous buffer, that window is deleted.  If that
+window is the only window on its frame, the frame is deleted too
+when there are other frames left.  If there are no other frames
+left, some other buffer is displayed in that window.
 
 This function removes the buffer denoted by BUFFER-OR-NAME from
 all window-local buffer lists."
@@ -3084,7 +3057,7 @@ selected on WINDOW's frame."
         (frame (window-frame window))
         (function (window-parameter window 'split-window-function))
         ;; Rebind this locally since in some cases we do have to nest.
-        (window-splits window-splits)
+        (window-nest window-nest)
         atom-root)
     (window-check frame)
     (catch 'done
@@ -3110,15 +3083,15 @@ selected on WINDOW's frame."
             ;; `new-size' to the size of the new window.
             (old-size (window-total-size window horflag))
             (resize
-             (and (eq window-splits 'resize)
+             (and window-splits (not window-nest)
                   ;; Resize makes sense in iso-combinations only.
                   (window-iso-combined-p window horflag)
-                  (or (not size) (< size 0) 
+                  (or (not size) (< size 0)
                       ;; If SIZE is a non-negative integer, we cannot
-                      ;; resize, bind `window-splits' to 'nest instead
-                      ;; to make sure that subsequent window deletions
-                      ;; are handled correctly.
-                      (and (setq window-splits 'nest) nil))))
+                      ;; resize, bind `window-nest' to t instead to
+                      ;; make sure that subsequent window deletions are
+                      ;; handled correctly.
+                      (and (setq window-nest t) nil))))
             (new-size
              (cond
               ((not size)
@@ -3151,13 +3124,13 @@ selected on WINDOW's frame."
                (- size))))
             (root (window-parameter window 'root))
             (window-side (window-parameter window 'window-side)))
-       ;; Check window types and handle `window-splits' with sides.
+       ;; Check window types and handle `window-nest' with sides.
        (when (and window-side
                   (or (not parent)
                       (not (window-parameter parent 'window-side))))
          ;; A side root window.  Make sure a new parent gets created.
          ;; Reset `resize' to nil too.
-         (setq window-splits 'nest)
+         (setq window-nest t)
          (setq resize nil))
 
        ;; Check the sizes.
@@ -3213,7 +3186,7 @@ selected on WINDOW's frame."
                         (- parent-size new-size))
                      parent-size))
              (setq sub (window-right sub)))))
-        ((eq window-splits 'nest)
+        (window-nest
          ;; Get entire space from WINDOW making sure that a new parent
          ;; windows gets created.
          (resize-window-total window (- old-size new-size))
@@ -3581,8 +3554,8 @@ specific buffers."
           (cons 'total-width (window-total-size window t))
           (cons 'normal-height (window-normal-size window))
           (cons 'normal-width (window-normal-size window t))
-          (when (and (not buffer) (window-nested window))
-            (cons 'nested t))
+          (cons 'splits (window-splits window))
+          (cons 'nest (window-nest window))
           (let (list)
             (dolist (parameter (window-parameters window))
               (unless (memq (car parameter)
@@ -3703,7 +3676,7 @@ value can be also stored on disk and read back in a new session."
                                     window-safe-min-width)))
 
              (if (window-sizable-p window (- size) horflag 'safe)
-                 (let* ((window-splits (when (assq 'nested item) 'nest)))
+                 (let* ((window-nest (assq 'nest item)))
                    ;; We must inherit the nesting, otherwise we might mess
                    ;; up handling of atomic and side window.
                    (setq new (split-window window size horflag)))
@@ -3729,10 +3702,14 @@ value can be also stored on disk and read back in a new session."
   (dolist (item window-state-put-list)
     (let ((window (car item))
          (clone-number (cdr (assq 'clone-number item)))
+         (splits (cdr (assq 'splits item)))
+         (nest (cdr (assq 'nest item)))
          (parameters (cdr (assq 'parameters item)))
          (state (cdr (assq 'buffer item))))
       ;; Put in clone-number.
       (when clone-number (set-window-clone-number window clone-number))
+      (when splits (set-window-splits window splits))
+      (when nest (set-window-nest window nest))
       ;; Process parameters.
       (when parameters
        (dolist (parameter parameters)
@@ -3896,7 +3873,7 @@ buffer display specifiers.")
      (reuse-window other same nil)
      (pop-up-window (largest . nil) (lru . nil))
      (reuse-window other other nil))
-    (other-visible-frame
+    (other-frame
      ;; Avoid selected frame.
      (reuse-window nil same other)
      (pop-up-frame)
@@ -4156,7 +4133,7 @@ The following macro specifiers are provided:
   `same-frame-other-window' as `other-window' but stay on the
   selected frame.
 
-  `other-visible-frame' to display the buffer on another visible
+  `other-frame' to display the buffer on another visible
   frame.
 
   `default' to use the default value of `display-buffer-alist'.
@@ -4587,7 +4564,7 @@ using the location specifiers `same-window' or `other-frame'."
         :tag "Other frame only"
         :format "%t%v"
         :inline t
-        (const :format "\n" other-visible-frame))
+        (const :format "\n" other-frame))
        (list
         :tag "Default"
         :format "%t%v"
@@ -4898,8 +4875,7 @@ none was found."
   "Subroutine of `display-buffer-split-window'."
   (let* ((horflag (memq side '(left right)))
         (parent (window-parent window))
-        (resize (and (eq window-splits 'resize)
-                     (window-iso-combined-p window horflag)))
+        (resize (and window-splits (window-iso-combined-p window horflag)))
         (old-size
          ;; We either resize WINDOW or its parent.
          (window-total-size (if resize parent window) horflag))
@@ -5008,7 +4984,7 @@ Return the new window, nil if it could not be created."
 (defun display-buffer-split-atom-window (window &optional side nest specifiers)
   "Make WINDOW part of an atomic window."
   (let ((ignore-window-parameters t)
-       (window-splits 'nest)
+       (window-nest t)
        (selected-window (selected-window))
        root new new-parent)
 
@@ -5100,7 +5076,9 @@ description."
        (set-window-parameter
         window 'quit-restore (list 'new-window buffer selected-window))
        (setq display-buffer-window (cons window 'new-window))
-       (display-buffer-in-window buffer window specifiers)))))
+       (display-buffer-in-window buffer window specifiers)
+       (set-window-prev-buffers window nil)
+       window))))
 
 (defun display-buffer-pop-up-frame (buffer &optional graphic-only specifiers)
   "Make a new frame for displaying BUFFER.
@@ -5171,7 +5149,9 @@ failed."
        window 'quit-restore (list 'new-window buffer selected-window))
       (setq display-buffer-window (cons window 'new-window))
       (set-window-parameter window 'window-slot slot)
-      (display-buffer-in-window buffer window specifiers))))
+      (display-buffer-in-window buffer window specifiers)
+      (set-window-prev-buffers window nil)
+      window)))
 
 (defun display-buffer-in-side-window (buffer side &optional slot specifiers)
   "Display BUFFER in a window on SIDE of the selected frame.
index a48f08d8e85d6037d3f622e6ebf3a836d7f43a47..2cc58f95bfa30d6e6545095a0219ca7e7fc60fd8 100644 (file)
@@ -1,3 +1,40 @@
+2011-04-09  Martin Rudalics  <rudalics@gmx.at>
+
+       * lisp.h: Extern other_buffer_safely.
+
+       * buffer.c: New symbol Qbuffer_list_update_hook.
+       (Fget_buffer_create, Fmake_indirect_buffer, Frename_buffer)
+       (Fkill_buffer, record_buffer): Run buffer-list-update-hook.
+       (other_buffer_safely): New function.
+       (Frecord_buffer): Mention return value in doc-string.
+       (Funrecord_buffer): Mention return value in doc-string.  Run
+       buffer-list-update-hook.
+       (syms_of_buffer): Define Vbuffer_list_update_hook.
+
+       * window.h (window): New slot nest.
+
+       * window.c: Remove Qsafe, Qabove, Qbelow.  Add Qauto_buffer_name.
+       (select_window): Restore version from Emacs 23 to avoid
+       clobbering the current buffer when the selected window is
+       selected.  Reported by Juanma Barranquero.
+       (Fwindow_nested, Fset_window_nested): Remove.
+       (Fwindow_splits, Fset_window_splits, Fwindow_nest)
+       (Fset_window_nest): New functions.
+       (recombine_windows): Use ->nest instead of ->nested.
+       (window_loop): Call other_buffer_safely
+       (Fdelete_other_windows_internal): Reset splits status of
+       remaining window.
+       (make_parent_window, make_window): Initialize splits and nest
+       status.
+       (Fsplit_window_internal): Handle splits and nest status.
+       (Fdelete_window_internal): Remove bflag.  Handle nest status.
+       (saved_window): Add slots for splits and nest status.
+       (Fset_window_configuration): Handle auto_buffer_name.  Handle
+       splits and nest status.  Reorder code.
+       (save_window_save): Handle splits and nest status.
+       (syms_of_window): Rewrite doc-string of window-splits.  New
+       variable window-nest.
+
 2011-02-25  Paul Eggert  <eggert@cs.ucla.edu>
 
        * dired.c (Ffile_attributes): Increase size of modes from 10 to 12
index 57fecce2fb487b09c6414f250321ac1e620e5006..87ee8a26836964e2f59c6d576f5d127351161dc2 100644 (file)
@@ -129,6 +129,7 @@ Lisp_Object Qprotected_field;
 Lisp_Object QSFundamental;     /* A string "Fundamental" */
 
 Lisp_Object Qkill_buffer_hook;
+Lisp_Object Qbuffer_list_update_hook;
 
 Lisp_Object Qget_file_buffer;
 
@@ -382,6 +383,9 @@ even if it is dead.  The return value is never nil.  */)
   /* Put this in the alist of all live buffers.  */
   XSETBUFFER (buffer, b);
   Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buffer), Qnil));
+  /* And run buffer-list-update-hook.  */
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qbuffer_list_update_hook);
 
   /* An error in calling the function here (should someone redefine it)
      can lead to infinite regress until you run out of stack.  rms
@@ -611,6 +615,10 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
       set_buffer_internal_1 (old_b);
     }
 
+  /* Run buffer-list-update-hook.  */
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qbuffer_list_update_hook);
+
   return buf;
 }
 
@@ -1214,6 +1222,11 @@ This does not change the name of the visited file (if any).  */)
   if (NILP (BVAR (current_buffer, filename))
       && !NILP (BVAR (current_buffer, auto_save_file_name)))
     call0 (intern ("rename-auto-save-file"));
+
+  /* Run buffer-list-update-hook.  */
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qbuffer_list_update_hook);
+
   /* Refetch since that last call may have done GC.  */
   return BVAR (current_buffer, name);
 }
@@ -1294,6 +1307,36 @@ exists, return the buffer `*scratch*' (creating it if necessary).  */)
       return buf;
     }
 }
+
+/* The following function is a safe variant of Fother_buffer: It doesn't
+   pay attention to any frame-local buffer lists, doesn't care about
+   visibility of buffers, and doesn't evaluate any frame predicates.  */
+
+Lisp_Object
+other_buffer_safely (Lisp_Object buffer)
+{
+  Lisp_Object Fset_buffer_major_mode (Lisp_Object buffer);
+  Lisp_Object tail, buf;
+
+  tail = Vbuffer_alist;
+  for (; CONSP (tail); tail = XCDR (tail))
+    {
+      buf = Fcdr (XCAR (tail));
+      if (BUFFERP (buf) && !EQ (buf, buffer)
+         && !NILP (BVAR (XBUFFER (buf), name))
+         && (SREF (BVAR (XBUFFER (buf), name), 0) != ' '))
+       return buf;
+    }
+
+  buf = Fget_buffer (build_string ("*scratch*"));
+  if (NILP (buf))
+    {
+      buf = Fget_buffer_create (build_string ("*scratch*"));
+      Fset_buffer_major_mode (buf);
+    }
+
+  return buf;
+}
 \f
 DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo,
        0, 1, "",
@@ -1545,6 +1588,10 @@ with SIGHUP.  */)
   UNBLOCK_INPUT;
   BVAR (b, undo_list) = Qnil;
 
+  /* Run buffer-list-update-hook.  */
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qbuffer_list_update_hook);
+
   return Qt;
 }
 \f
@@ -1583,10 +1630,15 @@ record_buffer (Lisp_Object buffer)
   /* Update buffer list of selected frame.  */
   f->buffer_list = Fcons (buffer, Fdelq (buffer, f->buffer_list));
   f->buried_buffer_list = Fdelq (buffer, f->buried_buffer_list);
+
+  /* Run buffer-list-update-hook.  */
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qbuffer_list_update_hook);
 }
 
 DEFUN ("record-buffer", Frecord_buffer, Srecord_buffer, 1, 1, 0,
-       doc: /* Move BUFFER to the front of the buffer list.  */)
+       doc: /* Move BUFFER to the front of the buffer list.
+Return BUFFER.  */)
   (Lisp_Object buffer)
 {
   CHECK_BUFFER (buffer);
@@ -1603,7 +1655,8 @@ DEFUN ("record-buffer", Frecord_buffer, Srecord_buffer, 1, 1, 0,
      called only when BUFFER was shown in the selected frame.  */
 
 DEFUN ("unrecord-buffer", Funrecord_buffer, Sunrecord_buffer, 1, 1, 0,
-       doc: /* Move BUFFER to the end of the buffer list.  */)
+       doc: /* Move BUFFER to the end of the buffer list.
+Return BUFFER.  */)
   (Lisp_Object buffer)
 {
   Lisp_Object aelt, link, tem;
@@ -1626,6 +1679,12 @@ DEFUN ("unrecord-buffer", Funrecord_buffer, Sunrecord_buffer, 1, 1, 0,
   /* Update buffer lists of selected frame.  */
   f->buffer_list = Fdelq (buffer, f->buffer_list);
   f->buried_buffer_list = Fcons (buffer, Fdelq (buffer, f->buried_buffer_list));
+
+  /* Run buffer-list-update-hook.  */
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qbuffer_list_update_hook);
+
+  return buffer;
 }
 
 DEFUN ("set-buffer-major-mode", Fset_buffer_major_mode, Sset_buffer_major_mode, 1, 1, 0,
@@ -6003,6 +6062,15 @@ The function `kill-all-local-variables' runs this before doing anything else.  *
   Qchange_major_mode_hook = intern_c_string ("change-major-mode-hook");
   staticpro (&Qchange_major_mode_hook);
 
+  DEFVAR_LISP ("buffer-list-update-hook", Vbuffer_list_update_hook,
+              doc: /* Hook run when the buffer list changes.
+Functions running this hook are `get-buffer-create',
+`make-indirect-buffer', `rename-buffer', `kill-buffer',
+`record-buffer' and `unrecord-buffer'.  */);
+  Vbuffer_list_update_hook = Qnil;
+  Qbuffer_list_update_hook = intern_c_string ("buffer-list-update-hook");
+  staticpro (&Qbuffer_list_update_hook);
+
   defsubr (&Sbuffer_live_p);
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
index 82c4f65613d39840f670946e2e4fce0c14360aaf..13281de6b569e81d31041f11b91ba54bf3390eb6 100644 (file)
@@ -2960,6 +2960,7 @@ EXFUN (Fbarf_if_buffer_read_only, 0);
 EXFUN (Fcurrent_buffer, 0);
 EXFUN (Fswitch_to_buffer, 2);
 EXFUN (Fother_buffer, 3);
+extern Lisp_Object other_buffer_safely (Lisp_Object);
 EXFUN (Foverlay_get, 2);
 EXFUN (Fbuffer_modified_p, 1);
 EXFUN (Fset_buffer_modified_p, 1);
index 0e254973f0eb9e2eb7d65f6607bbd0b7e4d3d2cd..abd128a5a40cdfffa6ba943269f468dc7ae4171f 100644 (file)
@@ -56,7 +56,8 @@ Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
 Lisp_Object Qrecord_window_buffer;
 Lisp_Object Qresize_root_window, Qresize_root_window_vertically;
 Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
-Lisp_Object Qset, Qsafe, Qabove, Qbelow, Qnest, Qgroup, Qresize;
+Lisp_Object Qset, Qsafe, Qabove, Qbelow;
+Lisp_Object Qauto_buffer_name;
 
 static int displayed_window_lines (struct window *);
 static struct window *decode_window (Lisp_Object);
@@ -324,55 +325,54 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
   register struct window *w;
   register struct window *ow;
   struct frame *sf;
-  int not_selected_before = !EQ (window, selected_window) || inhibit_point_swap;
 
   CHECK_LIVE_WINDOW (window);
 
   w = XWINDOW (window);
   w->frozen_window_start_p = 0;
 
-  if (not_selected_before)
+  if (NILP (norecord))
     {
-      sf = SELECTED_FRAME ();
-      if (XFRAME (WINDOW_FRAME (w)) != sf)
-       {
-         XFRAME (WINDOW_FRAME (w))->selected_window = window;
-         /* Use this rather than Fhandle_switch_frame
-            so that FRAME_FOCUS_FRAME is moved appropriately as we
-            move around in the state where a minibuffer in a separate
-            frame is active.  */
-         Fselect_frame (WINDOW_FRAME (w), norecord);
-         /* Fselect_frame called us back so we've done all the work already.  */
-         eassert (EQ (window, selected_window));
-         return window;
-       }
-      else
-       sf->selected_window = window;
+      ++window_select_count;
+      XSETFASTINT (w->use_time, window_select_count);
+      record_buffer (w->buffer);
+    }
 
-      if (!inhibit_point_swap)
-       {
-         /* Store the current buffer's actual point into the old
-            selected window.  It belongs to that window, and when the
-            window is not selected, must be in the window.  */
-         ow = XWINDOW (selected_window);
-         if (! NILP (ow->buffer))
-           set_marker_both (ow->pointm, ow->buffer,
-                            BUF_PT (XBUFFER (ow->buffer)),
-                            BUF_PT_BYTE (XBUFFER (ow->buffer)));
-       }
+  if (EQ (window, selected_window) && !inhibit_point_swap)
+    return window;
 
-      selected_window = window;
+  sf = SELECTED_FRAME ();
+  if (XFRAME (WINDOW_FRAME (w)) != sf)
+    {
+      XFRAME (WINDOW_FRAME (w))->selected_window = window;
+      /* Use this rather than Fhandle_switch_frame
+        so that FRAME_FOCUS_FRAME is moved appropriately as we
+        move around in the state where a minibuffer in a separate
+        frame is active.  */
+      Fselect_frame (WINDOW_FRAME (w), norecord);
+      /* Fselect_frame called us back so we've done all the work already.  */
+      eassert (EQ (window, selected_window));
+      return window;
     }
+  else
+    sf->selected_window = window;
 
-  Fset_buffer (w->buffer);
-
-  if (NILP (norecord))
+  /* Store the current buffer's actual point into the
+     old selected window.  It belongs to that window,
+     and when the window is not selected, must be in the window.  */
+  if (!inhibit_point_swap)
     {
-      ++window_select_count;
-      XSETFASTINT (w->use_time, window_select_count);
-      record_buffer (w->buffer);
+      ow = XWINDOW (selected_window);
+      if (! NILP (ow->buffer))
+       set_marker_both (ow->pointm, ow->buffer,
+                        BUF_PT (XBUFFER (ow->buffer)),
+                        BUF_PT_BYTE (XBUFFER (ow->buffer)));
     }
 
+  selected_window = window;
+
+  Fset_buffer (w->buffer);
+
   BVAR (XBUFFER (w->buffer), last_selected_window) = window;
 
   /* Go to the point recorded in the window.
@@ -380,25 +380,20 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
      than one window.  It also matters when
      redisplay_window has altered point after scrolling,
      because it makes the change only in the window.  */
-  if (not_selected_before)
-    {
-      register EMACS_INT new_point = marker_position (w->pointm);
-      if (new_point < BEGV)
-       SET_PT (BEGV);
-      else if (new_point > ZV)
-       SET_PT (ZV);
-      else
-       SET_PT (new_point);
-
-      windows_or_buffers_changed++;
-    }
+  {
+    register EMACS_INT new_point = marker_position (w->pointm);
+    if (new_point < BEGV)
+      SET_PT (BEGV);
+    else if (new_point > ZV)
+      SET_PT (ZV);
+    else
+      SET_PT (new_point);
+  }
 
+  windows_or_buffers_changed++;
   return window;
 }
 
-
-/* Note that selected_window can be nil when this is called from
-   Fset_window_configuration.  */
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
        doc: /* Select WINDOW.  Most editing will apply to WINDOW's buffer.
 Also make WINDOW's buffer current and make WINDOW the frame's selected
@@ -477,31 +472,69 @@ Return nil if WINDOW has no left sibling.  */)
   return decode_any_window (window)->prev;
 }
 
-DEFUN ("window-nested", Fwindow_nested, Swindow_nested, 0, 1, 0,
-       doc: /* Return non-nil when WINDOW is nested.
+DEFUN ("window-splits", Fwindow_splits, Swindow_splits, 0, 1, 0,
+       doc: /* Return splits status for WINDOW.
 WINDOW can be any window and defaults to the selected one.
 
-Subwindows of a nested are never \(re-)combined with the window's
-siblings.  */)
+If the value returned by this function is nil and WINDOW is resized, the
+corresponding space is preferably taken from (or given to) WINDOW's
+right sibling.  When WINDOW is deleted, its space is given to its left
+sibling.
+
+If the value returned by this function is non-nil, resizing and deleting
+WINDOW may resize all windows in the same combination.  */)
   (Lisp_Object window)
 {
-  return decode_any_window (window)->nested;
+  return decode_any_window (window)->splits;
 }
 
-DEFUN ("set-window-nested", Fset_window_nested, Sset_window_nested, 2, 2, 0,
-       doc: /* Set nesting of WINDOW to STATUS.
-WINDOW must be an internal window.  Return STATUS.
+DEFUN ("set-window-splits", Fset_window_splits, Sset_window_splits, 2, 2, 0,
+       doc: /* Set splits status of WINDOW to STATUS.
+WINDOW can be any window and defaults to the selected one.  Return
+STATUS.
+
+If STATUS is nil and WINDOW is later resized, the corresponding space is
+preferably taken from (or given to) WINDOW's right sibling.  When WINDOW
+is deleted, its space is given to its left sibling.
 
-When a window is nested its subwindows are never recombined with the
-window's siblings.  */)
+If STATUS is non-nil, resizing and deleting WINDOW may resize all
+windows in the same combination.  */)
   (Lisp_Object window, Lisp_Object status)
 {
   register struct window *w = decode_any_window (window);
 
-  if (! NILP (w->buffer))
-    w->nested = status;
+  w->splits = status;
 
-  return w->nested;
+  return w->splits;
+}
+
+DEFUN ("window-nest", Fwindow_nest, Swindow_nest, 0, 1, 0,
+       doc: /* Return nest status of WINDOW.
+WINDOW can be any window and defaults to the selected one.
+
+If the return value is nil, subwindows of WINDOW can be recombined with
+WINDOW's siblings.  A return value of nil means that subwindows of
+WINDOW are never \(re-)combined with WINDOW's siblings.  */)
+  (Lisp_Object window)
+{
+  return decode_any_window (window)->nest;
+}
+
+DEFUN ("set-window-nest", Fset_window_nest, Sset_window_nest, 2, 2, 0,
+       doc: /* Set nest status of WINDOW to STATUS.
+WINDOW can be any window and defaults to the selected one.  Return
+STATUS.
+
+If the return value is nil, subwindows of WINDOW can be recombined with
+WINDOW's siblings.  A return value of nil means that subwindows of
+WINDOW are never \(re-)combined with WINDOW's siblings.  */)
+  (Lisp_Object window, Lisp_Object status)
+{
+  register struct window *w = decode_any_window (window);
+
+  w->nest = status;
+
+  return w->nest;
 }
 
 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
@@ -1883,7 +1916,7 @@ recombine_windows (Lisp_Object window)
 
   w = XWINDOW (window);
   parent = w->parent;
-  if (NILP (w->nested) && !NILP (parent))
+  if (!NILP (parent) && NILP (w->nest))
     {
       p = XWINDOW (parent);
       if (((!NILP (p->vchild) && !NILP (w->vchild))
@@ -2464,10 +2497,10 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
              {
                /* Undedicate WINDOW.  */
                w->dedicated = Qnil;
-               /* Make WINDOW show the buffer returned by Fother_buffer
-                  but don't run any hooks.  */
+               /* Make WINDOW show the buffer returned by
+                  other_buffer_safely, don't run any hooks.  */
                set_window_buffer
-                 (window, Fother_buffer (w->buffer, Qnil, w->frame), 0, 0);
+                 (window, other_buffer_safely (w->buffer), 0, 0);
                /* If WINDOW is the selected window, make its buffer
                   current.  But do so only if the window shows the
                   current buffer (Bug#6454).  */
@@ -2741,6 +2774,9 @@ window-start value is reasonable when this function is called.  */)
 
   replace_window (root, window, 1);
 
+  /* Reset WINDOW's splits status.  */
+  w->splits = Qnil;
+
   /* This must become SWINDOW anyway ....... */
   if (!NILP (w->buffer) && !resize_failed)
     {
@@ -3264,6 +3300,8 @@ make_parent_window (Lisp_Object window, int horflag)
   p->start = Qnil;
   p->pointm = Qnil;
   p->buffer = Qnil;
+  p->splits = Qnil;
+  p->nest = Qnil;
   p->window_parameters = Qnil;
 }
 
@@ -3311,7 +3349,7 @@ make_window (void)
   w->start_at_line_beg = w->display_table = w->dedicated = Qnil;
   w->base_line_number = w->base_line_pos = w->region_showing = Qnil;
   w->column_number_displayed = w->redisplay_end_trigger = Qnil;
-  w->nested = w->window_parameters = Qnil;
+  w->splits = w->nest = w->window_parameters = Qnil;
   w->prev_buffers = w->next_buffers = Qnil;
   /* Initialize non-Lisp data.  */
   w->desired_matrix = w->current_matrix = 0;
@@ -3696,7 +3734,8 @@ divder column.  */)
   int horflag
     /* HORFLAG is 1 when we split horizontally, 0 otherwise.  */
     = EQ (horizontal, Qt) || EQ (horizontal, Qleft) || EQ (horizontal, Qright);
-  int do_resize;
+  int do_resize = 0;
+  int do_nest = 0;
 
   CHECK_WINDOW (old);
   o = XWINDOW (old);
@@ -3705,14 +3744,18 @@ divder column.  */)
 
   CHECK_NUMBER (size);
 
-  /* Set do_resize to 1 iff we don't nest and OLD has an iso-combined
-     parent window.  */
-  do_resize =
-    EQ (Vwindow_splits, Qresize)
-    && !NILP (o->parent)
-    && (horflag
-       ? !NILP (XWINDOW (o->parent)->hchild)
-       : !NILP (XWINDOW (o->parent)->vchild));
+  /* Set do_nest to 1 if either Vwindow_nest is non-nil, OLD has no
+     parent, or OLD is ortho-combined.  */
+  do_nest =
+    !NILP (Vwindow_nest)
+    || NILP (o->parent)
+    || NILP (horflag
+            ? (XWINDOW (o->parent)->hchild)
+            : (XWINDOW (o->parent)->vchild));
+
+  /* Set do_resize to 1 iff do_nest was not set and Vwindow_splits is
+     non-nil.  */
+  do_resize = !do_nest && !NILP (Vwindow_splits);
 
   /* We may need a live reference window to copy some parameters.  */
   if (WINDOW_LIVE_P (old))
@@ -3736,7 +3779,7 @@ divder column.  */)
       if (!resize_window_check (p, horflag))
        error ("Sum of window sizes won't fit");
       else
-       /* Undo the temporal pretension.  */
+       /* Undo the temporary pretension.  */
        p->new_total = horflag ? p->total_cols : p->total_lines;
     }
   else
@@ -3753,7 +3796,7 @@ divder column.  */)
       || NILP (horflag
               ? (XWINDOW (o->parent)->hchild)
               : (XWINDOW (o->parent)->vchild))
-      || EQ (Vwindow_splits, Qnest))
+      || !NILP (Vwindow_nest))
     /* Make a new parent window in the following cases:
 
        - OLD doesn't have a parent window, or
@@ -3772,9 +3815,12 @@ divder column.  */)
       Lisp_Object new_normal = horflag ? o->normal_cols : o->normal_lines;
       make_parent_window (old, horflag);
       p = XWINDOW (o->parent);
-      if (EQ (Vwindow_splits, Qnest))
-       /* Make sure that parent is not recombined.  */
-       p->nested = Qt;
+      /* Store nesting in parent.  */
+      p->nest = Vwindow_nest;
+      /* Inherit splits from old.  */
+      p->splits = o->splits;
+      /* Set splits in old window.  */
+      o->splits = Vwindow_splits;
       /* These get applied below.  */
       p->new_total = horflag ? o->total_cols : o->total_lines;
       p->new_normal = new_normal;
@@ -3835,11 +3881,15 @@ divder column.  */)
       n->left_col = o->left_col;
       n->total_cols = o->total_cols;
     }
+
   n->new_total = size;
 
   BLOCK_INPUT;
   resize_window_apply (p, horflag);
 
+  /* Store splits in new.  */
+  n->splits = Vwindow_splits;
+
   if (!do_resize)
     {
       /* Assign normal sizes for OLD.  */
@@ -3880,7 +3930,6 @@ when WINDOW is the only window on its frame.  */)
   struct window *w, *p, *s, *r;
   struct frame *f;
   int horflag;
-  int bflag = 0;
   int before_sibling = 0;
 
   w = decode_any_window (window);
@@ -3971,15 +4020,14 @@ when WINDOW is the only window on its frame.  */)
        {
          /* Put SIBLING into PARENT's place.  */
          replace_window (parent, sibling, 0);
-         /* Inherit these two.  */
+         /* Inherit these three.  */
          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;
-         /* Merge SIBLING's into its new parent unless we want binary
-            trees.  */
-         if (!EQ (Vwindow_splits, Qnest))
-           recombine_windows (sibling);
+         /* Try to merge SIBLING into its new parent.  */
+         recombine_windows (sibling);
        }
 
       adjust_glyphs (f);
@@ -5340,8 +5388,7 @@ struct saved_window
   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, dedicated;
-  Lisp_Object nested;
-  Lisp_Object window_parameters;
+  Lisp_Object splits, nest, window_parameters;
 };
 
 #define SAVED_WINDOW_N(swv,n) \
@@ -5382,6 +5429,7 @@ the return value is nil.  Otherwise the value is t.  */)
   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;
 
@@ -5571,7 +5619,8 @@ the return value is nil.  Otherwise the value is t.  */)
          w->scroll_bar_width = p->scroll_bar_width;
          w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
          w->dedicated = p->dedicated;
-         w->nested = p->nested;
+         w->splits = p->splits;
+         w->nest = p->nest;
          w->window_parameters = p->window_parameters;
          XSETFASTINT (w->last_modified, 0);
          XSETFASTINT (w->last_overlay_modified, 0);
@@ -5597,10 +5646,37 @@ the return value is nil.  Otherwise the value is t.  */)
                  && 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.  */
+         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.  */
            {
-             w->buffer = Fcdr (Fcar (Vbuffer_alist));
+             /* 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);
@@ -5612,20 +5688,6 @@ the return value is nil.  Otherwise the value is t.  */)
              /* Make sure window is no more dedicated.  */
              w->dedicated = Qnil;
            }
-         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;
-           }
        }
 
       FRAME_ROOT_WINDOW (f) = data->root_window;
@@ -5836,7 +5898,8 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       p->scroll_bar_width = w->scroll_bar_width;
       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
       p->dedicated = w->dedicated;
-      p->nested = w->nested;
+      p->splits = w->splits;
+      p->nest = w->nest;
       p->window_parameters = w->window_parameters;
       if (!NILP (w->buffer))
        {
@@ -6320,7 +6383,7 @@ freeze_window_starts (struct frame *f, int freeze_p)
    and the like.
 
    This ignores a couple of things like the dedicatedness status of
-   window, nested and the like.  This might have to be fixed.  */
+   window, splits, nest and the like.  This might have to be fixed.  */
 
 int
 compare_window_configurations (Lisp_Object configuration1, Lisp_Object configuration2, int ignore_positions)
@@ -6493,14 +6556,8 @@ syms_of_window (void)
   Qbelow = intern_c_string ("below");
   staticpro (&Qbelow);
 
-  Qnest = intern_c_string ("nest");
-  staticpro (&Qnest);
-
-  Qresize = intern_c_string ("resize");
-  staticpro (&Qresize);
-
-  Qgroup = intern_c_string ("group");
-  staticpro (&Qgroup);
+  Qauto_buffer_name = intern_c_string ("auto-buffer-name");
+  staticpro (&Qauto_buffer_name);
 
   staticpro (&Vwindow_list);
 
@@ -6585,24 +6642,40 @@ frame to be redrawn only if it is a tty frame.  */);
 
   DEFVAR_LISP ("window-splits", Vwindow_splits,
               doc: /* Non-nil means splitting windows is handled specially.
-If this variable is nil, splitting a window WINDOW will create a new
-parent window only if WINDOW has no parent window or WINDOW shall be
-split in another direction than the combination WINDOW is part of.
-Resizing WINDOW preferably resizes WINDOW's right sibling.  Deleting
-WINDOW will preferably return space to WINDOW's left sibling.
-
-If this variable equals `nest', splitting WINDOW always creates a new
-parent window.  Consequently, any frame's window tree is a binary tree
-and every window has at most one (left or right) sibling.  Resizing
-WINDOW will preferably resize WINDOW's sibling.  Deleting WINDOW will
-preferably return space to WINDOW's sibling.
-
-If this variable equals `resize', splitting, resizing and deleting
-WINDOW will try to resize all windows in the same combination as WINDOW
-first.  This setting allows to split windows that are otherwise too
-small or of fixed size.  */);
+If this variable is nil, splitting a window gets the entire screen space
+for displaying the new window from the window to split.  If this
+variable is non-nil, splitting a window may resize all windows in the
+same combination.  This also allows to split a window that is otherwise
+too small or of fixed size.
+
+The value of this variable is also assigned to the split status of the
+new window and, provided the old and new window form a new combination,
+to the window that was split as well.  The split status of a window can
+be retrieved with the function `window-splits' and altered by the
+function `set-window-splits'.
+
+If the value of the variable `window-nest' is non-nil, the space for the
+new window is exclusively taken from the window that shall be split, but
+the split status of the window that is split as well as that of the new
+window are still set to the value of this variable.  */);
   Vwindow_splits = Qnil;
 
+  DEFVAR_LISP ("window-nest", Vwindow_nest,
+              doc: /* Non-nil means splitting a window makes a new parent window.
+If this variable is nil, splitting a window will create a new parent
+window only if the window has no parent window or the window shall
+become a combination orthogonal to the one it it is part of.
+
+If this variable is non-nil, splitting a window always creates a new
+parent window.  If all splits behave this way, each frame's window tree
+is a binary tree and every window but the frame's root window has
+exactly one sibling.
+
+The value of this variable is also assigned to the nest status of the
+new parent window.  The nest status of a window can be retrieved via the
+function `window-nest' and altered by the function `set-window-nest'.  */);
+  Vwindow_nest = Qnil;
+
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
@@ -6622,8 +6695,10 @@ small or of fixed size.  */);
   defsubr (&Swindow_hchild);
   defsubr (&Swindow_next);
   defsubr (&Swindow_prev);
-  defsubr (&Swindow_nested);
-  defsubr (&Sset_window_nested);
+  defsubr (&Swindow_splits);
+  defsubr (&Sset_window_splits);
+  defsubr (&Swindow_nest);
+  defsubr (&Sset_window_nest);
   defsubr (&Swindow_use_time);
   defsubr (&Swindow_top_line);
   defsubr (&Swindow_left_column);
index 75d90f14950077c5cc9cdcf69551169466d6d091..d08902e84357bd65cab5d6bc3efaedb4bb211d0d 100644 (file)
@@ -264,8 +264,13 @@ struct window
        must run the redisplay-end-trigger-hook.  */
     Lisp_Object redisplay_end_trigger;
 
-    /* Non-nil means this window's subwindows are never recombined.  */
-    Lisp_Object nested;
+    /* Non-nil means deleting or resizing this window distributes
+       space among all windows in the same combination.  */
+    Lisp_Object splits;
+
+    /* Non-nil means this window's child windows are never
+       (re-)combined.  */
+    Lisp_Object nest;
 
     /* Alist of <buffer, window-start, window-point> triples listing
        buffers previously shown in this window.  */