summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2015-02-09 18:24:46 +0200
committerEli Zaretskii <eliz@gnu.org>2015-02-09 18:24:46 +0200
commit403cb178c75a80603dbd8ed23e342d2109645401 (patch)
tree815315bef8212ed239805f13089612ebcef78a82
parentaf560cd6f15e7cc7e42bff5b3c802b9d1d1640b5 (diff)
downloademacs-403cb178c75a80603dbd8ed23e342d2109645401.tar.gz
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.
-rw-r--r--doc/lispref/ChangeLog5
-rw-r--r--doc/lispref/positions.texi10
-rw-r--r--src/ChangeLog7
-rw-r--r--src/indent.c55
-rw-r--r--src/window.c21
5 files changed, 74 insertions, 24 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 3fe3d6fd6a0..0c76a6b8b34 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -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
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index 317b9d64a5c..b74116ebf1d 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -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
diff --git a/src/ChangeLog b/src/ChangeLog
index 2a702a29a7d..4afcdcf0711 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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.
diff --git a/src/indent.c b/src/indent.c
index 8660400e1ce..f0aea002fd2 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -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);
diff --git a/src/window.c b/src/window.c
index 293140041a9..d59616d0545 100644
--- a/src/window.c
+++ b/src/window.c
@@ -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);
}