diff options
| author | Eli Zaretskii | 2022-02-04 15:50:50 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2022-02-04 15:50:50 +0200 |
| commit | 9a8796f067d1f9d5d0c2c1285dc86b2f577f4f27 (patch) | |
| tree | 0c1eb9d82581c1b12149101e70d359194c38b618 /src | |
| parent | 38ffb828f26d630cf7e10b7e8554aea98e299f1b (diff) | |
| download | emacs-9a8796f067d1f9d5d0c2c1285dc86b2f577f4f27.tar.gz emacs-9a8796f067d1f9d5d0c2c1285dc86b2f577f4f27.zip | |
Fix infloop in redisplay_window due to fix of bug#14582
* src/xdisp.c (window_start_acceptable_p): New function.
(redisplay_window): Call 'window_start_acceptable_p' to determine
whether a given window-start point is acceptable, including when
the window's force_start flag is set -- this fixes infloop in
redisplay_window in that case.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 78 |
1 files changed, 45 insertions, 33 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 20b0d97b975..db9bc512a98 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -18739,6 +18739,34 @@ set_horizontal_scroll_bar (struct window *w) | |||
| 18739 | (w, portion, whole, start); | 18739 | (w, portion, whole, start); |
| 18740 | } | 18740 | } |
| 18741 | 18741 | ||
| 18742 | /* Subroutine of redisplay_window, to determine whether a window-start | ||
| 18743 | point STARTP of WINDOW should be rejected. */ | ||
| 18744 | static bool | ||
| 18745 | window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp) | ||
| 18746 | { | ||
| 18747 | if (!make_window_start_visible) | ||
| 18748 | return true; | ||
| 18749 | |||
| 18750 | struct window *w = XWINDOW (window); | ||
| 18751 | struct frame *f = XFRAME (w->frame); | ||
| 18752 | Lisp_Object startpos = make_fixnum (startp); | ||
| 18753 | Lisp_Object invprop, disp_spec; | ||
| 18754 | struct text_pos ignored; | ||
| 18755 | |||
| 18756 | /* Is STARTP in invisible text? */ | ||
| 18757 | if (startp > BEGV | ||
| 18758 | && ((invprop = Fget_char_property (startpos, Qinvisible, window)), | ||
| 18759 | TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)) | ||
| 18760 | return false; | ||
| 18761 | |||
| 18762 | /* Is STARTP covered by a replacing 'display' property? */ | ||
| 18763 | if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window)) | ||
| 18764 | && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp, | ||
| 18765 | FRAME_WINDOW_P (f)) > 0) | ||
| 18766 | return false; | ||
| 18767 | |||
| 18768 | return true; | ||
| 18769 | } | ||
| 18742 | 18770 | ||
| 18743 | /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P means only | 18771 | /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P means only |
| 18744 | selected_window is redisplayed. | 18772 | selected_window is redisplayed. |
| @@ -19036,9 +19064,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 19036 | force_start: | 19064 | force_start: |
| 19037 | 19065 | ||
| 19038 | /* Handle case where place to start displaying has been specified, | 19066 | /* Handle case where place to start displaying has been specified, |
| 19039 | unless the specified location is outside the accessible range, or | 19067 | unless the specified location is outside the accessible range. */ |
| 19040 | the buffer wants the window-start point to be always visible. */ | 19068 | if (w->force_start) |
| 19041 | if (w->force_start && !make_window_start_visible) | ||
| 19042 | { | 19069 | { |
| 19043 | /* We set this later on if we have to adjust point. */ | 19070 | /* We set this later on if we have to adjust point. */ |
| 19044 | int new_vpos = -1; | 19071 | int new_vpos = -1; |
| @@ -19071,6 +19098,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 19071 | else if (CHARPOS (startp) > ZV) | 19098 | else if (CHARPOS (startp) > ZV) |
| 19072 | SET_TEXT_POS (startp, ZV, ZV_BYTE); | 19099 | SET_TEXT_POS (startp, ZV, ZV_BYTE); |
| 19073 | 19100 | ||
| 19101 | /* Reject the specified start location if it is invisible, and | ||
| 19102 | the buffer wants it always visible. */ | ||
| 19103 | if (!window_start_acceptable_p (window, CHARPOS (startp))) | ||
| 19104 | goto ignore_start; | ||
| 19105 | |||
| 19074 | /* Redisplay, then check if cursor has been set during the | 19106 | /* Redisplay, then check if cursor has been set during the |
| 19075 | redisplay. Give up if new fonts were loaded. */ | 19107 | redisplay. Give up if new fonts were loaded. */ |
| 19076 | /* We used to issue a CHECK_MARGINS argument to try_window here, | 19108 | /* We used to issue a CHECK_MARGINS argument to try_window here, |
| @@ -19228,8 +19260,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 19228 | goto done; | 19260 | goto done; |
| 19229 | } | 19261 | } |
| 19230 | 19262 | ||
| 19231 | Lisp_Object iprop, dspec; | 19263 | ignore_start: |
| 19232 | struct text_pos ignored; | 19264 | |
| 19233 | /* Handle case where text has not changed, only point, and it has | 19265 | /* Handle case where text has not changed, only point, and it has |
| 19234 | not moved off the frame, and we are not retrying after hscroll. | 19266 | not moved off the frame, and we are not retrying after hscroll. |
| 19235 | (current_matrix_up_to_date_p is true when retrying.) */ | 19267 | (current_matrix_up_to_date_p is true when retrying.) */ |
| @@ -19253,26 +19285,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 19253 | /* If current starting point was originally the beginning of a line | 19285 | /* If current starting point was originally the beginning of a line |
| 19254 | but no longer is, or if the starting point is invisible but the | 19286 | but no longer is, or if the starting point is invisible but the |
| 19255 | buffer wants it always visible, find a new starting point. */ | 19287 | buffer wants it always visible, find a new starting point. */ |
| 19256 | else if (w->start_at_line_beg | 19288 | else if ((w->start_at_line_beg |
| 19257 | && (!(CHARPOS (startp) <= BEGV | 19289 | && !(CHARPOS (startp) <= BEGV |
| 19258 | || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n') | 19290 | || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')) |
| 19259 | || (make_window_start_visible | 19291 | || !window_start_acceptable_p (window, CHARPOS (startp))) |
| 19260 | /* Is window-start in invisible text? */ | ||
| 19261 | && ((CHARPOS (startp) > BEGV | ||
| 19262 | && ((iprop = | ||
| 19263 | Fget_char_property | ||
| 19264 | (make_fixnum (CHARPOS (startp) - 1), Qinvisible, | ||
| 19265 | window)), | ||
| 19266 | TEXT_PROP_MEANS_INVISIBLE (iprop) != 0)) | ||
| 19267 | /* Is window-start covered by a replacing | ||
| 19268 | 'display' property? */ | ||
| 19269 | || (!NILP (dspec = | ||
| 19270 | Fget_char_property | ||
| 19271 | (make_fixnum (CHARPOS (startp)), Qdisplay, | ||
| 19272 | window)) | ||
| 19273 | && handle_display_spec (NULL, dspec, Qnil, Qnil, | ||
| 19274 | &ignored, CHARPOS (startp), | ||
| 19275 | FRAME_WINDOW_P (f)) > 0))))) | ||
| 19276 | { | 19292 | { |
| 19277 | #ifdef GLYPH_DEBUG | 19293 | #ifdef GLYPH_DEBUG |
| 19278 | debug_method_add (w, "recenter 1"); | 19294 | debug_method_add (w, "recenter 1"); |
| @@ -19348,14 +19364,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 19348 | goto force_start; | 19364 | goto force_start; |
| 19349 | } | 19365 | } |
| 19350 | 19366 | ||
| 19351 | /* Don't use the same window-start if it is covered by a | 19367 | /* Don't use the same window-start if it is invisible or covered |
| 19352 | replacing 'display' property and the buffer requested the | 19368 | by a replacing 'display' property and the buffer requested |
| 19353 | window-start to be always visible. */ | 19369 | the window-start to be always visible. */ |
| 19354 | if (make_window_start_visible | 19370 | if (!window_start_acceptable_p (window, CHARPOS (startp))) |
| 19355 | && !NILP (dspec = Fget_char_property (make_fixnum (CHARPOS (startp)), | ||
| 19356 | Qdisplay, window)) | ||
| 19357 | && handle_display_spec (NULL, dspec, Qnil, Qnil, &ignored, | ||
| 19358 | CHARPOS (startp), FRAME_WINDOW_P (f)) > 0) | ||
| 19359 | { | 19371 | { |
| 19360 | #ifdef GLYPH_DEBUG | 19372 | #ifdef GLYPH_DEBUG |
| 19361 | debug_method_add (w, "recenter 2"); | 19373 | debug_method_add (w, "recenter 2"); |