update.
[chise/xemacs-chise.git.1] / src / event-stream.c
index 0d09051..de65d4e 100644 (file)
@@ -52,8 +52,6 @@ Boston, MA 02111-1307, USA.  */
 /* TODO:
    This stuff is way too hard to maintain - needs rework.
 
-   C-x @ h <scrollbar-drag> x causes a crash.
-
    The command builder should deal only with key and button events.
    Other command events should be able to come in the MIDDLE of a key
    sequence, without disturbing the key sequence composition, or the
@@ -102,7 +100,7 @@ Boston, MA 02111-1307, USA.  */
 #include <errno.h>
 
 /* The number of keystrokes between auto-saves. */
-static int auto_save_interval;
+static Fixnum auto_save_interval;
 
 Lisp_Object Qundefined_keystroke_sequence;
 
@@ -121,23 +119,19 @@ Lisp_Object Qpre_idle_hook, Vpre_idle_hook;
 /* Control gratuitous keyboard focus throwing. */
 int focus_follows_mouse;
 
+/* When true, modifier keys are sticky. */
 int modifier_keys_are_sticky;
+/* Modifier keys are sticky for this many milliseconds. */
+Lisp_Object Vmodifier_keys_sticky_time;
 
-#if 0 /* FSF Emacs crap */
-/* Hook run after a command if there's no more input soon.  */
-Lisp_Object Qpost_command_idle_hook, Vpost_command_idle_hook;
-
-/* Delay time in microseconds before running post-command-idle-hook.  */
-int post_command_idle_delay;
+/* Here FSF Emacs 20.7 defines Vpost_command_idle_hook,
+   post_command_idle_delay, Vdeferred_action_list, and
+   Vdeferred_action_function, but we don't because that stuff is crap,
+   and we're smarter than them, and their momas are fat. */
 
-/* List of deferred actions to be performed at a later time.
-   The precise format isn't relevant here; we just check whether it is nil.  */
-Lisp_Object Vdeferred_action_list;
-
-/* Function to call to handle deferred actions, when there are any.  */
-Lisp_Object Vdeferred_action_function;
-Lisp_Object Qdeferred_action_function;
-#endif /* FSF Emacs crap */
+/* FSF Emacs 20.7 also defines Vinput_method_function,
+   Qinput_method_exit_on_first_char and Qinput_method_use_echo_area.
+   I don't know this should be imported or not. */
 
 /* Non-nil disable property on a command means
    do not execute it; call disabled-command-hook's value instead. */
@@ -256,7 +250,7 @@ Lisp_Object Qself_insert_defer_undo;
 extern Lisp_Object Fmake_keymap (Lisp_Object name);
 
 #ifdef DEBUG_XEMACS
-int debug_emacs_events;
+Fixnum debug_emacs_events;
 
 static void
 external_debugging_print_event (char *event_description, Lisp_Object event)
@@ -429,7 +423,7 @@ check_event_stream_ok (enum event_stream_operation op)
        case EVENT_STREAM_READ:
          error ("Can't read events in -batch mode");
        default:
-         abort ();
+         ABORT ();
        }
     }
   else if (!event_stream)
@@ -502,15 +496,7 @@ event_stream_next_event (Lisp_Event *event)
      Let's hope it doesn't.  I think the code here is fairly
      clean and doesn't do this. */
   emacs_is_blocking = 1;
-#if 0
-  /* Do this if the poll-for-quit timer seems to be taking too
-     much CPU time when idle ... */
-  reset_poll_for_quit ();
-#endif
   event_stream->next_event_cb (event);
-#if 0
-  init_poll_for_quit ();
-#endif
   emacs_is_blocking = 0;
 
 #ifdef DEBUG_XEMACS
@@ -715,7 +701,8 @@ reset_key_echo (struct command_builder *command_builder,
   /* This function can GC */
   struct frame *f = selected_frame ();
 
-  command_builder->echo_buf_index = -1;
+  if (command_builder)
+    command_builder->echo_buf_index = -1;
 
   if (remove_echo_area_echo)
     clear_echo_area (f, Qcommand, 0);
@@ -759,7 +746,7 @@ maybe_kbd_translate (Lisp_Object event)
             This way is safer. */
          zero_event (&ev2);
          character_to_event (XCHAR (traduit), &ev2,
-                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 1, 1);
+                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 0, 1);
          XEVENT (event)->event.key.keysym = ev2.event.key.keysym;
          XEVENT (event)->event.key.modifiers = ev2.event.key.modifiers;
          did_translate = 1;
@@ -781,7 +768,7 @@ maybe_kbd_translate (Lisp_Object event)
 
          zero_event (&ev2);
          character_to_event (XCHAR (traduit), &ev2,
-                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 1, 1);
+                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 0, 1);
          XEVENT (event)->event.key.keysym = ev2.event.key.keysym;
          XEVENT (event)->event.key.modifiers |= ev2.event.key.modifiers;
          did_translate = 1;
@@ -798,7 +785,8 @@ maybe_kbd_translate (Lisp_Object event)
    keystrokes_since_auto_save is equivalent to the difference between
    num_nonmacro_input_chars and last_auto_save. */
 
-/* When an auto-save happens, record the "time", and don't do again soon.  */
+/* When an auto-save happens, record the number of keystrokes, and
+   don't do again soon.  */
 
 void
 record_auto_save (void)
@@ -812,10 +800,6 @@ void
 force_auto_save_soon (void)
 {
   keystrokes_since_auto_save = 1 + max (auto_save_interval, 20);
-
-#if 0 /* FSFmacs */
-  record_asynch_buffer_change ();
-#endif
 }
 
 static void
@@ -1403,7 +1387,7 @@ is a race condition.  That's why the RESIGNAL argument exists.
   Lisp_Object lid;
   id = event_stream_generate_wakeup (msecs, msecs2, function, object, 0);
   lid = make_int (id);
-  if (id != XINT (lid)) abort ();
+  if (id != XINT (lid)) ABORT ();
   return lid;
 }
 
@@ -1482,7 +1466,7 @@ is a race condition.  That's why the RESIGNAL argument exists.
   Lisp_Object lid;
   id = event_stream_generate_wakeup (msecs, msecs2, function, object, 1);
   lid = make_int (id);
-  if (id != XINT (lid)) abort ();
+  if (id != XINT (lid)) ABORT ();
   return lid;
 }
 
@@ -1695,19 +1679,6 @@ run_select_frame_hook (void)
 static void
 run_deselect_frame_hook (void)
 {
-#if 0 /* unclean!  FSF calls this at all sorts of random places,
-         including a bunch of places in their mouse.el.  If this
-         is implemented, it has to be done cleanly. */
-  run_hook (Qmouse_leave_buffer_hook); /* #### Correct?  It's also
-                                         called in `call-interactively'.
-                                         Does this mean it will be
-                                         called twice?  Oh well, FSF
-                                         bug -- FSF calls it in
-                                         `handle-switch-frame',
-                                         which is approximately the
-                                         same as the caller of this
-                                         function. */
-#endif
   run_hook (Qdeselect_frame_hook);
 }
 
@@ -1837,7 +1808,8 @@ emacs_handle_focus_change_preliminary (Lisp_Object frame_inp_and_dev)
        MARK_WINDOWS_CHANGED (w);
       }
 
-      if (FRAMEP (focus_frame) && !EQ (frame, focus_frame))
+      if (FRAMEP (focus_frame) && FRAME_LIVE_P (XFRAME (focus_frame))
+         && !EQ (frame, focus_frame))
        {
          /* Oops, we missed a focus-out event. */
          DEVICE_FRAME_WITH_FOCUS_REAL (d) = Qnil;
@@ -2039,6 +2011,7 @@ static void push_this_command_keys (Lisp_Object event);
 static void push_recent_keys (Lisp_Object event);
 static void dribble_out_event (Lisp_Object event);
 static void execute_internal_event (Lisp_Object event);
+static int is_scrollbar_event (Lisp_Object event);
 
 DEFUN ("next-event", Fnext_event, 0, 2, 0, /*
 Return the next available event.
@@ -2231,8 +2204,6 @@ The returned event will be one of the following types:
 
   switch (XEVENT_TYPE (event))
     {
-    default:
-      goto RETURN;
     case button_release_event:
     case misc_user_event:
       /* don't echo menu accelerator keys */
@@ -2242,6 +2213,8 @@ The returned event will be one of the following types:
       goto STORE_AND_EXECUTE_KEY;
     case key_press_event:         /* any key input can trigger autosave */
       break;
+    default:
+      goto RETURN;
     }
 
   maybe_do_auto_save ();
@@ -2299,7 +2272,9 @@ The returned event will be one of the following types:
      */
   if (store_this_key)
     {
-      push_this_command_keys (event);
+      if (!is_scrollbar_event (event)) /* #### not quite right, see
+                                         comment in execute_command_event */
+       push_this_command_keys (event);
       if (!inhibit_input_event_recording)
        push_recent_keys (event);
       dribble_out_event (event);
@@ -2491,7 +2466,7 @@ A user event is a key press, button press, button release, or
     }
 
   if (!NILP (command_event_queue) || !NILP (command_event_queue_tail))
-    abort ();
+    ABORT ();
 
   /* Now tack our chain of events back on to the front of the queue.
      Actually, since the queue is now drained, we can just replace it.
@@ -2684,11 +2659,11 @@ Return non-nil iff we received any output before the timeout expired.
 }
 
 DEFUN ("sleep-for", Fsleep_for, 1, 1, 0, /*
-Pause, without updating display, for ARG seconds.
-ARG may be a float, meaning pause for some fractional part of a second.
+Pause, without updating display, for SECONDS seconds.
+SECONDS may be a float, allowing pauses for fractional parts of a second.
 
 It is recommended that you never call sleep-for from inside of a process
- filter function or timer event (either synchronous or asynchronous).
+filter function or timer event (either synchronous or asynchronous).
 */
        (seconds))
 {
@@ -2751,9 +2726,9 @@ It is recommended that you never call sleep-for from inside of a process
 }
 
 DEFUN ("sit-for", Fsit_for, 1, 2, 0, /*
-Perform redisplay, then wait ARG seconds or until user input is available.
-ARG may be a float, meaning a fractional part of a second.
-Optional second arg non-nil means don't redisplay, just wait for input.
+Perform redisplay, then wait SECONDS seconds or until user input is available.
+SECONDS may be a float, meaning a fractional part of a second.
+Optional second arg NODISPLAY non-nil means don't redisplay; just wait.
 Redisplay is preempted as always if user input arrives, and does not
  happen if input is available before it starts.
 Value is t if waited the full time with no input arriving.
@@ -3066,7 +3041,7 @@ execute_internal_event (Lisp_Object event)
        return;
       }
     default:
-      abort ();
+      ABORT ();
     }
 }
 
@@ -3402,7 +3377,7 @@ modify them.
     {
       Vrecent_keys_ring = make_vector (recent_keys_ring_size, Qnil);
       /* And return nothing in particular. */
-      return make_vector (0, Qnil);
+      RETURN_UNGCPRO (make_vector (0, Qnil));
     }
 
   if (NILP (XVECTOR_DATA (Vrecent_keys_ring)[recent_keys_ring_index]))
@@ -3434,7 +3409,7 @@ modify them.
     Lisp_Object e = XVECTOR_DATA (Vrecent_keys_ring)[j];
 
     if (NILP (e))
-      abort ();
+      ABORT ();
     XVECTOR_DATA (val)[i] = Fcopy_event (e, Qnil);
     if (++j >= recent_keys_ring_size)
       j = 0;
@@ -3460,7 +3435,6 @@ Set the maximum number of events to be stored internally.
   Lisp_Object new_vector = Qnil;
   int i, j, nkeys, start, min;
   struct gcpro gcpro1;
-  GCPRO1 (new_vector);
 
   CHECK_INT (size);
   if (XINT (size) <= 0)
@@ -3468,12 +3442,13 @@ Set the maximum number of events to be stored internally.
   if (XINT (size) == recent_keys_ring_size)
     return size;
 
+  GCPRO1 (new_vector);
   new_vector = make_vector (XINT (size), Qnil);
 
   if (NILP (Vrecent_keys_ring))
     {
       Vrecent_keys_ring = new_vector;
-      return size;
+      RETURN_UNGCPRO (size);
     }
 
   if (NILP (XVECTOR_DATA (Vrecent_keys_ring)[recent_keys_ring_index]))
@@ -3530,16 +3505,24 @@ Set the maximum number of events to be stored internally.
 void
 reset_this_command_keys (Lisp_Object console, int clear_echo_area_p)
 {
-  struct command_builder *command_builder =
-    XCOMMAND_BUILDER (XCONSOLE (console)->command_builder);
-
-  reset_key_echo (command_builder, clear_echo_area_p);
+  if (!NILP (console))
+    {
+      /* console is nil if we just deleted the console as a result of C-x 5
+        0.  Unfortunately things are currently in a messy situation where
+        some stuff is console-local and other stuff isn't, so we need to
+        do everything that's not console-local. */
+      struct command_builder *command_builder =
+       XCOMMAND_BUILDER (XCONSOLE (console)->command_builder);
+
+      reset_key_echo (command_builder, clear_echo_area_p);
+      reset_current_events (command_builder);
+    }
+  else
+    reset_key_echo (0, clear_echo_area_p);
 
   deallocate_event_chain (Vthis_command_keys);
   Vthis_command_keys = Qnil;
   Vthis_command_keys_tail = Qnil;
-
-  reset_current_events (command_builder);
 }
 
 static void
@@ -3570,7 +3553,7 @@ extract_this_command_keys_nth_mouse_event (int n)
        {
          if (!n)
            {
-             /* must copy to avoid an abort() in next_event_internal() */
+             /* must copy to avoid an ABORT() in next_event_internal() */
              if (!NILP (XEVENT_NEXT (event)))
                 return Fcopy_event (event, Qnil);
              else
@@ -3701,7 +3684,7 @@ lookup_command_event (struct command_builder *command_builder,
                 || e->event_type == button_release_event)
          e->event.button.modifiers |= XEMACS_MOD_META;
        else
-         abort ();
+         ABORT ();
 
        {
          int tckn = event_chain_count (Vthis_command_keys);
@@ -3786,6 +3769,35 @@ lookup_command_event (struct command_builder *command_builder,
   }
 }
 
+static int
+is_scrollbar_event (Lisp_Object event)
+{
+#ifdef HAVE_SCROLLBARS
+  Lisp_Object fun;
+
+  if (XEVENT (event)->event_type != misc_user_event)
+    return 0;
+  fun = XEVENT (event)->event.misc.function;
+
+  return (EQ (fun, Qscrollbar_line_up) ||
+         EQ (fun, Qscrollbar_line_down) ||
+         EQ (fun, Qscrollbar_page_up) ||
+         EQ (fun, Qscrollbar_page_down) ||
+         EQ (fun, Qscrollbar_to_top) ||
+         EQ (fun, Qscrollbar_to_bottom) ||
+         EQ (fun, Qscrollbar_vertical_drag) ||
+         EQ (fun, Qscrollbar_char_left) ||
+         EQ (fun, Qscrollbar_char_right) ||
+         EQ (fun, Qscrollbar_page_left) ||
+         EQ (fun, Qscrollbar_page_right) ||
+         EQ (fun, Qscrollbar_to_left) ||
+         EQ (fun, Qscrollbar_to_right) ||
+         EQ (fun, Qscrollbar_horizontal_drag));
+#else
+  return 0;
+#endif /* HAVE_SCROLLBARS */
+}
+
 static void
 execute_command_event (struct command_builder *command_builder,
                        Lisp_Object event)
@@ -3795,7 +3807,59 @@ execute_command_event (struct command_builder *command_builder,
   struct gcpro gcpro1;
 
   GCPRO1 (event); /* event may be freshly created */
-  reset_current_events (command_builder);
+
+  /* #### This call to is_scrollbar_event() isn't quite right, but
+     fixing properly it requires more work than can go into 21.4.
+     (We really need to split out menu, scrollbar, dialog, and other
+     types of events from misc-user, and put the remaining ones in a
+     new `user-eval' type that behaves like an eval event but is a
+     user event and thus has all of its semantics -- e.g. being
+     delayed during `accept-process-output' and similar wait states.)
+
+     The real issue here is that "user events" and "command events"
+     are not the same thing, but are very much confused in
+     event-stream.c.  User events are, essentially, any event that
+     should be delayed by accept-process-output, should terminate a
+     sit-for, etc. -- basically, any event that needs to be processed
+     synchronously with key and mouse events.  Command events are
+     those that participate in command building; scrollbar events
+     clearly don't belong because they should be transparent in a
+     sequence like C-x @ h <scrollbar-drag> x, which used to cause a
+     crash before checks similar to the is_scrollbar_event() call were
+     added.  Do other events belong with scrollbar events?  I'm not
+     sure; we need to categorize all misc-user events and see what
+     their semantics are.
+
+     (You might ask, why do scrollbar events need to be user events?
+     That's a good question.  The answer seems to be that they can
+     change point, and having this happen asynchronously would be a
+     very bad idea.  According to the "proper" functioning of
+     scrollbars, this should not happen, but XEmacs does not allow
+     point to go outside of the window.)
+
+     Scrollbar events and similar non-command events should obviously
+     not be recorded in this-command-keys, so we need to check for
+     this in next-event.
+
+     #### We call reset_current_events() twice in this function --
+     #### here, and later as a result of reset_this_command_keys().
+     #### This is almost certainly wrong; need to figure out what's
+     #### correct.
+
+     #### We need to figure out what's really correct w.r.t. scrollbar
+     #### events.  With these new fixes in, it actually works to do
+     #### C-x <scrollbar-drag> 5 2, but the key echo gets messed up
+     #### (starts over at 5).  We really need to be special-casing
+     #### scrollbar events at a lower level, and not really passing
+     #### them through the command builder at all.  (e.g. do scrollbar
+     #### events belong in macros???  doubtful; probably only the
+     #### point movement, if any, belongs, special-cased as a
+     #### pseudo-issued M-x goto-char command).  #### Need more work
+     #### here.  Do this when separating out scrollbar events.
+  */
+
+  if (!is_scrollbar_event (event))
+    reset_current_events (command_builder);
 
   switch (XEVENT (event)->event_type)
     {
@@ -3862,17 +3926,16 @@ execute_command_event (struct command_builder *command_builder,
 
     post_command_hook ();
 
-#if 0 /* #### here was an attempted fix that didn't work */
-    if (XEVENT (event)->event_type == misc_user_event)
-      ;
-    else
-#endif
-    if (!NILP (con->prefix_arg))
+    /* Console might have been deleted by command */
+    if (CONSOLE_LIVE_P (con) && !NILP (con->prefix_arg))
       {
        /* Commands that set the prefix arg don't update last-command, don't
           reset the echoing state, and don't go into keyboard macros unless
-          followed by another command. */
+          followed by another command.  Also don't quit here.  */
+       int speccount = specpdl_depth ();
+       specbind (Qinhibit_quit, Qt);
        maybe_echo_keys (command_builder, 0);
+       unbind_to (speccount, Qnil);
 
        /* If we're recording a keyboard macro, and the last command
           executed set a prefix argument, then decrement the pointer to
@@ -3891,7 +3954,10 @@ execute_command_event (struct command_builder *command_builder,
 
        /* Emacs 18 doesn't unconditionally clear the echoed keystrokes,
           so we don't either */
-       reset_this_command_keys (make_console (con), 0);
+
+       if (!is_scrollbar_event (event))
+         reset_this_command_keys (CONSOLE_LIVE_P (con) ? make_console (con)
+                                  : Qnil, 0);
       }
   }
 
@@ -3955,34 +4021,6 @@ post_command_hook (void)
     ("Error in `post-command-hook' (setting hook to nil)",
      Qpost_command_hook, 1);
 
-#if 0 /* FSF Emacs crap */
-  if (!NILP (Vdeferred_action_list))
-    call0 (Vdeferred_action_function);
-
-  if (NILP (Vunread_command_events)
-      && NILP (Vexecuting_macro)
-      && !NILP (Vpost_command_idle_hook)
-      && !NILP (Fsit_for (make_float ((double) post_command_idle_delay
-                                     / 1000000), Qnil)))
-  safe_run_hook_trapping_errors
-    ("Error in `post-command-idle-hook' (setting hook to nil)",
-     Qpost_command_idle_hook, 1);
-#endif /* FSF Emacs crap */
-
-#if 0 /* FSF Emacs */
-  if (!NILP (current_buffer->mark_active))
-    {
-      if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
-        {
-          current_buffer->mark_active = Qnil;
-         run_hook (intern ("deactivate-mark-hook"));
-        }
-      else if (current_buffer != prev_buffer ||
-              BUF_MODIFF (current_buffer) != prev_modiff)
-       run_hook (intern ("activate-mark-hook"));
-    }
-#endif /* FSF Emacs */
-
   /* #### Kludge!!! This is necessary to make sure that things
      are properly positioned even if post-command-hook moves point.
      #### There should be a cleaner way of handling this. */
@@ -3991,7 +4029,7 @@ post_command_hook (void)
 
 \f
 DEFUN ("dispatch-event", Fdispatch_event, 1, 1, 0, /*
-Given an event object as returned by `next-event', execute it.
+Given an event object EVENT as returned by `next-event', execute it.
 
 Key-press, button-press, and button-release events get accumulated
 until a complete key sequence (see `read-key-sequence') is reached,
@@ -4161,13 +4199,6 @@ Magic events are handled as necessary.
              command_builder->self_insert_countdown = 0;
            if (NILP (XCONSOLE (console)->prefix_arg)
                && NILP (Vexecuting_macro)
-#if 0
-               /* This was done in the days when there was no undo
-                  in the minibuffer.  If we don't disable this code,
-                  then each instance of "undo" undoes everything in
-                  the minibuffer. */
-               && !EQ (minibuf_window, Fselected_window (Qnil))
-#endif
                && command_builder->self_insert_countdown == 0)
              Fundo_boundary ();
 
@@ -4178,13 +4209,13 @@ Magic events are handled as necessary.
              }
            execute_command_event
               (command_builder,
-              internal_equal (event, command_builder-> most_current_event, 0)
+              internal_equal (event, command_builder->most_current_event, 0)
                ? event
                /* Use the translated event that was most recently seen.
                   This way, last-command-event becomes f1 instead of
                   the P from ESC O P.  But we must copy it, else we'll
                   lose when the command-builder events are deallocated. */
-               : Fcopy_event (command_builder-> most_current_event, Qnil));
+               : Fcopy_event (command_builder->most_current_event, Qnil));
          }
        break;
       }
@@ -4239,7 +4270,7 @@ Magic events are handled as necessary.
 DEFUN ("read-key-sequence", Fread_key_sequence, 1, 3, 0, /*
 Read a sequence of keystrokes or mouse clicks.
 Returns a vector of the event objects read.  The vector and the event
-objects it contains are freshly created (and will not be side-effected
+objects it contains are freshly created (and so will not be side-effected
 by subsequent calls to this function).
 
 The sequence read is sufficient to specify a non-prefix command starting
@@ -4247,19 +4278,17 @@ from the current local and global keymaps.  A C-g typed while in this
 function is treated like any other character, and `quit-flag' is not set.
 
 First arg PROMPT is a prompt string.  If nil, do not prompt specially.
-Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echoes
-as a continuation of the previous key.
 
-The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not
-convert the last event to lower case.  (Normally any upper case event
-is converted to lower case if the original event is undefined and the lower
-case equivalent is defined.) This argument is provided mostly for
-FSF compatibility; the equivalent effect can be achieved more generally
-by binding `retry-undefined-key-binding-unshifted' to nil around the
-call to `read-key-sequence'.
+Second optional arg CONTINUE-ECHO non-nil means this key echoes as a
+continuation of the previous key.
 
-A C-g typed while in this function is treated like any other character,
-and `quit-flag' is not set.
+Third optional arg DONT-DOWNCASE-LAST non-nil means do not convert the
+last event to lower case.  (Normally any upper case event is converted
+to lower case if the original event is undefined and the lower case
+equivalent is defined.) This argument is provided mostly for FSF
+compatibility; the equivalent effect can be achieved more generally by
+binding `retry-undefined-key-binding-unshifted' to nil around the call
+to `read-key-sequence'.
 
 If the user selects a menu item while we are prompting for a key-sequence,
 the returned value will be a vector of a single menu-selection event.
@@ -4267,8 +4296,8 @@ An error will be signalled if you pass this value to `lookup-key' or a
 related function.
 
 `read-key-sequence' checks `function-key-map' for function key
-sequences, where they wouldn't conflict with ordinary bindings.  See
-`function-key-map' for more details.
+sequences, where they wouldn't conflict with ordinary bindings.
+See `function-key-map' for more details.
 */
        (prompt, continue_echo, dont_downcase_last))
 {
@@ -4285,6 +4314,7 @@ sequences, where they wouldn't conflict with ordinary bindings.  See
   struct gcpro gcpro1;
   GCPRO1 (event);
 
+  record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
   if (!NILP (prompt))
     CHECK_STRING (prompt);
   /* else prompt = Fkeymap_prompt (current_buffer->keymap); may GC */
@@ -4404,10 +4434,10 @@ dribble_out_event (Lisp_Object event)
 
 DEFUN ("open-dribble-file", Fopen_dribble_file, 1, 1,
        "FOpen dribble file: ", /*
-Start writing all keyboard characters to a dribble file called FILE.
-If FILE is nil, close any open dribble file.
+Start writing all keyboard characters to a dribble file called FILENAME.
+If FILENAME is nil, close any open dribble file.
 */
-       (file))
+       (filename))
 {
   /* This function can GC */
   /* XEmacs change: always close existing dribble file. */
@@ -4417,12 +4447,12 @@ If FILE is nil, close any open dribble file.
       Lstream_close (XLSTREAM (Vdribble_file));
       Vdribble_file = Qnil;
     }
-  if (!NILP (file))
+  if (!NILP (filename))
     {
       int fd;
 
-      file = Fexpand_file_name (file, Qnil);
-      fd = open ((char*) XSTRING_DATA (file),
+      filename = Fexpand_file_name (filename, Qnil);
+      fd = open ((char*) XSTRING_DATA (filename),
                 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
                 CREAT_MODE);
       if (fd < 0)
@@ -4451,7 +4481,7 @@ CONSOLE defaults to the selected console if omitted.
   /* This junk is so that timestamps don't get to be negative, but contain
      as many bits as this particular emacs will allow.
    */
-  return make_int (((1L << (VALBITS - 1)) - 1) & tiempo);
+  return make_int (EMACS_INT_MAX & tiempo);
 }
 
 \f
@@ -4500,10 +4530,6 @@ syms_of_event_stream (void)
   defsymbol (&Qpre_idle_hook, "pre-idle-hook");
   defsymbol (&Qhandle_pre_motion_command, "handle-pre-motion-command");
   defsymbol (&Qhandle_post_motion_command, "handle-post-motion-command");
-#if 0 /* FSF Emacs crap */
-  defsymbol (&Qpost_command_idle_hook, "post-command-idle-hook");
-  defsymbol (&Qdeferred_action_function, "deferred-action-function");
-#endif
   defsymbol (&Qretry_undefined_key_binding_unshifted,
             "retry-undefined-key-binding-unshifted");
   defsymbol (&Qauto_show_make_point_visible,
@@ -4538,12 +4564,12 @@ vars_of_event_stream (void)
   Vthis_command_keys = Qnil;
   staticpro (&Vthis_command_keys);
   Vthis_command_keys_tail = Qnil;
-  pdump_wire (&Vthis_command_keys_tail);
+  dump_add_root_object (&Vthis_command_keys_tail);
 
   command_event_queue = Qnil;
   staticpro (&command_event_queue);
   command_event_queue_tail = Qnil;
-  pdump_wire (&command_event_queue_tail);
+  dump_add_root_object (&command_event_queue_tail);
 
   Vlast_selected_frame = Qnil;
   staticpro (&Vlast_selected_frame);
@@ -4602,41 +4628,6 @@ used by the window manager, so it is up to the user to set it.
 */ );
   focus_follows_mouse = 0;
 
-#if 0 /* FSF Emacs crap */
-  /* Ill-conceived because it's not run in all sorts of cases
-     where XEmacs is blocking.  That's what `pre-idle-hook'
-     is designed to solve. */
-  xxDEFVAR_LISP ("post-command-idle-hook", &Vpost_command_idle_hook /*
-Normal hook run after each command is executed, if idle.
-`post-command-idle-delay' specifies a time in microseconds that XEmacs
-must be idle for in order for the functions on this hook to be called.
-Errors running the hook are caught and ignored.
-*/ );
-  Vpost_command_idle_hook = Qnil;
-
-  xxDEFVAR_INT ("post-command-idle-delay", &post_command_idle_delay /*
-Delay time before running `post-command-idle-hook'.
-This is measured in microseconds.
-*/ );
-  post_command_idle_delay = 5000;
-
-  /* Random FSFmacs crap.  There is absolutely nothing to gain,
-     and a great deal to lose, in using this in place of just
-     setting `post-command-hook'. */
-  xxDEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list /*
-List of deferred actions to be performed at a later time.
-The precise format isn't relevant here; we just check whether it is nil.
-*/ );
-  Vdeferred_action_list = Qnil;
-
-  xxDEFVAR_LISP ("deferred-action-function", &Vdeferred_action_function /*
-Function to call to handle deferred actions, after each command.
-This function is called with no arguments after each command
-whenever `deferred-action-list' is non-nil.
-*/ );
-  Vdeferred_action_function = Qnil;
-#endif /* FSF Emacs crap */
-
   DEFVAR_LISP ("last-command-event", &Vlast_command_event /*
 Last keyboard or mouse button event that was part of a command.  This
 variable is off limits: you may not set its value or modify the event that
@@ -4815,9 +4806,22 @@ This means that you can release the modifier key before pressing down
 the key that you wish to be modified.  Although this is non-standard
 behavior, it is recommended because it reduces the strain on your hand,
 thus reducing the incidence of the dreaded Emacs-pinky syndrome.
+
+Modifier keys are sticky within the inverval specified by
+`modifier-keys-sticky-time'.
 */ );
   modifier_keys_are_sticky = 0;
 
+  DEFVAR_LISP ("modifier-keys-sticky-time", &Vmodifier_keys_sticky_time /*
+*Modifier keys are sticky within this many milliseconds.
+If you don't want modifier keys sticking to be bounded, set this to
+non-integer value.
+
+This variable has no effect when `modifier-keys-are-sticky' is nil.
+Currently only implemented under X Window System.
+*/ );
+  Vmodifier_keys_sticky_time = make_int (500);
+
 #ifdef HAVE_XIM
   DEFVAR_LISP ("composed-character-default-binding",
                &Vcomposed_character_default_binding /*
@@ -4900,6 +4904,11 @@ init_event_stream (void)
        init_event_Xt_late ();
       else
 #endif
+#ifdef HAVE_GTK
+      if (!strcmp (display_use, "gtk"))
+       init_event_gtk_late ();
+      else
+#endif
 #ifdef HAVE_MS_WINDOWS
       if (!strcmp (display_use, "mswindows"))
        init_event_mswindows_late ();
@@ -4936,20 +4945,23 @@ useful testcases for v18/v19 compatibility:
 (global-set-key "\^Q" 'foo)
 
 without the read-key-sequence:
-  ^Q           ==>  (65 17 65 [... ^Q] [^Q])
-  ^U^U^Q       ==>  (65 17 65 [... ^U ^U ^Q] [^U ^U ^Q])
-  ^U^U^U^G^Q   ==>  (65 17 65 [... ^U ^U ^U ^G ^Q] [^Q])
+  ^Q           ==>  (?A ?\^Q ?A [... ^Q] [^Q])
+  ^U^U^Q       ==>  (?A ?\^Q ?A [... ^U ^U ^Q] [^U ^U ^Q])
+  ^U^U^U^G^Q   ==>  (?A ?\^Q ?A [... ^U ^U ^U ^G ^Q] [^Q])
 
 with the read-key-sequence:
-  ^Qb          ==>  (65 [b] 17 98 [... ^Q b] [b])
-  ^U^U^Qb      ==>  (65 [b] 17 98 [... ^U ^U ^Q b] [b])
-  ^U^U^U^G^Qb  ==>  (65 [b] 17 98 [... ^U ^U ^U ^G ^Q b] [b])
+  ^Qb          ==>  (?A [b] ?\^Q ?b [... ^Q b] [b])
+  ^U^U^Qb      ==>  (?A [b] ?\^Q ?b [... ^U ^U ^Q b] [b])
+  ^U^U^U^G^Qb  ==>  (?A [b] ?\^Q ?b [... ^U ^U ^U ^G ^Q b] [b])
 
 ;the evi-mode command "4dlj.j.j.j.j.j." is also a good testcase (gag)
 
 ;(setq x (list (read-char) quit-flag))^J^G
 ;(let ((inhibit-quit t)) (setq x (list (read-char) quit-flag)))^J^G
 ;for BOTH, x should get set to (7 t), but no result should be printed.
+;; #### According to the doc of quit-flag, second test should return
+;; (?\^G nil).  Accidentaly XEmacs returns correct value.  However,
+;; XEmacs 21.1.12 and 21.2.36 both fails on first test.
 
 ;also do this: make two frames, one viewing "*scratch*", the other "foo".
 ;in *scratch*, type (sit-for 20)^J
@@ -4969,9 +4981,9 @@ with the read-key-sequence:
          (quit c))
        (read-char)))
 
- (tst)^Ja^G    ==>  ((quit) 97) with no signal
- (tst)^J^Ga    ==>  ((quit) 97) with no signal
- (tst)^Jabc^G  ==>  ((quit) 97) with no signal, and "bc" inserted in buffer
+ (tst)^Ja^G    ==>  ((quit) ?a) with no signal
+ (tst)^J^Ga    ==>  ((quit) ?a) with no signal
+ (tst)^Jabc^G  ==>  ((quit) ?a) with no signal, and "bc" inserted in buffer
 
 ; with sit-for only do the 2nd test.
 ; Do all 3 tests with (accept-process-output nil 20)