(Qfixed_window_size): New.
(syms_of_window): Initialiaze it. (check_all_windows): Add return type void. (window_fixed_size_p): New. Return non-zero if window is fixed-size. (window_min_size_1): New. (window_min_size): Handle fixed-size windows. (size_window): New. Rewritten combination of set_window_height and set_window_width that handles fixed-size windows. (set_window_height): Call it. (set_window_width): Call it. (Fsplit_window): Give an error on attempt to split a fixed-size window. (change_window_height): Partly rewritten to handle fixed-size windows.
This commit is contained in:
parent
20c1822ee6
commit
233a4a2c3f
1 changed files with 487 additions and 194 deletions
681
src/window.c
681
src/window.c
|
@ -43,6 +43,8 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
|
||||
Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
|
||||
Lisp_Object Qfixed_window_size;
|
||||
extern Lisp_Object Qheight, Qwidth;
|
||||
|
||||
static struct window *decode_window P_ ((Lisp_Object));
|
||||
static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
|
||||
|
@ -51,7 +53,10 @@ static int get_leaf_windows P_ ((struct window *, struct window **, int));
|
|||
static void window_scroll P_ ((Lisp_Object, int, int, int));
|
||||
static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
|
||||
static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
|
||||
static int window_min_size P_ ((struct window *, int));
|
||||
static int window_min_size_1 P_ ((struct window *, int));
|
||||
static int window_min_size P_ ((struct window *, int, int *));
|
||||
static int window_fixed_size_p P_ ((struct window *, int, int));
|
||||
static void size_window P_ ((Lisp_Object, int, int, int));
|
||||
|
||||
|
||||
/* This is the window in which the terminal's cursor should
|
||||
|
@ -1655,6 +1660,7 @@ window_loop (type, obj, mini, frames)
|
|||
|
||||
/* Used for debugging. Abort if any window has a dead buffer. */
|
||||
|
||||
void
|
||||
check_all_windows ()
|
||||
{
|
||||
window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
|
||||
|
@ -1885,35 +1891,387 @@ check_frame_size (frame, rows, cols)
|
|||
}
|
||||
|
||||
|
||||
/* Return the minimum size of window W. WIDTH_P non-zero means
|
||||
return the minimum width, otherwise return the minimum height. */
|
||||
/* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
|
||||
check if W's width can be changed, otherwise check W's height.
|
||||
CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
|
||||
siblings, too. If none of the siblings is resizable, WINDOW isn't
|
||||
either. */
|
||||
|
||||
static INLINE int
|
||||
window_min_size (w, width_p)
|
||||
static int
|
||||
window_fixed_size_p (w, width_p, check_siblings_p)
|
||||
struct window *w;
|
||||
int width_p, check_siblings_p;
|
||||
{
|
||||
int fixed_p;
|
||||
struct window *c;
|
||||
|
||||
if (!NILP (w->hchild))
|
||||
{
|
||||
c = XWINDOW (w->hchild);
|
||||
|
||||
if (width_p)
|
||||
{
|
||||
/* A horiz. combination is fixed-width if all of if its
|
||||
children are. */
|
||||
while (c && window_fixed_size_p (c, width_p, 0))
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
fixed_p = c == NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A horiz. combination is fixed-height if one of if its
|
||||
children is. */
|
||||
while (c && !window_fixed_size_p (c, width_p, 0))
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
fixed_p = c != NULL;
|
||||
}
|
||||
}
|
||||
else if (!NILP (w->vchild))
|
||||
{
|
||||
c = XWINDOW (w->vchild);
|
||||
|
||||
if (width_p)
|
||||
{
|
||||
/* A vert. combination is fixed-width if one of if its
|
||||
children is. */
|
||||
while (c && !window_fixed_size_p (c, width_p, 0))
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
fixed_p = c != NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A vert. combination is fixed-height if all of if its
|
||||
children are. */
|
||||
while (c && window_fixed_size_p (c, width_p, 0))
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
fixed_p = c == NULL;
|
||||
}
|
||||
}
|
||||
else if (BUFFERP (w->buffer))
|
||||
{
|
||||
Lisp_Object val;
|
||||
struct buffer *old = current_buffer;
|
||||
|
||||
current_buffer = XBUFFER (w->buffer);
|
||||
val = find_symbol_value (Qfixed_window_size);
|
||||
current_buffer = old;
|
||||
|
||||
fixed_p = 0;
|
||||
if (!EQ (val, Qunbound))
|
||||
{
|
||||
fixed_p = !NILP (val);
|
||||
|
||||
if (fixed_p
|
||||
&& ((EQ (val, Qheight) && width_p)
|
||||
|| (EQ (val, Qwidth) && !width_p)))
|
||||
fixed_p = 0;
|
||||
}
|
||||
|
||||
/* Can't tell if this one is resizable without looking at
|
||||
siblings. If all siblings are fixed-size this one is too. */
|
||||
if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
|
||||
{
|
||||
Lisp_Object child;
|
||||
|
||||
for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
|
||||
if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
|
||||
break;
|
||||
|
||||
if (NILP (child))
|
||||
for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
|
||||
if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
|
||||
break;
|
||||
|
||||
if (NILP (child))
|
||||
fixed_p = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
fixed_p = 1;
|
||||
|
||||
return fixed_p;
|
||||
}
|
||||
|
||||
|
||||
/* Return the minimum size of window W, not taking fixed-width windows
|
||||
into account. WIDTH_P non-zero means return the minimum width,
|
||||
otherwise return the minimum height. If W is a combination window,
|
||||
compute the minimum size from the minimum sizes of W's children. */
|
||||
|
||||
static int
|
||||
window_min_size_1 (w, width_p)
|
||||
struct window *w;
|
||||
int width_p;
|
||||
{
|
||||
struct window *c;
|
||||
int size;
|
||||
|
||||
if (width_p)
|
||||
size = window_min_width;
|
||||
if (!NILP (w->hchild))
|
||||
{
|
||||
c = XWINDOW (w->hchild);
|
||||
size = 0;
|
||||
|
||||
if (width_p)
|
||||
{
|
||||
/* The min width of a horizontal combination is
|
||||
the sum of the min widths of its children. */
|
||||
while (c)
|
||||
{
|
||||
size += window_min_size_1 (c, width_p);
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The min height a horizontal combination equals
|
||||
the maximum of all min height of its children. */
|
||||
while (c)
|
||||
{
|
||||
int min_size = window_min_size_1 (c, width_p);
|
||||
size = max (min_size, size);
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!NILP (w->vchild))
|
||||
{
|
||||
c = XWINDOW (w->vchild);
|
||||
size = 0;
|
||||
|
||||
if (width_p)
|
||||
{
|
||||
/* The min width of a vertical combination is
|
||||
the maximum of the min widths of its children. */
|
||||
while (c)
|
||||
{
|
||||
int min_size = window_min_size_1 (c, width_p);
|
||||
size = max (min_size, size);
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The min height of a vertical combination equals
|
||||
the sum of the min height of its children. */
|
||||
while (c)
|
||||
{
|
||||
size += window_min_size_1 (c, width_p);
|
||||
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MINI_WINDOW_P (w)
|
||||
|| (!WINDOW_WANTS_MODELINE_P (w)
|
||||
&& !WINDOW_WANTS_TOP_LINE_P (w)))
|
||||
size = 1;
|
||||
if (width_p)
|
||||
size = window_min_width;
|
||||
else
|
||||
size = window_min_height;
|
||||
{
|
||||
if (MINI_WINDOW_P (w)
|
||||
|| (!WINDOW_WANTS_MODELINE_P (w)
|
||||
&& !WINDOW_WANTS_TOP_LINE_P (w)))
|
||||
size = 1;
|
||||
else
|
||||
size = window_min_height;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* Normally the window is deleted if it gets too small. nodelete
|
||||
nonzero means do not do this. (The caller should check later and
|
||||
do so if appropriate) */
|
||||
/* Return the minimum size of window W, taking fixed-size windows into
|
||||
account. WIDTH_P non-zero means return the minimum width,
|
||||
otherwise return the minimum height. Set *FIXED to 1 if W is
|
||||
fixed-size unless FIXED is null. */
|
||||
|
||||
static int
|
||||
window_min_size (w, width_p, fixed)
|
||||
struct window *w;
|
||||
int width_p, *fixed;
|
||||
{
|
||||
int size, fixed_p;
|
||||
|
||||
fixed_p = window_fixed_size_p (w, width_p, 1);
|
||||
if (fixed)
|
||||
*fixed = fixed_p;
|
||||
|
||||
if (fixed_p)
|
||||
size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
|
||||
else
|
||||
size = window_min_size_1 (w, width_p);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
|
||||
WINDOW's width. Resize WINDOW's children, if any, so that they
|
||||
keep their proportionate size relative to WINDOW. Propagate
|
||||
WINDOW's top or left edge position to children. Delete windows
|
||||
that become too small unless NODELETE_P is non-zero. */
|
||||
|
||||
static void
|
||||
size_window (window, size, width_p, nodelete_p)
|
||||
Lisp_Object window;
|
||||
int size, width_p, nodelete_p;
|
||||
{
|
||||
struct window *w = XWINDOW (window);
|
||||
struct window *c;
|
||||
Lisp_Object child, *forward, *sideward;
|
||||
int old_size, min_size;
|
||||
|
||||
check_min_window_sizes ();
|
||||
|
||||
/* If the window has been "too small" at one point,
|
||||
don't delete it for being "too small" in the future.
|
||||
Preserve it as long as that is at all possible. */
|
||||
if (width_p)
|
||||
{
|
||||
old_size = XFASTINT (w->width);
|
||||
min_size = window_min_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_size = XFASTINT (w->height);
|
||||
min_size = window_min_height;
|
||||
}
|
||||
|
||||
if (old_size < window_min_width)
|
||||
w->too_small_ok = Qt;
|
||||
|
||||
/* Maybe delete WINDOW if it's too small. */
|
||||
if (!nodelete_p && !NILP (w->parent))
|
||||
{
|
||||
int min_size;
|
||||
|
||||
if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
|
||||
min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
|
||||
else
|
||||
min_size = width_p ? window_min_width : window_min_height;
|
||||
|
||||
if (size < min_size)
|
||||
{
|
||||
delete_window (window);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set redisplay hints. */
|
||||
XSETFASTINT (w->last_modified, 0);
|
||||
XSETFASTINT (w->last_overlay_modified, 0);
|
||||
windows_or_buffers_changed++;
|
||||
FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
|
||||
|
||||
if (width_p)
|
||||
{
|
||||
sideward = &w->vchild;
|
||||
forward = &w->hchild;
|
||||
XSETFASTINT (w->width, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
sideward = &w->hchild;
|
||||
forward = &w->vchild;
|
||||
XSETFASTINT (w->height, size);
|
||||
}
|
||||
|
||||
if (!NILP (*sideward))
|
||||
{
|
||||
for (child = *sideward; !NILP (child); child = c->next)
|
||||
{
|
||||
c = XWINDOW (child);
|
||||
if (width_p)
|
||||
c->left = w->left;
|
||||
else
|
||||
c->top = w->top;
|
||||
size_window (child, size, width_p, nodelete_p);
|
||||
}
|
||||
}
|
||||
else if (!NILP (*forward))
|
||||
{
|
||||
int fixed_size, each, extra, n;
|
||||
int resize_fixed_p, nfixed;
|
||||
int last_pos, first_pos, nchildren;
|
||||
|
||||
/* Determine the fixed-size portion of the this window, and the
|
||||
number of child windows. */
|
||||
fixed_size = nchildren = nfixed = 0;
|
||||
for (child = *forward; !NILP (child); child = c->next, ++nchildren)
|
||||
{
|
||||
c = XWINDOW (child);
|
||||
if (window_fixed_size_p (c, width_p, 0))
|
||||
{
|
||||
fixed_size += (width_p
|
||||
? XFASTINT (c->width) : XFASTINT (c->height));
|
||||
++nfixed;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the new size is smaller than fixed_size, or if there
|
||||
aren't any resizable windows, allow resizing fixed-size
|
||||
windows. */
|
||||
resize_fixed_p = nfixed == nchildren || size < fixed_size;
|
||||
|
||||
/* Compute how many lines/columns to add to each child. The
|
||||
value of extra takes care of rounding errors. */
|
||||
n = resize_fixed_p ? nchildren : nchildren - nfixed;
|
||||
each = (size - old_size) / n;
|
||||
extra = (size - old_size) - n * each;
|
||||
|
||||
/* Compute new children heights and edge positions. */
|
||||
first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
|
||||
last_pos = first_pos;
|
||||
for (child = *forward; !NILP (child); child = c->next)
|
||||
{
|
||||
int new_size, old_size;
|
||||
|
||||
c = XWINDOW (child);
|
||||
old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
|
||||
new_size = old_size;
|
||||
|
||||
/* The top or left edge position of this child equals the
|
||||
bottom or right edge of its predecessor. */
|
||||
if (width_p)
|
||||
c->left = make_number (last_pos);
|
||||
else
|
||||
c->top = make_number (last_pos);
|
||||
|
||||
/* If this child can be resized, do it. */
|
||||
if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
|
||||
{
|
||||
new_size = old_size + each + extra;
|
||||
extra = 0;
|
||||
}
|
||||
|
||||
/* Set new height. Note that size_window also propagates
|
||||
edge positions to children, so it's not a no-op if we
|
||||
didn't change the child's size. */
|
||||
size_window (child, new_size, width_p, 1);
|
||||
|
||||
/* Remember the bottom/right edge position of this child; it
|
||||
will be used to set the top/left edge of the next child. */
|
||||
last_pos += new_size;
|
||||
}
|
||||
|
||||
/* We should have covered the parent exactly with child windows. */
|
||||
xassert (size == last_pos - first_pos);
|
||||
|
||||
/* Now delete any children that became too small. */
|
||||
if (!nodelete_p)
|
||||
for (child = *forward; !NILP (child); child = c->next)
|
||||
{
|
||||
int child_size;
|
||||
c = XWINDOW (child);
|
||||
child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
|
||||
size_window (child, child_size, width_p, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set WINDOW's height to HEIGHT, and recursively change the height of
|
||||
WINDOW's children. NODELETE non-zero means don't delete windows
|
||||
that become too small in the process. (The caller should check
|
||||
later and do so if appropriate.) */
|
||||
|
||||
void
|
||||
set_window_height (window, height, nodelete)
|
||||
|
@ -1921,82 +2279,14 @@ set_window_height (window, height, nodelete)
|
|||
int height;
|
||||
int nodelete;
|
||||
{
|
||||
register struct window *w = XWINDOW (window);
|
||||
register struct window *c;
|
||||
int oheight = XFASTINT (w->height);
|
||||
int top, pos, lastbot, opos, lastobot;
|
||||
Lisp_Object child;
|
||||
|
||||
check_min_window_sizes ();
|
||||
|
||||
/* If the window has been "too small" at one point,
|
||||
don't delete it for being "too small" in the future.
|
||||
Preserve it as long as that is at all possible. */
|
||||
if (oheight < window_min_height)
|
||||
w->too_small_ok = Qt;
|
||||
|
||||
if (!nodelete && !NILP (w->parent))
|
||||
{
|
||||
int min_height;
|
||||
|
||||
if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
|
||||
min_height = MIN_SAFE_WINDOW_HEIGHT;
|
||||
else
|
||||
min_height = window_min_size (w, 0);
|
||||
|
||||
if (height < min_height)
|
||||
{
|
||||
delete_window (window);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
XSETFASTINT (w->last_modified, 0);
|
||||
XSETFASTINT (w->last_overlay_modified, 0);
|
||||
windows_or_buffers_changed++;
|
||||
FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
|
||||
|
||||
XSETFASTINT (w->height, height);
|
||||
if (!NILP (w->hchild))
|
||||
{
|
||||
for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
|
||||
{
|
||||
XWINDOW (child)->top = w->top;
|
||||
set_window_height (child, height, nodelete);
|
||||
}
|
||||
}
|
||||
else if (!NILP (w->vchild))
|
||||
{
|
||||
lastbot = top = XFASTINT (w->top);
|
||||
lastobot = 0;
|
||||
for (child = w->vchild; !NILP (child); child = c->next)
|
||||
{
|
||||
c = XWINDOW (child);
|
||||
|
||||
opos = lastobot + XFASTINT (c->height);
|
||||
|
||||
XSETFASTINT (c->top, lastbot);
|
||||
|
||||
pos = (((opos * height) << 1) + oheight) / (oheight << 1);
|
||||
|
||||
/* Avoid confusion: inhibit deletion of child if becomes too small */
|
||||
set_window_height (child, pos + top - lastbot, 1);
|
||||
|
||||
/* Now advance child to next window,
|
||||
and set lastbot if child was not just deleted. */
|
||||
lastbot = pos + top;
|
||||
lastobot = opos;
|
||||
}
|
||||
/* Now delete any children that became too small. */
|
||||
if (!nodelete)
|
||||
for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
|
||||
{
|
||||
set_window_height (child, XINT (XWINDOW (child)->height), 0);
|
||||
}
|
||||
}
|
||||
size_window (window, height, 0, nodelete);
|
||||
}
|
||||
|
||||
/* Recursively set width of WINDOW and its inferiors. */
|
||||
|
||||
/* Set WINDOW's width to WIDTH, and recursively change the width of
|
||||
WINDOW's children. NODELETE non-zero means don't delete windows
|
||||
that become too small in the process. (The caller should check
|
||||
later and do so if appropriate.) */
|
||||
|
||||
void
|
||||
set_window_width (window, width, nodelete)
|
||||
|
@ -2004,70 +2294,9 @@ set_window_width (window, width, nodelete)
|
|||
int width;
|
||||
int nodelete;
|
||||
{
|
||||
register struct window *w = XWINDOW (window);
|
||||
register struct window *c;
|
||||
int owidth = XFASTINT (w->width);
|
||||
int left, pos, lastright, opos, lastoright;
|
||||
Lisp_Object child;
|
||||
|
||||
/* If the window has been "too small" at one point,
|
||||
don't delete it for being "too small" in the future.
|
||||
Preserve it as long as that is at all possible. */
|
||||
if (owidth < window_min_width)
|
||||
w->too_small_ok = Qt;
|
||||
|
||||
if (!nodelete && !NILP (w->parent)
|
||||
&& (! NILP (w->too_small_ok)
|
||||
? width < MIN_SAFE_WINDOW_WIDTH
|
||||
: width < window_min_width))
|
||||
{
|
||||
delete_window (window);
|
||||
return;
|
||||
}
|
||||
|
||||
XSETFASTINT (w->last_modified, 0);
|
||||
XSETFASTINT (w->last_overlay_modified, 0);
|
||||
windows_or_buffers_changed++;
|
||||
FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
|
||||
|
||||
XSETFASTINT (w->width, width);
|
||||
if (!NILP (w->vchild))
|
||||
{
|
||||
for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
|
||||
{
|
||||
XWINDOW (child)->left = w->left;
|
||||
set_window_width (child, width, nodelete);
|
||||
}
|
||||
}
|
||||
else if (!NILP (w->hchild))
|
||||
{
|
||||
lastright = left = XFASTINT (w->left);
|
||||
lastoright = 0;
|
||||
for (child = w->hchild; !NILP (child); child = c->next)
|
||||
{
|
||||
c = XWINDOW (child);
|
||||
|
||||
opos = lastoright + XFASTINT (c->width);
|
||||
|
||||
XSETFASTINT (c->left, lastright);
|
||||
|
||||
pos = (((opos * width) << 1) + owidth) / (owidth << 1);
|
||||
|
||||
/* Inhibit deletion for becoming too small */
|
||||
set_window_width (child, pos + left - lastright, 1);
|
||||
|
||||
/* Now advance child to next window,
|
||||
and set lastright if child was not just deleted. */
|
||||
lastright = pos + left, lastoright = opos;
|
||||
}
|
||||
/* Delete children that became too small */
|
||||
if (!nodelete)
|
||||
for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
|
||||
{
|
||||
set_window_width (child, XINT (XWINDOW (child)->width), 0);
|
||||
}
|
||||
}
|
||||
size_window (window, width, 1, nodelete);
|
||||
}
|
||||
|
||||
|
||||
int window_select_count;
|
||||
|
||||
|
@ -2677,6 +2906,8 @@ SIZE includes that window's scroll bar, or the divider column to its right.")
|
|||
|
||||
if (MINI_WINDOW_P (o))
|
||||
error ("Attempt to split minibuffer window");
|
||||
else if (window_fixed_size_p (o, !NILP (horflag), 0))
|
||||
error ("Attempt to split fixed-size window");
|
||||
|
||||
check_min_window_sizes ();
|
||||
|
||||
|
@ -2810,42 +3041,51 @@ window_width (window)
|
|||
#define CURSIZE(w) \
|
||||
*(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
|
||||
|
||||
/* Unlike set_window_height, this function
|
||||
also changes the heights of the siblings so as to
|
||||
keep everything consistent. */
|
||||
|
||||
/* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
|
||||
increase its width. Siblings of the selected window are resized to
|
||||
fullfil the size request. If they become too small in the process,
|
||||
they will be deleted. */
|
||||
|
||||
void
|
||||
change_window_height (delta, widthflag)
|
||||
register int delta;
|
||||
int widthflag;
|
||||
int delta, widthflag;
|
||||
{
|
||||
register Lisp_Object parent;
|
||||
Lisp_Object window;
|
||||
register struct window *p;
|
||||
int *sizep;
|
||||
Lisp_Object parent, window, next, prev;
|
||||
struct window *p;
|
||||
int *sizep, maximum;
|
||||
int (*sizefun) P_ ((Lisp_Object))
|
||||
= widthflag ? window_width : window_height;
|
||||
register void (*setsizefun) P_ ((Lisp_Object, int, int))
|
||||
void (*setsizefun) P_ ((Lisp_Object, int, int))
|
||||
= (widthflag ? set_window_width : set_window_height);
|
||||
int maximum;
|
||||
Lisp_Object next, prev;
|
||||
|
||||
/* Check values of window_min_width and window_min_height for
|
||||
validity. */
|
||||
check_min_window_sizes ();
|
||||
|
||||
/* Give up if this window cannot be resized. */
|
||||
window = selected_window;
|
||||
if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
|
||||
error ("Window is not resizable");
|
||||
|
||||
/* Find the parent of the selected window. */
|
||||
while (1)
|
||||
{
|
||||
p = XWINDOW (window);
|
||||
parent = p->parent;
|
||||
|
||||
if (NILP (parent))
|
||||
{
|
||||
if (widthflag)
|
||||
error ("No other window to side of this one");
|
||||
break;
|
||||
}
|
||||
if (widthflag ? !NILP (XWINDOW (parent)->hchild)
|
||||
|
||||
if (widthflag
|
||||
? !NILP (XWINDOW (parent)->hchild)
|
||||
: !NILP (XWINDOW (parent)->vchild))
|
||||
break;
|
||||
|
||||
window = parent;
|
||||
}
|
||||
|
||||
|
@ -2857,10 +3097,10 @@ change_window_height (delta, widthflag)
|
|||
maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
|
||||
: !NILP (p->next) ? ((*sizefun) (p->next)
|
||||
- window_min_size (XWINDOW (p->next),
|
||||
widthflag))
|
||||
widthflag, 0))
|
||||
: !NILP (p->prev) ? ((*sizefun) (p->prev)
|
||||
- window_min_size (XWINDOW (p->prev),
|
||||
widthflag))
|
||||
widthflag, 0))
|
||||
/* This is a frame with only one window, a minibuffer-only
|
||||
or a minibufferless frame. */
|
||||
: (delta = 0));
|
||||
|
@ -2872,7 +3112,7 @@ change_window_height (delta, widthflag)
|
|||
delta = maxdelta;
|
||||
}
|
||||
|
||||
if (*sizep + delta < window_min_size (XWINDOW (window), widthflag))
|
||||
if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
|
||||
{
|
||||
delete_window (window);
|
||||
return;
|
||||
|
@ -2885,16 +3125,17 @@ change_window_height (delta, widthflag)
|
|||
maximum = 0;
|
||||
for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
|
||||
maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
|
||||
widthflag);
|
||||
widthflag, 0);
|
||||
for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
|
||||
maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
|
||||
widthflag);
|
||||
widthflag, 0);
|
||||
|
||||
/* If we can get it all from them, do so. */
|
||||
if (delta <= maximum)
|
||||
{
|
||||
Lisp_Object first_unaffected;
|
||||
Lisp_Object first_affected;
|
||||
int fixed_p;
|
||||
|
||||
next = p->next;
|
||||
prev = p->prev;
|
||||
|
@ -2902,42 +3143,54 @@ change_window_height (delta, widthflag)
|
|||
/* Look at one sibling at a time,
|
||||
moving away from this window in both directions alternately,
|
||||
and take as much as we can get without deleting that sibling. */
|
||||
while (delta != 0)
|
||||
while (delta != 0 && (!NILP (next) || !NILP (prev)))
|
||||
{
|
||||
if (delta == 0)
|
||||
break;
|
||||
if (! NILP (next))
|
||||
{
|
||||
int this_one = ((*sizefun) (next)
|
||||
- window_min_size (XWINDOW (next), widthflag));
|
||||
if (this_one > delta)
|
||||
this_one = delta;
|
||||
- window_min_size (XWINDOW (next),
|
||||
widthflag, &fixed_p));
|
||||
if (!fixed_p)
|
||||
{
|
||||
if (this_one > delta)
|
||||
this_one = delta;
|
||||
|
||||
(*setsizefun) (next, (*sizefun) (next) - this_one, 0);
|
||||
(*setsizefun) (window, *sizep + this_one, 0);
|
||||
|
||||
(*setsizefun) (next, (*sizefun) (next) - this_one, 0);
|
||||
(*setsizefun) (window, *sizep + this_one, 0);
|
||||
|
||||
delta -= this_one;
|
||||
delta -= this_one;
|
||||
}
|
||||
|
||||
next = XWINDOW (next)->next;
|
||||
}
|
||||
|
||||
if (delta == 0)
|
||||
break;
|
||||
|
||||
if (! NILP (prev))
|
||||
{
|
||||
int this_one = ((*sizefun) (prev)
|
||||
- window_min_size (XWINDOW (prev), widthflag));
|
||||
if (this_one > delta)
|
||||
this_one = delta;
|
||||
- window_min_size (XWINDOW (prev),
|
||||
widthflag, &fixed_p));
|
||||
if (!fixed_p)
|
||||
{
|
||||
if (this_one > delta)
|
||||
this_one = delta;
|
||||
|
||||
first_affected = prev;
|
||||
|
||||
(*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
|
||||
(*setsizefun) (window, *sizep + this_one, 0);
|
||||
|
||||
first_affected = prev;
|
||||
|
||||
(*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
|
||||
(*setsizefun) (window, *sizep + this_one, 0);
|
||||
|
||||
delta -= this_one;
|
||||
delta -= this_one;
|
||||
}
|
||||
|
||||
prev = XWINDOW (prev)->prev;
|
||||
}
|
||||
}
|
||||
|
||||
xassert (delta == 0);
|
||||
|
||||
/* Now recalculate the edge positions of all the windows affected,
|
||||
based on the new sizes. */
|
||||
first_unaffected = next;
|
||||
|
@ -2961,12 +3214,49 @@ change_window_height (delta, widthflag)
|
|||
all the siblings end up with less than one line and are deleted. */
|
||||
if (opht <= *sizep + delta)
|
||||
delta1 = opht * opht * 2;
|
||||
/* Otherwise, make delta1 just right so that if we add delta1
|
||||
lines to this window and to the parent, and then shrink
|
||||
the parent back to its original size, the new proportional
|
||||
size of this window will increase by delta. */
|
||||
else
|
||||
delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
|
||||
{
|
||||
/* Otherwise, make delta1 just right so that if we add
|
||||
delta1 lines to this window and to the parent, and then
|
||||
shrink the parent back to its original size, the new
|
||||
proportional size of this window will increase by delta.
|
||||
|
||||
The function size_window will compute the new height h'
|
||||
of the window from delta1 as:
|
||||
|
||||
e = delta1/n
|
||||
x = delta1 - delta1/n * n for the 1st resizable child
|
||||
h' = h + e + x
|
||||
|
||||
where n is the number of children that can be resized.
|
||||
We can ignore x by choosing a delta1 that is a multiple of
|
||||
n. We want the height of this window to come out as
|
||||
|
||||
h' = h + delta
|
||||
|
||||
So, delta1 must be
|
||||
|
||||
h + e = h + delta
|
||||
delta1/n = delta
|
||||
delta1 = n * delta.
|
||||
|
||||
The number of children n rquals the number of resizable
|
||||
children of this window + 1 because we know window itself
|
||||
is resizable (otherwise we would have signalled an error. */
|
||||
|
||||
struct window *w = XWINDOW (window);
|
||||
Lisp_Object s;
|
||||
int n = 1;
|
||||
|
||||
for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
|
||||
if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
|
||||
++n;
|
||||
for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
|
||||
if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
|
||||
++n;
|
||||
|
||||
delta1 = n * delta;
|
||||
}
|
||||
|
||||
/* Add delta1 lines or columns to this window, and to the parent,
|
||||
keeping things consistent while not affecting siblings. */
|
||||
|
@ -4514,6 +4804,9 @@ init_window_once ()
|
|||
void
|
||||
syms_of_window ()
|
||||
{
|
||||
Qfixed_window_size = intern ("fixed-window-size");
|
||||
staticpro (&Qfixed_window_size);
|
||||
|
||||
staticpro (&Qwindow_configuration_change_hook);
|
||||
Qwindow_configuration_change_hook
|
||||
= intern ("window-configuration-change-hook");
|
||||
|
|
Loading…
Add table
Reference in a new issue