diff src/event-stream.c @ 185:3d6bfa290dbd r20-3b19

Import from CVS: tag r20-3b19
author cvs
date Mon, 13 Aug 2007 09:55:28 +0200
parents bfd6434d15b3
children b405438285a2
line wrap: on
line diff
--- a/src/event-stream.c	Mon Aug 13 09:54:24 2007 +0200
+++ b/src/event-stream.c	Mon Aug 13 09:55:28 2007 +0200
@@ -35,6 +35,30 @@
  *
  */
 
+/* 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.
+   Other command events should be able to come in the MIDDLE of a key
+   sequence, without disturbing the key sequence composition, or the
+   command builder structure representing it.
+
+   Someone should rethink univeral-argument and figure out how an
+   arbitrary command can influence the next command (universal-argument
+   or univeral-coding-system-argument) or the next key (hyperify).
+
+   Both C-h and Help in the middle of a key sequence should trigger
+   prefix-help-command.  help-char is stupid.  Maybe we need
+   keymap-of-last-resort?
+
+   After prefix-help is run, one should be able to CONTINUE TYPING,
+   instead of RETYPING, the key sequence.
+ */
+
 #include <config.h>
 #include "lisp.h"
 
@@ -153,8 +177,7 @@
 /* The buffer that was current when the last command was started.  */
 Lisp_Object last_point_position_buffer;
 
-/* A (16bit . 16bit) representation of the time of the last-command-event.
- */
+/* A (16bit . 16bit) representation of the time of the last-command-event. */
 Lisp_Object Vlast_input_time;
 
 /* Character to recognize as the help char.  */
@@ -163,13 +186,13 @@
 /* Form to execute when help char is typed.  */
 Lisp_Object Vhelp_form;
 
+/* Command to run when the help character follows a prefix key.  */
+Lisp_Object Vprefix_help_command;
+
 /* Flag to tell QUIT that some interesting occurrence (e.g. a keypress)
    may have happened. */
 volatile int something_happened;
 
-/* Command to run when the help character follows a prefix key.  */
-Lisp_Object Vprefix_help_command;
-
 /* Hash table to translate keysyms through */
 Lisp_Object Vkeyboard_translate_table;
 
@@ -230,13 +253,29 @@
 
 #ifdef DEBUG_XEMACS
 int debug_emacs_events;
+
+static void
+external_debugging_print_event (char *event_description, Lisp_Object event)
+{
+  write_c_string ("(",		     Qexternal_debugging_output);
+  write_c_string (event_description, Qexternal_debugging_output);
+  write_c_string (") ",		     Qexternal_debugging_output);
+  print_internal (event,	     Qexternal_debugging_output, 1);
+  write_c_string ("\n",		     Qexternal_debugging_output);
+}
+#define DEBUG_PRINT_EMACS_EVENT(event_description, event) do {	\
+  if (debug_emacs_events)					\
+    external_debugging_print_event (event_description, event);	\
+} while (0)
+#else
+#define DEBUG_PRINT_EMACS_EVENT(string, event)
 #endif
 
 
 /* The callback routines for the window system or terminal driver */
 struct event_stream *event_stream;
 
-/* This structure is what we use to excapsulate the state of a command sequence
+/* 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.
@@ -256,30 +295,28 @@
   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. */
+  /* 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];
+  {
+    /* 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 */
@@ -361,12 +398,10 @@
 static void
 finalize_command_builder (void *header, int for_disksave)
 {
-  struct command_builder *c = (struct command_builder *) header;
-
   if (!for_disksave)
     {
-      xfree (c->echo_buf);
-      c->echo_buf = 0;
+      xfree (((struct command_builder *) header)->echo_buf);
+      ((struct command_builder *) header)->echo_buf = 0;
     }
 }
 
@@ -386,14 +421,12 @@
 {
   Lisp_Object builder_obj = Qnil;
   struct command_builder *builder =
-    alloc_lcrecord (sizeof (struct command_builder),
-		    lrecord_command_builder);
+    alloc_lcrecord_type (struct command_builder, lrecord_command_builder);
 
   builder->console = console;
   reset_command_builder_event_chain (builder);
   builder->echo_buf_length = 300; /* #### Kludge */
-  builder->echo_buf =
-    (Bufbyte *) xmalloc (builder->echo_buf_length);
+  builder->echo_buf = xnew_array (Bufbyte, builder->echo_buf_length);
   builder->echo_buf[0] = 0;
   builder->echo_buf_index = -1;
   builder->echo_buf_index = -1;
@@ -510,15 +543,7 @@
      which will unblock us. */
   if (maybe_read_quit_event (event))
     {
-#ifdef DEBUG_XEMACS
-      if (debug_emacs_events)
-	{
-	  write_c_string ("(SIGINT) ",
-			  Qexternal_debugging_output);
-	  print_internal (event_obj, Qexternal_debugging_output, 1);
-	  write_c_string ("\n", Qexternal_debugging_output);
-	}
-#endif
+      DEBUG_PRINT_EMACS_EVENT ("SIGINT", event_obj);
       return;
     }
 
@@ -538,18 +563,10 @@
   emacs_is_blocking = 0;
 
 #ifdef DEBUG_XEMACS
-  if (debug_emacs_events)
-    {
-      write_c_string ("(real) ",
-		      Qexternal_debugging_output);
-      /* timeout events have more info set later, so
-	 print the event out in next_event_internal(). */
-      if (event->event_type != timeout_event)
-	{
-	  print_internal (event_obj, Qexternal_debugging_output, 1);
-	  write_c_string ("\n", Qexternal_debugging_output);
-	}
-    }
+  /* timeout events have more info set later, so
+     print the event out in next_event_internal(). */
+  if (event->event_type != timeout_event)
+    DEBUG_PRINT_EMACS_EVENT ("real", event_obj);
 #endif
   maybe_kbd_translate (event_obj);
 }
@@ -777,13 +794,8 @@
     }
 
 #ifdef DEBUG_XEMACS
-  if (did_translate && debug_emacs_events)
-    {
-      write_c_string ("(->keyboard-translate-table) ",
-		      Qexternal_debugging_output);
-      print_internal (event, Qexternal_debugging_output, 1);
-      write_c_string ("\n", Qexternal_debugging_output);
-    }
+  if (did_translate)
+    DEBUG_PRINT_EMACS_EVENT ("->keyboard-translate-table", event);
 #endif
 }
 
@@ -1155,10 +1167,7 @@
   GCPRO1 (op); /* just in case ...  because it's removed from the list
 		  for awhile. */
 
-  if (async_p)
-    timeout_list = &pending_async_timeout_list;
-  else
-    timeout_list = &pending_timeout_list;
+  timeout_list = async_p ? &pending_async_timeout_list : &pending_timeout_list;
 
   /* Find the timeout on the list of pending ones. */
   LIST_LOOP (rest, *timeout_list)
@@ -1534,9 +1543,7 @@
 void
 enqueue_magic_eval_event (void (*fun) (Lisp_Object), Lisp_Object object)
 {
-  Lisp_Object event;
-
-  event = Fmake_event ();
+  Lisp_Object event = Fmake_event ();
 
   XEVENT (event)->event_type = magic_eval_event;
   /* channel for magic_eval events is nil */
@@ -1554,9 +1561,7 @@
 */
        (function, object))
 {
-  Lisp_Object event;
-
-  event = Fmake_event ();
+  Lisp_Object event = Fmake_event ();
 
   XEVENT (event)->event_type = eval_event;
   /* channel for eval events is nil */
@@ -1571,9 +1576,7 @@
 enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function,
 			 Lisp_Object object)
 {
-  Lisp_Object event;
-
-  event = Fmake_event ();
+  Lisp_Object event = Fmake_event ();
 
   XEVENT (event)->event_type = misc_user_event;
   XEVENT (event)->channel = channel;
@@ -1884,8 +1887,7 @@
   return in_single_console;
 }
 
-/* the number of keyboard characters read.  callint.c wants this.
- */
+/* the number of keyboard characters read.  callint.c wants this. */
 Charcount num_input_chars;
 
 static void
@@ -1905,15 +1907,7 @@
       Lisp_Object event = dequeue_command_event ();
       Fcopy_event (event, target_event);
       Fdeallocate_event (event);
-#ifdef DEBUG_XEMACS
-      if (debug_emacs_events)
-	{
-	  write_c_string ("(command event queue) ",
-			  Qexternal_debugging_output);
-	  print_internal (target_event, Qexternal_debugging_output, 1);
-	  write_c_string ("\n", Qexternal_debugging_output);
-	}
-#endif
+      DEBUG_PRINT_EMACS_EVENT ("command event queue", target_event);
     }
   else
     {
@@ -1934,15 +1928,9 @@
 
 	  e->event.timeout.function = tristan;
 	  e->event.timeout.object = isolde;
-#ifdef DEBUG_XEMACS
 	  /* next_event_internal() doesn't print out timeout events
 	     because of the extra info we just set. */
-	  if (debug_emacs_events)
-	    {
-	      print_internal (target_event, Qexternal_debugging_output, 1);
-	      write_c_string ("\n", Qexternal_debugging_output);
-	    }
-#endif
+	  DEBUG_PRINT_EMACS_EVENT ("real, timeout", target_event);
 	}
 
       /* If we read a ^G, then set quit-flag but do not discard the ^G.
@@ -1985,7 +1973,7 @@
 Return the next available event.
 Pass this object to `dispatch-event' to handle it.
 In most cases, you will want to use `next-command-event', which returns
-the next available \"user\" event (i.e. keypress, button-press,
+the next available "user" event (i.e. keypress, button-press,
 button-release, or menu selection) instead of this function.
 
 If EVENT is non-nil, it should be an event object and will be filled in
@@ -2014,7 +2002,7 @@
    event is dispatched.  Eval events are generated by `enqueue-eval-event'
    or by certain other conditions happening.
 -- a magic event, indicating that some window-system-specific event
-   happened (such as an focus-change notification) that must be handled
+   happened (such as a focus-change notification) that must be handled
    synchronously with other events.  `dispatch-event' knows what to do with
    these events.
 */
@@ -2101,20 +2089,11 @@
 	  redisplay ();
 	  if (!EQ (e, event))
 	    Fcopy_event (e, event);
-#ifdef DEBUG_XEMACS
-	  if (debug_emacs_events)
-	    {
-	      write_c_string ("(unread-command-events) ",
-			      Qexternal_debugging_output);
-	      print_internal (event, Qexternal_debugging_output, 1);
-	      write_c_string ("\n", Qexternal_debugging_output);
-	    }
-#endif
+	  DEBUG_PRINT_EMACS_EVENT ("unread-command-events", event);
 	}
     }
 
-  /* Do similar for unread-command-event (obsoleteness support).
-   */
+  /* Do similar for unread-command-event (obsoleteness support). */
   else if (!NILP (Vunread_command_event))
     {
       Lisp_Object e = Vunread_command_event;
@@ -2128,15 +2107,7 @@
       if (!EQ (e, event))
 	Fcopy_event (e, event);
       redisplay ();
-#ifdef DEBUG_XEMACS
-      if (debug_emacs_events)
-	{
-	  write_c_string ("(unread-command-event) ",
-			  Qexternal_debugging_output);
-	  print_internal (event, Qexternal_debugging_output, 1);
-	  write_c_string ("\n", Qexternal_debugging_output);
-	}
-#endif
+      DEBUG_PRINT_EMACS_EVENT ("unread-command-event", event);
     }
 
   /* If we're executing a keyboard macro, take the next event from that,
@@ -2151,15 +2122,7 @@
 	  pop_kbd_macro_event (event);  /* This throws past us at
 					   end-of-macro. */
 	  store_this_key = 1;
-#ifdef DEBUG_XEMACS
-	  if (debug_emacs_events)
-	    {
-	      write_c_string ("(keyboard macro) ",
-			      Qexternal_debugging_output);
-	      print_internal (event, Qexternal_debugging_output, 1);
-	      write_c_string ("\n", Qexternal_debugging_output);
-	    }
-#endif
+	  DEBUG_PRINT_EMACS_EVENT ("keyboard macro", event);
 	}
       /* Otherwise, read a real event, possibly from the
 	 command_event_queue, and update this-command-keys and
@@ -2245,10 +2208,8 @@
     EMACS_GET_TIME (t);
     if (!CONSP (Vlast_input_time))
       Vlast_input_time = Fcons (Qnil, Qnil);
-    XCAR (Vlast_input_time)
-      = make_int ((EMACS_SECS (t) >> 16) & 0xffff);
-    XCDR (Vlast_input_time)
-      = make_int ((EMACS_SECS (t) >> 0)  & 0xffff);
+    XCAR (Vlast_input_time) = make_int ((EMACS_SECS (t) >> 16) & 0xffff);
+    XCDR (Vlast_input_time) = make_int ((EMACS_SECS (t) >> 0)  & 0xffff);
   }
 
   /* If this key came from the keyboard or from a keyboard macro, then
@@ -2284,7 +2245,7 @@
 }
 
 DEFUN ("next-command-event", Fnext_command_event, 0, 2, 0, /*
-Return the next available \"user\" event.
+Return the next available "user" event.
 Pass this object to `dispatch-event' to handle it.
 
 If EVENT is non-nil, it should be an event object and will be filled in
@@ -2336,10 +2297,10 @@
 }
 
 DEFUN ("discard-input", Fdiscard_input, 0, 0, 0, /*
-Discard any pending \"user\" events.
+Discard any pending "user" events.
 Also cancel any kbd macro being defined.
 A user event is a key press, button press, button release, or
-\"other-user\" event (menu selection or scrollbar action).
+"misc-user" event (menu selection or scrollbar action).
 */
        ())
 {
@@ -3027,7 +2988,7 @@
 {
   widget_value *current, *prev;
   widget_value *entries;
-  
+
   current = lw_get_entries (False);
   entries = lw_get_entries (True);
   prev = NULL;
@@ -3069,16 +3030,16 @@
 {
   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);
@@ -3093,7 +3054,7 @@
 	  return;
 	}
     }
-  
+
   lw_set_item (new);
 }
 
@@ -3103,7 +3064,7 @@
   int level = lw_menu_level ();
   int l = level;
   widget_value *current;
-  
+
   while (level >= 3)
     {
       --level;
@@ -3121,7 +3082,7 @@
   int level = lw_menu_level ();
   int l = level;
   widget_value *current;
-  
+
   while (level >= 3)
     {
       --level;
@@ -3138,13 +3099,13 @@
 {
   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);
     }
@@ -3161,12 +3122,12 @@
 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
@@ -3174,7 +3135,7 @@
     int i;
     Lisp_Object t;
     char buf[50];
-    
+
     t = builder->current_events;
     i = 0;
     while (!NILP (t))
@@ -3188,14 +3149,14 @@
       }
   }
 #endif
-  
+
   /* 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
@@ -3208,11 +3169,11 @@
 	  lw_display_menu (CurrentTime);
 	}
     }
-  
+
   /* compare event to the current menu accelerators */
-  
+
   entries=lw_get_entries (True);
-  
+
   while (entries)
     {
       Lisp_Object accel;
@@ -3222,11 +3183,11 @@
 	  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;
@@ -3234,11 +3195,11 @@
 	}
       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 */
@@ -3295,7 +3256,7 @@
       else if (EQ (binding, Qmenu_escape))
 	{
 	  int level = lw_menu_level ();
-	  
+
 	  if (level > 2)
 	    {
 	      lw_pop_menu ();
@@ -3323,25 +3284,25 @@
 	  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_prefix    = Qnil;
   Vmenu_accelerator_modifiers = Qnil;
-  Vmenu_accelerator_enabled = 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))
@@ -3352,7 +3313,7 @@
 	 emacs_doprnt_string_lisp ((CONST Bufbyte *) "%s: %s",
 				   Qnil, -1, 2, args));
     }
-  
+
   return Qnil;
 }
 
@@ -3398,13 +3359,13 @@
   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,
@@ -3413,39 +3374,39 @@
 				 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;
+      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)
@@ -3464,35 +3425,35 @@
 	      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;
@@ -3509,17 +3470,17 @@
   struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
   LWLIB_ID id = XPOPUP_DATA (f->menubar_data)->id;
   widget_value *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 */
@@ -3539,83 +3500,81 @@
     {
       Lisp_Object result = munging_key_map_event_binding (suffix, munge);
 
-      if (!NILP (result))
+      if (NILP (result))
+	continue;
+
+      if (KEYMAPP (result))
+	{
+	  if (NILP (builder->last_non_munged_event)
+	      && !has_normal_binding_p)
+	    builder->last_non_munged_event = builder->most_current_event;
+	}
+      else
+	builder->last_non_munged_event = Qnil;
+
+      if (!KEYMAPP (result) &&
+	  !VECTORP (result) &&
+	  !STRINGP (result))
 	{
-	  if (KEYMAPP (result))
+	  struct gcpro gcpro1;
+	  GCPRO1 (suffix);
+	  result = call1 (result, Qnil);
+	  UNGCPRO;
+	  if (NILP (result))
+	    return Qnil;
+	}
+
+      if (KEYMAPP (result))
+	return result;
+
+      if (VECTORP (result) || STRINGP (result))
+	{
+	  Lisp_Object new_chain = key_sequence_to_event_chain (result);
+	  Lisp_Object tempev;
+	  int n, tckn;
+
+	  /* If the first_mungeable_event of the other munger is
+	     within the events we're munging, then it will point to
+	     deallocated events afterwards, which is bad -- so make it
+	     point at the beginning of the munged events. */
+	  EVENT_CHAIN_LOOP (tempev, suffix)
 	    {
-	      if (NILP (builder->last_non_munged_event)
-		  && !has_normal_binding_p)
-		builder->last_non_munged_event =
-		  builder->most_current_event;
-	    }
-	  else
-	    builder->last_non_munged_event = Qnil;
-
-	  if (!KEYMAPP (result) && !VECTORP (result)
-	      && !STRINGP (result))
-	  {
-	    struct gcpro gcpro1;
-	    GCPRO1 (suffix);
-	    result = call1 (result, Qnil);
-	    UNGCPRO;
-	  }
-
-	  if (KEYMAPP (result))
-	    return result;
-
-	  if (VECTORP (result) || STRINGP (result))
-	    {
-	      Lisp_Object new_chain =
-		key_sequence_to_event_chain (result);
-	      Lisp_Object tempev;
-	      int n, tckn;
-
-	      /* If the first_mungeable_event of the other munger
-		 is within the events we're munging, then it will
-		 point to deallocated events afterwards, which is
-		 bad -- so make it point at the beginning of the
-		 munged events. */
-	      EVENT_CHAIN_LOOP (tempev, suffix)
+	      Lisp_Object *mungeable_event =
+		&builder->munge_me[1 - munge].first_mungeable_event;
+	      if (EQ (tempev, *mungeable_event))
 		{
-		  if (EQ (tempev, builder->munge_me[1 - munge].
-			  first_mungeable_event))
-		    {
-		      builder->munge_me[1 - munge].first_mungeable_event =
-			new_chain;
-		      break;
-		    }
+		  *mungeable_event = new_chain;
+		  break;
 		}
-
-	      n = event_chain_count (suffix);
-	      command_builder_replace_suffix (builder, suffix, new_chain);
-	      builder->munge_me[munge].first_mungeable_event = Qnil;
-	      /* Now hork this-command-keys as well. */
-
-	      /* We just assume that the events we just replaced
-		 are sitting in copied form at the end of this-command-keys.
-		 If the user did weird things with `dispatch-event'
-		 this may not be the case, but at least we make
-		 sure we won't crash. */
-	      new_chain = copy_event_chain (new_chain);
-	      tckn = event_chain_count (Vthis_command_keys);
-	      if (tckn >= n)
-		{
-		  this_command_keys_replace_suffix
-		    (event_chain_nth (Vthis_command_keys, tckn - n),
-		     new_chain);
-		}
-
-	      result = command_builder_find_leaf_1 (builder);
-	      return result;
 	    }
 
-	  if (munge == MUNGE_ME_FUNCTION_KEY)
-	    signal_simple_error ("Invalid binding in function-key-map",
-				 result);
-	  else
-	    signal_simple_error ("Invalid binding in key-translation-map",
-				 result);
+	  n = event_chain_count (suffix);
+	  command_builder_replace_suffix (builder, suffix, new_chain);
+	  builder->munge_me[munge].first_mungeable_event = Qnil;
+	  /* Now hork this-command-keys as well. */
+
+	  /* We just assume that the events we just replaced are
+	     sitting in copied form at the end of this-command-keys.
+	     If the user did weird things with `dispatch-event' this
+	     may not be the case, but at least we make sure we won't
+	     crash. */
+	  new_chain = copy_event_chain (new_chain);
+	  tckn = event_chain_count (Vthis_command_keys);
+	  if (tckn >= n)
+	    {
+	      this_command_keys_replace_suffix
+		(event_chain_nth (Vthis_command_keys, tckn - n),
+		 new_chain);
+	    }
+
+	  result = command_builder_find_leaf_1 (builder);
+	  return result;
 	}
+
+      signal_simple_error ((munge == MUNGE_ME_FUNCTION_KEY ?
+			    "Invalid binding in function-key-map" :
+			    "Invalid binding in key-translation-map"),
+			   result);
     }
 
   return Qnil;
@@ -3638,29 +3597,24 @@
   Lisp_Object result;
   Lisp_Object evee = builder->current_events;
 
-  if (allow_misc_user_events_p
-      && (NILP (XEVENT_NEXT (evee)))
-      && (XEVENT_TYPE (evee) == misc_user_event))
+  if (XEVENT_TYPE (evee) == misc_user_event)
     {
-      Lisp_Object fn  = XEVENT (evee)->event.eval.function;
-      Lisp_Object arg = XEVENT (evee)->event.eval.object;
-      return list2 (fn, arg);
+      if (allow_misc_user_events_p && (NILP (XEVENT_NEXT (evee))))
+	return list2 (XEVENT (evee)->event.eval.function,
+		      XEVENT (evee)->event.eval.object);
+      else
+	return Qnil;
     }
 
-  
-  if (XEVENT_TYPE (evee) == misc_user_event)
-    return Qnil;
-
   /* if we're currently in a menu accelerator, check there for further events */
 #if defined(HAVE_X_WINDOWS) && defined(HAVE_MENUBARS)
   if (lw_menu_active)
     {
-      result = command_builder_operate_menu_accelerator (builder);
-      return result;
+      return command_builder_operate_menu_accelerator (builder);
     }
   else
     {
-      result=Qnil;
+      result = Qnil;
       if (EQ (Vmenu_accelerator_enabled, Qmenu_force))
 	result = command_builder_find_menu_accelerator (builder);
       if (NILP (result))
@@ -4168,20 +4122,16 @@
 	      maybe_echo_keys (command_builder, 0);
 	  }
 	else if (!NILP (Vquit_flag)) {
-	  Lisp_Object event = Fmake_event();
-	  struct Lisp_Event *e = XEVENT (event);
-	  struct console *con;
-	  int ch;
-	  
+	  Lisp_Object quit_event = Fmake_event();
+	  struct Lisp_Event *e = XEVENT (quit_event);
 	  /* if quit happened during menu acceleration, pretend we read it */
-	  con = XCONSOLE (Fselected_console ());
-	  
-	  ch = CONSOLE_QUIT_CHAR (con);
-	  
+	  struct console *con = XCONSOLE (Fselected_console ());
+	  int ch = CONSOLE_QUIT_CHAR (con);
+
 	  character_to_event (ch, e, con, 1);
 	  e->channel = make_console (con);
-	  
-	  enqueue_command_event (event);
+
+	  enqueue_command_event (quit_event);
 	  Vquit_flag = Qnil;
 	}
       }
@@ -4213,16 +4163,21 @@
   GCPRO1 (event); /* event may be freshly created */
   reset_current_events (command_builder);
 
-  if (XEVENT (event)->event_type == key_press_event)
-    Vcurrent_mouse_event = Qnil;
-  else if (XEVENT (event)->event_type == button_press_event
-	   || XEVENT (event)->event_type == button_release_event
-	   || XEVENT (event)->event_type == misc_user_event)
-    Vcurrent_mouse_event = Fcopy_event (event, Qnil);
-
-  /* Store the last-command-event.  The semantics of this is that it is
-     the last event most recently involved in command-lookup.
-     */
+  switch (XEVENT (event)->event_type)
+    {
+    case key_press_event:
+      Vcurrent_mouse_event = Qnil;
+      break;
+    case button_press_event:
+    case button_release_event:
+    case misc_user_event:
+      Vcurrent_mouse_event = Fcopy_event (event, Qnil);
+      break;
+    default: break;
+    }
+
+  /* Store the last-command-event.  The semantics of this is that it
+     is the last event most recently involved in command-lookup. */
   if (!EVENTP (Vlast_command_event))
     Vlast_command_event = Fmake_event ();
   if (XEVENT (Vlast_command_event)->event_type == dead_event)
@@ -4235,20 +4190,16 @@
     Fcopy_event (event, Vlast_command_event);
 
   /* Note that last-command-char will never have its high-bit set, in
-     an effort to sidestep the ambiguity between M-x and oslash.
-     */
+     an effort to sidestep the ambiguity between M-x and oslash. */
   Vlast_command_char = Fevent_to_character (Vlast_command_event,
 					    Qnil, Qnil, Qnil);
 
   /* Actually call the command, with all sorts of hair to preserve or clear
      the echo-area and region as appropriate and call the pre- and post-
-     command-hooks.
-     */
+     command-hooks. */
   {
     int old_kbd_macro = con->kbd_macro_end;
-    struct window *w;
-
-    w = XWINDOW (Fselected_window (Qnil));
+    struct window *w = XWINDOW (Fselected_window (Qnil));
 
     /* We're executing a new command, so the old value is irrelevant. */
     zmacs_region_stays = 0;
@@ -4272,29 +4223,28 @@
       }
     else
       {
-#if 0
-	call3 (Qcommand_execute, Vthis_command, Qnil, Qnil);
-#else
 	Fcommand_execute (Vthis_command, Qnil, Qnil);
-#endif
       }
 
     post_command_hook ();
 
-    if (!NILP (con->prefix_arg))
+#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))
       {
 	/* 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. */
 	maybe_echo_keys (command_builder, 0);
 
 	/* If we're recording a keyboard macro, and the last command
 	   executed set a prefix argument, then decrement the pointer to
 	   the "last character really in the macro" to be just before this
 	   command.  This is so that the ^U in "^U ^X )" doesn't go onto
-	   the end of macro.
-	   */
+	   the end of macro. */
 	if (!NILP (con->defining_kbd_macro))
 	  con->kbd_macro_end = old_kbd_macro;
       }
@@ -4449,9 +4399,8 @@
     case button_release_event:
     case key_press_event:
       {
-	Lisp_Object leaf;
-
-	leaf = lookup_command_event (command_builder, event, 1);
+	Lisp_Object leaf = lookup_command_event (command_builder, event, 1);
+
 	if (KEYMAPP (leaf))
 	  /* Incomplete key sequence */
 	  break;
@@ -4486,8 +4435,7 @@
 		XEVENT_TYPE (terminal) = button_release_event;
 		/* If the "up" version is bound, don't complain. */
 		no_bitching
-		  = !NILP (command_builder_find_leaf
-			   (command_builder, 0));
+		  = !NILP (command_builder_find_leaf (command_builder, 0));
 		/* Undo the temporary changes we just made. */
 		XEVENT_TYPE (terminal) = button_press_event;
 		if (no_bitching)
@@ -4516,15 +4464,13 @@
 	      }
 
 	    /* Complain that the typed sequence is not defined, if this is the
-	       kind of sequence that warrants a complaint.
-	       */
+	       kind of sequence that warrants a complaint. */
 	    XCONSOLE (console)->defining_kbd_macro = Qnil;
 	    XCONSOLE (console)->prefix_arg = Qnil;
 	    /* Don't complain about undefined button-release events */
 	    if (XEVENT_TYPE (terminal) != button_release_event)
 	      {
-		Lisp_Object keys =
-		  current_events_into_vector (command_builder);
+		Lisp_Object keys = current_events_into_vector (command_builder);
 		struct gcpro gcpro1;
 
 		/* Run the pre-command-hook before barfing about an undefined
@@ -4610,7 +4556,7 @@
 
 	/* clear the echo area */
 	reset_key_echo (command_builder, 1);
-	
+
 	command_builder->self_insert_countdown = 0;
 	if (NILP (XCONSOLE (console)->prefix_arg)
 	    && NILP (Vexecuting_macro)
@@ -4886,7 +4832,7 @@
 
   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");
@@ -5056,7 +5002,7 @@
 
   DEFVAR_LISP ("current-mouse-event", &Vcurrent_mouse_event /*
 The mouse-button event which invoked this command, or nil.
-This is usually what `(interactive \"e\")' returns.
+This is usually what `(interactive "e")' returns.
 */ );
   Vcurrent_mouse_event = Qnil;
 
@@ -5228,7 +5174,7 @@
 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
@@ -5238,7 +5184,7 @@
 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
+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