Subject: bug#27008: 26.0.50; auto-hscroll-mode and scroll-left

From: Eli Zaretskii <[email-masked]>
Date: Wed, 31 May 2017 10:14:41 +0300

> From: Stephen Berman <[email-masked]>
> Cc: [email-masked]
> Date: Tue, 30 May 2017 21:45:47 +0200
> 
> Thanks.  Yes, with this patch the non-current lines are displayed from
> w->min_hscroll.  However, there's a new problem: now when points moves
> to a line, that line automatically scrolls further by w->min_hscroll.
> So when I do `(scroll-left 32 t)' and then move point to another line,
> that line scrolls further left so that its column 64 is on the left edge
> of the window (the other lines remain displayed starting at column 32).
> When point moves to the next line, that one scrolls further to column 64
> and the previous one goes back to being displayed from column 32.

Does the below (to be applied on top of current master, i.e. first
revert the previous patch) fix this?

diff --git a/src/xdisp.c b/src/xdisp.c
index c03689b..c96ffce 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2890,8 +2890,19 @@ init_iterator (struct it *it, struct window *w,
     }
   else
     {
+      /* When hscrolling only the current line, don't apply the
+	 hscroll here, it will be applied by display_line when it gets
+	 to laying out the line showing point.  However, if the
+	 window's min_hscroll is positive, the user specified a lower
+	 bound for automatic hscrolling, so they expect the
+	 non-current lines to obey that hscroll amount.  */
       if (hscrolling_current_line_p (w))
-	it->first_visible_x = 0;
+	{
+	  if (w->min_hscroll > 0)
+	    it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
+	  else
+	    it->first_visible_x = 0;
+	}
       else
 	it->first_visible_x =
 	  window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
@@ -13099,7 +13110,9 @@ hscroll_window_tree (Lisp_Object window)
 		     that doesn't need to be hscrolled.  If we omit
 		     this condition, the line from which we move will
 		     remain hscrolled.  */
-		  || (hscl && w->hscroll && !cursor_row->truncated_on_left_p)))
+		  || (hscl
+		      && w->hscroll != w->min_hscroll
+		      && !cursor_row->truncated_on_left_p)))
 	    {
 	      struct it it;
 	      ptrdiff_t hscroll;
@@ -20710,7 +20723,9 @@ display_line (struct it *it, int cursor_vpos)
   /* If we are going to display the cursor's line, account for the
      hscroll of that line.  */
   if (hscroll_this_line)
-    x_incr = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
+    x_incr =
+      (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
+      * FRAME_COLUMN_WIDTH (it->f);
 
   /* Move over display elements that are not visible because we are
      hscrolled.  This may stop at an x-position < first_visible_x