int redisplay_dont_pause;
+/* Define PERIODIC_PREEMPTION_CHECKING to 1, if micro-second timers
+ are supported, so we can check for input during redisplay at
+ regular intervals. */
+#ifdef EMACS_HAS_USECS
+#define PERIODIC_PREEMPTION_CHECKING 1
+#else
+#define PERIODIC_PREEMPTION_CHECKING 0
+#endif
+
+#if PERIODIC_PREEMPTION_CHECKING
+
+/* If a number (float), check for user input every N seconds. */
+
+Lisp_Object Vredisplay_preemption_period;
+
+/* Redisplay preemption timers. */
+
+static EMACS_TIME preemption_period;
+static EMACS_TIME preemption_next_check;
+
+#endif
+
/* Nonzero upon entry to redisplay means do not assume anything about
current contents of actual terminal frame; clear and redraw it. */
static void add_frame_display_history P_ ((struct frame *, int));
static void add_window_display_history P_ ((struct window *, char *, int));
-
-
+\f
/* Add to the redisplay history how window W has been displayed.
MSG is a trace containing the information how W's glyph matrix
has been constructed. PAUSED_P non-zero means that the update
int paused_p;
struct window *root_window = XWINDOW (f->root_window);
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p && NUMBERP (Vredisplay_preemption_period))
+ {
+ EMACS_TIME tm;
+ double p = XFLOATINT (Vredisplay_preemption_period);
+ int sec, usec;
+
+ if (detect_input_pending_ignore_squeezables ())
+ {
+ paused_p = 1;
+ goto do_pause;
+ }
+
+ sec = (int) p;
+ usec = (p - sec) * 1000000;
+
+ EMACS_GET_TIME (tm);
+ EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ }
+#endif
+
if (FRAME_WINDOW_P (f))
{
/* We are working on window matrix basis. All windows whose
#endif
}
+ do_pause:
/* Reset flags indicating that a window should be updated. */
set_window_update_flags (root_window, 0);
/* Record that this is not a frame-based redisplay. */
set_frame_matrix_frame (NULL);
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p && NUMBERP (Vredisplay_preemption_period))
+ {
+ EMACS_TIME tm;
+ double p = XFLOATINT (Vredisplay_preemption_period);
+ int sec, usec;
+
+ sec = (int) p;
+ usec = (p - sec) * 1000000;
+
+ EMACS_GET_TIME (tm);
+ EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ }
+#endif
+
/* Update W. */
update_begin (f);
update_window (w, force_p);
{
struct glyph_matrix *desired_matrix = w->desired_matrix;
int paused_p;
+#if !PERIODIC_PREEMPTION_CHECKING
int preempt_count = baud_rate / 2400 + 1;
+#endif
extern int input_pending;
extern Lisp_Object do_mouse_tracking;
#if GLYPH_DEBUG
/* Check pending input the first time so that we can quickly return. */
if (redisplay_dont_pause)
force_p = 1;
- else
+#if PERIODIC_PREEMPTION_CHECKING
+ else if (NILP (Vredisplay_preemption_period))
+ force_p = 1;
+#else
+ else if (!force_p)
detect_input_pending_ignore_squeezables ();
+#endif
/* If forced to complete the update, or if no input is pending, do
the update. */
update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
desired_matrix),
&mouse_face_overwritten_p);
- changed_p = 1;
}
/* Find first enabled row. Optimizations in redisplay_internal
detect_input_pending. If it's done too often,
scrolling large windows with repeated scroll-up
commands will too quickly pause redisplay. */
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p)
+ {
+ EMACS_TIME tm, dif;
+ EMACS_GET_TIME (tm);
+ EMACS_SUB_TIME (dif, preemption_next_check, tm);
+ if (EMACS_TIME_NEG_P (dif))
+ {
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ if (detect_input_pending_ignore_squeezables ())
+ break;
+ }
+ }
+#else
if (!force_p && ++n_updated % preempt_count == 0)
detect_input_pending_ignore_squeezables ();
-
+#endif
changed_p |= update_window_line (w, vpos,
&mouse_face_overwritten_p);
{
header_line_row->y = 0;
update_window_line (w, 0, &mouse_face_overwritten_p);
- changed_p = 1;
}
/* Fix the appearance of overlapping/overlapped rows. */
if (redisplay_dont_pause)
force_p = 1;
+#if PERIODIC_PREEMPTION_CHECKING
+ else if (NILP (Vredisplay_preemption_period))
+ force_p = 1;
+#else
else if (!force_p && detect_input_pending_ignore_squeezables ())
{
pause = 1;
goto do_pause;
}
+#endif
/* If we cannot insert/delete lines, it's no use trying it. */
if (!line_ins_del_ok)
}
}
- if ((i - 1) % preempt_count == 0)
+#if PERIODIC_PREEMPTION_CHECKING
+ if (!force_p)
+ {
+ EMACS_TIME tm, dif;
+ EMACS_GET_TIME (tm);
+ EMACS_SUB_TIME (dif, preemption_next_check, tm);
+ if (EMACS_TIME_NEG_P (dif))
+ {
+ EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+ if (detect_input_pending_ignore_squeezables ())
+ break;
+ }
+ }
+#else
+ if (!force_p && (i - 1) % preempt_count == 0)
detect_input_pending_ignore_squeezables ();
+#endif
update_frame_line (f, i);
}
sit_for (sec, usec, reading, display, initial_display)
int sec, usec, reading, display, initial_display;
{
+ int preempt = (sec >= 0) || (sec == 0 && usec >= 0);
+
swallow_events (display);
- if (detect_input_pending_run_timers (display) || !NILP (Vexecuting_kbd_macro))
+ if ((detect_input_pending_run_timers (display) && preempt)
+ || !NILP (Vexecuting_kbd_macro))
return Qnil;
if (initial_display)
- redisplay_preserve_echo_area (2);
+ {
+ int count = SPECPDL_INDEX ();
+ if (!preempt)
+ specbind (Qredisplay_dont_pause, Qt);
+ redisplay_preserve_echo_area (2);
+ unbind_to (count, Qnil);
+ }
if (sec == 0 && usec == 0)
return Qt;
if input is available before it starts.
Value is t if waited the full time with no input arriving.
+Redisplay will occur even when input is available if SECONDS is negative.
+
An obsolete but still supported form is
\(sit-for SECONDS &optional MILLISECONDS NODISP)
Where the optional arg MILLISECONDS specifies an additional wait period,
try to use X, and die with an error message if that doesn't work. */
#ifdef HAVE_X_WINDOWS
- if (! display_arg)
+ if (! inhibit_window_system && ! display_arg)
{
char *display;
#ifdef VMS
doc: /* *Non-nil means update isn't paused when input is detected. */);
redisplay_dont_pause = 0;
- /* Initialize `window-system', unless init_display already decided it. */
+#if PERIODIC_PREEMPTION_CHECKING
+ DEFVAR_LISP ("redisplay-preemption-period", &Vredisplay_preemption_period,
+ doc: /* *The period in seconds between checking for input during redisplay.
+If input is detected, redisplay is pre-empted, and the input is processed.
+If nil, never pre-empt redisplay. */);
+ Vredisplay_preemption_period = make_float (0.10);
+#endif
+
#ifdef CANNOT_DUMP
if (noninteractive)
#endif