diff src/window.c @ 95566:b3c0438c570b

* window.c (window_scroll_pixel_based_preserve_x) (window_scroll_preserve_hpos, window_scroll_preserve_vpos): New vars. (window_scroll_pixel_based, window_scroll_line_based): Use them to preserve column positions. (syms_of_window): Initialize them. * indent.c (Fvertical_motion): Extend first arg to allow passing an (HPOS . VPOS) pair. * xdisp.c (move_it_in_display_line_to): Improve the type of its args. (move_it_in_display_line): New wrapper. * dispextern.h (move_it_in_display_line): Declare.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Thu, 05 Jun 2008 03:57:09 +0000
parents 823072be49ad
children 9a4b27c8feec
line wrap: on
line diff
--- a/src/window.c	Thu Jun 05 03:23:31 2008 +0000
+++ b/src/window.c	Thu Jun 05 03:57:09 2008 +0000
@@ -224,8 +224,14 @@
 
 /* Used by the function window_scroll_pixel_based */
 
+static int window_scroll_pixel_based_preserve_x;
 static int window_scroll_pixel_based_preserve_y;
 
+/* Same for window_scroll_line_based.  */
+
+static int window_scroll_preserve_hpos;
+static int window_scroll_preserve_vpos;
+
 #if 0 /* This isn't used anywhere.  */
 /* Nonzero means we can split a frame even if it is "unsplittable".  */
 static int inhibit_frame_unsplittable;
@@ -5216,10 +5222,12 @@
 	  start_display (&it, w, start);
 	  move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
 	  window_scroll_pixel_based_preserve_y = it.current_y;
+	  window_scroll_pixel_based_preserve_x = it.current_x;
 	}
     }
   else
-    window_scroll_pixel_based_preserve_y = -1;
+    window_scroll_pixel_based_preserve_y
+      = window_scroll_pixel_based_preserve_x = -1;
 
   /* Move iterator it from start the specified distance forward or
      backward.  The result is the new window start.  */
@@ -5355,10 +5363,11 @@
 	{
 	  /* If we have a header line, take account of it.
 	     This is necessary because we set it.current_y to 0, above.  */
-	  move_it_to (&it, -1, -1,
+	  move_it_to (&it, -1,
+		      window_scroll_pixel_based_preserve_x,
 		      window_scroll_pixel_based_preserve_y
 		      - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
-		      -1, MOVE_TO_Y);
+		      -1, MOVE_TO_Y | MOVE_TO_X);
 	  SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
 	}
       else
@@ -5416,8 +5425,9 @@
 	  /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
 	     here because we called start_display again and did not
 	     alter it.current_y this time.  */
-	  move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
-		      MOVE_TO_Y);
+	  move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
+		      window_scroll_pixel_based_preserve_y, -1,
+		      MOVE_TO_Y | MOVE_TO_X);
 	  SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
 	}
       else
@@ -5455,8 +5465,7 @@
   int lose;
   Lisp_Object bolp;
   int startpos;
-  struct position posit;
-  int original_vpos;
+  Lisp_Object original_pos = Qnil;
 
   /* If scrolling screen-fulls, compute the number of lines to
      scroll from the window's height.  */
@@ -5465,11 +5474,24 @@
 
   startpos = marker_position (w->start);
 
-  posit = *compute_motion (startpos, 0, 0, 0,
-			   PT, ht, 0,
-			   -1, XINT (w->hscroll),
-			   0, w);
-  original_vpos = posit.vpos;
+  if (!NILP (Vscroll_preserve_screen_position))
+    {
+      if (window_scroll_preserve_vpos <= 0
+	  || (!EQ (current_kboard->Vlast_command, Qscroll_up)
+	      && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+	{
+	  struct position posit
+	    = *compute_motion (startpos, 0, 0, 0,
+			       PT, ht, 0,
+			       -1, XINT (w->hscroll),
+			       0, w);
+	  window_scroll_preserve_vpos = posit.vpos;
+	  window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
+	}
+
+      original_pos = Fcons (make_number (window_scroll_preserve_hpos),
+			    make_number (window_scroll_preserve_vpos));
+    }
 
   XSETFASTINT (tem, PT);
   tem = Fpos_visible_in_window_p (tem, window, Qnil);
@@ -5520,7 +5542,7 @@
 	  && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
 	{
 	  SET_PT_BOTH (pos, pos_byte);
-	  Fvertical_motion (make_number (original_vpos), window);
+	  Fvertical_motion (original_pos, window);
 	}
       /* If we scrolled forward, put point enough lines down
 	 that it is outside the scroll margin.  */
@@ -5542,7 +5564,7 @@
 	  else if (!NILP (Vscroll_preserve_screen_position))
 	    {
 	      SET_PT_BOTH (pos, pos_byte);
-	      Fvertical_motion (make_number (original_vpos), window);
+	      Fvertical_motion (original_pos, window);
 	    }
 	  else
 	    SET_PT (top_margin);
@@ -5567,7 +5589,7 @@
 	      if (!NILP (Vscroll_preserve_screen_position))
 		{
 		  SET_PT_BOTH (pos, pos_byte);
-		  Fvertical_motion (make_number (original_vpos), window);
+		  Fvertical_motion (original_pos, window);
 		}
 	      else
 		Fvertical_motion (make_number (-1), window);
@@ -7439,7 +7461,10 @@
   minibuf_selected_window = Qnil;
   staticpro (&minibuf_selected_window);
 
+  window_scroll_pixel_based_preserve_x = -1;
   window_scroll_pixel_based_preserve_y = -1;
+  window_scroll_preserve_hpos = -1;
+  window_scroll_preserve_vpos = -1;
 
   DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
 	       doc: /* Non-nil means call as function to display a help buffer.
@@ -7640,7 +7665,7 @@
 
   DEFVAR_LISP ("scroll-preserve-screen-position",
 	       &Vscroll_preserve_screen_position,
-	       doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
+	       doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
 A value of nil means point does not keep its screen position except
 at the scroll margin or window boundary respectively.
 A value of t means point keeps its screen position if the scroll