Speed up vertical-motion when screen coordinates are known

src/indent.c (Fvertical_motion): Accept an additional argument
 CUR-COL and use it as the starting screen coordinate.
 src/window.c (window_scroll_line_based, Fmove_to_window_line): All
 callers of vertical-motion changed.

 doc/lispref/positions.texi (Screen Lines): Update the documentation of
 vertical-motion to document the new additional argument.
This commit is contained in:
Eli Zaretskii 2015-02-09 18:24:46 +02:00
parent af560cd6f1
commit 403cb178c7
5 changed files with 74 additions and 24 deletions

View file

@ -1,3 +1,8 @@
2015-02-09 Eli Zaretskii <eliz@gnu.org>
* positions.texi (Screen Lines): Update the documentation of
vertical-motion to document the new additional argument.
2015-02-06 Nicolas Petton <nicolas@petton.fr>
* sequences.texi (Sequence Functions): Add documentation for

View file

@ -493,7 +493,7 @@ If you intend to use them heavily, Emacs provides caches which may
improve the performance of your code. @xref{Truncation, cache-long-scans}.
@end ignore
@defun vertical-motion count &optional window
@defun vertical-motion count &optional window cur-col
This function moves point to the start of the screen line @var{count}
screen lines down from the screen line containing point. If @var{count}
is negative, it moves up instead.
@ -515,6 +515,14 @@ The window @var{window} is used for obtaining parameters such as the
width, the horizontal scrolling, and the display table. But
@code{vertical-motion} always operates on the current buffer, even if
@var{window} currently displays some other buffer.
The optional argument @var{cur-col} specifies the current column when
the function is called. This is the window-relative horizontal
coordinate of point, measured in units of font width of the frame's
default face. Providing it speeds up the function, especially in very
long lines, because it doesn't have to go back in the buffer in order
to determine the current column. Note that @var{cur-col} is also
counted from the visual start of the line.
@end defun
@defun count-screen-lines &optional beg end count-final-newline window

View file

@ -1,3 +1,10 @@
2015-02-09 Eli Zaretskii <eliz@gnu.org>
* indent.c (Fvertical_motion): Accept an additional argument
CUR-COL and use it as the starting screen coordinate.
* window.c (window_scroll_line_based, Fmove_to_window_line): All
callers of vertical-motion changed.
2015-02-09 Dima Kogan <dima@secretsauce.net>
* font.c (font_score): Remove unused variable assignment.

View file

@ -1928,7 +1928,7 @@ vmotion (register ptrdiff_t from, register ptrdiff_t from_byte,
-1, hscroll, 0, w);
}
DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 3, 0,
doc: /* Move point to start of the screen line LINES lines down.
If LINES is negative, this means moving up.
@ -1951,12 +1951,18 @@ is). If the line is scrolled horizontally, COLS is interpreted
visually, i.e., as addition to the columns of text beyond the left
edge of the window.
The optional third argument CUR-COL specifies the horizontal
window-relative coordinate of point, in units of frame's canonical
character width, where the function is invoked. If this argument is
omitted or nil, the function will determine the point coordinate by
going back to the beginning of the line.
`vertical-motion' always uses the current buffer,
regardless of which buffer is displayed in WINDOW.
This is consistent with other cursor motion functions
and makes it possible to use `vertical-motion' in any buffer,
whether or not it is currently displayed in some window. */)
(Lisp_Object lines, Lisp_Object window)
(Lisp_Object lines, Lisp_Object window, Lisp_Object cur_col)
{
struct it it;
struct text_pos pt;
@ -2006,6 +2012,22 @@ whether or not it is currently displayed in some window. */)
bool disp_string_at_start_p = 0;
ptrdiff_t nlines = XINT (lines);
int vpos_init = 0;
double start_col;
int start_x;
bool start_x_given = false;
int to_x = -1;
if (!NILP (cur_col))
{
CHECK_NUMBER_OR_FLOAT (cur_col);
start_col =
INTEGERP (cur_col)
? (double) XINT (cur_col)
: XFLOAT_DATA (cur_col);
start_x =
(int)(start_col * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5);
start_x_given = true;
}
itdata = bidi_shelve_cache ();
SET_TEXT_POS (pt, PT, PT_BYTE);
@ -2042,11 +2064,19 @@ whether or not it is currently displayed in some window. */)
it_overshoot_count =
!(it.method == GET_FROM_IMAGE || it.method == GET_FROM_STRETCH);
/* Scan from the start of the line containing PT. If we don't
do this, we start moving with IT->current_x == 0, while PT is
really at some x > 0. */
reseat_at_previous_visible_line_start (&it);
it.current_x = it.hpos = 0;
if (start_x_given)
{
it.hpos = (int) start_col;
it.current_x = start_x;
}
else
{
/* Scan from the start of the line containing PT. If we don't
do this, we start moving with IT->current_x == 0, while PT is
really at some x > 0. */
reseat_at_previous_visible_line_start (&it);
it.current_x = it.hpos = 0;
}
if (IT_CHARPOS (it) != PT)
/* We used to temporarily disable selective display here; the
comment said this is "so we don't move too far" (2005-01-19
@ -2108,12 +2138,15 @@ whether or not it is currently displayed in some window. */)
return the correct value to the caller. */
vpos_init = -1;
}
if (!NILP (lcols))
to_x = (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5);
if (nlines <= 0)
{
it.vpos = vpos_init;
/* Do this even if LINES is 0, so that we move back to the
beginning of the current line as we ought. */
if (nlines == 0 || IT_CHARPOS (it) > 0)
if ((nlines < 0 && IT_CHARPOS (it) > 0)
|| (nlines == 0 && !(start_x_given && start_x <= to_x)))
move_it_by_lines (&it, max (PTRDIFF_MIN, nlines));
}
else if (overshoot_handled)
@ -2153,11 +2186,7 @@ whether or not it is currently displayed in some window. */)
was originally hscrolled, the goal column is interpreted as
an addition to the hscroll amount. */
if (!NILP (lcols))
{
int to_x = (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5);
move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X);
}
move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X);
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
bidi_unshelve_cache (itdata, 0);

View file

@ -5350,14 +5350,14 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
if (NILP (tem))
{
Fvertical_motion (make_number (- (ht / 2)), window);
Fvertical_motion (make_number (- (ht / 2)), window, Qnil);
startpos = PT;
startbyte = PT_BYTE;
}
SET_PT_BOTH (startpos, startbyte);
lose = n < 0 && PT == BEGV;
Fvertical_motion (make_number (n), window);
Fvertical_motion (make_number (n), window, Qnil);
pos = PT;
pos_byte = PT_BYTE;
bolp = Fbolp ();
@ -5389,7 +5389,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
&& (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (original_pos, window);
Fvertical_motion (original_pos, window, Qnil);
}
/* If we scrolled forward, put point enough lines down
that it is outside the scroll margin. */
@ -5400,7 +5400,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
if (this_scroll_margin > 0)
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (make_number (this_scroll_margin), window);
Fvertical_motion (make_number (this_scroll_margin), window, Qnil);
top_margin = PT;
}
else
@ -5412,7 +5412,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
else if (!NILP (Vscroll_preserve_screen_position))
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (original_pos, window);
Fvertical_motion (original_pos, window, Qnil);
}
else
SET_PT (top_margin);
@ -5424,7 +5424,8 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
/* If we scrolled backward, put point near the end of the window
but not within the scroll margin. */
SET_PT_BOTH (pos, pos_byte);
tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
tem = Fvertical_motion (make_number (ht - this_scroll_margin), window,
Qnil);
if (XFASTINT (tem) == ht - this_scroll_margin)
bottom_margin = PT;
else
@ -5438,10 +5439,10 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
if (!NILP (Vscroll_preserve_screen_position))
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (original_pos, window);
Fvertical_motion (original_pos, window, Qnil);
}
else
Fvertical_motion (make_number (-1), window);
Fvertical_motion (make_number (-1), window, Qnil);
}
}
}
@ -5999,7 +6000,7 @@ zero means top of window, negative means relative to bottom of window. */)
if (start < BEGV || start > ZV)
{
int height = window_internal_height (w);
Fvertical_motion (make_number (- (height / 2)), window);
Fvertical_motion (make_number (- (height / 2)), window, Qnil);
set_marker_both (w->start, w->contents, PT, PT_BYTE);
w->start_at_line_beg = !NILP (Fbolp ());
w->force_start = 1;
@ -6040,7 +6041,7 @@ zero means top of window, negative means relative to bottom of window. */)
if (w->vscroll)
XSETINT (arg, XINT (arg) + 1);
return Fvertical_motion (arg, window);
return Fvertical_motion (arg, window, Qnil);
}