Function: split-window-internal
split-window-internal is a function defined in window.c.
Signature
(split-window-internal OLD PIXEL-SIZE SIDE NORMAL-SIZE)
Documentation
Split window OLD.
Second argument PIXEL-SIZE specifies the number of pixels of the new window. It 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 PIXEL-SIZE specifies the pixel
height of the new window including space reserved for the mode and/or
header/tab 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 PIXEL-SIZE specifies the
width 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 pixel and normal sizes of all involved windows must have been
set correctly. See the code of split-window for how this is done.
Source Code
// Defined in /usr/src/emacs/src/window.c
// Skipping highlighting due to helpful-max-highlight.
{
/* 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
parent. REFERENCE (*r) must denote a live window, or is set to OLD
provided OLD is a leaf window, or to the frame's selected window.
NEW (*n) is the new window created with some parameters taken from
REFERENCE (*r). */
Lisp_Object new, frame, reference;
struct window *o, *p, *n, *r, *c;
struct frame *f;
bool horflag
/* HORFLAG is true when we split side-by-side, false otherwise. */
= EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
CHECK_WINDOW (old);
o = XWINDOW (old);
frame = WINDOW_FRAME (o);
f = XFRAME (frame);
CHECK_FIXNUM (pixel_size);
EMACS_INT total_size
= XFIXNUM (pixel_size) / (horflag
? FRAME_COLUMN_WIDTH (f)
: FRAME_LINE_HEIGHT (f));
/* Set combination_limit if we have to make a new parent window.
We do that if either `window-combination-limit' is t, or OLD has no
parent, or OLD is ortho-combined. */
bool combination_limit
= (EQ (Vwindow_combination_limit, Qt)
|| NILP (o->parent)
|| (horflag
? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
: WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
/* 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
/* 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 (total_size < (horflag ? 2 : 1))
error ("Size of new window too small (after split)");
else if (!combination_limit && !NILP (Vwindow_combination_resize))
/* `window-combination-resize' non-nil means try to resize OLD's siblings
proportionally. */
{
p = XWINDOW (o->parent);
/* Temporarily pretend we split the parent window. */
wset_new_pixel
(p, make_fixnum ((horflag ? p->pixel_width : p->pixel_height)
- XFIXNUM (pixel_size)));
if (!window_resize_check (p, horflag))
error ("Window sizes don't fit");
else
/* Undo the temporary pretension. */
wset_new_pixel (p, make_fixnum (horflag ? p->pixel_width : p->pixel_height));
}
else
{
if (!window_resize_check (o, horflag))
error ("Resizing old window failed");
else if (XFIXNUM (pixel_size) + XFIXNUM (o->new_pixel)
!= (horflag ? o->pixel_width : o->pixel_height))
error ("Sum of sizes of old and new window don't fit");
}
/* This is our point of no return. */
if (combination_limit)
{
/* 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);
if (EQ (Vwindow_combination_limit, Qt))
/* Store t in the new parent's combination_limit slot to avoid
that its children get merged into another window. */
wset_combination_limit (p, Qt);
/* These get applied below. */
wset_new_pixel
(p, make_fixnum (horflag ? o->pixel_width : o->pixel_height));
wset_new_total
(p, make_fixnum (horflag ? o->total_cols : o->total_lines));
wset_new_normal (p, new_normal);
}
else
p = XWINDOW (o->parent);
fset_redisplay (f);
new = make_window ();
n = XWINDOW (new);
wset_frame (n, frame);
wset_parent (n, o->parent);
if (EQ (side, Qabove) || EQ (side, Qleft))
{
wset_prev (n, o->prev);
if (NILP (n->prev))
wset_combination (p, horflag, new);
else
wset_next (XWINDOW (n->prev), new);
wset_next (n, old);
wset_prev (o, new);
}
else
{
wset_next (n, o->next);
if (!NILP (n->next))
wset_prev (XWINDOW (n->next), new);
wset_prev (n, old);
wset_next (o, new);
}
n->window_end_valid = false;
n->last_cursor_vpos = 0;
/* Get special geometry settings from reference window. */
n->left_margin_cols = r->left_margin_cols;
n->right_margin_cols = r->right_margin_cols;
n->left_fringe_width = r->left_fringe_width;
n->right_fringe_width = r->right_fringe_width;
n->fringes_outside_margins = r->fringes_outside_margins;
n->scroll_bar_width = r->scroll_bar_width;
n->scroll_bar_height = r->scroll_bar_height;
wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
/* Directly assign orthogonal coordinates and sizes. */
if (horflag)
{
n->pixel_top = o->pixel_top;
n->top_line = o->top_line;
n->pixel_height = o->pixel_height;
n->total_lines = o->total_lines;
}
else
{
n->pixel_left = o->pixel_left;
n->left_col = o->left_col;
n->pixel_width = o->pixel_width;
n->total_cols = o->total_cols;
}
/* Iso-coordinates and sizes are assigned by window_resize_apply,
get them ready here. */
wset_new_pixel (n, pixel_size);
EMACS_INT sum = 0;
c = XWINDOW (p->contents);
while (c)
{
if (c != n)
sum = sum + XFIXNUM (c->new_total);
c = NILP (c->next) ? 0 : XWINDOW (c->next);
}
wset_new_total (n, make_fixnum ((horflag
? p->total_cols
: p->total_lines)
- sum));
wset_new_normal (n, normal_size);
block_input ();
window_resize_apply (p, horflag);
adjust_frame_glyphs (f);
/* Set buffer of NEW to buffer of reference window. */
set_window_buffer (new, r->contents, true, true);
FRAME_WINDOW_CHANGE (f) = true;
unblock_input ();
return new;
}