Include <config.h> instead of "config.h".
[bpt/emacs.git] / src / keymap.c
index 096a6ca..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,7 +18,7 @@ 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"
@@ -75,12 +75,13 @@ Lisp_Object Vfunction_key_map;
 
 Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii;
 
-/* A char over 0200 in a key sequence
-   is equivalent to prefixing with this character.  */
-
+/* 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 ();
@@ -90,7 +91,7 @@ static void describe_map_2 ();
 
 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\".\n\n\
@@ -170,10 +171,11 @@ synkey (frommap, fromchar, tomap, tochar)
 DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0,
   "Return t if ARG is a keymap.\n\
 \n\
-A keymap is a 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;
 {
@@ -221,8 +223,8 @@ get_keymap_1 (object, error, autoload)
        {
          struct gcpro gcpro1, gcpro2;
 
-         GCPRO2 (tem, object)
-           do_autoload (tem, object);
+         GCPRO2 (tem, object);
+         do_autoload (tem, object);
          UNGCPRO;
 
          goto autoload_retry;
@@ -254,14 +256,20 @@ get_keymap (object)
    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.  */
+   If T_OK is zero, bindings for Qt are not treated specially.
+
+   If NOINHERIT, don't accept a subkeymap found in an inherited keymap.  */
 
 Lisp_Object
-access_keymap (map, idx, t_ok)
+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.  */
@@ -271,6 +279,10 @@ access_keymap (map, idx, t_ok)
      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 tail;
@@ -282,19 +294,35 @@ access_keymap (map, idx, t_ok)
 
        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))
-             return XCONS (binding)->cdr;
+             {
+               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 (XVECTOR (binding)->size == DENSE_TABLE_SIZE
-               && XTYPE (idx) == Lisp_Int
+           if (XTYPE (idx) == Lisp_Int
                && XINT (idx) >= 0
-               && XINT (idx) < DENSE_TABLE_SIZE)
-             return XVECTOR (binding)->contents[XINT (idx)];
+               && 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;
          }
 
@@ -326,7 +354,7 @@ get_keyelt (object)
       map = get_keymap_1 (Fcar_safe (object), 0, 0);
       tem = Fkeymapp (map);
       if (!NILP (tem))
-       object = access_keymap (map, Fcdr (object), 0);
+       object = access_keymap (map, Fcdr (object), 0, 0);
       
       /* If the keymap contents looks like (STRING . DEFN),
         use DEFN.
@@ -368,7 +396,10 @@ store_in_keymap (keymap, idx, def)
      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.  */
   {
@@ -389,10 +420,8 @@ store_in_keymap (keymap, idx, def)
        switch (XTYPE (elt))
          {
          case Lisp_Vector:
-           if (XVECTOR (elt)->size != DENSE_TABLE_SIZE)
-             break;
            if (XTYPE (idx) == Lisp_Int
-               && XINT (idx) >= 0 && XINT (idx) < DENSE_TABLE_SIZE)
+               && XINT (idx) >= 0 && XINT (idx) < XVECTOR (elt)->size)
              {
                XVECTOR (elt)->contents[XFASTINT (idx)] = def;
                return def;
@@ -450,17 +479,16 @@ is not copied.")
     {
       Lisp_Object elt = XCONS (tail)->car;
 
-      if (XTYPE (elt) == Lisp_Vector
-         && XVECTOR (elt)->size == DENSE_TABLE_SIZE)
+      if (XTYPE (elt) == Lisp_Vector)
        {
          int i;
 
          elt = Fcopy_sequence (elt);
          XCONS (tail)->car = elt;
 
-         for (i = 0; i < DENSE_TABLE_SIZE; i++)
+         for (i = 0; i < XVECTOR (elt)->size; i++)
            if (XTYPE (XVECTOR (elt)->contents[i]) != Lisp_Symbol
-               && Fkeymapp (XVECTOR (elt)->contents[i]))
+               && ! NILP (Fkeymapp (XVECTOR (elt)->contents[i])))
              XVECTOR (elt)->contents[i] =
                Fcopy_keymap (XVECTOR (elt)->contents[i]);
        }
@@ -548,13 +576,11 @@ the front of KEYMAP.")
       if (idx == length)
        RETURN_UNGCPRO (store_in_keymap (keymap, c, def));
 
-      cmd = get_keyelt (access_keymap (keymap, c, 0));
+      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 (Qnil);
-         store_in_keymap (keymap, c, cmd);
-       }
+       cmd = define_as_prefix (keymap, c);
 
       keymap = get_keymap_1 (cmd, 0, 1);
       if (NILP (keymap))
@@ -636,7 +662,7 @@ recognize the default bindings, just as `read-key-sequence' does.")
          idx++;
        }
 
-      cmd = get_keyelt (access_keymap (keymap, c, t_ok));
+      cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0));
       if (idx == length)
        return cmd;
 
@@ -648,6 +674,42 @@ recognize the default bindings, just as `read-key-sequence' does.")
     }
 }
 
+/* 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
@@ -730,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++;
       }
 
@@ -850,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)
@@ -868,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)
@@ -982,15 +1044,21 @@ 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;
+
+  if (!NILP (prefix))
+    prefixlen = XINT (Flength (prefix));
 
   maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil),
                       get_keymap (startmap)),
@@ -1024,7 +1092,7 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
              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;
@@ -1069,7 +1137,7 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
          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);
@@ -1080,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
@@ -1095,8 +1163,8 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                          /* 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,
@@ -1108,7 +1176,35 @@ so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
        }
     }
 
-  return maps;
+  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 Fnreverse (good_maps);
 }
 
 Lisp_Object Qsingle_key_description, Qkey_description;
@@ -1362,10 +1458,10 @@ 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;
 
@@ -1417,7 +1513,7 @@ indirect definition itself.")
              /* 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 >= DENSE_TABLE_SIZE)
+             if (i >= XVECTOR (elt)->size)
                {
                  map = XCONS (map)->cdr;
                  i = 0;
@@ -1554,35 +1650,41 @@ 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 *key_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.  */
@@ -1626,37 +1728,49 @@ nominal         alternate\n\
     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 (key_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 (key_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");
-  if (NILP (start1))
-    insert_string (key_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;
@@ -1666,57 +1780,95 @@ nominal         alternate\n\
     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), Qt);
-         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;
 }
 
@@ -1769,6 +1921,24 @@ describe_map (map, keys, partial, shadow)
   describe_map_2 (map, keysdesc, describe_command, partial, shadow);
 }
 
+/* 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)
+    {
+      value = Flookup_key (XCONS (tail)->car, key, flag);
+      if (!NILP (value))
+       return value;
+    }
+  return Qnil;
+}
+
 /* Insert a description of KEYMAP into the current buffer.  */
 
 static void
@@ -1779,8 +1949,8 @@ describe_map_2 (keymap, elt_prefix, elt_describer, partial, shadow)
      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;
@@ -1793,42 +1963,44 @@ describe_map_2 (keymap, elt_prefix, elt_describer, partial, shadow)
      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 (keymap); keymap = Fcdr (keymap))
+  for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = Fcdr (tail))
     {
       QUIT;
 
-      if (XTYPE (XCONS (keymap)->car) == Lisp_Vector)
-       describe_vector (XCONS (keymap)->car,
+      if (XTYPE (XCONS (tail)->car) == Lisp_Vector)
+       describe_vector (XCONS (tail)->car,
                         elt_prefix, elt_describer, partial, shadow);
       else
        {
-         tem1 =             Fcar_safe (Fcar (keymap));
-         tem2 = get_keyelt (Fcdr_safe (Fcar (keymap)));
+         event = Fcar_safe (Fcar (tail));
+         definition = get_keyelt (Fcdr_safe (Fcar (tail)));
 
          /* Don't show undefined commands or suppressed commands.  */
-         if (NILP (tem2)) continue;
-         if (XTYPE (tem2) == Lisp_Symbol && partial)
+         if (NILP (definition)) continue;
+         if (XTYPE (definition) == Lisp_Symbol && partial)
            {
-             this = Fget (tem2, suppress);
-             if (!NILP (this))
+             tem = Fget (definition, suppress);
+             if (!NILP (tem))
                continue;
            }
 
          /* Don't show a command that isn't really visible
             because a local definition of the same key shadows it.  */
 
+         XVECTOR (kludge)->contents[0] = event;
          if (!NILP (shadow))
            {
-             Lisp_Object tem;
-
-             XVECTOR (kludge)->contents[0] = tem1;
-             tem = Flookup_key (shadow, kludge, Qt);
+             tem = shadow_lookup (shadow, kludge, Qt);
              if (!NILP (tem)) continue;
            }
 
+         tem = Flookup_key (keymap, kludge, Qt);
+         if (! EQ (tem, definition)) continue;
+
          if (first)
            {
              insert ("\n", 1);
@@ -1838,14 +2010,13 @@ describe_map_2 (keymap, elt_prefix, elt_describer, partial, shadow)
          if (!NILP (elt_prefix))
            insert1 (elt_prefix);
 
-         /* THIS gets the string to describe the character TEM1.  */
-         this = Fsingle_key_description (tem1);
-         insert1 (this);
+         /* 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) (tem2);
+         (*elt_describer) (definition);
        }
     }
 
@@ -1856,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);
+
+  return unbind_to (count, Qnil);
 }
 
 describe_vector (vector, elt_prefix, elt_describer, partial, shadow)
@@ -1896,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]);
@@ -1918,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, Qt);
+         tem = shadow_lookup (shadow, kludge, Qt);
 
          if (!NILP (tem)) continue;
        }
@@ -1941,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++;
@@ -2015,7 +2193,8 @@ 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 (Qnil);
+  global_map = Fcons (Qkeymap,
+                     Fcons (Fmake_vector (make_number (0400), Qnil), Qnil));
   Fset (intern ("global-map"), global_map);
 
   meta_map = Fmake_keymap (Qnil);
@@ -2060,14 +2239,14 @@ 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].");
+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");