diff options
| author | Eli Zaretskii | 2017-07-07 12:21:10 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2017-07-07 12:21:10 +0300 |
| commit | 4caf65d4de591089c82ccf542a31ea5009a3c717 (patch) | |
| tree | 540c37b0e457351a6840d1060692569b1e6ac2e3 /src | |
| parent | 25bc3911615d1160d47287c023545c6e0587739f (diff) | |
| download | emacs-4caf65d4de591089c82ccf542a31ea5009a3c717.tar.gz emacs-4caf65d4de591089c82ccf542a31ea5009a3c717.zip | |
Fix vertical-motion across the place where line-number width changes
* src/indent.c (line_number_display_width): New function,
refactored from line-number width calculations in vertical-motion.
(Fvertical_motion): Call line_number_display_width when the width
of line-number display is needed.
(Fline_number_display_width): New defun.
(syms_of_indent): Defsubr it.
* doc/lispref/display.texi (Size of Displayed Text): Document
line-number-display-width.
* etc/NEWS: Mention line-number-display-width.
* lisp/simple.el (last--line-number-width): New internal variable.
(line-move-visual): Use it to adjust temporary-goal-column when
line-number display changes its width.
Diffstat (limited to 'src')
| -rw-r--r-- | src/indent.c | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/src/indent.c b/src/indent.c index 70351f90466..ba936509934 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -1947,6 +1947,59 @@ vmotion (register ptrdiff_t from, register ptrdiff_t from_byte, | |||
| 1947 | -1, hscroll, 0, w); | 1947 | -1, hscroll, 0, w); |
| 1948 | } | 1948 | } |
| 1949 | 1949 | ||
| 1950 | /* Return the width taken by line-number display in window W. */ | ||
| 1951 | static void | ||
| 1952 | line_number_display_width (struct window *w, int *width, int *pixel_width) | ||
| 1953 | { | ||
| 1954 | if (NILP (Vdisplay_line_numbers)) | ||
| 1955 | { | ||
| 1956 | *width = 0; | ||
| 1957 | *pixel_width = 0; | ||
| 1958 | } | ||
| 1959 | else | ||
| 1960 | { | ||
| 1961 | struct it it; | ||
| 1962 | struct text_pos wstart; | ||
| 1963 | bool saved_restriction = false; | ||
| 1964 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 1965 | SET_TEXT_POS_FROM_MARKER (wstart, w->start); | ||
| 1966 | void *itdata = bidi_shelve_cache (); | ||
| 1967 | /* We must start from window's start point, but it could be | ||
| 1968 | outside the accessible region. */ | ||
| 1969 | if (wstart.charpos < BEGV || wstart.charpos > ZV) | ||
| 1970 | { | ||
| 1971 | record_unwind_protect (save_restriction_restore, | ||
| 1972 | save_restriction_save ()); | ||
| 1973 | Fwiden (); | ||
| 1974 | saved_restriction = true; | ||
| 1975 | } | ||
| 1976 | start_display (&it, w, wstart); | ||
| 1977 | move_it_by_lines (&it, 1); | ||
| 1978 | *width = it.lnum_width; | ||
| 1979 | *pixel_width = it.lnum_pixel_width; | ||
| 1980 | if (saved_restriction) | ||
| 1981 | unbind_to (count, Qnil); | ||
| 1982 | bidi_unshelve_cache (itdata, 0); | ||
| 1983 | } | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | DEFUN ("line-number-display-width", Fline_number_display_width, | ||
| 1987 | Sline_number_display_width, 0, 1, 0, | ||
| 1988 | doc: /* Return the width used for displaying line numbers in the selected window. | ||
| 1989 | If optional argument PIXELWISE is non-nil, return the width in pixels, | ||
| 1990 | otherwise return the width in columns of the face used to display | ||
| 1991 | line numbers, `line-number'. */) | ||
| 1992 | (Lisp_Object pixelwise) | ||
| 1993 | { | ||
| 1994 | int width, pixel_width; | ||
| 1995 | line_number_display_width (XWINDOW (selected_window), &width, &pixel_width); | ||
| 1996 | if (!NILP (pixelwise)) | ||
| 1997 | return make_number (pixel_width); | ||
| 1998 | /* FIXME: The "+ 2" part knows that we add a blank on each side of | ||
| 1999 | the line number when producing glyphs for display. */ | ||
| 2000 | return make_number (width + 2); | ||
| 2001 | } | ||
| 2002 | |||
| 1950 | /* In window W (derived from WINDOW), return x coordinate for column | 2003 | /* In window W (derived from WINDOW), return x coordinate for column |
| 1951 | COL (derived from COLUMN). */ | 2004 | COL (derived from COLUMN). */ |
| 1952 | static int | 2005 | static int |
| @@ -2073,30 +2126,10 @@ whether or not it is currently displayed in some window. */) | |||
| 2073 | that's what normal window redisplay does. Otherwise C-n/C-p | 2126 | that's what normal window redisplay does. Otherwise C-n/C-p |
| 2074 | will sometimes err by one column. */ | 2127 | will sometimes err by one column. */ |
| 2075 | int lnum_width = 0; | 2128 | int lnum_width = 0; |
| 2129 | int lnum_pixel_width = 0; | ||
| 2076 | if (!NILP (Vdisplay_line_numbers) | 2130 | if (!NILP (Vdisplay_line_numbers) |
| 2077 | && !EQ (Vdisplay_line_numbers, Qvisual)) | 2131 | && !EQ (Vdisplay_line_numbers, Qvisual)) |
| 2078 | { | 2132 | line_number_display_width (w, &lnum_width, &lnum_pixel_width); |
| 2079 | struct text_pos wstart; | ||
| 2080 | bool saved_restriction = false; | ||
| 2081 | ptrdiff_t count1 = SPECPDL_INDEX (); | ||
| 2082 | SET_TEXT_POS_FROM_MARKER (wstart, w->start); | ||
| 2083 | itdata = bidi_shelve_cache (); | ||
| 2084 | /* We must start from window's start point, but it could be | ||
| 2085 | outside the accessible region. */ | ||
| 2086 | if (wstart.charpos < BEGV || wstart.charpos > ZV) | ||
| 2087 | { | ||
| 2088 | record_unwind_protect (save_restriction_restore, | ||
| 2089 | save_restriction_save ()); | ||
| 2090 | Fwiden (); | ||
| 2091 | saved_restriction = true; | ||
| 2092 | } | ||
| 2093 | start_display (&it, w, wstart); | ||
| 2094 | move_it_by_lines (&it, 1); | ||
| 2095 | lnum_width = it.lnum_width; | ||
| 2096 | if (saved_restriction) | ||
| 2097 | unbind_to (count1, Qnil); | ||
| 2098 | bidi_unshelve_cache (itdata, 0); | ||
| 2099 | } | ||
| 2100 | SET_TEXT_POS (pt, PT, PT_BYTE); | 2133 | SET_TEXT_POS (pt, PT, PT_BYTE); |
| 2101 | itdata = bidi_shelve_cache (); | 2134 | itdata = bidi_shelve_cache (); |
| 2102 | start_display (&it, w, pt); | 2135 | start_display (&it, w, pt); |
| @@ -2277,6 +2310,12 @@ whether or not it is currently displayed in some window. */) | |||
| 2277 | an addition to the hscroll amount. */ | 2310 | an addition to the hscroll amount. */ |
| 2278 | if (lcols_given) | 2311 | if (lcols_given) |
| 2279 | { | 2312 | { |
| 2313 | /* If we are displaying line numbers, we could cross the | ||
| 2314 | line where the width of the line-number display changes, | ||
| 2315 | in which case we need to fix up the pixel coordinate | ||
| 2316 | accordingly. */ | ||
| 2317 | if (lnum_pixel_width > 0) | ||
| 2318 | to_x += it.lnum_pixel_width - lnum_pixel_width; | ||
| 2280 | move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X); | 2319 | move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X); |
| 2281 | /* If we find ourselves in the middle of an overlay string | 2320 | /* If we find ourselves in the middle of an overlay string |
| 2282 | which includes a newline after current string position, | 2321 | which includes a newline after current string position, |
| @@ -2322,6 +2361,7 @@ syms_of_indent (void) | |||
| 2322 | defsubr (&Sindent_to); | 2361 | defsubr (&Sindent_to); |
| 2323 | defsubr (&Scurrent_column); | 2362 | defsubr (&Scurrent_column); |
| 2324 | defsubr (&Smove_to_column); | 2363 | defsubr (&Smove_to_column); |
| 2364 | defsubr (&Sline_number_display_width); | ||
| 2325 | defsubr (&Svertical_motion); | 2365 | defsubr (&Svertical_motion); |
| 2326 | defsubr (&Scompute_motion); | 2366 | defsubr (&Scompute_motion); |
| 2327 | } | 2367 | } |