]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix 'recenter' when visual-line-mode is turned on
authorEli Zaretskii <eliz@gnu.org>
Fri, 10 Apr 2015 10:09:42 +0000 (13:09 +0300)
committerEli Zaretskii <eliz@gnu.org>
Fri, 10 Apr 2015 10:09:42 +0000 (13:09 +0300)
* src/window.c (Frecenter): Use the same code for GUI and TTY
frames alike; use vmotion only for "initial" frames.  This is
because vmotion doesn't support visual-line-mode.  Rewrite the
'iarg >= 0' case to use move_it_* functions instead of using
vmotion, for the same reason.  Fix the clipping of the argument
value to support scroll-margin in all cases and avoid unwarranted
recentering.  Reported by Milan Stanojević <milanst@gmail.com> in
http://lists.gnu.org/archive/html/help-gnu-emacs/2015-04/msg00092.html,
which see.

src/window.c

index d59616d054554b54182f9342555e31e6775ae440..55fcb8cf02f6bb2c0bdcb1c8a3ce063626d0f4e8 100644 (file)
@@ -5799,10 +5799,9 @@ and redisplay normally--don't erase and redraw the frame.  */)
   this_scroll_margin
     = max (0, min (scroll_margin, w->total_lines / 4));
 
-  /* 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 (FRAME_WINDOW_P (XFRAME (w->frame)))
+  /* Don't use redisplay code for initial frames, as the necessary
+     data structures might not be set up yet then.  */
+  if (!FRAME_INITIAL_P (XFRAME (w->frame)))
     {
       if (center_p)
        {
@@ -5824,9 +5823,11 @@ and redisplay normally--don't erase and redraw the frame.  */)
          ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
          int extra_line_spacing;
          int h = window_box_height (w);
+         int ht = window_internal_height (w);
          void *itdata = bidi_shelve_cache ();
 
-         iarg = - max (-iarg, this_scroll_margin);
+         nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
+                                  ht - this_scroll_margin);
 
          SET_TEXT_POS (pt, PT, PT_BYTE);
          start_display (&it, w, pt);
@@ -5890,13 +5891,33 @@ and redisplay normally--don't erase and redraw the frame.  */)
        }
       else
        {
-         struct position pos;
+         struct it it;
+         struct text_pos pt;
+         ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
+         int ht = window_internal_height (w);
+         void *itdata = bidi_shelve_cache ();
+
+         nlines = clip_to_bounds (this_scroll_margin, nlines,
+                                  ht - this_scroll_margin - 1);
+
+         SET_TEXT_POS (pt, PT, PT_BYTE);
+         start_display (&it, w, pt);
 
-         iarg = max (iarg, this_scroll_margin);
+         /* Move to the beginning of screen line containing PT.  */
+         move_it_by_lines (&it, 0);
+
+         /* Move back to find the point which is ARG screen lines above PT.  */
+         if (nlines > 0)
+           {
+             it.current_y = 0;
+             it.vpos = 0;
+             move_it_by_lines (&it, -nlines);
+           }
 
-         pos = *vmotion (PT, PT_BYTE, -iarg, w);
-         charpos = pos.bufpos;
-         bytepos = pos.bytepos;
+         charpos = IT_CHARPOS (it);
+         bytepos = IT_BYTEPOS (it);
+
+         bidi_unshelve_cache (itdata, 0);
        }
     }
   else