XEmacs 21.2.36 "Notos"
[chise/xemacs-chise.git.1] / src / event-stream.c
index 81f5f02..0d09051 100644 (file)
@@ -23,6 +23,20 @@ Boston, MA 02111-1307, USA.  */
 
 /* Synched up with: Not in FSF. */
 
+/* Authorship:
+
+   Created 1991 by Jamie Zawinski.
+   A great deal of work over the ages by Ben Wing (Mule-ization for 19.12,
+     device abstraction for 19.12/19.13, async timers for 19.14,
+     rewriting of focus code for 19.12, pre-idle hook for 19.12,
+     redoing of signal and quit handling for 19.9 and 19.12,
+     misc-user events to clean up menu/scrollbar handling for 19.11,
+     function-key-map/key-translation-map/keyboard-translate-table for
+     19.13/19.14, open-dribble-file for 19.13, much other cleanup).
+   focus-follows-mouse from Chuck Thompson, 1995.
+   XIM stuff by Martin Buchholz, c. 1996?.
+*/
+
 /* This file has been Mule-ized. */
 
 /*
@@ -38,8 +52,6 @@ Boston, MA 02111-1307, USA.  */
 /* TODO:
    This stuff is way too hard to maintain - needs rework.
 
-   (global-set-key "\C-p" global-map) causes a crash - need recursion check.
-
    C-x @ h <scrollbar-drag> x causes a crash.
 
    The command builder should deal only with key and button events.
@@ -62,14 +74,6 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include "lisp.h"
 
-#ifdef HAVE_X_WINDOWS
-#include "console-x.h"         /* for menu accelerators ... */
-#include "gui-x.h"
-#include "../lwlib/lwlib.h"
-#else
-#define lw_menu_active 0
-#endif
-
 #include "blocktype.h"
 #include "buffer.h"
 #include "commands.h"
@@ -81,6 +85,7 @@ Boston, MA 02111-1307, USA.  */
 #include "keymap.h"
 #include "lstream.h"
 #include "macros.h"            /* for defining_keyboard_macro */
+#include "menubar.h"            /* #### for evil kludges. */
 #include "process.h"
 #include "window.h"
 
@@ -107,21 +112,24 @@ Lisp_Object Qcommand_event_p;
 Lisp_Object Vpre_command_hook, Vpost_command_hook;
 Lisp_Object Qpre_command_hook, Qpost_command_hook;
 
+/* See simple.el */
+Lisp_Object Qhandle_pre_motion_command, Qhandle_post_motion_command;
+
 /* Hook run when XEmacs is about to be idle. */
 Lisp_Object Qpre_idle_hook, Vpre_idle_hook;
 
 /* Control gratuitous keyboard focus throwing. */
 int focus_follows_mouse;
 
-#ifdef ILL_CONCEIVED_HOOK
+int modifier_keys_are_sticky;
+
+#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;
-#endif /* ILL_CONCEIVED_HOOK */
 
-#ifdef DEFERRED_ACTION_CRAP
 /* 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;
@@ -129,7 +137,7 @@ 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 /* DEFERRED_ACTION_CRAP */
+#endif /* FSF Emacs crap */
 
 /* Non-nil disable property on a command means
    do not execute it; call disabled-command-hook's value instead. */
@@ -164,13 +172,20 @@ Lisp_Object Vunread_command_event; /* obsoleteness support */
 static Lisp_Object Qunread_command_events, Qunread_command_event;
 
 /* Previous command, represented by a Lisp object.
-   Does not include prefix commands and arg setting commands */
+   Does not include prefix commands and arg setting commands. */
 Lisp_Object Vlast_command;
 
+/* Contents of this-command-properties for the last command. */
+Lisp_Object Vlast_command_properties;
+
 /* If a command sets this, the value goes into
-   previous-command for the next command. */
+   last-command for the next command. */
 Lisp_Object Vthis_command;
 
+/* If a command sets this, the value goes into
+   last-command-properties for the next command. */
+Lisp_Object Vthis_command_properties;
+
 /* The value of point when the last command was executed.  */
 Bufpos last_point_position;
 
@@ -235,29 +250,7 @@ int recent_keys_ring_index;
    recent-keys. */
 int inhibit_input_event_recording;
 
-/* prefix key(s) that must match in order to activate menu.
-   This is ugly.  fix me.
-   */
-Lisp_Object Vmenu_accelerator_prefix;
-
-/* list of modifier keys to match accelerator for top level menus */
-Lisp_Object Vmenu_accelerator_modifiers;
-
-/* whether menu accelerators are enabled */
-Lisp_Object Vmenu_accelerator_enabled;
-
-/* keymap for auxiliary menu accelerator functions */
-Lisp_Object Vmenu_accelerator_map;
-
-Lisp_Object Qmenu_force;
-Lisp_Object Qmenu_fallback;
-Lisp_Object Qmenu_quit;
-Lisp_Object Qmenu_up;
-Lisp_Object Qmenu_down;
-Lisp_Object Qmenu_left;
-Lisp_Object Qmenu_right;
-Lisp_Object Qmenu_select;
-Lisp_Object Qmenu_escape;
+Lisp_Object Qself_insert_defer_undo;
 
 /* this is in keymap.c */
 extern Lisp_Object Fmake_keymap (Lisp_Object name);
@@ -286,60 +279,6 @@ external_debugging_print_event (char *event_description, Lisp_Object event)
 /* The callback routines for the window system or terminal driver */
 struct event_stream *event_stream;
 
-/* This structure is what we use to encapsulate the state of a command sequence
-   being composed; key events are executed by adding themselves to the command
-   builder; if the command builder is then complete (does not still represent
-   a prefix key sequence) it executes the corresponding command.
- */
-struct command_builder
-{
-  struct lcrecord_header header;
-  Lisp_Object console; /* back pointer to the console this command
-                         builder is for */
-  /* Qnil, or a Lisp_Event representing the first event read
-   *  after the last command completed.  Threaded. */
-  /* #### NYI */
-  Lisp_Object prefix_events;
-  /* Qnil, or a Lisp_Event representing event in the current
-   *  keymap-lookup sequence.  Subsequent events are threaded via
-   *  the event's next slot */
-  Lisp_Object current_events;
-  /* Last elt of above  */
-  Lisp_Object most_current_event;
-  /* Last elt before function map code took over. What this means is:
-     All prefixes up to (but not including) this event have non-nil
-     bindings, but the prefix including this event has a nil binding.
-     Any events in the chain after this one were read solely because
-     we're part of a possible function key.  If we end up with
-     something that's not part of a possible function key, we have to
-     unread all of those events. */
-  Lisp_Object last_non_munged_event;
-  /* One set of values for function-key-map, one for key-translation-map */
-  struct munging_key_translation
-  {
-    /* First event that can begin a possible function key sequence
-       (to be translated according to function-key-map).  Normally
-       this is the first event in the chain.  However, once we've
-       translated a sequence through function-key-map, this will point
-       to the first event after the translated sequence: we don't ever
-       want to translate any events twice through function-key-map, or
-       things could get really screwed up (e.g. if the user created a
-       translation loop).  If this is nil, then the next-read event is
-       the first that can begin a function key sequence. */
-    Lisp_Object first_mungeable_event;
-  } munge_me[2];
-
-  Bufbyte *echo_buf;
-  Bytecount echo_buf_length;          /* size of echo_buf */
-  Bytecount echo_buf_index;           /* index into echo_buf
-                                      * -1 before doing echoing for new cmd */
-  /* Self-insert-command is magic in that it doesn't always push an undo-
-     boundary: up to 20 consecutive self-inserts can happen before an undo-
-     boundary is pushed.  This variable is that counter.
-     */
-  int self_insert_countdown;
-};
-
 static void echo_key_event (struct command_builder *, Lisp_Object event);
 static void maybe_kbd_translate (Lisp_Object event);
 
@@ -382,7 +321,6 @@ static Lisp_Object recursive_sit_for;
   XRECORD (x, command_builder, struct command_builder)
 #define XSETCOMMAND_BUILDER(x, p) XSETRECORD (x, p, command_builder)
 #define COMMAND_BUILDERP(x) RECORDP (x, command_builder)
-#define GC_COMMAND_BUILDERP(x) GC_RECORDP (x, command_builder)
 #define CHECK_COMMAND_BUILDER(x) CHECK_RECORD (x, command_builder)
 
 static Lisp_Object
@@ -506,8 +444,15 @@ event_stream_event_pending_p (int user)
   return event_stream && event_stream->event_pending_p (user);
 }
 
+static void
+event_stream_force_event_pending (struct frame* f)
+{
+  if (event_stream->force_event_pending)
+    event_stream->force_event_pending (f);
+}
+
 static int
-maybe_read_quit_event (struct Lisp_Event *event)
+maybe_read_quit_event (Lisp_Event *event)
 {
   /* A C-g that came from `sigint_happened' will always come from the
      controlling terminal.  If that doesn't exist, however, then the
@@ -534,7 +479,7 @@ maybe_read_quit_event (struct Lisp_Event *event)
 }
 
 void
-event_stream_next_event (struct Lisp_Event *event)
+event_stream_next_event (Lisp_Event *event)
 {
   Lisp_Object event_obj;
 
@@ -578,7 +523,7 @@ event_stream_next_event (struct Lisp_Event *event)
 }
 
 void
-event_stream_handle_magic_event (struct Lisp_Event *event)
+event_stream_handle_magic_event (Lisp_Event *event)
 {
   check_event_stream_ok (EVENT_STREAM_READ);
   event_stream->handle_magic_event_cb (event);
@@ -621,7 +566,7 @@ event_stream_unselect_console (struct console *con)
 }
 
 void
-event_stream_select_process (struct Lisp_Process *proc)
+event_stream_select_process (Lisp_Process *proc)
 {
   check_event_stream_ok (EVENT_STREAM_PROCESS);
   if (!get_process_selected_p (proc))
@@ -632,7 +577,7 @@ event_stream_select_process (struct Lisp_Process *proc)
 }
 
 void
-event_stream_unselect_process (struct Lisp_Process *proc)
+event_stream_unselect_process (Lisp_Process *proc)
 {
   check_event_stream_ok (EVENT_STREAM_PROCESS);
   if (get_process_selected_p (proc))
@@ -665,6 +610,14 @@ event_stream_quit_p (void)
     event_stream->quit_p_cb ();
 }
 
+static int
+event_stream_current_event_timestamp (struct console *c)
+{
+  if (event_stream && event_stream->current_event_timestamp_cb)
+    return event_stream->current_event_timestamp_cb (c);
+  else
+    return 0;
+}
 
 \f
 /**********************************************************************/
@@ -733,7 +686,10 @@ maybe_echo_keys (struct command_builder *command_builder, int no_snooze)
 
   if (minibuf_level == 0
       && echo_keystrokes > 0.0
-      && !lw_menu_active)
+#if defined (HAVE_X_WINDOWS) && defined (LWLIB_MENUBARS_LUCID)
+      && !x_kludge_lw_menu_active ()
+#endif
+      )
     {
       if (!no_snooze)
        {
@@ -796,7 +752,7 @@ maybe_kbd_translate (Lisp_Object event)
        }
       else if (CHARP (traduit))
        {
-         struct Lisp_Event ev2;
+         Lisp_Event ev2;
 
          /* This used to call Fcharacter_to_event() directly into EVENT,
             but that can eradicate timestamps and other such stuff.
@@ -819,6 +775,17 @@ maybe_kbd_translate (Lisp_Object event)
          XEVENT (event)->event.key.keysym = traduit;
          did_translate = 1;
        }
+      else if (CHARP (traduit))
+       {
+         Lisp_Event ev2;
+
+         zero_event (&ev2);
+         character_to_event (XCHAR (traduit), &ev2,
+                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 1, 1);
+         XEVENT (event)->event.key.keysym = ev2.event.key.keysym;
+         XEVENT (event)->event.key.modifiers |= ev2.event.key.modifiers;
+         did_translate = 1;
+       }
     }
 
 #ifdef DEBUG_XEMACS
@@ -1105,7 +1072,7 @@ static Lisp_Object Vtimeout_free_list;
 static Lisp_Object
 mark_timeout (Lisp_Object obj)
 {
-  struct Lisp_Timeout *tm = XTIMEOUT (obj);
+  Lisp_Timeout *tm = XTIMEOUT (obj);
   mark_object (tm->function);
   return tm->object;
 }
@@ -1114,7 +1081,7 @@ mark_timeout (Lisp_Object obj)
 static void
 print_timeout (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 {
-  CONST struct Lisp_Timeout *t = XTIMEOUT (obj);
+  const Lisp_Timeout *t = XTIMEOUT (obj);
   char buf[64];
 
   sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (timeout) 0x%lx>",
@@ -1123,13 +1090,14 @@ print_timeout (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 }
 
 static const struct lrecord_description timeout_description[] = {
-  { XD_LISP_OBJECT, offsetof(struct Lisp_Timeout, function), 2 },
+  { XD_LISP_OBJECT, offsetof (Lisp_Timeout, function) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Timeout, object) },
   { XD_END }
 };
 
 DEFINE_LRECORD_IMPLEMENTATION ("timeout", timeout,
                               mark_timeout, print_timeout,
-                              0, 0, 0, timeout_description, struct Lisp_Timeout);
+                              0, 0, 0, timeout_description, Lisp_Timeout);
 
 /* Generate a timeout and return its ID. */
 
@@ -1140,7 +1108,7 @@ event_stream_generate_wakeup (unsigned int milliseconds,
                              int async_p)
 {
   Lisp_Object op = allocate_managed_lcrecord (Vtimeout_free_list);
-  struct Lisp_Timeout *timeout = XTIMEOUT (op);
+  Lisp_Timeout *timeout = XTIMEOUT (op);
   EMACS_TIME current_time;
   EMACS_TIME interval;
 
@@ -1189,7 +1157,7 @@ event_stream_resignal_wakeup (int interval_id, int async_p,
                              Lisp_Object *function, Lisp_Object *object)
 {
   Lisp_Object op = Qnil, rest;
-  struct Lisp_Timeout *timeout;
+  Lisp_Timeout *timeout;
   Lisp_Object *timeout_list;
   struct gcpro gcpro1;
   int id;
@@ -1262,7 +1230,7 @@ event_stream_resignal_wakeup (int interval_id, int async_p,
 void
 event_stream_disable_wakeup (int id, int async_p)
 {
-  struct Lisp_Timeout *timeout = 0;
+  Lisp_Timeout *timeout = 0;
   Lisp_Object rest;
   Lisp_Object *timeout_list;
 
@@ -1297,7 +1265,7 @@ event_stream_disable_wakeup (int id, int async_p)
 static int
 event_stream_wakeup_pending_p (int id, int async_p)
 {
-  struct Lisp_Timeout *timeout;
+  Lisp_Timeout *timeout;
   Lisp_Object rest;
   Lisp_Object timeout_list;
   int found = 0;
@@ -2014,7 +1982,7 @@ next_event_internal (Lisp_Object target_event, int allow_queued)
     }
   else
     {
-      struct Lisp_Event *e = XEVENT (target_event);
+      Lisp_Event *e = XEVENT (target_event);
 
       /* The command_event_queue was empty.  Wait for an event. */
       event_stream_next_event (e);
@@ -2088,7 +2056,12 @@ The next available event will be
 
 -- any events in `unread-command-events' or `unread-command-event'; else
 -- the next event in the currently executing keyboard macro, if any; else
--- an event queued by `enqueue-eval-event', if any; else
+-- an event queued by `enqueue-eval-event', if any, or any similar event
+   queued internally, such as a misc-user event. (For example, when an item
+   is selected from a menu or from a `question'-type dialog box, the item's
+   callback is not immediately executed, but instead a misc-user event
+   is generated and placed onto this queue; when it is dispatched, the
+   callback is executed.) Else
 -- the next available event from the window system or terminal driver.
 
 In the last case, this function will block until an event is available.
@@ -2121,9 +2094,6 @@ The returned event will be one of the following types:
     XCOMMAND_BUILDER (con->command_builder);
   int store_this_key = 0;
   struct gcpro gcpro1;
-#ifdef LWLIB_MENUBARS_LUCID
-  extern int in_menu_callback;  /* defined in menubar-x.c */
-#endif /* LWLIB_MENUBARS_LUCID */
 
   GCPRO1 (event);
   /* DO NOT do QUIT anywhere within this function or the functions it calls.
@@ -2399,6 +2369,56 @@ but it also makes a provision for displaying keystrokes in the echo area.
   return event;
 }
 
+DEFUN ("dispatch-non-command-events", Fdispatch_non_command_events, 0, 0, 0, /*
+Dispatch any pending "magic" events.
+
+This function is useful for forcing the redisplay of native
+widgets. Normally these are redisplayed through a native window-system
+event encoded as magic event, rather than by the redisplay code.  This
+function does not call redisplay or do any of the other things that
+`next-event' does.
+*/
+       ())
+{
+  /* This function can GC */
+  Lisp_Object event = Qnil;
+  struct gcpro gcpro1;
+  GCPRO1 (event);
+  event = Fmake_event (Qnil, Qnil);
+
+  /* Make sure that there will be something in the native event queue
+     so that externally managed things (e.g. widgets) get some CPU
+     time. */
+  event_stream_force_event_pending (selected_frame ());
+
+  while (event_stream_event_pending_p (0))
+    {
+      QUIT; /* next_event_internal() does not QUIT. */
+
+      /* We're a generator of the command_event_queue, so we can't be a
+        consumer as well.  Also, we have no reason to consult the
+        command_event_queue; there are only user and eval-events there,
+        and we'd just have to put them back anyway.
+       */
+      next_event_internal (event, 0); /* blocks */
+      /* See the comment in accept-process-output about Vquit_flag */
+      if (XEVENT_TYPE (event) == magic_event ||
+         XEVENT_TYPE (event) == timeout_event ||
+         XEVENT_TYPE (event) == process_event ||
+         XEVENT_TYPE (event) == pointer_motion_event)
+       execute_internal_event (event);
+      else
+       {
+         enqueue_command_event_1 (event);
+         break;
+       }
+    }
+
+  Fdeallocate_event (event);
+  UNGCPRO;
+  return Qnil;
+}
+
 static void
 reset_current_events (struct command_builder *command_builder)
 {
@@ -2879,10 +2899,8 @@ If sit-for is called from within a process filter function or timer
   return result;
 }
 
-/* This handy little function is used by xselect.c and energize.c to
-   wait for replies from processes that aren't really processes (that is,
-   the X server and the Energize server).
- */
+/* This handy little function is used by select-x.c to wait for replies
+   from processes that aren't really processes (e.g. the X server) */
 void
 wait_delaying_user_input (int (*predicate) (void *arg), void *predicate_arg)
 {
@@ -3036,7 +3054,7 @@ execute_internal_event (Lisp_Object event)
 
     case timeout_event:
       {
-       struct Lisp_Event *e = XEVENT (event);
+       Lisp_Event *e = XEVENT (event);
        if (!NILP (e->event.timeout.function))
          call1 (e->event.timeout.function,
                 e->event.timeout.object);
@@ -3094,514 +3112,6 @@ command_builder_find_leaf_1 (struct command_builder *builder)
   return event_binding (event0, 1);
 }
 
-#if defined(HAVE_X_WINDOWS) && defined(LWLIB_MENUBARS_LUCID)
-static void
-menu_move_up (void)
-{
-  widget_value *current, *prev;
-  widget_value *entries;
-
-  current = lw_get_entries (False);
-  entries = lw_get_entries (True);
-  prev = NULL;
-  if (current != entries)
-    {
-      while (entries != current)
-       {
-         if (entries->name /*&& entries->enabled*/) prev = entries;
-         entries = entries->next;
-         assert (entries);
-       }
-    }
-
-  if (!prev)
-    /* move to last item */
-    {
-      while (entries->next)
-       {
-         if (entries->name /*&& entries->enabled*/) prev = entries;
-         entries = entries->next;
-       }
-      if (prev)
-       {
-         if (entries->name /*&& entries->enabled*/)
-           prev = entries;
-       }
-      else
-       {
-         /* no selectable items in this menu, pop up to previous level */
-         lw_pop_menu ();
-         return;
-       }
-    }
-  lw_set_item (prev);
-}
-
-static void
-menu_move_down (void)
-{
-  widget_value *current;
-  widget_value *new;
-
-  current = lw_get_entries (False);
-  new = current;
-
-  while (new->next)
-    {
-      new = new->next;
-      if (new->name /*&& new->enabled*/) break;
-    }
-
-  if (new==current||!(new->name/*||new->enabled*/))
-    {
-      new = lw_get_entries (True);
-      while (new!=current)
-       {
-         if (new->name /*&& new->enabled*/) break;
-         new = new->next;
-       }
-      if (new==current&&!(new->name /*|| new->enabled*/))
-       {
-         lw_pop_menu ();
-         return;
-       }
-    }
-
-  lw_set_item (new);
-}
-
-static void
-menu_move_left (void)
-{
-  int level = lw_menu_level ();
-  int l = level;
-  widget_value *current;
-
-  while (level >= 3)
-    {
-      --level;
-      lw_pop_menu ();
-    }
-  menu_move_up ();
-  current = lw_get_entries (False);
-  if (l > 2 && current->contents)
-    lw_push_menu (current->contents);
-}
-
-static void
-menu_move_right (void)
-{
-  int level = lw_menu_level ();
-  int l = level;
-  widget_value *current;
-
-  while (level >= 3)
-    {
-      --level;
-      lw_pop_menu ();
-    }
-  menu_move_down ();
-  current = lw_get_entries (False);
-  if (l > 2 && current->contents)
-    lw_push_menu (current->contents);
-}
-
-static void
-menu_select_item (widget_value *val)
-{
-  if (val == NULL)
-    val = lw_get_entries (False);
-
-  /* is match a submenu? */
-
-  if (val->contents)
-    {
-      /* enter the submenu */
-
-      lw_set_item (val);
-      lw_push_menu (val->contents);
-    }
-  else
-    {
-      /* Execute the menu entry by calling the menu's `select'
-        callback function
-        */
-      lw_kill_menus (val);
-    }
-}
-
-static Lisp_Object
-command_builder_operate_menu_accelerator (struct command_builder *builder)
-{
-  /* this function can GC */
-
-  struct console *con = XCONSOLE (Vselected_console);
-  Lisp_Object evee = builder->most_current_event;
-  Lisp_Object binding;
-  widget_value *entries;
-
-  extern int lw_menu_accelerate; /* lwlib.c */
-
-#if 0
-  {
-    int i;
-    Lisp_Object t;
-    char buf[50];
-
-    t = builder->current_events;
-    i = 0;
-    while (!NILP (t))
-      {
-       i++;
-       sprintf (buf,"OPERATE (%d): ",i);
-       write_c_string (buf, Qexternal_debugging_output);
-       print_internal (t, Qexternal_debugging_output, 1);
-       write_c_string ("\n", Qexternal_debugging_output);
-       t = XEVENT_NEXT (t);
-      }
-  }
-#endif /* 0 */
-
-  /* menu accelerator keys don't go into keyboard macros */
-  if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
-    con->kbd_macro_ptr = con->kbd_macro_end;
-
-  /* don't echo menu accelerator keys */
-  /*reset_key_echo (builder, 1);*/
-
-  if (!lw_menu_accelerate)
-    {
-      /* `convert' mouse display to keyboard display
-        by entering the open submenu
-        */
-      entries = lw_get_entries (False);
-      if (entries->contents)
-       {
-         lw_push_menu (entries->contents);
-         lw_display_menu (CurrentTime);
-       }
-    }
-
-  /* compare event to the current menu accelerators */
-
-  entries=lw_get_entries (True);
-
-  while (entries)
-    {
-      Lisp_Object accel;
-      VOID_TO_LISP (accel, entries->accel);
-      if (entries->name && !NILP (accel))
-       {
-         if (event_matches_key_specifier_p (XEVENT (evee), accel))
-           {
-             /* a match! */
-
-             menu_select_item (entries);
-
-             if (lw_menu_active) lw_display_menu (CurrentTime);
-
-             reset_this_command_keys (Vselected_console, 1);
-             /*reset_command_builder_event_chain (builder);*/
-             return Vmenu_accelerator_map;
-           }
-       }
-      entries = entries->next;
-    }
-
-  /* try to look up event in menu-accelerator-map */
-
-  binding = event_binding_in (evee, Vmenu_accelerator_map, 1);
-
-  if (NILP (binding))
-    {
-      /* beep at user for undefined key */
-      return Qnil;
-    }
-  else
-    {
-      if (EQ (binding, Qmenu_quit))
-       {
-         /* turn off menus and set quit flag */
-         lw_kill_menus (NULL);
-         Vquit_flag = Qt;
-       }
-      else if (EQ (binding, Qmenu_up))
-       {
-         int level = lw_menu_level ();
-         if (level > 2)
-           menu_move_up ();
-       }
-      else if (EQ (binding, Qmenu_down))
-       {
-         int level = lw_menu_level ();
-         if (level > 2)
-           menu_move_down ();
-         else
-           menu_select_item (NULL);
-       }
-      else if (EQ (binding, Qmenu_left))
-       {
-         int level = lw_menu_level ();
-         if (level > 3)
-           {
-             lw_pop_menu ();
-             lw_display_menu (CurrentTime);
-           }
-         else
-           menu_move_left ();
-       }
-      else if (EQ (binding, Qmenu_right))
-       {
-         int level = lw_menu_level ();
-         if (level > 2 &&
-             lw_get_entries (False)->contents)
-           {
-             widget_value *current = lw_get_entries (False);
-             if (current->contents)
-               menu_select_item (NULL);
-           }
-         else
-           menu_move_right ();
-       }
-      else if (EQ (binding, Qmenu_select))
-       menu_select_item (NULL);
-      else if (EQ (binding, Qmenu_escape))
-       {
-         int level = lw_menu_level ();
-
-         if (level > 2)
-           {
-             lw_pop_menu ();
-             lw_display_menu (CurrentTime);
-           }
-         else
-           {
-             /* turn off menus quietly */
-             lw_kill_menus (NULL);
-           }
-       }
-      else if (KEYMAPP (binding))
-       {
-         /* prefix key */
-         reset_this_command_keys (Vselected_console, 1);
-         /*reset_command_builder_event_chain (builder);*/
-         return binding;
-       }
-      else
-       {
-         /* turn off menus and execute binding */
-         lw_kill_menus (NULL);
-         reset_this_command_keys (Vselected_console, 1);
-         /*reset_command_builder_event_chain (builder);*/
-         return binding;
-       }
-    }
-
-  if (lw_menu_active) lw_display_menu (CurrentTime);
-
-  reset_this_command_keys (Vselected_console, 1);
-  /*reset_command_builder_event_chain (builder);*/
-
-  return Vmenu_accelerator_map;
-}
-
-static Lisp_Object
-menu_accelerator_junk_on_error (Lisp_Object errordata, Lisp_Object ignored)
-{
-  Vmenu_accelerator_prefix    = Qnil;
-  Vmenu_accelerator_modifiers = Qnil;
-  Vmenu_accelerator_enabled   = Qnil;
-  if (!NILP (errordata))
-    {
-      Lisp_Object args[2];
-
-      args[0] = build_string ("Error in menu accelerators (setting to nil)");
-      /* #### This should call
-        (with-output-to-string (display-error errordata))
-        but that stuff is all in Lisp currently. */
-      args[1] = errordata;
-      warn_when_safe_lispobj
-       (Qerror, Qwarning,
-        emacs_doprnt_string_lisp ((CONST Bufbyte *) "%s: %s",
-                                  Qnil, -1, 2, args));
-    }
-
-  return Qnil;
-}
-
-static Lisp_Object
-menu_accelerator_safe_compare (Lisp_Object event0)
-{
-  if (CONSP (Vmenu_accelerator_prefix))
-    {
-      Lisp_Object t;
-      t=Vmenu_accelerator_prefix;
-      while (!NILP (t)
-            && !NILP (event0)
-            && event_matches_key_specifier_p (XEVENT (event0), Fcar (t)))
-       {
-         t = Fcdr (t);
-         event0 = XEVENT_NEXT (event0);
-       }
-      if (!NILP (t))
-       return Qnil;
-    }
-  else if (NILP (event0))
-    return Qnil;
-  else if (event_matches_key_specifier_p (XEVENT (event0), Vmenu_accelerator_prefix))
-    event0 = XEVENT_NEXT (event0);
-  else
-    return Qnil;
-  return event0;
-}
-
-static Lisp_Object
-menu_accelerator_safe_mod_compare (Lisp_Object cons)
-{
-  return (event_matches_key_specifier_p (XEVENT (XCAR (cons)), XCDR (cons))
-         ? Qt
-         : Qnil);
-}
-
-static Lisp_Object
-command_builder_find_menu_accelerator (struct command_builder *builder)
-{
-  /* this function can GC */
-  Lisp_Object event0 = builder->current_events;
-  struct console *con = XCONSOLE (Vselected_console);
-  struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
-  Widget menubar_widget;
-
-  /* compare entries in event0 against the menu prefix */
-
-  if ((!CONSOLE_X_P (XCONSOLE (builder->console))) || NILP (event0) ||
-      XEVENT (event0)->event_type != key_press_event)
-    return Qnil;
-
-  if (!NILP (Vmenu_accelerator_prefix))
-    {
-      event0 = condition_case_1 (Qerror,
-                                menu_accelerator_safe_compare,
-                                event0,
-                                menu_accelerator_junk_on_error,
-                                Qnil);
-    }
-
-  if (NILP (event0))
-    return Qnil;
-
-  menubar_widget = FRAME_X_MENUBAR_WIDGET (f);
-  if (menubar_widget
-      && CONSP (Vmenu_accelerator_modifiers))
-    {
-      Lisp_Object fake;
-      Lisp_Object last = Qnil;
-      struct gcpro gcpro1;
-      Lisp_Object matchp;
-
-      widget_value *val;
-      LWLIB_ID id = XPOPUP_DATA (f->menubar_data)->id;
-
-      val = lw_get_all_values (id);
-      if (val)
-       {
-         val = val->contents;
-
-         fake = Fcopy_sequence (Vmenu_accelerator_modifiers);
-         last = fake;
-
-         while (!NILP (Fcdr (last)))
-           last = Fcdr (last);
-
-         Fsetcdr (last, Fcons (Qnil, Qnil));
-         last = Fcdr (last);
-       }
-
-      fake = Fcons (Qnil, fake);
-
-      GCPRO1 (fake);
-
-      while (val)
-       {
-         Lisp_Object accel;
-         VOID_TO_LISP (accel, val->accel);
-         if (val->name && !NILP (accel))
-           {
-             Fsetcar (last, accel);
-             Fsetcar (fake, event0);
-             matchp = condition_case_1 (Qerror,
-                                        menu_accelerator_safe_mod_compare,
-                                        fake,
-                                        menu_accelerator_junk_on_error,
-                                        Qnil);
-             if (!NILP (matchp))
-               {
-                 /* we found one! */
-
-                 lw_set_menu (menubar_widget, val);
-                 /* yah - yet another hack.
-                    pretend emacs timestamp is the same as an X timestamp,
-                    which for the moment it is.  (read events.h)
-                    */
-                 lw_map_menu (XEVENT (event0)->timestamp);
-
-                 if (val->contents)
-                   lw_push_menu (val->contents);
-
-                 lw_display_menu (CurrentTime);
-
-                 /* menu accelerator keys don't go into keyboard macros */
-                 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
-                   con->kbd_macro_ptr = con->kbd_macro_end;
-
-                 /* don't echo menu accelerator keys */
-                 /*reset_key_echo (builder, 1);*/
-                 reset_this_command_keys (Vselected_console, 1);
-                 UNGCPRO;
-
-                 return Vmenu_accelerator_map;
-               }
-           }
-
-         val = val->next;
-       }
-
-      UNGCPRO;
-    }
-  return Qnil;
-}
-
-
-DEFUN ("accelerate-menu", Faccelerate_menu, 0, 0, "_", /*
-Make the menubar active.  Menu items can be selected using menu accelerators
-or by actions defined in menu-accelerator-map.
-*/
-       ())
-{
-  struct console *con = XCONSOLE (Vselected_console);
-  struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
-  LWLIB_ID id;
-  widget_value *val;
-
-  if (NILP (f->menubar_data))
-    error ("Frame has no menubar.");
-
-  id = XPOPUP_DATA (f->menubar_data)->id;
-  val = lw_get_all_values (id);
-  val = val->contents;
-  lw_set_menu (FRAME_X_MENUBAR_WIDGET (f), val);
-  lw_map_menu (CurrentTime);
-
-  lw_display_menu (CurrentTime);
-
-  /* menu accelerator keys don't go into keyboard macros */
-  if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
-    con->kbd_macro_ptr = con->kbd_macro_end;
-
-  return Qnil;
-}
-#endif /* HAVE_X_WINDOWS && HAVE_MENUBARS */
-
 /* See if we can do function-key-map or key-translation-map translation
    on the current events in the command builder.  If so, do this, and
    return the resulting binding, if any. */
@@ -3723,9 +3233,11 @@ command_builder_find_leaf (struct command_builder *builder,
        return Qnil;
     }
 
-  /* if we're currently in a menu accelerator, check there for further events */
+  /* if we're currently in a menu accelerator, check there for further
+     events */
+  /* #### fuck me!  who wrote this crap?  think "abstraction", baby. */
 #if defined(HAVE_X_WINDOWS) && defined(LWLIB_MENUBARS_LUCID)
-  if (lw_menu_active)
+  if (x_kludge_lw_menu_active ())
     {
       return command_builder_operate_menu_accelerator (builder);
     }
@@ -3776,14 +3288,14 @@ command_builder_find_leaf (struct command_builder *builder,
       Lisp_Object terminal = builder->most_current_event;
       struct key_data* key = & XEVENT (terminal)->event.key;
       Emchar c = 0;
-      if ((key->modifiers & MOD_SHIFT)
+      if ((key->modifiers & XEMACS_MOD_SHIFT)
           || (CHAR_OR_CHAR_INTP (key->keysym)
               && ((c = XCHAR_OR_CHAR_INT (key->keysym)), c >= 'A' && c <= 'Z')))
         {
-          struct Lisp_Event terminal_copy = *XEVENT (terminal);
+          Lisp_Event terminal_copy = *XEVENT (terminal);
 
-          if (key->modifiers & MOD_SHIFT)
-            key->modifiers &= (~ MOD_SHIFT);
+          if (key->modifiers & XEMACS_MOD_SHIFT)
+            key->modifiers &= (~ XEMACS_MOD_SHIFT);
           else
             key->keysym = make_char (c + 'a' - 'A');
 
@@ -4173,7 +3685,7 @@ lookup_command_event (struct command_builder *command_builder,
     if (EVENTP (recent)
        && event_matches_key_specifier_p (XEVENT (recent), Vmeta_prefix_char))
       {
-       struct Lisp_Event *e;
+       Lisp_Event *e;
        /* When we see a sequence like "ESC x", pretend we really saw "M-x".
           DoubleThink the recent-keys and this-command-keys as well. */
 
@@ -4184,10 +3696,10 @@ lookup_command_event (struct command_builder *command_builder,
        Fcopy_event (event, recent);
        e = XEVENT (recent);
        if (e->event_type == key_press_event)
-         e->event.key.modifiers |= MOD_META;
+         e->event.key.modifiers |= XEMACS_MOD_META;
        else if (e->event_type == button_press_event
                 || e->event_type == button_release_event)
-         e->event.button.modifiers |= MOD_META;
+         e->event.button.modifiers |= XEMACS_MOD_META;
        else
          abort ();
 
@@ -4218,7 +3730,11 @@ lookup_command_event (struct command_builder *command_builder,
 
     if (KEYMAPP (leaf))
       {
-       if (!lw_menu_active)
+#if defined (HAVE_X_WINDOWS) && defined (LWLIB_MENUBARS_LUCID)
+        if (!x_kludge_lw_menu_active ())
+#else
+       if (1)
+#endif
          {
            Lisp_Object prompt = Fkeymap_prompt (leaf, Qt);
            if (STRINGP (prompt))
@@ -4238,19 +3754,20 @@ lookup_command_event (struct command_builder *command_builder,
            else
              maybe_echo_keys (command_builder, 0);
          }
-       else if (!NILP (Vquit_flag)) {
-         Lisp_Object quit_event = Fmake_event(Qnil, Qnil);
-         struct Lisp_Event *e = XEVENT (quit_event);
-         /* if quit happened during menu acceleration, pretend we read it */
-         struct console *con = XCONSOLE (Fselected_console ());
-         int ch = CONSOLE_QUIT_CHAR (con);
-
-         character_to_event (ch, e, con, 1, 1);
-         e->channel = make_console (con);
-
-         enqueue_command_event (quit_event);
-         Vquit_flag = Qnil;
-       }
+       else if (!NILP (Vquit_flag))
+         {
+           Lisp_Object quit_event = Fmake_event (Qnil, Qnil);
+           Lisp_Event *e = XEVENT (quit_event);
+           /* if quit happened during menu acceleration, pretend we read it */
+           struct console *con = XCONSOLE (Fselected_console ());
+           int ch = CONSOLE_QUIT_CHAR (con);
+
+           character_to_event (ch, e, con, 1, 1);
+           e->channel = make_console (con);
+
+           enqueue_command_event (quit_event);
+           Vquit_flag = Qnil;
+         }
       }
     else if (!NILP (leaf))
       {
@@ -4369,6 +3886,9 @@ execute_command_event (struct command_builder *command_builder,
       {
        /* Start a new command next time */
        Vlast_command = Vthis_command;
+       Vlast_command_properties = Vthis_command_properties;
+       Vthis_command_properties = Qnil;
+
        /* Emacs 18 doesn't unconditionally clear the echoed keystrokes,
           so we don't either */
        reset_this_command_keys (make_console (con), 0);
@@ -4389,6 +3909,9 @@ pre_command_hook (void)
   safe_run_hook_trapping_errors
     ("Error in `pre-command-hook' (setting hook to nil)",
      Qpre_command_hook, 1);
+
+  /* This is a kludge, but necessary; see simple.el */
+  call0 (Qhandle_pre_motion_command);
 }
 
 /* Run the post command hook. */
@@ -4408,14 +3931,18 @@ post_command_hook (void)
 
   Lisp_Object win = Fselected_window (Qnil);
 
-#if 0
   /* If the last command deleted the frame, `win' might be nil.
      It seems safest to do nothing in this case. */
-  /* ### This doesn't really fix the problem,
+  /* Note: Someone added the following comment and put #if 0's around
+     this code, not realizing that doing this invites a crash in the
+     line after. */
+  /* #### This doesn't really fix the problem,
      if delete-frame is called by some hook */
   if (NILP (win))
     return;
-#endif
+
+  /* This is a kludge, but necessary; see simple.el */
+  call0 (Qhandle_post_motion_command);
 
   if (! zmacs_region_stays
       && (!MINI_WINDOW_P (XWINDOW (win))
@@ -4428,12 +3955,10 @@ post_command_hook (void)
     ("Error in `post-command-hook' (setting hook to nil)",
      Qpost_command_hook, 1);
 
-#ifdef DEFERRED_ACTION_CRAP
+#if 0 /* FSF Emacs crap */
   if (!NILP (Vdeferred_action_list))
     call0 (Vdeferred_action_function);
-#endif
 
-#ifdef ILL_CONCEIVED_HOOK
   if (NILP (Vunread_command_events)
       && NILP (Vexecuting_macro)
       && !NILP (Vpost_command_idle_hook)
@@ -4442,9 +3967,9 @@ post_command_hook (void)
   safe_run_hook_trapping_errors
     ("Error in `post-command-idle-hook' (setting hook to nil)",
      Qpost_command_idle_hook, 1);
-#endif
+#endif /* FSF Emacs crap */
 
-#if 0 /* FSFmacs */
+#if 0 /* FSF Emacs */
   if (!NILP (current_buffer->mark_active))
     {
       if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
@@ -4456,7 +3981,7 @@ post_command_hook (void)
               BUF_MODIFF (current_buffer) != prev_modiff)
        run_hook (intern ("activate-mark-hook"));
     }
-#endif /* FSFmacs */
+#endif /* FSF Emacs */
 
   /* #### Kludge!!! This is necessary to make sure that things
      are properly positioned even if post-command-hook moves point.
@@ -4490,7 +4015,7 @@ Magic events are handled as necessary.
 {
   /* This function can GC */
   struct command_builder *command_builder;
-  struct Lisp_Event *ev;
+  Lisp_Event *ev;
   Lisp_Object console;
   Lisp_Object channel;
 
@@ -4604,15 +4129,35 @@ Magic events are handled as necessary.
          }
        else /* key sequence is bound to a command */
          {
+           int magic_undo = 0;
+           int magic_undo_count = 20;
+
            Vthis_command = leaf;
+
            /* Don't push an undo boundary if the command set the prefix arg,
               or if we are executing a keyboard macro, or if in the
               minibuffer.  If the command we are about to execute is
               self-insert, it's tricky: up to 20 consecutive self-inserts may
               be done without an undo boundary.  This counter is reset as
               soon as a command other than self-insert-command is executed.
-              */
-           if (! EQ (leaf, Qself_insert_command))
+
+              Programmers can also use the `self-insert-defer-undo'
+              property to install that behavior on functions other
+              than `self-insert-command', or to change the magic
+              number 20 to something else.  #### DOCUMENT THIS!  */
+
+           if (SYMBOLP (leaf))
+             {
+               Lisp_Object prop = Fget (leaf, Qself_insert_defer_undo, Qnil);
+               if (NATNUMP (prop))
+                 magic_undo = 1, magic_undo_count = XINT (prop);
+               else if (!NILP (prop))
+                 magic_undo = 1;
+               else if (EQ (leaf, Qself_insert_command))
+                 magic_undo = 1;
+             }
+
+           if (!magic_undo)
              command_builder->self_insert_countdown = 0;
            if (NILP (XCONSOLE (console)->prefix_arg)
                && NILP (Vexecuting_macro)
@@ -4626,10 +4171,10 @@ Magic events are handled as necessary.
                && command_builder->self_insert_countdown == 0)
              Fundo_boundary ();
 
-           if (EQ (leaf, Qself_insert_command))
+           if (magic_undo)
              {
                if (--command_builder->self_insert_countdown < 0)
-                 command_builder->self_insert_countdown = 20;
+                 command_builder->self_insert_countdown = magic_undo_count;
              }
            execute_command_event
               (command_builder,
@@ -4815,7 +4360,7 @@ That is not right.
 
 Calling this function directs the translated event to replace
 the original event, so that only one version of the event actually
-appears in the echo area and in the value of `this-command-keys.'.
+appears in the echo area and in the value of `this-command-keys'.
 */
        ())
 {
@@ -4893,6 +4438,23 @@ If FILE is nil, close any open dribble file.
 }
 
 \f
+
+DEFUN ("current-event-timestamp", Fcurrent_event_timestamp, 0, 1, 0, /*
+Return the current event timestamp of the window system associated with CONSOLE.
+CONSOLE defaults to the selected console if omitted.
+*/
+       (console))
+{
+  struct console *c = decode_console (console);
+  int tiempo = event_stream_current_event_timestamp (c);
+
+  /* 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);
+}
+
+\f
 /************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
@@ -4900,11 +4462,13 @@ If FILE is nil, close any open dribble file.
 void
 syms_of_event_stream (void)
 {
+  INIT_LRECORD_IMPLEMENTATION (command_builder);
+  INIT_LRECORD_IMPLEMENTATION (timeout);
+
   defsymbol (&Qdisabled, "disabled");
   defsymbol (&Qcommand_event_p, "command-event-p");
 
-  deferror (&Qundefined_keystroke_sequence, "undefined-keystroke-sequence",
-            "Undefined keystroke sequence", Qerror);
+  DEFERROR_STANDARD (Qundefined_keystroke_sequence, Qinvalid_argument);
 
   DEFSUBR (Frecent_keys);
   DEFSUBR (Frecent_keys_ring_size);
@@ -4922,23 +4486,22 @@ syms_of_event_stream (void)
   DEFSUBR (Fadd_async_timeout);
   DEFSUBR (Fdisable_async_timeout);
   DEFSUBR (Fdispatch_event);
+  DEFSUBR (Fdispatch_non_command_events);
   DEFSUBR (Fread_key_sequence);
   DEFSUBR (Fthis_command_keys);
   DEFSUBR (Freset_this_command_lengths);
   DEFSUBR (Fopen_dribble_file);
-#if defined(HAVE_X_WINDOWS) && defined(LWLIB_MENUBARS_LUCID)
-  DEFSUBR (Faccelerate_menu);
-#endif
+  DEFSUBR (Fcurrent_event_timestamp);
 
   defsymbol (&Qpre_command_hook, "pre-command-hook");
   defsymbol (&Qpost_command_hook, "post-command-hook");
   defsymbol (&Qunread_command_events, "unread-command-events");
   defsymbol (&Qunread_command_event, "unread-command-event");
   defsymbol (&Qpre_idle_hook, "pre-idle-hook");
-#ifdef ILL_CONCEIVED_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");
-#endif
-#ifdef DEFERRED_ACTION_CRAP
   defsymbol (&Qdeferred_action_function, "deferred-action-function");
 #endif
   defsymbol (&Qretry_undefined_key_binding_unshifted,
@@ -4946,17 +4509,7 @@ syms_of_event_stream (void)
   defsymbol (&Qauto_show_make_point_visible,
             "auto-show-make-point-visible");
 
-  defsymbol (&Qmenu_force, "menu-force");
-  defsymbol (&Qmenu_fallback, "menu-fallback");
-
-  defsymbol (&Qmenu_quit, "menu-quit");
-  defsymbol (&Qmenu_up, "menu-up");
-  defsymbol (&Qmenu_down, "menu-down");
-  defsymbol (&Qmenu_left, "menu-left");
-  defsymbol (&Qmenu_right, "menu-right");
-  defsymbol (&Qmenu_select, "menu-select");
-  defsymbol (&Qmenu_escape, "menu-escape");
-
+  defsymbol (&Qself_insert_defer_undo, "self-insert-defer-undo");
   defsymbol (&Qcancel_mode_internal, "cancel-mode-internal");
 }
 
@@ -4966,7 +4519,7 @@ reinit_vars_of_event_stream (void)
   recent_keys_ring_index = 0;
   recent_keys_ring_size = 100;
   num_input_chars = 0;
-  Vtimeout_free_list = make_lcrecord_list (sizeof (struct Lisp_Timeout),
+  Vtimeout_free_list = make_lcrecord_list (sizeof (Lisp_Timeout),
                                           &lrecord_timeout);
   staticpro_nodump (&Vtimeout_free_list);
   the_low_level_timeout_blocktype =
@@ -5036,7 +4589,7 @@ Normal hook run when XEmacs it about to be idle.
 This occurs whenever it is going to block, waiting for an event.
 This generally happens as a result of a call to `next-event',
 `next-command-event', `sit-for', `sleep-for', `accept-process-output',
-`x-get-selection', or various Energize-specific commands.
+or `x-get-selection'.
 Errors running the hook are caught and ignored.
 */ );
   Vpre_idle_hook = Qnil;
@@ -5049,7 +4602,7 @@ used by the window manager, so it is up to the user to set it.
 */ );
   focus_follows_mouse = 0;
 
-#ifdef ILL_CONCEIVED_HOOK
+#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. */
@@ -5066,9 +4619,7 @@ Delay time before running `post-command-idle-hook'.
 This is measured in microseconds.
 */ );
   post_command_idle_delay = 5000;
-#endif /* ILL_CONCEIVED_HOOK */
 
-#ifdef DEFERRED_ACTION_CRAP
   /* 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'. */
@@ -5084,7 +4635,7 @@ This function is called with no arguments after each command
 whenever `deferred-action-list' is non-nil.
 */ );
   Vdeferred_action_function = Qnil;
-#endif /* DEFERRED_ACTION_CRAP */
+#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
@@ -5174,6 +4725,23 @@ will be in `last-command' during the following command.
 */ );
   Vthis_command = Qnil;
 
+  DEFVAR_LISP ("last-command-properties", &Vlast_command_properties /*
+Value of `this-command-properties' for the last command.
+Used by commands to help synchronize consecutive commands, in preference
+to looking at `last-command' directly.
+*/ );
+  Vlast_command_properties = Qnil;
+
+  DEFVAR_LISP ("this-command-properties", &Vthis_command_properties /*
+Properties set by the current command.
+At the beginning of each command, the current value of this variable is
+copied to `last-command-properties', and then it is set to nil.  Use `putf'
+to add properties to this variable.  Commands should use this to communicate
+with pre/post-command hooks, subsequent commands, wrapping commands, etc.
+in preference to looking at and/or setting `this-command'.
+*/ );
+  Vthis_command_properties = Qnil;
+
   DEFVAR_LISP ("help-char", &Vhelp_char /*
 Character to recognize as meaning Help.
 When it is read, do `(eval help-form)', and display result if it's a string.
@@ -5207,6 +4775,10 @@ Each key-press event is looked up in this table as follows:
    keysym changed and its modifiers left alone.  This is useful for
    dealing with non-standard X keyboards, such as the grievous damage
    that Sun has inflicted upon the world.
+-- If an entry maps a symbol to a character, then a key-press event
+   whose keysym is the former symbol (with any modifiers at all) gets
+   changed into a key-press event matching the latter character, and the
+   resulting modifiers are the union of the original and new modifiers.
 -- If an entry maps a character to a character, then a key-press event
    matching the former character gets converted to a key-press event
    matching the latter character.  This is useful on ASCII terminals
@@ -5215,6 +4787,16 @@ Each key-press event is looked up in this table as follows:
 -- If an entry maps a character to a symbol, then a key-press event
    matching the character gets converted to a key-press event whose
    keysym is the given symbol and which has no modifiers.
+
+Here's an example: This makes typing parens and braces easier by rerouting
+their positions to eliminate the need to use the Shift key.
+
+  (keyboard-translate ?[ ?()
+  (keyboard-translate ?] ?))
+  (keyboard-translate ?{ ?[)
+  (keyboard-translate ?} ?])
+  (keyboard-translate 'f11 ?{)
+  (keyboard-translate 'f12 ?})
 */ );
 
   DEFVAR_LISP ("retry-undefined-key-binding-unshifted",
@@ -5227,6 +4809,15 @@ you should *bind* this, not set it.
 */ );
     Vretry_undefined_key_binding_unshifted = Qt;
 
+  DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
+*Non-nil makes modifier keys sticky.
+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 = 0;
+
 #ifdef HAVE_XIM
   DEFVAR_LISP ("composed-character-default-binding",
                &Vcomposed_character_default_binding /*
@@ -5287,41 +4878,6 @@ and is one of the following:
 Non-nil inhibits recording of input-events to recent-keys ring.
 */ );
   inhibit_input_event_recording = 0;
-
-  DEFVAR_LISP("menu-accelerator-prefix", &Vmenu_accelerator_prefix /*
-Prefix key(s) that must be typed before menu accelerators will be activated.
-Set this to a value acceptable by define-key.
-*/ );
-  Vmenu_accelerator_prefix = Qnil;
-
-  DEFVAR_LISP ("menu-accelerator-modifiers", &Vmenu_accelerator_modifiers /*
-Modifier keys which must be pressed to get to the top level menu accelerators.
-This is a list of modifier key symbols.  All modifier keys must be held down
-while a valid menu accelerator key is pressed in order for the top level
-menu to become active.
-
-See also menu-accelerator-enabled and menu-accelerator-prefix.
-*/ );
-  Vmenu_accelerator_modifiers = list1 (Qmeta);
-
-  DEFVAR_LISP ("menu-accelerator-enabled", &Vmenu_accelerator_enabled /*
-Whether menu accelerator keys can cause the menubar to become active.
-If 'menu-force or 'menu-fallback, then menu accelerator keys can
-be used to activate the top level menu.  Once the menubar becomes active, the
-accelerator keys can be used regardless of the value of this variable.
-
-menu-force is used to indicate that the menu accelerator key takes
-precedence over bindings in the current keymap(s).  menu-fallback means
-that bindings in the current keymap take precedence over menu accelerator keys.
-Thus a top level menu with an accelerator of "T" would be activated on a
-keypress of Meta-t if menu-accelerator-enabled is menu-force.
-However, if menu-accelerator-enabled is menu-fallback, then
-Meta-t will not activate the menubar and will instead run the function
-transpose-words, to which it is normally bound.
-
-See also menu-accelerator-modifiers and menu-accelerator-prefix.
-*/ );
-  Vmenu_accelerator_enabled = Qnil;
 }
 
 void
@@ -5329,41 +4885,6 @@ complex_vars_of_event_stream (void)
 {
   Vkeyboard_translate_table =
     make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
-
-  DEFVAR_LISP ("menu-accelerator-map", &Vmenu_accelerator_map /*
-Keymap for use when the menubar is active.
-The actions menu-quit, menu-up, menu-down, menu-left, menu-right,
-menu-select and menu-escape can be mapped to keys in this map.
-
-menu-quit    Immediately deactivate the menubar and any open submenus without
-             selecting an item.
-menu-up      Move the menu cursor up one row in the current menu.  If the
-             move extends past the top of the menu, wrap around to the bottom.
-menu-down    Move the menu cursor down one row in the current menu.  If the
-             move extends past the bottom of the menu, wrap around to the top.
-             If executed while the cursor is in the top level menu, move down
-             into the selected menu.
-menu-left    Move the cursor from a submenu into the parent menu.  If executed
-             while the cursor is in the top level menu, move the cursor to the
-             left.  If the move extends past the left edge of the menu, wrap
-             around to the right edge.
-menu-right   Move the cursor into a submenu.  If the cursor is located in the
-             top level menu or is not currently on a submenu heading, then move
-             the cursor to the next top level menu entry.  If the move extends
-             past the right edge of the menu, wrap around to the left edge.
-menu-select  Activate the item under the cursor.  If the cursor is located on
-             a submenu heading, then move the cursor into the submenu.
-menu-escape  Pop up to the next level of menus.  Moves from a submenu into its
-             parent menu.  From the top level menu, this deactivates the
-             menubar.
-
-This keymap can also contain normal key-command bindings, in which case the
-menubar is deactivated and the corresponding command is executed.
-
-The action bindings used by the menu accelerator code are designed to mimic
-the actions of menu traversal keys in a commonly used PC operating system.
-*/ );
-  Vmenu_accelerator_map = Fmake_keymap(Qnil);
 }
 
 void