]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
Parallelize documentation builds.
[gnu-emacs] / src / keyboard.c
index 582c35987179abf0bb5d5bfa79768671e6a1a01e..9cb9dd0b47b4bcd5894384fdf00b6adbf708c9e2 100644 (file)
@@ -1,6 +1,7 @@
 /* Keyboard and mouse input; editor command loop.
 
-Copyright (C) 1985-1989, 1993-1997, 1999-2012  Free Software Foundation, Inc.
+Copyright (C) 1985-1989, 1993-1997, 1999-2013 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -366,7 +367,7 @@ Lisp_Object Qmenu_bar;
 
 static Lisp_Object recursive_edit_unwind (Lisp_Object buffer);
 static Lisp_Object command_loop (void);
-static Lisp_Object Qextended_command_history;
+static Lisp_Object Qcommand_execute;
 EMACS_TIME timer_check (void);
 
 static void echo_now (void);
@@ -416,10 +417,9 @@ static void (*keyboard_init_hook) (void);
 
 static bool get_input_pending (int);
 static bool readable_events (int);
-static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *,
+static Lisp_Object read_char_x_menu_prompt (Lisp_Object,
                                             Lisp_Object, bool *);
-static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t,
-                                                  Lisp_Object *);
+static Lisp_Object read_char_minibuf_menu_prompt (int, Lisp_Object);
 static Lisp_Object make_lispy_event (struct input_event *);
 static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object,
                                         enum scroll_bar_part,
@@ -496,97 +496,103 @@ kset_system_key_syms (struct kboard *kb, Lisp_Object val)
 }
 
 \f
-/* Add C to the echo string, if echoing is going on.
-   C can be a character, which is printed prettily ("M-C-x" and all that
-   jazz), or a symbol, whose name is printed.  */
+/* Add C to the echo string, without echoing it immediately.  C can be
+   a character, which is pretty-printed, or a symbol, whose name is
+   printed.  */
 
 static void
-echo_char (Lisp_Object c)
+echo_add_key (Lisp_Object c)
 {
-  if (current_kboard->immediate_echo)
-    {
-      int size = KEY_DESCRIPTION_SIZE + 100;
-      char *buffer = alloca (size);
-      char *ptr = buffer;
-      Lisp_Object echo_string;
+  int size = KEY_DESCRIPTION_SIZE + 100;
+  char *buffer = alloca (size);
+  char *ptr = buffer;
+  Lisp_Object echo_string;
 
-      echo_string = KVAR (current_kboard, echo_string);
+  echo_string = KVAR (current_kboard, echo_string);
 
-      /* If someone has passed us a composite event, use its head symbol.  */
-      c = EVENT_HEAD (c);
+  /* If someone has passed us a composite event, use its head symbol.  */
+  c = EVENT_HEAD (c);
 
-      if (INTEGERP (c))
+  if (INTEGERP (c))
+    ptr = push_key_description (XINT (c), ptr);
+  else if (SYMBOLP (c))
+    {
+      Lisp_Object name = SYMBOL_NAME (c);
+      int nbytes = SBYTES (name);
+
+      if (size - (ptr - buffer) < nbytes)
        {
-         ptr = push_key_description (XINT (c), ptr);
+         int offset = ptr - buffer;
+         size = max (2 * size, size + nbytes);
+         buffer = alloca (size);
+         ptr = buffer + offset;
        }
-      else if (SYMBOLP (c))
-       {
-         Lisp_Object name = SYMBOL_NAME (c);
-         int nbytes = SBYTES (name);
 
-         if (size - (ptr - buffer) < nbytes)
-           {
-             int offset = ptr - buffer;
-             size = max (2 * size, size + nbytes);
-             buffer = alloca (size);
-             ptr = buffer + offset;
-           }
+      ptr += copy_text (SDATA (name), (unsigned char *) ptr, nbytes,
+                       STRING_MULTIBYTE (name), 1);
+    }
 
-         ptr += copy_text (SDATA (name), (unsigned char *) ptr, nbytes,
-                           STRING_MULTIBYTE (name), 1);
-       }
+  if ((NILP (echo_string) || SCHARS (echo_string) == 0)
+      && help_char_p (c))
+    {
+      const char *text = " (Type ? for further options)";
+      int len = strlen (text);
 
-      if ((NILP (echo_string) || SCHARS (echo_string) == 0)
-         && help_char_p (c))
+      if (size - (ptr - buffer) < len)
        {
-         const char *text = " (Type ? for further options)";
-         int len = strlen (text);
-
-         if (size - (ptr - buffer) < len)
-           {
-             int offset = ptr - buffer;
-             size += len;
-             buffer = alloca (size);
-             ptr = buffer + offset;
-           }
-
-         memcpy (ptr, text, len);
-         ptr += len;
+         int offset = ptr - buffer;
+         size += len;
+         buffer = alloca (size);
+         ptr = buffer + offset;
        }
 
-      /* Replace a dash from echo_dash with a space, otherwise
-        add a space at the end as a separator between keys.  */
-      if (STRINGP (echo_string)
-         && SCHARS (echo_string) > 1)
-       {
-         Lisp_Object last_char, prev_char, idx;
+      memcpy (ptr, text, len);
+      ptr += len;
+    }
+
+  /* Replace a dash from echo_dash with a space, otherwise add a space
+     at the end as a separator between keys.  */
+  if (STRINGP (echo_string) && SCHARS (echo_string) > 1)
+    {
+      Lisp_Object last_char, prev_char, idx;
 
-         idx = make_number (SCHARS (echo_string) - 2);
-         prev_char = Faref (echo_string, idx);
+      idx = make_number (SCHARS (echo_string) - 2);
+      prev_char = Faref (echo_string, idx);
 
-         idx = make_number (SCHARS (echo_string) - 1);
-         last_char = Faref (echo_string, idx);
+      idx = make_number (SCHARS (echo_string) - 1);
+      last_char = Faref (echo_string, idx);
 
-         /* We test PREV_CHAR to make sure this isn't the echoing
-            of a minus-sign.  */
-         if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
-           Faset (echo_string, idx, make_number (' '));
-         else
-           echo_string = concat2 (echo_string, build_string (" "));
-       }
-      else if (STRINGP (echo_string))
+      /* We test PREV_CHAR to make sure this isn't the echoing of a
+        minus-sign.  */
+      if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
+       Faset (echo_string, idx, make_number (' '));
+      else
        echo_string = concat2 (echo_string, build_string (" "));
+    }
+  else if (STRINGP (echo_string) && SCHARS (echo_string) > 0)
+    echo_string = concat2 (echo_string, build_string (" "));
+
+  kset_echo_string
+    (current_kboard,
+     concat2 (echo_string, make_string (buffer, ptr - buffer)));
+}
 
-      kset_echo_string
-       (current_kboard,
-        concat2 (echo_string, make_string (buffer, ptr - buffer)));
+/* Add C to the echo string, if echoing is going on.  C can be a
+   character or a symbol.  */
 
+static void
+echo_char (Lisp_Object c)
+{
+  if (current_kboard->immediate_echo)
+    {
+      echo_add_key (c);
       echo_now ();
     }
 }
 
 /* Temporarily add a dash to the end of the echo string if it's not
-   empty, so that it serves as a mini-prompt for the very next character.  */
+   empty, so that it serves as a mini-prompt for the very next
+   character.  */
 
 static void
 echo_dash (void)
@@ -668,9 +674,8 @@ echo_now (void)
     }
 
   echoing = 1;
-  message3_nolog (KVAR (current_kboard, echo_string),
-                 SBYTES (KVAR (current_kboard, echo_string)),
-                 STRING_MULTIBYTE (KVAR (current_kboard, echo_string)));
+  /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak).  */
+  message3_nolog (KVAR (current_kboard, echo_string));
   echoing = 0;
 
   /* Record in what buffer we echoed, and from which kboard.  */
@@ -1180,13 +1185,13 @@ top_level_2 (void)
 static Lisp_Object
 top_level_1 (Lisp_Object ignore)
 {
-  /* On entry to the outer level, run the startup file */
+  /* On entry to the outer level, run the startup file */
   if (!NILP (Vtop_level))
     internal_condition_case (top_level_2, Qerror, cmd_error);
   else if (!NILP (Vpurify_flag))
-    message ("Bare impure Emacs (standard Lisp code not loaded)");
+    message1 ("Bare impure Emacs (standard Lisp code not loaded)");
   else
-    message ("Bare Emacs (standard Lisp code not loaded)");
+    message1 ("Bare Emacs (standard Lisp code not loaded)");
   return Qnil;
 }
 
@@ -1422,7 +1427,7 @@ command_loop_1 (void)
          sit_for (Vminibuffer_message_timeout, 0, 2);
 
          /* Clear the echo area.  */
-         message2 (0, 0, 0);
+         message1 (0);
          safe_run_hooks (Qecho_area_clear_hook);
 
          unbind_to (count, Qnil);
@@ -1578,11 +1583,11 @@ command_loop_1 (void)
                  = (EQ (undo, BVAR (current_buffer, undo_list))
                     ? Qnil : BVAR (current_buffer, undo_list));
              }
-            Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
+            call1 (Qcommand_execute, Vthis_command);
 
 #ifdef HAVE_WINDOW_SYSTEM
          /* Do not check display_hourglass_p here, because
-            Fcommand_execute could change it, but we should cancel
+            `command-execute' could change it, but we should cancel
             hourglass cursor anyway.
             But don't cancel the hourglass within a macro
             just because a command in the macro finishes.  */
@@ -2225,13 +2230,12 @@ do { if (! polling_stopped_here) stop_polling ();       \
 do { if (polling_stopped_here) start_polling ();       \
        polling_stopped_here = 0; } while (0)
 
-/* read a character from the keyboard; call the redisplay if needed */
+/* Read a character from the keyboard; call the redisplay if needed.  */
 /* commandflag 0 means do not autosave, but do redisplay.
    -1 means do not redisplay, but do autosave.
    1 means do both.  */
 
-/* The arguments MAPS and NMAPS are for menu prompting.
-   MAPS is an array of keymaps;  NMAPS is the length of MAPS.
+/* The arguments MAP is for menu prompting.  MAP is a keymap.
 
    PREV_EVENT is the previous input event, or nil if we are reading
    the first event of a key sequence (or not reading a key sequence).
@@ -2253,7 +2257,7 @@ do { if (polling_stopped_here) start_polling ();  \
    Value is t if we showed a menu and the user rejected it.  */
 
 Lisp_Object
-read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
+read_char (int commandflag, Lisp_Object map,
           Lisp_Object prev_event,
           bool *used_mouse_menu, EMACS_TIME *end_time)
 {
@@ -2401,7 +2405,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
       goto reread_first;
     }
 
-  /* if redisplay was requested */
+  /* If redisplay was requested.  */
   if (commandflag >= 0)
     {
       bool echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
@@ -2410,7 +2414,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
           user-visible, such as X selection_request events.  */
       if (input_pending
          || detect_input_pending_run_timers (0))
-       swallow_events (0);             /* may clear input_pending */
+       swallow_events (0);             /* May clear input_pending.  */
 
       /* Redisplay if no pending input.  */
       while (!input_pending)
@@ -2480,13 +2484,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
      menu prompting. If EVENT_HAS_PARAMETERS then we are reading
      after a mouse event so don't try a minibuf menu.  */
   c = Qnil;
-  if (nmaps > 0 && INTERACTIVE
+  if (KEYMAPP (map) && INTERACTIVE
       && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
       /* Don't bring up a menu if we already have another event.  */
       && NILP (Vunread_command_events)
       && !detect_input_pending_run_timers (0))
     {
-      c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
+      c = read_char_minibuf_menu_prompt (commandflag, map);
 
       if (INTEGERP (c) && XINT (c) == -2)
         return c;               /* wrong_kboard_jmpbuf */
@@ -2610,7 +2614,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
      because the recursive call of read_char in read_char_minibuf_menu_prompt
      does not pass on any keymaps.  */
 
-  if (nmaps > 0 && INTERACTIVE
+  if (KEYMAPP (map) && INTERACTIVE
       && !NILP (prev_event)
       && EVENT_HAS_PARAMETERS (prev_event)
       && !EQ (XCAR (prev_event), Qmenu_bar)
@@ -2618,7 +2622,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
       /* Don't bring up a menu if we already have another event.  */
       && NILP (Vunread_command_events))
     {
-      c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+      c = read_char_x_menu_prompt (map, prev_event, used_mouse_menu);
 
       /* Now that we have read an event, Emacs is not idle.  */
       if (!end_time)
@@ -2653,9 +2657,10 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
          && XINT (Vauto_save_timeout) > 0)
        {
          Lisp_Object tem0;
-         EMACS_INT timeout = (delay_level
-                              * min (XFASTINT (Vauto_save_timeout) / 4,
-                                     MOST_POSITIVE_FIXNUM / delay_level));
+         EMACS_INT timeout = XFASTINT (Vauto_save_timeout);
+
+         timeout = min (timeout, MOST_POSITIVE_FIXNUM / delay_level * 4);
+         timeout = delay_level * timeout / 4;
          save_getcjmp (save_jump);
          restore_getcjmp (local_getcjmp);
          tem0 = sit_for (make_number (timeout), 1, 1);
@@ -2837,7 +2842,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
     {
       struct buffer *prev_buffer = current_buffer;
       last_input_event = c;
-      Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt);
+      call4 (Qcommand_execute, tem, Qnil, Fvector (1, &last_input_event), Qt);
 
       if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
        /* We stopped being idle for this event; undo that.  This
@@ -2996,7 +3001,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
 
       /* If we are not reading a key sequence,
         never use the echo area.  */
-      if (maps == 0)
+      if (!KEYMAPP (map))
        {
          specbind (Qinput_method_use_echo_area, Qt);
        }
@@ -3089,7 +3094,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
   last_input_event = c;
   num_input_events++;
 
-  /* Process the help character specially if enabled */
+  /* Process the help character specially if enabled */
   if (!NILP (Vhelp_form) && help_char_p (c))
     {
       ptrdiff_t count = SPECPDL_INDEX ();
@@ -3103,13 +3108,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
       cancel_echoing ();
       do
        {
-         c = read_char (0, 0, 0, Qnil, 0, NULL);
+         c = read_char (0, Qnil, Qnil, 0, NULL);
          if (EVENT_HAS_PARAMETERS (c)
              && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_click))
            XSETCAR (help_form_saved_window_configs, Qnil);
        }
       while (BUFFERP (c));
-      /* Remove the help from the frame */
+      /* Remove the help from the frame */
       unbind_to (count, Qnil);
 
       redisplay ();
@@ -3117,7 +3122,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
        {
          cancel_echoing ();
          do
-           c = read_char (0, 0, 0, Qnil, 0, NULL);
+           c = read_char (0, Qnil, Qnil, 0, NULL);
          while (BUFFERP (c));
        }
     }
@@ -8307,9 +8312,9 @@ init_tool_bar_items (Lisp_Object reuse)
 static void
 append_tool_bar_item (void)
 {
-  ptrdiff_t incr =
-    (ntool_bar_items
-     - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
+  ptrdiff_t incr
+    (ntool_bar_items
+       - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
 
   /* Enlarge tool_bar_items_vector if necessary.  */
   if (0 < incr)
@@ -8327,8 +8332,8 @@ append_tool_bar_item (void)
 
 
 \f
-/* Read a character using menus based on maps in the array MAPS.
-   NMAPS is the length of MAPS.  Return nil if there are no menus in the maps.
+/* Read a character using menus based on the keymap MAP.
+   Return nil if there are no menus in the maps.
    Return t if we displayed a menu but the user rejected it.
 
    PREV_EVENT is the previous input event, or nil if we are reading
@@ -8348,28 +8353,17 @@ append_tool_bar_item (void)
    and do auto-saving in the inner call of read_char.  */
 
 static Lisp_Object
-read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
+read_char_x_menu_prompt (Lisp_Object map,
                         Lisp_Object prev_event, bool *used_mouse_menu)
 {
-#ifdef HAVE_MENUS
-  ptrdiff_t mapno;
-#endif
-
   if (used_mouse_menu)
     *used_mouse_menu = 0;
 
-  /* Use local over global Menu maps */
+  /* Use local over global Menu maps */
 
   if (! menu_prompting)
     return Qnil;
 
-  /* Optionally disregard all but the global map.  */
-  if (inhibit_local_menu_bar_menus)
-    {
-      maps += (nmaps - 1);
-      nmaps = 1;
-    }
-
 #ifdef HAVE_MENUS
   /* If we got to this point via a mouse click,
      use a real menu for mouse selection.  */
@@ -8378,16 +8372,9 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
       && !EQ (XCAR (prev_event), Qtool_bar))
     {
       /* Display the menu and get the selection.  */
-      Lisp_Object *realmaps = alloca (nmaps * sizeof *realmaps);
       Lisp_Object value;
-      ptrdiff_t nmaps1 = 0;
-
-      /* Use the maps that are not nil.  */
-      for (mapno = 0; mapno < nmaps; mapno++)
-       if (!NILP (maps[mapno]))
-         realmaps[nmaps1++] = maps[mapno];
 
-      value = Fx_popup_menu (prev_event, Flist (nmaps1, realmaps));
+      value = Fx_popup_menu (prev_event, get_keymap (map, 0, 1));
       if (CONSP (value))
        {
          Lisp_Object tem;
@@ -8427,17 +8414,10 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
   return Qnil ;
 }
 
-/* Buffer in use so far for the minibuf prompts for menu keymaps.
-   We make this bigger when necessary, and never free it.  */
-static char *read_char_minibuf_menu_text;
-/* Size of that buffer.  */
-static ptrdiff_t read_char_minibuf_menu_width;
-
 static Lisp_Object
 read_char_minibuf_menu_prompt (int commandflag,
-                              ptrdiff_t nmaps, Lisp_Object *maps)
+                              Lisp_Object map)
 {
-  ptrdiff_t mapno;
   register Lisp_Object name;
   ptrdiff_t nlength;
   /* FIXME: Use the minibuffer's frame width.  */
@@ -8445,53 +8425,35 @@ read_char_minibuf_menu_prompt (int commandflag,
   ptrdiff_t idx = -1;
   bool nobindings = 1;
   Lisp_Object rest, vector;
-  char *menu;
+  Lisp_Object prompt_strings = Qnil;
 
   vector = Qnil;
-  name = Qnil;
 
   if (! menu_prompting)
     return Qnil;
 
-  /* Get the menu name from the first map that has one (a prompt string).  */
-  for (mapno = 0; mapno < nmaps; mapno++)
-    {
-      name = Fkeymap_prompt (maps[mapno]);
-      if (!NILP (name))
-       break;
-    }
+  map = get_keymap (map, 0, 1);
+  name = Fkeymap_prompt (map);
 
   /* If we don't have any menus, just read a character normally.  */
   if (!STRINGP (name))
     return Qnil;
 
-  /* Make sure we have a big enough buffer for the menu text.  */
-  width = max (width, SBYTES (name));
-  if (STRING_BYTES_BOUND - 4 < width)
-    memory_full (SIZE_MAX);
-  if (width + 4 > read_char_minibuf_menu_width)
-    {
-      read_char_minibuf_menu_text
-       = xrealloc (read_char_minibuf_menu_text, width + 4);
-      read_char_minibuf_menu_width = width + 4;
-    }
-  menu = read_char_minibuf_menu_text;
+#define PUSH_C_STR(str, listvar) \
+  listvar = Fcons (make_unibyte_string (str, strlen (str)), listvar)
 
   /* Prompt string always starts with map's prompt, and a space.  */
-  strcpy (menu, SSDATA (name));
-  nlength = SBYTES (name);
-  menu[nlength++] = ':';
-  menu[nlength++] = ' ';
-  menu[nlength] = 0;
+  prompt_strings = Fcons (name, prompt_strings);
+  PUSH_C_STR (": ", prompt_strings);
+  nlength = SCHARS (name) + 2;
 
-  /* Start prompting at start of first map.  */
-  mapno = 0;
-  rest = maps[mapno];
+  rest = map;
 
   /* Present the documented bindings, a line at a time.  */
   while (1)
     {
       bool notfirst = 0;
+      Lisp_Object menu_strings = prompt_strings;
       ptrdiff_t i = nlength;
       Lisp_Object obj;
       Lisp_Object orig_defn_macro;
@@ -8501,18 +8463,16 @@ read_char_minibuf_menu_prompt (int commandflag,
        {
          Lisp_Object elt;
 
-         /* If reached end of map, start at beginning of next map.  */
+         /* FIXME: Use map_keymap to handle new keymap formats.  */
+
+         /* At end of map, wrap around if just starting,
+            or end this line if already have something on it.  */
          if (NILP (rest))
            {
-             mapno++;
-             /* At end of last map, wrap around to first map if just starting,
-                or end this line if already have something on it.  */
-             if (mapno == nmaps)
-               {
-                 mapno = 0;
-                 if (notfirst || nobindings) break;
-               }
-             rest = maps[mapno];
+             if (notfirst || nobindings)
+               break;
+             else
+               rest = map;
            }
 
          /* Look at the next element of the map.  */
@@ -8596,7 +8556,7 @@ read_char_minibuf_menu_prompt (int commandflag,
                      /* Punctuate between strings.  */
                      if (notfirst)
                        {
-                         strcpy (menu + i, ", ");
+                         PUSH_C_STR (", ", menu_strings);
                          i += 2;
                        }
                      notfirst = 1;
@@ -8608,23 +8568,28 @@ read_char_minibuf_menu_prompt (int commandflag,
                        {
                          /* Add as much of string as fits.  */
                          thiswidth = min (SCHARS (desc), width - i);
-                         memcpy (menu + i, SDATA (desc), thiswidth);
+                         menu_strings
+                           = Fcons (Fsubstring (desc, make_number (0),
+                                                make_number (thiswidth)),
+                                    menu_strings);
                          i += thiswidth;
-                         strcpy (menu + i, " = ");
+                         PUSH_C_STR (" = ", menu_strings);
                          i += 3;
                        }
 
                      /* Add as much of string as fits.  */
                      thiswidth = min (SCHARS (s), width - i);
-                     memcpy (menu + i, SDATA (s), thiswidth);
+                     menu_strings
+                       = Fcons (Fsubstring (s, make_number (0),
+                                            make_number (thiswidth)),
+                                menu_strings);
                      i += thiswidth;
-                     menu[i] = 0;
                    }
                  else
                    {
                      /* If this element does not fit, end the line now,
                         and save the element for the next line.  */
-                     strcpy (menu + i, "...");
+                     PUSH_C_STR ("...", menu_strings);
                      break;
                    }
                }
@@ -8641,23 +8606,19 @@ read_char_minibuf_menu_prompt (int commandflag,
        }
 
       /* Prompt with that and read response.  */
-      message2_nolog (menu, strlen (menu),
-                     ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
+      message3_nolog (apply1 (intern ("concat"), Fnreverse (menu_strings)));
 
-      /* Make believe its not a keyboard macro in case the help char
+      /* Make believe it's not a keyboard macro in case the help char
         is pressed.  Help characters are not recorded because menu prompting
-        is not used on replay.
-        */
+        is not used on replay.  */
       orig_defn_macro = KVAR (current_kboard, defining_kbd_macro);
       kset_defining_kbd_macro (current_kboard, Qnil);
       do
-       obj = read_char (commandflag, 0, 0, Qt, 0, NULL);
+       obj = read_char (commandflag, Qnil, Qt, 0, NULL);
       while (BUFFERP (obj));
       kset_defining_kbd_macro (current_kboard, orig_defn_macro);
 
-      if (!INTEGERP (obj))
-       return obj;
-      else if (XINT (obj) == -2)
+      if (!INTEGERP (obj) || XINT (obj) == -2)
         return obj;
 
       if (! EQ (obj, menu_prompt_more_char)
@@ -8668,52 +8629,25 @@ read_char_minibuf_menu_prompt (int commandflag,
            store_kbd_macro_char (obj);
          return obj;
        }
-      /* Help char - go round again */
+      /* Help char - go round again */
     }
 }
 \f
 /* Reading key sequences.  */
 
-/* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings
-   in DEFS[0..NMAPS-1].  Set NEXT[i] to DEFS[i] if DEFS[i] is a
-   keymap, or nil otherwise.  Return the index of the first keymap in
-   which KEY has any binding, or NMAPS if no map has a binding.
-
-   If KEY is a meta ASCII character, treat it like meta-prefix-char
-   followed by the corresponding non-meta character.  Keymaps in
-   CURRENT with non-prefix bindings for meta-prefix-char become nil in
-   NEXT.
-
-   If KEY has no bindings in any of the CURRENT maps, NEXT is left
-   unmodified.
-
-   NEXT may be the same array as CURRENT.  */
-
-static int
-follow_key (Lisp_Object key, ptrdiff_t nmaps, Lisp_Object *current,
-           Lisp_Object *defs, Lisp_Object *next)
+static Lisp_Object
+follow_key (Lisp_Object keymap, Lisp_Object key)
 {
-  ptrdiff_t i, first_binding;
-
-  first_binding = nmaps;
-  for (i = nmaps - 1; i >= 0; i--)
-    {
-      if (! NILP (current[i]))
-       {
-         defs[i] = access_keymap (current[i], key, 1, 0, 1);
-         if (! NILP (defs[i]))
-           first_binding = i;
-       }
-      else
-       defs[i] = Qnil;
-    }
-
-  /* Given the set of bindings we've found, produce the next set of maps.  */
-  if (first_binding < nmaps)
-    for (i = 0; i < nmaps; i++)
-      next[i] = NILP (defs[i]) ? Qnil : get_keymap (defs[i], 0, 1);
+  return access_keymap (get_keymap (keymap, 0, 1),
+                       key, 1, 0, 1);
+}
 
-  return first_binding;
+static Lisp_Object
+active_maps (Lisp_Object first_event)
+{
+  Lisp_Object position
+    = CONSP (first_event) ? CAR_SAFE (XCDR (first_event)) : Qnil;
+  return Fcons (Qkeymap, Fcurrent_active_maps (Qt, position));
 }
 
 /* Structure used to keep track of partial application of key remapping
@@ -8845,8 +8779,9 @@ keyremap_step (Lisp_Object *keybuf, int bufsize, volatile keyremap *fkey,
 static bool
 test_undefined (Lisp_Object binding)
 {
-  return (EQ (binding, Qundefined)
-         || (!NILP (binding) && SYMBOLP (binding)
+  return (NILP (binding)
+         || EQ (binding, Qundefined)
+         || (SYMBOLP (binding)
              && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined)));
 }
 
@@ -8892,7 +8827,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                   bool dont_downcase_last, bool can_return_switch_frame,
                   bool fix_current_buffer)
 {
-  Lisp_Object from_string;
   ptrdiff_t count = SPECPDL_INDEX ();
 
   /* How many keys there are in the current key sequence.  */
@@ -8903,34 +8837,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
   ptrdiff_t echo_start IF_LINT (= 0);
   ptrdiff_t keys_start;
 
-  /* The number of keymaps we're scanning right now, and the number of
-     keymaps we have allocated space for.  */
-  ptrdiff_t nmaps;
-  ptrdiff_t nmaps_allocated = 0;
-
-  /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in
-     the current keymaps.  */
-  Lisp_Object *defs = NULL;
-
-  /* submaps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1]
-     in the current keymaps, or nil where it is not a prefix.  */
-  Lisp_Object *submaps = NULL;
-
-  /* The local map to start out with at start of key sequence.  */
-  Lisp_Object orig_local_map;
-
-  /* The map from the `keymap' property to start out with at start of
-     key sequence.  */
-  Lisp_Object orig_keymap;
+  Lisp_Object current_binding = Qnil;
+  Lisp_Object first_event = Qnil;
 
-  /* Positive if we have already considered switching to the local-map property
-     of the place where a mouse click occurred.  */
-  int localized_local_map = 0;
-
-  /* The index in submaps[] of the first keymap that has a binding for
-     this key sequence.  In other words, the lowest i such that
-     submaps[i] is non-nil.  */
-  ptrdiff_t first_binding;
   /* Index of the first key that has no binding.
      It is useless to try fkey.start larger than that.  */
   int first_unbound;
@@ -8973,11 +8882,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
      While we're reading, we keep the event here.  */
   Lisp_Object delayed_switch_frame;
 
-  /* See the comment below...  */
-#if defined (GOBBLE_FIRST_EVENT)
-  Lisp_Object first_event;
-#endif
-
   Lisp_Object original_uppercase IF_LINT (= Qnil);
   int original_uppercase_position = -1;
 
@@ -8989,10 +8893,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
   /* List of events for which a fake prefix key has been generated.  */
   Lisp_Object fake_prefixed_keys = Qnil;
 
-#if defined (GOBBLE_FIRST_EVENT)
-  int junk;
-#endif
-
   struct gcpro gcpro1;
 
   GCPRO1 (fake_prefixed_keys);
@@ -9028,21 +8928,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
   keys_start = this_command_key_count;
   this_single_command_key_start = keys_start;
 
-#if defined (GOBBLE_FIRST_EVENT)
-  /* This doesn't quite work, because some of the things that read_char
-     does cannot safely be bypassed.  It seems too risky to try to make
-     this work right.  */
-
-  /* Read the first char of the sequence specially, before setting
-     up any keymaps, in case a filter runs and switches buffers on us.  */
-  first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
-                          &junk, NULL);
-#endif /* GOBBLE_FIRST_EVENT */
-
-  orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
-  orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
-  from_string = Qnil;
-
   /* We jump here when we need to reinitialize fkey and keytran; this
      happens if we switch keyboards between rescans.  */
  replay_entire_sequence:
@@ -9067,59 +8952,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
      keybuf with its symbol, or if the sequence starts with a mouse
      click and we need to switch buffers, we jump back here to rebuild
      the initial keymaps from the current buffer.  */
-  nmaps = 0;
-
-  if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map)))
-    {
-      if (2 > nmaps_allocated)
-       {
-         submaps = alloca (2 * sizeof *submaps);
-         defs    = alloca (2 * sizeof *defs);
-         nmaps_allocated = 2;
-       }
-      submaps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
-    }
-  else if (!NILP (Voverriding_local_map))
-    {
-      if (2 > nmaps_allocated)
-       {
-         submaps = alloca (2 * sizeof *submaps);
-         defs    = alloca (2 * sizeof *defs);
-         nmaps_allocated = 2;
-       }
-      submaps[nmaps++] = Voverriding_local_map;
-    }
-  else
-    {
-      ptrdiff_t nminor;
-      ptrdiff_t total;
-      Lisp_Object *maps;
-
-      nminor = current_minor_maps (0, &maps);
-      total = nminor + (!NILP (orig_keymap) ? 3 : 2);
-
-      if (total > nmaps_allocated)
-       {
-         submaps = alloca (total * sizeof *submaps);
-         defs    = alloca (total * sizeof *defs);
-         nmaps_allocated = total;
-       }
-
-      if (!NILP (orig_keymap))
-       submaps[nmaps++] = orig_keymap;
-
-      memcpy (submaps + nmaps, maps, nminor * sizeof (submaps[0]));
-
-      nmaps += nminor;
-
-      submaps[nmaps++] = orig_local_map;
-    }
-  submaps[nmaps++] = current_global_map;
-
-  /* Find an accurate initial value for first_binding.  */
-  for (first_binding = 0; first_binding < nmaps; first_binding++)
-    if (! NILP (submaps[first_binding]))
-      break;
+  current_binding = active_maps (first_event);
 
   /* Start from the beginning in keybuf.  */
   t = 0;
@@ -9133,9 +8966,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
   /* If the best binding for the current key sequence is a keymap, or
      we may be looking at a function key's escape sequence, keep on
      reading.  */
-  while (first_binding < nmaps
+  while (!NILP (current_binding)
         /* Keep reading as long as there's a prefix binding.  */
-        ? !NILP (submaps[first_binding])
+        ? KEYMAPP (current_binding)
         /* Don't return in the middle of a possible function key sequence,
            if the only bindings we found were via case conversion.
            Thus, if ESC O a has a function-key-map translation
@@ -9159,7 +8992,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
         just one key.  */
       ptrdiff_t echo_local_start IF_LINT (= 0);
       int keys_local_start;
-      ptrdiff_t local_first_binding;
+      Lisp_Object new_binding;
 
       eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
       eassert (indec.start <= indec.end);
@@ -9196,7 +9029,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
       if (INTERACTIVE)
        echo_local_start = echo_length ();
       keys_local_start = this_command_key_count;
-      local_first_binding = first_binding;
 
     replay_key:
       /* These are no-ops, unless we throw away a keystroke below and
@@ -9206,7 +9038,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
       if (INTERACTIVE && t < mock_input)
        echo_truncate (echo_local_start);
       this_command_key_count = keys_local_start;
-      first_binding = local_first_binding;
 
       /* By default, assume each event is "real".  */
       last_real_key_start = t;
@@ -9217,8 +9048,12 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
          key = keybuf[t];
          add_command_key (key);
          if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
-             && NILP (Fzerop (Vecho_keystrokes)))
-           echo_char (key);
+             && NILP (Fzerop (Vecho_keystrokes))
+             && current_kboard->immediate_echo)
+           {
+             echo_add_key (key);
+             echo_dash ();
+           }
        }
 
       /* If not, we should actually read a character.  */
@@ -9227,8 +9062,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
          {
            KBOARD *interrupted_kboard = current_kboard;
            struct frame *interrupted_frame = SELECTED_FRAME ();
-           key = read_char (NILP (prompt), nmaps,
-                            (Lisp_Object *) submaps, last_nonmenu_event,
+           key = read_char (NILP (prompt),
+                            current_binding, last_nonmenu_event,
                             &used_mouse_menu, NULL);
            if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
                /* When switching to a new tty (with a new keyboard),
@@ -9283,8 +9118,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                              KVAR (interrupted_kboard, kbd_queue)));
                  }
                mock_input = 0;
-               orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
-               orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
                goto replay_entire_sequence;
              }
          }
@@ -9325,12 +9158,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                {
                  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
                    Fkill_emacs (Qnil);
-                 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+                 if (XBUFFER (XWINDOW (selected_window)->buffer)
+                     != current_buffer)
                    Fset_buffer (XWINDOW (selected_window)->buffer);
                }
 
-             orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
-             orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
              goto replay_sequence;
            }
 
@@ -9347,8 +9179,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
              keybuf[t++] = key;
              mock_input = t;
              Vquit_flag = Qnil;
-             orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
-             orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
              goto replay_sequence;
            }
 
@@ -9368,6 +9198,22 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                }
            }
 
+         if (NILP (first_event))
+           {
+             first_event = key;
+             /* Even if first_event does not specify a particular
+                window/position, it's important to recompute the maps here
+                since a long time might have passed since we entered
+                read_key_sequence, and a timer (or process-filter or
+                special-event-map, ...) might have switched the current buffer
+                or the selected window from under us in the mean time.  */
+             if (fix_current_buffer
+                 && (XBUFFER (XWINDOW (selected_window)->buffer)
+                     != current_buffer))
+               Fset_buffer (XWINDOW (selected_window)->buffer);
+             current_binding = active_maps (first_event);
+           }
+
          GROW_RAW_KEYBUF;
          ASET (raw_keybuf, raw_keybuf_count, key);
          raw_keybuf_count++;
@@ -9389,16 +9235,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
         or when user programs play with this-command-keys.  */
       if (EVENT_HAS_PARAMETERS (key))
        {
-         Lisp_Object kind;
-         Lisp_Object string;
-
-         kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
+         Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
          if (EQ (kind, Qmouse_click))
            {
-             Lisp_Object window, posn;
-
-             window = POSN_WINDOW (EVENT_START (key));
-             posn   = POSN_POSN (EVENT_START (key));
+             Lisp_Object window = POSN_WINDOW (EVENT_START (key));
+             Lisp_Object posn = POSN_POSN (EVENT_START (key));
 
              if (CONSP (posn)
                  || (!NILP (fake_prefixed_keys)
@@ -9441,58 +9282,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                      if (! FRAME_LIVE_P (XFRAME (selected_frame)))
                        Fkill_emacs (Qnil);
                      set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
-                     orig_local_map = get_local_map (PT, current_buffer,
-                                                     Qlocal_map);
-                     orig_keymap = get_local_map (PT, current_buffer,
-                                                  Qkeymap);
                      goto replay_sequence;
                    }
-
-                 /* For a mouse click, get the local text-property keymap
-                    of the place clicked on, rather than point.  */
-                 if (CONSP (XCDR (key))
-                     && ! localized_local_map)
-                   {
-                     Lisp_Object map_here, start, pos;
-
-                     localized_local_map = 1;
-                     start = EVENT_START (key);
-
-                     if (CONSP (start) && POSN_INBUFFER_P (start))
-                       {
-                         pos = POSN_BUFFER_POSN (start);
-                         if (INTEGERP (pos)
-                             && XINT (pos) >= BEGV
-                             && XINT (pos) <= ZV)
-                           {
-                             map_here = get_local_map (XINT (pos),
-                                                       current_buffer,
-                                                       Qlocal_map);
-                             if (!EQ (map_here, orig_local_map))
-                               {
-                                 orig_local_map = map_here;
-                                 ++localized_local_map;
-                               }
-
-                             map_here = get_local_map (XINT (pos),
-                                                       current_buffer,
-                                                       Qkeymap);
-                             if (!EQ (map_here, orig_keymap))
-                               {
-                                 orig_keymap = map_here;
-                                 ++localized_local_map;
-                               }
-
-                             if (localized_local_map > 1)
-                               {
-                                 keybuf[t] = key;
-                                 mock_input = t + 1;
-
-                                 goto replay_sequence;
-                               }
-                           }
-                       }
-                   }
                }
 
              /* Expand mode-line and scroll-bar events into two events:
@@ -9513,63 +9304,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                     prevent proper action when the event is pushed
                     back into unread-command-events.  */
                  fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
-
-                 /* If on a mode line string with a local keymap,
-                    reconsider the key sequence with that keymap.  */
-                 if (string = POSN_STRING (EVENT_START (key)),
-                     (CONSP (string) && STRINGP (XCAR (string))))
-                   {
-                     Lisp_Object pos, map, map2;
-
-                     pos = XCDR (string);
-                     string = XCAR (string);
-                      if (XINT (pos) >= 0
-                         && XINT (pos) < SCHARS (string))
-                        {
-                          map = Fget_text_property (pos, Qlocal_map, string);
-                          if (!NILP (map))
-                            orig_local_map = map;
-                          map2 = Fget_text_property (pos, Qkeymap, string);
-                          if (!NILP (map2))
-                            orig_keymap = map2;
-                          if (!NILP (map) || !NILP (map2))
-                            goto replay_sequence;
-                        }
-                   }
-
                  goto replay_key;
                }
-             else if (NILP (from_string)
-                      && (string = POSN_STRING (EVENT_START (key)),
-                          (CONSP (string) && STRINGP (XCAR (string)))))
-               {
-                 /* For a click on a string, i.e. overlay string or a
-                    string displayed via the `display' property,
-                    consider `local-map' and `keymap' properties of
-                    that string.  */
-                 Lisp_Object pos, map, map2;
-
-                 pos = XCDR (string);
-                 string = XCAR (string);
-                 if (XINT (pos) >= 0
-                     && XINT (pos) < SCHARS (string))
-                   {
-                     map = Fget_text_property (pos, Qlocal_map, string);
-                     if (!NILP (map))
-                       orig_local_map = map;
-                     map2 = Fget_text_property (pos, Qkeymap, string);
-                     if (!NILP (map2))
-                       orig_keymap = map2;
-
-                     if (!NILP (map) || !NILP (map2))
-                       {
-                         from_string = string;
-                         keybuf[t++] = key;
-                         mock_input = t;
-                         goto replay_sequence;
-                       }
-                   }
-               }
            }
          else if (CONSP (XCDR (key))
                   && CONSP (EVENT_START (key))
@@ -9585,7 +9321,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                  if (bufsize - t <= 1)
                    error ("Key sequence too long");
                  keybuf[t] = posn;
-                 keybuf[t+1] = key;
+                 keybuf[t + 1] = key;
 
                  /* Zap the position in key, so we know that we've
                     expanded it, and don't try to do so again.  */
@@ -9608,15 +9344,10 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
 
       /* We have finally decided that KEY is something we might want
         to look up.  */
-      first_binding = (follow_key (key,
-                                  nmaps   - first_binding,
-                                  submaps + first_binding,
-                                  defs    + first_binding,
-                                  submaps + first_binding)
-                      + first_binding);
+      new_binding = follow_key (current_binding, key);
 
       /* If KEY wasn't bound, we'll try some fallbacks.  */
-      if (first_binding < nmaps)
+      if (!NILP (new_binding))
        /* This is needed for the following scenario:
           event 0: a down-event that gets dropped by calling replay_key.
           event 1: some normal prefix like C-h.
@@ -9753,20 +9484,13 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                      new_click
                        = Fcons (new_head, Fcons (EVENT_START (key), Qnil));
 
-                     /* Look for a binding for this new key.  follow_key
-                        promises that it didn't munge submaps the
-                        last time we called it, since key was unbound.  */
-                     first_binding
-                       = (follow_key (new_click,
-                                      nmaps   - local_first_binding,
-                                      submaps + local_first_binding,
-                                      defs    + local_first_binding,
-                                      submaps + local_first_binding)
-                          + local_first_binding);
+                     /* Look for a binding for this new key.  */
+                     new_binding = follow_key (current_binding, new_click);
 
                      /* If that click is bound, go for it.  */
-                     if (first_binding < nmaps)
+                     if (!NILP (new_binding))
                        {
+                         current_binding = new_binding;
                          key = new_click;
                          break;
                        }
@@ -9775,6 +9499,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                }
            }
        }
+      current_binding = new_binding;
 
       keybuf[t++] = key;
       /* Normally, last_nonmenu_event gets the previous key we read.
@@ -9806,9 +9531,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
            }
        }
 
-      if (first_binding < nmaps
-         && NILP (submaps[first_binding])
-         && !test_undefined (defs[first_binding])
+      if (!KEYMAPP (current_binding)
+         && !test_undefined (current_binding)
          && indec.start >= t)
        /* There is a binding and it's not a prefix.
           (and it doesn't have any input-decode-map translation pending).
@@ -9837,8 +9561,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                                     first_binding >= nmaps) we don't want
                                     to apply this function-key-mapping.  */
                                  fkey.end + 1 == t
-                                 && (first_binding >= nmaps
-                                     || test_undefined (defs[first_binding])),
+                                 && (test_undefined (current_binding)),
                                  &diff, prompt);
            UNGCPRO;
            if (done)
@@ -9881,7 +9604,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
         and cannot be part of a function key or translation,
         and is an upper case letter
         use the corresponding lower-case letter instead.  */
-      if (first_binding >= nmaps
+      if (NILP (current_binding)
          && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
          && INTEGERP (key)
          && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK))
@@ -9912,7 +9635,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
         and cannot be part of a function key or translation,
         and is a shifted function key,
         use the corresponding unshifted function key instead.  */
-      if (first_binding >= nmaps
+      if (NILP (current_binding)
          && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t)
        {
          Lisp_Object breakdown = parse_modifiers (key);
@@ -9953,9 +9676,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
        }
     }
   if (!dummyflag)
-    read_key_sequence_cmd = (first_binding < nmaps
-                            ? defs[first_binding]
-                            : Qnil);
+    read_key_sequence_cmd = current_binding;
   read_key_sequence_remapped
     /* Remap command through active keymaps.
        Do the remapping here, before the unbind_to so it uses the keymaps
@@ -9969,7 +9690,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
 
   /* Don't downcase the last character if the caller says don't.
      Don't downcase it if the result is undefined, either.  */
-  if ((dont_downcase_last || first_binding >= nmaps)
+  if ((dont_downcase_last || NILP (current_binding))
       && t > 0
       && t - 1 == original_uppercase_position)
     {
@@ -10066,7 +9787,7 @@ will read just one key sequence.  */)
 
   memset (keybuf, 0, sizeof keybuf);
   GCPRO1 (keybuf[0]);
-  gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
+  gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0]));
 
   if (NILP (continue_echo))
     {
@@ -10080,7 +9801,7 @@ will read just one key sequence.  */)
     cancel_hourglass ();
 #endif
 
-  i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
+  i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
                         prompt, ! NILP (dont_downcase_last),
                         ! NILP (can_return_switch_frame), 0);
 
@@ -10154,95 +9875,6 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
   UNGCPRO;
   return unbind_to (count, Fvector (i, keybuf));
 }
-\f
-DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
-       doc: /* Execute CMD as an editor command.
-CMD must be a symbol that satisfies the `commandp' predicate.
-Optional second arg RECORD-FLAG non-nil
-means unconditionally put this command in `command-history'.
-Otherwise, that is done only if an arg is read using the minibuffer.
-The argument KEYS specifies the value to use instead of (this-command-keys)
-when reading the arguments; if it is nil, (this-command-keys) is used.
-The argument SPECIAL, if non-nil, means that this command is executing
-a special event, so ignore the prefix argument and don't clear it.  */)
-  (Lisp_Object cmd, Lisp_Object record_flag, Lisp_Object keys, Lisp_Object special)
-{
-  register Lisp_Object final;
-  register Lisp_Object tem;
-  Lisp_Object prefixarg;
-
-  debug_on_next_call = 0;
-
-  if (NILP (special))
-    {
-      prefixarg = KVAR (current_kboard, Vprefix_arg);
-      Vcurrent_prefix_arg = prefixarg;
-      kset_prefix_arg (current_kboard, Qnil);
-    }
-  else
-    prefixarg = Qnil;
-
-  if (SYMBOLP (cmd))
-    {
-      tem = Fget (cmd, Qdisabled);
-      if (!NILP (tem))
-       {
-         tem = Fsymbol_value (Qdisabled_command_function);
-         if (!NILP (tem))
-           return Frun_hooks (1, &Qdisabled_command_function);
-       }
-    }
-
-  while (1)
-    {
-      final = Findirect_function (cmd, Qnil);
-
-      if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
-       {
-         struct gcpro gcpro1, gcpro2;
-
-         GCPRO2 (cmd, prefixarg);
-         Fautoload_do_load (final, cmd, Qnil);
-         UNGCPRO;
-       }
-      else
-       break;
-    }
-
-  if (STRINGP (final) || VECTORP (final))
-    {
-      /* If requested, place the macro in the command history.  For
-        other sorts of commands, call-interactively takes care of
-        this.  */
-      if (!NILP (record_flag))
-       {
-         Vcommand_history
-           = Fcons (Fcons (Qexecute_kbd_macro,
-                           Fcons (final, Fcons (prefixarg, Qnil))),
-                    Vcommand_history);
-
-         /* Don't keep command history around forever.  */
-         if (NUMBERP (Vhistory_length) && XINT (Vhistory_length) > 0)
-           {
-             tem = Fnthcdr (Vhistory_length, Vcommand_history);
-             if (CONSP (tem))
-               XSETCDR (tem, Qnil);
-           }
-       }
-
-      return Fexecute_kbd_macro (final, prefixarg, Qnil);
-    }
-
-  if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
-    /* Don't call Fcall_interactively directly because we want to make
-       sure the backtrace has an entry for `call-interactively'.
-       For the same reason, pass `cmd' rather than `final'.  */
-      return call3 (Qcall_interactively, cmd, record_flag, keys);
-
-  return Qnil;
-}
-
-
 \f
 /* Return true if input events are pending.  */
 
@@ -11474,8 +11106,7 @@ syms_of_keyboard (void)
   raw_keybuf = Fmake_vector (make_number (30), Qnil);
   staticpro (&raw_keybuf);
 
-  DEFSYM (Qextended_command_history, "extended-command-history");
-  Fset (Qextended_command_history, Qnil);
+  DEFSYM (Qcommand_execute, "command-execute");
 
   accent_key_syms = Qnil;
   staticpro (&accent_key_syms);
@@ -11514,7 +11145,6 @@ syms_of_keyboard (void)
   defsubr (&Srecursive_edit);
   defsubr (&Strack_mouse);
   defsubr (&Sinput_pending_p);
-  defsubr (&Scommand_execute);
   defsubr (&Srecent_keys);
   defsubr (&Sthis_command_keys);
   defsubr (&Sthis_command_keys_vector);
@@ -11672,10 +11302,6 @@ This variable is also the threshold for motion of the mouse
 to count as a drag.  */);
   double_click_fuzz = 3;
 
-  DEFVAR_BOOL ("inhibit-local-menu-bar-menus", inhibit_local_menu_bar_menus,
-              doc: /* Non-nil means inhibit local map menu bar menus.  */);
-  inhibit_local_menu_bar_menus = 0;
-
   DEFVAR_INT ("num-input-keys", num_input_keys,
              doc: /* Number of complete key sequences read as input so far.
 This includes key sequences read from keyboard macros.
@@ -11903,9 +11529,7 @@ If the binding is a function, it is called with one argument (the prompt)
 and its return value (a key sequence) is used.
 
 The events that come from bindings in `input-decode-map' are not
-themselves looked up in `input-decode-map'.
-
-This variable is keyboard-local.  */);
+themselves looked up in `input-decode-map'.  */);
 
   DEFVAR_LISP ("function-key-map", Vfunction_key_map,
                doc: /* The parent keymap of all `local-function-key-map' instances.
@@ -11917,9 +11541,8 @@ definition will take precedence.  */);
 
   DEFVAR_LISP ("key-translation-map", Vkey_translation_map,
                doc: /* Keymap of key translations that can override keymaps.
-This keymap works like `function-key-map', but comes after that,
-and its non-prefix bindings override ordinary bindings.
-Another difference is that it is global rather than keyboard-local.  */);
+This keymap works like `input-decode-map', but comes after `function-key-map'.
+Another difference is that it is global rather than terminal-local.  */);
   Vkey_translation_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("deferred-action-list", Vdeferred_action_list,
@@ -12044,8 +11667,8 @@ This takes effect only when Transient Mark mode is enabled.  */);
               Vsaved_region_selection,
               doc: /* Contents of active region prior to buffer modification.
 If `select-active-regions' is non-nil, Emacs sets this to the
-text in the region before modifying the buffer.  The next
-`deactivate-mark' call uses this to set the window selection.  */);
+text in the region before modifying the buffer.  The next call to
+the function `deactivate-mark' uses this to set the window selection.  */);
   Vsaved_region_selection = Qnil;
 
   DEFVAR_LISP ("selection-inhibit-update-commands",