/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
- Copyright (C) 1985,86,87,93,94,95,96,97,1998 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000 Free Software Foundation, Inc.
This file is part of GNU Emacs.
static int foreach_window_1 P_ ((struct window *,
int (* fn) (struct window *, void *),
void *));
+static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
/* This is the window in which the terminal's cursor should
be left when nothing is being done with it. This must
Lisp_Object window;
{
struct window *w = decode_window (window);
- return (MINI_WINDOW_P (w) ? Qt : Qnil);
-}
-
-
-/* Return true if POS is fully visible in the window W. If W's end
- position is not known, then return false. */
-
-static int
-pos_fully_visible_in_window_p (pos, w)
- int pos;
- struct window *w;
-{
- struct glyph_row *first_row = &w->desired_matrix->rows[0];
- struct glyph_row *last_row;
-
- if (pos < first_row->start.pos.charpos)
- /* POS is before the beginning of W. */
- return 0;
- else if (pos < first_row->end.pos.charpos)
- /* POS is on the first row of W, so see if that row is fully visible. */
- return !MATRIX_ROW_PARTIALLY_VISIBLE_P (first_row);
-
- if (NILP (w->window_end_valid))
- /* We can't determine where the end is, so we don't know. */
- return 0;
-
- last_row = &w->desired_matrix->rows[XFASTINT (w->window_end_vpos)];
-
- if (pos < last_row->start.pos.charpos)
- /* POS is somewhere in the middle of the window, not on the first or
- last row, so it must be visible. */
- return 1;
- else if (pos >= last_row->end.pos.charpos)
- /* POS is after the end of W. */
- return 0;
- else
- /* POS is on the last row of W, so see if that row is fully visible. */
- return !MATRIX_ROW_PARTIALLY_VISIBLE_P (last_row);
+ return MINI_WINDOW_P (w) ? Qt : Qnil;
}
DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
Spos_visible_in_window_p, 0, 3, 0,
"Return t if position POS is currently on the frame in WINDOW.\n\
-Returns nil if that position is scrolled vertically out of view.\n\
+Return nil if that position is scrolled vertically out of view.\n\
If FULLY is non-nil, then only return t when POS is completely visible.\n\
-POS defaults to point; WINDOW, to the selected window.")
+POS defaults to point in WINDOW; WINDOW defaults to the selected window.")
(pos, window, fully)
Lisp_Object pos, window, fully;
{
register struct buffer *buf;
struct text_pos top;
Lisp_Object in_window;
+ int fully_p;
- if (NILP (pos))
- posint = PT;
- else
+ w = decode_window (window);
+ buf = XBUFFER (w->buffer);
+ SET_TEXT_POS_FROM_MARKER (top, w->start);
+
+ if (!NILP (pos))
{
CHECK_NUMBER_COERCE_MARKER (pos, 0);
posint = XINT (pos);
}
+ else if (w == XWINDOW (selected_window))
+ posint = PT;
+ else
+ posint = XMARKER (w->pointm)->charpos;
- w = decode_window (window);
- buf = XBUFFER (w->buffer);
- SET_TEXT_POS_FROM_MARKER (top, w->start);
-
- /* If position above window, it's not visible. */
+ /* If position is above window start, it's not visible. */
if (posint < CHARPOS (top))
in_window = Qnil;
else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
&& XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
&& posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
- /* If frame is up to date, and POSINT is < window end pos, use
- that info. This doesn't work for POSINT == end pos, because
- the window end pos is actually the position _after_ the last
- char in the window. */
{
- if (NILP (fully) || pos_fully_visible_in_window_p (posint, w))
- in_window = Qt;
+ /* If frame is up-to-date, and POSINT is < window end pos, use
+ that info. This doesn't work for POSINT == end pos, because
+ the window end pos is actually the position _after_ the last
+ char in the window. */
+ if (!NILP (fully))
+ {
+ pos_visible_p (w, posint, &fully_p, !NILP (fully));
+ in_window = fully_p ? Qt : Qnil;
+ }
else
- in_window = Qnil;
+ in_window = Qt;
}
else if (posint > BUF_ZV (buf))
in_window = Qnil;
in_window = Qnil;
else
{
- struct it it;
- start_display (&it, w, top);
- move_it_to (&it, posint, 0, it.last_visible_y, -1,
- MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
- if (IT_CHARPOS (it) == posint)
- {
- if (NILP (fully))
- in_window = Qt;
- else
- {
- struct glyph_row *pos_row = &w->desired_matrix->rows[it.vpos];
- return MATRIX_ROW_PARTIALLY_VISIBLE_P(pos_row) ? Qnil : Qt;
- }
- }
+ if (pos_visible_p (w, posint, &fully_p, !NILP (fully)))
+ in_window = NILP (fully) || fully_p ? Qt : Qnil;
else
in_window = Qnil;
}
return in_window;
}
+
\f
static struct window *
decode_window (window)
int left_x, right_x, top_y, bottom_y;
int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
+ /* Let's make this a global enum later, instead of using numbers
+ everywhere. */
+ enum {ON_NOTHING, ON_TEXT, ON_MODE_LINE, ON_VERTICAL_BORDER,
+ ON_HEADER_LINE, ON_LEFT_FRINGE, ON_RIGHT_FRINGE};
+
/* In what's below, we subtract 1 when computing right_x because we
want the rightmost pixel, which is given by left_pixel+width-1. */
if (w->pseudo_window_p)
bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
}
+ /* Completely outside anything interesting? */
if (*y < top_y
|| *y >= bottom_y
|| *x < (left_x
- (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
* CANON_X_UNIT (f)))
|| *x > right_x + flags_area_width)
- /* Completely outside anything interesting. */
- return 0;
- else if (WINDOW_WANTS_MODELINE_P (w)
- && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
- /* On the mode line. */
- return 2;
- else if (WINDOW_WANTS_HEADER_LINE_P (w)
- && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
- /* On the top line. */
- return 4;
- /* Need to say "*x > right_x" rather than >=, since on character
- terminals, the vertical line's x coordinate is right_x. */
- else if (*x < left_x || *x > right_x)
+ return ON_NOTHING;
+
+ /* On the mode line or header line? If it's near the start of
+ the mode or header line of window that's has a horizontal
+ sibling, say it's on the vertical line. That's to be able
+ to resize windows horizontally in case we're using toolkit
+ scroll bars. */
+
+ if (WINDOW_WANTS_MODELINE_P (w)
+ && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
+ {
+ if (!WINDOW_RIGHTMOST_P (w)
+ && (abs (*x - ((XFASTINT (w->left) + XFASTINT (w->width))
+ * CANON_X_UNIT (f)))
+ < CANON_X_UNIT (f) / 2))
+ return ON_VERTICAL_BORDER;
+ return ON_MODE_LINE;
+ }
+
+ if (WINDOW_WANTS_HEADER_LINE_P (w)
+ && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
+ {
+ if (!WINDOW_RIGHTMOST_P (w)
+ && (abs (*x - ((XFASTINT (w->left) + XFASTINT (w->width))
+ * CANON_X_UNIT (f)))
+ < CANON_X_UNIT (f) / 2))
+ return ON_VERTICAL_BORDER;
+ return ON_HEADER_LINE;
+ }
+
+ if (FRAME_WINDOW_P (f))
{
- /* Other lines than the mode line don't include flags areas and
- scroll bars on the left. */
+ if (!w->pseudo_window_p
+ && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ && !WINDOW_RIGHTMOST_P (w)
+ && (abs (*x - right_x - flags_area_width) < CANON_X_UNIT (f) / 2))
+ return ON_VERTICAL_BORDER;
+
+ if (*x < left_x || *x > right_x)
+ {
+ /* Other lines than the mode line don't include flags areas and
+ scroll bars on the left. */
- /* Convert X and Y to window-relative pixel coordinates. */
- *x -= left_x;
- *y -= top_y;
- return *x < left_x ? 5 : 6;
+ /* Convert X and Y to window-relative pixel coordinates. */
+ *x -= left_x;
+ *y -= top_y;
+ return *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
+ }
}
- /* Here, too, "*x > right_x" is because of character terminals. */
- else if (!w->pseudo_window_p
- && !WINDOW_RIGHTMOST_P (w)
- && *x > right_x - CANON_X_UNIT (f))
- /* On the border on the right side of the window? Assume that
- this area begins at RIGHT_X minus a canonical char width. */
- return 3;
else
{
- /* Convert X and Y to window-relative pixel coordinates. */
- *x -= left_x;
- *y -= top_y;
- return 1;
+ /* Need to say "*x > right_x" rather than >=, since on character
+ terminals, the vertical line's x coordinate is right_x. */
+ if (*x < left_x || *x > right_x)
+ {
+ /* Other lines than the mode line don't include flags areas and
+ scroll bars on the left. */
+
+ /* Convert X and Y to window-relative pixel coordinates. */
+ *x -= left_x;
+ *y -= top_y;
+ return *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
+ }
+
+ /* Here, too, "*x > right_x" is because of character terminals. */
+ if (!w->pseudo_window_p
+ && !WINDOW_RIGHTMOST_P (w)
+ && *x > right_x - CANON_X_UNIT (f))
+ /* On the border on the right side of the window? Assume that
+ this area begins at RIGHT_X minus a canonical char width. */
+ return ON_VERTICAL_BORDER;
}
+
+ /* Convert X and Y to window-relative pixel coordinates. */
+ *x -= left_x;
+ *y -= top_y;
+ return ON_TEXT;
}
DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
- "Return a list of windows in canonical ordering.\n\
-Arguments are like for `next-window'.")
- (window, minibuf, all_frames)
+ "Return a list of windows on FRAME, starting with WINDOW.\n\
+FRAME nil or omitted means use the selected frame.\n\
+WINDOW nil or omitted means use the selected window.\n\
+MINIBUF t means include the minibuffer window, even if it isn't active.\n\
+MINIBUF nil or omitted means include the minibuffer window only\n\
+if it's active.\n\
+MINIBUF neither nil nor t means never include the minibuffer window.")
+ (frame, minibuf, window)
+ Lisp_Object frame, minibuf, window;
+{
+ Lisp_Object list;
+
+ if (NILP (window))
+ window = selected_window;
+ if (NILP (frame))
+ frame = selected_frame;
+
+ if (!EQ (frame, XWINDOW (window)->frame))
+ error ("Window is on a different frame");
+
+ return window_list_1 (window, minibuf, frame);
+}
+
+
+/* Return a list of windows in canonical ordering. Arguments are like
+ for `next-window'. */
+
+static Lisp_Object
+window_list_1 (window, minibuf, all_frames)
Lisp_Object window, minibuf, all_frames;
{
Lisp_Object tail, list;
We can't just wait until we hit the first window again, because
it might be deleted. */
- windows = Fwindow_list (window, mini ? Qt : Qnil, frame_arg);
+ windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
GCPRO1 (windows);
best_window = Qnil;
int old_size, min_size;
check_min_window_sizes ();
+ size = max (0, size);
/* 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);
+ old_size = XINT (w->width);
min_size = window_min_width;
}
else
{
- old_size = XFASTINT (w->height);
+ old_size = XINT (w->height);
min_size = window_min_height;
}
}
/* Set redisplay hints. */
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
+ w->last_modified = make_number (0);
+ w->last_overlay_modified = make_number (0);
windows_or_buffers_changed++;
- FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
+ FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
if (width_p)
{
sideward = &w->vchild;
forward = &w->hchild;
- XSETFASTINT (w->width, size);
+ w->width = make_number (size);
}
else
{
sideward = &w->hchild;
forward = &w->vchild;
- XSETFASTINT (w->height, size);
+ w->height = make_number (size);
}
if (!NILP (*sideward))
{
int fixed_size, each, extra, n;
int resize_fixed_p, nfixed;
- int last_pos, first_pos, nchildren;
+ int last_pos, first_pos, nchildren, total;
/* Determine the fixed-size portion of the this window, and the
number of child windows. */
- fixed_size = nchildren = nfixed = 0;
+ fixed_size = nchildren = nfixed = total = 0;
for (child = *forward; !NILP (child); child = c->next, ++nchildren)
{
+ int child_size;
+
c = XWINDOW (child);
+ child_size = width_p ? XINT (c->width) : XINT (c->height);
+ total += child_size;
+
if (window_fixed_size_p (c, width_p, 0))
{
- fixed_size += (width_p
- ? XFASTINT (c->width) : XFASTINT (c->height));
+ fixed_size += child_size;
++nfixed;
}
}
/* 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;
+ each = (size - total) / n;
+ extra = (size - total) - n * each;
/* Compute new children heights and edge positions. */
- first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
+ first_pos = width_p ? XINT (w->left) : XINT (w->top);
last_pos = first_pos;
for (child = *forward; !NILP (child); child = c->next)
{
{
int child_size;
c = XWINDOW (child);
- child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
+ child_size = width_p ? XINT (c->width) : XINT (c->height);
size_window (child, child_size, width_p, 0);
}
}
If FRAME is a frame, search only that frame.\n\
If FRAME is nil, search only the selected frame\n\
(actually the last nonminibuffer frame),\n\
- unless `pop-up-frames' or `display-reuse-frames' is non-nil,\n\
+ unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,\n\
which means search visible and iconified frames.")
(buffer, not_this_window, frame)
register Lisp_Object buffer, not_this_window, frame;
/* If PT is not visible in WINDOW, move back one half of
the screen. */
XSETFASTINT (tem, PT);
- tem = Fpos_visible_in_window_p (tem, window, Qt);
+ tem = Fpos_visible_in_window_p (tem, window, Qnil);
if (NILP (tem))
{
/* Move backward half the height of the window. Performance note:
original_vpos = posit.vpos;
XSETFASTINT (tem, PT);
- tem = Fpos_visible_in_window_p (tem, window, Qt);
+ tem = Fpos_visible_in_window_p (tem, window, Qnil);
if (NILP (tem))
{
struct it it;
struct text_pos start;
int height = window_box_height (w);
+ struct buffer *old_buffer;
+ int bottom_y;
+
+ if (XBUFFER (w->buffer) != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal (XBUFFER (w->buffer));
+ }
+ else
+ old_buffer = NULL;
SET_TEXT_POS_FROM_MARKER (start, w->start);
start_display (&it, w, start);
move_it_vertically (&it, height);
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
+
/* Add in empty lines at the bottom of the window. */
- if (it.current_y < height)
+ bottom_y = it.current_y + it.max_ascent + it.max_descent;
+ if (bottom_y < height)
{
struct frame *f = XFRAME (w->frame);
- int rest = height - it.current_y;
+ int rest = height - bottom_y;
int lines = (rest + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
it.vpos += lines;
}
+ else if (it.current_y < height && bottom_y > height)
+ /* Partially visible line at the bottom. */
+ ++it.vpos;
return it.vpos;
}
Lisp_Object parent, prev;
Lisp_Object start_at_line_beg;
Lisp_Object display_table;
+ Lisp_Object orig_top, orig_height;
};
-#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
+#define SAVED_WINDOW_VECTOR_SIZE 16 /* Arg to Fmake_vector */
#define SAVED_WINDOW_N(swv,n) \
((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
{
if (XBUFFER (new_current_buffer) == current_buffer)
old_point = PT;
-
}
frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
struct window *root_window;
struct window **leaf_windows;
int n_leaf_windows;
- int k, i;
+ int k, i, n;
/* If the frame has been resized since this window configuration was
made, we change the frame to the size specified in the
w->height = p->height;
w->hscroll = p->hscroll;
w->display_table = p->display_table;
+ w->orig_top = p->orig_top;
+ w->orig_height = p->orig_height;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
#endif
/* Now, free glyph matrices in windows that were not reused. */
- for (i = 0; i < n_leaf_windows; ++i)
- if (NILP (leaf_windows[i]->buffer))
- {
- /* Assert it's not reused as a combination. */
- xassert (NILP (leaf_windows[i]->hchild)
- && NILP (leaf_windows[i]->vchild));
- free_window_matrices (leaf_windows[i]);
- SET_FRAME_GARBAGED (f);
- }
+ for (i = n = 0; i < n_leaf_windows; ++i)
+ {
+ if (NILP (leaf_windows[i]->buffer))
+ {
+ /* Assert it's not reused as a combination. */
+ xassert (NILP (leaf_windows[i]->hchild)
+ && NILP (leaf_windows[i]->vchild));
+ free_window_matrices (leaf_windows[i]);
+ SET_FRAME_GARBAGED (f);
+ }
+ else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
+ ++n;
+ }
+
+ /* If more than one window shows the new and old current buffer,
+ don't try to preserve point in that buffer. */
+ if (old_point > 0 && n > 1)
+ old_point = -1;
adjust_glyphs (f);
p->height = w->height;
p->hscroll = w->hscroll;
p->display_table = w->display_table;
+ p->orig_top = w->orig_top;
+ p->orig_height = w->orig_height;
if (!NILP (w->buffer))
{
/* Save w's value of point in the window configuration.
for (i = 0; i < n_windows; i++)
XVECTOR (tem)->contents[i]
= Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
- save_window_save (FRAME_ROOT_WINDOW (f),
- XVECTOR (tem), 0);
+ save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
XSETWINDOW_CONFIGURATION (tem, data);
return (tem);
}