]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
(command_loop_1): Call start_busy_cursor before
[gnu-emacs] / src / keyboard.c
index c5a760b623c0b70c0a5afff2aa0221898894da5a..ff94b42677cc84ba2d9da1b9f005ce2c53a025a7 100644 (file)
@@ -1,5 +1,6 @@
 /* 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.
 
@@ -38,6 +39,8 @@ Boston, MA 02111-1307, USA.  */
 #include "intervals.h"
 #include "blockinput.h"
 #include "puresize.h"
+#include "systime.h"
+#include "atimer.h"
 #include <setjmp.h>
 #include <errno.h>
 
@@ -376,6 +379,9 @@ Lisp_Object Qtimer_event_handler;
    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;
 
@@ -636,9 +642,6 @@ static void save_getcjmp ();
 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;
@@ -1516,18 +1519,18 @@ command_loop_1 ()
 
 #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;
@@ -1689,37 +1692,48 @@ safe_run_hooks (hook)
 
   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.  */
@@ -1730,13 +1744,28 @@ start_polling ()
 #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
 }
@@ -1760,14 +1789,7 @@ stop_polling ()
 {
 #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
 }
 
@@ -1805,6 +1827,7 @@ bind_polling_period (n)
   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.  */
@@ -2128,7 +2151,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       && !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.  */
@@ -2148,9 +2172,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        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))
@@ -2581,7 +2609,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       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)))
        {
@@ -2651,7 +2680,8 @@ record_menu_key (c)
   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);
 
@@ -3597,9 +3627,6 @@ timer_check (do_it_now)
            {
              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.  */
@@ -3607,17 +3634,9 @@ timer_check (do_it_now)
 
              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.  */
@@ -7431,7 +7450,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
     {
       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 ();
@@ -7577,7 +7598,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
        {
          key = keybuf[t];
          add_command_key (key);
-         if (echo_keystrokes)
+         if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+             && NILP (Fzerop (Vecho_keystrokes)))
            echo_char (key);
        }
 
@@ -8366,7 +8388,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
      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]);
     }
@@ -8459,10 +8482,20 @@ DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
       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;
@@ -8504,10 +8537,20 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
       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;
@@ -9911,9 +9954,10 @@ After auto-saving due to this many seconds of idle time,\n\
 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\