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. */
/* 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
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. */
/* 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);
}
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);
&& !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
#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 ();
&& !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)
{
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. */
&& !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
/* 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;
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
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
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);
}