/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "intervals.h"
#include "blockinput.h"
#include "puresize.h"
+#include "systime.h"
+#include "atimer.h"
#include <setjmp.h>
#include <errno.h>
key sequence that it reads. */
Lisp_Object read_key_sequence_cmd;
+/* Echo unfinished commands after this many seconds of pause. */
+Lisp_Object Vecho_keystrokes;
+
/* Form to evaluate (if non-nil) when Emacs is started. */
Lisp_Object Vtop_level;
static void restore_getcjmp ();
static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
-/* > 0 if we are to echo keystrokes. */
-static int echo_keystrokes;
-
/* Nonzero means don't try to suspend even if the operating system seems
to support it. */
static int cannot_suspend;
#ifdef HAVE_X_WINDOWS
if (display_busy_cursor_p)
- {
- if (inhibit_busy_cursor != 2)
- inhibit_busy_cursor = 0;
- if (!inhibit_busy_cursor)
- Fx_show_busy_cursor ();
- }
+ start_busy_cursor ();
#endif
nonundocount = 0;
if (NILP (current_kboard->Vprefix_arg))
Fundo_boundary ();
Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
+
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ cancel_busy_cursor ();
+#endif
}
directly_done: ;
current_kboard->Vlast_prefix_arg = Vcurrent_prefix_arg;
unbind_to (count, Qnil);
}
+
\f
-/* Number of seconds between polling for input. */
+/* Number of seconds between polling for input. This is a Lisp
+ variable that can be bound. */
+
int polling_period;
/* Nonzero means polling for input is temporarily suppressed. */
+
int poll_suppress_count;
-/* Nonzero if polling_for_input is actually being used. */
-int polling_for_input;
+/* Asynchronous timer for polling. */
+
+struct atimer *poll_timer;
+
#ifdef POLL_FOR_INPUT
-/* Handle an alarm once each second and read pending input
- so as to handle a C-g if it comces in. */
+/* Poll for input, so what we catch a C-g if it comes in. This
+ function is called from x_make_frame_visible, see comment
+ there. */
-SIGTYPE
-input_poll_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
+void
+poll_for_input_1 ()
{
- /* This causes the call to start_polling at the end
- to do its job. It also arranges for a quit or error
- from within read_avail_input to resume polling. */
- poll_suppress_count++;
if (interrupt_input_blocked == 0
&& !waiting_for_input)
read_avail_input (0);
- /* Turn on the SIGALRM handler and request another alarm. */
- start_polling ();
}
-#endif
+/* Timer callback function for poll_timer. TIMER is equal to
+ poll_timer. */
+
+void
+poll_for_input (timer)
+ struct atimer *timer;
+{
+ if (poll_suppress_count == 0)
+ poll_for_input_1 ();
+}
+
+#endif /* POLL_FOR_INPUT */
/* Begin signals to poll for input, if they are appropriate.
This function is called unconditionally from various places. */
#ifdef POLL_FOR_INPUT
if (read_socket_hook && !interrupt_input)
{
- poll_suppress_count--;
- if (poll_suppress_count == 0)
+ /* Turn alarm handling on unconditionally. It might have
+ been turned off in process.c. */
+ turn_on_atimers (1);
+
+ /* If poll timer doesn't exist, are we need one with
+ a different interval, start a new one. */
+ if (poll_timer == NULL
+ || EMACS_SECS (poll_timer->interval) != polling_period)
{
- signal (SIGALRM, input_poll_signal);
- polling_for_input = 1;
- alarm (polling_period);
+ EMACS_TIME interval;
+
+ if (poll_timer)
+ cancel_atimer (poll_timer);
+
+ EMACS_SET_SECS_USECS (interval, polling_period, 0);
+ poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
+ poll_for_input, NULL);
}
+
+ /* Let the timer's callback function poll for input
+ if this becomes zero. */
+ --poll_suppress_count;
}
#endif
}
{
#ifdef POLL_FOR_INPUT
if (read_socket_hook && !interrupt_input)
- {
- if (poll_suppress_count == 0)
- {
- polling_for_input = 0;
- alarm (0);
- }
- poll_suppress_count++;
- }
+ ++poll_suppress_count;
#endif
}
if (n > new)
new = n;
+ stop_other_atimers (poll_timer);
stop_polling ();
specbind (Qpolling_period, make_number (new));
/* Start a new alarm with the new period. */
&& !current_kboard->immediate_echo
&& this_command_key_count > 0
&& ! noninteractive
- && echo_keystrokes > 0
+ && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes))
&& (/* No message. */
NILP (echo_area_buffer[0])
/* Or empty message. */
echo_now ();
else
{
+ int sec, usec;
+ double duration = extract_float (Vecho_keystrokes);
+ sec = (int) duration;
+ usec += (duration - sec) * 1000000;
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- tem0 = sit_for (echo_keystrokes, 0, 1, 1, 0);
+ tem0 = sit_for (sec, usec, 1, 1, 0);
restore_getcjmp (save_jump);
if (EQ (tem0, Qt)
&& ! CONSP (Vunread_command_events))
before_command_echo_length = echo_length ();
/* Don't echo mouse motion events. */
- if (echo_keystrokes
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes))
&& ! (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
{
before_command_echo_length = echo_length ();
/* Don't echo mouse motion events. */
- if (echo_keystrokes)
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
{
echo_char (c);
{
int was_locked = single_kboard;
int count = specpdl_ptr - specpdl;
-#ifdef HAVE_WINDOW_SYSTEM
- int old_inhibit_busy_cursor = inhibit_busy_cursor;
-#endif
/* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */
specbind (Qinhibit_quit, Qt);
-#ifdef HAVE_WINDOW_SYSTEM
- inhibit_busy_cursor = 2;
-#endif
-
call1 (Qtimer_event_handler, chosen_timer);
timers_run++;
-#ifdef HAVE_WINDOW_SYSTEM
- inhibit_busy_cursor = old_inhibit_busy_cursor;
-#endif
-
unbind_to (count, Qnil);
/* Resume allowing input from any kboard, if that was true before. */
{
if (!NILP (prompt))
echo_prompt (XSTRING (prompt)->data);
- else if (cursor_in_echo_area && echo_keystrokes)
+ else if (cursor_in_echo_area
+ && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
/* This doesn't put in a dash if the echo buffer is empty, so
you don't always see a dash hanging out in the minibuffer. */
echo_dash ();
{
key = keybuf[t];
add_command_key (key);
- if (echo_keystrokes)
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
echo_char (key);
}
Better ideas? */
for (; t < mock_input; t++)
{
- if (echo_keystrokes)
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
echo_char (keybuf[t]);
add_command_key (keybuf[t]);
}
this_single_command_key_start = 0;
}
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ cancel_busy_cursor ();
+#endif
+
i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
! NILP (can_return_switch_frame), 0);
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ start_busy_cursor ();
+#endif
+
if (i == -1)
{
Vquit_flag = Qt;
this_single_command_key_start = 0;
}
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ cancel_busy_cursor ();
+#endif
+
i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
! NILP (can_return_switch_frame), 0);
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ start_busy_cursor ();
+#endif
+
if (i == -1)
{
Vquit_flag = Qt;
Emacs also does a garbage collection if that seems to be warranted.");
XSETFASTINT (Vauto_save_timeout, 30);
- DEFVAR_INT ("echo-keystrokes", &echo_keystrokes,
- "*Nonzero means echo unfinished commands after this many seconds of pause.");
- echo_keystrokes = 1;
+ DEFVAR_LISP ("echo-keystrokes", &Vecho_keystrokes,
+ "*Nonzero means echo unfinished commands after this many seconds of pause.\n\
+The value may be integer or floating point.");
+ Vecho_keystrokes = make_number (1);
DEFVAR_INT ("polling-period", &polling_period,
"*Interval between polling for input during Lisp execution.\n\