]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
* src/xdisp.c (windows_or_buffers_changed): Improve docstring
[gnu-emacs] / src / xdisp.c
index 2c38aa9ccff578d40bff57a0584042fd9744b027..051d3078529022d8391f8693e69b919cc91bf33b 100644 (file)
@@ -434,22 +434,54 @@ static Lisp_Object Vmessage_stack;
 
 static bool message_enable_multibyte;
 
-/* Nonzero if we should redraw the mode lines on the next redisplay.
-   If it has value REDISPLAY_SOME, then only redisplay the mode lines where
-   the `redisplay' bit has been set.  Otherwise, redisplay all mode lines
-   (the number used is then only used to track down the cause for this
-   full-redisplay).  */
+/* At each redisplay cycle, we should refresh everything there is to refresh.
+   To do that efficiently, we use many optimizations that try to make sure we
+   don't waste too much time updating things that haven't changed.
+   The coarsest such optimization is that, in the most common cases, we only
+   look at the selected-window.
+
+   To know whether other windows should be considered for redisplay, we use the
+   variable windows_or_buffers_changed: as long as it is 0, it means that we
+   have not noticed anything that should require updating anything else than
+   the selected-window.  If it is set to REDISPLAY_SOME, it means that since
+   last redisplay, some changes have been made which could impact other
+   windows.  To know which ones need redisplay, every buffer, window, and frame
+   has a `redisplay' bit, which (if true) means that this object needs to be
+   redisplayed.  If windows_or_buffers_changed is 0, we know there's no point
+   looking for those `redisplay' bits (actually, there might be some such bits
+   set, but then only on objects which aren't displayed anyway).
+
+   OTOH if it's non-zero we wil have to loop through all windows and then check
+   the `redisplay' bit of the corresponding window, frame, and buffer, in order
+   to decide whether that window needs attention or not.  Not that we can't
+   just look at the frame's redisplay bit to decide that the whole frame can be
+   skipped, since even if the frame's redisplay bit is unset, some of its
+   windows's redisplay bits may be set.
+
+   Mostly for historical reasons, windows_or_buffers_changed can also take
+   other non-zero values.  In that case, the precise value doesn't matter (it
+   encodes the cause of the setting but is only used for debugging purposes),
+   and what it means is that we shouldn't pay attention to any `redisplay' bits
+   and we should simply try and redisplay every window out there.  */
 
-int update_mode_lines;
+int windows_or_buffers_changed;
 
-/* Nonzero if window sizes or contents other than selected-window have changed
-   since last redisplay that finished.
-   If it has value REDISPLAY_SOME, then only redisplay the windows where
-   the `redisplay' bit has been set.  Otherwise, redisplay all windows
-   (the number used is then only used to track down the cause for this
-   full-redisplay).  */
+/* Nonzero if we should redraw the mode lines on the next redisplay.
+   Similarly to `windows_or_buffers_changed', If it has value REDISPLAY_SOME,
+   then only redisplay the mode lines in those buffers/windows/frames where the
+   `redisplay' bit has been set.
+   For any other value, redisplay all mode lines (the number used is then only
+   used to track down the cause for this full-redisplay).
+
+   The `redisplay' bits are the same as those used for
+   windows_or_buffers_changed, and setting windows_or_buffers_changed also
+   causes recomputation of the mode lines of all those windows.  IOW this
+   variable only has an effect if windows_or_buffers_changed is zero, in which
+   case we should only need to redisplay the mode-line of those objects with
+   a `redisplay' bit set but not the window's text content (tho we may still
+   need to refresh the text content of the selected-window).  */
 
-int windows_or_buffers_changed;
+int update_mode_lines;
 
 /* True after display_mode_line if %l was used and it displayed a
    line number.  */
@@ -13336,6 +13368,9 @@ redisplay_internal (void)
   /* True means redisplay has to redisplay the miniwindow.  */
   bool update_miniwindow_p = false;
 
+  /* True means we need to redraw frames whose 'redisplay' bit is set.  */
+  bool consider_some_frames_p = false;
+
   TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
 
   /* No redisplay if running in batch mode or frame is not yet fully
@@ -13383,6 +13418,10 @@ redisplay_internal (void)
   pending = false;
   forget_escape_and_glyphless_faces ();
 
+  inhibit_free_realized_faces = false;
+
+  consider_some_frames_p = false;
+
   /* If face_change, init_iterator will free all realized faces, which
      includes the faces referenced from current matrices.  So, we
      can't reuse current matrices in this case.  */
@@ -13430,7 +13469,7 @@ redisplay_internal (void)
          /* If cursor type has been changed on the frame
             other than selected, consider all frames.  */
          if (f != sf && f->cursor_type_changed)
-           update_mode_lines = 31;
+           fset_redisplay (f);
        }
       clear_desired_matrices (f);
     }
@@ -13528,9 +13567,12 @@ redisplay_internal (void)
   consider_all_windows_p = (update_mode_lines
                            || windows_or_buffers_changed);
 
-#define AINC(a,i) \
-  if (VECTORP (a) && i >= 0 && i < ASIZE (a) && INTEGERP (AREF (a, i))) \
-    ASET (a, i, make_number (1 + XINT (AREF (a, i))))
+#define AINC(a,i)                                                      \
+  {                                                                    \
+    Lisp_Object entry = Fgethash (make_number (i), a, make_number (0));        \
+    if (INTEGERP (entry))                                              \
+      Fputhash (make_number (i), make_number (1 + XINT (entry)), a);   \
+  }
 
   AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
   AINC (Vredisplay__mode_lines_cause, update_mode_lines);
@@ -13550,6 +13592,7 @@ redisplay_internal (void)
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       && !XFRAME (w->frame)->cursor_type_changed
       && !XFRAME (w->frame)->face_change
+      && !XFRAME (w->frame)->redisplay
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
       && match_p
@@ -13745,13 +13788,31 @@ redisplay_internal (void)
 #endif
 
   /* Build desired matrices, and update the display.  If
-     consider_all_windows_p, do it for all windows on all frames.
-     Otherwise do it for selected_window, only.  */
+     consider_all_windows_p, do it for all windows on all frames.  If
+     a frame's 'redisplay' flag is set, do it for all windows on each
+     such frame.  Otherwise do it for selected_window, only.  */
+
+  if (!consider_all_windows_p)
+    {
+      FOR_EACH_FRAME (tail, frame)
+       {
+         if (XFRAME (frame)->redisplay
+             && XFRAME (frame) != sf
+             && !FRAME_INITIAL_P (XFRAME (frame)))
+           {
+             consider_some_frames_p = true;
+             break;
+           }
+       }
+    }
 
-  if (consider_all_windows_p)
+  if (consider_all_windows_p || consider_some_frames_p)
     {
       FOR_EACH_FRAME (tail, frame)
-       XFRAME (frame)->updated_p = false;
+       {
+         if (XFRAME (frame)->redisplay || consider_all_windows_p)
+           XFRAME (frame)->updated_p = false;
+       }
 
       propagate_buffer_redisplay ();
 
@@ -13765,6 +13826,9 @@ redisplay_internal (void)
              && !EQ (FRAME_TTY (f)->top_frame, frame))
            continue;
 
+         if (!consider_all_windows_p && !f->redisplay)
+           continue;
+
        retry_frame:
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
@@ -13871,6 +13935,10 @@ redisplay_internal (void)
       if (sf->fonts_changed)
        goto retry;
 
+      /* Prevent freeing of realized faces, since desired matrices are
+        pending that reference the faces we computed and cached.  */
+      inhibit_free_realized_faces = true;
+
       /* Prevent various kinds of signals during display update.
         stdio is not robust about handling signals,
         which can cause an apparent I/O error.  */
@@ -15406,6 +15474,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
       && !update_mode_lines
       && !windows_or_buffers_changed
       && !f->cursor_type_changed
+      && !f->redisplay
       && NILP (Vshow_trailing_whitespace)
       /* This code is not used for mini-buffer for the sake of the case
         of redisplaying to replace an echo area message; since in
@@ -17016,6 +17085,7 @@ try_window_reusing_current_matrix (struct window *w)
       /* Don't try to reuse the display if windows have been split
         or such.  */
       || windows_or_buffers_changed
+      || f->redisplay
       || f->cursor_type_changed)
     return false;
 
@@ -17793,7 +17863,7 @@ try_window_id (struct window *w)
     GIVE_UP (1);
 
   /* This flag is used to prevent redisplay optimizations.  */
-  if (windows_or_buffers_changed || f->cursor_type_changed)
+  if (windows_or_buffers_changed || f->cursor_type_changed || f->redisplay)
     GIVE_UP (2);
 
   /* This function's optimizations cannot be used if overlays have
@@ -19802,7 +19872,8 @@ push_prefix_prop (struct it *it, Lisp_Object prop)
 
   eassert (it->method == GET_FROM_BUFFER
           || it->method == GET_FROM_DISPLAY_VECTOR
-          || it->method == GET_FROM_STRING);
+          || it->method == GET_FROM_STRING
+          || it->method == GET_FROM_IMAGE);
 
   /* We need to save the current buffer/string position, so it will be
      restored by pop_it, because iterate_out_of_display_property
@@ -31381,13 +31452,11 @@ display table takes effect; in this case, Emacs does not consult
 
   DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
               doc: /*  */);
-  Vredisplay__all_windows_cause
-    = Fmake_vector (make_number (100), make_number (0));
+  Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
 
   DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
               doc: /*  */);
-  Vredisplay__mode_lines_cause
-    = Fmake_vector (make_number (100), make_number (0));
+  Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
 }