From fb04f483a6b996215c73479600bdaa08f57137a8 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Tue, 31 May 2011 10:51:21 +0200 Subject: [PATCH] Minor fixes in window resizing routines and documentation update. * window.c (Fsplit_window_internal): Make all arguments mandatory. Rewrite doc-string. Simplify code. * window.el (ignore-window-parameters, window-size-fixed): Rewrite doc-strings. (window-min-delta-1, window-min-delta): Reorder. Minor rewrite. (resize-subwindows-normal): Use zerop when checking other-delta. Call window-min-delta with NODOWN argument nil. (adjust-window-trailing-edge): Fix doc-string. (other-window): Fix doc-string and respect ignore-window-parameters. (delete-window, delete-other-windows): Fix doc-strings. Remove -function postfix from associated window parameters. (quit-restore-window): Resize only if buffer was in temp-buffer-resize-mode. (window-split-min-size): Rewrite doc-string. (split-window): Rewrite doc-string. Rename horflag to horizontal. Major rewrite of size calculations. Remove -function postfix from associated window parameter. (window-state-put-1, display-buffer-split-window-1): Rename horflag to horizontal. (same-window-p): Remove call to non-existent function. * windows.texi (Windows and Frames, Window Sizes) (Resizing Windows): Minor rewrites. (Splitting Windows): Provide additional examples. Rewrite parts on window-splits and window-nest. (Deleting Windows, Window Parameters, Side Windows): Minor rewrites. --- doc/lispref/ChangeLog | 9 + doc/lispref/windows.texi | 641 +++++++++++++++++++++++++-------------- etc/NEWS | 135 +++++++++ lisp/ChangeLog | 22 ++ lisp/dired.el | 2 +- lisp/window.el | 637 +++++++++++++++++++------------------- src/ChangeLog | 5 + src/window.c | 129 ++++---- 8 files changed, 967 insertions(+), 613 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 57964f811ad..bf1f699c525 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,12 @@ +2011-05-30 Martin Rudalics + + * windows.texi (Windows and Frames, Window Sizes) + (Resizing Windows): Minor rewrites. + (Splitting Windows): Provide additional examples. Rewrite + parts on window-splits and window-nest. + (Deleting Windows, Window Parameters, Side Windows): Minor + rewrites. + 2011-05-19 Glenn Morris * lists.texi (Sets And Lists): Mention cl provides union etc. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 3b77fef4c3d..fc17668e439 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -227,7 +227,7 @@ combination of windows. A @dfn{vertical combination} is a set of windows arranged one above each other. A @dfn{horizontal combination} is a set of windows arranged side by side. Consider the frame shown below (for simplicity we assume that the frame does not contain a -minibuffer): +minibuffer window): @smallexample @group @@ -284,7 +284,7 @@ example above @code{(window-hchild W4)} is @code{W6} while @defun window-child window This function return @var{window}'s first child window. The return value is @code{nil} if @var{window} is a leaf window. In the example -above @code{(window-child W3)} is @code{W4} while @code{(window-vchild +above @code{(window-child W3)} is @code{W4} while @code{(window-child W4)} is @code{W6}. @end defun @@ -301,10 +301,6 @@ If the optional argument @var{horizontal} is non-@code{nil}, this means to return non-@code{nil} if and only if @var{window} is horizontally combined. The actual return value is the first horizontal child of window. - -In our canonical example @code{(window-iso-combined-p W5)} and -@code{(window-iso-combined-p W6 t)} both evaluate to @code{t} while -@code{(window-iso-combined-p W6)} is @code{nil}. @end defun @cindex sibling window @@ -462,7 +458,7 @@ otherwise. @end defun Alternatively, the following two functions can be used to retrieve -either the total height of the total width of a window: +either the total height or the total width of a window: @defun window-total-height &optional window This function returns the total number of lines of @var{window}. @@ -548,7 +544,7 @@ included in a window's body height. @cindex body width of a window The @dfn{body width of a window} denotes the total number of columns occupied by the window's text area. Scroll bars or columns of @samp{|} -characters that separates side-by-side windows are not included in a +characters that separate side-by-side windows are not included in a window's body width. @cindex body size of a window @@ -722,7 +718,7 @@ return value of zero means that @var{window} is not resizable. If @var{delta} is a positive number, this means that @var{window} shall be enlarged by @var{delta} lines or columns. If @var{window} cannot be -enlarged by @var{delta} lines or columns this function returns the +enlarged by @var{delta} lines or columns, this function returns the maximum value in the range from 0 to @var{delta} by which @var{window} can be enlarged. @@ -748,7 +744,7 @@ Optional argument @var{noup} non-@code{nil} means don't go up in the window tree but try to steal or distribute the space needed for the resize operation among the other windows within @var{window}'s combination. Optional argument @var{nodown} non-@code{nil} means don't -check whether @var{window} and its subwindows can be resized. +check whether @var{window} itself and its subwindows can be resized. @end defun The function @code{window-resizable} does not change any window sizes. @@ -773,10 +769,12 @@ A negative @var{delta} means @var{window} shall be shrunk by Optional argument @var{ignore} has the same meaning as for the function @code{window-resizable} above. -This function resizes other windows proportionally and never deletes any -windows. If only the low (right) edge of @var{window} shall be moved, -the function @code{adjust-window-trailing-edge} described below should -be used. +This function can simultaneously move two edges of WINDOW. Exactly +which edges of @var{window} are moved and which other windows are +resized along with @var{window} is determined by the splits and nest +status of the involved windows (@pxref{Splitting Windows}). If only the +low (right) edge of @var{window} shall be moved, the function +@code{adjust-window-trailing-edge} described below should be used. @end defun The next four commands are simple interfaces to @code{resize-window}. @@ -821,20 +819,32 @@ Optional argument @var{horizontal} non-@code{nil} means to move @var{window}'s right edge by @var{delta} columns. The argument @var{window} defaults to the selected window. -If the edge can't be moved by @var{delta} lines, move it as far as -possible in the desired direction. +If @var{delta} is greater zero, this moves the edge downwards or to the +right. If @var{delta} is less than zero, this moves the edge upwards or +to the left. If the edge can't be moved by @var{delta} lines or columns, +it is moved as far as possible in the desired direction but no error is +signalled. + +This function tries to resize windows adjacent to the edge that is +moved. Only if this is insufficient, it will also resize windows not +adjacent to that edge. As a consequence, if you move an edge in one +direction and back in the other direction by the same amount, the +resulting window configuration will not be necessarily identical to the +one before the first move. So if your intend to just resize +@var{window}, you should not use this function but call +@code{resize-window} (see above) instead. @end defun @deffn Command fit-window-to-buffer &optional window max-height min-height override This command makes @var{window} the right height to display its contents exactly. The default for @var{window} is the selected window. -The optional argument @var{max-height} specifies the maximum height the -window is allowed to be; @code{nil} means use the maximum permissible -height of a window on @var{window}'s frame. The optional argument -@var{min-height} specifies the minimum height for the window; @code{nil} -means use @code{window-min-height}. All these height values include the -mode line and/or header line. +The optional argument @var{max-height} specifies the maximum total +height the window is allowed to be; @code{nil} means use the maximum +permissible height of a window on @var{window}'s frame. The optional +argument @var{min-height} specifies the minimum toatl height for the +window; @code{nil} means use @code{window-min-height}. All these height +values include the mode line and/or header line. If the optional argument @var{override} is non-@code{nil}, this means to ignore any restrictions imposed by @code{window-min-height} and @@ -861,7 +871,7 @@ and @code{nil} otherwise. @cindex balancing window sizes Emacs provides two functions to balance windows, that is, to even out -the sizes of windows on the same frame. The minibuffer window and +the sizes of all windows on the same frame. The minibuffer window and fixed-size windows are not resized by these functions. @deffn Command balance-windows &optional window-or-frame @@ -958,12 +968,11 @@ frame. If @code{ignore-window-parameters} is non-@code{nil}, this function ignores window parameters (@pxref{Window Parameters}). Otherwise, if -the @code{split-window-function} parameter of @var{window} is @code{t}, -it splits the window disregarding any other window parameters. If the -@code{split-window-function} parameter specifies a function, that -function is called with the arguments @var{window}, @var{size}, and -@var{side} to split @var{window}. If that function is @code{ignore}, -nothing is done. +the @code{split-window} parameter of @var{window} is @code{t}, it splits +the window disregarding any other window parameters. If the +@code{split-window} parameter specifies a function, that function is +called with the arguments @var{window}, @var{size}, and @var{side} to +split @var{window}. If that function is @code{ignore}, nothing is done. Otherwise, if @var{window} is a subwindow of an atomic window (@pxref{Atomic Windows}) this function splits the root of the atomic @@ -1054,30 +1063,10 @@ window configuration from our earlier example (@pxref{Windows and Frames}) and how internal windows are created for this purpose. We start with a frame containing one leaf window @code{W2} (in the following scenarios window names are assigned in an arbitrary manner in -order to match the names of the example). -@smallexample -@group - ______________________________________ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - |__________________W2__________________| - -@end group -@end smallexample - -Evaluating the form @code{(split-window W2 8 t)} creates a new internal -window @code{W1} with two children---@code{W2} (the window we've split) -and a new leaf window @code{W6}: +order to match the names of the example). Evaluating the form +@code{(split-window W2 8 t)} creates a new internal window @code{W1} +with two children---@code{W2} (the window we've split) and a new leaf +window @code{W6}: @smallexample @group ______________________________________ @@ -1171,29 +1160,9 @@ following vertical combination: @end smallexample Evaluating now @code{(split-window (window-parent W6) -8 'left)} or, -equivalently, @code{(split-window W3 -8 'left)} should produce the -familiar configuration -@smallexample -@group - ______________________________________ - | ______ ____________________________ | - || || __________________________ || - || ||| ||| - || ||| ||| - || ||| ||| - || ||| ||| - || ||| ||| - || |||____________W6____________||| - || || __________________________ || - || ||| ||| - || |||____________W5____________||| - ||__W2__||_____________W3_____________ | - |__________________W1__________________| - -@end group -@end smallexample - -from where we can continue as described in the previous scenario. +equivalently, @code{(split-window W3 -8 'left)} should now produce the +penultimate configuration from the previous scenario from where we can +continue as described before. Another strategy starts with splitting an inital window @code{W6} by evaluating @code{(split-window W6 nil nil t)} with the following result: @@ -1270,43 +1239,29 @@ Evaluating now @code{(split-window W4 -3)} or, for example, @code{(split-window (window-parent W6) -3)} should produce the desired configuration. - The following two option can be used to tune the operation of + The two options described next 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. +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. +all windows that are part of the same combination as the old window to +accomodate the new window. Hence, the new window can be also created if +the old window is of fixed size or too small to split (@pxref{Window +Sizes}). 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. +altered by the function @code{set-window-splits} described next. 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 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. +status of the involved windows is nevertheless set as described here. @end defopt @defun window-splits &optional window @@ -1316,16 +1271,17 @@ This function returns the splits status of @var{window}. The argument @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) +combination. 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 @emph{all} windows in @var{window}'s +combination. + +The splits status is initially set by @code{split-window} +from 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 @@ -1334,6 +1290,89 @@ This function sets the splits status (see above) of @var{window} to to the selected one. The return value is @var{status}. @end defun +To illustrate the use of @code{window-splits} consider the following +window configuration: +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + || || + || || + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +Splitting window @code{W3} with @code{window-splits} @code{nil} +produces a configuration where the size of @code{W2} remains unchanged: +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + ||_________________W3_________________|| + | ____________________________________ | + || || + ||_________________W4_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +Splitting @code{W3} with @code{window-splits} non-@code{nil} instead +produces a configuration where all windows have approximately the same +height: + +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + || || + ||_________________W3_________________|| + | ____________________________________ | + || || + || || + ||_________________W4_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +@defopt window-nest +If this variable is @code{nil}, @code{split-window} creates a new parent +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-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, @@ -1341,10 +1380,10 @@ 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 +The @dfn{nest status} of a window specifies 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 +assigned by @code{split-window} from the current value of the variable @code{window-nest} (see above) and can be reset by the function @code{set-window-nest} (see below). @@ -1361,6 +1400,148 @@ to the selected one. Note that setting the nest status is meaningful for internal windows only. The return value is @var{status}. @end defun +To illustrate the use of @code{window-nest} consider the following +configuration (throughout the following examples we shall assume that +@code{window-splits} invariantly is @code{nil}). +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + || || + || || + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +Splitting @code{W2} into two windows above each other with +@code{window-nest} equal @code{nil} will get you a configuration like: +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + || || + ||_________________W4_________________|| + | ____________________________________ | + || || + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +If you now enlarge window @code{W4}, Emacs steals the necessary space +from window @code{W3} resulting in a configuration like: +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + || || + || || + ||_________________W4_________________|| + | ____________________________________ | + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +Deleting window @code{W4}, will return its space to @code{W2} as +follows: +@smallexample +@group + ______________________________________ + | ____________________________________ | + || || + || || + || || + || || + || || + || || + || || + ||_________________W2_________________|| + | ____________________________________ | + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +Hence, with respect to the initial configuration, window @code{W2} has +grown at the expense of window @code{W3}. If, however, in the initial +configuration you had split @code{W2} with @code{window-nest} bound to +@code{t}, a new internal window @code{W5} would have been created as +depicted below. +@smallexample +@group + ______________________________________ + | ____________________________________ | + || __________________________________ || + ||| ||| + |||________________W2________________||| + || __________________________________ || + ||| ||| + |||________________W4________________||| + ||_________________W5_________________|| + | ____________________________________ | + || || + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +Enlarging @code{W4} would now have stolen the necessary space from +@code{W2} instead of @code{W3} as +@smallexample +@group + ______________________________________ + | ____________________________________ | + || __________________________________ || + |||________________W2________________||| + || __________________________________ || + ||| ||| + ||| ||| + |||________________W4________________||| + ||_________________W5_________________|| + | ____________________________________ | + || || + || || + ||_________________W3_________________|| + |__________________W1__________________| + +@end group +@end smallexample + +and the subsequent deletion of @code{W4} would have restored the initial +configuration. + +For interactive use, Emacs provides two commands which always split the +selected window. + @deffn Command split-window-above-each-other &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} @@ -1415,26 +1596,26 @@ selected one. An error is signaled if @var{window} is the only window on its frame. Hence @var{window} must have at least one sibling window (@pxref{Windows and Frames}) in order to get deleted. -If @code{window-splits} is @code{nil}, the space @var{window} took up is -given to its left sibling if such a window exists and to its right -sibling otherwise. If @code{window-splits} equals @code{nest} that -space is given to the remaining sibling of @var{window}. If -@code{window-splits} equals @code{resize}, the space occupied by -@var{window} is proportionally distributed among the remaining windows -in the same combination. - -If @code{ignore-window-parameters} (@pxref{Window Parameters}) is -non-@code{nil}, this function ignores window parameters. Otherwise, if -the @code{delete-window-function} parameter of @var{window} is @code{t}, -it deletes the window disregarding other window parameters. If the -@code{delete-window-function} parameter specifies a function, that -function is called with @var{window} as its sole argument. - -If @var{window} is part of an atomic window (@pxref{Atomic Windows}), -this function is called with the root of the atomic window as its -argument. If that window is the root window of its frame, an error is -signalled. If @var{window} is the last non-side window on its frame +If the variable @code{ignore-window-parameters} (@pxref{Window +Parameters}) is non-@code{nil}, this function ignores all parameters of +@var{window}. Otherwise, if the @code{delete-window} parameter of +@var{window} is @code{t}, it deletes the window disregarding other +window parameters. If the @code{delete-window} parameter specifies a +function, that function is called with @var{window} as its sole +argument. + +Otherwise, if @var{window} is part of an atomic window (@pxref{Atomic +Windows}), this function is called with the root of the atomic window as +its argument. If that window is the root window of its frame, an error +is signalled. If @var{window} is the last non-side window on its frame (@pxref{Side Windows}), this function signals an error too. + +If the splits status of @var{window} (@pxref{Splitting Windows}) is +@code{nil}, the space @var{window} took up is given to its left sibling +if such a window exists and to its right sibling otherwise. If the +splits status of @var{window} is non-@code{nil}, its space is +proportionally distributed among the remaining windows in the same +combination. @end deffn @deffn Command delete-other-windows &optional window @@ -1442,19 +1623,20 @@ This function makes @var{window} fill its frame and returns @code{nil}. The argument @var{window} can denote an arbitrary window and defaults to the selected one. -If @code{ignore-window-parameters} (@pxref{Window Parameters}) is -non-@code{nil}, this function ignores window parameters. Otherwise, if -the @code{delete-other-windows-function} parameter equals @code{t}, it -deletes all other windows disregarding any remaining window parameters. -If the @code{delete-other-windows-function} parameter specifies a +If the variable @code{ignore-window-parameters} (@pxref{Window +Parameters}) is non-@code{nil}, this function ignores all parameters of +@var{window}. Otherwise, if the @code{delete-other-windows} parameter +of @var{window} equals @code{t}, it deletes all other windows +disregarding any remaining window parameters. If the +@code{delete-other-windows} parameter of @var{window} specifies a function, it calls that function with @var{window} as its sole argument. -If @var{window} is part of an atomic window (@pxref{Atomic Windows}), it -calls this function with the root of the atomic window as its argument. -If @var{window} is a non-side window (@pxref{Side Windows}), it makes -@var{window} the only non-side window on its frame and leaves side -windows alone. If @var{window} is a side window, this function signals -an error. +Otherwise, if @var{window} is part of an atomic window (@pxref{Atomic +Windows}), it calls this function with the root of the atomic window as +its argument. If @var{window} is a non-side window (@pxref{Side +Windows}), it makes @var{window} the only non-side window on its frame +and leaves side windows alone. If @var{window} is a side window, this +function signals an error. @end deffn @deffn Command delete-windows-on &optional buffer-or-name frame @@ -1468,12 +1650,16 @@ The function @code{delete-windows-on} operates by calling @code{delete-window} for each window showing @var{buffer-or-name}. If a frame has several windows showing different buffers, then those showing @var{buffer-or-name} are removed, and the other windows expand to fill -the space. If all windows in some frame are showing -@var{buffer-or-name} (including the case where there is only one -window), then the frame winds up with a single window showing another -buffer. If, however, that last remaining window is dedicated to the -buffer specified by @var{buffer-or-name} (@pxref{Dedicated Windows}), -and there are other frames left, that window's frame is deleted. +the space. + +If all windows in some frame are showing @var{buffer-or-name} (including +the case where there is only one window), then that frame winds up with +a single window showing another buffer. If, however, that last +remaining window is dedicated to the buffer specified by +@var{buffer-or-name} (@pxref{Dedicated Windows}) or that window's +@code{quit-restore} parameter (@pxref{Window Parameters}) is set +appropriately, that window's frame is deleted provided there are other +frames left. The optional argument @var{frame} specifies which frames to operate on. This function does not use it in quite the same way as the other @@ -1822,14 +2008,16 @@ The basic, low-level function to associate a window with a buffer is @code{display-buffer} try to obey a number of user customizations regulating which windows are supposed to display which buffers. When writing an application, programmers should therefore carefully evaluate -whether they really need the power of this @code{set-window-buffer}. +whether they really need the power of @code{set-window-buffer}. @defun set-window-buffer window buffer-or-name &optional keep-margins This function makes @var{window} display @var{buffer-or-name} and returns @code{nil}. The argument @var{window} has to denote a live window and defaults to the selected one. The argument @var{buffer-or-name} must specify a buffer or the name of an existing -buffer. +buffer. An error is signalled when @var{window} is @dfn{strongly} +dedicated to its buffer (@pxref{Dedicated Windows}) and does not already +display @var{buffer-or-name}. Normally, displaying @var{buffer-or-name} in @var{window} resets the window's position, display margins, fringe widths, and scroll bar @@ -1838,14 +2026,10 @@ if the optional argument @var{keep-margins} is non-@code{nil}, display margins and fringe widths of @var{window} remain unchanged. @xref{Fringes}. -@code{set-window-buffer} is the fundamental primitive for changing which -buffer is displayed in a window, and all ways of doing that call this -function. Neither the selected window nor the current buffer are -changed by this function. - -@code{set-window-buffer} signals an error when @var{window} is -@dfn{strongly} dedicated to its buffer (@pxref{Dedicated Windows}) and -does not already display @var{buffer-or-name}. +This function is the fundamental primitive for changing which buffer is +displayed in a window, and all ways of doing that call this function. +Neither the selected window nor the current buffer are changed by this +function. This function runs @code{window-scroll-functions} before running @code{window-configuration-change-hook}, see @ref{Window Hooks}. @@ -1918,11 +2102,12 @@ The argument @var{buffer-or-name} may be a buffer or the name of an existing buffer and defaults to the current buffer. If a window displaying @var{buffer-or-name} is dedicated -(@pxref{Dedicated Windows}), and is not the only window on its frame, -that window is deleted. If that window is the only window on its frame -and there are other frames left, the window's frame is deleted too. If -there are no other frames left, some other buffer is displayed in that -window as explained above. +(@pxref{Dedicated Windows}) or its @code{quit-restore} parameter +(@pxref{Window Parameters}) is set appropriately, and the window is not +the only window on its frame, that window is deleted. If that window is +the only window on its frame and there are other frames left, the +window's frame is deleted too. If there are no other frames left, some +other buffer is displayed in that window as explained above. This function returns @code{nil}. @end deffn @@ -2372,7 +2557,7 @@ passed as second argument to that function---the first argument is the buffer that shall be displayed. The function is not passed any specifiers. -The function shoul choose or create a window, display the specified +The function should choose or create a window, display the specified buffer in it, and return the window. It is also responsible for giving the variable @code{display-buffer-window} a meaningful value, see below for an explanation. Moreover, the function should set up the @@ -4161,27 +4346,26 @@ only return a window whose @var{parameter} equals @var{value} too. @end defun -Some functions, notably @code{split-window}, @code{delete-window}, and -@code{delete-other-windows} behave specially when their @var{window} -argument has a parameter set. For example, @code{delete-window} when -invoked on the main window of an atomic window (@pxref{Atomic Windows}) -calls @code{delete-window} with the root window of the atomic window as -argument instead. The entire information for retrieving the appropriate -root window is maintained with the help of window parameters. +Some functions, notably @code{delete-window}, +@code{delete-other-windows} and @code{split-window} may behave specially +when their @var{window} argument has a parameter set. For example, +@code{delete-window}, when invoked on a subwindow of an atomic window +(@pxref{Atomic Windows}), calls itself with the root of the atomic +window as argument instead. -You can override that special behavior by binding the following variable +You can override such special behavior by binding the following variable to a non-@code{nil} value: @defvar ignore-window-parameters -If this variable is non-@code{nil}, some standard functions ignore -window parameters. The functions currently affected by this are +If this variable is non-@code{nil}, some standard functions do not +process window parameters. The functions currently affected by this are @code{split-window}, @code{delete-window}, @code{delete-other-windows} and @code{other-window}. An application can bind this variable to a non-@code{nil} value around calls to these functions. If it does so, the application is fully -responsible for correctly assigning the parameters of windows when -exiting that function. +responsible for correctly assigning the parameters of all involved +windows when exiting that function. @end defvar The following parameters are currently used by the window management @@ -4189,28 +4373,28 @@ code. @table @asis @item @code{window-atom} -This symbol designates the associated window as part of an atomic +This parameter designates the associated window as part of an atomic window (@pxref{Atomic Windows}). @item @code{window-side} -This symbol designates the associated window as part of a side or +This parameter designates the associated window as part of a side or non-side window (@pxref{Side Windows}). -@item @code{delete-window-function} -This parameter is used by @code{delete-window} (@pxref{Deleting -Windows}). +@item @code{delete-window} +This parameter affects the execution of @code{delete-window} +(@pxref{Deleting Windows}). -@item @code{delete-other-windows-function} -This parameter is used by @code{delete-other-windows} (@pxref{Deleting -Windows}). +@item @code{delete-other-windows} +This parameter affects the execution of @code{delete-other-windows} +(@pxref{Deleting Windows}). -@item @code{split-window-function} -This parameter is used by @code{split-window} (@pxref{Splitting -Windows}). +@item @code{split-window} +This parameter affects the execution of @code{split-window} +(@pxref{Splitting Windows}). -@item @code{other-window-function} -This parameter is used by @code{other-window} (@pxref{Cyclic Window -Ordering}). +@item @code{other-window} +This parameter affects the execution of @code{other-window} +(@pxref{Cyclic Window Ordering}). @item @code{no-other-window} This parameter marks the window as not selectable by @code{other-window} @@ -4218,41 +4402,33 @@ This parameter marks the window as not selectable by @code{other-window} @end table The @code{quit-restore} parameter tells how to proceed with a window -when the user ``quits'' it by invoking @code{quit-restore-window}, see -@ref{Displaying Buffers}. The following non-@code{nil} values of this -parameter have a special meaning. - -@table @asis -@item @code{t} -This means to delete the associated window. By default, @code{t} is -used for a ``temporary'' window that was obtained by splitting an -existing window. - -@item @code{frame} -This means to delete the associated window's frame. This value -indicates that the associated windows was obtained by popping up a new -frame showing just this window. If the window is no more needed, it -should be deleted together with the containing frame. - -@item A list -This option is useful when the associated window was borrowed to -temporarily display some buffer and quitting shall ``restore'' the -previous contents of the window. The first three elements of the list -must specify a buffer, a window start position, and a window point. -Quitting the window will then try to display the indicated buffer with -the given start position and point in that window. - - The fourth element, if non-@code{nil}, must denote a live buffer. If -specified, quitting will restore the previous window contents if and -only if the buffer shown in the window is the buffer named by this -element. - - The fifth element, if non-@code{nil}, should specify the desired -height of the window when its buffer is restored. This value is applied -if the buffer temporarily shown in the window was in -@code{temp-buffer-resize-mode} to restore the original height of the -window. -@end table +when the buffer it shows is no more needed. This parameter is installed +by the buffer display functions (@pxref{Displaying Buffers}) and +consulted by functions that remove a buffer from display like +@code{delete-windows-on} (@pxref{Deleting Windows}), +@code{replace-buffer-in-windows} (@pxref{Buffers and Windows}), and +@code{quit-restore-window} (@pxref{Displaying Buffers}). The parameter +should be a list which is interpreted as sketched next. + + If the first element of the list is the symbol @code{new-window}, +this means that the window was specially created for displaying a +buffer. The second element of the list specifies that buffer, and the +third element is the window selected at the time this window was +created. The standard action in this case is to delete the window +provided its frame contains at least on other window. + + If the first element of the list is the symbol @code{new-frame}, this +means that the associated frame was created for displaying a buffer. +The remaining elements are as above. The standard action in this case +is to delete the frame provided there are other frames left. + + In any other case, the list should consist of five elements: A buffer +that was shown in the window before, the start position of that buffer +in the window, the position of @code{window-point} for that buffer in +the window, the total height of the window before another buffer was +displayed in it, and the window selected at the time that other buffer +was displayed. The standard action here is to keep the window alive and +to restore its contents to the state provided by these elements. @node Atomic Windows @@ -4502,8 +4678,20 @@ dominating side window on the left, for example, use the function If you create side windows by calling @code{display-buffer} (@pxref{Displaying Buffers}) with the @code{use-side-window} specifier, -this will set up these parameters automatically. If you want to manage -side windows manually, you should preserve the following invariants: +this will set up these parameters automatically. For example + +@example +(display-buffer + (get-buffer-create "*bar*") + '((use-side-window bottom 0) + (pop-up-window-set-height . 6))) +@end example + +can be used to display a buffer ``*bar*'' in a six lines high +side-window at the bottom of the selected frame. + +If you intend to manage side windows manually, you should preserve the +following invariants: @itemize @bullet @item @@ -4525,8 +4713,9 @@ parameter set to such a value and have a parent window whose @code{window-side} parameter is @code{nil}. @item -Live windows whose @code{window-side} parameter is @code{nil} are -invalid. +If a frame contains at least one window with a non-@code{nil} +@code{window-side} parameter, the @code{window-side} parameter of all +other live windows must be non-@code{nil} as well. @end itemize If a setup of @code{window-side} parameters fails to satisfy these diff --git a/etc/NEWS b/etc/NEWS index 98a66259db0..6693abea6a4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -284,6 +284,141 @@ If you need it, feedmail.el ought to provide a superset of the functionality. ** The variable `focus-follows-mouse' now always defaults to nil. ++++ +** Window handling code. + +*** Window tree functions accessible in Elisp. +You can use functions to return the parent, siblings or child windows of +any window including internal windows (windows not associated with a +buffer) in the window tree. `walk-window-tree' is a new function for +traversing window trees. + +*** Window handling code moved to Elisp. +Splitting, resizing, and deleting window is mostly done in Elisp now. +The parts remaining in C deal only with checking the validity of these +operations wrt the window tree and window sizes. + +*** Window manipulations can deal with internal windows. +Many window handling functions like `split-window', `delete-window', or +`delete-other-windows' as well as the window resizing functions can now +act on any window including internal ones. + +*** window-total-height/-width vs window-body-height/-width. +The function `window-height' has been renamed to `window-total-height' +and `window-width' has been renamed to `window-body-width'. Two new +functions `window-total-width' and `window-body-height' are provided. + +*** Window parameters specific to window handling functions. +For each window you can specify a parameter to override the default +behavior of a number of functions like `split-window', `delete-window' +and `delete-other-windows'. + +*** New semantics of third argument of `split-window'. +The third argument of `split-window' can be set to any of the values +'below, 'right, 'above, or 'left to make the new window appear on the +corresponding side of the window that shall be split. + +*** New option `window-nest'. +The new option `window-nest' allows to return the space obtained for +resizing or creating a window more reliably to the window from which +such space was obtained. + +*** New option `window-splits'. +The new option `window-splits' allows to split a window that otherwise +cannot be split because it's too small by stealing space from other +windows in the same combination. + +*** `split-window-above-each-other' and `split-window-side-by-side'. +The commands `split-window-vertically' and `split-window-horizontally' +have been renamed to `split-window-above-each-other' and +`split-window-side-by-side' respectively. The old names are provided as +aliases. + +*** Window resizing functions. +A new standard function for resizing windows called `resize-window' has +been introduced. This and all other functions for resizing windows no +longer delete any windows when they become too small. + +*** Frame/window resizing. +Resizing an Emacs frame now preserves the proportional sizes of +subwindows modulo restrictions imposed by window minimum sizes and +fixed-size windows. + +*** `adjust-window-trailing-edge' adjustments. +`adjust-window-trailing-edge' can now deal with fixed-size windows and +is able to resize other windows if a window adjacent to the trailing +edge cannot be shrunk any more. This makes its behavior more similar to +that of Emacs 21 without compromising, however, the latter's inability +to delete windows which was introduced in Emacs 22. + +*** Commands for maximizing and minimizing windows. +New functions to maximize and minimize a window within its frame are +provided, namely `maximize-window' and `minimize-window'. + +*** Window-local buffer lists. +Windows now have local buffer lists. This means that removing a buffer +from display in a window will preferably show the buffer previously +shown in that window with its previous window-start and window-point +positions. This also means that the same buffer may be automatically +shown twice even if it already appears in another window. + +*** New commands `switch-to-prev-buffer' and `switch-to-next-buffer'. +These functions allow to navigate through the live buffers that have +been shown in a specific window. + +*** New window parameter `quit-restore'. +Functions to remove a buffer from display like `delete-windows-on' or +`replace-buffer-in-windows' now respect the `quit-restore' window +parameter which tells how to proceed with the window: Delete it, delete +its frame, or display some previously shown buffer in it. This means +that you don't have to dedicate a window to its buffer to obtain the +corresponding behavior, setting its `quit-restore' parameter suffices. + +*** New command `quit-restore-window'. +This function explicitly restores the state of one specific window +consulting its `quit-restore' window parameter. Among others, it is +now also called when exiting view-mode. + +*** Buffer display specifiers. +Customizing the display of buffers is now handled with the help of +buffer display specifiers. These specifiers are customizable via the +option `display-buffer-alist' and completely obsolete all existing +`display-buffer' related options like, `pop-up-windows', `pop-up-frames' +`display-buffer-reuse-frames' or `split-height-threshold'. Buffer +display specifiers also allow to specify a number of new options to +choose, for example, the desired position of a new window or its size. + +*** Arguments of `display-buffer'. +The second argument of `display-buffer' now accepts a list of buffer +display specifiers. A new third argument accepts a label to identify +buffers whose names are not expressive enough. + +*** Functions for displaying and popping and switching to buffers. +The `display-buffer', `pop-to-buffer' and `switch-to-buffer' families of +functions are all based on buffer display specifiers now. A number of +new functions with unified mnemnonics like `display-buffer-same-frame', +`pop-to-buffer-same-frame' and `switch-to-buffer-same-frame' have been +added. By convention, functions in the `switch-to-buffer' family are +now recommended for interactive use only. Application are supposed to +use function from the `pop-to-buffer' family instead. + +*** Atomic windows. +Atomic windows are internal windows that are treated by a number of +functions like `split-window', `delete-window' and +`delete-other-windows' atomically. This means that any of these +operations when applied to a subwindow of the atomic window is applied +to the entire atomic window instead. Atomic windows can be either +created automatically with the help of buffer display specifiers or +manually via the `window-atom' window parameter. + +*** Side windows. +Side windows are special windows located at one of the four sides of a +frame. Side windows are useful for assigning buffers always the same +location within a frame whenever they are shown there. Side windows are +by default semi-permanent which means that functions like +`delete-other-windows' do not delete them. Side windows can be either +created automatically with the help of buffer display specifiers or +manually via the `window-side' window parameter. * Editing Changes in Emacs 24.1 diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e9002a66b5c..2b32237f3e0 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,25 @@ +2011-05-30 Martin Rudalics + + * window.el (ignore-window-parameters, window-size-fixed): + Rewrite doc-strings. + (window-min-delta-1, window-min-delta): Reorder. Minor rewrite. + (resize-subwindows-normal): Use zerop when checking other-delta. + Call window-min-delta with NODOWN argument nil. + (adjust-window-trailing-edge): Fix doc-string. + (other-window): Fix doc-string and respect + ignore-window-parameters. + (delete-window, delete-other-windows): Fix doc-strings. Remove + -function postfix from associated window parameters. + (quit-restore-window): Resize only if buffer was in + temp-buffer-resize-mode. + (window-split-min-size): Rewrite doc-string. + (split-window): Rewrite doc-string. Rename horflag to + horizontal. Major rewrite of size calculations. Remove + -function postfix from associated window parameter. + (window-state-put-1, display-buffer-split-window-1): Rename + horflag to horizontal. + (same-window-p): Remove call to non-existent function. + 2011-05-21 Glenn Morris * image-mode.el (image-after-revert-hook): diff --git a/lisp/dired.el b/lisp/dired.el index d63227a8be1..1864ef94853 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -3617,7 +3617,7 @@ Ask means pop up a menu for the user to select one of copy, move or link." ;;;;;; dired-run-shell-command dired-do-shell-command dired-do-async-shell-command ;;;;;; dired-clean-directory dired-do-print dired-do-touch dired-do-chown ;;;;;; dired-do-chgrp dired-do-chmod dired-compare-directories dired-backup-diff -;;;;;; dired-diff) "dired-aux" "dired-aux.el" "e34e1bbdb701078d52466c319d8e0cda") +;;;;;; dired-diff) "dired-aux" "dired-aux.el" "7efcfe4f9e0913ae4a87be014010c27f") ;;; Generated autoloads from dired-aux.el (autoload 'dired-diff "dired-aux" "\ diff --git a/lisp/window.el b/lisp/window.el index ef9c1869dfe..245ad23f414 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -146,23 +146,12 @@ WINDOW must be a live window and defaults to the selected one." (selected-window))) (defvar ignore-window-parameters nil - "If non-nil standard functions ignore window parameters. + "If non-nil, standard functions ignore window parameters. The functions currently affected by this are `split-window', `delete-window', `delete-other-windows' and `other-window'. -When this variable equals `pre', parameters are not consulted -before but are updated after performing the requested operation. -When this variable equals `post', parameters are consulted before -but are not updated after performing the requested operation. - -The value t means parameters are not consulted before and not -updated after performing the requested operation. Currently any -other non-nil value is handled like t. - An application may bind this to a non-nil value around calls to -these functions. If it does so and the value is not `pre', the -application is fully responsible for correctly setting the -parameters of all windows participating in the function called.") +these functions to inhibit processing of window parameters.") (defconst window-safe-min-height 1 "The absolut minimum number of lines of a window. @@ -675,9 +664,10 @@ FRAME defaults to the selected frame." If the value is `height', then only the window's height is fixed. If the value is `width', then only the window's width is fixed. Any other non-nil value fixes both the width and the height. + Emacs won't change the size of any window displaying that buffer, -unless you explicitly change the size, or Emacs has no other -choice \(like when deleting a neighboring window).") +unless it has no other choice \(like when deleting a neighboring +window).") (make-variable-buffer-local 'window-size-fixed) (defsubst window-size-ignore (window ignore) @@ -858,55 +848,19 @@ WINDOW can be resized in the desired direction. The functions (window-size-fixed-1 (normalize-any-window window) horizontal)) -(defun window-min-delta (&optional window horizontal ignore trail noup nodown) - "Return number of lines by which WINDOW can be shrunk. -WINDOW can be an arbitrary window and defaults to the selected -window. Return zero if WINDOW cannot be shrunk. - -Optional argument HORIZONTAL non-nil means return number of -columns by which WINDOW can be shrunk. - -Optional argument IGNORE non-nil means ignore any restrictions -imposed by fixed size windows, `window-min-height' or -`window-min-width' settings. IGNORE a window means ignore -restrictions for that window only. IGNORE equal `safe' means -live windows may get as small as `window-safe-min-height' lines -and `window-safe-min-width' columns. - -Optional argument TRAIL `before' means only windows to the left -of or above WINDOW can be enlarged. Optional argument TRAIL -`after' means only windows to the right of or below WINDOW can be -enlarged. - -Optional argument NOUP non-nil means don't go up in the window -tree but try to enlarge windows within WINDOW's combination only. - -Optional argument NODOWN non-nil means don't check whether WINDOW -and its subwindows can be shrunk." - (setq window (normalize-any-window window)) - (let ((size (window-total-size window horizontal)) - (minimum (window-min-size window horizontal ignore))) - (if (and (not nodown) (= size minimum)) - ;; Nothing to recover. - 0 - (window-min-delta-1 - ;; Think positive. - window (- size minimum) horizontal ignore trail noup)))) - (defun window-min-delta-1 (window delta &optional horizontal ignore trail noup) "Internal function for `window-min-delta'." (if (not (window-parent window)) - 0 ; delta - ;;; (min delta - ;;; (- (window-total-size window horizontal) - ;;; (window-min-size window horizontal ignore))) + ;; If we can't go up, return zero. + 0 + ;; Else try to find a non-fixed-size sibling of WINDOW. (let* ((parent (window-parent window)) (sub (window-child parent))) (catch 'done (if (window-iso-combined-p sub horizontal) ;; In an iso-combination throw DELTA if we find at least one - ;; subwindow and that subwindow is either non-fixed-size or - ;; we can ignore fixed-sizeness. + ;; subwindow and that subwindow is either not of fixed-size + ;; or we can ignore fixed-sizeness. (let ((skip (eq trail 'after))) (while sub (cond @@ -932,13 +886,13 @@ and its subwindows can be shrunk." delta (window-min-delta-1 parent delta horizontal ignore trail)))))) -(defun window-max-delta (&optional window horizontal ignore trail noup nodown) - "Return maximum number of lines WINDOW by which WINDOW can be enlarged. +(defun window-min-delta (&optional window horizontal ignore trail noup nodown) + "Return number of lines by which WINDOW can be shrunk. WINDOW can be an arbitrary window and defaults to the selected -window. The return value is zero if WINDOW cannot be enlarged. +window. Return zero if WINDOW cannot be shrunk. -Optional argument HORIZONTAL non-nil means return maximum number -of columns by which WINDOW can be enlarged. +Optional argument HORIZONTAL non-nil means return number of +columns by which WINDOW can be shrunk. Optional argument IGNORE non-nil means ignore any restrictions imposed by fixed size windows, `window-min-height' or @@ -948,21 +902,32 @@ live windows may get as small as `window-safe-min-height' lines and `window-safe-min-width' columns. Optional argument TRAIL `before' means only windows to the left -of or below WINDOW can be shrunk. Optional argument TRAIL -`after' means only windows to the right of or above WINDOW can be -shrunk. +of or above WINDOW can be enlarged. Optional argument TRAIL +`after' means only windows to the right of or below WINDOW can be +enlarged. Optional argument NOUP non-nil means don't go up in the window -tree but try to obtain the entire space from windows within -WINDOW's combination. +tree but try to enlarge windows within WINDOW's combination only. -Optional argument NODOWN non-nil means do not check whether -WINDOW and its subwindows can be enlarged." +Optional argument NODOWN non-nil means don't check whether WINDOW +itself \(and its subwindows) can be shrunk; check only whether at +least one other windows can be enlarged appropriately." (setq window (normalize-any-window window)) - (if (and (not (window-size-ignore window ignore)) - (not nodown) (window-size-fixed-p window horizontal)) - 0 - (window-max-delta-1 window 0 horizontal ignore trail noup))) + (let ((size (window-total-size window horizontal)) + (minimum (window-min-size window horizontal ignore))) + (cond + (nodown + ;; If NODOWN is t, try to recover the entire size of WINDOW. + (window-min-delta-1 window size horizontal ignore trail noup)) + ((= size minimum) + ;; If NODOWN is nil and WINDOW's size is already at its minimum, + ;; there's nothing to recover. + 0) + (t + ;; Otherwise, try to recover whatever WINDOW is larger than its + ;; minimum size. + (window-min-delta-1 + window (- size minimum) horizontal ignore trail noup))))) (defun window-max-delta-1 (window delta &optional horizontal ignore trail noup) "Internal function of `window-max-delta'." @@ -996,10 +961,48 @@ WINDOW and its subwindows can be enlarged." (throw 'fixed delta)) (setq sub (window-right sub)))) (if noup + ;; When NOUP is nil, DELTA is all we can get. delta - ;; Try to go up. + ;; Else try with parent of WINDOW, passing the DELTA we + ;; recovered so far. (window-max-delta-1 parent delta horizontal ignore trail)))))) +(defun window-max-delta (&optional window horizontal ignore trail noup nodown) + "Return maximum number of lines WINDOW by which WINDOW can be enlarged. +WINDOW can be an arbitrary window and defaults to the selected +window. The return value is zero if WINDOW cannot be enlarged. + +Optional argument HORIZONTAL non-nil means return maximum number +of columns by which WINDOW can be enlarged. + +Optional argument IGNORE non-nil means ignore any restrictions +imposed by fixed size windows, `window-min-height' or +`window-min-width' settings. IGNORE a window means ignore +restrictions for that window only. IGNORE equal `safe' means +live windows may get as small as `window-safe-min-height' lines +and `window-safe-min-width' columns. + +Optional argument TRAIL `before' means only windows to the left +of or below WINDOW can be shrunk. Optional argument TRAIL +`after' means only windows to the right of or above WINDOW can be +shrunk. + +Optional argument NOUP non-nil means don't go up in the window +tree but try to obtain the entire space from windows within +WINDOW's combination. + +Optional argument NODOWN non-nil means do not check whether +WINDOW itself \(and its subwindows) can be enlarged; check only +whether other windows can be shrunk appropriately." + (setq window (normalize-any-window window)) + (if (and (not (window-size-ignore window ignore)) + (not nodown) (window-size-fixed-p window horizontal)) + ;; With IGNORE and NOWDON nil return zero if WINDOW has fixed + ;; size. + 0 + ;; WINDOW has no fixed size. + (window-max-delta-1 window 0 horizontal ignore trail noup))) + ;; Make NOUP also inhibit the min-size check. (defun window-resizable (window delta &optional horizontal ignore trail noup nodown) "Return DELTA if WINDOW can be resized vertically by DELTA lines. @@ -1648,9 +1651,9 @@ OTHER-DELTA a number specifies that this many lines \(columns) have been obtained from \(or returned to) an ancestor window of PARENT in order to resize WINDOW." (let* ((delta-normal - (if (and (not other-delta) - (= (- this-delta) (window-total-size window horizontal))) - ;; When WINDOW gest deleted and we can return its entire + (if (and (= (- this-delta) (window-total-size window horizontal)) + (zerop other-delta)) + ;; When WINDOW gets deleted and we can return its entire ;; space to its siblings, use WINDOW's normal size as the ;; normal delta. (- (window-normal-size window horizontal)) @@ -1820,7 +1823,8 @@ already set by this routine." (set-window-new-normal sub (cons - (window-min-delta sub horizontal ignore trail t t) + ;; We used to call this with NODOWN t, "fixed" 2011-05-11. + (window-min-delta sub horizontal ignore trail t) ; t) (- (/ (float (window-total-size sub horizontal)) parent-total) (window-normal-size sub horizontal))))) @@ -2105,8 +2109,10 @@ any windows." Optional argument HORIZONTAL non-nil means move WINDOW's right edge by DELTA columns. WINDOW defaults to the selected window. -If the edge can't be moved by DELTA lines, move it as far as -possible in the desired direction." +If DELTA is greater zero, then move the edge downwards or to the +right. If DELTA is less than zero, move the edge upwards or to +the left. If the edge can't be moved by DELTA lines or columns, +move it as far as possible in the desired direction." (setq window (normalize-any-window window)) (let ((frame (window-frame window)) (right window) @@ -2290,8 +2296,6 @@ TOP RIGHT BOTTOM) as returned by `window-edges'." (setq frame (normalize-live-frame frame)) (window-tree-1 (frame-root-window frame) t)) -;;; Getting the "other" window. -;; FIXME: Handle `ignore-window-parameters' and some other things maybe. (defun other-window (count &optional all-frames) "Select another window in cyclic ordering of windows. COUNT specifies the number of windows to skip, starting with the @@ -2301,10 +2305,12 @@ skip -COUNT windows backwards. COUNT zero means do not skip any window, so select the selected window. In an interactive call, COUNT is the numeric prefix argument. Return nil. -Do not select a window whose `no-other-window' window parameter -is non-nil. If the `other-window-function' parameter of WINDOW -is a function call that function with the arguments COUNT and -ALL-FRAMES. +If the `other-window' parameter of WINDOW is a function and +`ignore-window-parameters' is nil, call that function with the +arguments COUNT and ALL-FRAMES. + +This function does not select a window whose `no-other-window' +window parameter is non-nil. This function uses `next-window' for finding the window to select. The argument ALL-FRAMES has the same meaning as in @@ -2312,7 +2318,8 @@ select. The argument ALL-FRAMES has the same meaning as in always effectively nil." (interactive "p") (let* ((window (selected-window)) - (function (window-parameter window 'other-window-function)) + (function (and (not ignore-window-parameters) + (window-parameter window 'other-window))) old-window old-count) (if (functionp function) (funcall function count all-frames) @@ -2354,6 +2361,7 @@ always effectively nil." (setq count (1+ count))))) (select-window window) + ;; Always return nil. nil)))) ;; This should probably return non-nil when the selected window is part @@ -2438,13 +2446,12 @@ instead." WINDOW can be an arbitrary window and defaults to the selected one. Return nil. -If `ignore-window-parameters' is non-nil, ignore any parameters -of WINDOW. Otherwise, if the `delete-window-function' parameter -of WINDOW equals t, delete WINDOW ignoring any other window -parameters. If the `delete-window-function' parameter specifies -a function, call that function with WINDOW as its sole argument. -It's the responsibility of that function to adjust the parameters -of all remaining windows. +If the variable `ignore-window-parameters' is non-nil or the +`delete-window' parameter of WINDOW equals t, do not process any +parameters of WINDOW. Otherwise, if the `delete-window' +parameter of WINDOW specifies a function, call that function with +WINDOW as its sole argument and return the value returned by that +function. Otherwise, if WINDOW is part of an atomic window, call `delete-window' with the root of the atomic window as its @@ -2453,7 +2460,7 @@ non-side window, signal an error." (interactive) (setq window (normalize-any-window window)) (let* ((frame (window-frame window)) - (function (window-parameter window 'delete-window-function)) + (function (window-parameter window 'delete-window)) (parent (window-parent window)) atom-root) (window-check frame) @@ -2461,12 +2468,12 @@ non-side window, signal an error." ;; Handle window parameters. (cond ;; Ignore window parameters if `ignore-window-parameters' tells - ;; us so or `delete-window-function' equals t. + ;; us so or `delete-window' equals t. ((or ignore-window-parameters (eq function t))) ((functionp function) - ;; The `delete-window-function' parameter specifies the function - ;; to call. If that function is `ignore' nothing is done. It's - ;; up to the function called here to avoid infinite recursion. + ;; The `delete-window' parameter specifies the function to call. + ;; If that function is `ignore' nothing is done. It's up to the + ;; function called here to avoid infinite recursion. (throw 'done (funcall function window))) ((and (window-parameter window 'window-atom) (setq atom-root (window-atom-root window)) @@ -2496,7 +2503,7 @@ non-side window, signal an error." 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. + ;; Can do without resizing fixed-size windows. (resize-other-windows window (- size) horizontal)) (t ;; Can't do without resizing fixed-size windows. @@ -2509,9 +2516,9 @@ non-side window, signal an error." ;; `delete-window-internal' has selected a window that should ;; not be selected, fix this here. (other-window -1 frame)) - (run-window-configuration-change-hook frame) (window-check frame) + ;; Always return nil. nil)))) (defun delete-other-windows (&optional window) @@ -2519,14 +2526,12 @@ non-side window, signal an error." WINDOW may be any window and defaults to the selected one. Return nil. -If the variable `ignore-window-parameters' is non-nil do not +If the variable `ignore-window-parameters' is non-nil or the +`delete-other-windows' parameter of WINDOW equals t, do not process any parameters of WINDOW. Otherwise, if the -`delete-other-windows-function' parameter of WINDOW equals t, -delete WINDOW ignoring other window parameters. If the -`delete-other-windows-function' parameter specifies a function, -call that function with WINDOW as its sole argument. It's the -responsibility of that function to adjust the parameters of all -remaining windows. +`delete-other-windows' parameter of WINDOW specifies a function, +call that function with WINDOW as its sole argument and return +the value returned by that function. Otherwise, if WINDOW is part of an atomic window, call this function with the root of the atomic window as its argument. If @@ -2536,20 +2541,19 @@ window signal an error." (interactive) (setq window (normalize-any-window window)) (let* ((frame (window-frame window)) - (function (window-parameter window 'delete-other-windows-function)) + (function (window-parameter window 'delete-other-windows)) (window-side (window-parameter window 'window-side)) atom-root side-main) (window-check frame) (catch 'done (cond ;; Ignore window parameters if `ignore-window-parameters' is t or - ;; `delete-other-windows-function' is t. + ;; `delete-other-windows' is t. ((or ignore-window-parameters (eq function t))) ((functionp function) - ;; The `delete-other-windows-function' parameter specifies the - ;; function to call. If the function is `ignore' no windows are - ;; deleted. It's up to the function called to avoid infinite - ;; recursion. + ;; The `delete-other-windows' parameter specifies the function + ;; to call. If the function is `ignore' no windows are deleted. + ;; It's up to the function called to avoid infinite recursion. (throw 'done (funcall function window))) ((and (window-parameter window 'window-atom) (setq atom-root (window-atom-root window)) @@ -2560,11 +2564,12 @@ window signal an error." (setq side-main (window-with-parameter 'window-side 'none nil t))) ((memq window-side window-sides) (error "Cannot make side window the only window"))) - + ;; If WINDOW is the main non-side window, do nothing. (unless (eq window side-main) (delete-other-windows-internal window side-main) (run-window-configuration-change-hook frame) (window-check frame)) + ;; Always return nil. nil))) (defun delete-other-windows-vertically (&optional window) @@ -2978,12 +2983,9 @@ frames left." ;; In window switch to previous buffer. (set-window-dedicated-p window nil) (switch-to-prev-buffer window 'bury)))) - ;; If a window doesn't show BUFFER, unrecord it nevertheless. + ;; If a window doesn't show BUFFER, unrecord BUFFER in it. (unrecord-window-buffer window buffer))))) -;;; (defun delete-buffer-window (&optional buffer-or-name frames) -;;; .... WRITE THIS - (defun replace-buffer-in-windows (&optional buffer-or-name) "Replace BUFFER-OR-NAME with some other buffer in all windows showing it. BUFFER-OR-NAME may be a buffer or the name of an existing buffer @@ -3033,7 +3035,7 @@ buffer list. Interactively, KILL is the prefix argument." (setq window (normalize-live-window window)) (let ((buffer (window-buffer window)) (quit-restore (window-parameter window 'quit-restore)) - deletable) + deletable resize) (cond ((and (or (and (memq (car-safe quit-restore) '(new-window new-frame)) ;; Check that WINDOW's buffer is still the same. @@ -3053,9 +3055,9 @@ buffer list. Interactively, KILL is the prefix argument." ((and (buffer-live-p (nth 0 quit-restore)) ;; The buffer currently shown in WINDOW must still be the ;; buffer shown when its `quit-restore' parameter was created - ;; in the first place. Leave WINDOW's quit-restore parameter - ;; alone, it can be reused later. + ;; in the first place. (eq (window-buffer window) (nth 3 quit-restore))) + (setq resize (with-current-buffer buffer temp-buffer-resize-mode)) ;; Unrecord buffer. (unrecord-buffer buffer) (unrecord-window-buffer window buffer) @@ -3064,9 +3066,10 @@ buffer list. Interactively, KILL is the prefix argument." (set-window-buffer window (nth 0 quit-restore)) (set-window-start window (nth 1 quit-restore)) (set-window-point window (nth 2 quit-restore)) - (unless (= (nth 4 quit-restore) (window-total-size window)) + (when (and resize (/= (nth 4 quit-restore) (window-total-size window))) (resize-window window (- (nth 4 quit-restore) (window-total-size window)))) + ;; Reset the quit-restore parameter. (set-window-parameter window 'quit-restore nil) (when (window-live-p (nth 5 quit-restore)) (select-window (nth 5 quit-restore)))) @@ -3082,28 +3085,25 @@ buffer list. Interactively, KILL is the prefix argument." nil)) ;;; Splitting windows. -(defsubst window-split-min-size (&optional horflag) - "Return minimum height of any window. -Optional argument HORFLAG non-nil means return minimum width." - (if horflag +(defsubst window-split-min-size (&optional horizontal) + "Return minimum height of any window when splitting windows. +Optional argument HORIZONTAL non-nil means return minimum width." + (if horizontal (max window-min-width window-safe-min-width) (max window-min-height window-safe-min-height))) (defun split-window (&optional window size side) - "Create a new window adjacent to WINDOW. -WINDOW can be any window and defaults to the selected one. If -WINDOW was selected before invoking this function, it remains -selected. Return the new window which is always a live window. + "Make a new window adjacent to WINDOW. +WINDOW can be any window and defaults to the selected one. +Return the new window which is always a live window. Optional argument SIZE a positive number means make WINDOW SIZE -lines/columns tall. If SIZE is negative, make the new window --SIZE lines/columns tall. If and only if SIZE is non-nil, its +lines or columns tall. If SIZE is negative, make the new window +-SIZE lines or columns tall. If and only if SIZE is non-nil, its absolute value can be less than `window-min-height' or `window-min-width'; so this command can make a new window as small as one line or two columns. SIZE defaults to half of -WINDOW's size. The variable `window-splits' determines whether -the size of any other windows is affected. Interactively, SIZE -is the prefix argument. +WINDOW's size. Interactively, SIZE is the prefix argument. Optional third argument SIDE nil (or `below') specifies that the new window shall be located below WINDOW. SIDE `above' means the @@ -3120,69 +3120,90 @@ window provided SIZE is negative) including space reserved for fringes and the scrollbar or a divider column. Any other non-nil value for SIDE is currently handled like t (or `right'). -If WINDOW is part of an atomic window, \"split\" the root of the -atomic window instead. The new window does not become a member -of the atomic window. If WINDOW is a side window, signal an -error. - -If you split a live window, properties of the new window like -margins and scrollbars are inherited from WINDOW. If you split -an internal window, these properties as well as the buffer -displayed in the new window are inherited from the window -selected on WINDOW's frame." +If the variable `ignore-window-parameters' is non-nil or the +`split-window' parameter of WINDOW equals t, do not process any +parameters of WINDOW. Otherwise, if the `split-window' parameter +of WINDOW specifies a function, call that function with all three +arguments and return the value returned by that function. + +Otherwise, if WINDOW is part of an atomic window, \"split\" the +root of that atomic window. The new window does not become a +member of that atomic window. + +If WINDOW is live, properties of the new window like margins and +scrollbars are inherited from WINDOW. If WINDOW is an internal +window, these properties as well as the buffer displayed in the +new window are inherited from the window selected on WINDOW's +frame. The selected window is not changed by this function." (interactive "i") (setq window (normalize-any-window window)) - (let* ((horflag (and side (not (memq side '(below above))))) + (let* ((horizontal (not (memq side '(nil below above)))) (frame (window-frame window)) - (function (window-parameter window 'split-window-function)) - ;; Rebind this locally since in some cases we do have to nest. + (parent (window-parent window)) + (function (window-parameter window 'split-window)) + (window-side (window-parameter window 'window-side)) + ;; Rebind `window-nest' since in some cases we may have to + ;; override its value. (window-nest window-nest) atom-root) + (window-check frame) (catch 'done (cond - ;; Ignore window parameters if `ignore-window-parameters' is t or - ;; `split-window-function' is t. + ;; Ignore window parameters if either `ignore-window-parameters' + ;; is t or the `split-window' parameter equals t. ((or ignore-window-parameters (eq function t))) ((functionp function) - ;; The `split-window-function' parameter specifies the function - ;; to call instead. If this is `ignore', WINDOW won't be split. + ;; The `split-window' parameter specifies the function to call. + ;; If that function is `ignore', do nothing. (throw 'done (funcall function window size side))) - ;; For an atomic window split the entire atomic window instead. + ;; If WINDOW is a subwindow of an atomic window, split the root + ;; window of that atomic window instead. ((and (window-parameter window 'window-atom) (setq atom-root (window-atom-root window)) (not (eq atom-root window))) (throw 'done (split-window atom-root size side)))) - (let* ((parent (window-parent window)) - ;; Size calculations. - (parent-size - (when parent (window-total-size parent horflag))) - ;; Bind `old-size' to the current size of WINDOW and - ;; `new-size' to the size of the new window. - (old-size (window-total-size window horflag)) + (when (and window-side + (or (not parent) + (not (window-parameter parent 'window-side)))) + ;; WINDOW is a side root window. To make sure that a new parent + ;; window gets created set `window-nest' to t. + (setq window-nest t)) + + (when (and window-splits size (> size 0)) + ;; If `window-splits' is non-nil and SIZE is a non-negative + ;; integer, we cannot reasonably resize other windows. Rather + ;; bind `window-nest' to t to make sure that subsequent window + ;; deletions are handled correctly. + (setq window-nest t)) + + (let* ((parent-size + ;; `parent-size' is the size of WINDOW's parent, provided + ;; it has one. + (when parent (window-total-size parent horizontal))) + ;; `resize' non-nil means we are supposed to resize other + ;; windows in WINDOW's combination. (resize (and window-splits (not window-nest) ;; Resize makes sense in iso-combinations only. - (window-iso-combined-p window horflag) - (or (not size) (< size 0) - ;; If SIZE is a non-negative integer, we cannot - ;; resize, bind `window-nest' to t instead to - ;; make sure that subsequent window deletions are - ;; handled correctly. - (and (setq window-nest t) nil)))) + (window-iso-combined-p window horizontal))) + ;; `old-size' is the current size of WINDOW. + (old-size (window-total-size window horizontal)) + ;; `new-size' is the specified or calculated size of the + ;; new window. (new-size (cond ((not size) - (max (window-split-min-size horflag) + (max (window-split-min-size horizontal) (if resize - ;; For a resizing split try to give the new - ;; window the average size of a window in this - ;; combination. + ;; When resizing try to give the new window the + ;; average size of a window in its combination. (min (- parent-size - (window-min-size parent horflag)) + (window-min-size parent horizontal)) (/ parent-size - (1+ (window-iso-combinations parent horflag)))) + (1+ (window-iso-combinations + parent horizontal)))) ;; Else try to give the new window half the size ;; of WINDOW (plus an eventual odd line). (+ (/ old-size 2) (% old-size 2))))) @@ -3190,109 +3211,98 @@ selected on WINDOW's frame." ;; SIZE non-negative specifies the new size of WINDOW. ;; Note: Specifying a non-negative SIZE is practically - ;; always done to have a workaround for making the new - ;; window appear above or on the left of the new window - ;; (the ispell window is a typical example of that). In - ;; all these cases the SIDE argument should be set to - ;; 'above or 'left in order to support the 'resize - ;; option. Here we will nest the windows instead. + ;; always done as workaround for making the new window + ;; appear above or on the left of the new window (the + ;; ispell window is a typical example of that). In all + ;; these cases the SIDE argument should be set to 'above + ;; or 'left in order to support the 'resize option. + ;; Here we have to nest the windows instead, see above. (- old-size size)) (t ;; SIZE negative specifies the size of the new window. (- size)))) - (new-normal - ;; The normal size of the new window. - (cond - (size (/ (float new-size) - (or parent-size (window-total-size window horflag)))) - (resize (/ 1.0 (1+ (window-iso-combinations parent horflag)))) - (t (/ (window-normal-size window horflag) 2)))) - (root (window-parameter window 'root)) - (window-side (window-parameter window 'window-side))) - ;; 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-nest t) - (setq resize nil)) - - ;; Check the sizes. + new-parent new-normal) + + ;; Check SIZE. (cond ((not size) (cond (resize - ;; Size unspecified, resizing. - (when (and (not (window-sizable-p parent (- new-size) horflag)) - ;; Try agin with minimum acceptable size. + ;; SIZE unspecified, resizing. + (when (and (not (window-sizable-p parent (- new-size) horizontal)) + ;; Try again with minimum split size. (setq new-size - (max new-size - (window-split-min-size horflag))) - (not (window-sizable-p parent (- new-size) horflag))) - (error "Cannot resize %s" parent))) - ((> (+ new-size (window-min-size window horflag)) old-size) - ;; Size unspecified, no resizing. - (error "Cannot resize %s" window)))) + (max new-size (window-split-min-size horizontal))) + (not (window-sizable-p parent (- new-size) horizontal))) + (error "Window %s too small for splitting" parent))) + ((> (+ new-size (window-min-size window horizontal)) old-size) + ;; SIZE unspecified, no resizing. + (error "Window %s too small for splitting" window)))) ((and (>= size 0) (or (>= size old-size) - (< new-size (if horflag + (< new-size (if horizontal window-safe-min-width window-safe-min-width)))) - ;; Size specified as new size of old window. If the new size + ;; SIZE specified as new size of old window. If the new size ;; is larger than the old size or the size of the new window - ;; would be less than the safe minimum signal an error. - (error "Cannot resize %s" window)) + ;; would be less than the safe minimum, signal an error. + (error "Window %s too small for splitting" window)) (resize - ;; Size specified, resizing. - (unless (window-sizable-p parent (- new-size) horflag) + ;; SIZE specified, resizing. + (unless (window-sizable-p parent (- new-size) horizontal) ;; If we cannot resize the parent give up. - (error "Cannot resize %s" parent))) + (error "Window %s too small for splitting" parent))) ((or (< new-size - (if horflag window-safe-min-width window-safe-min-height)) + (if horizontal window-safe-min-width window-safe-min-height)) (< (- old-size new-size) - (if horflag window-safe-min-width window-safe-min-height))) - (error "Cannot resize %s" window))) + (if horizontal window-safe-min-width window-safe-min-height))) + ;; SIZE specification violates minimum size restrictions. + (error "Window %s too small for splitting" window))) - (resize-window-reset frame horflag) - (cond - (resize - ;; Try to get space from OLD's siblings. We could go "up" and - ;; try getting additional space from surrounding windows but - ;; we won't be able to return space to those windows when we - ;; delete the one we create here. Hence we do not go up. - (resize-subwindows parent (- new-size) horflag) - (let* ((normal (- 1 new-normal)) - (sub (window-child parent))) - (while sub - (set-window-new-normal - sub (* (window-normal-size sub horflag) normal)) - (setq sub (window-right sub))))) - (window-nest - ;; Get entire space from WINDOW making sure that a new parent - ;; windows gets created. - (set-window-new-total window (- old-size new-size)) - (resize-this-window window (- new-size) horflag) - (set-window-new-normal - window (- (window-normal-size window horflag) new-normal))) - (t - ;; Get entire space from WINDOW making a new parent window only - ;; if we need one. + (resize-window-reset frame horizontal) + + (setq new-parent + ;; Make new-parent non-nil if we need a new parent window; + ;; either because we want to nest or because WINDOW is not + ;; iso-combined. + (or window-nest (not (window-iso-combined-p window horizontal)))) + (setq new-normal + ;; Make new-normal the normal size of the new window. + (cond + (size (/ (float new-size) (if new-parent old-size parent-size))) + (new-parent 0.5) + (resize (/ 1.0 (1+ (window-iso-combinations parent horizontal)))) + (t (/ (window-normal-size window horizontal) 2.0)))) + + (if resize + ;; Try to get space from OLD's siblings. We could go "up" and + ;; try getting additional space from surrounding windows but + ;; we won't be able to return space to those windows when we + ;; delete the one we create here. Hence we do not go up. + (progn + (resize-subwindows parent (- new-size) horizontal) + (let* ((normal (- 1.0 new-normal)) + (sub (window-child parent))) + (while sub + (set-window-new-normal + sub (* (window-normal-size sub horizontal) normal)) + (setq sub (window-right sub))))) + ;; Get entire space from WINDOW. (set-window-new-total window (- old-size new-size)) - (resize-this-window window (- new-size) horflag) + (resize-this-window window (- new-size) horizontal) (set-window-new-normal - window (- (window-normal-size window horflag) new-normal)))) - - (let* ((new (split-window-internal window new-size side new-normal)) - (new-parent (window-parent new))) - (when window-side - ;; Inherit window-side parameters, if necessary. - (unless (eq parent new-parent) - (set-window-parameter new-parent 'window-side window-side)) + window (- (if new-parent 1.0 (window-normal-size window horizontal)) + new-normal))) + + (let* ((new (split-window-internal window new-size side new-normal))) + ;; Inherit window-side parameters, if any. + (when (and window-side new-parent) + (set-window-parameter (window-parent new) 'window-side window-side) (set-window-parameter new 'window-side window-side)) (run-window-configuration-change-hook frame) (window-check frame) + ;; Always return the new window. new))))) ;; I think this should be the default; I think people will prefer it--rms. @@ -3393,47 +3403,8 @@ The selected window remains selected. Return the new window." (defalias 'split-window-horizontally 'split-window-side-by-side) ;;; Balancing windows. -(defun balance-windows (&optional window-or-frame) - "Balance the sizes of subwindows of WINDOW-OR-FRAME. -WINDOW-OR-FRAME is optional and defaults to the selected frame. -If WINDOW-OR-FRAME denotes a frame, balance the sizes of all -subwindows of that frame's root window. If WINDOW-OR-FRAME -denots a window, balance the sizes of all subwindows of that -window." - (interactive) - (let* ((window - (cond - ((or (not window-or-frame) - (frame-live-p window-or-frame)) - (frame-root-window window-or-frame)) - ((or (window-live-p window-or-frame) - (window-child window-or-frame)) - window-or-frame) - (t - (error "Not a window or frame %s" window-or-frame)))) - (frame (window-frame window))) - ;; Balance vertically. - (resize-window-reset (window-frame window)) - (balance-windows-1 window) - (resize-window-apply frame) - ;; Balance horizontally. - (resize-window-reset (window-frame window) t) - (balance-windows-1 window t) - (resize-window-apply frame t))) -(defun balance-windows-1 (window &optional horizontal) - "Subroutine of `balance-windows'." - (if (window-child window) - (let ((sub (window-child window))) - (if (window-iso-combined-p sub horizontal) - (balance-windows-2 window horizontal) - (let ((size (window-new-total window))) - (while sub - (set-window-new-total sub size) - (balance-windows-1 sub horizontal) - (setq sub (window-right sub)))))))) - -;; The following routine uses the recycled code from the old version of +;; The following routine uses the recycled code from an old version of ;; `resize-subwindows'. It's not very pretty, but coding it the way the ;; new `resize-subwindows' code does would hardly make it any shorter or ;; more readable (FWIW we'd need three loops - one to calculate the @@ -3511,6 +3482,46 @@ WINDOW must be an iso-combination." (balance-windows-1 sub horizontal) (setq sub (window-right sub))))) +(defun balance-windows-1 (window &optional horizontal) + "Subroutine of `balance-windows'." + (if (window-child window) + (let ((sub (window-child window))) + (if (window-iso-combined-p sub horizontal) + (balance-windows-2 window horizontal) + (let ((size (window-new-total window))) + (while sub + (set-window-new-total sub size) + (balance-windows-1 sub horizontal) + (setq sub (window-right sub)))))))) + +(defun balance-windows (&optional window-or-frame) + "Balance the sizes of subwindows of WINDOW-OR-FRAME. +WINDOW-OR-FRAME is optional and defaults to the selected frame. +If WINDOW-OR-FRAME denotes a frame, balance the sizes of all +subwindows of that frame's root window. If WINDOW-OR-FRAME +denots a window, balance the sizes of all subwindows of that +window." + (interactive) + (let* ((window + (cond + ((or (not window-or-frame) + (frame-live-p window-or-frame)) + (frame-root-window window-or-frame)) + ((or (window-live-p window-or-frame) + (window-child window-or-frame)) + window-or-frame) + (t + (error "Not a window or frame %s" window-or-frame)))) + (frame (window-frame window))) + ;; Balance vertically. + (resize-window-reset (window-frame window)) + (balance-windows-1 window) + (resize-window-apply frame) + ;; Balance horizontally. + (resize-window-reset (window-frame window) t) + (balance-windows-1 window t) + (resize-window-apply frame t))) + (defun window-fixed-size-p (&optional window direction) "Return t if WINDOW cannot be resized in DIRECTION. WINDOW defaults to the selected window. DIRECTION can be @@ -3737,8 +3748,8 @@ value can be also stored on disk and read back in a new session." (setq window-state-put-list (cons (cons window state) window-state-put-list))) ((memq type '(vc hc)) - (let* ((horflag (eq type 'hc)) - (total (window-total-size window horflag)) + (let* ((horizontal (eq type 'hc)) + (total (window-total-size window horizontal)) (first t) size new) (dolist (item state) @@ -3755,23 +3766,23 @@ value can be also stored on disk and read back in a new session." (setq size (if totals ;; Use total size. - (cdr (assq (if horflag 'total-width 'total-height) item)) + (cdr (assq (if horizontal 'total-width 'total-height) item)) ;; Use normalized size and round. (round (* total (cdr (assq - (if horflag 'normal-width 'normal-height) + (if horizontal 'normal-width 'normal-height) item)))))) ;; Use safe sizes, we try to resize later. - (setq size (max size (if horflag + (setq size (max size (if horizontal window-safe-min-height window-safe-min-width))) - (if (window-sizable-p window (- size) horflag 'safe) + (if (window-sizable-p window (- size) horizontal 'safe) (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))) + (setq new (split-window window size horizontal))) ;; Give up if we can't resize window down to safe sizes. (error "Cannot resize window %s" window)) @@ -4967,12 +4978,12 @@ none was found." (defun display-buffer-split-window-1 (window side min-size) "Subroutine of `display-buffer-split-window'." - (let* ((horflag (memq side '(left right))) + (let* ((horizontal (memq side '(left right))) (parent (window-parent window)) - (resize (and window-splits (window-iso-combined-p window horflag))) + (resize (and window-splits (window-iso-combined-p window horizontal))) (old-size ;; We either resize WINDOW or its parent. - (window-total-size (if resize parent window) horflag)) + (window-total-size (if resize parent window) horizontal)) new-size) ;; We don't call split-window-vertically/-horizontally any more ;; here. If for some reason it's needed we can always do so @@ -4983,20 +4994,20 @@ none was found." ;; MIN-SIZE large after the split. (setq new-size (max min-size - (min (- old-size (window-min-size parent horflag)) + (min (- old-size (window-min-size parent horizontal)) (/ old-size ;; Try to make the size of the new window ;; proportional to the number of iso-arranged ;; windows in the combination. - (1+ (window-iso-combinations parent horflag)))))) - (when (window-sizable-p parent (- new-size) horflag) + (1+ (window-iso-combinations parent horizontal)))))) + (when (window-sizable-p parent (- new-size) horizontal) (split-window window (- new-size) side))) ((window-live-p window) (setq new-size (/ old-size 2)) ;; When WINDOW is live, the old _and_ the new window must be at ;; least MIN-SIZE large after the split. (when (and (>= new-size min-size) - (window-sizable-p window (- new-size) horflag)) + (window-sizable-p window (- new-size) horizontal)) ;; Do an even split to make Stepan happy. (split-window window nil side))) (t @@ -5008,8 +5019,8 @@ none was found." ;; Try to make the size of the new window ;; proportional to the number of iso-arranged ;; subwindows of WINDOW. - (1+ (window-iso-combinations window horflag))))) - (when (window-sizable-p window (- new-size) horflag) + (1+ (window-iso-combinations window horizontal))))) + (when (window-sizable-p window (- new-size) horizontal) (split-window window (- new-size) side)))))) (defun display-buffer-split-window (window &optional side specifiers) @@ -6090,10 +6101,8 @@ matching BUFFER-NAME. If `special-display-buffer-names' or `special-display-regexps' contain a list entry whose car equals or matches BUFFER-NAME, the return value is the cdr of that entry." - (let ((buffer-names (with-no-warnings - special-display-buffer-names)) - (regexps (with-no-warnings - special-display-regexps)) + (let ((buffer-names (with-no-warnings special-display-buffer-names)) + (regexps (with-no-warnings special-display-regexps)) tmp) (cond ((not (stringp buffer-name))) @@ -6175,10 +6184,8 @@ This function returns non-nil if `display-buffer' or `pop-to-buffer' would show a buffer named BUFFER-NAME in the selected rather than \(as usual\) some other window. See `same-window-buffer-names' and `same-window-regexps'." - (let ((buffer-names (with-no-warnings - (same-window-buffer-names))) - (regexps (with-no-warnings - (same-window-regexps)))) + (let ((buffer-names (with-no-warnings special-display-buffer-names)) + (regexps (with-no-warnings special-display-regexps))) (cond ((not (stringp buffer-name))) ;; The elements of `same-window-buffer-names' can be buffer diff --git a/src/ChangeLog b/src/ChangeLog index 4aef77b05f7..561612b519f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2011-05-30 Martin Rudalics + + * window.c (Fsplit_window_internal): Make all arguments + mandatory. Rewrite doc-string. Simplify code. + 2011-05-21 YAMAMOTO Mitsuharu * dispnew.c (scrolling_window): Don't exclude the case that the diff --git a/src/window.c b/src/window.c index a288bdd864a..7565e271859 100644 --- a/src/window.c +++ b/src/window.c @@ -3690,27 +3690,29 @@ resize_frame_windows (struct frame *f, int size, int horflag) } -DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 2, 4, 0, - doc: /* Split window OLD vertically giving the new window SIZE lines. -Optional argument SIDE non-nil means split OLD giving the new -window SIZE columns. In any case SIZE must be a positive integer. - -Optional third argument SIDE nil (or `below') specifies that the -new window shall be located below WINDOW. SIDE `above' means the -new window shall be located above WINDOW. In these cases SIZE specifies -the new number of lines for WINDOW (or the new window provided SIZE is -negative) including space reserved for the mode and/or header line. - -SIDE t (or `right') specifies that the new window shall be located -on the right side of WINDOW. SIDE `left' means the new window -shall be located on the left of WINDOW. In these cases SIZE specifies -the new number of columns for WINDOW (or the new window provided SIZE is -negative) including space reserved for fringes and the scrollbar or a -divder column. - -Optional fourth argument NORMAL-SIZE specifies the normal size of the -new window. */) - (Lisp_Object old, Lisp_Object size, Lisp_Object side, Lisp_Object normal_size) +DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0, + doc: /* Split window OLD. +Second argument TOTAL-SIZE specifies the number of lines or columns of the +new window. In any case TOTAL-SIZE must be a positive integer + +Third argument SIDE nil (or `below') specifies that the new window shall +be located below WINDOW. SIDE `above' means the new window shall be +located above WINDOW. In both cases TOTAL-SIZE specifies the number of +lines of the new window including space reserved for the mode and/or +header line. + +SIDE t (or `right') specifies that the new window shall be located on +the right side of WINDOW. SIDE `left' means the new window shall be +located on the left of WINDOW. In both cases TOTAL-SIZE specifies the +number of columns of the new window including space reserved for fringes +and the scrollbar or a divider column. + +Fourth argument NORMAL-SIZE specifies the normal size of the new window +according to the SIDE argument. + +The new total and normal sizes of all involved windows must have been +set correctly. See the code of `split-window' for how this is done. */) + (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size) { /* OLD (*o) is the window we have to split. (*p) is either OLD's parent window or an internal window we have to install as OLD's new @@ -3724,7 +3726,6 @@ new window. */) int horflag /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */ = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright); - int do_resize = 0; int do_nest = 0; CHECK_WINDOW (old); @@ -3732,10 +3733,11 @@ new window. */) frame = WINDOW_FRAME (o); f = XFRAME (frame); - CHECK_NUMBER (size); + CHECK_NUMBER (total_size); - /* Set do_nest to 1 if either Vwindow_nest is non-nil, OLD has no - parent, or OLD is ortho-combined. */ + /* Set do_nest to 1 if we have to make a new parent window. We do + that if either `window-nest' is non-nil, or OLD has no parent, or + OLD is ortho-combined. */ do_nest = !NILP (Vwindow_nest) || NILP (o->parent) @@ -3743,31 +3745,31 @@ new window. */) ? (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. */ + /* We need a live reference window to initialize some parameters. */ if (WINDOW_LIVE_P (old)) + /* OLD is live, use it as reference window. */ reference = old; - else /* Neither REFERENCE nor OLD are alive. Use the frame's - selected window as reference window. */ + else + /* Use the frame's selected window as reference window. */ reference = FRAME_SELECTED_WINDOW (f); r = XWINDOW (reference); /* The following bugs are caught by `split-window'. */ if (MINI_WINDOW_P (o)) error ("Attempt to split minibuffer window"); - else if (XINT (size) < (horflag ? 2 : 1)) + else if (XINT (total_size) < (horflag ? 2 : 1)) error ("Size of new window too small (after split)"); - else if (do_resize) + else if (!do_nest && !NILP (Vwindow_splits)) + /* `window-splits' non-nil means try to resize OLD's siblings + proportionally. */ { p = XWINDOW (o->parent); /* Temporarily pretend we split the parent window. */ XSETINT (p->new_total, - XINT (horflag ? p->total_cols : p->total_lines) - XINT (size)); + XINT (horflag ? p->total_cols : p->total_lines) + - XINT (total_size)); if (!resize_window_check (p, horflag)) - error ("Sum of window sizes won't fit"); + error ("Window sizes don't fit"); else /* Undo the temporary pretension. */ p->new_total = horflag ? p->total_cols : p->total_lines; @@ -3776,40 +3778,26 @@ new window. */) { if (!resize_window_check (o, horflag)) error ("Resizing old window failed"); - else if (XINT (size) + XINT (o->new_total) + else if (XINT (total_size) + XINT (o->new_total) != XINT (horflag ? o->total_cols : o->total_lines)) error ("Sum of sizes of old and new window don't fit"); } /* This is our point of no return. */ - if (NILP (o->parent) - || NILP (horflag - ? (XWINDOW (o->parent)->hchild) - : (XWINDOW (o->parent)->vchild)) - || !NILP (Vwindow_nest)) - /* Make a new parent window in the following cases: - - - OLD doesn't have a parent window, or - - - OLD is in a vertical (horizontal) combination and shall be - split side-by-side (above-each-other), or - - - we want to nest the new parent window. - - Note that the new parent window is a matrjoshka window; so any - matrjoshka window invariants are temporarily invalid now. */ + if (do_nest) { /* Save the old value of o->normal_cols/lines. It gets corrupted by make_parent_window and we need it below for assigning it to p->new_normal. */ Lisp_Object new_normal = horflag ? o->normal_cols : o->normal_lines; + make_parent_window (old, horflag); p = XWINDOW (o->parent); - /* Store nesting in parent. */ + /* Store value of `window-nest' in new parent's nest slot. */ p->nest = Vwindow_nest; - /* Inherit splits from old. */ + /* Have PARENT inherit splits slot value from OLD. */ p->splits = o->splits; - /* Set splits in old window. */ + /* Store value of `window-splits' in OLD's splits slot. */ o->splits = Vwindow_splits; /* These get applied below. */ p->new_total = horflag ? o->total_cols : o->total_lines; @@ -3861,6 +3849,10 @@ new window. */) n->scroll_bar_width = r->scroll_bar_width; n->vertical_scroll_bar_type = r->vertical_scroll_bar_type; + /* Store `window-splits' in NEW's splits slot. */ + n->splits = Vwindow_splits; + + /* Directly assign orthogonal coordinates and sizes. */ if (horflag) { n->top_line = o->top_line; @@ -3872,31 +3864,25 @@ new window. */) n->total_cols = o->total_cols; } - n->new_total = size; + /* Iso-coordinates and sizes are assigned by resize_window_apply, + get them ready here. */ + n->new_total = total_size; + n->new_normal = normal_size; BLOCK_INPUT; resize_window_apply (p, horflag); - - /* Store actual value of `window-splits' for NEW. */ - n->splits = Vwindow_splits; - - /* Assign normal size of NEW. */ - if (horflag) - n->normal_cols = normal_size; - else - n->normal_lines = normal_size; - adjust_glyphs (f); - UNBLOCK_INPUT; - - /* Set buffer of new window to buffer of reference window. Don't run + /* Set buffer of NEW to buffer of reference window. Don't run any hooks. */ set_window_buffer (new, r->buffer, 0, 1); + UNBLOCK_INPUT; + /* Maybe we should run the scroll functions in Elisp (which already runs the configuration change hook). */ if (! NILP (Vwindow_scroll_functions)) run_hook_with_args_2 (Qwindow_scroll_functions, new, Fmarker_position (n->start)); + /* Return NEW. */ return new; } @@ -4001,7 +3987,8 @@ when WINDOW is the only window on its frame. */) { /* Put SIBLING into PARENT's place. */ replace_window (parent, sibling, 0); - /* Inherit these three. */ + /* Have SIBLING inherit the following three slot values from + PARENT (the nest slot is not inherited). */ s->normal_cols = p->normal_cols; s->normal_lines = p->normal_lines; s->splits = p->splits; -- 2.39.5