X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/21a0d7a0004522005fa603ab331de2c650ee9b7a..a3e99933ee7fcf6a98d8a478180ad8b49ba378a4:/src/keymap.c diff --git a/src/keymap.c b/src/keymap.c index 3ae7d7e360..e2a1b97c9d 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1,5 +1,5 @@ /* Manipulation of keymaps - Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc. + Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -15,7 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include @@ -27,6 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "keyboard.h" #include "termhooks.h" #include "blockinput.h" +#include "puresize.h" #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -73,6 +75,15 @@ Lisp_Object Vminor_mode_map_alist; documentation. */ Lisp_Object Vfunction_key_map; +/* Keymap mapping ASCII function key sequences onto their preferred forms. */ +Lisp_Object Vkey_translation_map; + +/* A list of all commands given new bindings since a certain time + when nil was stored here. + This is used to speed up recomputation of menu key equivalents + when Emacs starts up. t means don't record anything here. */ +Lisp_Object Vdefine_key_rebound_commands; + Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii; /* A char with the CHAR_META bit set in a vector or the 0200 bit set @@ -82,10 +93,9 @@ extern Lisp_Object meta_prefix_char; extern Lisp_Object Voverriding_local_map; -void describe_map_tree (); static Lisp_Object define_as_prefix (); static Lisp_Object describe_buffer_bindings (); -static void describe_command (); +static void describe_command (), describe_translation (); static void describe_map (); /* Keymap object support - constructors and predicates. */ @@ -163,14 +173,14 @@ synkey (frommap, fromchar, tomap, tochar) int fromchar, tochar; { Lisp_Object v, c; - XSET (v, Lisp_Vector, tomap); - XFASTINT (c) = tochar; + XSETVECTOR (v, tomap); + XSETFASTINT (c, tochar); frommap->contents[fromchar] = Fcons (v, c); } #endif /* 0 */ DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0, - "Return t if ARG is a keymap.\n\ + "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\ @@ -214,7 +224,7 @@ get_keymap_1 (object, error, autoload) /* Should we do an autoload? Autoload forms for keymaps have Qkeymap as their fifth element. */ if (autoload - && XTYPE (object) == Lisp_Symbol + && SYMBOLP (object) && CONSP (tem) && EQ (XCONS (tem)->car, Qautoload)) { @@ -248,8 +258,141 @@ get_keymap (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) + Lisp_Object keymap; +{ + Lisp_Object list; + + keymap = get_keymap_1 (keymap, 1, 1); + + /* Skip past the initial element `keymap'. */ + list = XCONS (keymap)->cdr; + for (; CONSP (list); list = XCONS (list)->cdr) + { + /* See if there is another `keymap'. */ + if (EQ (Qkeymap, XCONS (list)->car)) + return list; + } + + return Qnil; +} + +/* 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) + Lisp_Object keymap, parent; +{ + Lisp_Object list, prev; + int i; + + keymap = get_keymap_1 (keymap, 1, 1); + if (!NILP (parent)) + parent = get_keymap_1 (parent, 1, 1); + + /* Skip past the initial element `keymap'. */ + prev = keymap; + while (1) + { + list = XCONS (prev)->cdr; + /* If there is a parent keymap here, replace it. + If we came to the end, add the parent in PREV. */ + if (! CONSP (list) || EQ (Qkeymap, XCONS (list)->car)) + { + /* If we already have the right parent, return now + so that we avoid the loops below. */ + if (EQ (XCONS (prev)->cdr, parent)) + return parent; + + XCONS (prev)->cdr = parent; + break; + } + prev = list; + } + + /* Scan through for submaps, and set their parents too. */ + + for (list = XCONS (keymap)->cdr; CONSP (list); list = XCONS (list)->cdr) + { + /* Stop the scan when we come to the parent. */ + if (EQ (XCONS (list)->car, Qkeymap)) + break; + + /* If this element holds a prefix map, deal with it. */ + if (CONSP (XCONS (list)->car) + && CONSP (XCONS (XCONS (list)->car)->cdr)) + fix_submap_inheritance (keymap, XCONS (XCONS (list)->car)->car, + XCONS (XCONS (list)->car)->cdr); + + if (VECTORP (XCONS (list)->car)) + for (i = 0; i < XVECTOR (XCONS (list)->car)->size; i++) + if (CONSP (XVECTOR (XCONS (list)->car)->contents[i])) + fix_submap_inheritance (keymap, make_number (i), + XVECTOR (XCONS (list)->car)->contents[i]); + } + + return parent; +} + +/* EVENT is defined in MAP as a prefix, and SUBMAP is its definition. + if EVENT is also a prefix in MAP's parent, + make sure that SUBMAP inherits that definition as its own parent. */ + +fix_submap_inheritance (map, event, submap) + Lisp_Object map, event, submap; +{ + Lisp_Object map_parent, parent_entry; + + /* SUBMAP is a cons that we found as a key binding. + Discard the other things found in a menu key binding. */ + + if (CONSP (submap) + && STRINGP (XCONS (submap)->car)) + { + submap = XCONS (submap)->cdr; + /* Also remove a menu help string, if any, + following the menu item name. */ + if (CONSP (submap) && STRINGP (XCONS (submap)->car)) + submap = XCONS (submap)->cdr; + /* Also remove the sublist that caches key equivalences, if any. */ + if (CONSP (submap) + && CONSP (XCONS (submap)->car)) + { + Lisp_Object carcar; + carcar = XCONS (XCONS (submap)->car)->car; + if (NILP (carcar) || VECTORP (carcar)) + submap = XCONS (submap)->cdr; + } + } + + /* If it isn't a keymap now, there's no work to do. */ + if (! CONSP (submap) + || ! EQ (XCONS (submap)->car, Qkeymap)) + return; + map_parent = Fkeymap_parent (map); + if (! NILP (map_parent)) + parent_entry = access_keymap (map_parent, event, 0, 0); + else + parent_entry = Qnil; + + /* If MAP's parent has something other than a keymap, + our own submap shadows it completely, so use nil as SUBMAP's parent. */ + if (! (CONSP (parent_entry) && EQ (XCONS (parent_entry)->car, Qkeymap))) + parent_entry = Qnil; + if (! EQ (parent_entry, submap)) + Fset_keymap_parent (submap, parent_entry); +} + /* Look up IDX in MAP. IDX may be any sort of event. Note that this does only one level of lookup; IDX must be a single event, not a sequence. @@ -279,12 +422,12 @@ access_keymap (map, idx, t_ok, noinherit) /* If idx is a symbol, it might have modifiers, which need to be put in the canonical order. */ - if (XTYPE (idx) == Lisp_Symbol) + if (SYMBOLP (idx)) idx = reorder_modifiers (idx); else if (INTEGERP (idx)) /* Clobber the high bits that can be present on a machine with more than 24 bits of integer. */ - XFASTINT (idx) = XINT (idx) & (CHAR_META | (CHAR_META - 1)); + XSETFASTINT (idx, XINT (idx) & (CHAR_META | (CHAR_META - 1))); { Lisp_Object tail; @@ -296,38 +439,38 @@ access_keymap (map, idx, t_ok, noinherit) Lisp_Object binding; binding = XCONS (tail)->car; - switch (XTYPE (binding)) + if (SYMBOLP (binding)) { - case Lisp_Symbol: /* If NOINHERIT, stop finding prefix definitions after we pass a second occurrence of the `keymap' symbol. */ if (noinherit && EQ (binding, Qkeymap) && ! EQ (tail, map)) noprefix = 1; - break; - - case Lisp_Cons: + } + else if (CONSP (binding)) + { if (EQ (XCONS (binding)->car, idx)) { val = XCONS (binding)->cdr; if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) return Qnil; + if (CONSP (val)) + fix_submap_inheritance (map, idx, val); return val; } if (t_ok && EQ (XCONS (binding)->car, Qt)) t_binding = XCONS (binding)->cdr; - break; - - case Lisp_Vector: - if (XTYPE (idx) == Lisp_Int - && XINT (idx) >= 0 - && XINT (idx) < XVECTOR (binding)->size) + } + else if (VECTORP (binding)) + { + if (NATNUMP (idx) && XFASTINT (idx) < XVECTOR (binding)->size) { - val = XVECTOR (binding)->contents[XINT (idx)]; + val = XVECTOR (binding)->contents[XFASTINT (idx)]; if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) return Qnil; + if (CONSP (val)) + fix_submap_inheritance (map, idx, val); return val; } - break; } QUIT; @@ -368,14 +511,13 @@ get_keyelt (object, autoload) use DEFN. Keymap alist elements like (CHAR MENUSTRING . DEFN) will be used by HierarKey menus. */ - else if (XTYPE (object) == Lisp_Cons - && XTYPE (XCONS (object)->car) == Lisp_String) + else if (CONSP (object) + && STRINGP (XCONS (object)->car)) { object = XCONS (object)->cdr; /* Also remove a menu help string, if any, following the menu item name. */ - if (XTYPE (object) == Lisp_Cons - && XTYPE (XCONS (object)->car) == Lisp_String) + if (CONSP (object) && STRINGP (XCONS (object)->car)) object = XCONS (object)->cdr; /* Also remove the sublist that caches key equivalences, if any. */ if (CONSP (object) @@ -400,8 +542,12 @@ store_in_keymap (keymap, idx, def) register Lisp_Object idx; register Lisp_Object def; { - if (XTYPE (keymap) != Lisp_Cons - || ! EQ (XCONS (keymap)->car, Qkeymap)) + /* If we are preparing to dump, and DEF is a menu element + with a menu item string, copy it to ensure it is not pure. */ + if (CONSP (def) && PURE_P (def) && STRINGP (XCONS (def)->car)) + def = Fcons (XCONS (def)->car, XCONS (def)->cdr); + + if (!CONSP (keymap) || ! EQ (XCONS (keymap)->car, Qkeymap)) error ("attempt to define a key in a non-keymap"); /* If idx is a list (some sort of mouse click, perhaps?), @@ -411,12 +557,12 @@ store_in_keymap (keymap, idx, def) /* If idx is a symbol, it might have modifiers, which need to be put in the canonical order. */ - if (XTYPE (idx) == Lisp_Symbol) + if (SYMBOLP (idx)) idx = reorder_modifiers (idx); else if (INTEGERP (idx)) /* Clobber the high bits that can be present on a machine with more than 24 bits of integer. */ - XFASTINT (idx) = XINT (idx) & (CHAR_META | (CHAR_META - 1)); + XSETFASTINT (idx, XINT (idx) & (CHAR_META | (CHAR_META - 1))); /* Scan the keymap for a binding of idx. */ { @@ -436,34 +582,31 @@ store_in_keymap (keymap, idx, def) Lisp_Object elt; elt = XCONS (tail)->car; - switch (XTYPE (elt)) + if (VECTORP (elt)) { - case Lisp_Vector: - if (XTYPE (idx) == Lisp_Int - && XINT (idx) >= 0 && XINT (idx) < XVECTOR (elt)->size) + if (NATNUMP (idx) && XFASTINT (idx) < XVECTOR (elt)->size) { XVECTOR (elt)->contents[XFASTINT (idx)] = def; return def; } insertion_point = tail; - break; - - case Lisp_Cons: + } + else if (CONSP (elt)) + { if (EQ (idx, XCONS (elt)->car)) { XCONS (elt)->cdr = def; return def; } - break; - - case Lisp_Symbol: + } + else if (SYMBOLP (elt)) + { /* If we find a 'keymap' symbol in the spine of KEYMAP, then we must have found the start of a second keymap being used as the tail of KEYMAP, and a binding for IDX should be inserted before it. */ if (EQ (elt, Qkeymap)) goto keymap_end; - break; } QUIT; @@ -472,8 +615,8 @@ 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. */ - XCONS (insertion_point)->cdr = - Fcons (Fcons (idx, def), XCONS (insertion_point)->cdr); + XCONS (insertion_point)->cdr + = Fcons (Fcons (idx, def), XCONS (insertion_point)->cdr); } return def; @@ -499,7 +642,7 @@ is not copied.") Lisp_Object elt; elt = XCONS (tail)->car; - if (XTYPE (elt) == Lisp_Vector) + if (VECTORP (elt)) { int i; @@ -507,7 +650,7 @@ is not copied.") XCONS (tail)->car = elt; for (i = 0; i < XVECTOR (elt)->size; i++) - if (XTYPE (XVECTOR (elt)->contents[i]) != Lisp_Symbol + if (!SYMBOLP (XVECTOR (elt)->contents[i]) && ! NILP (Fkeymapp (XVECTOR (elt)->contents[i]))) XVECTOR (elt)->contents[i] = Fcopy_keymap (XVECTOR (elt)->contents[i]); @@ -591,17 +734,19 @@ the front of KEYMAP.") keymap = get_keymap_1 (keymap, 1, 1); - if (XTYPE (key) != Lisp_Vector - && XTYPE (key) != Lisp_String) + if (!VECTORP (key) && !STRINGP (key)) key = wrong_type_argument (Qarrayp, key); length = XFASTINT (Flength (key)); if (length == 0) return Qnil; + if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) + Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); + GCPRO3 (keymap, key, def); - if (XTYPE (key) == Lisp_Vector) + if (VECTORP (key)) meta_bit = meta_modifier; else meta_bit = 0x80; @@ -611,7 +756,10 @@ the front of KEYMAP.") { c = Faref (key, make_number (idx)); - if (XTYPE (c) == Lisp_Int + if (CONSP (c) && lucid_event_type_list_p (c)) + c = Fevent_convert_list (c); + + if (INTEGERP (c) && (XINT (c) & meta_bit) && !metized) { @@ -620,7 +768,7 @@ the front of KEYMAP.") } else { - if (XTYPE (c) == Lisp_Int) + if (INTEGERP (c)) XSETINT (c, XINT (c) & ~meta_bit); metized = 0; @@ -628,7 +776,7 @@ the front of KEYMAP.") } if (! INTEGERP (c) && ! SYMBOLP (c) && ! CONSP (c)) - error ("Key sequence contains illegal events"); + error ("Key sequence contains invalid events"); if (idx == length) RETURN_UNGCPRO (store_in_keymap (keymap, c, def)); @@ -663,7 +811,7 @@ it takes to reach a non-prefix command.\n\ \n\ Normally, `lookup-key' ignores bindings for t, which act as default\n\ bindings, used when nothing else in the keymap applies; this makes it\n\ -useable as a general function for probing keymaps. However, if the\n\ +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) @@ -683,15 +831,14 @@ recognize the default bindings, just as `read-key-sequence' does.") keymap = get_keymap_1 (keymap, 1, 1); - if (XTYPE (key) != Lisp_Vector - && XTYPE (key) != Lisp_String) + if (!VECTORP (key) && !STRINGP (key)) key = wrong_type_argument (Qarrayp, key); length = XFASTINT (Flength (key)); if (length == 0) return keymap; - if (XTYPE (key) == Lisp_Vector) + if (VECTORP (key)) meta_bit = meta_modifier; else meta_bit = 0x80; @@ -703,7 +850,10 @@ recognize the default bindings, just as `read-key-sequence' does.") { c = Faref (key, make_number (idx)); - if (XTYPE (c) == Lisp_Int + if (CONSP (c) && lucid_event_type_list_p (c)) + c = Fevent_convert_list (c); + + if (INTEGERP (c) && (XINT (c) & meta_bit) && !metized) { @@ -712,7 +862,7 @@ recognize the default bindings, just as `read-key-sequence' does.") } else { - if (XTYPE (c) == Lisp_Int) + if (INTEGERP (c)) XSETINT (c, XINT (c) & ~meta_bit); metized = 0; @@ -746,6 +896,20 @@ define_as_prefix (keymap, c) make it a prefix in this map, and make its definition inherit the other prefix definition. */ inherit = access_keymap (keymap, c, 0, 0); +#if 0 + /* This code is needed to do the right thing in the following case: + keymap A inherits from B, + you define KEY as a prefix in A, + then later you define KEY as a prefix in B. + We want the old prefix definition in A to inherit from that in B. + It is hard to do that retroactively, so this code + creates the prefix in B right away. + + But it turns out that this code causes problems immediately + when the prefix in A is defined: it causes B to define KEY + as a prefix with no subcommands. + + So I took out this code. */ if (NILP (inherit)) { /* If there's an inherited keymap @@ -760,6 +924,7 @@ define_as_prefix (keymap, c) if (!NILP (tail)) inherit = define_as_prefix (tail, c); } +#endif cmd = nconc2 (cmd, inherit); store_in_keymap (keymap, c, cmd); @@ -790,6 +955,13 @@ append_key (key_sequence, key) static Lisp_Object *cmm_modes, *cmm_maps; static int cmm_size; +/* Error handler used in current_minor_maps. */ +static Lisp_Object +current_minor_maps_error () +{ + return Qnil; +} + /* Store a pointer to an array of the keymaps of the currently active minor modes in *buf, and return the number of maps it contains. @@ -816,11 +988,13 @@ current_minor_maps (modeptr, mapptr) for (alist = Vminor_mode_map_alist; CONSP (alist); alist = XCONS (alist)->cdr) - if (CONSP (assoc = XCONS (alist)->car) - && XTYPE (var = XCONS (assoc)->car) == Lisp_Symbol - && ! EQ ((val = find_symbol_value (var)), Qunbound) + if ((assoc = XCONS (alist)->car, CONSP (assoc)) + && (var = XCONS (assoc)->car, SYMBOLP (var)) + && (val = find_symbol_value (var), ! EQ (val, Qunbound)) && ! NILP (val)) { + Lisp_Object temp; + if (i >= cmm_size) { Lisp_Object *newmodes, *newmaps; @@ -856,9 +1030,17 @@ current_minor_maps (modeptr, mapptr) else break; } - cmm_modes[i] = var; - cmm_maps [i] = Findirect_function (XCONS (assoc)->cdr); - i++; + + /* Get the keymap definition--or nil if it is not defined. */ + temp = internal_condition_case_1 (Findirect_function, + XCONS (assoc)->cdr, + Qerror, current_minor_maps_error); + if (!NILP (temp)) + { + cmm_modes[i] = var; + cmm_maps [i] = temp; + i++; + } } if (modeptr) *modeptr = cmm_modes; @@ -887,14 +1069,23 @@ recognize the default bindings, just as `read-key-sequence' does.") GCPRO1 (key); - if (!NILP (Voverriding_local_map)) + if (!NILP (current_kboard->Voverriding_terminal_local_map)) + { + value = Flookup_key (current_kboard->Voverriding_terminal_local_map, + key, accept_default); + if (! NILP (value) && !INTEGERP (value)) + RETURN_UNGCPRO (value); + } + else if (!NILP (Voverriding_local_map)) { value = Flookup_key (Voverriding_local_map, key, accept_default); - if (! NILP (value) && XTYPE (value) != Lisp_Int) + if (! NILP (value) && !INTEGERP (value)) RETURN_UNGCPRO (value); } else { + Lisp_Object local; + nmaps = current_minor_maps (0, &maps); /* Note that all these maps are GCPRO'd in the places where we found them. */ @@ -903,21 +1094,23 @@ recognize the default bindings, just as `read-key-sequence' does.") if (! NILP (maps[i])) { value = Flookup_key (maps[i], key, accept_default); - if (! NILP (value) && XTYPE (value) != Lisp_Int) + if (! NILP (value) && !INTEGERP (value)) RETURN_UNGCPRO (value); } - if (! NILP (current_buffer->keymap)) + local = get_local_map (PT, current_buffer); + + if (! NILP (local)) { - value = Flookup_key (current_buffer->keymap, key, accept_default); - if (! NILP (value) && XTYPE (value) != Lisp_Int) + value = Flookup_key (local, key, accept_default); + if (! NILP (value) && !INTEGERP (value)) RETURN_UNGCPRO (value); } } value = Flookup_key (current_global_map, key, accept_default); UNGCPRO; - if (! NILP (value) && XTYPE (value) != Lisp_Int) + if (! NILP (value) && !INTEGERP (value)) return value; return Qnil; @@ -992,7 +1185,7 @@ bindings; see the description of `lookup-key' for more details about this.") for (i = j = 0; i < nmaps; i++) if (! NILP (maps[i]) && ! NILP (binding = Flookup_key (maps[i], key, accept_default)) - && XTYPE (binding) != Lisp_Int) + && !INTEGERP (binding)) { if (! NILP (get_keymap (binding))) maps[j++] = Fcons (modes[i], binding); @@ -1004,93 +1197,23 @@ bindings; see the description of `lookup-key' for more details about this.") return Flist (j, maps); } -DEFUN ("global-set-key", Fglobal_set_key, Sglobal_set_key, 2, 2, - "kSet key globally: \nCSet key %s to command: ", - "Give KEY a global binding as COMMAND.\n\ -COMMAND is a symbol naming an interactively-callable function.\n\ -KEY is a key sequence (a string or vector of characters or event types).\n\ -Non-ASCII characters with codes above 127 (such as ISO Latin-1)\n\ -can be included if you use a vector.\n\ -Note that if KEY has a local binding in the current buffer\n\ -that local binding will continue to shadow any global binding.") - (keys, function) - Lisp_Object keys, function; -{ - if (XTYPE (keys) != Lisp_Vector - && XTYPE (keys) != Lisp_String) - keys = wrong_type_argument (Qarrayp, keys); - - Fdefine_key (current_global_map, keys, function); - return Qnil; -} - -DEFUN ("local-set-key", Flocal_set_key, Slocal_set_key, 2, 2, - "kSet key locally: \nCSet key %s locally to command: ", - "Give KEY a local binding as COMMAND.\n\ -COMMAND is a symbol naming an interactively-callable function.\n\ -KEY is a key sequence (a string or vector of characters or event types).\n\ -Non-ASCII characters with codes above 127 (such as ISO Latin-1)\n\ -can be included if you use a vector.\n\ -The binding goes in the current buffer's local map,\n\ -which in most cases is shared with all other buffers in the same major mode.") - (keys, function) - Lisp_Object keys, function; -{ - register Lisp_Object map; - map = current_buffer->keymap; - if (NILP (map)) - { - map = Fmake_sparse_keymap (Qnil); - current_buffer->keymap = map; - } - - if (XTYPE (keys) != Lisp_Vector - && XTYPE (keys) != Lisp_String) - keys = wrong_type_argument (Qarrayp, keys); - - Fdefine_key (map, keys, function); - return Qnil; -} - -DEFUN ("global-unset-key", Fglobal_unset_key, Sglobal_unset_key, - 1, 1, "kUnset key globally: ", - "Remove global binding of KEY.\n\ -KEY is a string representing a sequence of keystrokes.") - (keys) - Lisp_Object keys; -{ - return Fglobal_set_key (keys, Qnil); -} - -DEFUN ("local-unset-key", Flocal_unset_key, Slocal_unset_key, 1, 1, - "kUnset key locally: ", - "Remove local binding of KEY.\n\ -KEY is a string representing a sequence of keystrokes.") - (keys) - Lisp_Object keys; -{ - if (!NILP (current_buffer->keymap)) - Flocal_set_key (keys, Qnil); - return Qnil; -} - DEFUN ("define-prefix-command", Fdefine_prefix_command, Sdefine_prefix_command, 1, 2, 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.") - (name, mapvar) - Lisp_Object name, mapvar; + (command, mapvar) + Lisp_Object command, mapvar; { Lisp_Object map; map = Fmake_sparse_keymap (Qnil); - Ffset (name, map); + Ffset (command, map); if (!NILP (mapvar)) Fset (mapvar, map); else - Fset (name, map); - return name; + Fset (command, map); + return command; } DEFUN ("use-global-map", Fuse_global_map, Suse_global_map, 1, 1, 0, @@ -1100,6 +1223,7 @@ DEFUN ("use-global-map", Fuse_global_map, Suse_global_map, 1, 1, 0, { keymap = get_keymap (keymap); current_global_map = keymap; + return Qnil; } @@ -1150,11 +1274,11 @@ DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps, "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\ +so that the KEYS increase in length. The first element is ([] . KEYMAP).\n\ An optional argument PREFIX, if non-nil, should be a key sequence;\n\ then the value includes only maps for prefixes that start with PREFIX.") - (startmap, prefix) - Lisp_Object startmap, prefix; + (keymap, prefix) + Lisp_Object keymap, prefix; { Lisp_Object maps, good_maps, tail; int prefixlen = 0; @@ -1164,9 +1288,25 @@ then the value includes only maps for prefixes that start with PREFIX.") if (!NILP (prefix)) prefixlen = XINT (Flength (prefix)); - maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil), - get_keymap (startmap)), - Qnil); + if (!NILP (prefix)) + { + /* If a prefix was specified, start with the keymap (if any) for + that prefix, so we don't waste time considering other prefixes. */ + Lisp_Object tem; + tem = Flookup_key (keymap, prefix, Qt); + /* 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)) + maps = Fcons (Fcons (prefix, tem), Qnil); + else + return Qnil; + } + else + maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil), + get_keymap (keymap)), + Qnil); /* For each map in the list maps, look at any other maps it points to, @@ -1196,7 +1336,7 @@ then the value includes only maps for prefixes that start with PREFIX.") QUIT; - if (XTYPE (elt) == Lisp_Vector) + if (VECTORP (elt)) { register int i; @@ -1263,7 +1403,7 @@ then the value includes only maps for prefixes that start with PREFIX.") /* 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 && XTYPE (elt) == Lisp_Int) + if (is_metized && INTEGERP (elt)) { tem = Fcopy_sequence (thisseq); Faset (tem, last, @@ -1304,7 +1444,7 @@ then the value includes only maps for prefixes that start with PREFIX.") for (i = 0; i < prefixlen; i++) { Lisp_Object i1; - XFASTINT (i1) = i; + XSETFASTINT (i1, i); if (!EQ (Faref (thisseq, i1), Faref (prefix, i1))) break; } @@ -1332,21 +1472,23 @@ spaces are put between sequence elements, etc.") Lisp_Object sep; Lisp_Object *args; - if (XTYPE (keys) == Lisp_String) + if (STRINGP (keys)) { Lisp_Object vector; vector = Fmake_vector (Flength (keys), Qnil); for (i = 0; i < XSTRING (keys)->size; i++) { if (XSTRING (keys)->data[i] & 0x80) - XFASTINT (XVECTOR (vector)->contents[i]) - = meta_modifier | (XSTRING (keys)->data[i] & ~0x80); + XSETFASTINT (XVECTOR (vector)->contents[i], + meta_modifier | (XSTRING (keys)->data[i] & ~0x80)); else - XFASTINT (XVECTOR (vector)->contents[i]) - = XSTRING (keys)->data[i]; + XSETFASTINT (XVECTOR (vector)->contents[i], + XSTRING (keys)->data[i]); } keys = vector; } + else if (!VECTORP (keys)) + keys = wrong_type_argument (Qarrayp, keys); /* In effect, this computes (mapconcat 'single-key-description keys " ") @@ -1486,22 +1628,17 @@ Control characters turn into C-whatever, etc.") key = EVENT_HEAD (key); - switch (XTYPE (key)) + if (INTEGERP (key)) /* Normal character */ { - case Lisp_Int: /* Normal character */ *push_key_description (XUINT (key), tem) = 0; return build_string (tem); - - case Lisp_Symbol: /* Function key or event-symbol */ - return Fsymbol_name (key); - - /* Buffer names in the menubar can trigger this. */ - case Lisp_String: - return Fcopy_sequence (key); - - default: - error ("KEY must be an integer, cons, symbol, or string."); } + else if (SYMBOLP (key)) /* Function key or event-symbol */ + return Fsymbol_name (key); + else if (STRINGP (key)) /* Buffer names in the menubar. */ + return Fcopy_sequence (key); + else + error ("KEY must be an integer, cons, symbol, or string"); } char * @@ -1533,16 +1670,16 @@ push_text_char_description (c, 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 CHAR.\n\ + "Return a pretty description of file-character CHARACTER.\n\ Control characters turn into \"^char\", etc.") - (chr) - Lisp_Object chr; + (character) + Lisp_Object character; { char tem[6]; - CHECK_NUMBER (chr, 0); + CHECK_NUMBER (character, 0); - *push_text_char_description (XINT (chr) & 0377, tem) = 0; + *push_text_char_description (XINT (character) & 0377, tem) = 0; return build_string (tem); } @@ -1553,16 +1690,17 @@ static int ascii_sequence_p (seq) Lisp_Object seq; { - Lisp_Object i; + int i; int len = XINT (Flength (seq)); - for (XFASTINT (i) = 0; XFASTINT (i) < len; XFASTINT (i)++) + for (i = 0; i < len; i++) { - Lisp_Object elt; + Lisp_Object ii, elt; - elt = Faref (seq, i); + XSETFASTINT (ii, i); + elt = Faref (seq, ii); - if (XTYPE (elt) != Lisp_Int + if (!INTEGERP (elt) || (XUINT (elt) & ~CHAR_META) >= 0x80) return 0; } @@ -1582,10 +1720,10 @@ If KEYMAP is nil, search all the currently active 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 t, avoid key sequences which use non-ASCII\n\ -keys and therefore may not be usable on ASCII terminals. If FIRSTONLY\n\ -is the symbol `non-ascii', return the first binding found, no matter\n\ -what its components.\n\ +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\ @@ -1598,6 +1736,8 @@ indirect definition itself.") Lisp_Object found, sequence; int keymap_specified = !NILP (keymap); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + /* 1 means ignore all menu bindings entirely. */ + int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); if (! keymap_specified) { @@ -1673,11 +1813,11 @@ indirect definition itself.") /* Set key and binding to the current key and binding, and advance map and i to the next binding. */ - if (XTYPE (elt) == Lisp_Vector) + if (VECTORP (elt)) { /* In a vector, look at each element. */ binding = XVECTOR (elt)->contents[i]; - XFASTINT (key) = i; + XSETFASTINT (key, i); i++; /* If we've just finished scanning a vector, advance map @@ -1706,12 +1846,33 @@ indirect definition itself.") /* Search through indirections unless that's not wanted. */ if (NILP (noindirect)) - binding = get_keyelt (binding, 0); + { + if (nomenus) + { + while (1) + { + Lisp_Object map, tem; + /* If the contents are (KEYMAP . ELEMENT), go indirect. */ + map = get_keymap_1 (Fcar_safe (definition), 0, 0); + tem = Fkeymapp (map); + if (!NILP (tem)) + definition = access_keymap (map, Fcdr (definition), 0, 0); + else + break; + } + /* If the contents are (STRING ...), reject. */ + if (CONSP (definition) + && STRINGP (XCONS (definition)->car)) + continue; + } + else + binding = get_keyelt (binding, 0); + } /* End this iteration if this element does not match the target. */ - if (XTYPE (definition) == Lisp_Cons) + if (CONSP (definition)) { Lisp_Object tem; tem = Fequal (binding, definition); @@ -1724,7 +1885,7 @@ indirect definition itself.") /* We have found a match. Construct the key sequence where we found it. */ - if (XTYPE (key) == Lisp_Int && last_is_meta) + if (INTEGERP (key) && last_is_meta) { sequence = Fcopy_sequence (this); Faset (sequence, last, make_number (XINT (key) | meta_modifier)); @@ -1744,9 +1905,9 @@ indirect definition itself.") if (keymap_specified) { binding = Flookup_key (keymap, sequence, Qnil); - if (!NILP (binding) && XTYPE (binding) != Lisp_Int) + if (!NILP (binding) && !INTEGERP (binding)) { - if (XTYPE (definition) == Lisp_Cons) + if (CONSP (definition)) { Lisp_Object tem; tem = Fequal (binding, definition); @@ -1805,7 +1966,7 @@ then we display only bindings that start with that prefix.") Lisp_Object prefix; { register Lisp_Object thisbuf; - XSET (thisbuf, Lisp_Buffer, current_buffer); + XSETBUFFER (thisbuf, current_buffer); internal_with_output_to_temp_buffer ("*Help*", describe_buffer_bindings, Fcons (thisbuf, prefix)); @@ -1836,7 +1997,7 @@ nominal alternate\n\ Fset_buffer (Vstandard_output); /* Report on alternates for keys. */ - if (XTYPE (Vkeyboard_translate_table) == Lisp_String) + if (STRINGP (Vkeyboard_translate_table) && !NILP (prefix)) { int c; unsigned char *translate = XSTRING (Vkeyboard_translate_table)->data; @@ -1866,6 +2027,10 @@ nominal alternate\n\ insert ("\n", 1); } + if (!NILP (Vkey_translation_map)) + describe_map_tree (Vkey_translation_map, 0, Qnil, prefix, + "Key translations", 0, 1, 0); + { int i, nmaps; Lisp_Object *modes, *maps; @@ -1873,7 +2038,9 @@ nominal alternate\n\ /* Temporarily switch to descbuf, so that we can get that buffer's minor modes correctly. */ Fset_buffer (descbuf); - if (!NILP (Voverriding_local_map)) + + if (!NILP (current_kboard->Voverriding_terminal_local_map) + || !NILP (Voverriding_local_map)) nmaps = 0; else nmaps = current_minor_maps (&modes, &maps); @@ -1888,7 +2055,7 @@ nominal alternate\n\ because it takes care of other features when doing so. */ char *title, *p; - if (XTYPE (modes[i]) != Lisp_Symbol) + if (!SYMBOLP (modes[i])) abort(); p = title = (char *) alloca (40 + XSYMBOL (modes[i])->name->size); @@ -1901,13 +2068,15 @@ nominal alternate\n\ p += sizeof (" Minor Mode Bindings") - 1; *p = 0; - describe_map_tree (maps[i], 0, shadow, prefix, title, 0); + describe_map_tree (maps[i], 0, shadow, prefix, title, 0, 0, 0); shadow = Fcons (maps[i], shadow); } } /* Print the (major mode) local map. */ - if (!NILP (Voverriding_local_map)) + 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; @@ -1915,19 +2084,25 @@ nominal alternate\n\ if (!NILP (start1)) { describe_map_tree (start1, 0, shadow, prefix, - "Major Mode Bindings", 0); + "Major Mode Bindings", 0, 0, 0); shadow = Fcons (start1, shadow); } describe_map_tree (current_global_map, 0, shadow, prefix, - "Global Bindings", 0); + "Global Bindings", 0, 0, 1); + /* Print the function-key-map translations under this prefix. */ + if (!NILP (Vfunction_key_map)) + describe_map_tree (Vfunction_key_map, 0, Qnil, prefix, + "Function key map translations", 0, 1, 0); + + call0 (intern ("help-mode")); Fset_buffer (descbuf); UNGCPRO; return Qnil; } -/* Insert a desription of the key bindings in STARTMAP, +/* Insert a description of the key bindings in STARTMAP, followed by those of all maps reachable through STARTMAP. If PARTIAL is nonzero, omit certain "uninteresting" commands (such as `undefined'). @@ -1936,14 +2111,23 @@ nominal alternate\n\ PREFIX, if non-nil, says mention only keys that start with PREFIX. TITLE, if not 0, is a string to insert at the beginning. TITLE should not end with a colon or a newline; we supply that. - If NOMENU is not 0, then omit menu-bar commands. */ + If NOMENU is not 0, then omit menu-bar commands. + + If TRANSL is nonzero, the definitions are actually key translations + so print strings and vectors differently. + + If ALWAYS_TITLE is nonzero, print the title even if there are no maps + to look through. */ void -describe_map_tree (startmap, partial, shadow, prefix, title, nomenu) +describe_map_tree (startmap, partial, shadow, prefix, title, nomenu, transl, + always_title) Lisp_Object startmap, shadow, prefix; int partial; char *title; int nomenu; + int transl; + int always_title; { Lisp_Object maps, seen, sub_shadows; struct gcpro gcpro1, gcpro2, gcpro3; @@ -1978,7 +2162,7 @@ key binding\n\ } } - if (!NILP (maps)) + if (!NILP (maps) || always_title) { if (title) { @@ -2011,10 +2195,8 @@ key binding\n\ /* If the sequence by which we reach this keymap is zero-length, then the shadow map for this keymap is just SHADOW. */ - if ((XTYPE (prefix) == Lisp_String - && XSTRING (prefix)->size == 0) - || (XTYPE (prefix) == Lisp_Vector - && XVECTOR (prefix)->size == 0)) + if ((STRINGP (prefix) && XSTRING (prefix)->size == 0) + || (VECTORP (prefix) && XVECTOR (prefix)->size == 0)) ; /* If the sequence by which we reach this keymap actually has some elements, then the sequence's definition in SHADOW is @@ -2022,7 +2204,7 @@ key binding\n\ else { shmap = Flookup_key (shmap, Fcar (elt), Qt); - if (XTYPE (shmap) == Lisp_Int) + if (INTEGERP (shmap)) shmap = Qnil; } @@ -2036,8 +2218,9 @@ key binding\n\ sub_shadows = Fcons (shmap, sub_shadows); } - describe_map (Fcdr (elt), Fcar (elt), describe_command, - partial, sub_shadows, &seen); + describe_map (Fcdr (elt), Fcar (elt), + transl ? describe_translation : describe_command, + partial, sub_shadows, &seen, nomenu); skip: ; } @@ -2048,21 +2231,38 @@ key binding\n\ UNGCPRO; } +static int previous_description_column; + static void describe_command (definition) Lisp_Object definition; { register Lisp_Object tem1; + int column = current_column (); + int description_column; - Findent_to (make_number (16), make_number (1)); + /* If column 16 is no good, go to col 32; + but don't push beyond that--go to next line instead. */ + if (column > 30) + { + insert_char ('\n'); + description_column = 32; + } + else if (column > 14 || (column > 10 && previous_description_column == 32)) + description_column = 32; + else + description_column = 16; + + Findent_to (make_number (description_column), make_number (1)); + previous_description_column = description_column; - if (XTYPE (definition) == Lisp_Symbol) + if (SYMBOLP (definition)) { - XSET (tem1, Lisp_String, XSYMBOL (definition)->name); + XSETSTRING (tem1, XSYMBOL (definition)->name); insert1 (tem1); insert_string ("\n"); } - else if (STRINGP (definition)) + else if (STRINGP (definition) || VECTORP (definition)) insert_string ("Keyboard Macro\n"); else { @@ -2074,6 +2274,35 @@ describe_command (definition) } } +static void +describe_translation (definition) + Lisp_Object definition; +{ + register Lisp_Object tem1; + + Findent_to (make_number (16), make_number (1)); + + if (SYMBOLP (definition)) + { + XSETSTRING (tem1, XSYMBOL (definition)->name); + insert1 (tem1); + insert_string ("\n"); + } + else if (STRINGP (definition) || VECTORP (definition)) + { + insert1 (Fkey_description (definition)); + insert_string ("\n"); + } + else + { + tem1 = Fkeymapp (definition); + if (!NILP (tem1)) + insert_string ("Prefix Command\n"); + else + insert_string ("??\n"); + } +} + /* 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. */ @@ -2094,16 +2323,17 @@ shadow_lookup (shadow, key, flag) /* Describe the contents of map MAP, assuming that this map itself is reached by the sequence of prefix keys KEYS (a string or vector). - PARTIAL, SHADOW are as in `describe_map_tree' above. */ + PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */ static void -describe_map (map, keys, elt_describer, partial, shadow, seen) +describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu) register Lisp_Object map; Lisp_Object keys; int (*elt_describer) (); int partial; Lisp_Object shadow; Lisp_Object *seen; + int nomenu; { Lisp_Object elt_prefix; Lisp_Object tail, definition, event; @@ -2137,9 +2367,9 @@ describe_map (map, keys, elt_describer, partial, shadow, seen) { QUIT; - if (XTYPE (XCONS (tail)->car) == Lisp_Vector) + if (VECTORP (XCONS (tail)->car)) describe_vector (XCONS (tail)->car, - elt_prefix, elt_describer, partial, shadow); + elt_prefix, elt_describer, partial, shadow, map); else if (CONSP (XCONS (tail)->car)) { event = XCONS (XCONS (tail)->car)->car; @@ -2149,11 +2379,14 @@ describe_map (map, keys, elt_describer, partial, shadow, seen) if (! (SYMBOLP (event) || INTEGERP (event))) continue; + if (nomenu && EQ (event, Qmenu_bar)) + continue; + definition = get_keyelt (XCONS (XCONS (tail)->car)->cdr, 0); /* Don't show undefined commands or suppressed commands. */ if (NILP (definition)) continue; - if (XTYPE (definition) == Lisp_Symbol && partial) + if (SYMBOLP (definition) && partial) { tem = Fget (definition, suppress); if (!NILP (tem)) @@ -2175,6 +2408,7 @@ describe_map (map, keys, elt_describer, partial, shadow, seen) if (first) { + previous_description_column = 0; insert ("\n", 1); first = 0; } @@ -2223,56 +2457,89 @@ This is text showing the elements of vector matched against indices.") int count = specpdl_ptr - specpdl; specbind (Qstandard_output, Fcurrent_buffer ()); - CHECK_VECTOR (vector, 0); - describe_vector (vector, Qnil, describe_vector_princ, 0, Qnil); + CHECK_VECTOR_OR_CHAR_TABLE (vector, 0); + describe_vector (vector, Qnil, describe_vector_princ, 0, Qnil, Qnil); return unbind_to (count, Qnil); } -describe_vector (vector, elt_prefix, elt_describer, partial, shadow) +/* Insert in the current buffer a description of the contents of VECTOR. + We call ELT_DESCRIBER to insert the description of one value found + in VECTOR. + + ELT_PREFIX describes what "comes before" the keys or indices defined + by this vector. + + If the vector is in a keymap, ELT_PREFIX is a prefix key which + leads to this keymap. + + If the vector is a chartable, ELT_PREFIX is the vector + of bytes that lead to the character set or portion of a character + set described by this chartable. + + If PARTIAL is nonzero, it means do not mention suppressed commands + (that assumes the vector is in a keymap). + + SHADOW is a list of keymaps that shadow this map. + If it is non-nil, then we look up the key in those maps + and we don't mention it now if it is defined by any of them. + + ENTIRE_MAP is the keymap in which this vector appears. + If the definition in effect in the whole map does not match + the one in this vector, we ignore this one. */ + +describe_vector (vector, elt_prefix, elt_describer, + partial, shadow, entire_map) register Lisp_Object vector; Lisp_Object elt_prefix; int (*elt_describer) (); int partial; Lisp_Object shadow; + Lisp_Object entire_map; { Lisp_Object this; Lisp_Object dummy; - Lisp_Object tem1, tem2; + Lisp_Object definition; + Lisp_Object tem2; register int i; Lisp_Object suppress; Lisp_Object kludge; + Lisp_Object chartable_kludge; int first = 1; - struct gcpro gcpro1, gcpro2, gcpro3; + int size; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; - tem1 = Qnil; + definition = Qnil; + chartable_kludge = Qnil; /* This vector gets used to present single keys to Flookup_key. Since that is done once per vector element, we don't want to cons up a fresh vector every time. */ kludge = Fmake_vector (make_number (1), Qnil); - GCPRO3 (elt_prefix, tem1, kludge); + GCPRO4 (elt_prefix, definition, kludge, chartable_kludge); if (partial) suppress = intern ("suppress-keymap"); - for (i = 0; i < XVECTOR (vector)->size; i++) + /* This does the right thing for char-tables as well as ordinary vectors. */ + size = XFASTINT (Flength (vector)); + + for (i = 0; i < size; i++) { QUIT; - tem1 = get_keyelt (XVECTOR (vector)->contents[i], 0); + definition = get_keyelt (XVECTOR (vector)->contents[i], 0); - if (NILP (tem1)) continue; + if (NILP (definition)) continue; /* Don't mention suppressed commands. */ - if (XTYPE (tem1) == Lisp_Symbol && partial) + if (SYMBOLP (definition) && partial) { - this = Fget (tem1, suppress); + this = Fget (definition, suppress); if (!NILP (this)) continue; } - /* If this command in this map is shadowed by some other map, - ignore it. */ + /* If this binding is shadowed by some other map, ignore it. */ if (!NILP (shadow)) { Lisp_Object tem; @@ -2283,27 +2550,83 @@ describe_vector (vector, elt_prefix, elt_describer, partial, shadow) if (!NILP (tem)) continue; } + /* Ignore this definition if it is shadowed by an earlier + one in the same keymap. */ + if (!NILP (entire_map)) + { + Lisp_Object tem; + + XVECTOR (kludge)->contents[0] = make_number (i); + tem = Flookup_key (entire_map, kludge, Qt); + + if (! EQ (tem, definition)) + continue; + } + + /* If we find a 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) && CHAR_TABLE_P (definition)) + { + int outer_level + = !NILP (elt_prefix) ? XVECTOR (elt_prefix)->size : 0; + if (NILP (chartable_kludge)) + { + chartable_kludge + = Fmake_vector (make_number (outer_level + 1), Qnil); + if (outer_level != 0) + bcopy (XVECTOR (elt_prefix)->contents, + XVECTOR (chartable_kludge)->contents, + outer_level * sizeof (Lisp_Object)); + } + XVECTOR (chartable_kludge)->contents[outer_level] + = make_number (i); + describe_vector (definition, chartable_kludge, elt_describer, + partial, shadow, entire_map); + continue; + } + if (first) { insert ("\n", 1); first = 0; } - /* Output the prefix that applies to every entry in this map. */ - if (!NILP (elt_prefix)) - insert1 (elt_prefix); + if (CHAR_TABLE_P (vector)) + { + if (!NILP (elt_prefix)) + { + /* Must combine elt_prefix with i to produce a character + code, then insert that character's description. */ + } + else + { + /* Get the string to describe the character I, and print it. */ + XSETFASTINT (dummy, i); - /* Get the string to describe the character I, and print it. */ - XFASTINT (dummy) = i; + /* THIS gets the string to describe the character DUMMY. */ + this = Fsingle_key_description (dummy); + insert1 (this); + } + } + else + { + /* Output the prefix that applies to every entry in this map. */ + if (!NILP (elt_prefix)) + insert1 (elt_prefix); - /* THIS gets the string to describe the character DUMMY. */ - this = Fsingle_key_description (dummy); - insert1 (this); + /* Get the string to describe the character I, and print it. */ + XSETFASTINT (dummy, i); + + /* THIS gets the string to describe the character DUMMY. */ + this = Fsingle_key_description (dummy); + insert1 (this); + } /* Find all consecutive characters that have the same definition. */ while (i + 1 < XVECTOR (vector)->size && (tem2 = get_keyelt (XVECTOR (vector)->contents[i+1], 0), - EQ (tem2, tem1))) + EQ (tem2, definition))) i++; /* If we have a range of more than one character, @@ -2312,17 +2635,35 @@ describe_vector (vector, elt_prefix, elt_describer, partial, shadow) if (i != XINT (dummy)) { insert (" .. ", 4); - if (!NILP (elt_prefix)) - insert1 (elt_prefix); + if (CHAR_TABLE_P (vector)) + { + if (!NILP (elt_prefix)) + { + /* Must combine elt_prefix with i to produce a character + code, then insert that character's description. */ + } + else + { + XSETFASTINT (dummy, i); - XFASTINT (dummy) = i; - insert1 (Fsingle_key_description (dummy)); + this = Fsingle_key_description (dummy); + insert1 (this); + } + } + else + { + if (!NILP (elt_prefix)) + insert1 (elt_prefix); + + XSETFASTINT (dummy, i); + insert1 (Fsingle_key_description (dummy)); + } } /* Print a description of the definition of this character. elt_describer will take care of spacing out far enough for alignment purposes. */ - (*elt_describer) (tem1); + (*elt_describer) (definition); } UNGCPRO; @@ -2347,18 +2688,18 @@ 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 PRED is non-nil, (funcall PRED SYM) is done\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.") - (string, pred) - Lisp_Object string, pred; + (regexp, predicate) + Lisp_Object regexp, predicate; { struct gcpro gcpro1, gcpro2; - CHECK_STRING (string, 0); - apropos_predicate = pred; + CHECK_STRING (regexp, 0); + apropos_predicate = predicate; GCPRO2 (apropos_predicate, apropos_accumulate); apropos_accumulate = Qnil; - map_obarray (Vobarray, apropos_accum, string); + map_obarray (Vobarray, apropos_accum, regexp); apropos_accumulate = Fsort (apropos_accumulate, Qstring_lessp); UNGCPRO; return apropos_accumulate; @@ -2379,6 +2720,10 @@ syms_of_keymap () Fcons (Fmake_vector (make_number (0400), Qnil), Qnil)); Fset (intern ("global-map"), global_map); + current_global_map = global_map; + staticpro (&global_map); + staticpro (¤t_global_map); + meta_map = Fmake_keymap (Qnil); Fset (intern ("esc-map"), meta_map); Ffset (intern ("ESC-prefix"), meta_map); @@ -2387,6 +2732,12 @@ syms_of_keymap () Fset (intern ("ctl-x-map"), control_x_map); Ffset (intern ("Control-X-prefix"), control_x_map); + 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."); + Vdefine_key_rebound_commands = Qt; + DEFVAR_LISP ("minibuffer-local-map", &Vminibuffer_local_map, "Default keymap to use when reading from the minibuffer."); Vminibuffer_local_map = Fmake_sparse_keymap (Qnil); @@ -2403,8 +2754,6 @@ syms_of_keymap () "Local keymap for minibuffer input with completion, for exact match."); Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil); - current_global_map = global_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\ @@ -2418,19 +2767,28 @@ in the list takes precedence."); 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 subsequences bound by\n\ -function-key-map with their bindings. When the current local and global\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\ +`function-key-map' binds a suffix of the sequence to a vector or string,\n\ +`read-key-sequence' replaces the matching suffix with its binding, and\n\ continues with the new sequence.\n\ \n\ -For example, suppose function-key-map binds `ESC O P' to [f1].\n\ -Typing `ESC O P' to read-key-sequence would return [f1]. Typing\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]."); 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."); + Vkey_translation_map = Qnil; + Qsingle_key_description = intern ("single-key-description"); staticpro (&Qsingle_key_description); @@ -2444,6 +2802,8 @@ key, typing `ESC O P x' would return [f1 x]."); staticpro (&Qnon_ascii); defsubr (&Skeymapp); + defsubr (&Skeymap_parent); + defsubr (&Sset_keymap_parent); defsubr (&Smake_keymap); defsubr (&Smake_sparse_keymap); defsubr (&Scopy_keymap); @@ -2451,12 +2811,8 @@ key, typing `ESC O P x' would return [f1 x]."); defsubr (&Slocal_key_binding); defsubr (&Sglobal_key_binding); defsubr (&Sminor_mode_key_binding); - defsubr (&Sglobal_set_key); - defsubr (&Slocal_set_key); defsubr (&Sdefine_key); defsubr (&Slookup_key); - defsubr (&Sglobal_unset_key); - defsubr (&Slocal_unset_key); defsubr (&Sdefine_prefix_command); defsubr (&Suse_global_map); defsubr (&Suse_local_map);