Function: split-window
split-window is a byte-compiled function defined in window.el.gz.
Signature
(split-window &optional WINDOW SIZE SIDE PIXELWISE)
Documentation
Make a new window adjacent to WINDOW.
WINDOW must be a valid window and defaults to the selected one. Return the new window which is always a live window.
Optional argument SIZE a positive number means make WINDOW SIZE
lines or columns tall. If SIZE is negative, make the new window
-SIZE lines or columns tall. If and only if SIZE is non-nil, its
absolute value can be less than window-min-height or
window-min-width; so this command can make a new window as
small as one line or two columns. SIZE defaults to half of
WINDOW's size.
Optional third argument SIDE nil (or below) specifies that the
new window shall be located below WINDOW. SIDE above means the
new window shall be located above WINDOW. In both cases SIZE
specifies the new number of lines for WINDOW (or the new window
if SIZE is negative) including space reserved for the mode and/or
header line.
SIDE t (or right) specifies that the new window shall be
located on the right side of WINDOW. SIDE left means the new
window shall be located on the left of WINDOW. In both cases
SIZE specifies the new number of columns for WINDOW (or the new
window provided SIZE is negative) including space reserved for
fringes and the scrollbar or a divider column.
For compatibility reasons, SIDE up and down are interpreted
as above and below. Any other non-nil value for SIDE is
currently handled like t (or right).
PIXELWISE, if non-nil, means to interpret SIZE pixelwise.
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.
Probably introduced at or before Emacs version 24.1.
Source Code
;; Defined in /usr/src/emacs/lisp/window.el.gz
(defun split-window (&optional window size side pixelwise)
"Make a new window adjacent to WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return the new window which is always a live window.
Optional argument SIZE a positive number means make WINDOW SIZE
lines or columns tall. If SIZE is negative, make the new window
-SIZE lines or columns tall. If and only if SIZE is non-nil, its
absolute value can be less than `window-min-height' or
`window-min-width'; so this command can make a new window as
small as one line or two columns. SIZE defaults to half of
WINDOW's size.
Optional third argument SIDE nil (or `below') specifies that the
new window shall be located below WINDOW. SIDE `above' means the
new window shall be located above WINDOW. In both cases SIZE
specifies the new number of lines for WINDOW (or the new window
if SIZE is negative) including space reserved for the mode and/or
header line.
SIDE t (or `right') specifies that the new window shall be
located on the right side of WINDOW. SIDE `left' means the new
window shall be located on the left of WINDOW. In both cases
SIZE specifies the new number of columns for WINDOW (or the new
window provided SIZE is negative) including space reserved for
fringes and the scrollbar or a divider column.
For compatibility reasons, SIDE `up' and `down' are interpreted
as `above' and `below'. Any other non-nil value for SIDE is
currently handled like t (or `right').
PIXELWISE, if non-nil, means to interpret SIZE pixelwise.
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."
(setq window (window-normalize-window window))
(let* ((side (cond
((not side) 'below)
((eq side 'up) 'above)
((eq side 'down) 'below)
((memq side '(below above right left)) side)
(t 'right)))
(horizontal (not (memq side '(below above))))
(frame (window-frame window))
(parent (window-parent window))
(function (window-parameter window 'split-window))
(window-side (window-parameter window 'window-side))
;; Rebind the following two variables since in some cases we
;; have to override their value.
(window-combination-limit window-combination-limit)
(window-combination-resize window-combination-resize)
(char-size (frame-char-size window horizontal))
(pixel-size
(when (numberp size)
(window--size-to-pixel window size horizontal pixelwise t)))
(divider-width (if horizontal
(frame-right-divider-width frame)
(frame-bottom-divider-width frame)))
atom-root ignore)
(window--check frame)
(catch 'done
(cond
;; Ignore window parameters if either `ignore-window-parameters'
;; is t or the 'split-window' parameter equals t.
((or ignore-window-parameters (eq function t)))
((functionp function)
;; The 'split-window' parameter specifies the function to call.
;; If that function is `ignore', do nothing.
(throw 'done (funcall function window size side)))
;; If WINDOW is part 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 pixelwise)))
;; If WINDOW is a side window or its first or last child is a
;; side window, throw an error unless `window-combination-resize'
;; equals 'side.
((and (not (eq window-combination-resize 'side))
(window-parameter window 'window-side))
(error "Cannot split side window or parent of side window"))
;; If `window-combination-resize' is 'side and window has a side
;; window sibling, bind `window-combination-limit' to t.
((and (not (eq window-combination-resize 'side))
(or (and (window-prev-sibling window)
(window-parameter
(window-prev-sibling window) 'window-side))
(and (window-next-sibling window)
(window-parameter
(window-next-sibling window) 'window-side))))
(setq window-combination-limit t)))
;; If `window-combination-resize' is t and SIZE is non-negative,
;; bind `window-combination-limit' to t.
(when (and (eq window-combination-resize t)
pixel-size (> pixel-size 0))
(setq window-combination-limit t))
(let* ((parent-pixel-size
;; 'parent-pixel-size' is the pixel size of WINDOW's
;; parent, provided it has one.
(when parent (window-size parent horizontal t)))
;; 'resize' non-nil means we are supposed to resize other
;; windows in WINDOW's combination.
(resize
(and window-combination-resize
(or (window-parameter window 'window-side)
(not (eq window-combination-resize 'side)))
(not (eq window-combination-limit t))
;; Resize makes sense in iso-combinations only.
(window-combined-p window horizontal)))
;; 'old-pixel-size' is the current pixel size of WINDOW.
(old-pixel-size (window-size window horizontal t))
;; 'new-size' is the specified or calculated size of the
;; new window.
new-pixel-size new-parent new-normal)
(cond
((not pixel-size)
(setq new-pixel-size
(if resize
;; When resizing try to give the new window the
;; average size of a window in its combination.
(max (min (- parent-pixel-size
(window-min-size parent horizontal nil t))
(window--combination-resizable parent horizontal))
(window-min-pixel-size))
;; Else try to give the new window half the size
;; of WINDOW (plus an eventual odd pixel).
(/ old-pixel-size 2)))
(unless window-resize-pixelwise
;; Round to nearest char-size multiple.
(setq new-pixel-size
(* char-size (round new-pixel-size char-size)))))
((>= pixel-size 0)
;; SIZE non-negative specifies the new size of WINDOW.
;; Note: Specifying a non-negative SIZE is practically
;; always done as workaround for making the new window
;; appear above or on the left of the new window (the
;; ispell window is a typical example of that). In all
;; these cases the SIDE argument should be set to 'above
;; or 'left in order to support the 'resize option.
;; Here we have to nest the windows instead, see above.
(setq new-pixel-size (- old-pixel-size pixel-size)))
(t
;; SIZE negative specifies the size of the new window.
(setq new-pixel-size (- pixel-size))))
;; Check SIZE.
(cond
((not pixel-size)
(cond
(resize
;; SIZE unspecified, resizing.
(unless (or (window-sizable-p
parent (- (+ new-pixel-size divider-width)) horizontal
nil t)
(window-sizable-p
parent (- (+ new-pixel-size divider-width)) horizontal
(setq ignore 'preserved) t))
(error "Window %s too small for splitting" parent)))
((and (> (+ new-pixel-size divider-width
(window-min-size window horizontal nil t))
old-pixel-size)
(> (+ new-pixel-size divider-width
(window-min-size
window horizontal (setq ignore 'preserved) t))
old-pixel-size))
;; SIZE unspecified, no resizing.
(error "Window %s too small for splitting" window))))
((and (>= pixel-size 0)
(or (>= pixel-size old-pixel-size)
(< new-pixel-size
(window-safe-min-pixel-size window horizontal))))
;; SIZE specified as new size of old window. If the new size
;; is larger than the old size or the size of the new window
;; would be less than the safe minimum, signal an error.
(error "Window %s too small for splitting" window))
(resize
;; SIZE specified, resizing.
(unless (or (window-sizable-p
parent (- (+ new-pixel-size divider-width)) horizontal
nil t)
(window-sizable-p
parent (- (+ new-pixel-size divider-width)) horizontal
(setq ignore 'preserved) t))
;; If we cannot resize the parent give up.
(error "Window %s too small for splitting" parent)))
((or (< new-pixel-size
(window-safe-min-pixel-size window horizontal))
(< (- old-pixel-size new-pixel-size)
(window-safe-min-pixel-size window horizontal)))
;; SIZE specification violates minimum size restrictions.
(error "Window %s too small for splitting" window)))
(window--resize-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 (eq window-combination-limit t)
(not (window-combined-p window horizontal))))
(setq new-normal
;; Make new-normal the normal size of the new window.
(cond
(pixel-size (/ (float new-pixel-size)
(if new-parent old-pixel-size parent-pixel-size)))
(new-parent 0.5)
(resize (/ 1.0 (1+ (window-combinations parent horizontal t))))
(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
(window--resize-child-windows
parent (- new-pixel-size) horizontal nil ignore)
(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-pixel
window (- old-pixel-size new-pixel-size))
(window--resize-this-window
window (- new-pixel-size) horizontal ignore)
(set-window-new-normal
window (- (if new-parent 1.0 (window-normal-size window horizontal))
new-normal)))
(let* ((new (split-window-internal window new-pixel-size side new-normal)))
(window--pixel-to-total frame horizontal)
;; Assign window-side parameters, if any.
(cond
((eq window-combination-resize 'side)
(let ((window-side
(cond
(window-side window-side)
((eq side 'above) 'top)
((eq side 'below) 'bottom)
(t side))))
;; We made a new side window.
(set-window-parameter new 'window-side window-side)
(when (and new-parent (window-parameter window 'window-side))
;; We've been splitting a side root window. Give the
;; new parent the same window-side parameter.
(set-window-parameter
(window-parent new) 'window-side window-side))))
((eq window-combination-resize 'atom)
;; Make sure `window--check' won't destroy an existing
;; atomic window in case the new window gets nested inside.
(unless (window-parameter window 'window-atom)
(set-window-parameter window 'window-atom t))
(when new-parent
(set-window-parameter (window-parent new) 'window-atom t))
(set-window-parameter new 'window-atom t)))
;; Make the new window inherit the `min-margins' parameter of
;; WINDOW (Bug#44483).
(let ((min-margins (window-parameter window 'min-margins)))
(when min-margins
(set-window-parameter new 'min-margins min-margins)))
;; Sanitize sizes unless SIZE was specified.
(unless size
(window--sanitize-window-sizes horizontal))
(run-window-scroll-functions new)
(window--check frame)
;; Always return the new window.
new)))))