From: Martin Rudalics Date: Sun, 10 Apr 2011 12:38:11 +0000 (+0200) Subject: Revise window splitting/nesting. Fix errors reported by Juanma. X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=967f49308ac07ad3dbba9ff3ed692b0fd3971499;p=emacs.git Revise window splitting/nesting. Fix errors reported by Juanma. * 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. --- diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 649f078d6e1..71a5ce2b7de 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,9 @@ +2011-04-09 Martin Rudalics + + * windows.texi (Splitting Windows): Explain window-splits and + window-nest. + (Displaying Buffers): Replace other-visible-frame by other-frame. + 2011-02-24 Martin Rudalics * windows.texi (Window Configurations): Fix typo. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index d1602213d7a..6e4d08751ad 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -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 diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4de9272d901..70929780a97 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,31 @@ +2011-04-09 Martin Rudalics + + * 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 * files-x.el (modify-dir-local-variable): Handle dir-locals from diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el index 05f3a073bf5..a6065907054 100644 --- a/lisp/buff-menu.el +++ b/lisp/buff-menu.el @@ -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) diff --git a/lisp/cus-start.el b/lisp/cus-start.el index c3e4d899e00..ce82eef00ae 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -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) diff --git a/lisp/help.el b/lisp/help.el index a5bf93166ed..5c952f83aca 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -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.") diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 8a33381b618..41b18f8b66f 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -433,7 +433,7 @@ (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)) diff --git a/lisp/window.el b/lisp/window.el index e4b3c6174c1..20f7c09af2c 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -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. diff --git a/src/ChangeLog b/src/ChangeLog index a48f08d8e85..2cc58f95bfa 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,40 @@ +2011-04-09 Martin Rudalics + + * 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 * dired.c (Ffile_attributes): Increase size of modes from 10 to 12 diff --git a/src/buffer.c b/src/buffer.c index 57fecce2fb4..87ee8a26836 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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; +} 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; } @@ -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); diff --git a/src/lisp.h b/src/lisp.h index 82c4f65613d..13281de6b56 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -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); diff --git a/src/window.c b/src/window.c index 0e254973f0e..abd128a5a40 100644 --- a/src/window.c +++ b/src/window.c @@ -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); diff --git a/src/window.h b/src/window.h index 75d90f14950..d08902e8435 100644 --- a/src/window.h +++ b/src/window.h @@ -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 triples listing buffers previously shown in this window. */