# HG changeset patch # User Stefan Monnier # Date 1212638229 0 # Node ID b3c0438c570b999e5e66aa26db139ce8d360bceb # Parent c7d9c3b0bfc4bef6b01af512f845f2f46518e376 * 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. diff -r c7d9c3b0bfc4 -r b3c0438c570b etc/NEWS --- 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. diff -r c7d9c3b0bfc4 -r b3c0438c570b src/ChangeLog --- 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 + + * 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 * 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'. diff -r c7d9c3b0bfc4 -r b3c0438c570b src/dispextern.h --- 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 *)); diff -r c7d9c3b0bfc4 -r b3c0438c570b src/indent.c --- 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)); } diff -r c7d9c3b0bfc4 -r b3c0438c570b src/window.c --- 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 diff -r c7d9c3b0bfc4 -r b3c0438c570b src/xdisp.c --- 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.