(Ffind_coding_systems_region_internal): Include raw-text and
[bpt/emacs.git] / src / keymap.c
index 68c63c6..7fa4d9a 100644 (file)
@@ -76,6 +76,9 @@ Lisp_Object Vminor_mode_map_alist;
    minor mode variables and keymaps.  */
 Lisp_Object Vminor_mode_overriding_map_alist;
 
+/* List of emulation mode keymap alists.  */
+Lisp_Object Vemulation_mode_map_alists;
+
 /* Keymap mapping ASCII function key sequences onto their preferred forms.
    Initialized by the terminal-specific lisp files.  See DEFVAR for more
    documentation.  */
@@ -95,8 +98,8 @@ Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap;
 /* Alist of elements like (DEL . "\d").  */
 static Lisp_Object exclude_keys;
 
-/* Pre-allocated 2-element vector for Fremap_command to use.  */
-static Lisp_Object remap_command_vector;
+/* Pre-allocated 2-element vector for Fcommand_remapping to use.  */
+static Lisp_Object command_remapping_vector;
 
 /* A char with the CHAR_META bit set in a vector or the 0200 bit set
    in a string key sequence is equivalent to prefixing with this
@@ -271,11 +274,11 @@ get_keymap (object, error, autoload)
              if (autoload)
                {
                  struct gcpro gcpro1, gcpro2;
-                 
+
                  GCPRO2 (tem, object);
                  do_autoload (tem, object);
                  UNGCPRO;
-                 
+
                  goto autoload_retry;
                }
              else
@@ -290,17 +293,17 @@ get_keymap (object, error, autoload)
   return Qnil;
 }
 \f
-/* Return the parent map of the keymap MAP, or nil if it has none.
-   We assume that MAP is a valid keymap.  */
+/* Return the parent map of KEYMAP, or nil if it has none.
+   We assume that KEYMAP is a valid keymap.  */
 
-DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0,
-       doc: /* Return the parent keymap of KEYMAP.  */)
-     (keymap)
+Lisp_Object
+keymap_parent (keymap, autoload)
      Lisp_Object keymap;
+     int autoload;
 {
   Lisp_Object list;
 
-  keymap = get_keymap (keymap, 1, 1);
+  keymap = get_keymap (keymap, 1, autoload);
 
   /* Skip past the initial element `keymap'.  */
   list = XCDR (keymap);
@@ -311,9 +314,16 @@ DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0,
        return list;
     }
 
-  return get_keymap (list, 0, 1);
+  return get_keymap (list, 0, autoload);
 }
 
+DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0,
+       doc: /* Return the parent keymap of KEYMAP.  */)
+     (keymap)
+     Lisp_Object keymap;
+{
+  return keymap_parent (keymap, 1);
+}
 
 /* Check whether MAP is one of MAPS parents.  */
 int
@@ -322,7 +332,7 @@ keymap_memberp (map, maps)
 {
   if (NILP (map)) return 0;
   while (KEYMAPP (maps) && !EQ (map, maps))
-    maps = Fkeymap_parent (maps);
+    maps = keymap_parent (maps, 0);
   return (EQ (map, maps));
 }
 
@@ -335,7 +345,7 @@ PARENT should be nil or another keymap.  */)
      Lisp_Object keymap, parent;
 {
   Lisp_Object list, prev;
-  struct gcpro gcpro1;
+  struct gcpro gcpro1, gcpro2;
   int i;
 
   /* Force a keymap flush for the next call to where-is.
@@ -347,9 +357,9 @@ PARENT should be nil or another keymap.  */)
      This is a very minor correctness (rather than safety) issue.  */
   where_is_cache_keymaps = Qt;
 
+  GCPRO2 (keymap, parent);
   keymap = get_keymap (keymap, 1, 1);
-  GCPRO1 (keymap);
-  
+
   if (!NILP (parent))
     {
       parent = get_keymap (parent, 1, 1);
@@ -401,10 +411,7 @@ PARENT should be nil or another keymap.  */)
 
       if (CHAR_TABLE_P (XCAR (list)))
        {
-         Lisp_Object indices[3];
-
-         map_char_table (fix_submap_inheritance, Qnil, XCAR (list),
-                         keymap, 0, indices);
+         map_char_table (fix_submap_inheritance, Qnil, XCAR (list), keymap);
        }
     }
 
@@ -430,7 +437,7 @@ fix_submap_inheritance (map, event, submap)
   if (!CONSP (submap))
     return;
 
-  map_parent = Fkeymap_parent (map);
+  map_parent = keymap_parent (map, 0);
   if (!NILP (map_parent))
     parent_entry =
       get_keymap (access_keymap (map_parent, event, 0, 0, 0), 0, 0);
@@ -450,7 +457,7 @@ fix_submap_inheritance (map, event, submap)
        {
          Lisp_Object tem;
 
-         tem = Fkeymap_parent (submap_parent);
+         tem = keymap_parent (submap_parent, 0);
 
          if (KEYMAPP (tem))
            {
@@ -468,11 +475,11 @@ fix_submap_inheritance (map, event, submap)
 \f
 /* Look up IDX in MAP.  IDX may be any sort of event.
    Note that this does only one level of lookup; IDX must be a single
-   event, not a sequence. 
+   event, not a sequence.
 
    If T_OK is non-zero, bindings for Qt are treated as default
    bindings; any key left unmentioned by other tables and bindings is
-   given the binding of Qt.  
+   given the binding of Qt.
 
    If T_OK is zero, bindings for Qt are not treated specially.
 
@@ -510,10 +517,13 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
     {
       /* See if there is a meta-map.  If there's none, there is
          no binding for IDX, unless a default binding exists in MAP.  */
-      Lisp_Object meta_map =
-       get_keymap (access_keymap (map, meta_prefix_char,
-                                  t_ok, noinherit, autoload),
-                   0, autoload);
+      struct gcpro gcpro1;
+      Lisp_Object meta_map;
+      GCPRO1 (map);
+      meta_map = get_keymap (access_keymap (map, meta_prefix_char,
+                                           t_ok, noinherit, autoload),
+                            0, autoload);
+      UNGCPRO;
       if (CONSP (meta_map))
        {
          map = meta_map;
@@ -527,15 +537,15 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
        return Qnil;
     }
 
+  /* t_binding is where we put a default binding that applies,
+     to use in case we do not find a binding specifically
+     for this key sequence.  */
   {
     Lisp_Object tail;
+    Lisp_Object t_binding = Qnil;
+    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
-    /* t_binding is where we put a default binding that applies,
-       to use in case we do not find a binding specifically
-       for this key sequence.  */
-
-    Lisp_Object t_binding;
-    t_binding = Qnil;
+    GCPRO4 (map, tail, idx, t_binding);
 
     /* If `t_ok' is 2, both `t' is accepted.  */
     t_ok = t_ok ? 2 : 0;
@@ -553,12 +563,12 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
            /* If NOINHERIT, stop finding prefix definitions
               after we pass a second occurrence of the `keymap' symbol.  */
            if (noinherit && EQ (binding, Qkeymap))
-             return Qnil;
+             RETURN_UNGCPRO (Qnil);
          }
        else if (CONSP (binding))
          {
            Lisp_Object key = XCAR (binding);
-           
+
            if (EQ (key, idx))
              val = XCDR (binding);
            else if (t_ok > 1 && EQ (key, Qt))
@@ -599,15 +609,110 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
            val = get_keyelt (val, autoload);
            if (KEYMAPP (val))
              fix_submap_inheritance (map, idx, val);
-           return val;
+           RETURN_UNGCPRO (val);
          }
        QUIT;
       }
-
+    UNGCPRO;
     return get_keyelt (t_binding, autoload);
   }
 }
 
+static void
+map_keymap_item (fun, args, key, val, data)
+     map_keymap_function_t fun;
+     Lisp_Object args, key, val;
+     void *data;
+{
+  /* We should maybe try to detect bindings shadowed by previous
+     ones and things like that.  */
+  if (EQ (val, Qt))
+    val = Qnil;
+  (*fun) (key, val, args, data);
+}
+
+static void
+map_keymap_char_table_item (args, key, val)
+     Lisp_Object args, key, val;
+{
+  if (!NILP (val))
+    {
+      map_keymap_function_t fun = XSAVE_VALUE (XCAR (args))->pointer;
+      args = XCDR (args);
+      map_keymap_item (fun, XCDR (args), key, val,
+                      XSAVE_VALUE (XCAR (args))->pointer);
+    }
+}
+
+/* Call FUN for every binding in MAP.
+   FUN is called with 4 arguments: FUN (KEY, BINDING, ARGS, DATA).
+   AUTOLOAD if non-zero means that we can autoload keymaps if necessary.  */
+void
+map_keymap (map, fun, args, data, autoload)
+     map_keymap_function_t fun;
+     Lisp_Object map, args;
+     void *data;
+     int autoload;
+{
+  struct gcpro gcpro1, gcpro2, gcpro3;
+  Lisp_Object tail;
+
+  GCPRO3 (map, args, tail);
+  map = get_keymap (map, 1, autoload);
+  for (tail = (CONSP (map) && EQ (Qkeymap, XCAR (map))) ? XCDR (map) : map;
+       CONSP (tail) || (tail = get_keymap (tail, 0, autoload), CONSP (tail));
+       tail = XCDR (tail))
+    {
+      Lisp_Object binding = XCAR (tail);
+
+      if (CONSP (binding))
+       map_keymap_item (fun, args, XCAR (binding), XCDR (binding), data);
+      else if (VECTORP (binding))
+       {
+         /* Loop over the char values represented in the vector.  */
+         int len = ASIZE (binding);
+         int c;
+         abort();
+         for (c = 0; c < len; c++)
+           {
+             Lisp_Object character;
+             XSETFASTINT (character, c);
+             map_keymap_item (fun, args, character, AREF (binding, c), data);
+           }
+       }
+      else if (CHAR_TABLE_P (binding))
+       {
+         map_char_table (map_keymap_char_table_item, Qnil, binding,
+                         Fcons (make_save_value (fun, 0),
+                                Fcons (make_save_value (data, 0),
+                                       args)));
+       }
+    }
+  UNGCPRO;
+}
+
+static void
+map_keymap_call (key, val, fun, dummy)
+     Lisp_Object key, val, fun;
+     void *dummy;
+{
+  call2 (fun, key, val);
+}
+
+DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 2, 0,
+       doc: /* Call FUNCTION for every binding in KEYMAP.
+FUNCTION is called with two arguments: the event and its binding.  */)
+     (function, keymap)
+     Lisp_Object function, keymap;
+{
+  if (INTEGERP (function))
+    /* We have to stop integers early since map_keymap gives them special
+       significance.  */
+    Fsignal (Qinvalid_function, Fcons (function, Qnil));
+  map_keymap (keymap, map_keymap_call, function, NULL, 1);
+  return Qnil;
+}
+
 /* Given OBJECT which was found in a slot in a keymap,
    trace indirect definitions to get the actual definition of that slot.
    An indirect definition is a list of the form
@@ -622,7 +727,7 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
 
 Lisp_Object
 get_keyelt (object, autoload)
-     register Lisp_Object object;
+     Lisp_Object object;
      int autoload;
 {
   while (1)
@@ -664,7 +769,7 @@ get_keyelt (object, autoload)
                  }
            }
          else
-           /* Invalid keymap */
+           /* Invalid keymap */
            return object;
        }
 
@@ -691,8 +796,11 @@ get_keyelt (object, autoload)
       /* If the contents are (KEYMAP . ELEMENT), go indirect.  */
       else
        {
+         struct gcpro gcpro1;
          Lisp_Object map;
+         GCPRO1 (object);
          map = get_keymap (Fcar_safe (object), 0, autoload);
+         UNGCPRO;
          return (!CONSP (map) ? object /* Invalid keymap */
                  : access_keymap (map, Fcdr (object), 0, 0, autoload));
        }
@@ -718,10 +826,15 @@ store_in_keymap (keymap, idx, def)
   if (!CONSP (keymap) || !EQ (XCAR (keymap), Qkeymap))
     error ("attempt to define a key in a non-keymap");
 
-  /* If idx is a list (some sort of mouse click, perhaps?),
-     the index we want to use is the car of the list, which
-     ought to be a symbol.  */
-  idx = EVENT_HEAD (idx);
+  /* If idx is a cons, and the car part is a character, idx must be of
+     the form (FROM-CHAR . TO-CHAR).  */
+  if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+    CHECK_CHARACTER_CDR (idx);
+  else
+    /* If idx is a list (some sort of mouse click, perhaps?),
+       the index we want to use is the car of the list, which
+       ought to be a symbol.  */
+    idx = EVENT_HEAD (idx);
 
   /* If idx is a symbol, it might have modifiers, which need to
      be put in the canonical order.  */
@@ -757,6 +870,19 @@ store_in_keymap (keymap, idx, def)
                ASET (elt, XFASTINT (idx), def);
                return def;
              }
+           else if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+             {
+               int from = XFASTINT (XCAR (idx));
+               int to = XFASTINT (XCDR (idx));
+
+               if (to >= ASIZE (elt))
+                 to = ASIZE (elt) - 1;
+               for (; from <= to; from++)
+                 ASET (elt, from, def);
+               if (to == XFASTINT (XCDR (idx)))
+                 /* We have defined all keys in IDX.  */
+                 return def;
+             }
            insertion_point = tail;
          }
        else if (CHAR_TABLE_P (elt))
@@ -787,6 +913,19 @@ store_in_keymap (keymap, idx, def)
                XSETCDR (elt, def);
                return def;
              }
+           else if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+             {
+               int from = XFASTINT (XCAR (idx));
+               int to = XFASTINT (XCDR (idx));
+
+               if (from <= XFASTINT (XCAR (elt))
+                   && to >= XFASTINT (XCAR (elt)))
+                 {
+                   XSETCDR (elt, def);
+                   if (from == to)
+                     return def;
+                 }
+             }
          }
        else if (EQ (elt, Qkeymap))
          /* If we find a 'keymap' symbol in the spine of KEYMAP,
@@ -801,21 +940,107 @@ store_in_keymap (keymap, idx, def)
   keymap_end:
     /* We have scanned the entire keymap, and not found a binding for
        IDX.  Let's add one.  */
-    XSETCDR (insertion_point,
-            Fcons (Fcons (idx, def), XCDR (insertion_point)));
+    {
+      Lisp_Object elt;
+
+      if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+       {
+         /* IDX specifies a range of characters, and not all of them
+            were handled yet, which means this keymap doesn't have a
+            char-table.  So, we insert a char-table now.  */
+         elt = Fmake_char_table (Qkeymap, Qnil);
+         Fset_char_table_range (elt, idx, NILP (def) ? Qt : def);
+       }
+      else
+       elt = Fcons (idx, def);
+      XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point)));
+    }
   }
-  
+
   return def;
 }
 
 EXFUN (Fcopy_keymap, 1);
 
-void
+Lisp_Object
+copy_keymap_item (elt)
+     Lisp_Object elt;
+{
+  Lisp_Object res, tem;
+
+  if (!CONSP (elt))
+    return elt;
+
+  res = tem = elt;
+
+  /* Is this a new format menu item.  */
+  if (EQ (XCAR (tem), Qmenu_item))
+    {
+      /* Copy cell with menu-item marker.  */
+      res = elt = Fcons (XCAR (tem), XCDR (tem));
+      tem = XCDR (elt);
+      if (CONSP (tem))
+       {
+         /* Copy cell with menu-item name.  */
+         XSETCDR (elt, Fcons (XCAR (tem), XCDR (tem)));
+         elt = XCDR (elt);
+         tem = XCDR (elt);
+       }
+      if (CONSP (tem))
+       {
+         /* Copy cell with binding and if the binding is a keymap,
+            copy that.  */
+         XSETCDR (elt, Fcons (XCAR (tem), XCDR (tem)));
+         elt = XCDR (elt);
+         tem = XCAR (elt);
+         if (CONSP (tem) && EQ (XCAR (tem), Qkeymap))
+           XSETCAR (elt, Fcopy_keymap (tem));
+         tem = XCDR (elt);
+         if (CONSP (tem) && CONSP (XCAR (tem)))
+           /* Delete cache for key equivalences.  */
+           XSETCDR (elt, XCDR (tem));
+       }
+    }
+  else
+    {
+      /* It may be an old fomat menu item.
+        Skip the optional menu string.  */
+      if (STRINGP (XCAR (tem)))
+       {
+         /* Copy the cell, since copy-alist didn't go this deep.  */
+         res = elt = Fcons (XCAR (tem), XCDR (tem));
+         tem = XCDR (elt);
+         /* Also skip the optional menu help string.  */
+         if (CONSP (tem) && STRINGP (XCAR (tem)))
+           {
+             XSETCDR (elt, Fcons (XCAR (tem), XCDR (tem)));
+             elt = XCDR (elt);
+             tem = XCDR (elt);
+           }
+         /* There may also be a list that caches key equivalences.
+            Just delete it for the new keymap.  */
+         if (CONSP (tem)
+             && CONSP (XCAR (tem))
+             && (NILP (XCAR (XCAR (tem)))
+                 || VECTORP (XCAR (XCAR (tem)))))
+           {
+             XSETCDR (elt, XCDR (tem));
+             tem = XCDR (tem);
+           }
+         if (CONSP (tem) && EQ (XCAR (tem), Qkeymap))
+           XSETCDR (elt, Fcopy_keymap (tem));
+       }
+      else if (EQ (XCAR (tem), Qkeymap))
+       res = Fcopy_keymap (elt);
+    }
+  return res;
+}
+
+static void
 copy_keymap_1 (chartable, idx, elt)
      Lisp_Object chartable, idx, elt;
 {
-  if (CONSP (elt) && EQ (XCAR (elt), Qkeymap))
-    Faset (chartable, idx, Fcopy_keymap (elt));
+  Fset_char_table_range (chartable, idx, copy_keymap_item (elt));
 }
 
 DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0,
@@ -828,112 +1053,33 @@ is not copied.  */)
      (keymap)
      Lisp_Object keymap;
 {
-  /* FIXME: This doesn't properly copy menu-items in vectors.  */
-  /* FIXME: This also copies the parent keymap.  */
-
   register Lisp_Object copy, tail;
+  keymap = get_keymap (keymap, 1, 0);
+  copy = tail = Fcons (Qkeymap, Qnil);
+  keymap = XCDR (keymap);              /* Skip the `keymap' symbol.  */
 
-  copy = Fcopy_alist (get_keymap (keymap, 1, 0));
-
-  for (tail = copy; CONSP (tail); tail = XCDR (tail))
+  while (CONSP (keymap) && !EQ (XCAR (keymap), Qkeymap))
     {
-      Lisp_Object elt;
-
-      elt = XCAR (tail);
+      Lisp_Object elt = XCAR (keymap);
       if (CHAR_TABLE_P (elt))
        {
-         Lisp_Object indices[3];
-
          elt = Fcopy_sequence (elt);
-         XSETCAR (tail, elt);
-
-         map_char_table (copy_keymap_1, Qnil, elt, elt, 0, indices);
+         map_char_table (copy_keymap_1, Qnil, elt, elt);
        }
       else if (VECTORP (elt))
        {
          int i;
-
          elt = Fcopy_sequence (elt);
-         XSETCAR (tail, elt);
-
          for (i = 0; i < ASIZE (elt); i++)
-           if (CONSP (AREF (elt, i)) && EQ (XCAR (AREF (elt, i)), Qkeymap))
-             ASET (elt, i, Fcopy_keymap (AREF (elt, i)));
-       }
-      else if (CONSP (elt) && CONSP (XCDR (elt)))
-       {
-         Lisp_Object tem;
-         tem = XCDR (elt);
-
-         /* Is this a new format menu item.  */
-         if (EQ (XCAR (tem),Qmenu_item))
-           {
-             /* Copy cell with menu-item marker.  */
-             XSETCDR (elt,
-                      Fcons (XCAR (tem), XCDR (tem)));
-             elt = XCDR (elt);
-             tem = XCDR (elt);
-             if (CONSP (tem))
-               {
-                 /* Copy cell with menu-item name.  */
-                 XSETCDR (elt,
-                          Fcons (XCAR (tem), XCDR (tem)));
-                 elt = XCDR (elt);
-                 tem = XCDR (elt);
-               };
-             if (CONSP (tem))
-               {
-                 /* Copy cell with binding and if the binding is a keymap,
-                    copy that.  */
-                 XSETCDR (elt,
-                          Fcons (XCAR (tem), XCDR (tem)));
-                 elt = XCDR (elt);
-                 tem = XCAR (elt);
-                 if (CONSP (tem) && EQ (XCAR (tem), Qkeymap))
-                   XSETCAR (elt, Fcopy_keymap (tem));
-                 tem = XCDR (elt);
-                 if (CONSP (tem) && CONSP (XCAR (tem)))
-                   /* Delete cache for key equivalences.  */
-                   XSETCDR (elt, XCDR (tem));
-               }
-           }
-         else
-           {
-             /* It may be an old fomat menu item.
-                Skip the optional menu string.
-             */
-             if (STRINGP (XCAR (tem)))
-               {
-                 /* Copy the cell, since copy-alist didn't go this deep.  */
-                 XSETCDR (elt,
-                          Fcons (XCAR (tem), XCDR (tem)));
-                 elt = XCDR (elt);
-                 tem = XCDR (elt);
-                 /* Also skip the optional menu help string.  */
-                 if (CONSP (tem) && STRINGP (XCAR (tem)))
-                   {
-                     XSETCDR (elt,
-                              Fcons (XCAR (tem), XCDR (tem)));
-                     elt = XCDR (elt);
-                     tem = XCDR (elt);
-                   }
-                 /* There may also be a list that caches key equivalences.
-                    Just delete it for the new keymap.  */
-                 if (CONSP (tem)
-                     && CONSP (XCAR (tem))
-                     && (NILP (XCAR (XCAR (tem)))
-                         || VECTORP (XCAR (XCAR (tem)))))
-                   XSETCDR (elt, XCDR (tem));
-               }
-             if (CONSP (elt)
-                 && CONSP (XCDR (elt))
-                 && EQ (XCAR (XCDR (elt)), Qkeymap))
-               XSETCDR (elt, Fcopy_keymap (XCDR (elt)));
-           }
-
+           ASET (elt, i, copy_keymap_item (AREF (elt, i)));
        }
+      else if (CONSP (elt))
+       elt = Fcons (XCAR (elt), copy_keymap_item (XCDR (elt)));
+      XSETCDR (tail, Fcons (elt, Qnil));
+      tail = XCDR (tail);
+      keymap = XCDR (keymap);
     }
-  
+  XSETCDR (tail, keymap);
   return copy;
 }
 \f
@@ -942,12 +1088,14 @@ is not copied.  */)
 /* GC is possible in this function if it autoloads a keymap.  */
 
 DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0,
-       doc: /* Args KEYMAP, KEY, DEF.  Define key sequence KEY, in KEYMAP, as DEF.
+       doc: /* In KEYMAP, define key sequence KEY as DEF.
 KEYMAP is a keymap.
 
 KEY is a string or a vector of symbols and characters meaning a
 sequence of keystrokes and events.  Non-ASCII characters with codes
 above 127 (such as ISO Latin-1) can be included if you use a vector.
+Using [t] for KEY creates a default definition, which applies to any
+event type that has no other definition in this keymap.
 
 DEF is anything that can be a key's definition:
  nil (means key is undefined in this keymap),
@@ -961,8 +1109,9 @@ DEF is anything that can be a key's definition:
     (DEFN should be a valid definition in its own right),
  or a cons (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP.
 
-If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at
-the front of KEYMAP.  */)
+If KEYMAP is a sparse keymap with a binding for KEY, the existing
+binding is altered.  If there is no binding for KEY, the new pair
+binding KEY to DEF is added at the front of KEYMAP.  */)
      (keymap, key, def)
      Lisp_Object keymap;
      Lisp_Object key;
@@ -976,29 +1125,20 @@ the front of KEYMAP.  */)
   int length;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
+  GCPRO3 (keymap, key, def);
   keymap = get_keymap (keymap, 1, 1);
 
   if (!VECTORP (key) && !STRINGP (key))
-      key = wrong_type_argument (Qarrayp, key);
+    key = wrong_type_argument (Qarrayp, key);
 
   length = XFASTINT (Flength (key));
   if (length == 0)
-    return Qnil;
-
-  /* Check for valid [remap COMMAND] bindings.  */
-  if (VECTORP (key) && EQ (AREF (key, 0), Qremap)
-      && (length != 2 || !SYMBOLP (AREF (key, 1))))
-    wrong_type_argument (Qvectorp, key);
+    RETURN_UNGCPRO (Qnil);
 
   if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt))
     Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands);
 
-  GCPRO3 (keymap, key, def);
-
-  if (VECTORP (key))
-    meta_bit = meta_modifier;
-  else
-    meta_bit = 0x80;
+  meta_bit = VECTORP (key) ? meta_modifier : 0x80;
 
   idx = 0;
   while (1)
@@ -1007,12 +1147,12 @@ the front of KEYMAP.  */)
 
       if (CONSP (c))
        {
-         /* C may be a cons (FROM . TO) specifying a range of
-            characters.  */
-         if (CHARACTERP (XCAR (c)))
-           CHECK_CHARACTER (XCDR (c));
-         else if (lucid_event_type_list_p (c))
+         /* C may be a Lucid style event type list or a cons (FROM .
+            TO) specifying a range of characters.  */
+         if (lucid_event_type_list_p (c))
            c = Fevent_convert_list (c);
+         else if (CHARACTERP (XCAR (c)))
+           CHECK_CHARACTER_CDR (c);
        }
 
       if (SYMBOLP (c))
@@ -1054,21 +1194,23 @@ the front of KEYMAP.  */)
        /* We must use Fkey_description rather than just passing key to
           error; key might be a vector, not a string.  */
        error ("Key sequence %s uses invalid prefix characters",
-              XSTRING (Fkey_description (key))->data);
+              SDATA (Fkey_description (key)));
     }
 }
 
 /* This function may GC (it calls Fkey_binding).  */
 
-DEFUN ("remap-command", Fremap_command, Sremap_command, 1, 1, 0,
+DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 1, 0,
        doc: /* Return the remapping for command COMMAND in current keymaps.
-Returns nil if COMMAND is not remapped.  */)
+Returns nil if COMMAND is not remapped (or not a symbol).  */)
      (command)
      Lisp_Object command;
 {
-  /* This will GCPRO the command argument.  */
-  ASET (remap_command_vector, 1, command);
-  return Fkey_binding (remap_command_vector, Qnil, Qt);
+  if (!SYMBOLP (command))
+    return Qnil;
+
+  ASET (command_remapping_vector, 1, command);
+  return Fkey_binding (command_remapping_vector, Qnil, Qt);
 }
 
 /* Value is number if KEY is too long; nil if valid but has no definition. */
@@ -1090,7 +1232,7 @@ usable as a general function for probing keymaps.  However, if the
 third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will
 recognize the default bindings, just as `read-key-sequence' does.  */)
      (keymap, key, accept_default)
-     register Lisp_Object keymap;
+     Lisp_Object keymap;
      Lisp_Object key;
      Lisp_Object accept_default;
 {
@@ -1099,32 +1241,17 @@ recognize the default bindings, just as `read-key-sequence' does.  */)
   register Lisp_Object c;
   int length;
   int t_ok = !NILP (accept_default);
-  struct gcpro gcpro1;
+  struct gcpro gcpro1, gcpro2;
 
+  GCPRO2 (keymap, key);
   keymap = get_keymap (keymap, 1, 1);
 
-  /* Perform command remapping initiated by Fremap_command directly.
-     This is strictly not necessary, but it is faster and it returns
-     nil instead of 1 if KEYMAP doesn't contain command remappings.  */
-  if (EQ (key, remap_command_vector))
-    {
-      /* KEY has format [remap COMMAND]. 
-        Lookup `remap' in KEYMAP; result is nil or a keymap containing
-        command remappings.  Then lookup COMMAND in that keymap.  */
-      if ((keymap = access_keymap (keymap, Qremap, t_ok, 0, 1), !NILP (keymap))
-         && (keymap = get_keymap (keymap, 0, 1), CONSP (keymap)))
-       return access_keymap (keymap, AREF (key, 1), t_ok, 0, 1);
-      return Qnil;
-    }
-
   if (!VECTORP (key) && !STRINGP (key))
     key = wrong_type_argument (Qarrayp, key);
 
   length = XFASTINT (Flength (key));
   if (length == 0)
-    return keymap;
-
-  GCPRO1 (key);
+    RETURN_UNGCPRO (keymap);
 
   idx = 0;
   while (1)
@@ -1198,7 +1325,7 @@ silly_event_symbol_error (c)
 {
   Lisp_Object parsed, base, name, assoc;
   int modifiers;
-         
+
   parsed = parse_modifiers (c);
   modifiers = (int) XUINT (XCAR (XCDR (parsed)));
   base = XCAR (parsed);
@@ -1227,12 +1354,12 @@ silly_event_symbol_error (c)
 
       c = reorder_modifiers (c);
       keystring = concat2 (build_string (new_mods), XCDR (assoc));
-               
+
       error ((modifiers & ~meta_modifier
              ? "To bind the key %s, use [?%s], not [%s]"
              : "To bind the key %s, use \"%s\", not [%s]"),
-            XSYMBOL (c)->name->data, XSTRING (keystring)->data,
-            XSYMBOL (c)->name->data);
+            SDATA (SYMBOL_NAME (c)), SDATA (keystring),
+            SDATA (SYMBOL_NAME (c)));
     }
 }
 \f
@@ -1241,8 +1368,8 @@ silly_event_symbol_error (c)
 /* We can't put these variables inside current_minor_maps, since under
    some systems, static gets macro-defined to be the empty string.
    Ickypoo.  */
-static Lisp_Object *cmm_modes, *cmm_maps;
-static int cmm_size;
+static Lisp_Object *cmm_modes = NULL, *cmm_maps = NULL;
+static int cmm_size = 0;
 
 /* Error handler used in current_minor_maps.  */
 static Lisp_Object
@@ -1274,81 +1401,95 @@ current_minor_maps (modeptr, mapptr)
   int i = 0;
   int list_number = 0;
   Lisp_Object alist, assoc, var, val;
+  Lisp_Object emulation_alists;
   Lisp_Object lists[2];
 
+  emulation_alists = Vemulation_mode_map_alists;
   lists[0] = Vminor_mode_overriding_map_alist;
   lists[1] = Vminor_mode_map_alist;
 
   for (list_number = 0; list_number < 2; list_number++)
-    for (alist = lists[list_number];
-        CONSP (alist);
-        alist = XCDR (alist))
-      if ((assoc = XCAR (alist), CONSP (assoc))
-         && (var = XCAR (assoc), SYMBOLP (var))
-         && (val = find_symbol_value (var), !EQ (val, Qunbound))
-         && !NILP (val))
+    {
+      if (CONSP (emulation_alists))
        {
-         Lisp_Object temp;
+         alist = XCAR (emulation_alists);
+         emulation_alists = XCDR (emulation_alists);
+         if (SYMBOLP (alist))
+           alist = find_symbol_value (alist);
+         list_number = -1;
+       }
+      else
+       alist = lists[list_number];
 
-         /* If a variable has an entry in Vminor_mode_overriding_map_alist,
-            and also an entry in Vminor_mode_map_alist,
-            ignore the latter.  */
-         if (list_number == 1)
-           {
-             val = assq_no_quit (var, lists[0]);
-             if (!NILP (val))
-               continue;
-           }
+      for ( ; CONSP (alist); alist = XCDR (alist))
+       if ((assoc = XCAR (alist), CONSP (assoc))
+           && (var = XCAR (assoc), SYMBOLP (var))
+           && (val = find_symbol_value (var), !EQ (val, Qunbound))
+           && !NILP (val))
+         {
+           Lisp_Object temp;
 
-         if (i >= cmm_size)
-           {
-             Lisp_Object *newmodes, *newmaps;
+           /* If a variable has an entry in Vminor_mode_overriding_map_alist,
+              and also an entry in Vminor_mode_map_alist,
+              ignore the latter.  */
+           if (list_number == 1)
+             {
+               val = assq_no_quit (var, lists[0]);
+               if (!NILP (val))
+                 continue;
+             }
 
-             /* Use malloc/realloc here.  See the comment above
-                this function.  */
-             if (cmm_maps)
-               {
-                 BLOCK_INPUT;
-                 cmm_size *= 2;
-                 newmodes
-                   = (Lisp_Object *) realloc (cmm_modes,
-                                               cmm_size * sizeof *newmodes);
-                 newmaps
-                   = (Lisp_Object *) realloc (cmm_maps,
-                                               cmm_size * sizeof *newmaps);
-                 UNBLOCK_INPUT;
-               }
-             else
-               {
-                 BLOCK_INPUT;
-                 cmm_size = 30;
-                 newmodes
-                   = (Lisp_Object *) malloc (cmm_size * sizeof *newmodes);
-                 newmaps
-                   = (Lisp_Object *) malloc (cmm_size * sizeof *newmaps);
-                 UNBLOCK_INPUT;
-               }
+           if (i >= cmm_size)
+             {
+               int newsize, allocsize;
+               Lisp_Object *newmodes, *newmaps;
 
-             if (newmodes)
-               cmm_modes = newmodes;
-             if (newmaps)
-               cmm_maps = newmaps;
-             
-             if (newmodes == NULL || newmaps == NULL)
-               break;
-           }
+               newsize = cmm_size == 0 ? 30 : cmm_size * 2;
+               allocsize = newsize * sizeof *newmodes;
 
-         /* Get the keymap definition--or nil if it is not defined.  */
-         temp = internal_condition_case_1 (Findirect_function,
-                                           XCDR (assoc),
-                                           Qerror, current_minor_maps_error);
-         if (!NILP (temp))
-           {
-             cmm_modes[i] = var;
-             cmm_maps [i] = temp;
-             i++;
-           }
-       }
+               /* Use malloc here.  See the comment above this function.
+                  Avoid realloc here; it causes spurious traps on GNU/Linux [KFS] */
+               BLOCK_INPUT;
+               newmodes = (Lisp_Object *) malloc (allocsize);
+               if (newmodes)
+                 {
+                   if (cmm_modes)
+                     {
+                       bcopy (cmm_modes, newmodes, cmm_size * sizeof cmm_modes[0]);
+                       free (cmm_modes);
+                     }
+                   cmm_modes = newmodes;
+                 }
+
+               newmaps = (Lisp_Object *) malloc (allocsize);
+               if (newmaps)
+                 {
+                   if (cmm_maps)
+                     {
+                       bcopy (cmm_maps, newmaps, cmm_size * sizeof cmm_maps[0]);
+                       free (cmm_maps);
+                     }
+                   cmm_maps = newmaps;
+                 }
+               UNBLOCK_INPUT;
+
+               if (newmodes == NULL || newmaps == NULL)
+                 break;
+               cmm_size = newsize;
+             }
+
+           /* Get the keymap definition--or nil if it is not defined.  */
+           temp = internal_condition_case_1 (Findirect_function,
+                                             XCDR (assoc),
+                                             Qerror, current_minor_maps_error);
+           if (!NILP (temp))
+             {
+               cmm_modes[i] = var;
+               cmm_maps [i] = temp;
+               i++;
+             }
+         }
+    }
 
   if (modeptr) *modeptr = cmm_modes;
   if (mapptr)  *mapptr  = cmm_maps;
@@ -1392,7 +1533,7 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and
       if (!NILP (local))
        keymaps = Fcons (local, keymaps);
     }
-  
+
   return keymaps;
 }
 
@@ -1411,7 +1552,7 @@ recognize the default bindings, just as `read-key-sequence' does.
 
 Like the normal command loop, `key-binding' will remap the command
 resulting from looking up KEY by looking up the command in the
-currrent keymaps.  However, if the optional third argument NO-REMAP
+current keymaps.  However, if the optional third argument NO-REMAP
 is non-nil, `key-binding' returns the unmapped command.  */)
      (key, accept_default, no_remap)
      Lisp_Object key, accept_default, no_remap;
@@ -1436,7 +1577,7 @@ is non-nil, `key-binding' returns the unmapped command.  */)
        goto done;
     }
   else
-    { 
+    {
       Lisp_Object local;
 
       local = get_local_map (PT, current_buffer, Qkeymap);
@@ -1477,14 +1618,14 @@ is non-nil, `key-binding' returns the unmapped command.  */)
 
   /* If the result of the ordinary keymap lookup is an interactive
      command, look for a key binding (ie. remapping) for that command.  */
-     
+
   if (NILP (no_remap) && SYMBOLP (value))
     {
       Lisp_Object value1;
-      if (value1 = Fremap_command (value), !NILP (value1))
+      if (value1 = Fcommand_remapping (value), !NILP (value1))
        value = value1;
     }
-  
+
   return value;
 }
 
@@ -1649,43 +1790,54 @@ accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized)
 {
   Lisp_Object tem;
 
-  cmd = get_keyelt (cmd, 0);
+  cmd = get_keymap (get_keyelt (cmd, 0), 0, 0);
   if (NILP (cmd))
     return;
 
-  tem = get_keymap (cmd, 0, 0);
-  if (CONSP (tem))
-    {
-      cmd = tem;
-      /* Ignore keymaps that are already added to maps.  */
-      tem = Frassq (cmd, maps);
-      if (NILP (tem))
-       {
-         /* If the last key in thisseq is meta-prefix-char,
-            turn it into a meta-ized keystroke.  We know
-            that the event we're about to append is an
-            ascii keystroke since we're processing a
-            keymap table.  */
-         if (is_metized)
-           {
-             int meta_bit = meta_modifier;
-             Lisp_Object last = make_number (XINT (Flength (thisseq)) - 1);
-             tem = Fcopy_sequence (thisseq);
-             
-             Faset (tem, last, make_number (XINT (key) | meta_bit));
-             
-             /* This new sequence is the same length as
-                thisseq, so stick it in the list right
-                after this one.  */
-             XSETCDR (tail,
-                      Fcons (Fcons (tem, cmd), XCDR (tail)));
-           }
-         else
-           {
-             tem = append_key (thisseq, key);
-             nconc2 (tail, Fcons (Fcons (tem, cmd), Qnil));
-           }
+  /* Look for and break cycles.  */
+  while (!NILP (tem = Frassq (cmd, maps)))
+    {
+      Lisp_Object prefix = XCAR (tem);
+      int lim = XINT (Flength (XCAR (tem)));
+      if (lim <= XINT (Flength (thisseq)))
+       { /* This keymap was already seen with a smaller prefix.  */
+         int i = 0;
+         while (i < lim && EQ (Faref (prefix, make_number (i)),
+                               Faref (thisseq, make_number (i))))
+           i++;
+         if (i >= lim)
+           /* `prefix' is a prefix of `thisseq' => there's a cycle.  */
+           return;
        }
+      /* This occurrence of `cmd' in `maps' does not correspond to a cycle,
+        but maybe `cmd' occurs again further down in `maps', so keep
+        looking.  */
+      maps = XCDR (Fmemq (tem, maps));
+    }
+
+  /* If the last key in thisseq is meta-prefix-char,
+     turn it into a meta-ized keystroke.  We know
+     that the event we're about to append is an
+     ascii keystroke since we're processing a
+     keymap table.  */
+  if (is_metized)
+    {
+      int meta_bit = meta_modifier;
+      Lisp_Object last = make_number (XINT (Flength (thisseq)) - 1);
+      tem = Fcopy_sequence (thisseq);
+
+      Faset (tem, last, make_number (XINT (key) | meta_bit));
+
+      /* This new sequence is the same length as
+        thisseq, so stick it in the list right
+        after this one.  */
+      XSETCDR (tail,
+              Fcons (Fcons (tem, cmd), XCDR (tail)));
+    }
+  else
+    {
+      tem = append_key (thisseq, key);
+      nconc2 (tail, Fcons (Fcons (tem, cmd), Qnil));
     }
 }
 
@@ -1713,7 +1865,7 @@ then the value includes only maps for prefixes that start with PREFIX.  */)
      (keymap, prefix)
      Lisp_Object keymap, prefix;
 {
-  Lisp_Object maps, good_maps, tail;
+  Lisp_Object maps, tail;
   int prefixlen = 0;
 
   /* no need for gcpro because we don't autoload any keymaps.  */
@@ -1740,8 +1892,8 @@ then the value includes only maps for prefixes that start with PREFIX.  */)
              int i, i_byte, c;
              Lisp_Object copy;
 
-             copy = Fmake_vector (make_number (XSTRING (prefix)->size), Qnil);
-             for (i = 0, i_byte = 0; i < XSTRING (prefix)->size;)
+             copy = Fmake_vector (make_number (SCHARS (prefix)), Qnil);
+             for (i = 0, i_byte = 0; i < SCHARS (prefix);)
                {
                  int i_before = i;
 
@@ -1794,12 +1946,9 @@ then the value includes only maps for prefixes that start with PREFIX.  */)
 
          if (CHAR_TABLE_P (elt))
            {
-             Lisp_Object indices[3];
-
              map_char_table (accessible_keymaps_char_table, Qnil,
                              elt, Fcons (Fcons (maps, make_number (is_metized)),
-                                         Fcons (tail, thisseq)),
-                             0, indices);
+                                         Fcons (tail, thisseq)));
            }
          else if (VECTORP (elt))
            {
@@ -1809,45 +1958,17 @@ then the value includes only maps for prefixes that start with PREFIX.  */)
              for (i = 0; i < ASIZE (elt); i++)
                accessible_keymaps_1 (make_number (i), AREF (elt, i),
                                      maps, tail, thisseq, is_metized);
-                                       
+
            }
          else if (CONSP (elt))
            accessible_keymaps_1 (XCAR (elt), XCDR (elt),
                                  maps, tail, thisseq,
                                  is_metized && INTEGERP (XCAR (elt)));
-                                   
-       }
-    }
-
-  if (NILP (prefix))
-    return maps;
 
-  /* Now find just the maps whose access prefixes start with PREFIX.  */
-
-  good_maps = Qnil;
-  for (; CONSP (maps); maps = XCDR (maps))
-    {
-      Lisp_Object elt, thisseq;
-      elt = XCAR (maps);
-      thisseq = XCAR (elt);
-      /* The access prefix must be at least as long as PREFIX,
-        and the first elements must match those of PREFIX.  */
-      if (XINT (Flength (thisseq)) >= prefixlen)
-       {
-         int i;
-         for (i = 0; i < prefixlen; i++)
-           {
-             Lisp_Object i1;
-             XSETFASTINT (i1, i);
-             if (!EQ (Faref (thisseq, i1), Faref (prefix, i1)))
-               break;
-           }
-         if (i == prefixlen)
-           good_maps = Fcons (elt, good_maps);
        }
     }
 
-  return Fnreverse (good_maps);
+  return maps;
 }
 \f
 Lisp_Object Qsingle_key_description, Qkey_description;
@@ -1870,7 +1991,7 @@ spaces are put between sequence elements, etc.  */)
     {
       Lisp_Object vector;
       vector = Fmake_vector (Flength (keys), Qnil);
-      for (i = 0, i_byte = 0; i < XSTRING (keys)->size; )
+      for (i = 0, i_byte = 0; i < SCHARS (keys); )
        {
          int c;
          int i_before = i;
@@ -1933,7 +2054,7 @@ push_key_description (c, p, force_multibyte)
      int force_multibyte;
 {
   unsigned c2;
-  
+
   /* Clear all the meaningless bits above the meta bit.  */
   c &= meta_modifier | ~ - meta_modifier;
   c2 = c & ~(alt_modifier | ctrl_modifier | hyper_modifier
@@ -2075,8 +2196,8 @@ around function keys and event symbols.  */)
       if (NILP (no_angles))
        {
          char *buffer
-           = (char *) alloca (STRING_BYTES (XSYMBOL (key)->name) + 5);
-         sprintf (buffer, "<%s>", XSYMBOL (key)->name->data);
+           = (char *) alloca (SBYTES (SYMBOL_NAME (key)) + 5);
+         sprintf (buffer, "<%s>", SDATA (SYMBOL_NAME (key)));
          return build_string (buffer);
        }
       else
@@ -2130,7 +2251,7 @@ Control characters turn into "^char", etc.  */)
   CHECK_NUMBER (character);
 
   c = XINT (character);
-  if (!SINGLE_BYTE_CHAR_P (c))
+  if (!ASCII_CHAR_P (c))
     {
       int len = CHAR_STRING (c, str);
 
@@ -2191,6 +2312,8 @@ shadow_lookup (shadow, key, flag)
   return Qnil;
 }
 
+static Lisp_Object Vmenu_events;
+
 /* This function can GC if Flookup_key autoloads any keymaps.  */
 
 static Lisp_Object
@@ -2209,7 +2332,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
   if (NILP (no_remap) && SYMBOLP (definition))
     {
       Lisp_Object tem;
-      if (tem = Fremap_command (definition), !NILP (tem))
+      if (tem = Fcommand_remapping (definition), !NILP (tem))
        return Qnil;
     }
 
@@ -2221,7 +2344,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
                Faccessible_keymaps (get_keymap (XCAR (found), 1, 0), Qnil));
       found = XCDR (found);
     }
+
   GCPRO5 (definition, keymaps, maps, found, sequences);
   found = Qnil;
   sequences = Qnil;
@@ -2229,7 +2352,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
   for (; !NILP (maps); maps = Fcdr (maps))
     {
       /* Key sequence to reach map, and the map that it reaches */
-      register Lisp_Object this, map;
+      register Lisp_Object this, map, tem;
 
       /* In order to fold [META-PREFIX-CHAR CHAR] sequences into
         [M-CHAR] sequences, check if last character of the sequence
@@ -2245,12 +2368,13 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
 
       /* if (nomenus && !ascii_sequence_p (this)) */
       if (nomenus && XINT (last) >= 0
-         && !INTEGERP (Faref (this, make_number (0))))
+         && SYMBOLP (tem = Faref (this, make_number (0)))
+         && !NILP (Fmemq (XCAR (parse_modifiers (tem)), Vmenu_events)))
        /* If no menu entries should be returned, skip over the
           keymaps bound to `menu-bar' and `tool-bar' and other
           non-ascii prefixes like `C-down-mouse-2'.  */
        continue;
-      
+
       QUIT;
 
       while (CONSP (map))
@@ -2291,7 +2415,6 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
            }
          else if (CHAR_TABLE_P (elt))
            {
-             Lisp_Object indices[3];
              Lisp_Object args;
 
              args = Fcons (Fcons (Fcons (definition, noindirect),
@@ -2299,8 +2422,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
                            Fcons (Fcons (this, last),
                                   Fcons (make_number (nomenus),
                                          make_number (last_is_meta))));
-             map_char_table (where_is_internal_2, Qnil, elt, args,
-                             0, indices);
+             map_char_table (where_is_internal_2, Qnil, elt, args);
              sequences = XCDR (XCAR (args));
            }
          else if (CONSP (elt))
@@ -2395,7 +2517,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
      return the best we could find.  */
   if (!NILP (firstonly))
     return Fcar (found);
-    
+
   return found;
 }
 
@@ -2443,7 +2565,7 @@ remapped command in the returned list.  */)
       Lisp_Object *defns;
       int i, j, n;
       struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-      
+
       /* Check heuristic-consistency of the cache.  */
       if (NILP (Fequal (keymaps, where_is_cache_keymaps)))
        where_is_cache = Qnil;
@@ -2454,7 +2576,7 @@ remapped command in the returned list.  */)
          Lisp_Object args[2];
          where_is_cache = Fmake_hash_table (0, args);
          where_is_cache_keymaps = Qt;
-         
+
          /* Fill in the cache.  */
          GCPRO5 (definition, keymaps, firstonly, noindirect, no_remap);
          where_is_internal (definition, keymaps, firstonly, noindirect, no_remap);
@@ -2471,7 +2593,7 @@ remapped command in the returned list.  */)
       defns = (Lisp_Object *) alloca (n * sizeof *defns);
       for (i = 0; CONSP (sequences); sequences = XCDR (sequences))
        defns[i++] = XCAR (sequences);
-      
+
       /* Verify that the key bindings are not shadowed.  Note that
         the following can GC.  */
       GCPRO2 (definition, keymaps);
@@ -2614,8 +2736,8 @@ You type        Translation\n\
   if (STRINGP (Vkeyboard_translate_table) && !NILP (prefix))
     {
       int c;
-      unsigned char *translate = XSTRING (Vkeyboard_translate_table)->data;
-      int translate_len = XSTRING (Vkeyboard_translate_table)->size;
+      const unsigned char *translate = SDATA (Vkeyboard_translate_table);
+      int translate_len = SCHARS (Vkeyboard_translate_table);
 
       for (c = 0; c < translate_len; c++)
        if (translate[c] != c)
@@ -2693,13 +2815,13 @@ You type        Translation\n\
          if (!SYMBOLP (modes[i]))
            abort();
 
-         p = title = (char *) alloca (42 + XSYMBOL (modes[i])->name->size);
+         p = title = (char *) alloca (42 + SCHARS (SYMBOL_NAME (modes[i])));
          *p++ = '\f';
          *p++ = '\n';
          *p++ = '`';
-         bcopy (XSYMBOL (modes[i])->name->data, p,
-                XSYMBOL (modes[i])->name->size);
-         p += XSYMBOL (modes[i])->name->size;
+         bcopy (SDATA (SYMBOL_NAME (modes[i])), p,
+                SCHARS (SYMBOL_NAME (modes[i])));
+         p += SCHARS (SYMBOL_NAME (modes[i]));
          *p++ = '\'';
          bcopy (" Minor Mode Bindings", p, sizeof (" Minor Mode Bindings") - 1);
          p += sizeof (" Minor Mode Bindings") - 1;
@@ -2830,7 +2952,7 @@ key             binding\n\
 
          /* If the sequence by which we reach this keymap is zero-length,
             then the shadow map for this keymap is just SHADOW.  */
-         if ((STRINGP (prefix) && XSTRING (prefix)->size == 0)
+         if ((STRINGP (prefix) && SCHARS (prefix) == 0)
              || (VECTORP (prefix) && XVECTOR (prefix)->size == 0))
            ;
          /* If the sequence by which we reach this keymap actually has
@@ -2882,7 +3004,7 @@ describe_command (definition, args)
      Lisp_Object definition, args;
 {
   register Lisp_Object tem1;
-  int column = current_column ();
+  int column = (int) current_column (); /* iftc */
   int description_column;
 
   /* If column 16 is no good, go to col 32;
@@ -2902,7 +3024,7 @@ describe_command (definition, args)
 
   if (SYMBOLP (definition))
     {
-      XSETSTRING (tem1, XSYMBOL (definition)->name);
+      tem1 = SYMBOL_NAME (definition);
       insert1 (tem1);
       insert_string ("\n");
     }
@@ -2924,7 +3046,7 @@ describe_translation (definition, args)
 
   if (SYMBOLP (definition))
     {
-      XSETSTRING (tem1, XSYMBOL (definition)->name);
+      tem1 = SYMBOL_NAME (definition);
       insert1 (tem1);
       insert_string ("\n");
     }
@@ -3076,7 +3198,7 @@ This is text showing the elements of vector matched against indices.  */)
      (vector, describer)
      Lisp_Object vector, describer;
 {
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   if (NILP (describer))
     describer = intern ("princ");
   specbind (Qstandard_output, Fcurrent_buffer ());
@@ -3192,7 +3314,7 @@ describe_vector (vector, elt_prefix, args, elt_describer,
       if (!NILP (shadow))
        {
          Lisp_Object tem;
-         
+
          ASET (kludge, 0, character);
          tem = shadow_lookup (shadow, kludge, Qt);
 
@@ -3252,6 +3374,7 @@ describe_vector (vector, elt_prefix, args, elt_describer,
 
          if (!NILP (elt_prefix))
            insert1 (elt_prefix);
+
          insert1 (Fsingle_key_description (make_number (i), Qnil));
        }
 
@@ -3261,13 +3384,20 @@ describe_vector (vector, elt_prefix, args, elt_describer,
       (*elt_describer) (definition, args);
     }
 
+  if (CHAR_TABLE_P (vector) && ! NILP (XCHAR_TABLE (vector)->defalt))
+    {
+      if (!NILP (elt_prefix))
+       insert1 (elt_prefix);
+      insert ("default", 7);
+      (*elt_describer) (XCHAR_TABLE (vector)->defalt, args);
+    }
+
   UNGCPRO;
 }
-
 \f
 /* Apropos - finding all symbols whose names match a regexp.           */
-Lisp_Object apropos_predicate;
-Lisp_Object apropos_accumulate;
+static Lisp_Object apropos_predicate;
+static Lisp_Object apropos_accumulate;
 
 static void
 apropos_accum (symbol, string)
@@ -3282,7 +3412,7 @@ apropos_accum (symbol, string)
     apropos_accumulate = Fcons (symbol, apropos_accumulate);
 }
 
-DEFUN ("apropos-internal", Fapropos_internal, Sapropos_internal, 1, 2, 0, 
+DEFUN ("apropos-internal", Fapropos_internal, Sapropos_internal, 1, 2, 0,
        doc: /* Show all symbols whose names contain match for REGEXP.
 If optional 2nd arg PREDICATE is non-nil, (funcall PREDICATE SYMBOL) is done
 for each symbol and a symbol is mentioned only if that returns non-nil.
@@ -3290,15 +3420,15 @@ Return list of symbols found.  */)
      (regexp, predicate)
      Lisp_Object regexp, predicate;
 {
-  struct gcpro gcpro1, gcpro2;
+  Lisp_Object tem;
   CHECK_STRING (regexp);
   apropos_predicate = predicate;
-  GCPRO2 (apropos_predicate, apropos_accumulate);
   apropos_accumulate = Qnil;
   map_obarray (Vobarray, apropos_accum, regexp);
-  apropos_accumulate = Fsort (apropos_accumulate, Qstring_lessp);
-  UNGCPRO;
-  return apropos_accumulate;
+  tem = Fsort (apropos_accumulate, Qstring_lessp);
+  apropos_accumulate = Qnil;
+  apropos_predicate = Qnil;
+  return tem;
 }
 \f
 void
@@ -3306,6 +3436,10 @@ syms_of_keymap ()
 {
   Qkeymap = intern ("keymap");
   staticpro (&Qkeymap);
+  staticpro (&apropos_predicate);
+  staticpro (&apropos_accumulate);
+  apropos_predicate = Qnil;
+  apropos_accumulate = Qnil;
 
   /* Now we are ready to set up this property, so we can
      create char tables.  */
@@ -3375,11 +3509,21 @@ in the list takes precedence.  */);
 
   DEFVAR_LISP ("minor-mode-overriding-map-alist", &Vminor_mode_overriding_map_alist,
               doc: /* Alist of keymaps to use for minor modes, in current major mode.
-This variable is a alist just like `minor-mode-map-alist', and it is
+This variable is an alist just like `minor-mode-map-alist', and it is
 used the same way (and before `minor-mode-map-alist'); however,
 it is provided for major modes to bind locally.  */);
   Vminor_mode_overriding_map_alist = Qnil;
 
+  DEFVAR_LISP ("emulation-mode-map-alists", &Vemulation_mode_map_alists,
+              doc: /* List of keymap alists to use for emulations modes.
+It is intended for modes or packages using multiple minor-mode keymaps.
+Each element is a keymap alist just like `minor-mode-map-alist', or a
+symbol with a variable binding which is a keymap alist, and it is used
+the same way.  The "active" keymaps in each alist are used before
+`minor-mode-map-alist' and `minor-mode-overriding-map-alist'.  */);
+  Vemulation_mode_map_alists = Qnil;
+
+
   DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
               doc: /* Keymap mapping ASCII function key sequences onto their preferred forms.
 This allows Emacs to recognize function keys sent from ASCII
@@ -3407,6 +3551,15 @@ This keymap works like `function-key-map', but comes after that,
 and applies even for keys that have ordinary bindings.  */);
   Vkey_translation_map = Qnil;
 
+  staticpro (&Vmenu_events);
+  Vmenu_events = Fcons (intern ("menu-bar"),
+                       Fcons (intern ("tool-bar"),
+                              Fcons (intern ("mouse-1"),
+                                     Fcons (intern ("mouse-2"),
+                                            Fcons (intern ("mouse-3"),
+                                                   Qnil)))));
+
+
   Qsingle_key_description = intern ("single-key-description");
   staticpro (&Qsingle_key_description);
 
@@ -3425,8 +3578,8 @@ and applies even for keys that have ordinary bindings.  */);
   Qremap = intern ("remap");
   staticpro (&Qremap);
 
-  remap_command_vector = Fmake_vector (make_number (2), Qremap);
-  staticpro (&remap_command_vector);
+  command_remapping_vector = Fmake_vector (make_number (2), Qremap);
+  staticpro (&command_remapping_vector);
 
   where_is_cache_keymaps = Qt;
   where_is_cache = Qnil;
@@ -3439,8 +3592,9 @@ and applies even for keys that have ordinary bindings.  */);
   defsubr (&Sset_keymap_parent);
   defsubr (&Smake_keymap);
   defsubr (&Smake_sparse_keymap);
+  defsubr (&Smap_keymap);
   defsubr (&Scopy_keymap);
-  defsubr (&Sremap_command);
+  defsubr (&Scommand_remapping);
   defsubr (&Skey_binding);
   defsubr (&Slocal_key_binding);
   defsubr (&Sglobal_key_binding);