]> code.delx.au - gnu-emacs/blobdiff - src/keymap.c
Merge from emacs--devo--0
[gnu-emacs] / src / keymap.c
index 45bcba9a5fc99b1a9ef85d3e63b1a795f07e381b..95534f9efa636b4fda33fea2dae0577c91e2d65d 100644 (file)
@@ -1,7 +1,7 @@
 /* Manipulation of keymaps
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -23,9 +23,13 @@ Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 #include <stdio.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
+#include "character.h"
 #include "charset.h"
 #include "keyboard.h"
 #include "termhooks.h"
@@ -426,11 +430,7 @@ Return PARENT.  PARENT should be nil or another keymap.  */)
 
       if (CHAR_TABLE_P (XCAR (list)))
        {
-         Lisp_Object indices[3];
-
-         map_char_table (fix_submap_inheritance, Qnil,
-                         XCAR (list), XCAR (list),
-                         keymap, 0, indices);
+         map_char_table (fix_submap_inheritance, Qnil, XCAR (list), keymap);
        }
     }
 
@@ -570,9 +570,7 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
 
     GCPRO4 (map, tail, idx, t_binding);
 
-    /* If `t_ok' is 2, both `t' and generic-char bindings are accepted.
-       If it is 1, only generic-char bindings are accepted.
-       Otherwise, neither are.  */
+    /* If `t_ok' is 2, both `t' is accepted.  */
     t_ok = t_ok ? 2 : 0;
 
     for (tail = XCDR (map);
@@ -596,24 +594,6 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
 
            if (EQ (key, idx))
              val = XCDR (binding);
-           else if (t_ok
-                    && INTEGERP (idx)
-                    && (XINT (idx) & CHAR_MODIFIER_MASK) == 0
-                    && INTEGERP (key)
-                    && (XINT (key) & CHAR_MODIFIER_MASK) == 0
-                    && !SINGLE_BYTE_CHAR_P (XINT (idx))
-                    && !SINGLE_BYTE_CHAR_P (XINT (key))
-                    && CHAR_VALID_P (XINT (key), 1)
-                    && !CHAR_VALID_P (XINT (key), 0)
-                    && (CHAR_CHARSET (XINT (key))
-                        == CHAR_CHARSET (XINT (idx))))
-             {
-               /* KEY is the generic character of the charset of IDX.
-                  Use KEY's binding if there isn't a binding for IDX
-                  itself.  */
-               t_binding = XCDR (binding);
-               t_ok = 0;
-             }
            else if (t_ok > 1 && EQ (key, Qt))
              {
                t_binding = XCDR (binding);
@@ -725,12 +705,10 @@ map_keymap (map, fun, args, data, autoload)
        }
       else if (CHAR_TABLE_P (binding))
        {
-         Lisp_Object indices[3];
-         map_char_table (map_keymap_char_table_item, Qnil, binding, binding,
+         map_char_table (map_keymap_char_table_item, Qnil, binding,
                          Fcons (make_save_value (fun, 0),
                                 Fcons (make_save_value (data, 0),
-                                       args)),
-                         0, indices);
+                                       args)));
        }
     }
   UNGCPRO;
@@ -747,7 +725,10 @@ map_keymap_call (key, val, fun, dummy)
 DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 3, 0,
        doc: /* Call FUNCTION once for each event binding in KEYMAP.
 FUNCTION is called with two arguments: the event that is bound, and
-the definition it is bound to.
+the definition it is bound to.  If the event is an integer, it may be
+a generic character (see Info node `(elisp)Splitting Characters'), and
+that means that all actual character events belonging to that generic
+character are bound to the definition.
 
 If KEYMAP has a parent, the parent's bindings are included as well.
 This works recursively: if the parent has itself a parent, then the
@@ -882,10 +863,15 @@ store_in_keymap (keymap, idx, def)
   if (!CONSP (keymap) || !EQ (XCAR (keymap), Qkeymap))
     error ("attempt to define a key in a non-keymap");
 
-  /* If idx is a list (some sort of mouse click, perhaps?),
-     the index we want to use is the car of the list, which
-     ought to be a symbol.  */
-  idx = EVENT_HEAD (idx);
+  /* If idx is a cons, and the car part is a character, idx must be of
+     the form (FROM-CHAR . TO-CHAR).  */
+  if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+    CHECK_CHARACTER_CDR (idx);
+  else
+    /* If idx is a list (some sort of mouse click, perhaps?),
+       the index we want to use is the car of the list, which
+       ought to be a symbol.  */
+    idx = EVENT_HEAD (idx);
 
   /* If idx is a symbol, it might have modifiers, which need to
      be put in the canonical order.  */
@@ -922,6 +908,19 @@ store_in_keymap (keymap, idx, def)
                ASET (elt, XFASTINT (idx), def);
                return def;
              }
+           else if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+             {
+               int from = XFASTINT (XCAR (idx));
+               int to = XFASTINT (XCDR (idx));
+
+               if (to >= ASIZE (elt))
+                 to = ASIZE (elt) - 1;
+               for (; from <= to; from++)
+                 ASET (elt, from, def);
+               if (to == XFASTINT (XCDR (idx)))
+                 /* We have defined all keys in IDX.  */
+                 return def;
+             }
            insertion_point = tail;
          }
        else if (CHAR_TABLE_P (elt))
@@ -938,6 +937,11 @@ store_in_keymap (keymap, idx, def)
                       NILP (def) ? Qt : def);
                return def;
              }
+           else if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+             {
+               Fset_char_table_range (elt, idx, NILP (def) ? Qt : def);
+               return def;
+             }
            insertion_point = tail;
          }
        else if (CONSP (elt))
@@ -948,6 +952,19 @@ store_in_keymap (keymap, idx, def)
                XSETCDR (elt, def);
                return def;
              }
+           else if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+             {
+               int from = XFASTINT (XCAR (idx));
+               int to = XFASTINT (XCDR (idx));
+
+               if (from <= XFASTINT (XCAR (elt))
+                   && to >= XFASTINT (XCAR (elt)))
+                 {
+                   XSETCDR (elt, def);
+                   if (from == to)
+                     return def;
+                 }
+             }
          }
        else if (EQ (elt, Qkeymap))
          /* If we find a 'keymap' symbol in the spine of KEYMAP,
@@ -962,9 +979,22 @@ store_in_keymap (keymap, idx, def)
   keymap_end:
     /* We have scanned the entire keymap, and not found a binding for
        IDX.  Let's add one.  */
-    CHECK_IMPURE (insertion_point);
-    XSETCDR (insertion_point,
-            Fcons (Fcons (idx, def), XCDR (insertion_point)));
+    {
+      Lisp_Object elt;
+
+      if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+       {
+         /* IDX specifies a range of characters, and not all of them
+            were handled yet, which means this keymap doesn't have a
+            char-table.  So, we insert a char-table now.  */
+         elt = Fmake_char_table (Qkeymap, Qnil);
+         Fset_char_table_range (elt, idx, NILP (def) ? Qt : def);
+       }
+      else
+       elt = Fcons (idx, def);
+      CHECK_IMPURE (insertion_point);
+      XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point)));
+    }
   }
 
   return def;
@@ -1050,7 +1080,7 @@ static void
 copy_keymap_1 (chartable, idx, elt)
      Lisp_Object chartable, idx, elt;
 {
-  Faset (chartable, idx, copy_keymap_item (elt));
+  Fset_char_table_range (chartable, idx, copy_keymap_item (elt));
 }
 
 DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0,
@@ -1073,9 +1103,8 @@ is not copied.  */)
       Lisp_Object elt = XCAR (keymap);
       if (CHAR_TABLE_P (elt))
        {
-         Lisp_Object indices[3];
          elt = Fcopy_sequence (elt);
-         map_char_table (copy_keymap_1, Qnil, elt, elt, elt, 0, indices);
+         map_char_table (copy_keymap_1, Qnil, elt, elt);
        }
       else if (VECTORP (elt))
        {
@@ -1118,7 +1147,9 @@ DEF is anything that can be a key's definition:
     or another symbol whose function definition is used, etc.),
  a cons (STRING . DEFN), meaning that DEFN is the definition
     (DEFN should be a valid definition in its own right),
- or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP.
+ or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
+ or an extended menu item definition.
+ (See info node `(elisp)Extended Menu Items'.)
 
 If KEYMAP is a sparse keymap with a binding for KEY, the existing
 binding is altered.  If there is no binding for KEY, the new pair
@@ -1148,9 +1179,10 @@ binding KEY to DEF is added at the front of KEYMAP.  */)
   if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt))
     Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands);
 
-  meta_bit = VECTORP (key) ? meta_modifier : 0x80;
+  meta_bit = (VECTORP (key) || STRINGP (key) && STRING_MULTIBYTE (key)
+             ? meta_modifier : 0x80);
 
-  if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, make_number (0))))
+  if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0)))
     { /* DEF is apparently an XEmacs-style keyboard macro.  */
       Lisp_Object tmp = Fmake_vector (make_number (ASIZE (def)), Qnil);
       int i = ASIZE (def);
@@ -1169,8 +1201,15 @@ binding KEY to DEF is added at the front of KEYMAP.  */)
     {
       c = Faref (key, make_number (idx));
 
-      if (CONSP (c) && lucid_event_type_list_p (c))
-       c = Fevent_convert_list (c);
+      if (CONSP (c))
+       {
+         /* C may be a Lucid style event type list or a cons (FROM .
+            TO) specifying a range of characters.  */
+         if (lucid_event_type_list_p (c))
+           c = Fevent_convert_list (c);
+         else if (CHARACTERP (XCAR (c)))
+           CHECK_CHARACTER_CDR (c);
+       }
 
       if (SYMBOLP (c))
        silly_event_symbol_error (c);
@@ -1191,7 +1230,10 @@ binding KEY to DEF is added at the front of KEYMAP.  */)
          idx++;
        }
 
-      if (!INTEGERP (c) && !SYMBOLP (c) && !CONSP (c))
+      if (!INTEGERP (c) && !SYMBOLP (c)
+         && (!CONSP (c)
+             /* If C is a range, it must be a leaf.  */
+             || (INTEGERP (XCAR (c)) && idx != length)))
        error ("Key sequence contains invalid event");
 
       if (idx == length)
@@ -1217,23 +1259,42 @@ binding KEY to DEF is added at the front of KEYMAP.  */)
 
 /* This function may GC (it calls Fkey_binding).  */
 
-DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 2, 0,
-       doc: /* Return the remapping for command COMMAND in current keymaps.
+DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 3, 0,
+       doc: /* Return the remapping for command COMMAND.
 Returns nil if COMMAND is not remapped (or not a symbol).
 
 If the optional argument POSITION is non-nil, it specifies a mouse
 position as returned by `event-start' and `event-end', and the
 remapping occurs in the keymaps associated with it.  It can also be a
 number or marker, in which case the keymap properties at the specified
-buffer position instead of point are used. */)
-     (command, position)
-     Lisp_Object command, position;
+buffer position instead of point are used.  The KEYMAPS argument is
+ignored if POSITION is non-nil.
+
+If the optional argument KEYMAPS is non-nil, it should be a list of
+keymaps to search for command remapping.  Otherwise, search for the
+remapping in all currently active keymaps.  */)
+     (command, position, keymaps)
+     Lisp_Object command, position, keymaps;
 {
   if (!SYMBOLP (command))
     return Qnil;
 
   ASET (command_remapping_vector, 1, command);
-  return Fkey_binding (command_remapping_vector, Qnil, Qt, position);
+
+  if (NILP (keymaps))
+    return Fkey_binding (command_remapping_vector, Qnil, Qt, position);
+  else
+    {
+      Lisp_Object maps, binding;
+
+      for (maps = keymaps; !NILP (maps); maps = Fcdr (maps))
+       {
+         binding = Flookup_key (Fcar (maps), command_remapping_vector, Qnil);
+         if (!NILP (binding) && !INTEGERP (binding))
+           return binding;
+       }
+      return Qnil;
+    }
 }
 
 /* Value is number if KEY is too long; nil if valid but has no definition. */
@@ -1241,7 +1302,8 @@ buffer position instead of point are used. */)
 
 DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0,
        doc: /* In keymap KEYMAP, look up key sequence KEY.  Return the definition.
-nil means undefined.  See doc of `define-key' for kinds of definitions.
+A value of nil means undefined.  See doc of `define-key'
+for kinds of definitions.
 
 A number as value means KEY is "too long";
 that is, characters or symbols in it except for the last one
@@ -1284,7 +1346,7 @@ recognize the default bindings, just as `read-key-sequence' does.  */)
        c = Fevent_convert_list (c);
 
       /* Turn the 8th bit of string chars into a meta modifier.  */
-      if (INTEGERP (c) && XINT (c) & 0x80 && STRINGP (key))
+      if (STRINGP (key) && XINT (c) & 0x80 && !STRING_MULTIBYTE (key))
        XSETINT (c, (XINT (c) | meta_modifier) & ~0x80);
 
       /* Allow string since binding for `menu-bar-select-buffer'
@@ -1393,8 +1455,10 @@ silly_event_symbol_error (c)
 static Lisp_Object *cmm_modes = NULL, *cmm_maps = NULL;
 static int cmm_size = 0;
 
-/* Store a pointer to an array of the keymaps of the currently active
-   minor modes in *buf, and return the number of maps it contains.
+/* Store a pointer to an array of the currently active minor modes in
+   *modeptr, a pointer to an array of the keymaps of the currently
+   active minor modes in *mapptr, and return the number of maps
+   *mapptr contains.
 
    This function always returns a pointer to the same buffer, and may
    free or reallocate it, so if you want to keep it for a long time or
@@ -1595,38 +1659,34 @@ specified buffer position instead of point are used.
 
   GCPRO2 (key, position);
 
-  if (NILP (position))
+  if (NILP (position) && VECTORP (key))
     {
-      Lisp_Object event;
-      /* mouse events may have a symbolic prefix indicating the
-        scrollbar or mode line */
-      if (SYMBOLP (AREF (key, 0)) && ASIZE (key) > 1)
-       event = AREF (key, 1);
-      else
-       event = AREF (key, 0);
+      Lisp_Object event
+       /* mouse events may have a symbolic prefix indicating the
+          scrollbar or mode line */
+       = AREF (key, SYMBOLP (AREF (key, 0)) && ASIZE (key) > 1 ? 1 : 0);
 
       /* We are not interested in locations without event data */
 
-      if (EVENT_HAS_PARAMETERS (event)) {
-       Lisp_Object kind;
-
-       kind = EVENT_HEAD_KIND (EVENT_HEAD (event));
-       if (EQ (kind, Qmouse_click))
-         position = EVENT_START (event);
-      }
+      if (EVENT_HAS_PARAMETERS (event) && CONSP (XCDR (event)))
+       {
+         Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (event));
+         if (EQ (kind, Qmouse_click))
+           position = EVENT_START (event);
+       }
     }
 
   /* Key sequences beginning with mouse clicks
      are read using the keymaps of the buffer clicked on, not
      the current buffer.  So we may have to switch the buffer
      here. */
-  
+
   if (CONSP (position))
     {
       Lisp_Object window;
-      
+
       window = POSN_WINDOW (position);
-         
+
       if (WINDOWP (window)
          && BUFFERP (XWINDOW (window)->buffer)
          && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
@@ -1638,13 +1698,13 @@ specified buffer position instead of point are used.
             would not be a problem here, but it is easier to keep
             things the same.
          */
-             
+
          record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
-         
+
          set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
        }
     }
-  
+
   if (! NILP (current_kboard->Voverriding_terminal_local_map))
     {
       value = Flookup_key (current_kboard->Voverriding_terminal_local_map,
@@ -1667,18 +1727,16 @@ specified buffer position instead of point are used.
        : MARKERP (position) ? marker_position (position)
        : PT;
 
-      local_map = get_local_map (pt, current_buffer, Qlocal_map); 
-      keymap = get_local_map (pt, current_buffer, Qkeymap); 
+      local_map = get_local_map (pt, current_buffer, Qlocal_map);
+      keymap = get_local_map (pt, current_buffer, Qkeymap);
 
       if (CONSP (position))
        {
-         Lisp_Object string, window;
-
-         window = POSN_WINDOW (position);
+         Lisp_Object string;
 
          /* For a mouse click, get the local text-property keymap
             of the place clicked on, rather than point.  */
-         
+
          if (POSN_INBUFFER_P (position))
            {
              Lisp_Object pos;
@@ -1689,7 +1747,7 @@ specified buffer position instead of point are used.
                {
                  local_map = get_local_map (XINT (pos),
                                             current_buffer, Qlocal_map);
-                 
+
                  keymap = get_local_map (XINT (pos),
                                          current_buffer, Qkeymap);
                }
@@ -1700,15 +1758,16 @@ specified buffer position instead of point are used.
             string displayed via the `display' property,
             consider `local-map' and `keymap' properties of
             that string.  */
-         
+
          if (string = POSN_STRING (position),
              (CONSP (string) && STRINGP (XCAR (string))))
            {
              Lisp_Object pos, map;
-             
+
              pos = XCDR (string);
              string = XCAR (string);
-             if (XINT (pos) >= 0
+             if (INTEGERP (pos)
+                 && XINT (pos) >= 0
                  && XINT (pos) < SCHARS (string))
                {
                  map = Fget_text_property (pos, Qlocal_map, string);
@@ -1720,7 +1779,7 @@ specified buffer position instead of point are used.
                    keymap = map;
                }
            }
-         
+
        }
 
       if (! NILP (keymap))
@@ -1765,7 +1824,7 @@ specified buffer position instead of point are used.
   if (NILP (no_remap) && SYMBOLP (value))
     {
       Lisp_Object value1;
-      if (value1 = Fcommand_remapping (value, position), !NILP (value1))
+      if (value1 = Fcommand_remapping (value, position, Qnil), !NILP (value1))
        value = value1;
     }
 
@@ -2090,12 +2149,9 @@ then the value includes only maps for prefixes that start with PREFIX.  */)
 
          if (CHAR_TABLE_P (elt))
            {
-             Lisp_Object indices[3];
-
-             map_char_table (accessible_keymaps_char_table, Qnil, elt,
+             map_char_table (accessible_keymaps_char_table, Qnil,
                              elt, Fcons (Fcons (maps, make_number (is_metized)),
-                                         Fcons (tail, thisseq)),
-                             0, indices);
+                                         Fcons (tail, thisseq)));
            }
          else if (VECTORP (elt))
            {
@@ -2232,15 +2288,13 @@ push_key_description (c, p, force_multibyte)
      int force_multibyte;
 {
   unsigned c2;
-  int valid_p;
 
   /* Clear all the meaningless bits above the meta bit.  */
   c &= meta_modifier | ~ - meta_modifier;
   c2 = c & ~(alt_modifier | ctrl_modifier | hyper_modifier
             | meta_modifier | shift_modifier | super_modifier);
 
-  valid_p = SINGLE_BYTE_CHAR_P (c2) || char_valid_p (c2, 0);
-  if (! valid_p)
+  if (! CHARACTERP (make_number (c2)))
     {
       /* KEY_DESCRIPTION_SIZE is large enough for this.  */
       p += sprintf (p, "[%d]", c);
@@ -2334,25 +2388,12 @@ push_key_description (c, p, force_multibyte)
     }
   else
     {
-      if (force_multibyte)
-       {
-         if (SINGLE_BYTE_CHAR_P (c))
-           c = unibyte_char_to_multibyte (c);
-         p += CHAR_STRING (c, p);
-       }
-      else if (NILP (current_buffer->enable_multibyte_characters))
-       {
-         int bit_offset;
-         *p++ = '\\';
-         /* The biggest character code uses 19 bits.  */
-         for (bit_offset = 18; bit_offset >= 0; bit_offset -= 3)
-           {
-             if (c >= (1 << bit_offset))
-               *p++ = ((c & (7 << bit_offset)) >> bit_offset) + '0';
-           }
-       }
+      /* Now we are sure that C is a valid character code.  */
+      if (NILP (current_buffer->enable_multibyte_characters)
+         && ! force_multibyte)
+       *p++ = multibyte_char_to_unibyte (c, Qnil);
       else
-       p += CHAR_STRING (c, p);
+       p += CHAR_STRING (c, (unsigned char *) p);
     }
 
   return p;
@@ -2376,43 +2417,10 @@ around function keys and event symbols.  */)
 
   if (INTEGERP (key))          /* Normal character */
     {
-      unsigned int charset, c1, c2;
-      int without_bits = XINT (key) & ~((-1) << CHARACTERBITS);
-
-      if (SINGLE_BYTE_CHAR_P (without_bits))
-       charset = 0;
-      else
-       SPLIT_CHAR (without_bits, charset, c1, c2);
+      char tem[KEY_DESCRIPTION_SIZE];
 
-      if (charset
-         && CHARSET_DEFINED_P (charset)
-         && ((c1 >= 0 && c1 < 32)
-             || (c2 >= 0 && c2 < 32)))
-       {
-         /* Handle a generic character.  */
-         Lisp_Object name;
-         name = CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX);
-         CHECK_STRING (name);
-         return concat2 (build_string ("Character set "), name);
-       }
-      else
-       {
-         char tem[KEY_DESCRIPTION_SIZE], *end;
-         int nbytes, nchars;
-         Lisp_Object string;
-
-         end = push_key_description (XUINT (key), tem, 1);
-         nbytes = end - tem;
-         nchars = multibyte_chars_in_text (tem, nbytes);
-         if (nchars == nbytes)
-           {
-             *end = '\0';
-             string = build_string (tem);
-           }
-         else
-           string = make_multibyte_string (tem, nchars, nbytes);
-         return string;
-       }
+      *push_key_description (XUINT (key), tem, 1) = 0;
+      return build_string (tem);
     }
   else if (SYMBOLP (key))      /* Function key or event-symbol */
     {
@@ -2478,7 +2486,7 @@ See Info node `(elisp)Describing Characters' for examples.  */)
   CHECK_NUMBER (character);
 
   c = XINT (character);
-  if (!SINGLE_BYTE_CHAR_P (c))
+  if (!ASCII_CHAR_P (c))
     {
       int len = CHAR_STRING (c, str);
 
@@ -2561,15 +2569,6 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
   /* 1 means ignore all menu bindings entirely.  */
   int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii);
 
-  /* If this command is remapped, then it has no key bindings
-     of its own.  */
-  if (NILP (no_remap) && SYMBOLP (definition))
-    {
-      Lisp_Object tem;
-      if (tem = Fcommand_remapping (definition, Qnil), !NILP (tem))
-       return Qnil;
-    }
-
   found = keymaps;
   while (CONSP (found))
     {
@@ -2583,6 +2582,13 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
   found = Qnil;
   sequences = Qnil;
 
+  /* If this command is remapped, then it has no key bindings
+     of its own.  */
+  if (NILP (no_remap)
+      && SYMBOLP (definition)
+      && !NILP (Fcommand_remapping (definition, Qnil, keymaps)))
+    RETURN_UNGCPRO (Qnil);
+
   for (; !NILP (maps); maps = Fcdr (maps))
     {
       /* Key sequence to reach map, and the map that it reaches */
@@ -2649,7 +2655,6 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
            }
          else if (CHAR_TABLE_P (elt))
            {
-             Lisp_Object indices[3];
              Lisp_Object args;
 
              args = Fcons (Fcons (Fcons (definition, noindirect),
@@ -2657,8 +2662,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
                            Fcons (Fcons (this, last),
                                   Fcons (make_number (nomenus),
                                          make_number (last_is_meta))));
-             map_char_table (where_is_internal_2, Qnil, elt, elt, args,
-                             0, indices);
+             map_char_table (where_is_internal_2, Qnil, elt, args);
              sequences = XCDR (XCAR (args));
            }
          else if (CONSP (elt))
@@ -2873,12 +2877,15 @@ remapped command in the returned list.  */)
 
 /* This is the function that Fwhere_is_internal calls using map_char_table.
    ARGS has the form
-   (((DEFINITION . NOINDIRECT) . (KEYMAP . RESULT))
+   (((DEFINITION . NOINDIRECT) . RESULT)
     .
     ((THIS . LAST) . (NOMENUS . LAST_IS_META)))
    Since map_char_table doesn't really use the return value from this function,
    we the result append to RESULT, the slot in ARGS.
 
+   KEY may be a cons (FROM . TO) where both FROM and TO are integers
+   (i.e. character events).
+
    This function can GC because it calls where_is_internal_1 which can
    GC.  */
 
@@ -2892,7 +2899,6 @@ where_is_internal_2 (args, key, binding)
   struct gcpro gcpro1, gcpro2, gcpro3;
 
   GCPRO3 (args, key, binding);
-  result = XCDR (XCAR (args));
   definition = XCAR (XCAR (XCAR (args)));
   noindirect = XCDR (XCAR (XCAR (args)));
   this = XCAR (XCAR (XCDR (args)));
@@ -2900,11 +2906,39 @@ where_is_internal_2 (args, key, binding)
   nomenus = XFASTINT (XCAR (XCDR (XCDR (args))));
   last_is_meta = XFASTINT (XCDR (XCDR (XCDR (args))));
 
-  sequence = where_is_internal_1 (binding, key, definition, noindirect,
-                                 this, last, nomenus, last_is_meta);
+  result = Qnil;
+  if (CONSP (key) && INTEGERP (XCAR (key)) && INTEGERP (XCDR (key)))
+    {
+      /* Try all ASCII characters.  Try also non-ASCII characters but
+        only the first and last one because trying all of them is
+        extremely memory and time consuming.
+
+        Fixme: Perhaps it should be allowed to store a cons directly
+        in RESULT.  -- handa@m17n.org   */
+      int from = XINT (XCAR (key)), to = XINT (XCDR (key));
+      Lisp_Object k;
 
-  if (!NILP (sequence))
-    XSETCDR (XCAR (args), Fcons (sequence, result));
+      for (; from <= to; to--)
+       {
+         k = make_number (to);
+         sequence = where_is_internal_1 (binding, k, definition, noindirect,
+                                         this, last, nomenus, last_is_meta);
+         if (!NILP (sequence))
+           result = Fcons (sequence, result);
+         if (to > 129)
+           to = 129;
+       }
+    }
+  else
+    {
+      sequence = where_is_internal_1 (binding, key, definition, noindirect,
+                                     this, last, nomenus, last_is_meta);
+      if (!NILP (sequence))
+       result = Fcons (sequence, Qnil);
+    }
+
+  if (! NILP (result))
+    nconc2 (XCAR (args), result);
 
   UNGCPRO;
 }
@@ -2976,6 +3010,8 @@ Keyboard translations:\n\n\
 You type        Translation\n\
 --------        -----------\n";
 
+  CHECK_BUFFER (buffer);
+
   shadow = Qnil;
   GCPRO1 (shadow);
 
@@ -3439,9 +3475,13 @@ describe_map (map, prefix, elt_describer, partial, shadow,
              tem = shadow_lookup (shadow, kludge, Qt);
              if (!NILP (tem))
                {
+                 /* If both bindings are keymaps, this key is a prefix key,
+                    so don't say it is shadowed.  */
+                 if (KEYMAPP (definition) && KEYMAPP (tem))
+                   ;
                  /* Avoid generating duplicate entries if the
-                    shadowed binding has the same definition. */
-                 if (mention_shadow && !EQ (tem, definition))
+                    shadowed binding has the same definition.  */
+                 else if (mention_shadow && !EQ (tem, definition))
                    this_shadowed = 1;
                  else
                    continue;
@@ -3586,9 +3626,10 @@ DESCRIBER is the output function used; nil means use `princ'.  */)
    If the definition in effect in the whole map does not match
    the one in this vector, we ignore this one.
 
-   When describing a sub-char-table, INDICES is a list of
-   indices at higher levels in this char-table,
-   and CHAR_TABLE_DEPTH says how many levels down we have gone.
+   ARGS is simply passed as the second argument to ELT_DESCRIBER.
+
+   INDICES and CHAR_TABLE_DEPTH are ignored.  They will be removed in
+   the near future.
 
    KEYMAP_P is 1 if vector is known to be a keymap, so map ESC to M-.
 
@@ -3613,24 +3654,18 @@ describe_vector (vector, prefix, args, elt_describer,
   Lisp_Object definition;
   Lisp_Object tem2;
   Lisp_Object elt_prefix = Qnil;
-  register int i;
+  int i;
   Lisp_Object suppress;
   Lisp_Object kludge;
   int first = 1;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   /* Range of elements to be handled.  */
   int from, to;
-  /* A flag to tell if a leaf in this level of char-table is not a
-     generic character (i.e. a complete multibyte character).  */
-  int complete_char;
-  int character;
+  Lisp_Object character;
   int starting_i;
 
   suppress = Qnil;
 
-  if (indices == 0)
-    indices = (int *) alloca (3 * sizeof (int));
-
   definition = Qnil;
 
   if (!keymap_p)
@@ -3654,61 +3689,24 @@ describe_vector (vector, prefix, args, elt_describer,
   if (partial)
     suppress = intern ("suppress-keymap");
 
-  if (CHAR_TABLE_P (vector))
-    {
-      if (char_table_depth == 0)
-       {
-         /* VECTOR is a top level char-table.  */
-         complete_char = 1;
-         from = 0;
-         to = CHAR_TABLE_ORDINARY_SLOTS;
-       }
-      else
-       {
-         /* VECTOR is a sub char-table.  */
-         if (char_table_depth >= 3)
-           /* A char-table is never that deep.  */
-           error ("Too deep char table");
-
-         complete_char
-           = (CHARSET_VALID_P (indices[0])
-              && ((CHARSET_DIMENSION (indices[0]) == 1
-                   && char_table_depth == 1)
-                  || char_table_depth == 2));
-
-         /* Meaningful elements are from 32th to 127th.  */
-         from = 32;
-         to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
-       }
-    }
-  else
-    {
-      /* This does the right thing for ordinary vectors.  */
-
-      complete_char = 1;
-      from = 0;
-      to = XVECTOR (vector)->size;
-    }
+  from = 0;
+  to = CHAR_TABLE_P (vector) ? MAX_CHAR + 1 : XVECTOR (vector)->size;
 
   for (i = from; i < to; i++)
     {
       int this_shadowed = 0;
-      QUIT;
+      int range_beg, range_end;
+      Lisp_Object val;
 
-      if (CHAR_TABLE_P (vector))
-       {
-         if (char_table_depth == 0 && i >= CHAR_TABLE_SINGLE_BYTE_SLOTS)
-           complete_char = 0;
+      QUIT;
 
-         if (i >= CHAR_TABLE_SINGLE_BYTE_SLOTS
-             && !CHARSET_DEFINED_P (i - 128))
-           continue;
+      starting_i = i;
 
-         definition
-           = get_keyelt (XCHAR_TABLE (vector)->contents[i], 0);
-       }
+      if (CHAR_TABLE_P (vector))
+       val = char_table_ref_and_range (vector, i, &range_beg, &i);
       else
-       definition = get_keyelt (AREF (vector, i), 0);
+       val = AREF (vector, i);
+      definition = get_keyelt (val, 0);
 
       if (NILP (definition)) continue;
 
@@ -3722,31 +3720,11 @@ describe_vector (vector, prefix, args, elt_describer,
          if (!NILP (tem)) continue;
        }
 
-      /* Set CHARACTER to the character this entry describes, if any.
-        Also update *INDICES.  */
-      if (CHAR_TABLE_P (vector))
-       {
-         indices[char_table_depth] = i;
-
-         if (char_table_depth == 0)
-           {
-             character = i;
-             indices[0] = i - 128;
-           }
-         else if (complete_char)
-           {
-             character = MAKE_CHAR (indices[0], indices[1], indices[2]);
-           }
-         else
-           character = 0;
-       }
-      else
-       character = i;
-
-      ASET (kludge, 0, make_number (character));
+      character = make_number (starting_i);
+      ASET (kludge, 0, character);
 
       /* If this binding is shadowed by some other map, ignore it.  */
-      if (!NILP (shadow) && complete_char)
+      if (!NILP (shadow))
        {
          Lisp_Object tem;
 
@@ -3763,7 +3741,7 @@ describe_vector (vector, prefix, args, elt_describer,
 
       /* Ignore this definition if it is shadowed by an earlier
         one in the same keymap.  */
-      if (!NILP (entire_map) && complete_char)
+      if (!NILP (entire_map))
        {
          Lisp_Object tem;
 
@@ -3775,89 +3753,28 @@ describe_vector (vector, prefix, args, elt_describer,
 
       if (first)
        {
-         if (char_table_depth == 0)
-           insert ("\n", 1);
+         insert ("\n", 1);
          first = 0;
        }
 
-      /* For a sub char-table, show the depth by indentation.
-        CHAR_TABLE_DEPTH can be greater than 0 only for a char-table.  */
-      if (char_table_depth > 0)
-       insert ("    ", char_table_depth * 2); /* depth is 1 or 2.  */
-
       /* Output the prefix that applies to every entry in this map.  */
       if (!NILP (elt_prefix))
        insert1 (elt_prefix);
 
-      /* Insert or describe the character this slot is for,
-        or a description of what it is for.  */
-      if (SUB_CHAR_TABLE_P (vector))
-       {
-         if (complete_char)
-           insert_char (character);
-         else
-           {
-             /* We need an octal representation for this block of
-                 characters.  */
-             char work[16];
-             sprintf (work, "(row %d)", i);
-             insert (work, strlen (work));
-           }
-       }
-      else if (CHAR_TABLE_P (vector))
-       {
-         if (complete_char)
-           insert1 (Fkey_description (kludge, prefix));
-         else
-           {
-             /* Print the information for this character set.  */
-             insert_string ("<");
-             tem2 = CHARSET_TABLE_INFO (i - 128, CHARSET_SHORT_NAME_IDX);
-             if (STRINGP (tem2))
-               insert_from_string (tem2, 0, 0, SCHARS (tem2),
-                                   SBYTES (tem2), 0);
-             else
-               insert ("?", 1);
-             insert (">", 1);
-           }
-       }
-      else
-       {
-         insert1 (Fkey_description (kludge, prefix));
-       }
-
-      /* If we find a sub char-table within a char-table,
-        scan it recursively; it defines the details for
-        a character set or a portion of a character set.  */
-      if (CHAR_TABLE_P (vector) && SUB_CHAR_TABLE_P (definition))
-       {
-         insert ("\n", 1);
-         describe_vector (definition, prefix, args, elt_describer,
-                          partial, shadow, entire_map,
-                          indices, char_table_depth + 1, keymap_p,
-                          mention_shadow);
-         continue;
-       }
-
-      starting_i = i;
+      insert1 (Fkey_description (kludge, prefix));
 
       /* Find all consecutive characters or rows that have the same
          definition.  But, for elements of a top level char table, if
          they are for charsets, we had better describe one by one even
          if they have the same definition.  */
       if (CHAR_TABLE_P (vector))
-       {
-         int limit = to;
-
-         if (char_table_depth == 0)
-           limit = CHAR_TABLE_SINGLE_BYTE_SLOTS;
-
-         while (i + 1 < limit
-                && (tem2 = get_keyelt (XCHAR_TABLE (vector)->contents[i + 1], 0),
-                    !NILP (tem2))
-                && !NILP (Fequal (tem2, definition)))
-           i++;
-       }
+       while (i + 1 < to
+              && (val = char_table_ref_and_range (vector, i + 1,
+                                                  &range_beg, &range_end),
+                  tem2 = get_keyelt (val, 0),
+                  !NILP (tem2))
+              && !NILP (Fequal (tem2, definition)))
+         i = range_end;
       else
        while (i + 1 < to
               && (tem2 = get_keyelt (AREF (vector, i + 1), 0),
@@ -3865,7 +3782,6 @@ describe_vector (vector, prefix, args, elt_describer,
               && !NILP (Fequal (tem2, definition)))
          i++;
 
-
       /* If we have a range of more than one character,
         print where the range reaches to.  */
 
@@ -3878,31 +3794,7 @@ describe_vector (vector, prefix, args, elt_describer,
          if (!NILP (elt_prefix))
            insert1 (elt_prefix);
 
-         if (CHAR_TABLE_P (vector))
-           {
-             if (char_table_depth == 0)
-               {
-                 insert1 (Fkey_description (kludge, prefix));
-               }
-             else if (complete_char)
-               {
-                 indices[char_table_depth] = i;
-                 character = MAKE_CHAR (indices[0], indices[1], indices[2]);
-                 insert_char (character);
-               }
-             else
-               {
-                 /* We need an octal representation for this block of
-                    characters.  */
-                 char work[16];
-                 sprintf (work, "(row %d)", i);
-                 insert (work, strlen (work));
-               }
-           }
-         else
-           {
-             insert1 (Fkey_description (kludge, prefix));
-           }
+         insert1 (Fkey_description (kludge, prefix));
        }
 
       /* Print a description of the definition of this character.
@@ -3918,11 +3810,11 @@ describe_vector (vector, prefix, args, elt_describer,
        }
     }
 
-  /* For (sub) char-table, print `defalt' slot at last.  */
-  if (CHAR_TABLE_P (vector) && !NILP (XCHAR_TABLE (vector)->defalt))
+  if (CHAR_TABLE_P (vector) && ! NILP (XCHAR_TABLE (vector)->defalt))
     {
-      insert ("    ", char_table_depth * 2);
-      insert_string ("<<default>>");
+      if (!NILP (elt_prefix))
+       insert1 (elt_prefix);
+      insert ("default", 7);
       (*elt_describer) (XCHAR_TABLE (vector)->defalt, args);
     }