Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-7
[bpt/emacs.git] / src / keymap.c
index cc2d21b..2977b4d 100644 (file)
@@ -1,6 +1,6 @@
 /* Manipulation of keymaps
-   Copyright (C) 1985, 86,87,88,93,94,95,98,99, 2000, 01, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 1999, 2000,
+     2001, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
+#include "character.h"
 #include "charset.h"
 #include "keyboard.h"
 #include "termhooks.h"
@@ -130,10 +131,11 @@ static void silly_event_symbol_error P_ ((Lisp_Object));
 
 DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 1, 0,
        doc: /* Construct and return a new keymap, of the form (keymap CHARTABLE . ALIST).
-CHARTABLE is a char-table that holds the bindings for the ASCII
-characters.  ALIST is an assoc-list which holds bindings for function keys,
-mouse events, and any other things that appear in the input stream.
-All entries in it are initially nil, meaning "command undefined".
+CHARTABLE is a char-table that holds the bindings for all characters
+without modifiers.  All entries in it are initially nil, meaning
+"command undefined".  ALIST is an assoc-list which holds bindings for
+function keys, mouse events, and any other things that appear in the
+input stream.  Initially, ALIST is nil.
 
 The optional arg STRING supplies a menu name for the keymap
 in case you use it as a menu with `x-popup-menu'.  */)
@@ -212,13 +214,13 @@ when reading a key-sequence to be looked-up in this keymap.  */)
      (map)
      Lisp_Object map;
 {
+  map = get_keymap (map, 0, 0);
   while (CONSP (map))
     {
-      register Lisp_Object tem;
-      tem = Fcar (map);
+      Lisp_Object tem = XCAR (map);
       if (STRINGP (tem))
        return tem;
-      map = Fcdr (map);
+      map = XCDR (map);
     }
   return Qnil;
 }
@@ -266,7 +268,8 @@ get_keymap (object, error, autoload)
 
       /* Should we do an autoload?  Autoload forms for keymaps have
         Qkeymap as their fifth element.  */
-      if ((autoload || !error) && EQ (XCAR (tem), Qautoload))
+      if ((autoload || !error) && EQ (XCAR (tem), Qautoload)
+         && SYMBOLP (object))
        {
          Lisp_Object tail;
 
@@ -342,7 +345,7 @@ keymap_memberp (map, maps)
 
 DEFUN ("set-keymap-parent", Fset_keymap_parent, Sset_keymap_parent, 2, 2, 0,
        doc: /* Modify KEYMAP to set its parent map to PARENT.
-PARENT should be nil or another keymap.  */)
+Return PARENT.  PARENT should be nil or another keymap.  */)
      (keymap, parent)
      Lisp_Object keymap, parent;
 {
@@ -413,11 +416,7 @@ PARENT should be nil or another keymap.  */)
 
       if (CHAR_TABLE_P (XCAR (list)))
        {
-         Lisp_Object indices[3];
-
-         map_char_table (fix_submap_inheritance, Qnil,
-                         XCAR (list), XCAR (list),
-                         keymap, 0, indices);
+         map_char_table (fix_submap_inheritance, Qnil, XCAR (list), keymap);
        }
     }
 
@@ -526,6 +525,10 @@ access_keymap (map, idx, t_ok, noinherit, autoload)
       struct gcpro gcpro1;
       Lisp_Object meta_map;
       GCPRO1 (map);
+      /* A strange value in which Meta is set would cause
+        infinite recursion.  Protect against that.  */
+      if (XINT (meta_prefix_char) & CHAR_META)
+       meta_prefix_char = make_number (27);
       meta_map = get_keymap (access_keymap (map, meta_prefix_char,
                                            t_ok, noinherit, autoload),
                             0, autoload);
@@ -553,9 +556,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);
@@ -579,24 +580,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);
@@ -707,12 +690,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;
@@ -726,16 +707,23 @@ map_keymap_call (key, val, fun, dummy)
   call2 (fun, key, val);
 }
 
-DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 2, 0,
+DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 3, 0,
        doc: /* Call FUNCTION for every binding in KEYMAP.
-FUNCTION is called with two arguments: the event and its binding.  */)
-     (function, keymap)
-     Lisp_Object function, keymap;
+FUNCTION is called with two arguments: the event and its binding.
+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
+grandparent's bindings are also included and so on.
+usage: (map-keymap FUNCTION KEYMAP)  */)
+     (function, keymap, sort_first)
+     Lisp_Object function, keymap, sort_first;
 {
   if (INTEGERP (function))
     /* We have to stop integers early since map_keymap gives them special
        significance.  */
     Fsignal (Qinvalid_function, Fcons (function, Qnil));
+  if (! NILP (sort_first))
+    return call3 (intern ("map-keymap-internal"), function, keymap, Qt);
+      
   map_keymap (keymap, map_keymap_call, function, NULL, 1);
   return Qnil;
 }
@@ -853,10 +841,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.  */
@@ -892,6 +885,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))
@@ -908,6 +914,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))
@@ -917,6 +928,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,
@@ -931,8 +955,21 @@ store_in_keymap (keymap, idx, def)
   keymap_end:
     /* We have scanned the entire keymap, and not found a binding for
        IDX.  Let's add one.  */
-    XSETCDR (insertion_point,
-            Fcons (Fcons (idx, def), XCDR (insertion_point)));
+    {
+      Lisp_Object elt;
+
+      if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+       {
+         /* IDX specifies a range of characters, and not all of them
+            were handled yet, which means this keymap doesn't have a
+            char-table.  So, we insert a char-table now.  */
+         elt = Fmake_char_table (Qkeymap, Qnil);
+         Fset_char_table_range (elt, idx, NILP (def) ? Qt : def);
+       }
+      else
+       elt = Fcons (idx, def);
+      XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point)));
+    }
   }
 
   return def;
@@ -1018,7 +1055,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,
@@ -1041,9 +1078,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))
        {
@@ -1124,8 +1160,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);
@@ -1146,7 +1189,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)
@@ -1231,7 +1277,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 (XINT (c) & 0x80 && STRINGP (key))
+      if (INTEGERP (c) && XINT (c) & 0x80 && STRINGP (key))
        XSETINT (c, (XINT (c) | meta_modifier) & ~0x80);
 
       /* Allow string since binding for `menu-bar-select-buffer'
@@ -1477,10 +1523,13 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and
 
   if (!NILP (olp))
     {
-      if (!NILP (Voverriding_local_map))
-       keymaps = Fcons (Voverriding_local_map, keymaps);
       if (!NILP (current_kboard->Voverriding_terminal_local_map))
        keymaps = Fcons (current_kboard->Voverriding_terminal_local_map, keymaps);
+      /* The doc said that overriding-terminal-local-map should
+        override overriding-local-map.  The code used them both,
+        but it seems clearer to use just one.  rms, jan 2005.  */
+      else if (!NILP (Voverriding_local_map))
+       keymaps = Fcons (Voverriding_local_map, keymaps);
     }
   if (NILP (XCDR (keymaps)))
     {
@@ -1488,16 +1537,20 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and
       Lisp_Object *maps;
       int nmaps, i;
 
+      /* This usually returns the buffer's local map,
+        but that can be overridden by a `local-map' property.  */
       local = get_local_map (PT, current_buffer, Qlocal_map);
       if (!NILP (local))
        keymaps = Fcons (local, keymaps);
 
+      /* Now put all the minor mode keymaps on the list.  */
       nmaps = current_minor_maps (0, &maps);
 
       for (i = --nmaps; i >= 0; i--)
        if (!NILP (maps[i]))
          keymaps = Fcons (maps[i], keymaps);
 
+      /* This returns nil unless there is a `keymap' property.  */
       local = get_local_map (PT, current_buffer, Qkeymap);
       if (!NILP (local))
        keymaps = Fcons (local, keymaps);
@@ -1602,7 +1655,7 @@ is non-nil, `key-binding' returns the unmapped command.  */)
 
 DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 2, 0,
        doc: /* Return the binding for command KEYS in current local keymap only.
-KEYS is a string, a sequence of keystrokes.
+KEYS is a string or vector, a sequence of keystrokes.
 The binding is probably a symbol with a function definition.
 
 If optional argument ACCEPT-DEFAULT is non-nil, recognize default
@@ -1621,7 +1674,7 @@ bindings; see the description of `lookup-key' for more details about this.  */)
 
 DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 2, 0,
        doc: /* Return the binding for command KEYS in current global keymap only.
-KEYS is a string, a sequence of keystrokes.
+KEYS is a string or vector, a sequence of keystrokes.
 The binding is probably a symbol with a function definition.
 This function's return values are the same as those of `lookup-key'
 \(which see).
@@ -1686,7 +1739,8 @@ If a second optional argument MAPVAR is given, the map is stored as
 its value instead of as COMMAND's value; but COMMAND is still defined
 as a function.
 The third optional argument NAME, if given, supplies a menu name
-string for the map.  This is required to use the keymap as a menu.  */)
+string for the map.  This is required to use the keymap as a menu.
+This function returns COMMAND.  */)
      (command, mapvar, name)
      Lisp_Object command, mapvar, name;
 {
@@ -1915,12 +1969,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))
            {
@@ -2148,30 +2199,24 @@ push_key_description (c, p, force_multibyte)
     {
       *p++ = c;
     }
+  else if (CHARACTERP (make_number (c)))
+    {
+      if (NILP (current_buffer->enable_multibyte_characters)
+         && ! force_multibyte)
+       *p++ = multibyte_char_to_unibyte (c, Qnil);
+      else
+       p += CHAR_STRING (c, (unsigned char *) p);
+    }
   else
     {
-      int valid_p = SINGLE_BYTE_CHAR_P (c) || char_valid_p (c, 0);
-
-      if (force_multibyte && valid_p)
+      int bit_offset;
+      *p++ = '\\';
+      /* The biggest character code uses 22 bits.  */
+      for (bit_offset = 21; bit_offset >= 0; bit_offset -= 3)
        {
-         if (SINGLE_BYTE_CHAR_P (c))
-           c = unibyte_char_to_multibyte (c);
-         p += CHAR_STRING (c, p);
+         if (c >= (1 << bit_offset))
+           *p++ = ((c & (7 << bit_offset)) >> bit_offset) + '0';
        }
-      else if (NILP (current_buffer->enable_multibyte_characters)
-              || valid_p)
-       {
-         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';
-           }
-       }
-      else
-       p += CHAR_STRING (c, p);
     }
 
   return p;
@@ -2195,43 +2240,10 @@ around function keys and event symbols.  */)
 
   if (INTEGERP (key))          /* Normal character */
     {
-      unsigned int charset, c1, c2;
-      int without_bits = XINT (key) & ~((-1) << CHARACTERBITS);
+      char tem[KEY_DESCRIPTION_SIZE];
 
-      if (SINGLE_BYTE_CHAR_P (without_bits))
-       charset = 0;
-      else
-       SPLIT_CHAR (without_bits, charset, c1, c2);
-
-      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 */
     {
@@ -2282,7 +2294,11 @@ push_text_char_description (c, p)
 
 DEFUN ("text-char-description", Ftext_char_description, Stext_char_description, 1, 1, 0,
        doc: /* Return a pretty description of file-character CHARACTER.
-Control characters turn into "^char", etc.  */)
+Control characters turn into "^char", etc.  This differs from
+`single-key-description' which turns them into "C-char".
+Also, this function recognizes the 2**7 bit as the Meta character,
+whereas `single-key-description' uses the 2**27 bit for Meta.
+See Info node `(elisp)Describing Characters' for examples.  */)
      (character)
      Lisp_Object character;
 {
@@ -2293,7 +2309,7 @@ Control characters turn into "^char", etc.  */)
   CHECK_NUMBER (character);
 
   c = XINT (character);
-  if (!SINGLE_BYTE_CHAR_P (c))
+  if (!ASCII_CHAR_P (c))
     {
       int len = CHAR_STRING (c, str);
 
@@ -2457,7 +2473,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),
@@ -2465,8 +2480,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))
@@ -2567,7 +2581,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
 
 DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0,
        doc: /* Return list of keys that invoke DEFINITION.
-If KEYMAP is non-nil, search only KEYMAP and the global keymap.
+If KEYMAP is a keymap, search only KEYMAP and the global keymap.
 If KEYMAP is nil, search all the currently active keymaps.
 If KEYMAP is a list of keymaps, search only those keymaps.
 
@@ -2575,8 +2589,8 @@ If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found,
 rather than a list of all possible key sequences.
 If FIRSTONLY is the symbol `non-ascii', return the first binding found,
 no matter what it is.
-If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters,
-and entirely reject menu bindings.
+If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters
+\(or their meta variants) and entirely reject menu bindings.
 
 If optional 4th arg NOINDIRECT is non-nil, don't follow indirections
 to other keymaps or slots.  This makes it possible to search for an
@@ -2668,12 +2682,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.  */
 
@@ -2687,7 +2704,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)));
@@ -2695,11 +2711,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;
 }
@@ -3267,9 +3311,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-.
 
@@ -3292,24 +3337,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)
@@ -3333,60 +3372,23 @@ 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++)
     {
-      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;
 
@@ -3400,31 +3402,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;
 
@@ -3435,7 +3417,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;
 
@@ -3447,88 +3429,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);
-         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),
@@ -3536,7 +3458,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.  */
 
@@ -3549,31 +3470,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.
@@ -3582,11 +3479,11 @@ describe_vector (vector, prefix, args, elt_describer,
       (*elt_describer) (definition, args);
     }
 
-  /* 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);
     }
 
@@ -3746,7 +3643,7 @@ key, typing `ESC O P x' would return [f1 x].  */);
   DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
               doc: /* Keymap of key translations that can override keymaps.
 This keymap works like `function-key-map', but comes after that,
-and applies even for keys that have ordinary bindings.  */);
+and its non-prefix bindings override ordinary bindings.  */);
   Vkey_translation_map = Qnil;
 
   staticpro (&Vmouse_events);