X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/1e7d1ab059a1cab5f042f9a3fe6cb99dfdcb36c9..534c20b22f89ffbe99a4d6a1035b74eacc544ee5:/src/keymap.c diff --git a/src/keymap.c b/src/keymap.c index 0f61304a8e..e56a21a735 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1,5 +1,5 @@ /* Manipulation of keymaps - Copyright (C) 1985, 86,87,88,93,94,95,98,99, 2000 + Copyright (C) 1985, 86,87,88,93,94,95,98,99, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -31,9 +31,7 @@ Boston, MA 02111-1307, USA. */ #include "blockinput.h" #include "puresize.h" #include "intervals.h" - -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define KEYMAPP(m) (!NILP (Fkeymapp (m))) +#include "keymap.h" /* The number of elements in keymap vectors. */ #define DENSE_TABLE_SIZE (0200) @@ -57,7 +55,7 @@ Lisp_Object Vminibuffer_local_map; minibuf */ /* was MinibufLocalNSMap */ -Lisp_Object Vminibuffer_local_ns_map; +Lisp_Object Vminibuffer_local_ns_map; /* The keymap used by the minibuf for local bindings when spaces are not encouraged in the minibuf */ @@ -91,7 +89,13 @@ Lisp_Object Vkey_translation_map; when Emacs starts up. t means don't record anything here. */ Lisp_Object Vdefine_key_rebound_commands; -Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item; +Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap; + +/* Alist of elements like (DEL . "\d"). */ +static Lisp_Object exclude_keys; + +/* Pre-allocated 2-element vector for Fremap_command to use. */ +static Lisp_Object remap_command_vector; /* 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 @@ -109,24 +113,25 @@ static Lisp_Object store_in_keymap P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); static void fix_submap_inheritance P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); static Lisp_Object define_as_prefix P_ ((Lisp_Object, Lisp_Object)); -static Lisp_Object describe_buffer_bindings P_ ((Lisp_Object)); -static void describe_command P_ ((Lisp_Object)); -static void describe_translation P_ ((Lisp_Object)); +static void describe_command P_ ((Lisp_Object, Lisp_Object)); +static void describe_translation P_ ((Lisp_Object, Lisp_Object)); static void describe_map P_ ((Lisp_Object, Lisp_Object, - void (*) P_ ((Lisp_Object)), + void (*) P_ ((Lisp_Object, Lisp_Object)), int, Lisp_Object, Lisp_Object*, int)); +static void silly_event_symbol_error P_ ((Lisp_Object)); /* Keymap object support - constructors and predicates. */ DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 1, 0, - "Construct and return a new keymap, of the form (keymap CHARTABLE . ALIST).\n\ -CHARTABLE is a char-table that 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\ -The optional arg STRING supplies a menu name for the keymap\n\ -in case you use it as a menu with `x-popup-menu'.") - (string) + 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". + +The optional arg STRING supplies a menu name for the keymap +in case you use it as a menu with `x-popup-menu'. */) + (string) Lisp_Object string; { Lisp_Object tail; @@ -139,14 +144,15 @@ in case you use it as a menu with `x-popup-menu'.") } DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, Smake_sparse_keymap, 0, 1, 0, - "Construct and return a new sparse keymap.\n\ -Its car is `keymap' and its cdr is an alist of (CHAR . DEFINITION),\n\ -which binds the character CHAR to DEFINITION, or (SYMBOL . DEFINITION),\n\ -which binds the function key or mouse event SYMBOL to DEFINITION.\n\ -Initially the alist is nil.\n\n\ -The optional arg STRING supplies a menu name for the keymap\n\ -in case you use it as a menu with `x-popup-menu'.") - (string) + doc: /* Construct and return a new sparse keymap. +Its car is `keymap' and its cdr is an alist of (CHAR . DEFINITION), +which binds the character CHAR to DEFINITION, or (SYMBOL . DEFINITION), +which binds the function key or mouse event SYMBOL to DEFINITION. +Initially the 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'. */) + (string) Lisp_Object string; { if (!NILP (string)) @@ -180,18 +186,35 @@ initial_define_lispy_key (keymap, keyname, defname) } DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0, - "Return t if OBJECT is a keymap.\n\ -\n\ -A keymap is a list (keymap . ALIST),\n\ -or a symbol whose function definition is itself a keymap.\n\ -ALIST elements look like (CHAR . DEFN) or (SYMBOL . DEFN);\n\ -a vector of densely packed bindings for small character codes\n\ -is also allowed as an element.") - (object) + doc: /* Return t if OBJECT is a keymap. + +A keymap is a list (keymap . ALIST), +or a symbol whose function definition is itself a keymap. +ALIST elements look like (CHAR . DEFN) or (SYMBOL . DEFN); +a vector of densely packed bindings for small character codes +is also allowed as an element. */) + (object) Lisp_Object object; { - /* FIXME: Maybe this should return t for autoloaded keymaps? -sm */ - return (NILP (get_keymap_1 (object, 0, 0)) ? Qnil : Qt); + return (KEYMAPP (object) ? Qt : Qnil); +} + +DEFUN ("keymap-prompt", Fkeymap_prompt, Skeymap_prompt, 1, 1, 0, + doc: /* Return the prompt-string of a keymap MAP. +If non-nil, the prompt is shown in the echo-area +when reading a key-sequence to be looked-up in this keymap. */) + (map) + Lisp_Object map; +{ + while (CONSP (map)) + { + register Lisp_Object tem; + tem = Fcar (map); + if (STRINGP (tem)) + return tem; + map = Fcdr (map); + } + return Qnil; } /* Check that OBJECT is a keymap (after dereferencing through any @@ -201,6 +224,9 @@ is also allowed as an element.") is an autoload form, do the autoload and try again. If AUTOLOAD is nonzero, callers must assume GC is possible. + If the map needs to be autoloaded, but AUTOLOAD is zero (and ERROR + is zero as well), return Qt. + ERROR controls how we respond if OBJECT isn't a keymap. If ERROR is non-zero, signal an error; otherwise, just return Qnil. @@ -214,7 +240,7 @@ is also allowed as an element.") do_autoload which can GC. */ Lisp_Object -get_keymap_1 (object, error, autoload) +get_keymap (object, error, autoload) Lisp_Object object; int error, autoload; { @@ -225,32 +251,35 @@ get_keymap_1 (object, error, autoload) goto end; if (CONSP (object) && EQ (XCAR (object), Qkeymap)) return object; - else - { - tem = indirect_function (object); - if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) - return tem; - } - /* Should we do an autoload? Autoload forms for keymaps have - Qkeymap as their fifth element. */ - if (autoload - && SYMBOLP (object) - && CONSP (tem) - && EQ (XCAR (tem), Qautoload)) + tem = indirect_function (object); + if (CONSP (tem)) { - Lisp_Object tail; + if (EQ (XCAR (tem), Qkeymap)) + return tem; - tail = Fnth (make_number (4), tem); - if (EQ (tail, Qkeymap)) + /* Should we do an autoload? Autoload forms for keymaps have + Qkeymap as their fifth element. */ + if ((autoload || !error) && EQ (XCAR (tem), Qautoload)) { - struct gcpro gcpro1, gcpro2; + Lisp_Object tail; - GCPRO2 (tem, object); - do_autoload (tem, object); - UNGCPRO; - - goto autoload_retry; + tail = Fnth (make_number (4), tem); + if (EQ (tail, Qkeymap)) + { + if (autoload) + { + struct gcpro gcpro1, gcpro2; + + GCPRO2 (tem, object); + do_autoload (tem, object); + UNGCPRO; + + goto autoload_retry; + } + else + return Qt; + } } } @@ -259,28 +288,18 @@ get_keymap_1 (object, error, autoload) wrong_type_argument (Qkeymapp, object); return Qnil; } - - -/* Follow any symbol chaining, and return the keymap denoted by OBJECT. - If OBJECT doesn't denote a keymap at all, signal an error. */ -Lisp_Object -get_keymap (object) - Lisp_Object object; -{ - return get_keymap_1 (object, 1, 0); -} /* Return the parent map of the keymap MAP, or nil if it has none. We assume that MAP is a valid keymap. */ DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0, - "Return the parent keymap of KEYMAP.") - (keymap) + doc: /* Return the parent keymap of KEYMAP. */) + (keymap) Lisp_Object keymap; { Lisp_Object list; - keymap = get_keymap_1 (keymap, 1, 1); + keymap = get_keymap (keymap, 1, 1); /* Skip past the initial element `keymap'. */ list = XCDR (keymap); @@ -291,7 +310,7 @@ DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0, return list; } - return get_keymap_1(list, 0, 1); + return get_keymap (list, 0, 1); } @@ -309,9 +328,9 @@ keymap_memberp (map, maps) /* Set the parent keymap of MAP to PARENT. */ DEFUN ("set-keymap-parent", Fset_keymap_parent, Sset_keymap_parent, 2, 2, 0, - "Modify KEYMAP to set its parent map to PARENT.\n\ -PARENT should be nil or another keymap.") - (keymap, parent) + doc: /* Modify KEYMAP to set its parent map to PARENT. +PARENT should be nil or another keymap. */) + (keymap, parent) Lisp_Object keymap, parent; { Lisp_Object list, prev; @@ -327,12 +346,12 @@ PARENT should be nil or another keymap.") This is a very minor correctness (rather than safety) issue. */ where_is_cache_keymaps = Qt; - keymap = get_keymap_1 (keymap, 1, 1); + keymap = get_keymap (keymap, 1, 1); GCPRO1 (keymap); if (!NILP (parent)) { - parent = get_keymap_1 (parent, 1, 1); + parent = get_keymap (parent, 1, 1); /* Check for cycles. */ if (keymap_memberp (keymap, parent)) @@ -346,14 +365,14 @@ PARENT should be nil or another keymap.") list = XCDR (prev); /* If there is a parent keymap here, replace it. If we came to the end, add the parent in PREV. */ - if (! CONSP (list) || KEYMAPP (list)) + if (!CONSP (list) || KEYMAPP (list)) { /* If we already have the right parent, return now so that we avoid the loops below. */ if (EQ (XCDR (prev), parent)) RETURN_UNGCPRO (parent); - XCDR (prev) = parent; + XSETCDR (prev, parent); break; } prev = list; @@ -404,22 +423,22 @@ fix_submap_inheritance (map, event, submap) /* SUBMAP is a cons that we found as a key binding. Discard the other things found in a menu key binding. */ - submap = get_keymap_1 (get_keyelt (submap, 0), 0, 0); + submap = get_keymap (get_keyelt (submap, 0), 0, 0); /* If it isn't a keymap now, there's no work to do. */ - if (NILP (submap)) + if (!CONSP (submap)) return; map_parent = Fkeymap_parent (map); - if (! NILP (map_parent)) + if (!NILP (map_parent)) parent_entry = - get_keymap_1 (access_keymap (map_parent, event, 0, 0, 0), 0, 0); + get_keymap (access_keymap (map_parent, event, 0, 0, 0), 0, 0); else parent_entry = Qnil; /* If MAP's parent has something other than a keymap, our own submap shadows it completely. */ - if (NILP (parent_entry)) + if (!CONSP (parent_entry)) return; if (! EQ (parent_entry, submap)) @@ -466,9 +485,11 @@ access_keymap (map, idx, t_ok, noinherit, autoload) int noinherit; int autoload; { - int noprefix = 0; Lisp_Object val; + /* Qunbound in VAL means we have found no binding yet. */ + val = Qunbound; + /* 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. */ @@ -489,10 +510,10 @@ access_keymap (map, idx, t_ok, noinherit, autoload) /* See if there is a meta-map. If there's none, there is no binding for IDX, unless a default binding exists in MAP. */ Lisp_Object meta_map = - get_keymap_1 (access_keymap (map, meta_prefix_char, - t_ok, noinherit, autoload), - 0, autoload); - if (!NILP (meta_map)) + get_keymap (access_keymap (map, meta_prefix_char, + t_ok, noinherit, autoload), + 0, autoload); + if (CONSP (meta_map)) { map = meta_map; idx = make_number (XUINT (idx) & ~meta_modifier); @@ -507,13 +528,22 @@ access_keymap (map, idx, t_ok, noinherit, autoload) { Lisp_Object tail; - Lisp_Object t_binding; + /* t_binding is where we put a default binding that applies, + to use in case we do not find a binding specifically + for this key sequence. */ + + Lisp_Object t_binding; t_binding = Qnil; + + /* 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. */ + t_ok = t_ok ? 2 : 0; + for (tail = XCDR (map); (CONSP (tail) - || (tail = get_keymap_1 (tail, 0, autoload), - CONSP (tail))); + || (tail = get_keymap (tail, 0, autoload), CONSP (tail))); tail = XCDR (tail)) { Lisp_Object binding; @@ -524,53 +554,72 @@ access_keymap (map, idx, t_ok, noinherit, autoload) /* If NOINHERIT, stop finding prefix definitions after we pass a second occurrence of the `keymap' symbol. */ if (noinherit && EQ (binding, Qkeymap)) - noprefix = 1; + return Qnil; } else if (CONSP (binding)) { - if (EQ (XCAR (binding), idx)) + Lisp_Object key = XCAR (binding); + + 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)) { - val = XCDR (binding); - if (noprefix && KEYMAPP (val)) - return Qnil; - if (CONSP (val)) - fix_submap_inheritance (map, idx, val); - return get_keyelt (val, autoload); + t_binding = XCDR (binding); + t_ok = 1; } - if (t_ok && EQ (XCAR (binding), Qt)) - t_binding = XCDR (binding); } else if (VECTORP (binding)) { - if (NATNUMP (idx) && XFASTINT (idx) < XVECTOR (binding)->size) - { - val = XVECTOR (binding)->contents[XFASTINT (idx)]; - if (noprefix && KEYMAPP (val)) - return Qnil; - if (CONSP (val)) - fix_submap_inheritance (map, idx, val); - return get_keyelt (val, autoload); - } + if (NATNUMP (idx) && XFASTINT (idx) < ASIZE (binding)) + val = AREF (binding, XFASTINT (idx)); } else if (CHAR_TABLE_P (binding)) { /* Character codes with modifiers are not included in a char-table. All character codes without modifiers are included. */ - if (NATNUMP (idx) - && ! (XFASTINT (idx) - & (CHAR_ALT | CHAR_SUPER | CHAR_HYPER - | CHAR_SHIFT | CHAR_CTL | CHAR_META))) + if (NATNUMP (idx) && (XFASTINT (idx) & CHAR_MODIFIER_MASK) == 0) { val = Faref (binding, idx); - if (noprefix && KEYMAPP (val)) - return Qnil; - if (CONSP (val)) - fix_submap_inheritance (map, idx, val); - return get_keyelt (val, autoload); + /* `nil' has a special meaning for char-tables, so + we use something else to record an explicitly + unbound entry. */ + if (NILP (val)) + val = Qunbound; } } + /* If we found a binding, clean it up and return it. */ + if (!EQ (val, Qunbound)) + { + if (EQ (val, Qt)) + /* A Qt binding is just like an explicit nil binding + (i.e. it shadows any parent binding but not bindings in + keymaps of lower precedence). */ + val = Qnil; + val = get_keyelt (val, autoload); + if (KEYMAPP (val)) + fix_submap_inheritance (map, idx, val); + return val; + } QUIT; } @@ -622,18 +671,14 @@ get_keyelt (object, autoload) /* If there's a `:filter FILTER', apply FILTER to the menu-item's definition to get the real definition to - use. Temporarily inhibit GC while evaluating FILTER, - because not functions calling get_keyelt are prepared - for a GC. */ + use. */ for (; CONSP (tem) && CONSP (XCDR (tem)); tem = XCDR (tem)) - if (EQ (XCAR (tem), QCfilter)) + if (EQ (XCAR (tem), QCfilter) && autoload) { - int count = inhibit_garbage_collection (); Lisp_Object filter; filter = XCAR (XCDR (tem)); filter = list2 (filter, list2 (Qquote, object)); object = menu_item_eval_property (filter); - unbind_to (count, Qnil); break; } } @@ -666,8 +711,8 @@ get_keyelt (object, autoload) else { Lisp_Object map; - map = get_keymap_1 (Fcar_safe (object), 0, autoload); - return (NILP (map) ? object /* Invalid keymap */ + map = get_keymap (Fcar_safe (object), 0, autoload); + return (!CONSP (map) ? object /* Invalid keymap */ : access_keymap (map, Fcdr (object), 0, 0, autoload)); } } @@ -689,7 +734,7 @@ store_in_keymap (keymap, idx, def) && (EQ (XCAR (def), Qmenu_item) || STRINGP (XCAR (def)))) def = Fcons (XCAR (def), XCDR (def)); - if (!CONSP (keymap) || ! EQ (XCAR (keymap), Qkeymap)) + 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?), @@ -738,12 +783,13 @@ store_in_keymap (keymap, idx, def) /* Character codes with modifiers are not included in a char-table. All character codes without modifiers are included. */ - if (NATNUMP (idx) - && ! (XFASTINT (idx) - & (CHAR_ALT | CHAR_SUPER | CHAR_HYPER - | CHAR_SHIFT | CHAR_CTL | CHAR_META))) + if (NATNUMP (idx) && !(XFASTINT (idx) & CHAR_MODIFIER_MASK)) { - Faset (elt, idx, def); + Faset (elt, idx, + /* `nil' has a special meaning for char-tables, so + we use something else to record an explicitly + unbound entry. */ + NILP (def) ? Qt : def); return def; } insertion_point = tail; @@ -752,7 +798,7 @@ store_in_keymap (keymap, idx, def) { if (EQ (idx, XCAR (elt))) { - XCDR (elt) = def; + XSETCDR (elt, def); return def; } } @@ -769,34 +815,39 @@ 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. */ - XCDR (insertion_point) - = Fcons (Fcons (idx, def), XCDR (insertion_point)); + XSETCDR (insertion_point, + Fcons (Fcons (idx, def), XCDR (insertion_point))); } return def; } +EXFUN (Fcopy_keymap, 1); + void copy_keymap_1 (chartable, idx, elt) Lisp_Object chartable, idx, elt; { - if (!SYMBOLP (elt) && ! NILP (Fkeymapp (elt))) + if (CONSP (elt) && EQ (XCAR (elt), Qkeymap)) Faset (chartable, idx, Fcopy_keymap (elt)); } DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, - "Return a copy of the keymap KEYMAP.\n\ -The copy starts out with the same definitions of KEYMAP,\n\ -but changing either the copy or KEYMAP does not affect the other.\n\ -Any key definitions that are subkeymaps are recursively copied.\n\ -However, a key definition which is a symbol whose definition is a keymap\n\ -is not copied.") - (keymap) + doc: /* Return a copy of the keymap KEYMAP. +The copy starts out with the same definitions of KEYMAP, +but changing either the copy or KEYMAP does not affect the other. +Any key definitions that are subkeymaps are recursively copied. +However, a key definition which is a symbol whose definition is a keymap +is not copied. */) + (keymap) Lisp_Object keymap; { + /* FIXME: This doesn't properly copy menu-items in vectors. */ + /* FIXME: This also copies the parent keymap. */ + register Lisp_Object copy, tail; - copy = Fcopy_alist (get_keymap (keymap)); + copy = Fcopy_alist (get_keymap (keymap, 1, 0)); for (tail = copy; CONSP (tail); tail = XCDR (tail)) { @@ -808,7 +859,7 @@ is not copied.") Lisp_Object indices[3]; elt = Fcopy_sequence (elt); - XCAR (tail) = elt; + XSETCAR (tail, elt); map_char_table (copy_keymap_1, Qnil, elt, elt, 0, indices); } @@ -817,11 +868,10 @@ is not copied.") int i; elt = Fcopy_sequence (elt); - XCAR (tail) = elt; + XSETCAR (tail, elt); for (i = 0; i < ASIZE (elt); i++) - if (!SYMBOLP (AREF (elt, i)) - && ! NILP (Fkeymapp (AREF (elt, i)))) + if (CONSP (AREF (elt, i)) && EQ (XCAR (AREF (elt, i)), Qkeymap)) ASET (elt, i, Fcopy_keymap (AREF (elt, i))); } else if (CONSP (elt) && CONSP (XCDR (elt))) @@ -833,15 +883,15 @@ is not copied.") if (EQ (XCAR (tem),Qmenu_item)) { /* Copy cell with menu-item marker. */ - XCDR (elt) - = Fcons (XCAR (tem), XCDR (tem)); + XSETCDR (elt, + Fcons (XCAR (tem), XCDR (tem))); elt = XCDR (elt); tem = XCDR (elt); if (CONSP (tem)) { /* Copy cell with menu-item name. */ - XCDR (elt) - = Fcons (XCAR (tem), XCDR (tem)); + XSETCDR (elt, + Fcons (XCAR (tem), XCDR (tem))); elt = XCDR (elt); tem = XCDR (elt); }; @@ -849,16 +899,16 @@ is not copied.") { /* Copy cell with binding and if the binding is a keymap, copy that. */ - XCDR (elt) - = Fcons (XCAR (tem), XCDR (tem)); + XSETCDR (elt, + Fcons (XCAR (tem), XCDR (tem))); elt = XCDR (elt); tem = XCAR (elt); - if (!(SYMBOLP (tem) || NILP (Fkeymapp (tem)))) - XCAR (elt) = Fcopy_keymap (tem); + if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) + XSETCAR (elt, Fcopy_keymap (tem)); tem = XCDR (elt); if (CONSP (tem) && CONSP (XCAR (tem))) /* Delete cache for key equivalences. */ - XCDR (elt) = XCDR (tem); + XSETCDR (elt, XCDR (tem)); } } else @@ -869,15 +919,15 @@ is not copied.") if (STRINGP (XCAR (tem))) { /* Copy the cell, since copy-alist didn't go this deep. */ - XCDR (elt) - = Fcons (XCAR (tem), XCDR (tem)); + XSETCDR (elt, + Fcons (XCAR (tem), XCDR (tem))); elt = XCDR (elt); tem = XCDR (elt); /* Also skip the optional menu help string. */ if (CONSP (tem) && STRINGP (XCAR (tem))) { - XCDR (elt) - = Fcons (XCAR (tem), XCDR (tem)); + XSETCDR (elt, + Fcons (XCAR (tem), XCDR (tem))); elt = XCDR (elt); tem = XCDR (elt); } @@ -887,17 +937,17 @@ is not copied.") && CONSP (XCAR (tem)) && (NILP (XCAR (XCAR (tem))) || VECTORP (XCAR (XCAR (tem))))) - XCDR (elt) = XCDR (tem); + XSETCDR (elt, XCDR (tem)); } if (CONSP (elt) - && ! SYMBOLP (XCDR (elt)) - && ! NILP (Fkeymapp (XCDR (elt)))) - XCDR (elt) = Fcopy_keymap (XCDR (elt)); + && CONSP (XCDR (elt)) + && EQ (XCAR (XCDR (elt)), Qkeymap)) + XSETCDR (elt, Fcopy_keymap (XCDR (elt))); } } } - + return copy; } @@ -906,26 +956,28 @@ is not copied.") /* GC is possible in this function if it autoloads a keymap. */ DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0, - "Args KEYMAP, KEY, DEF. Define key sequence KEY, in KEYMAP, as DEF.\n\ -KEYMAP is a keymap. KEY is a string or a vector of symbols and characters\n\ -meaning a sequence of keystrokes and events.\n\ -Non-ASCII characters with codes above 127 (such as ISO Latin-1)\n\ -can be included if you use a vector.\n\ -DEF is anything that can be a key's definition:\n\ - nil (means key is undefined in this keymap),\n\ - a command (a Lisp function suitable for interactive calling)\n\ - a string (treated as a keyboard macro),\n\ - a keymap (to define a prefix key),\n\ - a symbol. When the key is looked up, the symbol will stand for its\n\ - function definition, which should at that time be one of the above,\n\ - or another symbol whose function definition is used, etc.\n\ - a cons (STRING . DEFN), meaning that DEFN is the definition\n\ - (DEFN should be a valid definition in its own right),\n\ - or a cons (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP.\n\ -\n\ -If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at\n\ -the front of KEYMAP.") - (keymap, key, def) + doc: /* Args KEYMAP, KEY, DEF. Define key sequence KEY, in KEYMAP, as DEF. +KEYMAP is a keymap. + +KEY is a string or a vector of symbols and characters meaning a +sequence of keystrokes and events. Non-ASCII characters with codes +above 127 (such as ISO Latin-1) can be included if you use a vector. + +DEF is anything that can be a key's definition: + nil (means key is undefined in this keymap), + a command (a Lisp function suitable for interactive calling) + a string (treated as a keyboard macro), + a keymap (to define a prefix key), + a symbol. When the key is looked up, the symbol will stand for its + function definition, which should at that time be one of the above, + 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 (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP. + +If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at +the front of KEYMAP. */) + (keymap, key, def) Lisp_Object keymap; Lisp_Object key; Lisp_Object def; @@ -938,15 +990,20 @@ the front of KEYMAP.") int length; struct gcpro gcpro1, gcpro2, gcpro3; - keymap = get_keymap_1 (keymap, 1, 1); + keymap = get_keymap (keymap, 1, 1); if (!VECTORP (key) && !STRINGP (key)) - key = wrong_type_argument (Qarrayp, key); + key = wrong_type_argument (Qarrayp, key); length = XFASTINT (Flength (key)); if (length == 0) return Qnil; + /* Check for valid [remap COMMAND] bindings. */ + if (VECTORP (key) && EQ (AREF (key, 0), Qremap) + && (length != 2 || !SYMBOLP (AREF (key, 1)))) + wrong_type_argument (Qvectorp, key); + if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); @@ -965,6 +1022,9 @@ the front of KEYMAP.") if (CONSP (c) && lucid_event_type_list_p (c)) c = Fevent_convert_list (c); + if (SYMBOLP (c)) + silly_event_symbol_error (c); + if (INTEGERP (c) && (XINT (c) & meta_bit) && !metized) @@ -981,8 +1041,8 @@ the front of KEYMAP.") idx++; } - if (! INTEGERP (c) && ! SYMBOLP (c) && ! CONSP (c)) - error ("Key sequence contains invalid events"); + if (!INTEGERP (c) && !SYMBOLP (c) && !CONSP (c)) + error ("Key sequence contains invalid event"); if (idx == length) RETURN_UNGCPRO (store_in_keymap (keymap, c, def)); @@ -993,8 +1053,8 @@ the front of KEYMAP.") if (NILP (cmd)) cmd = define_as_prefix (keymap, c); - keymap = get_keymap_1 (cmd, 0, 1); - if (NILP (keymap)) + keymap = get_keymap (cmd, 0, 1); + if (!CONSP (keymap)) /* We must use Fkey_description rather than just passing key to error; key might be a vector, not a string. */ error ("Key sequence %s uses invalid prefix characters", @@ -1002,25 +1062,38 @@ the front of KEYMAP.") } } -/* Value is number if KEY is too long; NIL if valid but has no definition. */ +/* This function may GC (it calls Fkey_binding). */ + +DEFUN ("remap-command", Fremap_command, Sremap_command, 1, 1, 0, + doc: /* Return the remapping for command COMMAND in current keymaps. +Returns nil if COMMAND is not remapped. */) + (command) + Lisp_Object command; +{ + /* This will GCPRO the command argument. */ + ASET (remap_command_vector, 1, command); + return Fkey_binding (remap_command_vector, Qnil, Qt); +} + +/* Value is number if KEY is too long; nil if valid but has no definition. */ /* GC is possible in this function if it autoloads a keymap. */ DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0, - "In keymap KEYMAP, look up key sequence KEY. Return the definition.\n\ -nil means undefined. See doc of `define-key' for kinds of definitions.\n\ -\n\ -A number as value means KEY is \"too long\";\n\ -that is, characters or symbols in it except for the last one\n\ -fail to be a valid sequence of prefix characters in KEYMAP.\n\ -The number is how many characters at the front of KEY\n\ -it takes to reach a non-prefix command.\n\ -\n\ -Normally, `lookup-key' ignores bindings for t, which act as default\n\ -bindings, used when nothing else in the keymap applies; this makes it\n\ -usable as a general function for probing keymaps. However, if the\n\ -third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will\n\ -recognize the default bindings, just as `read-key-sequence' does.") - (keymap, key, accept_default) + 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 number as value means KEY is "too long"; +that is, characters or symbols in it except for the last one +fail to be a valid sequence of prefix characters in KEYMAP. +The number is how many characters at the front of KEY +it takes to reach a non-prefix command. + +Normally, `lookup-key' ignores bindings for t, which act as default +bindings, used when nothing else in the keymap applies; this makes it +usable as a general function for probing keymaps. However, if the +third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will +recognize the default bindings, just as `read-key-sequence' does. */) + (keymap, key, accept_default) register Lisp_Object keymap; Lisp_Object key; Lisp_Object accept_default; @@ -1029,10 +1102,24 @@ recognize the default bindings, just as `read-key-sequence' does.") register Lisp_Object cmd; register Lisp_Object c; int length; - int t_ok = ! NILP (accept_default); + int t_ok = !NILP (accept_default); struct gcpro gcpro1; - keymap = get_keymap_1 (keymap, 1, 1); + keymap = get_keymap (keymap, 1, 1); + + /* Perform command remapping initiated by Fremap_command directly. + This is strictly not necessary, but it is faster and it returns + nil instead of 1 if KEYMAP doesn't contain command remappings. */ + if (EQ (key, remap_command_vector)) + { + /* KEY has format [remap COMMAND]. + Lookup `remap' in KEYMAP; result is nil or a keymap containing + command remappings. Then lookup COMMAND in that keymap. */ + if ((keymap = access_keymap (keymap, Qremap, t_ok, 0, 1), !NILP (keymap)) + && (keymap = get_keymap (keymap, 0, 1), CONSP (keymap))) + return access_keymap (keymap, AREF (key, 1), t_ok, 0, 1); + return Qnil; + } if (!VECTORP (key) && !STRINGP (key)) key = wrong_type_argument (Qarrayp, key); @@ -1055,12 +1142,17 @@ recognize the default bindings, just as `read-key-sequence' does.") if (XINT (c) & 0x80 && STRINGP (key)) XSETINT (c, (XINT (c) | meta_modifier) & ~0x80); + /* Allow string since binding for `menu-bar-select-buffer' + includes the buffer name in the key sequence. */ + if (!INTEGERP (c) && !SYMBOLP (c) && !CONSP (c) && !STRINGP (c)) + error ("Key sequence contains invalid event"); + cmd = access_keymap (keymap, c, t_ok, 0, 1); if (idx == length) RETURN_UNGCPRO (cmd); - keymap = get_keymap_1 (cmd, 0, 1); - if (NILP (keymap)) + keymap = get_keymap (cmd, 0, 1); + if (!CONSP (keymap)) RETURN_UNGCPRO (make_number (idx)); QUIT; @@ -1101,6 +1193,52 @@ append_key (key_sequence, key) return Fvconcat (2, args); } +/* Given a event type C which is a symbol, + signal an error if is a mistake such as RET or M-RET or C-DEL, etc. */ + +static void +silly_event_symbol_error (c) + Lisp_Object c; +{ + Lisp_Object parsed, base, name, assoc; + int modifiers; + + parsed = parse_modifiers (c); + modifiers = (int) XUINT (XCAR (XCDR (parsed))); + base = XCAR (parsed); + name = Fsymbol_name (base); + /* This alist includes elements such as ("RET" . "\\r"). */ + assoc = Fassoc (name, exclude_keys); + + if (! NILP (assoc)) + { + char new_mods[sizeof ("\\A-\\C-\\H-\\M-\\S-\\s-")]; + char *p = new_mods; + Lisp_Object keystring; + if (modifiers & alt_modifier) + { *p++ = '\\'; *p++ = 'A'; *p++ = '-'; } + if (modifiers & ctrl_modifier) + { *p++ = '\\'; *p++ = 'C'; *p++ = '-'; } + if (modifiers & hyper_modifier) + { *p++ = '\\'; *p++ = 'H'; *p++ = '-'; } + if (modifiers & meta_modifier) + { *p++ = '\\'; *p++ = 'M'; *p++ = '-'; } + if (modifiers & shift_modifier) + { *p++ = '\\'; *p++ = 'S'; *p++ = '-'; } + if (modifiers & super_modifier) + { *p++ = '\\'; *p++ = 's'; *p++ = '-'; } + *p = 0; + + c = reorder_modifiers (c); + keystring = concat2 (build_string (new_mods), XCDR (assoc)); + + error ((modifiers & ~meta_modifier + ? "To bind the key %s, use [?%s], not [%s]" + : "To bind the key %s, use \"%s\", not [%s]"), + XSYMBOL (c)->name->data, XSTRING (keystring)->data, + XSYMBOL (c)->name->data); + } +} /* Global, local, and minor mode keymap stuff. */ @@ -1151,8 +1289,8 @@ current_minor_maps (modeptr, mapptr) alist = XCDR (alist)) if ((assoc = XCAR (alist), CONSP (assoc)) && (var = XCAR (assoc), SYMBOLP (var)) - && (val = find_symbol_value (var), ! EQ (val, Qunbound)) - && ! NILP (val)) + && (val = find_symbol_value (var), !EQ (val, Qunbound)) + && !NILP (val)) { Lisp_Object temp; @@ -1163,23 +1301,25 @@ current_minor_maps (modeptr, mapptr) { val = assq_no_quit (var, lists[0]); if (!NILP (val)) - break; + continue; } if (i >= cmm_size) { Lisp_Object *newmodes, *newmaps; + /* Use malloc/realloc here. See the comment above + this function. */ if (cmm_maps) { BLOCK_INPUT; cmm_size *= 2; newmodes = (Lisp_Object *) realloc (cmm_modes, - cmm_size * sizeof (Lisp_Object)); + cmm_size * sizeof *newmodes); newmaps = (Lisp_Object *) realloc (cmm_maps, - cmm_size * sizeof (Lisp_Object)); + cmm_size * sizeof *newmaps); UNBLOCK_INPUT; } else @@ -1187,18 +1327,18 @@ current_minor_maps (modeptr, mapptr) BLOCK_INPUT; cmm_size = 30; newmodes - = (Lisp_Object *) xmalloc (cmm_size * sizeof (Lisp_Object)); + = (Lisp_Object *) malloc (cmm_size * sizeof *newmodes); newmaps - = (Lisp_Object *) xmalloc (cmm_size * sizeof (Lisp_Object)); + = (Lisp_Object *) malloc (cmm_size * sizeof *newmaps); UNBLOCK_INPUT; } - if (newmaps && newmodes) - { - cmm_modes = newmodes; - cmm_maps = newmaps; - } - else + if (newmodes) + cmm_modes = newmodes; + if (newmaps) + cmm_maps = newmaps; + + if (newmodes == NULL || newmaps == NULL) break; } @@ -1219,20 +1359,66 @@ current_minor_maps (modeptr, mapptr) return i; } +DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps, + 0, 1, 0, + doc: /* Return a list of the currently active keymaps. +OLP if non-nil indicates that we should obey `overriding-local-map' and +`overriding-terminal-local-map'. */) + (olp) + Lisp_Object olp; +{ + Lisp_Object keymaps = Fcons (current_global_map, Qnil); + + 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); + } + if (NILP (XCDR (keymaps))) + { + Lisp_Object local; + Lisp_Object *maps; + int nmaps, i; + + local = get_local_map (PT, current_buffer, Qlocal_map); + if (!NILP (local)) + keymaps = Fcons (local, keymaps); + + nmaps = current_minor_maps (0, &maps); + + for (i = --nmaps; i >= 0; i--) + if (!NILP (maps[i])) + keymaps = Fcons (maps[i], keymaps); + + local = get_local_map (PT, current_buffer, Qkeymap); + if (!NILP (local)) + keymaps = Fcons (local, keymaps); + } + + return keymaps; +} + /* GC is possible in this function if it autoloads a keymap. */ -DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 2, 0, - "Return the binding for command KEY in current keymaps.\n\ -KEY is a string or vector, a sequence of keystrokes.\n\ -The binding is probably a symbol with a function definition.\n\ -\n\ -Normally, `key-binding' ignores bindings for t, which act as default\n\ -bindings, used when nothing else in the keymap applies; this makes it\n\ -usable as a general function for probing keymaps. However, if the\n\ -optional second argument ACCEPT-DEFAULT is non-nil, `key-binding' does\n\ -recognize the default bindings, just as `read-key-sequence' does.") - (key, accept_default) - Lisp_Object key, accept_default; +DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0, + doc: /* Return the binding for command KEY in current keymaps. +KEY is a string or vector, a sequence of keystrokes. +The binding is probably a symbol with a function definition. + +Normally, `key-binding' ignores bindings for t, which act as default +bindings, used when nothing else in the keymap applies; this makes it +usable as a general function for probing keymaps. However, if the +optional second argument ACCEPT-DEFAULT is non-nil, `key-binding' does +recognize the default bindings, just as `read-key-sequence' does. + +Like the normal command loop, `key-binding' will remap the command +resulting from looking up KEY by looking up the command in the +currrent keymaps. However, if the optional third argument NO-REMAP +is non-nil, `key-binding' returns the unmapped command. */) + (key, accept_default, no_remap) + Lisp_Object key, accept_default, no_remap; { Lisp_Object *maps, value; int nmaps, i; @@ -1245,18 +1431,26 @@ recognize the default bindings, just as `read-key-sequence' does.") value = Flookup_key (current_kboard->Voverriding_terminal_local_map, key, accept_default); if (! NILP (value) && !INTEGERP (value)) - RETURN_UNGCPRO (value); + goto done; } else if (!NILP (Voverriding_local_map)) { value = Flookup_key (Voverriding_local_map, key, accept_default); if (! NILP (value) && !INTEGERP (value)) - RETURN_UNGCPRO (value); + goto done; } else { Lisp_Object local; + local = get_local_map (PT, current_buffer, Qkeymap); + if (! NILP (local)) + { + value = Flookup_key (local, key, accept_default); + if (! NILP (value) && !INTEGERP (value)) + goto done; + } + nmaps = current_minor_maps (0, &maps); /* Note that all these maps are GCPRO'd in the places where we found them. */ @@ -1266,45 +1460,48 @@ recognize the default bindings, just as `read-key-sequence' does.") { value = Flookup_key (maps[i], key, accept_default); if (! NILP (value) && !INTEGERP (value)) - RETURN_UNGCPRO (value); + goto done; } - local = get_local_map (PT, current_buffer, keymap); - if (! NILP (local)) - { - value = Flookup_key (local, key, accept_default); - if (! NILP (value) && !INTEGERP (value)) - RETURN_UNGCPRO (value); - } - - local = get_local_map (PT, current_buffer, local_map); - + local = get_local_map (PT, current_buffer, Qlocal_map); if (! NILP (local)) { value = Flookup_key (local, key, accept_default); if (! NILP (value) && !INTEGERP (value)) - RETURN_UNGCPRO (value); + goto done; } } value = Flookup_key (current_global_map, key, accept_default); + + done: UNGCPRO; - if (! NILP (value) && !INTEGERP (value)) - return value; + if (NILP (value) || INTEGERP (value)) + return Qnil; + + /* If the result of the ordinary keymap lookup is an interactive + command, look for a key binding (ie. remapping) for that command. */ + + if (NILP (no_remap) && SYMBOLP (value)) + { + Lisp_Object value1; + if (value1 = Fremap_command (value), !NILP (value1)) + value = value1; + } - return Qnil; + return value; } /* GC is possible in this function if it autoloads a keymap. */ DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 2, 0, - "Return the binding for command KEYS in current local keymap only.\n\ -KEYS is a string, a sequence of keystrokes.\n\ -The binding is probably a symbol with a function definition.\n\ -\n\ -If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\ -bindings; see the description of `lookup-key' for more details about this.") - (keys, accept_default) + doc: /* Return the binding for command KEYS in current local keymap only. +KEYS is a string, a sequence of keystrokes. +The binding is probably a symbol with a function definition. + +If optional argument ACCEPT-DEFAULT is non-nil, recognize default +bindings; see the description of `lookup-key' for more details about this. */) + (keys, accept_default) Lisp_Object keys, accept_default; { register Lisp_Object map; @@ -1317,15 +1514,15 @@ bindings; see the description of `lookup-key' for more details about this.") /* GC is possible in this function if it autoloads a keymap. */ DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 2, 0, - "Return the binding for command KEYS in current global keymap only.\n\ -KEYS is a string, a sequence of keystrokes.\n\ -The binding is probably a symbol with a function definition.\n\ -This function's return values are the same as those of lookup-key\n\ -\(which see).\n\ -\n\ -If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\ -bindings; see the description of `lookup-key' for more details about this.") - (keys, accept_default) + doc: /* Return the binding for command KEYS in current global keymap only. +KEYS is a string, 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). + +If optional argument ACCEPT-DEFAULT is non-nil, recognize default +bindings; see the description of `lookup-key' for more details about this. */) + (keys, accept_default) Lisp_Object keys, accept_default; { return Flookup_key (current_global_map, keys, accept_default); @@ -1334,18 +1531,18 @@ bindings; see the description of `lookup-key' for more details about this.") /* GC is possible in this function if it autoloads a keymap. */ DEFUN ("minor-mode-key-binding", Fminor_mode_key_binding, Sminor_mode_key_binding, 1, 2, 0, - "Find the visible minor mode bindings of KEY.\n\ -Return an alist of pairs (MODENAME . BINDING), where MODENAME is the\n\ -the symbol which names the minor mode binding KEY, and BINDING is\n\ -KEY's definition in that mode. In particular, if KEY has no\n\ -minor-mode bindings, return nil. If the first binding is a\n\ -non-prefix, all subsequent bindings will be omitted, since they would\n\ -be ignored. Similarly, the list doesn't include non-prefix bindings\n\ -that come after prefix bindings.\n\ -\n\ -If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\ -bindings; see the description of `lookup-key' for more details about this.") - (key, accept_default) + doc: /* Find the visible minor mode bindings of KEY. +Return an alist of pairs (MODENAME . BINDING), where MODENAME is the +the symbol which names the minor mode binding KEY, and BINDING is +KEY's definition in that mode. In particular, if KEY has no +minor-mode bindings, return nil. If the first binding is a +non-prefix, all subsequent bindings will be omitted, since they would +be ignored. Similarly, the list doesn't include non-prefix bindings +that come after prefix bindings. + +If optional argument ACCEPT-DEFAULT is non-nil, recognize default +bindings; see the description of `lookup-key' for more details about this. */) + (key, accept_default) Lisp_Object key, accept_default; { Lisp_Object *modes, *maps; @@ -1362,11 +1559,11 @@ bindings; see the description of `lookup-key' for more details about this.") GCPRO2 (key, binding); for (i = j = 0; i < nmaps; i++) - if (! NILP (maps[i]) - && ! NILP (binding = Flookup_key (maps[i], key, accept_default)) + if (!NILP (maps[i]) + && !NILP (binding = Flookup_key (maps[i], key, accept_default)) && !INTEGERP (binding)) { - if (! NILP (get_keymap (binding))) + if (KEYMAPP (binding)) maps[j++] = Fcons (modes[i], binding); else if (j == 0) RETURN_UNGCPRO (Fcons (Fcons (modes[i], binding), Qnil)); @@ -1377,14 +1574,14 @@ bindings; see the description of `lookup-key' for more details about this.") } DEFUN ("define-prefix-command", Fdefine_prefix_command, Sdefine_prefix_command, 1, 3, 0, - "Define COMMAND as a prefix command. COMMAND should be a symbol.\n\ -A new sparse keymap is stored as COMMAND's function definition and its value.\n\ -If a second optional argument MAPVAR is given, the map is stored as\n\ -its value instead of as COMMAND's value; but COMMAND is still defined\n\ -as a function.\n\ -The third optional argument NAME, if given, supplies a menu name\n\ -string for the map. This is required to use the keymap as a menu.") - (command, mapvar, name) + doc: /* Define COMMAND as a prefix command. COMMAND should be a symbol. +A new sparse keymap is stored as COMMAND's function definition and its value. +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. */) + (command, mapvar, name) Lisp_Object command, mapvar, name; { Lisp_Object map; @@ -1398,24 +1595,24 @@ string for the map. This is required to use the keymap as a menu.") } DEFUN ("use-global-map", Fuse_global_map, Suse_global_map, 1, 1, 0, - "Select KEYMAP as the global keymap.") - (keymap) + doc: /* Select KEYMAP as the global keymap. */) + (keymap) Lisp_Object keymap; { - keymap = get_keymap (keymap); + keymap = get_keymap (keymap, 1, 1); current_global_map = keymap; return Qnil; } DEFUN ("use-local-map", Fuse_local_map, Suse_local_map, 1, 1, 0, - "Select KEYMAP as the local keymap.\n\ -If KEYMAP is nil, that means no local keymap.") - (keymap) + doc: /* Select KEYMAP as the local keymap. +If KEYMAP is nil, that means no local keymap. */) + (keymap) Lisp_Object keymap; { if (!NILP (keymap)) - keymap = get_keymap (keymap); + keymap = get_keymap (keymap, 1, 1); current_buffer->keymap = keymap; @@ -1423,22 +1620,22 @@ If KEYMAP is nil, that means no local keymap.") } DEFUN ("current-local-map", Fcurrent_local_map, Scurrent_local_map, 0, 0, 0, - "Return current buffer's local keymap, or nil if it has none.") - () + doc: /* Return current buffer's local keymap, or nil if it has none. */) + () { return current_buffer->keymap; } DEFUN ("current-global-map", Fcurrent_global_map, Scurrent_global_map, 0, 0, 0, - "Return the current global keymap.") - () + doc: /* Return the current global keymap. */) + () { return current_global_map; } DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_maps, 0, 0, 0, - "Return a list of keymaps for the minor modes of the current buffer.") - () + doc: /* Return a list of keymaps for the minor modes of the current buffer. */) + () { Lisp_Object *maps; int nmaps = current_minor_maps (0, &maps); @@ -1448,19 +1645,76 @@ DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_ /* Help functions for describing and documenting keymaps. */ -static void accessible_keymaps_char_table (); + +static void +accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized) + Lisp_Object maps, tail, thisseq, key, cmd; + int is_metized; /* If 1, `key' is assumed to be INTEGERP. */ +{ + Lisp_Object tem; + + cmd = get_keyelt (cmd, 0); + if (NILP (cmd)) + return; + + tem = get_keymap (cmd, 0, 0); + if (CONSP (tem)) + { + cmd = tem; + /* Ignore keymaps that are already added to maps. */ + tem = Frassq (cmd, maps); + if (NILP (tem)) + { + /* If the last key in thisseq is meta-prefix-char, + turn it into a meta-ized keystroke. We know + that the event we're about to append is an + ascii keystroke since we're processing a + keymap table. */ + if (is_metized) + { + int meta_bit = meta_modifier; + Lisp_Object last = make_number (XINT (Flength (thisseq)) - 1); + tem = Fcopy_sequence (thisseq); + + Faset (tem, last, make_number (XINT (key) | meta_bit)); + + /* This new sequence is the same length as + thisseq, so stick it in the list right + after this one. */ + XSETCDR (tail, + Fcons (Fcons (tem, cmd), XCDR (tail))); + } + else + { + tem = append_key (thisseq, key); + nconc2 (tail, Fcons (Fcons (tem, cmd), Qnil)); + } + } + } +} + +static void +accessible_keymaps_char_table (args, index, cmd) + Lisp_Object args, index, cmd; +{ + accessible_keymaps_1 (index, cmd, + XCAR (XCAR (args)), + XCAR (XCDR (args)), + XCDR (XCDR (args)), + XINT (XCDR (XCAR (args)))); +} /* This function cannot GC. */ DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps, - 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).\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.") - (keymap, prefix) + 1, 2, 0, + doc: /* Find all keymaps accessible via prefix characters from KEYMAP. +Returns a list of elements of the form (KEYS . MAP), where the sequence +KEYS starting from KEYMAP gets you to MAP. These elements are ordered +so that the KEYS increase in length. The first element is ([] . KEYMAP). +An optional argument PREFIX, if non-nil, should be a key sequence; +then the value includes only maps for prefixes that start with PREFIX. */) + (keymap, prefix) Lisp_Object keymap, prefix; { Lisp_Object maps, good_maps, tail; @@ -1480,8 +1734,8 @@ then the value includes only maps for prefixes that start with PREFIX.") /* Flookup_key may give us nil, or a number, if the prefix is not defined in this particular map. It might even give us a list that isn't a keymap. */ - tem = get_keymap_1 (tem, 0, 0); - if (!NILP (tem)) + tem = get_keymap (tem, 0, 0); + if (CONSP (tem)) { /* Convert PREFIX to a vector now, so that later on we don't have to deal with the possibility of a string. */ @@ -1509,7 +1763,7 @@ then the value includes only maps for prefixes that start with PREFIX.") } else maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil), - get_keymap (keymap)), + get_keymap (keymap, 1, 0)), Qnil); /* For each map in the list maps, @@ -1547,7 +1801,8 @@ then the value includes only maps for prefixes that start with PREFIX.") Lisp_Object indices[3]; map_char_table (accessible_keymaps_char_table, Qnil, - elt, Fcons (maps, Fcons (tail, thisseq)), + elt, Fcons (Fcons (maps, make_number (is_metized)), + Fcons (tail, thisseq)), 0, indices); } else if (VECTORP (elt)) @@ -1556,89 +1811,15 @@ then the value includes only maps for prefixes that start with PREFIX.") /* Vector keymap. Scan all the elements. */ for (i = 0; i < ASIZE (elt); i++) - { - register Lisp_Object tem; - register Lisp_Object cmd; - - cmd = get_keyelt (AREF (elt, i), 0); - if (NILP (cmd)) continue; - tem = Fkeymapp (cmd); - if (!NILP (tem)) - { - cmd = get_keymap (cmd); - /* Ignore keymaps that are already added to maps. */ - tem = Frassq (cmd, maps); - if (NILP (tem)) - { - /* If the last key in thisseq is meta-prefix-char, - turn it into a meta-ized keystroke. We know - that the event we're about to append is an - ascii keystroke since we're processing a - keymap table. */ - if (is_metized) - { - int meta_bit = meta_modifier; - tem = Fcopy_sequence (thisseq); - - Faset (tem, last, make_number (i | meta_bit)); - - /* This new sequence is the same length as - thisseq, so stick it in the list right - after this one. */ - XCDR (tail) - = Fcons (Fcons (tem, cmd), XCDR (tail)); - } - else - { - tem = append_key (thisseq, make_number (i)); - nconc2 (tail, Fcons (Fcons (tem, cmd), Qnil)); - } - } - } - } + accessible_keymaps_1 (make_number (i), AREF (elt, i), + maps, tail, thisseq, is_metized); + } else if (CONSP (elt)) - { - register Lisp_Object cmd, tem; - - cmd = get_keyelt (XCDR (elt), 0); - /* Ignore definitions that aren't keymaps themselves. */ - tem = Fkeymapp (cmd); - if (!NILP (tem)) - { - /* Ignore keymaps that have been seen already. */ - cmd = get_keymap (cmd); - tem = Frassq (cmd, maps); - if (NILP (tem)) - { - /* Let elt be the event defined by this map entry. */ - elt = XCAR (elt); - - /* If the last key in thisseq is meta-prefix-char, and - this entry is a binding for an ascii keystroke, - turn it into a meta-ized keystroke. */ - if (is_metized && INTEGERP (elt)) - { - Lisp_Object element; - - element = thisseq; - tem = Fvconcat (1, &element); - XSETFASTINT (AREF (tem, XINT (last)), - XINT (elt) | meta_modifier); - - /* This new sequence is the same length as - thisseq, so stick it in the list right - after this one. */ - XCDR (tail) - = Fcons (Fcons (tem, cmd), XCDR (tail)); - } - else - nconc2 (tail, - Fcons (Fcons (append_key (thisseq, elt), cmd), - Qnil)); - } - } - } + accessible_keymaps_1 (XCAR (elt), XCDR (elt), + maps, tail, thisseq, + is_metized && INTEGERP (XCAR (elt))); + } } @@ -1672,44 +1853,16 @@ then the value includes only maps for prefixes that start with PREFIX.") return Fnreverse (good_maps); } - -static void -accessible_keymaps_char_table (args, index, cmd) - Lisp_Object args, index, cmd; -{ - Lisp_Object tem; - Lisp_Object maps, tail, thisseq; - - if (NILP (cmd)) - return; - - maps = XCAR (args); - tail = XCAR (XCDR (args)); - thisseq = XCDR (XCDR (args)); - - tem = Fkeymapp (cmd); - if (!NILP (tem)) - { - cmd = get_keymap (cmd); - /* Ignore keymaps that are already added to maps. */ - tem = Frassq (cmd, maps); - if (NILP (tem)) - { - tem = append_key (thisseq, index); - nconc2 (tail, Fcons (Fcons (tem, cmd), Qnil)); - } - } -} Lisp_Object Qsingle_key_description, Qkey_description; /* This function cannot GC. */ DEFUN ("key-description", Fkey_description, Skey_description, 1, 1, 0, - "Return a pretty description of key-sequence KEYS.\n\ -Control characters turn into \"C-foo\" sequences, meta into \"M-foo\"\n\ -spaces are put between sequence elements, etc.") - (keys) + doc: /* Return a pretty description of key-sequence KEYS. +Control characters turn into "C-foo" sequences, meta into "M-foo" +spaces are put between sequence elements, etc. */) + (keys) Lisp_Object keys; { int len = 0; @@ -1772,13 +1925,16 @@ spaces are put between sequence elements, etc.") else keys = wrong_type_argument (Qarrayp, keys); + if (len == 0) + return empty_string; return Fconcat (len * 2 - 1, args); } char * -push_key_description (c, p) +push_key_description (c, p, force_multibyte) register unsigned int c; register char *p; + int force_multibyte; { unsigned c2; @@ -1867,16 +2023,23 @@ push_key_description (c, p) } else if (c < 128 || (NILP (current_buffer->enable_multibyte_characters) - && SINGLE_BYTE_CHAR_P (c))) - *p++ = c; + && SINGLE_BYTE_CHAR_P (c) + && !force_multibyte)) + { + *p++ = c; + } else { - if (! NILP (current_buffer->enable_multibyte_characters)) - c = unibyte_char_to_multibyte (c); - - if (NILP (current_buffer->enable_multibyte_characters) - || SINGLE_BYTE_CHAR_P (c) - || ! char_valid_p (c, 0)) + int valid_p = SINGLE_BYTE_CHAR_P (c) || char_valid_p (c, 0); + + if (force_multibyte && valid_p) + { + 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) + || valid_p) { int bit_offset; *p++ = '\\'; @@ -1888,23 +2051,21 @@ push_key_description (c, p) } } else - { - p += CHAR_STRING (c, p); - } + p += CHAR_STRING (c, p); } - return p; + return p; } /* This function cannot GC. */ DEFUN ("single-key-description", Fsingle_key_description, Ssingle_key_description, 1, 2, 0, - "Return a pretty description of command character KEY.\n\ -Control characters turn into C-whatever, etc.\n\ -Optional argument NO-ANGLES non-nil means don't put angle brackets\n\ -around function keys and event symbols.") - (key, no_angles) + doc: /* Return a pretty description of command character KEY. +Control characters turn into C-whatever, etc. +Optional argument NO-ANGLES non-nil means don't put angle brackets +around function keys and event symbols. */) + (key, no_angles) Lisp_Object key, no_angles; { if (CONSP (key) && lucid_event_type_list_p (key)) @@ -1930,15 +2091,26 @@ around function keys and event symbols.") /* Handle a generic character. */ Lisp_Object name; name = CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX); - CHECK_STRING (name, 0); + CHECK_STRING (name); return concat2 (build_string ("Character set "), name); } else { - char tem[KEY_DESCRIPTION_SIZE]; - - *push_key_description (XUINT (key), tem) = 0; - return build_string (tem); + 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; } } else if (SYMBOLP (key)) /* Function key or event-symbol */ @@ -1983,22 +2155,22 @@ push_text_char_description (c, p) } else *p++ = c; - return p; + return p; } /* This function cannot GC. */ DEFUN ("text-char-description", Ftext_char_description, Stext_char_description, 1, 1, 0, - "Return a pretty description of file-character CHARACTER.\n\ -Control characters turn into \"^char\", etc.") - (character) + doc: /* Return a pretty description of file-character CHARACTER. +Control characters turn into "^char", etc. */) + (character) Lisp_Object character; { /* Currently MAX_MULTIBYTE_LENGTH is 4 (< 6). */ unsigned char str[6]; int c; - CHECK_NUMBER (character, 0); + CHECK_NUMBER (character); c = XINT (character); if (!SINGLE_BYTE_CHAR_P (c)) @@ -2040,18 +2212,10 @@ ascii_sequence_p (seq) /* where-is - finding a command in a set of keymaps. */ +static Lisp_Object where_is_internal (); static Lisp_Object where_is_internal_1 (); static void where_is_internal_2 (); -static INLINE int -menu_item_p (item) - Lisp_Object item; -{ - return (CONSP (item) - && (EQ (XCAR (item),Qmenu_item) - || STRINGP (XCAR (item)))); -} - /* 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. */ @@ -2073,9 +2237,9 @@ shadow_lookup (shadow, key, flag) /* This function can GC if Flookup_key autoloads any keymaps. */ static Lisp_Object -where_is_internal (definition, keymaps, firstonly, noindirect) +where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) Lisp_Object definition, keymaps; - Lisp_Object firstonly, noindirect; + Lisp_Object firstonly, noindirect, no_remap; { Lisp_Object maps = Qnil; Lisp_Object found, sequences; @@ -2083,11 +2247,21 @@ where_is_internal (definition, keymaps, firstonly, noindirect) /* 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 = Fremap_command (definition), !NILP (tem)) + return Qnil; + } + found = keymaps; while (CONSP (found)) { maps = - nconc2 (maps, Faccessible_keymaps (get_keymap (XCAR (found)), Qnil)); + nconc2 (maps, + Faccessible_keymaps (get_keymap (XCAR (found), 1, 0), Qnil)); found = XCDR (found); } @@ -2112,14 +2286,14 @@ where_is_internal (definition, keymaps, firstonly, noindirect) last_is_meta = (XINT (last) >= 0 && EQ (Faref (this, last), meta_prefix_char)); - if (nomenus && XINT (last) >= 0) - { /* If no menu entries should be returned, skip over the - keymaps bound to `menu-bar' and `tool-bar'. */ - Lisp_Object tem = Faref (this, 0); - if (EQ (tem, Qmenu_bar) || EQ (tem, Qtool_bar)) - continue; - } - + /* if (nomenus && !ascii_sequence_p (this)) */ + if (nomenus && XINT (last) >= 0 + && !INTEGERP (Faref (this, make_number (0)))) + /* If no menu entries should be returned, skip over the + keymaps bound to `menu-bar' and `tool-bar' and other + non-ascii prefixes like `C-down-mouse-2'. */ + continue; + QUIT; while (CONSP (map)) @@ -2187,11 +2361,36 @@ where_is_internal (definition, keymaps, firstonly, noindirect) } - for (; ! NILP (sequences); sequences = XCDR (sequences)) + while (!NILP (sequences)) { - Lisp_Object sequence; + Lisp_Object sequence, remapped, function; sequence = XCAR (sequences); + sequences = XCDR (sequences); + + /* If the current sequence is a command remapping with + format [remap COMMAND], find the key sequences + which run COMMAND, and use those sequences instead. */ + remapped = Qnil; + if (NILP (no_remap) + && VECTORP (sequence) && XVECTOR (sequence)->size == 2 + && EQ (AREF (sequence, 0), Qremap) + && (function = AREF (sequence, 1), SYMBOLP (function))) + { + Lisp_Object remapped1; + + remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); + if (CONSP (remapped1)) + { + /* Verify that this key binding actually maps to the + remapped command (see below). */ + if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) + continue; + sequence = XCAR (remapped1); + remapped = XCDR (remapped1); + goto record_sequence; + } + } /* Verify that this key binding is not shadowed by another binding for the same key, before we say it exists. @@ -2205,6 +2404,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect) if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) continue; + record_sequence: /* It is a true unshadowed match. Record it, unless it's already been seen (as could happen when inheriting keymaps). */ if (NILP (Fmember (sequence, found))) @@ -2216,8 +2416,15 @@ where_is_internal (definition, keymaps, firstonly, noindirect) we find. */ if (EQ (firstonly, Qnon_ascii)) RETURN_UNGCPRO (sequence); - else if (! NILP (firstonly) && ascii_sequence_p (sequence)) + else if (!NILP (firstonly) && ascii_sequence_p (sequence)) RETURN_UNGCPRO (sequence); + + if (CONSP (remapped)) + { + sequence = XCAR (remapped); + remapped = XCDR (remapped); + goto record_sequence; + } } } } @@ -2229,54 +2436,57 @@ where_is_internal (definition, keymaps, firstonly, noindirect) /* firstonly may have been t, but we may have gone all the way through the keymaps without finding an all-ASCII key sequence. So just return the best we could find. */ - if (! NILP (firstonly)) + if (!NILP (firstonly)) return Fcar (found); return found; } -DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 4, 0, - "Return list of keys that invoke DEFINITION.\n\ -If KEYMAP is non-nil, search only KEYMAP and the global keymap.\n\ -If KEYMAP is nil, search all the currently active keymaps.\n\ -If KEYMAP is a list of keymaps, search only those keymaps.\n\ -\n\ -If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found,\n\ -rather than a list of all possible key sequences.\n\ -If FIRSTONLY is the symbol `non-ascii', return the first binding found,\n\ -no matter what it is.\n\ -If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters,\n\ -and entirely reject menu bindings.\n\ -\n\ -If optional 4th arg NOINDIRECT is non-nil, don't follow indirections\n\ -to other keymaps or slots. This makes it possible to search for an\n\ -indirect definition itself.") - (definition, xkeymap, firstonly, noindirect) - Lisp_Object definition, xkeymap; - Lisp_Object firstonly, noindirect; +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 nil, search all the currently active keymaps. +If KEYMAP is a list of keymaps, search only those keymaps. + +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 optional 4th arg NOINDIRECT is non-nil, don't follow indirections +to other keymaps or slots. This makes it possible to search for an +indirect definition itself. + +If optional 5th arg NO-REMAP is non-nil, don't search for key sequences +that invoke a command which is remapped to DEFINITION, but include the +remapped command in the returned list. */) + (definition, keymap, firstonly, noindirect, no_remap) + Lisp_Object definition, keymap; + Lisp_Object firstonly, noindirect, no_remap; { Lisp_Object sequences, keymaps; - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; /* 1 means ignore all menu bindings entirely. */ int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); + Lisp_Object result; /* Find the relevant keymaps. */ - if (CONSP (xkeymap) && KEYMAPP (XCAR (xkeymap))) - keymaps = xkeymap; - else if (! NILP (xkeymap)) - keymaps = Fcons (xkeymap, Fcons (current_global_map, Qnil)); + if (CONSP (keymap) && KEYMAPP (XCAR (keymap))) + keymaps = keymap; + else if (!NILP (keymap)) + keymaps = Fcons (keymap, Fcons (current_global_map, Qnil)); else - keymaps = - Fdelq (Qnil, - nconc2 (Fcurrent_minor_mode_maps (), - Fcons (get_local_map (PT, current_buffer, keymap), - Fcons (get_local_map (PT, current_buffer, local_map), - Fcons (current_global_map, Qnil))))); + keymaps = Fcurrent_active_maps (Qnil); /* Only use caching for the menubar (i.e. called with (def nil t nil). - We don't really need to check `xkeymap'. */ - if (nomenus && NILP (noindirect) && NILP (xkeymap)) + We don't really need to check `keymap'. */ + if (nomenus && NILP (noindirect) && NILP (keymap)) { + Lisp_Object *defns; + int i, j, n; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + /* Check heuristic-consistency of the cache. */ if (NILP (Fequal (keymaps, where_is_cache_keymaps))) where_is_cache = Qnil; @@ -2289,31 +2499,48 @@ indirect definition itself.") where_is_cache_keymaps = Qt; /* Fill in the cache. */ - GCPRO4 (definition, keymaps, firstonly, noindirect); - where_is_internal (definition, keymaps, firstonly, noindirect); + GCPRO5 (definition, keymaps, firstonly, noindirect, no_remap); + where_is_internal (definition, keymaps, firstonly, noindirect, no_remap); UNGCPRO; where_is_cache_keymaps = keymaps; } + /* We want to process definitions from the last to the first. + Instead of consing, copy definitions to a vector and step + over that vector. */ sequences = Fgethash (definition, where_is_cache, Qnil); - /* Verify that the key bindings are not shadowed. */ - /* key-binding can GC. */ - GCPRO3 (definition, sequences, keymaps); - for (sequences = Fnreverse (sequences); - CONSP (sequences); - sequences = XCDR (sequences)) - if (EQ (shadow_lookup (keymaps, XCAR (sequences), Qnil), definition)) - RETURN_UNGCPRO (XCAR (sequences)); - RETURN_UNGCPRO (Qnil); + n = XINT (Flength (sequences)); + defns = (Lisp_Object *) alloca (n * sizeof *defns); + for (i = 0; CONSP (sequences); sequences = XCDR (sequences)) + defns[i++] = XCAR (sequences); + + /* Verify that the key bindings are not shadowed. Note that + the following can GC. */ + GCPRO2 (definition, keymaps); + result = Qnil; + j = -1; + for (i = n - 1; i >= 0; --i) + if (EQ (shadow_lookup (keymaps, defns[i], Qnil), definition)) + { + if (ascii_sequence_p (defns[i])) + break; + else if (j < 0) + j = i; + } + + result = i >= 0 ? defns[i] : (j >= 0 ? defns[j] : Qnil); + UNGCPRO; } else { /* Kill the cache so that where_is_internal_1 doesn't think we're filling it up. */ where_is_cache = Qnil; - return where_is_internal (definition, keymaps, firstonly, noindirect); + result = where_is_internal (definition, keymaps, firstonly, noindirect, no_remap); } + + return result; } /* This is the function that Fwhere_is_internal calls using map_char_table. @@ -2349,7 +2576,7 @@ where_is_internal_2 (args, key, binding) this, last, nomenus, last_is_meta); if (!NILP (sequence)) - XCDR (XCAR (args)) = Fcons (sequence, result); + XSETCDR (XCAR (args), Fcons (sequence, result)); UNGCPRO; } @@ -2365,10 +2592,6 @@ where_is_internal_1 (binding, key, definition, noindirect, this, last, { Lisp_Object sequence; - /* Skip left-over menu-items. - These can appear in a keymap bound to a mouse click, for example. */ - if (nomenus && menu_item_p (binding)) - return Qnil; /* Search through indirections unless that's not wanted. */ if (NILP (noindirect)) binding = get_keyelt (binding, 0); @@ -2403,33 +2626,19 @@ where_is_internal_1 (binding, key, definition, noindirect, this, last, /* describe-bindings - summarizing all the bindings in a set of keymaps. */ -DEFUN ("describe-bindings-internal", Fdescribe_bindings_internal, Sdescribe_bindings_internal, 0, 2, "", - "Show a list of all defined keys, and their definitions.\n\ -We put that list in a buffer, and display the buffer.\n\ -\n\ -The optional argument MENUS, if non-nil, says to mention menu bindings.\n\ -\(Ordinarily these are omitted from the output.)\n\ -The optional argument PREFIX, if non-nil, should be a key sequence;\n\ -then we display only bindings that start with that prefix.") - (menus, prefix) - Lisp_Object menus, prefix; -{ - register Lisp_Object thisbuf; - XSETBUFFER (thisbuf, current_buffer); - internal_with_output_to_temp_buffer ("*Help*", - describe_buffer_bindings, - list3 (thisbuf, prefix, menus)); - return Qnil; -} - -/* ARG is (BUFFER PREFIX MENU-FLAG). */ - -static Lisp_Object -describe_buffer_bindings (arg) - Lisp_Object arg; +DEFUN ("describe-buffer-bindings", Fdescribe_buffer_bindings, Sdescribe_buffer_bindings, 1, 3, 0, + doc: /* Insert the list of all defined keys and their definitions. +The list is inserted in the current buffer, while the bindings are +looked up in BUFFER. +The optional argument PREFIX, if non-nil, should be a key sequence; +then we display only bindings that start with that prefix. +The optional argument MENUS, if non-nil, says to mention menu bindings. +\(Ordinarily these are omitted from the output.) */) + (buffer, prefix, menus) + Lisp_Object buffer, prefix, menus; { - Lisp_Object descbuf, prefix, shadow; - int nomenu; + Lisp_Object outbuf, shadow; + int nomenu = NILP (menus); register Lisp_Object start1; struct gcpro gcpro1; @@ -2439,16 +2648,10 @@ Keyboard translations:\n\n\ You type Translation\n\ -------- -----------\n"; - descbuf = XCAR (arg); - arg = XCDR (arg); - prefix = XCAR (arg); - arg = XCDR (arg); - nomenu = NILP (XCAR (arg)); - shadow = Qnil; GCPRO1 (shadow); - Fset_buffer (Vstandard_output); + outbuf = Fcurrent_buffer (); /* Report on alternates for keys. */ if (STRINGP (Vkeyboard_translate_table) && !NILP (prefix)) @@ -2469,10 +2672,10 @@ You type Translation\n\ alternate_heading = 0; } - bufend = push_key_description (translate[c], buf); + bufend = push_key_description (translate[c], buf, 1); insert (buf, bufend - buf); Findent_to (make_number (16), make_number (1)); - bufend = push_key_description (c, buf); + bufend = push_key_description (c, buf, 1); insert (buf, bufend - buf); insert ("\n", 1); @@ -2485,64 +2688,85 @@ You type Translation\n\ describe_map_tree (Vkey_translation_map, 0, Qnil, prefix, "Key translations", nomenu, 1, 0); - { - int i, nmaps; - Lisp_Object *modes, *maps; - - /* Temporarily switch to descbuf, so that we can get that buffer's - minor modes correctly. */ - Fset_buffer (descbuf); - - if (!NILP (current_kboard->Voverriding_terminal_local_map) - || !NILP (Voverriding_local_map)) - nmaps = 0; - else - nmaps = current_minor_maps (&modes, &maps); - Fset_buffer (Vstandard_output); - - /* Print the minor mode maps. */ - for (i = 0; i < nmaps; i++) - { - /* The 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, *p; - - if (!SYMBOLP (modes[i])) - abort(); - - p = title = (char *) alloca (42 + XSYMBOL (modes[i])->name->size); - *p++ = '\f'; - *p++ = '\n'; - *p++ = '`'; - bcopy (XSYMBOL (modes[i])->name->data, p, - XSYMBOL (modes[i])->name->size); - p += XSYMBOL (modes[i])->name->size; - *p++ = '\''; - bcopy (" Minor Mode Bindings", p, sizeof (" Minor Mode Bindings") - 1); - p += sizeof (" Minor Mode Bindings") - 1; - *p = 0; - - describe_map_tree (maps[i], 1, shadow, prefix, title, nomenu, 0, 0); - shadow = Fcons (maps[i], shadow); - } - } /* Print the (major mode) local map. */ + start1 = Qnil; if (!NILP (current_kboard->Voverriding_terminal_local_map)) start1 = current_kboard->Voverriding_terminal_local_map; else if (!NILP (Voverriding_local_map)) start1 = Voverriding_local_map; - else - start1 = XBUFFER (descbuf)->keymap; if (!NILP (start1)) { describe_map_tree (start1, 1, shadow, prefix, - "\f\nMajor Mode Bindings", nomenu, 0, 0); + "\f\nOverriding Bindings", nomenu, 0, 0); shadow = Fcons (start1, shadow); } + else + { + /* Print the minor mode and major mode keymaps. */ + int i, nmaps; + Lisp_Object *modes, *maps; + + /* Temporarily switch to `buffer', so that we can get that buffer's + minor modes correctly. */ + Fset_buffer (buffer); + + nmaps = current_minor_maps (&modes, &maps); + Fset_buffer (outbuf); + + start1 = get_local_map (BUF_PT (XBUFFER (buffer)), + XBUFFER (buffer), Qkeymap); + if (!NILP (start1)) + { + describe_map_tree (start1, 1, shadow, prefix, + "\f\n`keymap' Property Bindings", nomenu, 0, 0); + shadow = Fcons (start1, shadow); + } + + /* Print the minor mode maps. */ + for (i = 0; i < nmaps; i++) + { + /* The 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, *p; + + if (!SYMBOLP (modes[i])) + abort(); + + p = title = (char *) alloca (42 + XSYMBOL (modes[i])->name->size); + *p++ = '\f'; + *p++ = '\n'; + *p++ = '`'; + bcopy (XSYMBOL (modes[i])->name->data, p, + XSYMBOL (modes[i])->name->size); + p += XSYMBOL (modes[i])->name->size; + *p++ = '\''; + bcopy (" Minor Mode Bindings", p, sizeof (" Minor Mode Bindings") - 1); + p += sizeof (" Minor Mode Bindings") - 1; + *p = 0; + + describe_map_tree (maps[i], 1, shadow, prefix, title, nomenu, 0, 0); + shadow = Fcons (maps[i], shadow); + } + + start1 = get_local_map (BUF_PT (XBUFFER (buffer)), + XBUFFER (buffer), Qlocal_map); + if (!NILP (start1)) + { + if (EQ (start1, XBUFFER (buffer)->keymap)) + describe_map_tree (start1, 1, shadow, prefix, + "\f\nMajor Mode Bindings", nomenu, 0, 0); + else + describe_map_tree (start1, 1, shadow, prefix, + "\f\n`local-map' Property Bindings", + nomenu, 0, 0); + + shadow = Fcons (start1, shadow); + } + } describe_map_tree (current_global_map, 1, shadow, prefix, "\f\nGlobal Bindings", nomenu, 0, 1); @@ -2552,8 +2776,6 @@ You type Translation\n\ describe_map_tree (Vfunction_key_map, 0, Qnil, prefix, "\f\nFunction key map translations", nomenu, 1, 0); - call0 (intern ("help-mode")); - Fset_buffer (descbuf); UNGCPRO; return Qnil; } @@ -2667,7 +2889,7 @@ key binding\n\ /* 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))) + if (!NILP (shmap) && !KEYMAPP (shmap)) goto skip; if (!NILP (shmap)) @@ -2675,11 +2897,11 @@ key binding\n\ } /* Maps we have already listed in this loop shadow this map. */ - for (tail = orig_maps; ! EQ (tail, maps); tail = XCDR (tail)) + for (tail = orig_maps; !EQ (tail, maps); tail = XCDR (tail)) { Lisp_Object tem; tem = Fequal (Fcar (XCAR (tail)), prefix); - if (! NILP (tem)) + if (!NILP (tem)) sub_shadows = Fcons (XCDR (XCAR (tail)), sub_shadows); } @@ -2699,8 +2921,8 @@ key binding\n\ static int previous_description_column; static void -describe_command (definition) - Lisp_Object definition; +describe_command (definition, args) + Lisp_Object definition, args; { register Lisp_Object tem1; int column = current_column (); @@ -2729,19 +2951,15 @@ describe_command (definition) } else if (STRINGP (definition) || VECTORP (definition)) insert_string ("Keyboard Macro\n"); + else if (KEYMAPP (definition)) + insert_string ("Prefix Command\n"); else - { - tem1 = Fkeymapp (definition); - if (!NILP (tem1)) - insert_string ("Prefix Command\n"); - else - insert_string ("??\n"); - } + insert_string ("??\n"); } static void -describe_translation (definition) - Lisp_Object definition; +describe_translation (definition, args) + Lisp_Object definition, args; { register Lisp_Object tem1; @@ -2758,14 +2976,10 @@ describe_translation (definition) insert1 (Fkey_description (definition)); insert_string ("\n"); } + else if (KEYMAPP (definition)) + insert_string ("Prefix Command\n"); else - { - tem1 = Fkeymapp (definition); - if (!NILP (tem1)) - insert_string ("Prefix Command\n"); - else - insert_string ("??\n"); - } + insert_string ("??\n"); } /* Describe the contents of map MAP, assuming that this map itself is @@ -2776,7 +2990,7 @@ static void describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) register Lisp_Object map; Lisp_Object keys; - void (*elt_describer) P_ ((Lisp_Object)); + void (*elt_describer) P_ ((Lisp_Object, Lisp_Object)); int partial; Lisp_Object shadow; Lisp_Object *seen; @@ -2819,7 +3033,7 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) if (VECTORP (XCAR (tail)) || CHAR_TABLE_P (XCAR (tail))) describe_vector (XCAR (tail), - elt_prefix, elt_describer, partial, shadow, map, + elt_prefix, Qnil, elt_describer, partial, shadow, map, (int *)0, 0); else if (CONSP (XCAR (tail))) { @@ -2827,7 +3041,7 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) /* Ignore bindings whose "keys" are not really valid events. (We get these in the frames and buffers menu.) */ - if (! (SYMBOLP (event) || INTEGERP (event))) + if (!(SYMBOLP (event) || INTEGERP (event))) continue; if (nomenu && EQ (event, Qmenu_bar)) @@ -2855,7 +3069,7 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) } tem = Flookup_key (map, kludge, Qt); - if (! EQ (tem, definition)) continue; + if (!EQ (tem, definition)) continue; if (first) { @@ -2873,7 +3087,7 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) /* Print a description of the definition of this character. elt_describer will take care of spacing out far enough for alignment purposes. */ - (*elt_describer) (definition); + (*elt_describer) (definition, Qnil); } else if (EQ (XCAR (tail), Qkeymap)) { @@ -2891,25 +3105,26 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) } static void -describe_vector_princ (elt) - Lisp_Object elt; +describe_vector_princ (elt, fun) + Lisp_Object elt, fun; { Findent_to (make_number (16), make_number (1)); - Fprinc (elt, Qnil); + call1 (fun, elt); Fterpri (Qnil); } -DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 1, 0, - "Insert a description of contents of VECTOR.\n\ -This is text showing the elements of vector matched against indices.") - (vector) - Lisp_Object vector; +DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0, + doc: /* Insert a description of contents of VECTOR. +This is text showing the elements of vector matched against indices. */) + (vector, describer) + Lisp_Object vector, describer; { int count = specpdl_ptr - specpdl; - + if (NILP (describer)) + describer = intern ("princ"); specbind (Qstandard_output, Fcurrent_buffer ()); - CHECK_VECTOR_OR_CHAR_TABLE (vector, 0); - describe_vector (vector, Qnil, describe_vector_princ, 0, + CHECK_VECTOR_OR_CHAR_TABLE (vector); + describe_vector (vector, Qnil, describer, describe_vector_princ, 0, Qnil, Qnil, (int *)0, 0); return unbind_to (count, Qnil); @@ -2943,15 +3158,17 @@ This is text showing the elements of vector matched against indices.") 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. */ + and CHAR_TABLE_DEPTH says how many levels down we have gone. + + ARGS is simply passed as the second argument to ELT_DESCRIBER. */ void -describe_vector (vector, elt_prefix, elt_describer, +describe_vector (vector, elt_prefix, args, elt_describer, partial, shadow, entire_map, indices, char_table_depth) register Lisp_Object vector; - Lisp_Object elt_prefix; - void (*elt_describer) P_ ((Lisp_Object)); + Lisp_Object elt_prefix, args; + void (*elt_describer) P_ ((Lisp_Object, Lisp_Object)); int partial; Lisp_Object shadow; Lisp_Object entire_map; @@ -3044,7 +3261,7 @@ describe_vector (vector, elt_prefix, elt_describer, else definition = get_keyelt (AREF (vector, i), 0); - if (NILP (definition)) continue; + if (NILP (definition)) continue; /* Don't mention suppressed commands. */ if (SYMBOLP (definition) && partial) @@ -3097,7 +3314,7 @@ describe_vector (vector, elt_prefix, elt_describer, ASET (kludge, 0, make_number (character)); tem = Flookup_key (entire_map, kludge, Qt); - if (! EQ (tem, definition)) + if (!EQ (tem, definition)) continue; } @@ -3160,7 +3377,7 @@ describe_vector (vector, elt_prefix, elt_describer, if (CHAR_TABLE_P (vector) && SUB_CHAR_TABLE_P (definition)) { insert ("\n", 1); - describe_vector (definition, elt_prefix, elt_describer, + describe_vector (definition, elt_prefix, args, elt_describer, partial, shadow, entire_map, indices, char_table_depth + 1); continue; @@ -3233,7 +3450,7 @@ describe_vector (vector, elt_prefix, elt_describer, /* Print a description of the definition of this character. elt_describer will take care of spacing out far enough for alignment purposes. */ - (*elt_describer) (definition); + (*elt_describer) (definition, args); } /* For (sub) char-table, print `defalt' slot at last. */ @@ -3241,7 +3458,7 @@ describe_vector (vector, elt_prefix, elt_describer, { insert (" ", char_table_depth * 2); insert_string ("<>"); - (*elt_describer) (XCHAR_TABLE (vector)->defalt); + (*elt_describer) (XCHAR_TABLE (vector)->defalt, args); } UNGCPRO; @@ -3265,15 +3482,15 @@ apropos_accum (symbol, string) } DEFUN ("apropos-internal", Fapropos_internal, Sapropos_internal, 1, 2, 0, - "Show all symbols whose names contain match for REGEXP.\n\ -If optional 2nd arg PREDICATE is non-nil, (funcall PREDICATE SYMBOL) is done\n\ -for each symbol and a symbol is mentioned only if that returns non-nil.\n\ -Return list of symbols found.") - (regexp, predicate) + doc: /* Show all symbols whose names contain match for REGEXP. +If optional 2nd arg PREDICATE is non-nil, (funcall PREDICATE SYMBOL) is done +for each symbol and a symbol is mentioned only if that returns non-nil. +Return list of symbols found. */) + (regexp, predicate) Lisp_Object regexp, predicate; { struct gcpro gcpro1, gcpro2; - CHECK_STRING (regexp, 0); + CHECK_STRING (regexp); apropos_predicate = predicate; GCPRO2 (apropos_predicate, apropos_accumulate); apropos_accumulate = Qnil; @@ -3312,68 +3529,81 @@ syms_of_keymap () Fset (intern ("ctl-x-map"), control_x_map); Ffset (intern ("Control-X-prefix"), control_x_map); + exclude_keys + = Fcons (Fcons (build_string ("DEL"), build_string ("\\d")), + Fcons (Fcons (build_string ("TAB"), build_string ("\\t")), + Fcons (Fcons (build_string ("RET"), build_string ("\\r")), + Fcons (Fcons (build_string ("ESC"), build_string ("\\e")), + Fcons (Fcons (build_string ("SPC"), build_string (" ")), + Qnil))))); + staticpro (&exclude_keys); + DEFVAR_LISP ("define-key-rebound-commands", &Vdefine_key_rebound_commands, - "List of commands given new key bindings recently.\n\ -This is used for internal purposes during Emacs startup;\n\ -don't alter it yourself."); + doc: /* List of commands given new key bindings recently. +This is used for internal purposes during Emacs startup; +don't alter it yourself. */); Vdefine_key_rebound_commands = Qt; DEFVAR_LISP ("minibuffer-local-map", &Vminibuffer_local_map, - "Default keymap to use when reading from the minibuffer."); + doc: /* Default keymap to use when reading from the minibuffer. */); Vminibuffer_local_map = Fmake_sparse_keymap (Qnil); DEFVAR_LISP ("minibuffer-local-ns-map", &Vminibuffer_local_ns_map, - "Local keymap for the minibuffer when spaces are not allowed."); + doc: /* Local keymap for the minibuffer when spaces are not allowed. */); Vminibuffer_local_ns_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_ns_map, Vminibuffer_local_map); DEFVAR_LISP ("minibuffer-local-completion-map", &Vminibuffer_local_completion_map, - "Local keymap for minibuffer input with completion."); + doc: /* Local keymap for minibuffer input with completion. */); Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_completion_map, Vminibuffer_local_map); DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map, - "Local keymap for minibuffer input with completion, for exact match."); + doc: /* Local keymap for minibuffer input with completion, for exact match. */); Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_must_match_map, + Vminibuffer_local_completion_map); DEFVAR_LISP ("minor-mode-map-alist", &Vminor_mode_map_alist, - "Alist of keymaps to use for minor modes.\n\ -Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read\n\ -key sequences and look up bindings iff VARIABLE's value is non-nil.\n\ -If two active keymaps bind the same key, the keymap appearing earlier\n\ -in the list takes precedence."); + doc: /* Alist of keymaps to use for minor modes. +Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read +key sequences and look up bindings iff VARIABLE's value is non-nil. +If two active keymaps bind the same key, the keymap appearing earlier +in the list takes precedence. */); Vminor_mode_map_alist = Qnil; DEFVAR_LISP ("minor-mode-overriding-map-alist", &Vminor_mode_overriding_map_alist, - "Alist of keymaps to use for minor modes, in current major mode.\n\ -This variable is a alist just like `minor-mode-map-alist', and it is\n\ -used the same way (and before `minor-mode-map-alist'); however,\n\ -it is provided for major modes to bind locally."); + doc: /* Alist of keymaps to use for minor modes, in current major mode. +This variable is a alist just like `minor-mode-map-alist', and it is +used the same way (and before `minor-mode-map-alist'); however, +it is provided for major modes to bind locally. */); Vminor_mode_overriding_map_alist = Qnil; DEFVAR_LISP ("function-key-map", &Vfunction_key_map, - "Keymap mapping ASCII function key sequences onto their preferred forms.\n\ -This allows Emacs to recognize function keys sent from ASCII\n\ -terminals at any point in a key sequence.\n\ -\n\ -The `read-key-sequence' function replaces any subsequence bound by\n\ -`function-key-map' with its binding. More precisely, when the active\n\ -keymaps have no binding for the current key sequence but\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\ -The events that come from bindings in `function-key-map' are not\n\ -themselves looked up in `function-key-map'.\n\ -\n\ -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]."); + doc: /* Keymap mapping ASCII function key sequences onto their preferred forms. +This allows Emacs to recognize function keys sent from ASCII +terminals at any point in a key sequence. + +The `read-key-sequence' function replaces any subsequence bound by +`function-key-map' with its binding. More precisely, when the active +keymaps have no binding for the current key sequence but +`function-key-map' binds a suffix of the sequence to a vector or string, +`read-key-sequence' replaces the matching suffix with its binding, and +continues with the new sequence. + +The events that come from bindings in `function-key-map' are not +themselves looked up in `function-key-map'. + +For example, suppose `function-key-map' binds `ESC O P' to [f1]. +Typing `ESC O P' to `read-key-sequence' would return [f1]. Typing +`C-x ESC O P' would return [?\\C-x f1]. If [f1] were a prefix +key, typing `ESC O P x' would return [f1 x]. */); Vfunction_key_map = Fmake_sparse_keymap (Qnil); DEFVAR_LISP ("key-translation-map", &Vkey_translation_map, - "Keymap of key translations that can override keymaps.\n\ -This keymap works like `function-key-map', but comes after that,\n\ -and applies even for keys that have ordinary bindings."); + 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. */); Vkey_translation_map = Qnil; Qsingle_key_description = intern ("single-key-description"); @@ -3391,6 +3621,12 @@ and applies even for keys that have ordinary bindings."); Qmenu_item = intern ("menu-item"); staticpro (&Qmenu_item); + Qremap = intern ("remap"); + staticpro (&Qremap); + + remap_command_vector = Fmake_vector (make_number (2), Qremap); + staticpro (&remap_command_vector); + where_is_cache_keymaps = Qt; where_is_cache = Qnil; staticpro (&where_is_cache); @@ -3398,10 +3634,12 @@ and applies even for keys that have ordinary bindings."); defsubr (&Skeymapp); defsubr (&Skeymap_parent); + defsubr (&Skeymap_prompt); defsubr (&Sset_keymap_parent); defsubr (&Smake_keymap); defsubr (&Smake_sparse_keymap); defsubr (&Scopy_keymap); + defsubr (&Sremap_command); defsubr (&Skey_binding); defsubr (&Slocal_key_binding); defsubr (&Sglobal_key_binding); @@ -3414,13 +3652,14 @@ and applies even for keys that have ordinary bindings."); defsubr (&Scurrent_local_map); defsubr (&Scurrent_global_map); defsubr (&Scurrent_minor_mode_maps); + defsubr (&Scurrent_active_maps); defsubr (&Saccessible_keymaps); defsubr (&Skey_description); defsubr (&Sdescribe_vector); defsubr (&Ssingle_key_description); defsubr (&Stext_char_description); defsubr (&Swhere_is_internal); - defsubr (&Sdescribe_bindings_internal); + defsubr (&Sdescribe_buffer_bindings); defsubr (&Sapropos_internal); }