changeset 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 c7d9c3b0bfc4
children 4170d7f0d918
files etc/NEWS src/ChangeLog src/dispextern.h src/indent.c src/window.c src/xdisp.c
diffstat 6 files changed, 95 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Thu Jun 05 03:23:31 2008 +0000
+++ b/etc/NEWS	Thu Jun 05 03:57:09 2008 +0000
@@ -63,6 +63,7 @@
 
 * Changes in Emacs 23.1
 
+** scroll-preserve-screen-position also preserves the column position.
 ** Completion.
 *** `completion-styles' can be customized to choose your favorite completion.
 *** The default completion styles include a form of partial-completion.
--- a/src/ChangeLog	Thu Jun 05 03:23:31 2008 +0000
+++ b/src/ChangeLog	Thu Jun 05 03:57:09 2008 +0000
@@ -1,3 +1,19 @@
+2008-06-05  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* xdisp.c (move_it_in_display_line_to): Improve the type of its args.
+	(move_it_in_display_line): New wrapper.
+
+	* 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.
+
+	* dispextern.h (move_it_in_display_line): Declare.
+
 2008-06-05  Juanma Barranquero  <lekktu@gmail.com>
 
 	* window.c (Fwindow_parameter): Return VALUE, not (PARAMETER . VALUE).
@@ -113,11 +129,11 @@
 	(struct named_merge_point): Add `named_merge_point_kind' field.
 	(push_named_merge_point): Make cycle detection respect different
 	named-merge-point kinds.
-	(lface_from_face_name_no_resolve): Renamed from `lface_from_face_name'.
+	(lface_from_face_name_no_resolve): Rename from `lface_from_face_name'.
 	Remove face-name alias resolution.
 	(lface_from_face_name): New definition using
 	`lface_from_face_name_no_resolve'.
-	(get_lface_attributes_no_remap): Renamed from `get_lface_attributes'.
+	(get_lface_attributes_no_remap): Rename from `get_lface_attributes'.
 	Call lface_from_face_name_no_resolve instead of lface_from_face_name.
 	(get_lface_attributes): New definition that layers face-remapping on
 	top of get_lface_attributes_no_remap.  New arg `named_merge_points'.
--- a/src/dispextern.h	Thu Jun 05 03:23:31 2008 +0000
+++ b/src/dispextern.h	Thu Jun 05 03:57:09 2008 +0000
@@ -2685,6 +2685,9 @@
 void move_it_vertically_backward P_ ((struct it *, int));
 void move_it_by_lines P_ ((struct it *, int, int));
 void move_it_past_eol P_ ((struct it *));
+void move_it_in_display_line (struct it *it,
+			      EMACS_INT to_charpos, int to_x,
+			      enum move_operation_enum op);
 int in_display_vector_p P_ ((struct it *));
 int frame_mode_line_height P_ ((struct frame *));
 void highlight_trailing_whitespace P_ ((struct frame *, struct glyph_row *));
--- a/src/indent.c	Thu Jun 05 03:23:31 2008 +0000
+++ b/src/indent.c	Thu Jun 05 03:57:09 2008 +0000
@@ -1993,6 +1993,10 @@
 parameters such as width, horizontal scrolling, and so on.
 The default is to use the selected window's parameters.
 
+LINES can optionally take the form (COLS . LINES), in which case
+the motion will not stop at the start of a screen line but on
+its column COLS (if such exists on that line, that is).
+
 `vertical-motion' always uses the current buffer,
 regardless of which buffer is displayed in WINDOW.
 This is consistent with other cursor motion functions
@@ -2006,6 +2010,14 @@
   struct window *w;
   Lisp_Object old_buffer;
   struct gcpro gcpro1;
+  int cols = 0;
+
+  /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES).  */
+  if (CONSP (lines) && (NUMBERP (XCAR (lines))))
+    {
+      cols = XINT (XCAR (lines));
+      lines = XCDR (lines);
+    }
 
   CHECK_NUMBER (lines);
   if (! NILP (window))
@@ -2094,6 +2106,11 @@
       if (XINT (lines) >= 0 || IT_CHARPOS (it) > 0)
 	move_it_by_lines (&it, XINT (lines), 0);
 
+      if (cols)
+	move_it_in_display_line (&it, ZV,
+				 cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)),
+				 MOVE_TO_X);
+
       SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
     }
 
--- 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
--- a/src/xdisp.c	Thu Jun 05 03:23:31 2008 +0000
+++ b/src/xdisp.c	Thu Jun 05 03:57:09 2008 +0000
@@ -939,8 +939,9 @@
 				      struct display_pos *));
 static void reseat_to_string P_ ((struct it *, unsigned char *,
 				  Lisp_Object, int, int, int, int));
-static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
-							   int, int, int));
+static enum move_it_result
+       move_it_in_display_line_to (struct it *, EMACS_INT, int,
+				   enum move_operation_enum);
 void move_it_vertically_backward P_ ((struct it *, int));
 static void init_to_row_start P_ ((struct it *, struct window *,
 				   struct glyph_row *));
@@ -6630,9 +6631,9 @@
      display is on.  */
 
 static enum move_it_result
-move_it_in_display_line_to (it, to_charpos, to_x, op)
-     struct it *it;
-     int to_charpos, to_x, op;
+move_it_in_display_line_to (struct it *it,
+			    EMACS_INT to_charpos, int to_x,
+			    enum move_operation_enum op)
 {
   enum move_it_result result = MOVE_UNDEFINED;
   struct glyph_row *saved_glyph_row;
@@ -6892,6 +6893,15 @@
   return result;
 }
 
+/* For external use.  */
+void
+move_it_in_display_line (struct it *it,
+			 EMACS_INT to_charpos, int to_x,
+			 enum move_operation_enum op)
+{
+  move_it_in_display_line_to (it, to_charpos, to_x, op);
+}
+
 
 /* Move IT forward until it satisfies one or more of the criteria in
    TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.