Include <config.h> instead of "config.h".
[bpt/emacs.git] / src / keymap.c
index 89a273d..f34a917 100644 (file)
@@ -1,5 +1,5 @@
 /* Manipulation of keymaps
-   Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,19 +18,19 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
-#include "config.h"
+#include <config.h>
 #include <stdio.h>
 #undef NULL
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
 #include "keyboard.h"
+#include "termhooks.h"
+#include "blockinput.h"
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
-/* Dense keymaps look like (keymap VECTOR . ALIST), where VECTOR is a
-   128-element vector used to look up bindings for ASCII characters,
-   and ALIST is an assoc list for looking up symbols.  */
+/* The number of elements in keymap vectors.  */
 #define DENSE_TABLE_SIZE (0200)
 
 /* Actually allocate storage for these variables */
@@ -73,42 +73,56 @@ Lisp_Object Vminor_mode_map_alist;
    documentation.  */
 Lisp_Object Vfunction_key_map;
 
-Lisp_Object Qkeymapp, Qkeymap;
-
-/* A char over 0200 in a key sequence
-   is equivalent to prefixing with this character.  */
+Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii;
 
+/* 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
+   character.  */
 extern Lisp_Object meta_prefix_char;
 
 void describe_map_tree ();
+static Lisp_Object define_as_prefix ();
 static Lisp_Object describe_buffer_bindings ();
 static void describe_command ();
 static void describe_map ();
-static void describe_alist ();
+static void describe_map_2 ();
 \f
 /* Keymap object support - constructors and predicates.                        */
 
-DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 0, 0,
+DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 1, 0,
   "Construct and return a new keymap, of the form (keymap VECTOR . ALIST).\n\
-VECTOR is a 128-element vector which holds the bindings for the ASCII\n\
+VECTOR is a vector which holds the bindings for the ASCII\n\
 characters.  ALIST is an assoc-list which holds bindings for function keys,\n\
 mouse events, and any other things that appear in the input stream.\n\
-All entries in it are initially nil, meaning \"command undefined\".")
-  ()
+All entries in it are initially nil, meaning \"command undefined\".\n\n\
+The optional arg STRING supplies a menu name for the keymap\n\
+in case you use it as a menu with `x-popup-menu'.")
+  (string)
+     Lisp_Object string;
 {
+  Lisp_Object tail;
+  if (!NILP (string))
+    tail = Fcons (string, Qnil);
+  else
+    tail = Qnil;
   return Fcons (Qkeymap,
                Fcons (Fmake_vector (make_number (DENSE_TABLE_SIZE), Qnil),
-                      Qnil));
+                      tail));
 }
 
-DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, Smake_sparse_keymap, 0, 0, 0,
+DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, Smake_sparse_keymap, 0, 1, 0,
   "Construct and return a new sparse-keymap list.\n\
 Its car is `keymap' and its cdr is an alist of (CHAR . DEFINITION),\n\
 which binds the character CHAR to DEFINITION, or (SYMBOL . DEFINITION),\n\
 which binds the function key or mouse event SYMBOL to DEFINITION.\n\
-Initially the alist is nil.")
-  ()
+Initially the alist is nil.\n\n\
+The optional arg STRING supplies a menu name for the keymap\n\
+in case you use it as a menu with `x-popup-menu'.")
+  (string)
+     Lisp_Object string;
 {
+  if (!NILP (string))
+    return Fcons (Qkeymap, Fcons (string, Qnil));
   return Fcons (Qkeymap, Qnil);
 }
 
@@ -117,13 +131,7 @@ Initially the alist is nil.")
 
    For example:
 
-   initial_define_key (control_x_map, Ctl('X'), "exchange-point-and-mark");
-
-   I haven't extended these to allow the initializing code to bind
-   function keys and mouse events; since they are called by many files,
-   I'd have to fix lots of callers, and nobody right now would be using
-   the new functionality, so it seems like a waste of time.  But there's
-   no technical reason not to.  -JimB */
+   initial_define_key (control_x_map, Ctl('X'), "exchange-point-and-mark");  */
 
 void
 initial_define_key (keymap, key, defname)
@@ -134,6 +142,15 @@ initial_define_key (keymap, key, defname)
   store_in_keymap (keymap, make_number (key), intern (defname));
 }
 
+void
+initial_define_lispy_key (keymap, keyname, defname)
+     Lisp_Object keymap;
+     char *keyname;
+     char *defname;
+{
+  store_in_keymap (keymap, intern (keyname), intern (defname));
+}
+
 /* Define character fromchar in map frommap as an alias for character
    tochar in map tomap.  Subsequent redefinitions of the latter WILL
    affect the former. */
@@ -154,98 +171,165 @@ synkey (frommap, fromchar, tomap, tochar)
 DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0,
   "Return t if ARG is a keymap.\n\
 \n\
-A keymap is list (keymap . ALIST), a list (keymap VECTOR . ALIST),\n\
+A keymap is a list (keymap . ALIST),\n\
 or a symbol whose function definition is a keymap is itself a keymap.\n\
 ALIST elements look like (CHAR . DEFN) or (SYMBOL . DEFN);\n\
-VECTOR is a 128-element vector of bindings for ASCII characters.")
+a vector of densely packed bindings for small character codes\n\
+is also allowed as an element.")
   (object)
      Lisp_Object object;
 {
-  return (NILP (get_keymap_1 (object, 0)) ? Qnil : Qt);
+  return (NILP (get_keymap_1 (object, 0, 0)) ? Qnil : Qt);
 }
 
 /* Check that OBJECT is a keymap (after dereferencing through any
-   symbols).  If it is, return it; otherwise, return nil, or signal an
-   error if ERROR != 0.  */
+   symbols).  If it is, return it.
+
+   If AUTOLOAD is non-zero and OBJECT is a symbol whose function value
+   is an autoload form, do the autoload and try again.
+
+   ERROR controls how we respond if OBJECT isn't a keymap.
+   If ERROR is non-zero, signal an error; otherwise, just return Qnil.
+
+   Note that most of the time, we don't want to pursue autoloads.
+   Functions like Faccessible_keymaps which scan entire keymap trees
+   shouldn't load every autoloaded keymap.  I'm not sure about this,
+   but it seems to me that only read_key_sequence, Flookup_key, and
+   Fdefine_key should cause keymaps to be autoloaded.  */
+
 Lisp_Object
-get_keymap_1 (object, error)
+get_keymap_1 (object, error, autoload)
      Lisp_Object object;
-     int error;
+     int error, autoload;
 {
-  register Lisp_Object tem;
+  Lisp_Object tem;
 
+ autoload_retry:
   tem = indirect_function (object);
   if (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap))
     return tem;
+
+  /* Should we do an autoload?  Autoload forms for keymaps have
+     Qkeymap as their fifth element.  */
+  if (autoload
+      && XTYPE (object) == Lisp_Symbol
+      && CONSP (tem)
+      && EQ (XCONS (tem)->car, Qautoload))
+    {
+      Lisp_Object tail;
+
+      tail = Fnth (make_number (4), tem);
+      if (EQ (tail, Qkeymap))
+       {
+         struct gcpro gcpro1, gcpro2;
+
+         GCPRO2 (tem, object);
+         do_autoload (tem, object);
+         UNGCPRO;
+
+         goto autoload_retry;
+       }
+    }
+
   if (error)
     wrong_type_argument (Qkeymapp, object);
   else
     return Qnil;
 }
 
+
+/* Follow any symbol chaining, and return the keymap denoted by OBJECT.
+   If OBJECT doesn't denote a keymap at all, signal an error.  */
 Lisp_Object
 get_keymap (object)
      Lisp_Object object;
 {
-  return get_keymap_1 (object, 1);
+  return get_keymap_1 (object, 0, 0);
 }
 
 
-/* If KEYMAP is a dense keymap, return the vector from its cadr.
-   Otherwise, return nil.  */
-
-static Lisp_Object
-keymap_table (keymap)
-     Lisp_Object keymap;
-{
-  Lisp_Object cadr;
+/* 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. 
 
-  if (CONSP (XCONS (keymap)->cdr)
-      && XTYPE (cadr = XCONS (XCONS (keymap)->cdr)->car) == Lisp_Vector
-      && XVECTOR (cadr)->size == DENSE_TABLE_SIZE)
-    return cadr;
-  else
-    return Qnil;
-}
+   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.  
 
+   If T_OK is zero, bindings for Qt are not treated specially.
 
-/* 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.  */
+   If NOINHERIT, don't accept a subkeymap found in an inherited keymap.  */
 
 Lisp_Object
-access_keymap (map, idx)
+access_keymap (map, idx, t_ok, noinherit)
      Lisp_Object map;
      Lisp_Object idx;
+     int t_ok;
+     int noinherit;
 {
+  int noprefix = 0;
+  Lisp_Object val;
+
   /* 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.  */
-  if (EVENT_HAS_PARAMETERS (idx))
-    idx = EVENT_HEAD (idx);
+  idx = EVENT_HEAD (idx);
 
-  if (XTYPE (idx) == Lisp_Int
-      && (XINT (idx) < 0 || XINT (idx) >= DENSE_TABLE_SIZE))
-    error ("Command key is not an ASCII character");
+  /* If idx is a symbol, it might have modifiers, which need to
+     be put in the canonical order.  */
+  if (XTYPE (idx) == Lisp_Symbol)
+    idx = reorder_modifiers (idx);
+  else if (INTEGERP (idx))
+    /* Clobber the high bits that can be present on a machine
+       with more than 24 bits of integer.  */
+    XFASTINT (idx) = XINT (idx) & (CHAR_META | (CHAR_META - 1));
 
   {
-    Lisp_Object table = keymap_table (map);
-
-    /* A dense keymap indexed by a character?  */
-    if (XTYPE (idx) == Lisp_Int
-       && ! NILP (table))
-      return XVECTOR (table)->contents[XFASTINT (idx)];
+    Lisp_Object tail;
+    Lisp_Object t_binding = Qnil;
 
-    /* This lookup will not involve a vector reference.  */
-    else
+    for (tail = map; CONSP (tail); tail = XCONS (tail)->cdr)
       {
-       /* If idx is a symbol, it might have modifiers, which need to
-          be put in the canonical order.  */
-       if (XTYPE (idx) == Lisp_Symbol)
-         idx = reorder_modifiers (idx);
-       
-       return Fcdr (Fassq (idx, map));
+       Lisp_Object binding = XCONS (tail)->car;
+
+       switch (XTYPE (binding))
+         {
+         case Lisp_Symbol:
+           /* If NOINHERIT, stop finding prefix definitions
+              after we pass a second occurrence of the `keymap' symbol.  */
+           if (noinherit && EQ (binding, Qkeymap) && ! EQ (tail, map))
+             noprefix = 1;
+           break;
+
+         case Lisp_Cons:
+           if (EQ (XCONS (binding)->car, idx))
+             {
+               val = XCONS (binding)->cdr;
+               if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap))
+                 return Qnil;
+               return val;
+             }
+           if (t_ok && EQ (XCONS (binding)->car, Qt))
+             t_binding = XCONS (binding)->cdr;
+           break;
+
+         case Lisp_Vector:
+           if (XTYPE (idx) == Lisp_Int
+               && XINT (idx) >= 0
+               && XINT (idx) < XVECTOR (binding)->size)
+             {
+               val = XVECTOR (binding)->contents[XINT (idx)];
+               if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap))
+                 return Qnil;
+               return val;
+             }
+           break;
+         }
+
+       QUIT;
       }
+
+    return t_binding;
   }
 }
 
@@ -256,7 +340,7 @@ access_keymap (map, idx)
    and INDEX is the object to look up in KEYMAP to yield the definition.
 
    Also if OBJECT has a menu string as the first element,
-   remove that.  */
+   remove that.  Also remove a menu help string as second element.  */
 
 Lisp_Object
 get_keyelt (object)
@@ -266,12 +350,11 @@ get_keyelt (object)
     {
       register Lisp_Object map, tem;
 
-      map = get_keymap_1 (Fcar_safe (object), 0);
-      tem = Fkeymapp (map);
-
       /* If the contents are (KEYMAP . ELEMENT), go indirect.  */
+      map = get_keymap_1 (Fcar_safe (object), 0, 0);
+      tem = Fkeymapp (map);
       if (!NILP (tem))
-       object = access_keymap (map, Fcdr (object));
+       object = access_keymap (map, Fcdr (object), 0, 0);
       
       /* If the keymap contents looks like (STRING . DEFN),
         use DEFN.
@@ -279,7 +362,14 @@ get_keyelt (object)
         will be used by HierarKey menus.  */
       else if (XTYPE (object) == Lisp_Cons
               && XTYPE (XCONS (object)->car) == Lisp_String)
-       object = XCONS (object)->cdr;
+       {
+         object = XCONS (object)->cdr;
+         /* Also remove a menu help string, if any,
+            following the menu item name.  */
+         if (XTYPE (object) == Lisp_Cons
+             && XTYPE (XCONS (object)->car) == Lisp_String)
+           object = XCONS (object)->cdr;
+       }
 
       else
        /* Anything else is really the value.  */
@@ -293,52 +383,84 @@ store_in_keymap (keymap, idx, def)
      register Lisp_Object idx;
      register Lisp_Object def;
 {
+  if (XTYPE (keymap) != Lisp_Cons
+      || ! EQ (XCONS (keymap)->car, 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.  */
-  if (EVENT_HAS_PARAMETERS (idx))
-    idx = EVENT_HEAD (idx);
-
-  if (XTYPE (idx) == Lisp_Int
-      && (XINT (idx) < 0 || XINT (idx) >= DENSE_TABLE_SIZE))
-    error ("Command key is a character outside of the ASCII set.");
-  
+  idx = EVENT_HEAD (idx);
+
+  /* If idx is a symbol, it might have modifiers, which need to
+     be put in the canonical order.  */
+  if (XTYPE (idx) == Lisp_Symbol)
+    idx = reorder_modifiers (idx);
+  else if (INTEGERP (idx))
+    /* Clobber the high bits that can be present on a machine
+       with more than 24 bits of integer.  */
+    XFASTINT (idx) = XINT (idx) & (CHAR_META | (CHAR_META - 1));
+
+  /* Scan the keymap for a binding of idx.  */
   {
-    Lisp_Object table = keymap_table (keymap);
+    Lisp_Object tail;
 
-    /* A dense keymap indexed by a character?  */
-    if (XTYPE (idx) == Lisp_Int        && !NILP (table))
-      XVECTOR (table)->contents[XFASTINT (idx)] = def;
+    /* The cons after which we should insert new bindings.  If the
+       keymap has a table element, we record its position here, so new
+       bindings will go after it; this way, the table will stay
+       towards the front of the alist and character lookups in dense
+       keymaps will remain fast.  Otherwise, this just points at the
+       front of the keymap.  */
+    Lisp_Object insertion_point = keymap;
 
-    /* Must be a sparse keymap, or a dense keymap indexed by a symbol.  */
-    else
+    for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = XCONS (tail)->cdr)
       {
-       /* Point to the pointer to the start of the assoc-list part
-          of the keymap.  */
-       register Lisp_Object *assoc_head
-         = (NILP (table)
-            ? & XCONS (keymap)->cdr
-            : & XCONS (XCONS (keymap)->cdr)->cdr);
-       register Lisp_Object defining_pair;
-
-       /* If idx is a symbol, it might have modifiers, which need to
-          be put in the canonical order.  */
-       if (XTYPE (idx) == Lisp_Symbol)
-         idx = reorder_modifiers (idx);
-
-       /* Point to the pair where idx is bound, if any.  */
-       defining_pair = Fassq (idx, *assoc_head);
-
-       if (NILP (defining_pair))
-         *assoc_head = Fcons (Fcons (idx, def), *assoc_head);
-       else
-         Fsetcdr (defining_pair, def);
+       Lisp_Object elt = XCONS (tail)->car;
+
+       switch (XTYPE (elt))
+         {
+         case Lisp_Vector:
+           if (XTYPE (idx) == Lisp_Int
+               && XINT (idx) >= 0 && XINT (idx) < XVECTOR (elt)->size)
+             {
+               XVECTOR (elt)->contents[XFASTINT (idx)] = def;
+               return def;
+             }
+           insertion_point = tail;
+           break;
+
+         case Lisp_Cons:
+           if (EQ (idx, XCONS (elt)->car))
+             {
+               XCONS (elt)->cdr = def;
+               return def;
+             }
+           break;
+
+         case Lisp_Symbol:
+           /* If we find a 'keymap' symbol in the spine of KEYMAP,
+               then we must have found the start of a second keymap
+               being used as the tail of KEYMAP, and a binding for IDX
+               should be inserted before it.  */
+           if (EQ (elt, Qkeymap))
+             goto keymap_end;
+           break;
+         }
+
+       QUIT;
       }
-  }
 
+  keymap_end:
+    /* We have scanned the entire keymap, and not found a binding for
+       IDX.  Let's add one.  */
+    XCONS (insertion_point)->cdr =
+      Fcons (Fcons (idx, def), XCONS (insertion_point)->cdr);
+  }
+         
   return def;
 }
 
+
 DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0,
   "Return a copy of the keymap KEYMAP.\n\
 The copy starts out with the same definitions of KEYMAP,\n\
@@ -352,43 +474,28 @@ is not copied.")
   register Lisp_Object copy, tail;
 
   copy = Fcopy_alist (get_keymap (keymap));
-  tail = XCONS (copy)->cdr;
 
-  /* If this is a dense keymap, copy the vector.  */
-  if (CONSP (tail))
+  for (tail = copy; CONSP (tail); tail = XCONS (tail)->cdr)
     {
-      register Lisp_Object table = XCONS (tail)->car;
+      Lisp_Object elt = XCONS (tail)->car;
 
-      if (XTYPE (table) == Lisp_Vector
-         && XVECTOR (table)->size == DENSE_TABLE_SIZE)
+      if (XTYPE (elt) == Lisp_Vector)
        {
-         register int i;
+         int i;
 
-         table = Fcopy_sequence (table);
+         elt = Fcopy_sequence (elt);
+         XCONS (tail)->car = elt;
 
-         for (i = 0; i < DENSE_TABLE_SIZE; i++)
-           if (XTYPE (XVECTOR (copy)->contents[i]) != Lisp_Symbol)
-             if (! NILP (Fkeymapp (XVECTOR (table)->contents[i])))
-               XVECTOR (table)->contents[i]
-                 = Fcopy_keymap (XVECTOR (table)->contents[i]);
-         XCONS (tail)->car = table;
-      
-         tail = XCONS (tail)->cdr;
+         for (i = 0; i < XVECTOR (elt)->size; i++)
+           if (XTYPE (XVECTOR (elt)->contents[i]) != Lisp_Symbol
+               && ! NILP (Fkeymapp (XVECTOR (elt)->contents[i])))
+             XVECTOR (elt)->contents[i] =
+               Fcopy_keymap (XVECTOR (elt)->contents[i]);
        }
-    }
-
-  /* Copy the alist portion of the keymap.  */
-  while (CONSP (tail))
-    {
-      register Lisp_Object elt;
-
-      elt = XCONS (tail)->car;
-      if (CONSP (elt)
-         && XTYPE (XCONS (elt)->cdr) != Lisp_Symbol
-         && ! NILP (Fkeymapp (XCONS (elt)->cdr)))
+      else if (CONSP (elt)
+              && XTYPE (XCONS (elt)->cdr) != Lisp_Symbol
+              && ! NILP (Fkeymapp (XCONS (elt)->cdr)))
        XCONS (elt)->cdr = Fcopy_keymap (XCONS (elt)->cdr);
-
-      tail = XCONS (tail)->cdr;
     }
 
   return copy;
@@ -415,7 +522,7 @@ DEF is anything that can be a key's definition:\n\
 If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at\n\
 the front of KEYMAP.")
   (keymap, key, def)
-     register Lisp_Object keymap;
+     Lisp_Object keymap;
      Lisp_Object key;
      Lisp_Object def;
 {
@@ -424,7 +531,9 @@ the front of KEYMAP.")
   register Lisp_Object tem;
   register Lisp_Object cmd;
   int metized = 0;
+  int meta_bit;
   int length;
+  struct gcpro gcpro1, gcpro2, gcpro3;
 
   keymap = get_keymap (keymap);
 
@@ -432,17 +541,24 @@ the front of KEYMAP.")
       && XTYPE (key) != Lisp_String)
     key = wrong_type_argument (Qarrayp, key);
 
-  length = Flength (key);
+  length = XFASTINT (Flength (key));
   if (length == 0)
     return Qnil;
 
+  GCPRO3 (keymap, key, def);
+
+  if (XTYPE (key) == Lisp_Vector)
+    meta_bit = meta_modifier;
+  else
+    meta_bit = 0x80;
+
   idx = 0;
   while (1)
     {
       c = Faref (key, make_number (idx));
 
       if (XTYPE (c) == Lisp_Int
-         && XINT (c) >= 0200
+         && (XINT (c) & meta_bit)
          && !metized)
        {
          c = meta_prefix_char;
@@ -451,45 +567,55 @@ the front of KEYMAP.")
       else
        {
          if (XTYPE (c) == Lisp_Int)
-           XSETINT (c, XINT (c) & 0177);
+           XSETINT (c, XINT (c) & ~meta_bit);
 
          metized = 0;
          idx++;
        }
 
       if (idx == length)
-       return store_in_keymap (keymap, c, def);
+       RETURN_UNGCPRO (store_in_keymap (keymap, c, def));
 
-      cmd = get_keyelt (access_keymap (keymap, c));
+      cmd = get_keyelt (access_keymap (keymap, c, 0, 1));
 
+      /* If this key is undefined, make it a prefix.  */
       if (NILP (cmd))
-       {
-         cmd = Fmake_sparse_keymap ();
-         store_in_keymap (keymap, c, cmd);
-       }
+       cmd = define_as_prefix (keymap, c);
 
-      tem = Fkeymapp (cmd);
-      if (NILP (tem))
-       error ("Key sequence %s uses invalid prefix characters",
-              XSTRING (key)->data);
+      keymap = get_keymap_1 (cmd, 0, 1);
+      if (NILP (keymap))
+       {
+         /* We must use Fkey_description rather than just passing key to
+            error; key might be a vector, not a string.  */
+         Lisp_Object description = Fkey_description (key);
 
-      keymap = get_keymap (cmd);
+         error ("Key sequence %s uses invalid prefix characters",
+                XSTRING (description)->data);
+       }
     }
 }
 
 /* Value is number if KEY is too long; NIL if valid but has no definition. */
 
-DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 2, 0,
+DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0,
   "In keymap KEYMAP, look up key sequence KEY.  Return the definition.\n\
 nil means undefined.  See doc of `define-key' for kinds of definitions.\n\
+\n\
 A number as value means KEY is \"too long\";\n\
 that is, characters or symbols in it except for the last one\n\
 fail to be a valid sequence of prefix characters in KEYMAP.\n\
 The number is how many characters at the front of KEY\n\
-it takes to reach a non-prefix command.")
-  (keymap, key)
+it takes to reach a non-prefix command.\n\
+\n\
+Normally, `lookup-key' ignores bindings for t, which act as default\n\
+bindings, used when nothing else in the keymap applies; this makes it\n\
+useable as a general function for probing keymaps.  However, if the\n\
+third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will\n\
+recognize the default bindings, just as `read-key-sequence' does.")
+  (keymap, key, accept_default)
      register Lisp_Object keymap;
      Lisp_Object key;
+     Lisp_Object accept_default;
 {
   register int idx;
   register Lisp_Object tem;
@@ -497,6 +623,8 @@ it takes to reach a non-prefix command.")
   register Lisp_Object c;
   int metized = 0;
   int length;
+  int t_ok = ! NILP (accept_default);
+  int meta_bit;
 
   keymap = get_keymap (keymap);
 
@@ -504,17 +632,22 @@ it takes to reach a non-prefix command.")
       && XTYPE (key) != Lisp_String)
     key = wrong_type_argument (Qarrayp, key);
 
-  length = Flength (key);
+  length = XFASTINT (Flength (key));
   if (length == 0)
     return keymap;
 
+  if (XTYPE (key) == Lisp_Vector)
+    meta_bit = meta_modifier;
+  else
+    meta_bit = 0x80;
+
   idx = 0;
   while (1)
     {
       c = Faref (key, make_number (idx));
 
       if (XTYPE (c) == Lisp_Int
-         && XINT (c) >= 0200
+         && (XINT (c) & meta_bit)
          && !metized)
        {
          c = meta_prefix_char;
@@ -523,28 +656,62 @@ it takes to reach a non-prefix command.")
       else
        {
          if (XTYPE (c) == Lisp_Int)
-           XSETINT (c, XINT (c) & 0177);
+           XSETINT (c, XINT (c) & ~meta_bit);
 
          metized = 0;
          idx++;
        }
 
-      cmd = get_keyelt (access_keymap (keymap, c));
+      cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0));
       if (idx == length)
        return cmd;
 
-      tem = Fkeymapp (cmd);
-      if (NILP (tem))
+      keymap = get_keymap_1 (cmd, 0, 0);
+      if (NILP (keymap))
        return make_number (idx);
 
-      keymap = get_keymap (cmd);
       QUIT;
     }
 }
 
-/* Append a key to the end of a key sequence.  If key_sequence is a
-   string and key is a character, the result will be another string;
-   otherwise, it will be a vector.  */
+/* Make KEYMAP define event C as a keymap (i.e., as a prefix).
+   Assume that currently it does not define C at all.
+   Return the keymap.  */
+
+static Lisp_Object
+define_as_prefix (keymap, c)
+     Lisp_Object keymap, c;
+{
+  Lisp_Object inherit, cmd;
+
+  cmd = Fmake_sparse_keymap (Qnil);
+  /* If this key is defined as a prefix in an inherited keymap,
+     make it a prefix in this map, and make its definition
+     inherit the other prefix definition.  */
+  inherit = access_keymap (keymap, c, 0, 0);
+  if (NILP (inherit))
+    {
+      /* If there's an inherited keymap
+        and it doesn't define this key,
+        make it define this key.  */
+      Lisp_Object tail;
+
+      for (tail = Fcdr (keymap); CONSP (tail); tail = XCONS (tail)->cdr)
+       if (EQ (XCONS (tail)->car, Qkeymap))
+         break;
+
+      if (!NILP (tail))
+       inherit = define_as_prefix (tail, c);
+    }
+
+  cmd = nconc2 (cmd, inherit);
+  store_in_keymap (keymap, c, cmd);
+
+  return cmd;
+}
+
+/* Append a key to the end of a key sequence.  We always make a vector.  */
+
 Lisp_Object
 append_key (key_sequence, key)
      Lisp_Object key_sequence, key;
@@ -553,17 +720,8 @@ append_key (key_sequence, key)
 
   args[0] = key_sequence;
 
-  if (XTYPE (key_sequence) == Lisp_String
-      && XTYPE (key) == Lisp_Int)
-    {
-      args[1] = Fchar_to_string (key);
-      return Fconcat (2, args);
-    }
-  else
-    {
-      args[1] = Fcons (key, Qnil);
-      return Fvconcat (2, args);
-    }
+  args[1] = Fcons (key, Qnil);
+  return Fvconcat (2, args);
 }
 
 \f
@@ -612,13 +770,17 @@ current_minor_maps (modeptr, mapptr)
 
            if (cmm_maps)
              {
+               BLOCK_INPUT;
                newmodes = (Lisp_Object *) realloc (cmm_modes, cmm_size *= 2);
                newmaps  = (Lisp_Object *) realloc (cmm_maps,  cmm_size);
+               UNBLOCK_INPUT;
              }
            else
              {
+               BLOCK_INPUT;
                newmodes = (Lisp_Object *) malloc (cmm_size = 30);
                newmaps  = (Lisp_Object *) malloc (cmm_size);
+               UNBLOCK_INPUT;
              }
 
            if (newmaps && newmodes)
@@ -630,7 +792,7 @@ current_minor_maps (modeptr, mapptr)
              break;
          }
        cmm_modes[i] = var;
-       cmm_maps [i] = XCONS (assoc)->cdr;
+       cmm_maps [i] = Findirect_function (XCONS (assoc)->cdr);
        i++;
       }
 
@@ -639,11 +801,17 @@ current_minor_maps (modeptr, mapptr)
   return i;
 }
 
-DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 1, 0,
+DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 2, 0,
   "Return the binding for command KEY in current keymaps.\n\
-KEY is a string, a sequence of keystrokes.\n\
-The binding is probably a symbol with a function definition.")
-  (key)
+KEY is a string or vector, a sequence of keystrokes.\n\
+The binding is probably a symbol with a function definition.\n\
+\n\
+Normally, `key-binding' ignores bindings for t, which act as default\n\
+bindings, used when nothing else in the keymap applies; this makes it\n\
+useable as a general function for probing keymaps.  However, if the\n\
+third optional argument ACCEPT-DEFAULT is non-nil, `key-binding' will\n\
+recognize the default bindings, just as `read-key-sequence' does.")
+  (key, accept_default)
      Lisp_Object key;
 {
   Lisp_Object *maps, value;
@@ -653,52 +821,58 @@ The binding is probably a symbol with a function definition.")
   for (i = 0; i < nmaps; i++)
     if (! NILP (maps[i]))
       {
-       value = Flookup_key (maps[i], key);
+       value = Flookup_key (maps[i], key, accept_default);
        if (! NILP (value) && XTYPE (value) != Lisp_Int)
          return value;
       }
 
   if (! NILP (current_buffer->keymap))
     {
-      value = Flookup_key (current_buffer->keymap, key);
+      value = Flookup_key (current_buffer->keymap, key, accept_default);
       if (! NILP (value) && XTYPE (value) != Lisp_Int)
        return value;
     }
 
-  value = Flookup_key (current_global_map, key);
+  value = Flookup_key (current_global_map, key, accept_default);
   if (! NILP (value) && XTYPE (value) != Lisp_Int)
     return value;
   
   return Qnil;
 }
 
-DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 1, 0,
+DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 2, 0,
   "Return the binding for command KEYS in current local keymap only.\n\
 KEYS is a string, a sequence of keystrokes.\n\
-The binding is probably a symbol with a function definition.")
-  (keys)
-     Lisp_Object keys;
+The binding is probably a symbol with a function definition.\n\
+\n\
+If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\
+bindings; see the description of `lookup-key' for more details about this.")
+  (keys, accept_default)
+     Lisp_Object keys, accept_default;
 {
   register Lisp_Object map;
   map = current_buffer->keymap;
   if (NILP (map))
     return Qnil;
-  return Flookup_key (map, keys);
+  return Flookup_key (map, keys, accept_default);
 }
 
-DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 1, 0,
+DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 2, 0,
   "Return the binding for command KEYS in current global keymap only.\n\
 KEYS is a string, a sequence of keystrokes.\n\
 The binding is probably a symbol with a function definition.\n\
 This function's return values are the same as those of lookup-key\n\
-(which see).")
-  (keys)
-     Lisp_Object keys;
+(which see).\n\
+\n\
+If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\
+bindings; see the description of `lookup-key' for more details about this.")
+  (keys, accept_default)
+     Lisp_Object keys, accept_default;
 {
-  return Flookup_key (current_global_map, keys);
+  return Flookup_key (current_global_map, keys, accept_default);
 }
 
-DEFUN ("minor-mode-key-binding", Fminor_mode_key_binding, Sminor_mode_key_binding, 1, 1, 0,
+DEFUN ("minor-mode-key-binding", Fminor_mode_key_binding, Sminor_mode_key_binding, 1, 2, 0,
   "Find the visible minor mode bindings of KEY.\n\
 Return an alist of pairs (MODENAME . BINDING), where MODENAME is the\n\
 the symbol which names the minor mode binding KEY, and BINDING is\n\
@@ -706,8 +880,12 @@ KEY's definition in that mode.  In particular, if KEY has no\n\
 minor-mode bindings, return nil.  If the first binding is a\n\
 non-prefix, all subsequent bindings will be omitted, since they would\n\
 be ignored.  Similarly, the list doesn't include non-prefix bindings\n\
-that come after prefix bindings.")
-  (key)
+that come after prefix bindings.\n\
+\n\
+If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\
+bindings; see the description of `lookup-key' for more details about this.")
+  (key, accept_default)
+     Lisp_Object key, accept_default;
 {
   Lisp_Object *modes, *maps;
   int nmaps;
@@ -718,10 +896,10 @@ that come after prefix bindings.")
 
   for (i = j = 0; i < nmaps; i++)
     if (! NILP (maps[i])
-       && ! NILP (binding = Flookup_key (maps[i], key))
+       && ! NILP (binding = Flookup_key (maps[i], key, accept_default))
        && XTYPE (binding) != Lisp_Int)
       {
-       if (! NILP (get_keymap_1 (binding, 0)))
+       if (! NILP (get_keymap (binding)))
          maps[j++] = Fcons (modes[i], binding);
        else if (j == 0)
          return Fcons (Fcons (modes[i], binding), Qnil);
@@ -734,7 +912,7 @@ DEFUN ("global-set-key", Fglobal_set_key, Sglobal_set_key, 2, 2,
   "kSet key globally: \nCSet key %s to command: ",
   "Give KEY a global binding as COMMAND.\n\
 COMMAND is a symbol naming an interactively-callable function.\n\
-KEY is a string representing a sequence of keystrokes.\n\
+KEY is a key sequence (a string or vector of characters or event types).\n\
 Note that if KEY has a local binding in the current buffer\n\
 that local binding will continue to shadow any global binding.")
   (keys, function)
@@ -752,7 +930,7 @@ DEFUN ("local-set-key", Flocal_set_key, Slocal_set_key, 2, 2,
   "kSet key locally: \nCSet key %s locally to command: ",
   "Give KEY a local binding as COMMAND.\n\
 COMMAND is a symbol naming an interactively-callable function.\n\
-KEY is a string representing a sequence of keystrokes.\n\
+KEY is a key sequence (a string or vector of characters or event types).\n\
 The binding goes in the current buffer's local map,\n\
 which is shared with other buffers in the same major mode.")
   (keys, function)
@@ -762,7 +940,7 @@ which is shared with other buffers in the same major mode.")
   map = current_buffer->keymap;
   if (NILP (map))
     {
-      map = Fmake_sparse_keymap ();
+      map = Fmake_sparse_keymap (Qnil);
       current_buffer->keymap = map;
     }
 
@@ -797,7 +975,7 @@ KEY is a string representing a sequence of keystrokes.")
 }
 
 DEFUN ("define-prefix-command", Fdefine_prefix_command, Sdefine_prefix_command, 1, 2, 0,
-  "Define COMMAND as a prefix command.\n\
+  "Define COMMAND as a prefix command.  COMMAND should be a symbol.\n\
 A new sparse keymap is stored as COMMAND's function definition and its value.\n\
 If a second optional argument MAPVAR is given, the map is stored as\n\
 its value instead of as COMMAND's value; but COMMAND is still defined\n\
@@ -806,7 +984,7 @@ as a function.")
      Lisp_Object name, mapvar;
 {
   Lisp_Object map;
-  map = Fmake_sparse_keymap ();
+  map = Fmake_sparse_keymap (Qnil);
   Ffset (name, map);
   if (!NILP (mapvar))
     Fset (mapvar, map);
@@ -866,18 +1044,25 @@ DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_
 /* Help functions for describing and documenting keymaps.              */
 
 DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps,
-  1, 1, 0,
+  1, 2, 0,
   "Find all keymaps accessible via prefix characters from KEYMAP.\n\
 Returns a list of elements of the form (KEYS . MAP), where the sequence\n\
 KEYS starting from KEYMAP gets you to MAP.  These elements are ordered\n\
-so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
-  (startmap)
-     Lisp_Object startmap;
+so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).\n\
+An optional argument PREFIX, if non-nil, should be a key sequence;\n\
+then the value includes only maps for prefixes that start with PREFIX.")
+  (startmap, prefix)
+     Lisp_Object startmap, prefix;
 {
-  Lisp_Object maps, tail;
+  Lisp_Object maps, good_maps, tail;
+  int prefixlen = 0;
 
-  maps = Fcons (Fcons (build_string (""), get_keymap (startmap)), Qnil);
-  tail = maps;
+  if (!NILP (prefix))
+    prefixlen = XINT (Flength (prefix));
+
+  maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil),
+                      get_keymap (startmap)),
+               Qnil);
 
   /* For each map in the list maps,
      look at any other maps it points to,
@@ -886,7 +1071,7 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
      This is a breadth-first traversal, where tail is the queue of
      nodes, and maps accumulates a list of all nodes visited.  */
 
-  while (!NILP (tail))
+  for (tail = maps; CONSP (tail); tail = XCONS (tail)->cdr)
     {
       register Lisp_Object thisseq = Fcar (Fcar (tail));
       register Lisp_Object thismap = Fcdr (Fcar (tail));
@@ -896,24 +1081,23 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
       int is_metized = (XINT (last) >= 0
                        && EQ (Faref (thisseq, last), meta_prefix_char));
 
-      /* Skip the 'keymap element of the list.  */
-      thismap = Fcdr (thismap);
-
-      if (CONSP (thismap))
+      for (; CONSP (thismap); thismap = XCONS (thismap)->cdr)
        {
-         register Lisp_Object table = XCONS (thismap)->car;
+         Lisp_Object elt = XCONS (thismap)->car;
+
+         QUIT;
 
-         if (XTYPE (table) == Lisp_Vector)
+         if (XTYPE (elt) == Lisp_Vector)
            {
              register int i;
 
              /* Vector keymap.  Scan all the elements.  */
-             for (i = 0; i < DENSE_TABLE_SIZE; i++)
+             for (i = 0; i < XVECTOR (elt)->size; i++)
                {
                  register Lisp_Object tem;
                  register Lisp_Object cmd;
 
-                 cmd = get_keyelt (XVECTOR (table)->contents[i]);
+                 cmd = get_keyelt (XVECTOR (elt)->contents[i]);
                  if (NILP (cmd)) continue;
                  tem = Fkeymapp (cmd);
                  if (!NILP (tem))
@@ -926,17 +1110,20 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                          /* 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.  */
+                            ascii keystroke since we're processing a
+                            keymap table.  */
                          if (is_metized)
                            {
+                             int meta_bit = meta_modifier;
                              tem = Fcopy_sequence (thisseq);
-                             Faset (tem, last, make_number (i | 0200));
+                             
+                             Faset (tem, last, make_number (i | meta_bit));
                              
                              /* This new sequence is the same length as
                                 thisseq, so stick it in the list right
                                 after this one.  */
-                             XCONS (tail)->cdr =
-                               Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
+                             XCONS (tail)->cdr
+                               Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
                            }
                          else
                            {
@@ -946,23 +1133,11 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                        }
                    }
                }
-
-             /* Once finished with the lookup elements of the dense
-                keymap, go on to scan its assoc list.  */
-             thismap = XCONS (thismap)->cdr;
-           }
-       }
-
-      /* The rest is an alist.  Scan all the alist elements.  */
-      while (CONSP (thismap))
-       {
-         Lisp_Object elt = XCONS (thismap)->car;
-
-         /* Ignore elements that are not conses.  */
-         if (CONSP (elt))
+           }       
+         else if (CONSP (elt))
            {
              register Lisp_Object cmd = get_keyelt (XCONS (elt)->cdr);
-             register Lisp_Object tem;
+             register Lisp_Object tem, filter;
 
              /* Ignore definitions that aren't keymaps themselves.  */
              tem = Fkeymapp (cmd);
@@ -973,7 +1148,7 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                  tem = Frassq (cmd, maps);
                  if (NILP (tem))
                    {
-                     /* let elt be the event defined by this map entry.  */
+                     /* Let elt be the event defined by this map entry.  */
                      elt = XCONS (elt)->car;
 
                      /* If the last key in thisseq is meta-prefix-char, and
@@ -982,13 +1157,14 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                      if (is_metized && XTYPE (elt) == Lisp_Int)
                        {
                          tem = Fcopy_sequence (thisseq);
-                         Faset (tem, last, make_number (XINT (elt) | 0200));
+                         Faset (tem, last,
+                                make_number (XINT (elt) | meta_modifier));
 
                          /* This new sequence is the same length as
                             thisseq, so stick it in the list right
                             after this one.  */
-                         XCONS (tail)->cdr =
-                           Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
+                         XCONS (tail)->cdr
+                           Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
                        }
                      else
                        nconc2 (tail,
@@ -997,14 +1173,38 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                    }
                }
            }
-         
-         thismap = XCONS (thismap)->cdr;
        }
+    }
 
-      tail = Fcdr (tail);
+  if (NILP (prefix))
+    return maps;
+
+  /* Now find just the maps whose access prefixes start with PREFIX.  */
+
+  good_maps = Qnil;
+  for (; CONSP (maps); maps = XCONS (maps)->cdr)
+    {
+      Lisp_Object elt, thisseq;
+      elt = XCONS (maps)->car;
+      thisseq = XCONS (elt)->car;
+      /* 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;
+             XFASTINT (i1) = i;
+             if (!EQ (Faref (thisseq, i1), Faref (prefix, i1)))
+               break;
+           }
+         if (i == prefixlen)
+           good_maps = Fcons (elt, good_maps);
+       }
     }
 
-  return maps;
+  return Fnreverse (good_maps);
 }
 
 Lisp_Object Qsingle_key_description, Qkey_description;
@@ -1016,6 +1216,22 @@ spaces are put between sequence elements, etc.")
   (keys)
      Lisp_Object keys;
 {
+  if (XTYPE (keys) == Lisp_String)
+    {
+      Lisp_Object vector;
+      int i;
+      vector = Fmake_vector (Flength (keys), Qnil);
+      for (i = 0; i < XSTRING (keys)->size; i++)
+       {
+         if (XSTRING (keys)->data[i] & 0x80)
+           XFASTINT (XVECTOR (vector)->contents[i])
+             = meta_modifier | (XSTRING (keys)->data[i] & ~0x80);
+         else
+           XFASTINT (XVECTOR (vector)->contents[i])
+             = XSTRING (keys)->data[i];
+       }
+      keys = vector;
+    }
   return Fmapconcat (Qsingle_key_description, keys, build_string (" "));
 }
 
@@ -1024,11 +1240,44 @@ push_key_description (c, p)
      register unsigned int c;
      register char *p;
 {
-  if (c >= 0200)
+  /* Clear all the meaningless bits above the meta bit.  */
+  c &= meta_modifier | ~ - meta_modifier;
+
+  if (c & alt_modifier)
+    {
+      *p++ = 'A';
+      *p++ = '-';
+      c -= alt_modifier;
+    }
+  if (c & ctrl_modifier)
+    {
+      *p++ = 'C';
+      *p++ = '-';
+      c -= ctrl_modifier;
+    }
+  if (c & hyper_modifier)
+    {
+      *p++ = 'H';
+      *p++ = '-';
+      c -= hyper_modifier;
+    }
+  if (c & meta_modifier)
     {
       *p++ = 'M';
       *p++ = '-';
-      c -= 0200;
+      c -= meta_modifier;
+    }
+  if (c & shift_modifier)
+    {
+      *p++ = 'S';
+      *p++ = '-';
+      c -= shift_modifier;
+    }
+  if (c & super_modifier)
+    {
+      *p++ = 's';
+      *p++ = '-';
+      c -= super_modifier;
     }
   if (c < 040)
     {
@@ -1038,7 +1287,7 @@ push_key_description (c, p)
          *p++ = 'S';
          *p++ = 'C';
        }
-      else if (c == Ctl('I'))
+      else if (c == '\t')
        {
          *p++ = 'T';
          *p++ = 'A';
@@ -1078,8 +1327,18 @@ push_key_description (c, p)
       *p++ = 'P';
       *p++ = 'C';
     }
-  else
+  else if (c < 256)
     *p++ = c;
+  else
+    {
+      *p++ = '\\';
+      *p++ = (7 & (c >> 15)) + '0';
+      *p++ = (7 & (c >> 12)) + '0';
+      *p++ = (7 & (c >> 9)) + '0';
+      *p++ = (7 & (c >> 6)) + '0';
+      *p++ = (7 & (c >> 3)) + '0';
+      *p++ = (7 & (c >> 0)) + '0';
+    }
 
   return p;  
 }
@@ -1090,17 +1349,14 @@ Control characters turn into C-whatever, etc.")
   (key)
      Lisp_Object key;
 {
-  register unsigned char c;
-  char tem[6];
+  char tem[20];
 
-  if (EVENT_HAS_PARAMETERS (key))
-    key = EVENT_HEAD (key);
+  key = EVENT_HEAD (key);
 
   switch (XTYPE (key))
     {
     case Lisp_Int:             /* Normal character */
-      c = XINT (key) & 0377;
-      *push_key_description (c, tem) = 0;
+      *push_key_description (XUINT (key), tem) = 0;
       return build_string (tem);
 
     case Lisp_Symbol:          /* Function key or event-symbol */
@@ -1151,6 +1407,28 @@ Control characters turn into \"^char\", etc.")
 
   return build_string (tem);
 }
+
+/* Return non-zero if SEQ contains only ASCII characters, perhaps with
+   a meta bit.  */
+static int
+ascii_sequence_p (seq)
+     Lisp_Object seq;
+{
+  Lisp_Object i;
+  int len = XINT (Flength (seq));
+  
+  for (XFASTINT (i) = 0; XFASTINT (i) < len; XFASTINT (i)++)
+    {
+      Lisp_Object elt = Faref (seq, i);
+
+      if (XTYPE (elt) != Lisp_Int
+         || (XUINT (elt) & ~CHAR_META) >= 0x80)
+       return 0;
+    }
+
+  return 1;
+}
+
 \f
 /* where-is - finding a command in a set of keymaps.                   */
 
@@ -1159,9 +1437,12 @@ DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0,
 If KEYMAP is nil, search only KEYMAP1.\n\
 If KEYMAP1 is nil, use the current global map.\n\
 \n\
-If optional 4th arg FIRSTONLY is non-nil,\n\
-return a string representing the first key sequence found,\n\
-rather than a list of all possible key sequences.\n\
+If optional 4th arg FIRSTONLY is non-nil, return a string representing\n\
+the first key sequence found, rather than a list of all possible key\n\
+sequences.  If FIRSTONLY is t, avoid key sequences which use non-ASCII\n\
+keys and therefore may not be usable on ASCII terminals.  If FIRSTONLY\n\
+is the symbol `non-ascii', return the first binding found, no matter\n\
+what its components.\n\
 \n\
 If optional 5th arg NOINDIRECT is non-nil, don't follow indirections\n\
 to other keymaps or slots.  This makes it possible to search for an\n\
@@ -1177,19 +1458,23 @@ indirect definition itself.")
     global_keymap = current_global_map;
 
   if (!NILP (local_keymap))
-    maps = nconc2 (Faccessible_keymaps (get_keymap (local_keymap)),
-                  Faccessible_keymaps (get_keymap (global_keymap)));
+    maps = nconc2 (Faccessible_keymaps (get_keymap (local_keymap), Qnil),
+                  Faccessible_keymaps (get_keymap (global_keymap), Qnil));
   else
-    maps = Faccessible_keymaps (get_keymap (global_keymap));
+    maps = Faccessible_keymaps (get_keymap (global_keymap), Qnil);
 
   found = Qnil;
 
   for (; !NILP (maps); maps = Fcdr (maps))
     {
-      register this = Fcar (Fcar (maps)); /* Key sequence to reach map */
-      register map = Fcdr (Fcar (maps)); /* The map that it reaches */
-      register dense_alist;
-      register int i = 0;
+      /* Key sequence to reach map */
+      register Lisp_Object this = Fcar (Fcar (maps));
+
+      /* The map that it reaches */
+      register Lisp_Object map  = Fcdr (Fcar (maps));
+
+      /* If Fcar (map) is a VECTOR, the current element within that vector.  */
+      int i = 0;
 
       /* In order to fold [META-PREFIX-CHAR CHAR] sequences into
         [M-CHAR] sequences, check if last character of the sequence
@@ -1197,54 +1482,57 @@ indirect definition itself.")
       Lisp_Object last = make_number (XINT (Flength (this)) - 1);
       int last_is_meta = (XINT (last) >= 0
                          && EQ (Faref (this, last), meta_prefix_char));
-        
-      /* Skip the 'keymap element of the list.  */
-      map = Fcdr (map);
-
-      /* If the keymap is sparse, map traverses the alist to the end.
 
-        If the keymap is dense, we set map to the vector and
-        dense_alist to the assoc-list portion of the keymap.  When we
-        are finished dealing with the vector portion, we set map to
-        dense_alist, and handle the rest like a sparse keymap.  */
-      if (XTYPE (XCONS (map)->car) == Lisp_Vector)
-       {
-         dense_alist = XCONS (map)->cdr;
-         map = XCONS (map)->car;
-       }
+      QUIT;
 
-      while (1)
+      while (CONSP (map))
        {
-         register Lisp_Object key, binding, sequence;
+         /* Because the code we want to run on each binding is rather
+            large, we don't want to have two separate loop bodies for
+            sparse keymap bindings and tables; we want to iterate one
+            loop body over both keymap and vector bindings.
+
+            For this reason, if Fcar (map) is a vector, we don't
+            advance map to the next element until i indicates that we
+            have finished off the vector.  */
          
+         Lisp_Object elt = XCONS (map)->car;
+         Lisp_Object key, binding, sequence;
+
          QUIT;
-         if (XTYPE (map) == Lisp_Vector)
+
+         /* Set key and binding to the current key and binding, and
+            advance map and i to the next binding.  */
+         if (XTYPE (elt) == Lisp_Vector)
            {
              /* In a vector, look at each element.  */
-             binding = XVECTOR (map)->contents[i];
+             binding = XVECTOR (elt)->contents[i];
              XFASTINT (key) = i;
              i++;
 
-             /* If we've just finished scanning a vector, switch map to
-                the assoc-list at the end of the vector.  */
-             if (i >= DENSE_TABLE_SIZE)
-               map = dense_alist;
-           }
-         else if (CONSP (map))
-           {
-             /* In an alist, ignore elements that aren't conses.  */
-             if (! CONSP (XCONS (map)->car))
+             /* If we've just finished scanning a vector, advance map
+                to the next element, and reset i in anticipation of the
+                next vector we may find.  */
+             if (i >= XVECTOR (elt)->size)
                {
-                 /* Ignore other elements.  */
-                 map = Fcdr (map);
-                 continue;
+                 map = XCONS (map)->cdr;
+                 i = 0;
                }
-             binding = Fcdr (Fcar (map));
+           }
+         else if (CONSP (elt))
+           {
              key = Fcar (Fcar (map));
-             map = Fcdr (map);
+             binding = Fcdr (Fcar (map));
+
+             map = XCONS (map)->cdr;
            }
          else
-           break;
+           /* We want to ignore keymap elements that are neither
+              vectors nor conses.  */
+           {
+             map = XCONS (map)->cdr;
+             continue;
+           }
 
          /* Search through indirections unless that's not wanted.  */
          if (NILP (noindirect))
@@ -1269,7 +1557,7 @@ indirect definition itself.")
          if (XTYPE (key) == Lisp_Int && last_is_meta)
            {
              sequence = Fcopy_sequence (this);
-             Faset (sequence, last, make_number (XINT (key) | 0200));
+             Faset (sequence, last, make_number (XINT (key) | meta_modifier));
            }
          else
            sequence = append_key (this, key);
@@ -1285,7 +1573,7 @@ indirect definition itself.")
             means undefined.  */
          if (!NILP (local_keymap))
            {
-             binding = Flookup_key (local_keymap, sequence);
+             binding = Flookup_key (local_keymap, sequence, Qnil);
              if (!NILP (binding) && XTYPE (binding) != Lisp_Int)
                {
                  if (XTYPE (definition) == Lisp_Cons)
@@ -1302,13 +1590,28 @@ indirect definition itself.")
            }
 
          /* It is a true unshadowed match.  Record it.  */
+         found = Fcons (sequence, found);
 
-         if (!NILP (firstonly))
+         /* If firstonly is Qnon_ascii, then we can return the first
+            binding we find.  If firstonly is not Qnon_ascii but not
+            nil, then we should return the first ascii-only binding
+            we find.  */
+         if (EQ (firstonly, Qnon_ascii))
+           return sequence;
+         else if (! NILP (firstonly) && ascii_sequence_p (sequence))
            return sequence;
-         found = Fcons (sequence, found);
        }
     }
-  return Fnreverse (found);
+
+  found = Fnreverse (found);
+
+  /* firstonly may have been t, but we may have gone all the way through
+     the keymaps without finding an all-ASCII key sequence.  So just
+     return the best we could find.  */
+  if (! NILP (firstonly))
+    return Fcar (found);
+    
+  return found;
 }
 
 /* Return a string listing the keys and buttons that run DEFINITION.  */
@@ -1347,65 +1650,127 @@ Argument is a command definition, usually a symbol with a function definition.")
 \f
 /* describe-bindings - summarizing all the bindings in a set of keymaps.  */
 
-DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 0, "",
+DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 1, "",
   "Show a list of all defined keys, and their definitions.\n\
-The list is put in a buffer, which is displayed.")
-  ()
+The list is put in a buffer, which is displayed.\n\
+An optional argument PREFIX, if non-nil, should be a key sequence;\n\
+then we display only bindings that start with that prefix.")
+  (prefix)
+     Lisp_Object prefix;
 {
   register Lisp_Object thisbuf;
   XSET (thisbuf, Lisp_Buffer, current_buffer);
   internal_with_output_to_temp_buffer ("*Help*",
                                       describe_buffer_bindings,
-                                      thisbuf);
+                                      Fcons (thisbuf, prefix));
   return Qnil;
 }
 
+/* ARG is (BUFFER . PREFIX).  */
+
 static Lisp_Object
-describe_buffer_bindings (descbuf)
-     Lisp_Object descbuf;
+describe_buffer_bindings (arg)
+     Lisp_Object arg;
 {
+  Lisp_Object descbuf, prefix, shadow;
   register Lisp_Object start1, start2;
 
-  char *heading
-    = "key                     binding\n---                     -------\n";
+  char *alternate_heading
+    = "\
+Alternate Characters (use anywhere the nominal character is listed):\n\
+nominal         alternate\n\
+-------         ---------\n";
+
+  descbuf = XCONS (arg)->car;
+  prefix = XCONS (arg)->cdr;
+  shadow = Qnil;
 
   Fset_buffer (Vstandard_output);
 
+  /* Report on alternates for keys.  */
+  if (XTYPE (Vkeyboard_translate_table) == Lisp_String)
+    {
+      int c;
+      unsigned char *translate = XSTRING (Vkeyboard_translate_table)->data;
+      int translate_len = XSTRING (Vkeyboard_translate_table)->size;
+
+      for (c = 0; c < translate_len; c++)
+       if (translate[c] != c)
+         {
+           char buf[20];
+           char *bufend;
+
+           if (alternate_heading)
+             {
+               insert_string (alternate_heading);
+               alternate_heading = 0;
+             }
+
+           bufend = push_key_description (translate[c], buf);
+           insert (buf, bufend - buf);
+           Findent_to (make_number (16), make_number (1));
+           bufend = push_key_description (c, buf);
+           insert (buf, bufend - buf);
+
+           insert ("\n", 1);
+         }
+
+      insert ("\n", 1);
+    }
+
   {
     int i, nmaps;
     Lisp_Object *modes, *maps;
 
+    /* Temporarily switch to descbuf, so that we can get that buffer's
+       minor modes correctly.  */
+    Fset_buffer (descbuf);
     nmaps = current_minor_maps (&modes, &maps);
+    Fset_buffer (Vstandard_output);
+
+    /* Print the minor mode maps.  */
     for (i = 0; i < nmaps; i++)
       {
+       /* Tht title for a minor mode keymap
+          is constructed at run time.
+          We let describe_map_tree do the actual insertion
+          because it takes care of other features when doing so.  */
+       char *title = (char *) alloca (40 + XSYMBOL (modes[i])->name->size);
+       char *p = title;
+
        if (XTYPE (modes[i]) == Lisp_Symbol)
          {
-           insert_char ('`');
-           insert_string (XSYMBOL (modes[i])->name->data);
-           insert_char ('\'');
+           *p++ = '`';
+           bcopy (XSYMBOL (modes[i])->name->data, p,
+                  XSYMBOL (modes[i])->name->size);
+           p += XSYMBOL (modes[i])->name->size;
+           *p++ = '\'';
          }
        else
-         insert_string ("Strangely Named");
-       insert_string (" Minor Mode Bindings:\n");
-       insert_string (heading);
-       describe_map_tree (maps[i], 0, Qnil);
-       insert_char ('\n');
+         {
+           bcopy ("Strangely Named", p, sizeof ("Strangely Named"));
+           p += sizeof ("Strangely Named");
+         }
+       bcopy (" Minor Mode Bindings", p, sizeof (" Minor Mode Bindings"));
+       p += sizeof (" Minor Mode Bindings");
+       *p = 0;
+
+       describe_map_tree (maps[i], 0, shadow, prefix, title);
+       shadow = Fcons (maps[i], shadow);
       }
   }
 
+  /* Print the (major mode) local map.  */
   start1 = XBUFFER (descbuf)->keymap;
   if (!NILP (start1))
     {
-      insert_string ("Local Bindings:\n");
-      insert_string (heading);
-      describe_map_tree (start1, 0, Qnil);
-      insert_string ("\n");
+      describe_map_tree (start1, 0, shadow, prefix,
+                        "Major Mode Bindings");
+      shadow = Fcons (start1, shadow);
     }
 
-  insert_string ("Global Bindings:\n");
-  insert_string (heading);
-
-  describe_map_tree (current_global_map, 0, XBUFFER (descbuf)->keymap);
+  describe_map_tree (current_global_map, 0, shadow, prefix,
+                    "Global Bindings");
 
   Fset_buffer (descbuf);
   return Qnil;
@@ -1415,57 +1780,95 @@ describe_buffer_bindings (descbuf)
     followed by those of all maps reachable through STARTMAP.
    If PARTIAL is nonzero, omit certain "uninteresting" commands
     (such as `undefined').
-   If SHADOW is non-nil, it is another map;
-    don't mention keys which would be shadowed by it.  */
+   If SHADOW is non-nil, it is a list of maps;
+    don't mention keys which would be shadowed by any of them.
+   PREFIX, if non-nil, says mention only keys that start with PREFIX.
+   TITLE, if not 0, is a string to insert at the beginning.
+   TITLE should not end with a colon or a newline; we supply that.  */
 
 void
-describe_map_tree (startmap, partial, shadow)
-     Lisp_Object startmap, shadow;
+describe_map_tree (startmap, partial, shadow, prefix, title)
+     Lisp_Object startmap, shadow, prefix;
      int partial;
+     char *title;
 {
-  register Lisp_Object elt, sh;
   Lisp_Object maps;
   struct gcpro gcpro1;
+  int something = 0;
+  char *key_heading
+    = "\
+key             binding\n\
+---             -------\n";
 
-  maps = Faccessible_keymaps (startmap);
+  maps = Faccessible_keymaps (startmap, prefix);
   GCPRO1 (maps);
 
+  if (!NILP (maps))
+    {
+      if (title)
+       {
+         insert_string (title);
+         if (!NILP (prefix))
+           {
+             insert_string (" Starting With ");
+             insert1 (Fkey_description (prefix));
+           }
+         insert_string (":\n");
+       }
+      insert_string (key_heading);
+      something = 1;
+    }
+
   for (; !NILP (maps); maps = Fcdr (maps))
     {
+      register Lisp_Object elt, prefix, sub_shadows, tail;
+
       elt = Fcar (maps);
-      sh = Fcar (elt);
-
-      /* If there is no shadow keymap given, don't shadow.  */
-      if (NILP (shadow))
-       sh = Qnil;
-
-      /* If the sequence by which we reach this keymap is zero-length,
-        then the shadow map for this keymap is just SHADOW.  */
-      else if ((XTYPE (sh) == Lisp_String
-               && XSTRING (sh)->size == 0)
-              || (XTYPE (sh) == Lisp_Vector
-                  && XVECTOR (sh)->size == 0))
-       sh = shadow;
-
-      /* If the sequence by which we reach this keymap actually has
-        some elements, then the sequence's definition in SHADOW is
-        what we should use.  */
-      else
+      prefix = Fcar (elt);
+
+      sub_shadows = Qnil;
+
+      for (tail = shadow; CONSP (tail); tail = XCONS (tail)->cdr)
        {
-         sh = Flookup_key (shadow, Fcar (elt));
-         if (XTYPE (sh) == Lisp_Int)
-           sh = Qnil;
+         Lisp_Object shmap;
+
+         shmap = XCONS (tail)->car;
+
+         /* If the sequence by which we reach this keymap is zero-length,
+            then the shadow map for this keymap is just SHADOW.  */
+         if ((XTYPE (prefix) == Lisp_String
+              && XSTRING (prefix)->size == 0)
+             || (XTYPE (prefix) == Lisp_Vector
+                 && XVECTOR (prefix)->size == 0))
+           ;
+         /* If the sequence by which we reach this keymap actually has
+            some elements, then the sequence's definition in SHADOW is
+            what we should use.  */
+         else
+           {
+             shmap = Flookup_key (shadow, Fcar (elt), Qt);
+             if (XTYPE (shmap) == Lisp_Int)
+               shmap = Qnil;
+           }
+
+         /* If shmap is not nil and not a keymap,
+            it completely shadows this map, so don't
+            describe this map at all.  */
+         if (!NILP (shmap) && NILP (Fkeymapp (shmap)))
+           goto skip;
+
+         if (!NILP (shmap))
+           sub_shadows = Fcons (shmap, sub_shadows);
        }
 
-      /* If sh is null (meaning that the current map is not shadowed),
-        or a keymap (meaning that bindings from the current map might
-        show through), describe the map.  Otherwise, sh is a command
-        that completely shadows the current map, and we shouldn't
-        bother.  */
-      if (NILP (sh) || !NILP (Fkeymapp (sh)))
-       describe_map (Fcdr (elt), Fcar (elt), partial, sh);
+      describe_map (Fcdr (elt), Fcar (elt), partial, sub_shadows);
+
+    skip: ;
     }
 
+  if (something)
+    insert_string ("\n");
+
   UNGCPRO;
 }
 
@@ -1505,41 +1908,49 @@ describe_map (map, keys, partial, shadow)
 {
   register Lisp_Object keysdesc;
 
-  if (!NILP (keys) && Flength (keys) > 0)
-    keysdesc = concat2 (Fkey_description (keys),
-                       build_string (" "));
+  if (!NILP (keys) && XFASTINT (Flength (keys)) > 0)
+    {
+      Lisp_Object tem;
+      /* Call Fkey_description first, to avoid GC bug for the other string.  */
+      tem = Fkey_description (keys);
+      keysdesc = concat2 (tem, build_string (" "));
+    }
   else
     keysdesc = Qnil;
 
-  /* Skip the 'keymap element of the list.  */
-  map = Fcdr (map);
+  describe_map_2 (map, keysdesc, describe_command, partial, shadow);
+}
 
-  /* If this is a dense keymap, take care of the table.  */
-  if (CONSP (map)
-      && XTYPE (XCONS (map)->car) == Lisp_Vector)
+/* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map.
+   Returns the first non-nil binding found in any of those maps.  */
+
+static Lisp_Object
+shadow_lookup (shadow, key, flag)
+     Lisp_Object shadow, key, flag;
+{
+  Lisp_Object tail, value;
+
+  for (tail = shadow; CONSP (tail); tail = XCONS (tail)->cdr)
     {
-      describe_vector (XCONS (map)->car, keysdesc, describe_command,
-                      partial, shadow);
-      map = XCONS (map)->cdr;
+      value = Flookup_key (XCONS (tail)->car, key, flag);
+      if (!NILP (value))
+       return value;
     }
-
-  /* Now map is an alist.  */
-  describe_alist (map, keysdesc, describe_command, partial, shadow);
+  return Qnil;
 }
 
-/* Insert a description of ALIST into the current buffer. 
-   Note that ALIST is just a plain association list, not a keymap.  */
+/* Insert a description of KEYMAP into the current buffer.  */
 
 static void
-describe_alist (alist, elt_prefix, elt_describer, partial, shadow)
-     register Lisp_Object alist;
+describe_map_2 (keymap, elt_prefix, elt_describer, partial, shadow)
+     register Lisp_Object keymap;
      Lisp_Object elt_prefix;
      int (*elt_describer) ();
      int partial;
      Lisp_Object shadow;
 {
-  Lisp_Object this;
-  Lisp_Object tem1, tem2 = Qnil;
+  Lisp_Object tail, definition, event;
+  Lisp_Object tem;
   Lisp_Object suppress;
   Lisp_Object kludge;
   int first = 1;
@@ -1549,56 +1960,64 @@ describe_alist (alist, elt_prefix, elt_describer, partial, shadow)
     suppress = intern ("suppress-keymap");
 
   /* This vector gets used to present single keys to Flookup_key.  Since
-     that is done once per alist element, we don't want to cons up a
+     that is done once per keymap element, we don't want to cons up a
      fresh vector every time.  */
   kludge = Fmake_vector (make_number (1), Qnil);
+  definition = Qnil;
 
-  GCPRO3 (elt_prefix, tem2, kludge);
+  GCPRO3 (elt_prefix, definition, kludge);
 
-  for (; CONSP (alist); alist = Fcdr (alist))
+  for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = Fcdr (tail))
     {
       QUIT;
-      tem1 = Fcar_safe (Fcar (alist));
-      tem2 = get_keyelt (Fcdr_safe (Fcar (alist)));
 
-      /* Don't show undefined commands or suppressed commands.  */
-      if (NILP (tem2)) continue;
-      if (XTYPE (tem2) == Lisp_Symbol && partial)
+      if (XTYPE (XCONS (tail)->car) == Lisp_Vector)
+       describe_vector (XCONS (tail)->car,
+                        elt_prefix, elt_describer, partial, shadow);
+      else
        {
-         this = Fget (tem2, suppress);
-         if (!NILP (this))
-           continue;
-       }
+         event = Fcar_safe (Fcar (tail));
+         definition = get_keyelt (Fcdr_safe (Fcar (tail)));
 
-      /* Don't show a command that isn't really visible
-        because a local definition of the same key shadows it.  */
+         /* Don't show undefined commands or suppressed commands.  */
+         if (NILP (definition)) continue;
+         if (XTYPE (definition) == Lisp_Symbol && partial)
+           {
+             tem = Fget (definition, suppress);
+             if (!NILP (tem))
+               continue;
+           }
 
-      if (!NILP (shadow))
-       {
-         Lisp_Object tem;
+         /* Don't show a command that isn't really visible
+            because a local definition of the same key shadows it.  */
 
-         XVECTOR (kludge)->contents[0] = tem1;
-         tem = Flookup_key (shadow, kludge);
-         if (!NILP (tem)) continue;
-       }
+         XVECTOR (kludge)->contents[0] = event;
+         if (!NILP (shadow))
+           {
+             tem = shadow_lookup (shadow, kludge, Qt);
+             if (!NILP (tem)) continue;
+           }
 
-      if (first)
-       {
-         insert ("\n", 1);
-         first = 0;
-       }
+         tem = Flookup_key (keymap, kludge, Qt);
+         if (! EQ (tem, definition)) continue;
 
-      if (!NILP (elt_prefix))
-       insert1 (elt_prefix);
+         if (first)
+           {
+             insert ("\n", 1);
+             first = 0;
+           }
 
-      /* THIS gets the string to describe the character TEM1.  */
-      this = Fsingle_key_description (tem1);
-      insert1 (this);
+         if (!NILP (elt_prefix))
+           insert1 (elt_prefix);
 
-      /* Print a description of the definition of this character.
-        elt_describer will take care of spacing out far enough
-        for alignment purposes.  */
-      (*elt_describer) (tem2);
+         /* THIS gets the string to describe the character EVENT.  */
+         insert1 (Fsingle_key_description (event));
+
+         /* Print a description of the definition of this character.
+            elt_describer will take care of spacing out far enough
+            for alignment purposes.  */
+         (*elt_describer) (definition);
+       }
     }
 
   UNGCPRO;
@@ -1608,17 +2027,24 @@ static int
 describe_vector_princ (elt)
      Lisp_Object elt;
 {
+  Findent_to (make_number (16), make_number (1));
   Fprinc (elt, Qnil);
+  Fterpri (Qnil);
 }
 
 DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 1, 0,
-  "Print on `standard-output' a description of contents of VECTOR.\n\
+  "Insert a description of contents of VECTOR.\n\
 This is text showing the elements of vector matched against indices.")
   (vector)
      Lisp_Object vector;
 {
+  int count = specpdl_ptr - specpdl;
+
+  specbind (Qstandard_output, Fcurrent_buffer ());
   CHECK_VECTOR (vector, 0);
-  describe_vector (vector, Qnil, describe_vector_princ, 0, Qnil, Qnil);
+  describe_vector (vector, Qnil, describe_vector_princ, 0, Qnil);
+
+  return unbind_to (count, Qnil);
 }
 
 describe_vector (vector, elt_prefix, elt_describer, partial, shadow)
@@ -1648,7 +2074,7 @@ describe_vector (vector, elt_prefix, elt_describer, partial, shadow)
   if (partial)
     suppress = intern ("suppress-keymap");
 
-  for (i = 0; i < DENSE_TABLE_SIZE; i++)
+  for (i = 0; i < XVECTOR (vector)->size; i++)
     {
       QUIT;
       tem1 = get_keyelt (XVECTOR (vector)->contents[i]);
@@ -1670,7 +2096,7 @@ describe_vector (vector, elt_prefix, elt_describer, partial, shadow)
          Lisp_Object tem;
          
          XVECTOR (kludge)->contents[0] = make_number (i);
-         tem = Flookup_key (shadow, kludge);
+         tem = shadow_lookup (shadow, kludge, Qt);
 
          if (!NILP (tem)) continue;
        }
@@ -1693,7 +2119,7 @@ describe_vector (vector, elt_prefix, elt_describer, partial, shadow)
       insert1 (this);
 
       /* Find all consecutive characters that have the same definition.  */
-      while (i + 1 < DENSE_TABLE_SIZE
+      while (i + 1 < XVECTOR (vector)->size
             && (tem2 = get_keyelt (XVECTOR (vector)->contents[i+1]),
                 EQ (tem2, tem1)))
        i++;
@@ -1767,32 +2193,33 @@ syms_of_keymap ()
    Each one is the value of a Lisp variable, and is also
    pointed to by a C variable */
 
-  global_map = Fmake_keymap ();
+  global_map = Fcons (Qkeymap,
+                     Fcons (Fmake_vector (make_number (0400), Qnil), Qnil));
   Fset (intern ("global-map"), global_map);
 
-  meta_map = Fmake_keymap ();
+  meta_map = Fmake_keymap (Qnil);
   Fset (intern ("esc-map"), meta_map);
   Ffset (intern ("ESC-prefix"), meta_map);
 
-  control_x_map = Fmake_keymap ();
+  control_x_map = Fmake_keymap (Qnil);
   Fset (intern ("ctl-x-map"), control_x_map);
   Ffset (intern ("Control-X-prefix"), control_x_map);
 
   DEFVAR_LISP ("minibuffer-local-map", &Vminibuffer_local_map,
     "Default keymap to use when reading from the minibuffer.");
-  Vminibuffer_local_map = Fmake_sparse_keymap ();
+  Vminibuffer_local_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("minibuffer-local-ns-map", &Vminibuffer_local_ns_map,
     "Local keymap for the minibuffer when spaces are not allowed.");
-  Vminibuffer_local_ns_map = Fmake_sparse_keymap ();
+  Vminibuffer_local_ns_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("minibuffer-local-completion-map", &Vminibuffer_local_completion_map,
     "Local keymap for minibuffer input with completion.");
-  Vminibuffer_local_completion_map = Fmake_sparse_keymap ();
+  Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map,
     "Local keymap for minibuffer input with completion, for exact match.");
-  Vminibuffer_local_must_match_map = Fmake_sparse_keymap ();
+  Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil);
 
   current_global_map = global_map;
 
@@ -1812,15 +2239,15 @@ terminals at any point in a key sequence.\n\
 The read-key-sequence function replaces subsequences bound by\n\
 function-key-map with their bindings.  When the current local and global\n\
 keymaps have no binding for the current key sequence but\n\
-function-key-map binds a suffix of the sequence to a vector,\n\
+function-key-map binds a suffix of the sequence to a vector or string,\n\
 read-key-sequence replaces the matching suffix with its binding, and\n\
 continues with the new sequence.\n\
 \n\
-For example, suppose function-key-map binds `ESC O P' to [pf1].\n\
-Typing `ESC O P' to read-key-sequence would return [pf1].  Typing\n\
-`C-x ESC O P' would return [?\C-x pf1].  If [pf1] were a prefix\n\
-key, typing `ESC O P x' would return [pf1 x].");
-  Vfunction_key_map = Fmake_sparse_keymap ();
+For example, suppose function-key-map binds `ESC O P' to [f1].\n\
+Typing `ESC O P' to read-key-sequence would return [f1].  Typing\n\
+`C-x ESC O P' would return [?\\C-x f1].  If [f1] were a prefix\n\
+key, typing `ESC O P x' would return [f1 x].");
+  Vfunction_key_map = Fmake_sparse_keymap (Qnil);
 
   Qsingle_key_description = intern ("single-key-description");
   staticpro (&Qsingle_key_description);
@@ -1831,6 +2258,9 @@ key, typing `ESC O P x' would return [pf1 x].");
   Qkeymapp = intern ("keymapp");
   staticpro (&Qkeymapp);
 
+  Qnon_ascii = intern ("non-ascii");
+  staticpro (&Qnon_ascii);
+
   defsubr (&Skeymapp);
   defsubr (&Smake_keymap);
   defsubr (&Smake_sparse_keymap);