Lisp_Object Qwindow_size_fixed, Qleft_fringe, Qright_fringe;
extern Lisp_Object Qheight, Qwidth;
+static int displayed_window_lines P_ ((struct window *));
static struct window *decode_window P_ ((Lisp_Object));
static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
static int count_windows P_ ((struct window *));
{
Lisp_Object val;
register struct window *p;
- register struct Lisp_Vector *vec;
- int i;
- vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
- for (i = 0; i < VECSIZE (struct window); i++)
- vec->contents[i] = Qnil;
- vec->size = VECSIZE (struct window);
- p = (struct window *) vec;
+ p = allocate_window ();
XSETFASTINT (p->sequence_number, ++sequence_number);
XSETFASTINT (p->left, 0);
XSETFASTINT (p->top, 0);
int ux = CANON_X_UNIT (f), uy = CANON_Y_UNIT (f);
int x0 = XFASTINT (w->left) * ux;
int x1 = x0 + XFASTINT (w->width) * ux;
+ /* The width of the area where the vertical line can be dragged.
+ (Between mode lines for instance. */
+ int grabbable_width = ux;
if (*x < x0 || *x >= x1)
return ON_NOTHING;
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
{
- if (abs (*x - x0) < ux / 2)
+ if (abs (*x - x0) < grabbable_width)
part = ON_VERTICAL_BORDER;
}
- else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < ux / 2)
+ else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < grabbable_width)
part = ON_VERTICAL_BORDER;
}
else if (WINDOW_WANTS_HEADER_LINE_P (w)
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
{
- if (abs (*x - x0) < ux / 2)
+ if (abs (*x - x0) < grabbable_width)
part = ON_VERTICAL_BORDER;
}
- else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < ux / 2)
+ else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < grabbable_width)
part = ON_VERTICAL_BORDER;
}
/* Outside anything interesting? */
if (!w->pseudo_window_p
&& !FRAME_HAS_VERTICAL_SCROLL_BARS (f)
&& !WINDOW_RIGHTMOST_P (w)
- && (abs (*x - right_x - flags_area_width) < ux / 2))
+ && (abs (*x - right_x - flags_area_width) < grabbable_width))
{
part = ON_VERTICAL_BORDER;
}
{
struct text_pos startp;
struct it it;
+ struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
/* In case W->start is out of the range, use something
reasonable. This situation occured when loading a file with
/* Cannot use Fvertical_motion because that function doesn't
cope with variable-height lines. */
+ if (b != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal (b);
+ }
+
start_display (&it, w, startp);
move_it_vertically (&it, window_box_height (w));
- move_it_past_eol (&it);
+ if (it.current_y < it.last_visible_y)
+ move_it_past_eol (&it);
value = make_number (IT_CHARPOS (it));
+
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
}
else
XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
XSETFASTINT (w->window_end_vpos, 0);
bzero (&w->last_cursor, sizeof w->last_cursor);
w->window_end_valid = Qnil;
- XSETFASTINT (w->hscroll, 0);
- XSETFASTINT (w->min_hscroll, 0);
+ w->hscroll = w->min_hscroll = make_number (0);
+ w->vscroll = 0;
set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
set_marker_restricted (w->start,
make_number (b->last_window_start),
{
Lisp_Object new;
register struct window *o, *p;
- register struct Lisp_Vector *vec;
int i;
o = XWINDOW (window);
- vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
+ p = allocate_window ();
for (i = 0; i < VECSIZE (struct window); ++i)
- vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
- vec->size = VECSIZE (struct window);
- p = (struct window *)vec;
+ ((struct Lisp_Vector *) p)->contents[i]
+ = ((struct Lisp_Vector *)o)->contents[i];
XSETWINDOW (new, p);
XSETFASTINT (p->sequence_number, ++sequence_number);
}
-/* Return number of lines of text (not counting mode line) in W. */
+/* Return number of lines of text (not counting mode lines) in W. */
int
window_internal_height (w)
{
int ht = XFASTINT (w->height);
- if (MINI_WINDOW_P (w))
- return ht;
-
- if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
- || !NILP (w->next) || !NILP (w->prev)
- || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
- return ht - 1;
+ if (!MINI_WINDOW_P (w))
+ {
+ if (!NILP (w->parent)
+ || !NILP (w->vchild)
+ || !NILP (w->hchild)
+ || !NILP (w->next)
+ || !NILP (w->prev)
+ || WINDOW_WANTS_MODELINE_P (w))
+ --ht;
+
+ if (WINDOW_WANTS_HEADER_LINE_P (w))
+ --ht;
+ }
return ht;
}
***********************************************************************/
/* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
- one screen-full, which is defined as the height of the window minus
+ N screen-fulls, which is defined as the height of the window minus
next_screen_context_lines. If WHOLE is zero, scroll up N lines
instead. Negative values of N mean scroll down. NOERROR non-zero
means don't signal an error if we try to move over BEGV or ZV,
SET_TEXT_POS_FROM_MARKER (start, w->start);
/* If PT is not visible in WINDOW, move back one half of
- the screen. */
- tem = Fpos_visible_in_window_p (make_number (PT), window, Qnil);
+ the screen. Allow PT to be partially visible, otherwise
+ something like (scroll-down 1) with PT in the line before
+ the partially visible one would recenter. */
+ tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
if (NILP (tem))
{
/* Move backward half the height of the window. Performance note:
results for variable height lines. */
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
it.current_y = it.last_visible_y;
- move_it_vertically (&it, -it.last_visible_y / 2);
+ move_it_vertically (&it, - window_box_height (w) / 2);
/* The function move_iterator_vertically may move over more than
the specified y-distance. If it->w is small, e.g. a
start_display (&it, w, start);
if (whole)
{
- int screen_full = (it.last_visible_y
+ int screen_full = (window_box_height (w)
- next_screen_context_lines * CANON_Y_UNIT (it.f));
- int direction = n < 0 ? -1 : 1;
- int dy = direction * screen_full;
+ int dy = n * screen_full;
/* Note that move_it_vertically always moves the iterator to the
start of a line. So, if the last line doesn't have a newline,
struct position posit;
int original_vpos;
+ /* If scrolling screen-fulls, compute the number of lines to
+ scroll from the window's height. */
+ if (whole)
+ n *= max (1, ht - next_screen_context_lines);
+
startpos = marker_position (w->start);
posit = *compute_motion (startpos, 0, 0, 0,
Lisp_Object n;
int direction;
{
- register int defalt;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
xassert (abs (direction) == 1);
++windows_or_buffers_changed;
}
- defalt = (window_internal_height (XWINDOW (selected_window))
- - next_screen_context_lines);
- defalt = direction * (defalt < 1 ? 1 : defalt);
-
if (NILP (n))
- window_scroll (selected_window, defalt, 1, 0);
+ window_scroll (selected_window, direction, 1, 0);
else if (EQ (n, Qminus))
- window_scroll (selected_window, - defalt, 1, 0);
+ window_scroll (selected_window, -direction, 1, 0);
else
{
n = Fprefix_numeric_value (n);
If `other-window-scroll-buffer' is non-nil, scroll the window\n\
showing that buffer, popping the buffer up if necessary.")
(arg)
- register Lisp_Object arg;
+ Lisp_Object arg;
{
- register Lisp_Object window;
- register int defalt;
- register struct window *w;
- register int count = specpdl_ptr - specpdl;
+ Lisp_Object window;
+ struct window *w;
+ int count = BINDING_STACK_SIZE ();
window = Fother_window_for_scrolling ();
-
w = XWINDOW (window);
- defalt = window_internal_height (w) - next_screen_context_lines;
- if (defalt < 1) defalt = 1;
/* Don't screw up if window_scroll gets an error. */
record_unwind_protect (save_excursion_restore, save_excursion_save ());
SET_PT (marker_position (w->pointm));
if (NILP (arg))
- window_scroll (window, defalt, 1, 1);
+ window_scroll (window, 1, 1, 1);
else if (EQ (arg, Qminus))
- window_scroll (window, -defalt, 1, 1);
+ window_scroll (window, -1, 1, 1);
else
{
if (CONSP (arg))
else
old_buffer = NULL;
- SET_TEXT_POS_FROM_MARKER (start, w->start);
+ /* In case W->start is out of the accessible range, do something
+ reasonable. This happens in Info mode when Info-scroll-down
+ calls (recenter -1) while W->start is 1. */
+ if (XMARKER (w->start)->charpos < BEGV)
+ SET_TEXT_POS (start, BEGV, BEGV_BYTE);
+ else if (XMARKER (w->start)->charpos > ZV)
+ SET_TEXT_POS (start, ZV, ZV_BYTE);
+ else
+ 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);
-
- bottom_y = it.current_y + it.max_ascent + it.max_descent;
-
- if (bottom_y > it.current_y && bottom_y <= it.last_visible_y)
- /* Hit a line without a terminating newline. */
- it.vpos++;
+ bottom_y = line_bottom_y (&it);
/* Add in empty lines at the bottom of the window. */
if (bottom_y < height)
{
- struct frame *f = XFRAME (w->frame);
- int rest = height - bottom_y;
- int lines = rest / CANON_Y_UNIT (f);
- it.vpos += lines;
+ int uy = CANON_Y_UNIT (it.f);
+ it.vpos += (height - bottom_y + uy - 1) / uy;
}
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
+
return it.vpos;
}
set_buffer_internal (buf);
- /* Handle centering on a gfaphical frame specially. Such frames can
+ /* Handle centering on a graphical frame specially. Such frames can
have variable-height lines and centering point on the basis of
line counts would lead to strange effects. */
- if (center_p && FRAME_WINDOW_P (XFRAME (w->frame)))
- {
- struct it it;
- struct text_pos pt;
-
- SET_TEXT_POS (pt, PT, PT_BYTE);
- start_display (&it, w, pt);
- move_it_vertically (&it, - it.last_visible_y / 2);
- charpos = IT_CHARPOS (it);
- bytepos = IT_BYTEPOS (it);
- }
- else
+ if (FRAME_WINDOW_P (XFRAME (w->frame)))
{
- struct position pos;
-
if (center_p)
{
- int ht = displayed_window_lines (w);
- arg = make_number (ht / 2);
+ struct it it;
+ struct text_pos pt;
+
+ SET_TEXT_POS (pt, PT, PT_BYTE);
+ start_display (&it, w, pt);
+ move_it_vertically (&it, - window_box_height (w) / 2);
+ charpos = IT_CHARPOS (it);
+ bytepos = IT_BYTEPOS (it);
}
else if (XINT (arg) < 0)
{
- int ht = displayed_window_lines (w);
- XSETINT (arg, XINT (arg) + ht);
+ struct it it;
+ struct text_pos pt;
+ int y0, y1, h, nlines;
+
+ SET_TEXT_POS (pt, PT, PT_BYTE);
+ start_display (&it, w, pt);
+ y0 = it.current_y;
+
+ /* The amount of pixels we have to move back is the window
+ height minus what's displayed in the line containing PT,
+ and the lines below. */
+ nlines = - XINT (arg) - 1;
+ move_it_by_lines (&it, nlines, 1);
+
+ y1 = it.current_y - y0;
+ h = line_bottom_y (&it) - y1;
+
+ /* If we can't move down NLINES lines because we hit
+ the end of the buffer, count in some empty lines. */
+ if (it.vpos < nlines)
+ y1 += (nlines - it.vpos) * CANON_Y_UNIT (it.f);
+
+ y0 = it.last_visible_y - y1 - h;
+
+ start_display (&it, w, pt);
+ move_it_vertically (&it, - y0);
+ charpos = IT_CHARPOS (it);
+ bytepos = IT_BYTEPOS (it);
}
+ else
+ {
+ struct position pos;
+ pos = *vmotion (PT, - XINT (arg), w);
+ charpos = pos.bufpos;
+ bytepos = pos.bytepos;
+ }
+ }
+ else
+ {
+ struct position pos;
+ int ht = window_internal_height (w);
+
+ if (center_p)
+ arg = make_number (ht / 2);
+ else if (XINT (arg) < 0)
+ arg = make_number (XINT (arg) + ht);
pos = *vmotion (PT, - XINT (arg), w);
charpos = pos.bufpos;
XSETINT (arg, XINT (arg) + lines);
}
-#if 0 /* I don't understand why this is done. Among other things,
- it means that C-u 0 M-r moves to line 1, and C-u -1 M-r
- moves to the line below the window end. 2000-02-05, gerd */
+ /* Skip past a partially visible first line. */
if (w->vscroll)
- /* Skip past a partially visible first line. */
XSETINT (arg, XINT (arg) + 1);
-#endif
return Fvertical_motion (arg, window);
}
when the frame's old selected window has been deleted. */
if (f != selected_frame && FRAME_WINDOW_P (f))
do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
- Qnil, 0);
+ 0, 0);
#endif
/* Set the screen height to the value it had before this function. */
Fselect_window above totally superfluous; it still sets f's
selected window. */
if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
- do_switch_frame (data->selected_frame, Qnil, 0);
+ do_switch_frame (data->selected_frame, 0, 0);
if (! NILP (Vwindow_configuration_change_hook)
&& ! NILP (Vrun_hooks))
f = XFRAME (frame);
n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
- vec = allocate_vectorlike (VECSIZE (struct save_window_data));
- for (i = 0; i < VECSIZE (struct save_window_data); i++)
- vec->contents[i] = Qnil;
- vec->size = VECSIZE (struct save_window_data);
+ vec = allocate_other_vector (VECSIZE (struct save_window_data));
data = (struct save_window_data *)vec;
XSETFASTINT (data->frame_width, FRAME_WIDTH (f));