]> git.eshelyaron.com Git - emacs.git/commitdiff
Speed up vertical-motion when screen coordinates are known
authorEli Zaretskii <eliz@gnu.org>
Mon, 9 Feb 2015 16:24:46 +0000 (18:24 +0200)
committerEli Zaretskii <eliz@gnu.org>
Mon, 9 Feb 2015 16:24:46 +0000 (18:24 +0200)
 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.

doc/lispref/ChangeLog
doc/lispref/positions.texi
src/ChangeLog
src/indent.c
src/window.c

index 3fe3d6fd6a0d441a7654dcae617d56e1b509a042..0c76a6b8b34bc49732aca4b72e028b60bcd76cd6 100644 (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
index 317b9d64a5c20ce27966321359f8d87f0df8b35b..b74116ebf1d2ce578892ea52e1b5c19d654f19e0 100644 (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
index 2a702a29a7dba26813a7200158bb803e6d73f156..4afcdcf071173976826defb77be8d5ff4218b95c 100644 (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.
index 8660400e1cec8775f416098e7b848bd4aa442206..f0aea002fd23279f5d2608d3eec7c77fb7124035 100644 (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);
index 293140041a9e9fa081ce4d141bceb9ca0e70d189..d59616d054554b54182f9342555e31e6775ae440 100644 (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);
 }