declare smobs in alloc.c
[bpt/emacs.git] / src / keyboard.c
index 20498d0..7e63357 100644 (file)
@@ -43,6 +43,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "systime.h"
 #include "atimer.h"
 #include "process.h"
+#include "guile.h"
 #include <errno.h>
 
 #ifdef HAVE_PTHREAD
@@ -137,7 +138,7 @@ static ptrdiff_t before_command_echo_length;
 
 /* For longjmp to where kbd input is being done.  */
 
-static sys_jmp_buf getcjmp;
+static Lisp_Object getctag;
 
 /* True while doing kbd input.  */
 bool waiting_for_input;
@@ -417,8 +418,6 @@ static Lisp_Object make_lispy_focus_in (Lisp_Object);
 static Lisp_Object make_lispy_focus_out (Lisp_Object);
 #endif /* HAVE_WINDOW_SYSTEM */
 static bool help_char_p (Lisp_Object);
-static void save_getcjmp (sys_jmp_buf *);
-static void restore_getcjmp (sys_jmp_buf *);
 static Lisp_Object apply_modifiers (int, Lisp_Object);
 static void clear_event (struct input_event *);
 static void restore_kboard_configuration (int);
@@ -1167,24 +1166,55 @@ command_loop (void)
    value to us.  A value of nil means that command_loop_1 itself
    returned due to end of file (or end of kbd macro).  */
 
+static Lisp_Object
+command_loop_2_body (void *ignore)
+{
+  return command_loop_1 ();
+}
+
+static Lisp_Object
+command_loop_2_handler (void *ignore, SCM key, SCM args)
+{
+  return Fsignal (Qerror,
+                  list3 (build_string ("Scheme error"), key, args));
+}
+
+static Lisp_Object
+command_loop_2_inner (void)
+{
+  return scm_c_with_throw_handler (SCM_BOOL_T,
+                                   command_loop_2_body, NULL,
+                                   command_loop_2_handler, NULL,
+                                   0);
+}
+
 static Lisp_Object
 command_loop_2 (Lisp_Object ignore)
 {
   register Lisp_Object val;
 
   do
-    val = internal_condition_case (command_loop_1, Qerror, cmd_error);
+    val = internal_condition_case (command_loop_2_inner, Qerror, cmd_error);
   while (!NILP (val));
 
   return Qnil;
 }
 
 static Lisp_Object
-top_level_2 (void)
+top_level_2_body (void *ignore)
 {
   return Feval (Vtop_level, Qnil);
 }
 
+static Lisp_Object
+top_level_2 (void)
+{
+  return scm_c_with_throw_handler (SCM_BOOL_T,
+                                   top_level_2_body, NULL,
+                                   command_loop_2_handler, NULL,
+                                   0);
+}
+
 static Lisp_Object
 top_level_1 (Lisp_Object ignore)
 {
@@ -1265,13 +1295,13 @@ tracking_off (Lisp_Object old_value)
     }
 }
 
-DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
+DEFUN ("call-with-track-mouse", Ftrack_mouse, Strack_mouse, 1, 1, 0,
        doc: /* Evaluate BODY with mouse movement events enabled.
 Within a `track-mouse' form, mouse motion generates input events that
 you can read with `read-event'.
 Normally, mouse motion is ignored.
 usage: (track-mouse BODY...)  */)
-  (Lisp_Object args)
+  (Lisp_Object thunk)
 {
   dynwind_begin ();
   Lisp_Object val;
@@ -1280,7 +1310,7 @@ usage: (track-mouse BODY...)  */)
 
   do_mouse_tracking = Qt;
 
-  val = Fprogn (args);
+  val = call0 (thunk);
   dynwind_end ();
   return val;
 }
@@ -1683,7 +1713,7 @@ Lisp_Object
 read_menu_command (void)
 {
   Lisp_Object keybuf[30];
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
   int i;
 
   /* We don't want to echo the keystrokes while navigating the
@@ -1693,7 +1723,7 @@ read_menu_command (void)
   i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
                         Qnil, 0, 1, 1, 1);
 
-  unbind_to (count, Qnil);
+  dynwind_end ();
 
   if (! FRAME_LIVE_P (XFRAME (selected_frame)))
     Fkill_emacs (Qnil);
@@ -1943,11 +1973,6 @@ safe_run_hooks (Lisp_Object hook)
 }
 
 \f
-/* Nonzero means polling for input is temporarily suppressed.  */
-
-int poll_suppress_count;
-
-
 #ifdef POLL_FOR_INPUT
 
 /* Asynchronous timer for polling.  */
@@ -1969,8 +1994,6 @@ poll_for_input_1 (void)
 static void
 poll_for_input (struct atimer *timer)
 {
-  if (poll_suppress_count == 0)
-    pending_signals = 1;
 }
 
 #endif /* POLL_FOR_INPUT */
@@ -2005,10 +2028,6 @@ start_polling (void)
          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
 }
@@ -2028,40 +2047,6 @@ input_polling_used (void)
 #endif
 }
 
-/* Turn off polling.  */
-
-void
-stop_polling (void)
-{
-#ifdef POLL_FOR_INPUT
-  /* XXX This condition was (read_socket_hook && !interrupt_input),
-     but read_socket_hook is not global anymore.  Let's pretend that
-     it's always set.  */
-  if (!interrupt_input)
-    ++poll_suppress_count;
-#endif
-}
-
-/* Set the value of poll_suppress_count to COUNT
-   and start or stop polling accordingly.  */
-
-void
-set_poll_suppress_count (int count)
-{
-#ifdef POLL_FOR_INPUT
-  if (count == 0 && poll_suppress_count != 0)
-    {
-      poll_suppress_count = 1;
-      start_polling ();
-    }
-  else if (count != 0 && poll_suppress_count == 0)
-    {
-      stop_polling ();
-    }
-  poll_suppress_count = count;
-#endif
-}
-
 /* Bind polling_period to a value at least N.
    But don't decrease it.  */
 
@@ -2069,13 +2054,12 @@ void
 bind_polling_period (int n)
 {
 #ifdef POLL_FOR_INPUT
-  EMACS_INT new = polling_period;
+  EMACS_INT new = max (polling_period, new);
 
   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.  */
   start_polling ();
@@ -2203,20 +2187,13 @@ read_char_help_form_unwind (void)
     Fset_window_configuration (window_config);
 }
 
-#define STOP_POLLING                                   \
-do { if (! polling_stopped_here) stop_polling ();      \
-       polling_stopped_here = 1; } while (0)
-
-#define RESUME_POLLING                                 \
-do { if (polling_stopped_here) start_polling ();       \
-       polling_stopped_here = 0; } while (0)
-
 static Lisp_Object
 read_event_from_main_queue (struct timespec *end_time,
-                            sys_jmp_buf *local_getcjmp,
+                            Lisp_Object local_tag,
                             bool *used_mouse_menu)
 {
   Lisp_Object c = Qnil;
+  Lisp_Object save_tag = Qnil;
   sys_jmp_buf *save_jump = xmalloc (sizeof *save_jump);
   KBOARD *kb IF_LINT (= NULL);
 
@@ -2229,12 +2206,12 @@ read_event_from_main_queue (struct timespec *end_time,
     return c;
 
   /* Actually read a character, waiting if necessary.  */
-  save_getcjmp (save_jump);
-  restore_getcjmp (local_getcjmp);
+  save_tag = getctag;
+  getctag = local_tag;
   if (!end_time)
        timer_start_idle ();
   c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
-  restore_getcjmp (save_jump);
+  getctag = save_tag;
 
   if (! NILP (c) && (kb != current_kboard))
     {
@@ -2287,7 +2264,7 @@ read_event_from_main_queue (struct timespec *end_time,
    to tty input.  */
 static Lisp_Object
 read_decoded_event_from_main_queue (struct timespec *end_time,
-                                    sys_jmp_buf *local_getcjmp,
+                                    Lisp_Object local_getcjmp,
                                     Lisp_Object prev_event,
                                     bool *used_mouse_menu)
 {
@@ -2408,9 +2385,9 @@ struct read_char_state
   bool *used_mouse_menu;
   struct timespec *end_time;
   Lisp_Object c;
-  ptrdiff_t jmpcount;
-  sys_jmp_buf *local_getcjmp;
-  sys_jmp_buf *save_jump;
+  Lisp_Object tag;
+  Lisp_Object local_tag;
+  Lisp_Object save_tag;
   Lisp_Object previous_echo_area_message;
   Lisp_Object also_record;
   bool reread;
@@ -2420,13 +2397,65 @@ struct read_char_state
 
 static Lisp_Object read_char_1 (bool, volatile struct read_char_state *);
 
+static Lisp_Object
+read_char_thunk (void *data)
+{
+  return read_char_1 (false, data);
+}
+
+static Lisp_Object
+read_char_handle_quit (void *data, Lisp_Object k)
+{
+  struct read_char_state *state = data;
+  /* Handle quits while reading the keyboard.  */
+  /* We must have saved the outer value of getcjmp here,
+     so restore it now.  */
+  getctag = state->save_tag;
+  XSETINT (state->c, quit_char);
+  internal_last_event_frame = selected_frame;
+  Vlast_event_frame = internal_last_event_frame;
+  /* If we report the quit char as an event,
+     don't do so more than once.  */
+  if (!NILP (Vinhibit_quit))
+    Vquit_flag = Qnil;
+
+  {
+    KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
+    if (kb != current_kboard)
+      {
+        Lisp_Object last = KVAR (kb, kbd_queue);
+        /* We shouldn't get here if we were in single-kboard mode!  */
+        if (single_kboard)
+          emacs_abort ();
+        if (CONSP (last))
+          {
+            while (CONSP (XCDR (last)))
+              last = XCDR (last);
+            if (!NILP (XCDR (last)))
+              emacs_abort ();
+          }
+        if (!CONSP (last))
+          kset_kbd_queue (kb, list1 (state->c));
+        else
+          XSETCDR (last, list1 (state->c));
+        kb->kbd_queue_has_data = 1;
+        current_kboard = kb;
+        /* This is going to exit from read_char
+           so we had better get rid of this frame's stuff.  */
+        UNGCPRO;
+        return make_number (-2); /* wrong_kboard_jmpbuf */
+      }
+  }
+  return read_char_1 (true, state);
+}
+
 /* {{coccinelle:skip_start}} */
 Lisp_Object
 read_char (int commandflag, Lisp_Object map,
           Lisp_Object prev_event,
           bool *used_mouse_menu, struct timespec *end_time)
 {
-  volatile struct read_char_state *state = xmalloc (sizeof *state);
+  struct read_char_state *state = xmalloc (sizeof *state);
 
   state->commandflag = commandflag;
   state->map = map;
@@ -2434,8 +2463,8 @@ read_char (int commandflag, Lisp_Object map,
   state->used_mouse_menu = used_mouse_menu;
   state->end_time = end_time;
   state->c = Qnil;
-  state->local_getcjmp = xmalloc (sizeof (*state->local_getcjmp));
-  state->save_jump = xmalloc (sizeof (*state->save_jump));
+  state->local_tag = Qnil;
+  state->save_tag = Qnil;
   state->previous_echo_area_message = Qnil;
   state->also_record = Qnil;
   state->reread = false;
@@ -2448,54 +2477,11 @@ read_char (int commandflag, Lisp_Object map,
      around any call to sit_for or kbd_buffer_get_event;
      it *must not* be in effect when we call redisplay.  */
 
-  state->jmpcount = SPECPDL_INDEX ();
-  if (sys_setjmp (*state->local_getcjmp))
-    {
-      /* Handle quits while reading the keyboard.  */
-      /* We must have saved the outer value of getcjmp here,
-        so restore it now.  */
-      restore_getcjmp (state->save_jump);
-      pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
-      unbind_to (state->jmpcount, Qnil);
-      XSETINT (state->c, quit_char);
-      internal_last_event_frame = selected_frame;
-      Vlast_event_frame = internal_last_event_frame;
-      /* If we report the quit char as an event,
-        don't do so more than once.  */
-      if (!NILP (Vinhibit_quit))
-       Vquit_flag = Qnil;
-
-      {
-       KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
-       if (kb != current_kboard)
-         {
-           Lisp_Object last = KVAR (kb, kbd_queue);
-           /* We shouldn't get here if we were in single-kboard mode!  */
-           if (single_kboard)
-             emacs_abort ();
-           if (CONSP (last))
-             {
-               while (CONSP (XCDR (last)))
-                 last = XCDR (last);
-               if (!NILP (XCDR (last)))
-                 emacs_abort ();
-             }
-           if (!CONSP (last))
-             kset_kbd_queue (kb, list1 (state->c));
-           else
-             XSETCDR (last, list1 (state->c));
-           kb->kbd_queue_has_data = 1;
-           current_kboard = kb;
-           /* This is going to exit from read_char
-              so we had better get rid of this frame's stuff.  */
-           UNGCPRO;
-            return make_number (-2); /* wrong_kboard_jmpbuf */
-         }
-      }
-      return read_char_1 (true, state);
-    }
+  state->tag = state->local_tag = make_prompt_tag ();
 
-  return read_char_1 (false, state);
+  return call_with_prompt (state->tag,
+                           make_c_closure (read_char_thunk, state, 0, 0),
+                           make_c_closure (read_char_handle_quit, state, 1, 0));
 }
 
 static Lisp_Object
@@ -2508,13 +2494,15 @@ read_char_1 (bool jump, volatile struct read_char_state *state)
 #define end_time state->end_time
 #define c state->c
 #define jmpcount state->jmpcount
-#define local_getcjmp state->local_getcjmp
-#define save_jump state->save_jump
+#define local_getcjmp state->local_tag
+#define save_jump state->save_tag
 #define previous_echo_area_message state->previous_echo_area_message
 #define also_record state->also_record
 #define reread state->reread
 #define polling_stopped_here state->polling_stopped_here
 #define orig_kboard state->orig_kboard
+#define save_getcjmp(x) (x = getctag)
+#define restore_getcjmp(x) (getctag = x)
   Lisp_Object tem, save;
 
   if (jump)
@@ -2929,8 +2917,6 @@ read_char_1 (bool jump, volatile struct read_char_state *state)
 
  wrong_kboard:
 
-  STOP_POLLING;
-
   if (NILP (c))
     {
       c = read_decoded_event_from_main_queue (end_time, local_getcjmp,
@@ -2954,7 +2940,6 @@ read_char_1 (bool jump, volatile struct read_char_state *state)
 
   if (!end_time)
     timer_stop_idle ();
-  RESUME_POLLING;
 
   if (NILP (c))
     {
@@ -3268,7 +3253,6 @@ read_char_1 (bool jump, volatile struct read_char_state *state)
     }
 
  exit:
-  RESUME_POLLING;
   RETURN_UNGCPRO (c);
 #undef commandflag
 #undef map
@@ -3284,6 +3268,8 @@ read_char_1 (bool jump, volatile struct read_char_state *state)
 #undef reread
 #undef polling_stopped_here
 #undef orig_kboard
+#undef save_getcjmp
+#undef restore_getcjmp
 }
 /* {{coccinelle:skip_end}} */
 
@@ -3471,23 +3457,6 @@ record_char (Lisp_Object c)
       unblock_input ();
     }
 }
-
-/* Copy out or in the info on where C-g should throw to.
-   This is used when running Lisp code from within get_char,
-   in case get_char is called recursively.
-   See read_process_output.  */
-
-static void
-save_getcjmp (sys_jmp_buf *temp)
-{
-  memcpy (*temp, getcjmp, sizeof getcjmp);
-}
-
-static void
-restore_getcjmp (sys_jmp_buf *temp)
-{
-  memcpy (getcjmp, *temp, sizeof getcjmp);
-}
 \f
 /* Low level keyboard/mouse input.
    kbd_buffer_store_event places events in kbd_buffer, and
@@ -3719,7 +3688,6 @@ kbd_buffer_store_event_hold (register struct input_event *event,
           hold_keyboard_input ();
           if (!noninteractive)
             ignore_sigio ();
-          stop_polling ();
         }
 #endif /* subprocesses */
     }
@@ -3883,7 +3851,6 @@ kbd_buffer_get_event (KBOARD **kbp,
       /* Start reading input again because we have processed enough to
          be able to accept new events again.  */
       unhold_keyboard_input ();
-      start_polling ();
     }
 #endif /* subprocesses */
 
@@ -6844,16 +6811,7 @@ record_asynch_buffer_change (void)
       event.arg = Qnil;
 
       /* Make sure no interrupt happens while storing the event.  */
-#ifdef USABLE_SIGIO
-      if (interrupt_input)
-       kbd_buffer_store_event (&event);
-      else
-#endif
-       {
-         stop_polling ();
-         kbd_buffer_store_event (&event);
-         start_polling ();
-       }
+      kbd_buffer_store_event (&event);
     }
 }
 
@@ -7896,7 +7854,7 @@ parse_menu_item (Lisp_Object item, int inmenubar)
                       (such as lmenu.el set it up), check if the
                       original command matches the cached command.  */
                    && !(SYMBOLP (def)
-                        && EQ (tem, XSYMBOL (def)->function))))
+                        && EQ (tem, SYMBOL_FUNCTION (def)))))
              keys = Qnil;
          }
 
@@ -8763,9 +8721,10 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
   /* Handle a symbol whose function definition is a keymap
      or an array.  */
   if (SYMBOLP (next) && !NILP (Ffboundp (next))
-      && (ARRAYP (XSYMBOL (next)->function)
-         || KEYMAPP (XSYMBOL (next)->function)))
-    next = Fautoload_do_load (XSYMBOL (next)->function, next, Qnil);
+      && (ARRAYP (SYMBOL_FUNCTION (next))
+         || KEYMAPP (SYMBOL_FUNCTION (next))))
+    next = Fautoload_do_load (SYMBOL_FUNCTION (next),
+                                              next, Qnil);
 
   /* If the keymap gives a function, not an
      array, then call the function with one arg and use
@@ -10512,7 +10471,7 @@ quit_throw_to_read_char (bool from_signal)
     do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
                     0, 0, Qnil);
 
-  sys_longjmp (getcjmp, 1);
+  abort_to_prompt (getctag, SCM_EOL);
 }
 \f
 DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,
@@ -10542,9 +10501,6 @@ See also `current-input-mode'.  */)
 
   if (new_interrupt_input != interrupt_input)
     {
-#ifdef POLL_FOR_INPUT
-      stop_polling ();
-#endif
 #ifndef DOS_NT
       /* this causes startup screen to be restored and messes with the mouse */
       reset_all_sys_modes ();
@@ -10555,7 +10511,6 @@ See also `current-input-mode'.  */)
 #endif
 
 #ifdef POLL_FOR_INPUT
-      poll_suppress_count = 1;
       start_polling ();
 #endif
     }
@@ -10965,7 +10920,6 @@ init_keyboard (void)
 
 #ifdef POLL_FOR_INPUT
   poll_timer = NULL;
-  poll_suppress_count = 1;
   start_polling ();
 #endif
 }