]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix infloop in redisplay_window due to fix of bug#14582
authorEli Zaretskii <eliz@gnu.org>
Fri, 4 Feb 2022 13:50:50 +0000 (15:50 +0200)
committerEli Zaretskii <eliz@gnu.org>
Fri, 4 Feb 2022 13:50:50 +0000 (15:50 +0200)
* 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.

src/xdisp.c

index 20b0d97b97593b339723b6ab361308d4132e8d9a..db9bc512a987caece23f85e6e36ebcbd02987192 100644 (file)
@@ -18739,6 +18739,34 @@ set_horizontal_scroll_bar (struct window *w)
       (w, portion, whole, start);
 }
 
+/* Subroutine of redisplay_window, to determine whether a window-start
+   point STARTP of WINDOW should be rejected.  */
+static bool
+window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
+{
+  if (!make_window_start_visible)
+    return true;
+
+  struct window *w = XWINDOW (window);
+  struct frame *f = XFRAME (w->frame);
+  Lisp_Object startpos = make_fixnum (startp);
+  Lisp_Object invprop, disp_spec;
+  struct text_pos ignored;
+
+  /* Is STARTP in invisible text?  */
+  if (startp > BEGV
+      && ((invprop = Fget_char_property (startpos, Qinvisible, window)),
+         TEXT_PROP_MEANS_INVISIBLE (invprop) != 0))
+    return false;
+
+  /* Is STARTP covered by a replacing 'display' property?  */
+  if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
+      && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
+                             FRAME_WINDOW_P (f)) > 0)
+    return false;
+
+  return true;
+}
 
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P means only
    selected_window is redisplayed.
@@ -19036,9 +19064,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
  force_start:
 
   /* Handle case where place to start displaying has been specified,
-     unless the specified location is outside the accessible range, or
-     the buffer wants the window-start point to be always visible.  */
-  if (w->force_start && !make_window_start_visible)
+     unless the specified location is outside the accessible range.  */
+  if (w->force_start)
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
@@ -19071,6 +19098,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       else if (CHARPOS (startp) > ZV)
        SET_TEXT_POS (startp, ZV, ZV_BYTE);
 
+      /* Reject the specified start location if it is invisible, and
+        the buffer wants it always visible.  */
+      if (!window_start_acceptable_p (window, CHARPOS (startp)))
+       goto ignore_start;
+
       /* Redisplay, then check if cursor has been set during the
         redisplay.  Give up if new fonts were loaded.  */
       /* 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)
       goto done;
     }
 
-  Lisp_Object iprop, dspec;
-  struct text_pos ignored;
+ ignore_start:
+
   /* Handle case where text has not changed, only point, and it has
      not moved off the frame, and we are not retrying after hscroll.
      (current_matrix_up_to_date_p is true when retrying.)  */
@@ -19253,26 +19285,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* If current starting point was originally the beginning of a line
      but no longer is, or if the starting point is invisible but the
      buffer wants it always visible, find a new starting point.  */
-  else if (w->start_at_line_beg
-          && (!(CHARPOS (startp) <= BEGV
-                || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
-              || (make_window_start_visible
-                  /* Is window-start in invisible text?  */
-                  && ((CHARPOS (startp) > BEGV
-                       && ((iprop =
-                            Fget_char_property
-                            (make_fixnum (CHARPOS (startp) - 1), Qinvisible,
-                             window)),
-                           TEXT_PROP_MEANS_INVISIBLE (iprop) != 0))
-                      /* Is window-start covered by a replacing
-                         'display' property?  */
-                      || (!NILP (dspec =
-                                 Fget_char_property
-                                 (make_fixnum (CHARPOS (startp)), Qdisplay,
-                                  window))
-                          && handle_display_spec (NULL, dspec, Qnil, Qnil,
-                                                  &ignored, CHARPOS (startp),
-                                                  FRAME_WINDOW_P (f)) > 0)))))
+  else if ((w->start_at_line_beg
+           && !(CHARPOS (startp) <= BEGV
+                || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
+          || !window_start_acceptable_p (window, CHARPOS (startp)))
     {
 #ifdef GLYPH_DEBUG
       debug_method_add (w, "recenter 1");
@@ -19348,14 +19364,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
          goto force_start;
        }
 
-      /* Don't use the same window-start if it is covered by a
-        replacing 'display' property and the buffer requested the
-        window-start to be always visible.  */
-      if (make_window_start_visible
-         && !NILP (dspec = Fget_char_property (make_fixnum (CHARPOS (startp)),
-                                               Qdisplay, window))
-         && handle_display_spec (NULL, dspec, Qnil, Qnil, &ignored,
-                                 CHARPOS (startp), FRAME_WINDOW_P (f)) > 0)
+      /* Don't use the same window-start if it is invisible or covered
+        by a replacing 'display' property and the buffer requested
+        the window-start to be always visible.  */
+      if (!window_start_acceptable_p (window, CHARPOS (startp)))
        {
 #ifdef GLYPH_DEBUG
          debug_method_add (w, "recenter 2");