diff options
| author | Andreas Schwab | 2016-12-19 23:07:42 +0100 |
|---|---|---|
| committer | Andreas Schwab | 2016-12-19 23:17:36 +0100 |
| commit | 85aebc12de28667cdccde5b080972453544d015e (patch) | |
| tree | cf7810bfb5228fe6f5ef39dc5bc6faf1ac45d060 /src/indent.c | |
| parent | 504e3846041e4fcd1707a9ad6176ddaf3fec3d02 (diff) | |
| download | emacs-85aebc12de28667cdccde5b080972453544d015e.tar.gz emacs-85aebc12de28667cdccde5b080972453544d015e.zip | |
Protect change of window's buffer in vertical-motion against unwinds (bug#25209)
* indent.c (restore_window_buffer): New function.
(Fvertical_motion): Use it to restore window's buffer.
Diffstat (limited to 'src/indent.c')
| -rw-r--r-- | src/indent.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/src/indent.c b/src/indent.c index b68b60297fd..29c9ffd90cc 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -1958,6 +1958,20 @@ window_column_x (struct window *w, Lisp_Object window, | |||
| 1958 | return x; | 1958 | return x; |
| 1959 | } | 1959 | } |
| 1960 | 1960 | ||
| 1961 | /* Restore window's buffer and point. */ | ||
| 1962 | |||
| 1963 | static void | ||
| 1964 | restore_window_buffer (Lisp_Object list) | ||
| 1965 | { | ||
| 1966 | struct window *w = decode_live_window (XCAR (list)); | ||
| 1967 | list = XCDR (list); | ||
| 1968 | wset_buffer (w, XCAR (list)); | ||
| 1969 | list = XCDR (list); | ||
| 1970 | set_marker_both (w->pointm, w->contents, | ||
| 1971 | XFASTINT (XCAR (list)), | ||
| 1972 | XFASTINT (XCAR (XCDR (list)))); | ||
| 1973 | } | ||
| 1974 | |||
| 1961 | DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 3, 0, | 1975 | DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 3, 0, |
| 1962 | doc: /* Move point to start of the screen line LINES lines down. | 1976 | doc: /* Move point to start of the screen line LINES lines down. |
| 1963 | If LINES is negative, this means moving up. | 1977 | If LINES is negative, this means moving up. |
| @@ -1997,10 +2011,9 @@ whether or not it is currently displayed in some window. */) | |||
| 1997 | struct it it; | 2011 | struct it it; |
| 1998 | struct text_pos pt; | 2012 | struct text_pos pt; |
| 1999 | struct window *w; | 2013 | struct window *w; |
| 2000 | Lisp_Object old_buffer; | ||
| 2001 | EMACS_INT old_charpos UNINIT, old_bytepos UNINIT; | ||
| 2002 | Lisp_Object lcols; | 2014 | Lisp_Object lcols; |
| 2003 | void *itdata = NULL; | 2015 | void *itdata = NULL; |
| 2016 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 2004 | 2017 | ||
| 2005 | /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ | 2018 | /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ |
| 2006 | bool lcols_given = CONSP (lines); | 2019 | bool lcols_given = CONSP (lines); |
| @@ -2013,13 +2026,13 @@ whether or not it is currently displayed in some window. */) | |||
| 2013 | CHECK_NUMBER (lines); | 2026 | CHECK_NUMBER (lines); |
| 2014 | w = decode_live_window (window); | 2027 | w = decode_live_window (window); |
| 2015 | 2028 | ||
| 2016 | old_buffer = Qnil; | ||
| 2017 | if (XBUFFER (w->contents) != current_buffer) | 2029 | if (XBUFFER (w->contents) != current_buffer) |
| 2018 | { | 2030 | { |
| 2019 | /* Set the window's buffer temporarily to the current buffer. */ | 2031 | /* Set the window's buffer temporarily to the current buffer. */ |
| 2020 | old_buffer = w->contents; | 2032 | Lisp_Object old = list4 (window, w->contents, |
| 2021 | old_charpos = marker_position (w->pointm); | 2033 | make_number (marker_position (w->pointm)), |
| 2022 | old_bytepos = marker_byte_position (w->pointm); | 2034 | make_number (marker_byte_position (w->pointm))); |
| 2035 | record_unwind_protect (restore_window_buffer, old); | ||
| 2023 | wset_buffer (w, Fcurrent_buffer ()); | 2036 | wset_buffer (w, Fcurrent_buffer ()); |
| 2024 | set_marker_both (w->pointm, w->contents, | 2037 | set_marker_both (w->pointm, w->contents, |
| 2025 | BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer)); | 2038 | BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer)); |
| @@ -2255,12 +2268,7 @@ whether or not it is currently displayed in some window. */) | |||
| 2255 | bidi_unshelve_cache (itdata, 0); | 2268 | bidi_unshelve_cache (itdata, 0); |
| 2256 | } | 2269 | } |
| 2257 | 2270 | ||
| 2258 | if (BUFFERP (old_buffer)) | 2271 | unbind_to (count, Qnil); |
| 2259 | { | ||
| 2260 | wset_buffer (w, old_buffer); | ||
| 2261 | set_marker_both (w->pointm, w->contents, | ||
| 2262 | old_charpos, old_bytepos); | ||
| 2263 | } | ||
| 2264 | 2272 | ||
| 2265 | return make_number (it.vpos); | 2273 | return make_number (it.vpos); |
| 2266 | } | 2274 | } |