+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
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.
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
+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.
-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.
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;
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);
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
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)
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);
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 ();
&& (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. */
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
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);
/* 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
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);
}
}
}
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;
if (w->vscroll)
XSETINT (arg, XINT (arg) + 1);
- return Fvertical_motion (arg, window);
+ return Fvertical_motion (arg, window, Qnil);
}