X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/f63fd14ef3045ed0390707e919ea16e5c356b7e8..e0f24100c74828aadd926f0afa6e3440be8c89d0:/src/keymap.c diff --git a/src/keymap.c b/src/keymap.c index 3630bf7636..e1e45b18d4 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1,12 +1,13 @@ /* Manipulation of keymaps - Copyright (C) 1985, 86,87,88,93,94,95,98,99, 2000, 01, 2004 - Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, + 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, @@ -16,12 +17,15 @@ 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, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #include #include +#if HAVE_ALLOCA_H +# include +#endif #include "lisp.h" #include "commands.h" #include "buffer.h" @@ -32,6 +36,7 @@ Boston, MA 02111-1307, USA. */ #include "puresize.h" #include "intervals.h" #include "keymap.h" +#include "window.h" /* The number of elements in keymap vectors. */ #define DENSE_TABLE_SIZE (0200) @@ -64,6 +69,13 @@ Lisp_Object Vminibuffer_local_ns_map; /* was MinibufLocalCompletionMap */ Lisp_Object Vminibuffer_local_completion_map; +/* keymap used for minibuffers when doing completion in filenames */ +Lisp_Object Vminibuffer_local_filename_completion_map; + +/* keymap used for minibuffers when doing completion in filenames + with require-match*/ +Lisp_Object Vminibuffer_local_must_match_filename_map; + /* keymap used for minibuffers when doing completion and require a match */ /* was MinibufLocalMustMatchMap */ Lisp_Object Vminibuffer_local_must_match_map; @@ -120,20 +132,22 @@ 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, Lisp_Object)), - int, Lisp_Object, Lisp_Object*, int)); + int, Lisp_Object, Lisp_Object*, int, int)); static void describe_vector P_ ((Lisp_Object, Lisp_Object, Lisp_Object, void (*) (Lisp_Object, Lisp_Object), int, - Lisp_Object, Lisp_Object, int *, int, int)); + Lisp_Object, Lisp_Object, int *, + int, int, 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, doc: /* Construct and return a new keymap, of the form (keymap CHARTABLE . ALIST). -CHARTABLE is a char-table that holds the bindings for the ASCII -characters. ALIST is an assoc-list which holds bindings for function keys, -mouse events, and any other things that appear in the input stream. -All entries in it are initially nil, meaning "command undefined". +CHARTABLE is a char-table that holds the bindings for all characters +without modifiers. All entries in it are initially nil, meaning +"command undefined". ALIST is an assoc-list which holds bindings for +function keys, mouse events, and any other things that appear in the +input stream. Initially, ALIST is nil. The optional arg STRING supplies a menu name for the keymap in case you use it as a menu with `x-popup-menu'. */) @@ -212,13 +226,13 @@ when reading a key-sequence to be looked-up in this keymap. */) (map) Lisp_Object map; { + map = get_keymap (map, 0, 0); while (CONSP (map)) { - register Lisp_Object tem; - tem = Fcar (map); + Lisp_Object tem = XCAR (map); if (STRINGP (tem)) return tem; - map = Fcdr (map); + map = XCDR (map); } return Qnil; } @@ -266,7 +280,8 @@ get_keymap (object, error, autoload) /* Should we do an autoload? Autoload forms for keymaps have Qkeymap as their fifth element. */ - if ((autoload || !error) && EQ (XCAR (tem), Qautoload)) + if ((autoload || !error) && EQ (XCAR (tem), Qautoload) + && SYMBOLP (object)) { Lisp_Object tail; @@ -342,7 +357,7 @@ keymap_memberp (map, maps) DEFUN ("set-keymap-parent", Fset_keymap_parent, Sset_keymap_parent, 2, 2, 0, doc: /* Modify KEYMAP to set its parent map to PARENT. -PARENT should be nil or another keymap. */) +Return PARENT. PARENT should be nil or another keymap. */) (keymap, parent) Lisp_Object keymap, parent; { @@ -385,6 +400,7 @@ PARENT should be nil or another keymap. */) if (EQ (XCDR (prev), parent)) RETURN_UNGCPRO (parent); + CHECK_IMPURE (prev); XSETCDR (prev, parent); break; } @@ -526,6 +542,10 @@ access_keymap (map, idx, t_ok, noinherit, autoload) struct gcpro gcpro1; Lisp_Object meta_map; GCPRO1 (map); + /* A strange value in which Meta is set would cause + infinite recursion. Protect against that. */ + if (XINT (meta_prefix_char) & CHAR_META) + meta_prefix_char = make_number (27); meta_map = get_keymap (access_keymap (map, meta_prefix_char, t_ok, noinherit, autoload), 0, autoload); @@ -683,6 +703,7 @@ map_keymap (map, fun, args, data, autoload) struct gcpro gcpro1, gcpro2, gcpro3; Lisp_Object tail; + tail = Qnil; GCPRO3 (map, args, tail); map = get_keymap (map, 1, autoload); for (tail = (CONSP (map) && EQ (Qkeymap, XCAR (map))) ? XCDR (map) : map; @@ -726,16 +747,28 @@ map_keymap_call (key, val, fun, dummy) call2 (fun, key, val); } -DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 2, 0, - doc: /* Call FUNCTION for every binding in KEYMAP. -FUNCTION is called with two arguments: the event and its binding. */) - (function, keymap) - Lisp_Object function, keymap; +DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 3, 0, + doc: /* Call FUNCTION once for each event binding in KEYMAP. +FUNCTION is called with two arguments: the event that is bound, and +the definition it is bound to. If the event is an integer, it may be +a generic character (see Info node `(elisp)Splitting Characters'), and +that means that all actual character events belonging to that generic +character are bound to the definition. + +If KEYMAP has a parent, the parent's bindings are included as well. +This works recursively: if the parent has itself a parent, then the +grandparent's bindings are also included and so on. +usage: (map-keymap FUNCTION KEYMAP) */) + (function, keymap, sort_first) + Lisp_Object function, keymap, sort_first; { if (INTEGERP (function)) /* We have to stop integers early since map_keymap gives them special significance. */ - Fsignal (Qinvalid_function, Fcons (function, Qnil)); + xsignal1 (Qinvalid_function, function); + if (! NILP (sort_first)) + return call3 (intern ("map-keymap-internal"), function, keymap, Qt); + map_keymap (keymap, map_keymap_call, function, NULL, 1); return Qnil; } @@ -750,7 +783,9 @@ FUNCTION is called with two arguments: the event and its binding. */) remove that. Also remove a menu help string as second element. If AUTOLOAD is nonzero, load autoloadable keymaps - that are referred to with indirection. */ + that are referred to with indirection. + + This can GC because menu_item_eval_property calls Feval. */ Lisp_Object get_keyelt (object, autoload) @@ -838,7 +873,7 @@ static Lisp_Object store_in_keymap (keymap, idx, def) Lisp_Object keymap; register Lisp_Object idx; - register Lisp_Object def; + Lisp_Object def; { /* Flush any reverse-map cache. */ where_is_cache = Qnil; @@ -889,6 +924,7 @@ store_in_keymap (keymap, idx, def) { if (NATNUMP (idx) && XFASTINT (idx) < ASIZE (elt)) { + CHECK_IMPURE (elt); ASET (elt, XFASTINT (idx), def); return def; } @@ -914,6 +950,7 @@ store_in_keymap (keymap, idx, def) { if (EQ (idx, XCAR (elt))) { + CHECK_IMPURE (elt); XSETCDR (elt, def); return def; } @@ -931,6 +968,7 @@ store_in_keymap (keymap, idx, def) keymap_end: /* We have scanned the entire keymap, and not found a binding for IDX. Let's add one. */ + CHECK_IMPURE (insertion_point); XSETCDR (insertion_point, Fcons (Fcons (idx, def), XCDR (insertion_point))); } @@ -1086,7 +1124,9 @@ DEF is anything that can be a key's definition: or another symbol whose function definition is used, etc.), a cons (STRING . DEFN), meaning that DEFN is the definition (DEFN should be a valid definition in its own right), - or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP. + or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP, + or an extended menu item definition. + (See info node `(elisp)Extended Menu Items'.) If KEYMAP is a sparse keymap with a binding for KEY, the existing binding is altered. If there is no binding for KEY, the new pair @@ -1107,8 +1147,7 @@ binding KEY to DEF is added at the front of KEYMAP. */) GCPRO3 (keymap, key, def); keymap = get_keymap (keymap, 1, 1); - if (!VECTORP (key) && !STRINGP (key)) - key = wrong_type_argument (Qarrayp, key); + CHECK_VECTOR_OR_STRING (key); length = XFASTINT (Flength (key)); if (length == 0) @@ -1119,6 +1158,20 @@ binding KEY to DEF is added at the front of KEYMAP. */) meta_bit = VECTORP (key) ? meta_modifier : 0x80; + if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0))) + { /* DEF is apparently an XEmacs-style keyboard macro. */ + Lisp_Object tmp = Fmake_vector (make_number (ASIZE (def)), Qnil); + int i = ASIZE (def); + while (--i >= 0) + { + Lisp_Object c = AREF (def, i); + if (CONSP (c) && lucid_event_type_list_p (c)) + c = Fevent_convert_list (c); + ASET (tmp, i, c); + } + def = tmp; + } + idx = 0; while (1) { @@ -1162,24 +1215,52 @@ binding KEY to DEF is added at the front of KEYMAP. */) 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", - SDATA (Fkey_description (key, Qnil))); + error ("Key sequence %s starts with non-prefix key %s", + SDATA (Fkey_description (key, Qnil)), + SDATA (Fkey_description (Fsubstring (key, make_number (0), + make_number (idx)), + Qnil))); } } /* This function may GC (it calls Fkey_binding). */ -DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 1, 0, - doc: /* Return the remapping for command COMMAND in current keymaps. -Returns nil if COMMAND is not remapped (or not a symbol). */) - (command) - Lisp_Object command; +DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 3, 0, + doc: /* Return the remapping for command COMMAND. +Returns nil if COMMAND is not remapped (or not a symbol). + +If the optional argument POSITION is non-nil, it specifies a mouse +position as returned by `event-start' and `event-end', and the +remapping occurs in the keymaps associated with it. It can also be a +number or marker, in which case the keymap properties at the specified +buffer position instead of point are used. The KEYMAPS argument is +ignored if POSITION is non-nil. + +If the optional argument KEYMAPS is non-nil, it should be a list of +keymaps to search for command remapping. Otherwise, search for the +remapping in all currently active keymaps. */) + (command, position, keymaps) + Lisp_Object command, position, keymaps; { if (!SYMBOLP (command)) return Qnil; ASET (command_remapping_vector, 1, command); - return Fkey_binding (command_remapping_vector, Qnil, Qt); + + if (NILP (keymaps)) + return Fkey_binding (command_remapping_vector, Qnil, Qt, position); + else + { + Lisp_Object maps, binding; + + for (maps = keymaps; !NILP (maps); maps = Fcdr (maps)) + { + binding = Flookup_key (Fcar (maps), command_remapping_vector, Qnil); + if (!NILP (binding) && !INTEGERP (binding)) + return binding; + } + return Qnil; + } } /* Value is number if KEY is too long; nil if valid but has no definition. */ @@ -1187,13 +1268,14 @@ Returns nil if COMMAND is not remapped (or not a symbol). */) DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0, doc: /* In keymap KEYMAP, look up key sequence KEY. Return the definition. -nil means undefined. See doc of `define-key' for kinds of definitions. +A value of nil means undefined. See doc of `define-key' +for kinds of definitions. A number as value means KEY is "too long"; that is, characters or symbols in it except for the last one 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. +it takes to reach a non-prefix key. Normally, `lookup-key' ignores bindings for t, which act as default bindings, used when nothing else in the keymap applies; this makes it @@ -1215,8 +1297,7 @@ recognize the default bindings, just as `read-key-sequence' does. */) GCPRO2 (keymap, key); keymap = get_keymap (keymap, 1, 1); - if (!VECTORP (key) && !STRINGP (key)) - key = wrong_type_argument (Qarrayp, key); + CHECK_VECTOR_OR_STRING (key); length = XFASTINT (Flength (key)); if (length == 0) @@ -1231,7 +1312,7 @@ recognize the default bindings, just as `read-key-sequence' does. */) c = Fevent_convert_list (c); /* Turn the 8th bit of string chars into a meta modifier. */ - if (XINT (c) & 0x80 && STRINGP (key)) + if (INTEGERP (c) && XINT (c) & 0x80 && STRINGP (key)) XSETINT (c, (XINT (c) | meta_modifier) & ~0x80); /* Allow string since binding for `menu-bar-select-buffer' @@ -1340,15 +1421,10 @@ silly_event_symbol_error (c) static Lisp_Object *cmm_modes = NULL, *cmm_maps = NULL; static int cmm_size = 0; -/* 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. +/* Store a pointer to an array of the currently active minor modes in + *modeptr, a pointer to an array of the keymaps of the currently + active minor modes in *mapptr, and return the number of maps + *mapptr contains. This function always returns a pointer to the same buffer, and may free or reallocate it, so if you want to keep it for a long time or @@ -1448,9 +1524,7 @@ current_minor_maps (modeptr, mapptr) } /* Get the keymap definition--or nil if it is not defined. */ - temp = internal_condition_case_1 (Findirect_function, - XCDR (assoc), - Qerror, current_minor_maps_error); + temp = Findirect_function (XCDR (assoc), Qt); if (!NILP (temp)) { cmm_modes[i] = var; @@ -1477,10 +1551,13 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and if (!NILP (olp)) { - if (!NILP (Voverriding_local_map)) - keymaps = Fcons (Voverriding_local_map, keymaps); if (!NILP (current_kboard->Voverriding_terminal_local_map)) keymaps = Fcons (current_kboard->Voverriding_terminal_local_map, keymaps); + /* The doc said that overriding-terminal-local-map should + override overriding-local-map. The code used them both, + but it seems clearer to use just one. rms, jan 2005. */ + else if (!NILP (Voverriding_local_map)) + keymaps = Fcons (Voverriding_local_map, keymaps); } if (NILP (XCDR (keymaps))) { @@ -1488,16 +1565,20 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and Lisp_Object *maps; int nmaps, i; + /* This usually returns the buffer's local map, + but that can be overridden by a `local-map' property. */ local = get_local_map (PT, current_buffer, Qlocal_map); if (!NILP (local)) keymaps = Fcons (local, keymaps); + /* Now put all the minor mode keymaps on the list. */ nmaps = current_minor_maps (0, &maps); for (i = --nmaps; i >= 0; i--) if (!NILP (maps[i])) keymaps = Fcons (maps[i], keymaps); + /* This returns nil unless there is a `keymap' property. */ local = get_local_map (PT, current_buffer, Qkeymap); if (!NILP (local)) keymaps = Fcons (local, keymaps); @@ -1508,7 +1589,7 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and /* GC is possible in this function if it autoloads a keymap. */ -DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0, +DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 4, 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. @@ -1522,24 +1603,82 @@ 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 current 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; +is non-nil, `key-binding' returns the unmapped command. + +If KEY is a key sequence initiated with the mouse, the used keymaps +will depend on the clicked mouse position with regard to the buffer +and possible local keymaps on strings. + +If the optional argument POSITION is non-nil, it specifies a mouse +position as returned by `event-start' and `event-end', and the lookup +occurs in the keymaps associated with it instead of KEY. It can also +be a number or marker, in which case the keymap properties at the +specified buffer position instead of point are used. + */) + (key, accept_default, no_remap, position) + Lisp_Object key, accept_default, no_remap, position; { Lisp_Object *maps, value; int nmaps, i; - struct gcpro gcpro1; + struct gcpro gcpro1, gcpro2; + int count = SPECPDL_INDEX (); - GCPRO1 (key); + GCPRO2 (key, position); - if (!NILP (current_kboard->Voverriding_terminal_local_map)) + if (NILP (position) && VECTORP (key)) + { + Lisp_Object event + /* mouse events may have a symbolic prefix indicating the + scrollbar or mode line */ + = AREF (key, SYMBOLP (AREF (key, 0)) && ASIZE (key) > 1 ? 1 : 0); + + /* We are not interested in locations without event data */ + + if (EVENT_HAS_PARAMETERS (event) && CONSP (XCDR (event))) + { + Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (event)); + if (EQ (kind, Qmouse_click)) + position = EVENT_START (event); + } + } + + /* Key sequences beginning with mouse clicks + are read using the keymaps of the buffer clicked on, not + the current buffer. So we may have to switch the buffer + here. */ + + if (CONSP (position)) + { + Lisp_Object window; + + window = POSN_WINDOW (position); + + if (WINDOWP (window) + && BUFFERP (XWINDOW (window)->buffer) + && XBUFFER (XWINDOW (window)->buffer) != current_buffer) + { + /* Arrange to go back to the original buffer once we're done + processing the key sequence. We don't use + save_excursion_{save,restore} here, in analogy to + `read-key-sequence' to avoid saving point. Maybe this + would not be a problem here, but it is easier to keep + things the same. + */ + + record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); + + set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); + } + } + + if (! NILP (current_kboard->Voverriding_terminal_local_map)) { value = Flookup_key (current_kboard->Voverriding_terminal_local_map, key, accept_default); if (! NILP (value) && !INTEGERP (value)) goto done; } - else if (!NILP (Voverriding_local_map)) + else if (! NILP (Voverriding_local_map)) { value = Flookup_key (Voverriding_local_map, key, accept_default); if (! NILP (value) && !INTEGERP (value)) @@ -1547,12 +1686,71 @@ is non-nil, `key-binding' returns the unmapped command. */) } else { - Lisp_Object local; + Lisp_Object keymap, local_map; + EMACS_INT pt; - local = get_local_map (PT, current_buffer, Qkeymap); - if (! NILP (local)) + pt = INTEGERP (position) ? XINT (position) + : MARKERP (position) ? marker_position (position) + : PT; + + local_map = get_local_map (pt, current_buffer, Qlocal_map); + keymap = get_local_map (pt, current_buffer, Qkeymap); + + if (CONSP (position)) + { + Lisp_Object string; + + /* For a mouse click, get the local text-property keymap + of the place clicked on, rather than point. */ + + if (POSN_INBUFFER_P (position)) + { + Lisp_Object pos; + + pos = POSN_BUFFER_POSN (position); + if (INTEGERP (pos) + && XINT (pos) >= BEG && XINT (pos) <= Z) + { + local_map = get_local_map (XINT (pos), + current_buffer, Qlocal_map); + + keymap = get_local_map (XINT (pos), + current_buffer, Qkeymap); + } + } + + /* If on a mode line string with a local keymap, + or for a click on a string, i.e. overlay string or a + string displayed via the `display' property, + consider `local-map' and `keymap' properties of + that string. */ + + if (string = POSN_STRING (position), + (CONSP (string) && STRINGP (XCAR (string)))) + { + Lisp_Object pos, map; + + pos = XCDR (string); + string = XCAR (string); + if (INTEGERP (pos) + && XINT (pos) >= 0 + && XINT (pos) < SCHARS (string)) + { + map = Fget_text_property (pos, Qlocal_map, string); + if (!NILP (map)) + local_map = map; + + map = Fget_text_property (pos, Qkeymap, string); + if (!NILP (map)) + keymap = map; + } + } + + } + + if (! NILP (keymap)) { - value = Flookup_key (local, key, accept_default); + value = Flookup_key (keymap, key, accept_default); if (! NILP (value) && !INTEGERP (value)) goto done; } @@ -1569,10 +1767,9 @@ is non-nil, `key-binding' returns the unmapped command. */) goto done; } - local = get_local_map (PT, current_buffer, Qlocal_map); - if (! NILP (local)) + if (! NILP (local_map)) { - value = Flookup_key (local, key, accept_default); + value = Flookup_key (local_map, key, accept_default); if (! NILP (value) && !INTEGERP (value)) goto done; } @@ -1581,6 +1778,8 @@ is non-nil, `key-binding' returns the unmapped command. */) value = Flookup_key (current_global_map, key, accept_default); done: + unbind_to (count, Qnil); + UNGCPRO; if (NILP (value) || INTEGERP (value)) return Qnil; @@ -1591,7 +1790,7 @@ is non-nil, `key-binding' returns the unmapped command. */) if (NILP (no_remap) && SYMBOLP (value)) { Lisp_Object value1; - if (value1 = Fcommand_remapping (value), !NILP (value1)) + if (value1 = Fcommand_remapping (value, position, Qnil), !NILP (value1)) value = value1; } @@ -1602,7 +1801,7 @@ is non-nil, `key-binding' returns the unmapped command. */) DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 2, 0, doc: /* Return the binding for command KEYS in current local keymap only. -KEYS is a string, a sequence of keystrokes. +KEYS is a string or vector, a sequence of keystrokes. The binding is probably a symbol with a function definition. If optional argument ACCEPT-DEFAULT is non-nil, recognize default @@ -1621,9 +1820,9 @@ bindings; see the description of `lookup-key' for more details about this. */) DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 2, 0, doc: /* Return the binding for command KEYS in current global keymap only. -KEYS is a string, a sequence of keystrokes. +KEYS is a string or vector, a sequence of keystrokes. The binding is probably a symbol with a function definition. -This function's return values are the same as those of lookup-key +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 @@ -1638,7 +1837,7 @@ bindings; see the description of `lookup-key' for more details about this. */) DEFUN ("minor-mode-key-binding", Fminor_mode_key_binding, Sminor_mode_key_binding, 1, 2, 0, doc: /* Find the visible minor mode bindings of KEY. -Return an alist of pairs (MODENAME . BINDING), where MODENAME is the +Return an alist of pairs (MODENAME . BINDING), where MODENAME is 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 @@ -1686,7 +1885,8 @@ If a second optional argument MAPVAR is given, the map is stored as its value instead of as COMMAND's value; but COMMAND is still defined as a function. The third optional argument NAME, if given, supplies a menu name -string for the map. This is required to use the keymap as a menu. */) +string for the map. This is required to use the keymap as a menu. +This function returns COMMAND. */) (command, mapvar, name) Lisp_Object command, mapvar, name; { @@ -1950,7 +2150,7 @@ Lisp_Object Qsingle_key_description, Qkey_description; DEFUN ("key-description", Fkey_description, Skey_description, 1, 2, 0, doc: /* Return a pretty description of key-sequence KEYS. Optional arg PREFIX is the sequence of keys leading up to KEYS. -Control characters turn into "C-foo" sequences, meta into "M-foo" +Control characters turn into "C-foo" sequences, meta into "M-foo", spaces are put between sequence elements, etc. */) (keys, prefix) Lisp_Object keys, prefix; @@ -2057,12 +2257,21 @@ push_key_description (c, p, force_multibyte) int force_multibyte; { unsigned c2; + int valid_p; /* Clear all the meaningless bits above the meta bit. */ c &= meta_modifier | ~ - meta_modifier; c2 = c & ~(alt_modifier | ctrl_modifier | hyper_modifier | meta_modifier | shift_modifier | super_modifier); + valid_p = SINGLE_BYTE_CHAR_P (c2) || char_valid_p (c2, 0); + if (! valid_p) + { + /* KEY_DESCRIPTION_SIZE is large enough for this. */ + p += sprintf (p, "[%d]", c); + return p; + } + if (c & alt_modifier) { *p++ = 'A'; @@ -2150,16 +2359,13 @@ push_key_description (c, p, force_multibyte) } else { - int valid_p = SINGLE_BYTE_CHAR_P (c) || char_valid_p (c, 0); - - if (force_multibyte && valid_p) + if (force_multibyte) { if (SINGLE_BYTE_CHAR_P (c)) c = unibyte_char_to_multibyte (c); p += CHAR_STRING (c, p); } - else if (NILP (current_buffer->enable_multibyte_characters) - || valid_p) + else if (NILP (current_buffer->enable_multibyte_characters)) { int bit_offset; *p++ = '\\'; @@ -2203,16 +2409,29 @@ around function keys and event symbols. */) else SPLIT_CHAR (without_bits, charset, c1, c2); - if (charset - && CHARSET_DEFINED_P (charset) - && ((c1 >= 0 && c1 < 32) - || (c2 >= 0 && c2 < 32))) + if (! CHAR_VALID_P (without_bits, 1)) + { + char buf[256]; + + sprintf (buf, "Invalid char code %d", XINT (key)); + return build_string (buf); + } + else if (charset + && ((c1 == 0 && c2 == -1) || c2 == 0)) { /* Handle a generic character. */ Lisp_Object name; - name = CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX); + char buf[256]; + + name = CHARSET_TABLE_INFO (charset, CHARSET_SHORT_NAME_IDX); CHECK_STRING (name); - return concat2 (build_string ("Character set "), name); + if (c1 == 0) + /* Only a charset is specified. */ + sprintf (buf, "Generic char %d: all of ", without_bits); + else + /* 1st code-point of 2-dimensional charset is specified. */ + sprintf (buf, "Generic char %d: row %d of ", without_bits, c1); + return concat2 (build_string (buf), name); } else { @@ -2282,7 +2501,11 @@ push_text_char_description (c, p) DEFUN ("text-char-description", Ftext_char_description, Stext_char_description, 1, 1, 0, doc: /* Return a pretty description of file-character CHARACTER. -Control characters turn into "^char", etc. */) +Control characters turn into "^char", etc. This differs from +`single-key-description' which turns them into "C-char". +Also, this function recognizes the 2**7 bit as the Meta character, +whereas `single-key-description' uses the 2**27 bit for Meta. +See Info node `(elisp)Describing Characters' for examples. */) (character) Lisp_Object character; { @@ -2348,7 +2571,14 @@ shadow_lookup (shadow, key, flag) for (tail = shadow; CONSP (tail); tail = XCDR (tail)) { value = Flookup_key (XCAR (tail), key, flag); - if (!NILP (value) && !NATNUMP (value)) + if (NATNUMP (value)) + { + value = Flookup_key (XCAR (tail), + Fsubstring (key, make_number (0), value), flag); + if (!NILP (value)) + return Qnil; + } + else if (!NILP (value)) return value; } return Qnil; @@ -2369,15 +2599,6 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) /* 1 means ignore all menu bindings entirely. */ int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); - /* If this command is remapped, then it has no key bindings - of its own. */ - if (NILP (no_remap) && SYMBOLP (definition)) - { - Lisp_Object tem; - if (tem = Fcommand_remapping (definition), !NILP (tem)) - return Qnil; - } - found = keymaps; while (CONSP (found)) { @@ -2391,6 +2612,13 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) found = Qnil; sequences = Qnil; + /* If this command is remapped, then it has no key bindings + of its own. */ + if (NILP (no_remap) + && SYMBOLP (definition) + && !NILP (Fcommand_remapping (definition, Qnil, keymaps))) + RETURN_UNGCPRO (Qnil); + for (; !NILP (maps); maps = Fcdr (maps)) { /* Key sequence to reach map, and the map that it reaches */ @@ -2528,6 +2756,19 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) continue; record_sequence: + /* Don't annoy user with strings from a menu such as + Select Paste. Change them all to "(any string)", + so that there seems to be only one menu item + to report. */ + if (! NILP (sequence)) + { + Lisp_Object tem; + tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1)); + if (STRINGP (tem)) + Faset (sequence, make_number (XVECTOR (sequence)->size - 1), + build_string ("(any string)")); + } + /* 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))) @@ -2567,7 +2808,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0, doc: /* Return list of keys that invoke DEFINITION. -If KEYMAP is non-nil, search only KEYMAP and the global keymap. +If KEYMAP is a keymap, search only KEYMAP and the global keymap. If KEYMAP is nil, search all the currently active keymaps. If KEYMAP is a list of keymaps, search only those keymaps. @@ -2575,8 +2816,8 @@ If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, rather than a list of all possible key sequences. If FIRSTONLY is the symbol `non-ascii', return the first binding found, no matter what it is. -If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters, -and entirely reject menu bindings. +If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters +\(or their meta variants) and entirely reject menu bindings. If optional 4th arg NOINDIRECT is non-nil, don't follow indirections to other keymaps or slots. This makes it possible to search for an @@ -2705,7 +2946,7 @@ where_is_internal_2 (args, key, binding) } -/* This function cannot GC. */ +/* This function can GC because get_keyelt can. */ static Lisp_Object where_is_internal_1 (binding, key, definition, noindirect, this, last, @@ -2771,6 +3012,8 @@ Keyboard translations:\n\n\ You type Translation\n\ -------- -----------\n"; + CHECK_BUFFER (buffer); + shadow = Qnil; GCPRO1 (shadow); @@ -2802,6 +3045,9 @@ You type Translation\n\ insert (buf, bufend - buf); insert ("\n", 1); + + /* Insert calls signal_after_change which may GC. */ + translate = SDATA (Vkeyboard_translate_table); } insert ("\n", 1); @@ -2809,7 +3055,7 @@ You type Translation\n\ if (!NILP (Vkey_translation_map)) describe_map_tree (Vkey_translation_map, 0, Qnil, prefix, - "Key translations", nomenu, 1, 0); + "Key translations", nomenu, 1, 0, 0); /* Print the (major mode) local map. */ @@ -2822,7 +3068,7 @@ You type Translation\n\ if (!NILP (start1)) { describe_map_tree (start1, 1, shadow, prefix, - "\f\nOverriding Bindings", nomenu, 0, 0); + "\f\nOverriding Bindings", nomenu, 0, 0, 0); shadow = Fcons (start1, shadow); } else @@ -2843,7 +3089,8 @@ You type Translation\n\ if (!NILP (start1)) { describe_map_tree (start1, 1, shadow, prefix, - "\f\n`keymap' Property Bindings", nomenu, 0, 0); + "\f\n`keymap' Property Bindings", nomenu, + 0, 0, 0); shadow = Fcons (start1, shadow); } @@ -2871,7 +3118,8 @@ You type Translation\n\ p += sizeof (" Minor Mode Bindings") - 1; *p = 0; - describe_map_tree (maps[i], 1, shadow, prefix, title, nomenu, 0, 0); + describe_map_tree (maps[i], 1, shadow, prefix, + title, nomenu, 0, 0, 0); shadow = Fcons (maps[i], shadow); } @@ -2881,23 +3129,23 @@ You type Translation\n\ { if (EQ (start1, XBUFFER (buffer)->keymap)) describe_map_tree (start1, 1, shadow, prefix, - "\f\nMajor Mode Bindings", nomenu, 0, 0); + "\f\nMajor Mode Bindings", nomenu, 0, 0, 0); else describe_map_tree (start1, 1, shadow, prefix, "\f\n`local-map' Property Bindings", - nomenu, 0, 0); + nomenu, 0, 0, 0); shadow = Fcons (start1, shadow); } } describe_map_tree (current_global_map, 1, shadow, prefix, - "\f\nGlobal Bindings", nomenu, 0, 1); + "\f\nGlobal Bindings", nomenu, 0, 1, 0); /* Print the function-key-map translations under this prefix. */ if (!NILP (Vfunction_key_map)) describe_map_tree (Vfunction_key_map, 0, Qnil, prefix, - "\f\nFunction key map translations", nomenu, 1, 0); + "\f\nFunction key map translations", nomenu, 1, 0, 0); UNGCPRO; return Qnil; @@ -2918,17 +3166,21 @@ You type Translation\n\ so print strings and vectors differently. If ALWAYS_TITLE is nonzero, print the title even if there are no maps - to look through. */ + to look through. + + If MENTION_SHADOW is nonzero, then when something is shadowed by SHADOW, + don't omit it; instead, mention it but say it is shadowed. */ void describe_map_tree (startmap, partial, shadow, prefix, title, nomenu, transl, - always_title) + always_title, mention_shadow) Lisp_Object startmap, shadow, prefix; int partial; char *title; int nomenu; int transl; int always_title; + int mention_shadow; { Lisp_Object maps, orig_maps, seen, sub_shadows; struct gcpro gcpro1, gcpro2, gcpro3; @@ -3030,7 +3282,7 @@ key binding\n\ describe_map (Fcdr (elt), prefix, transl ? describe_translation : describe_command, - partial, sub_shadows, &seen, nomenu); + partial, sub_shadows, &seen, nomenu, mention_shadow); skip: ; } @@ -3105,12 +3357,41 @@ describe_translation (definition, args) insert_string ("??\n"); } +/* describe_map puts all the usable elements of a sparse keymap + into an array of `struct describe_map_elt', + then sorts them by the events. */ + +struct describe_map_elt { Lisp_Object event; Lisp_Object definition; int shadowed; }; + +/* qsort comparison function for sorting `struct describe_map_elt' by + the event field. */ + +static int +describe_map_compare (aa, bb) + const void *aa, *bb; +{ + const struct describe_map_elt *a = aa, *b = bb; + if (INTEGERP (a->event) && INTEGERP (b->event)) + return ((XINT (a->event) > XINT (b->event)) + - (XINT (a->event) < XINT (b->event))); + if (!INTEGERP (a->event) && INTEGERP (b->event)) + return 1; + if (INTEGERP (a->event) && !INTEGERP (b->event)) + return -1; + if (SYMBOLP (a->event) && SYMBOLP (b->event)) + return (!NILP (Fstring_lessp (a->event, b->event)) ? -1 + : !NILP (Fstring_lessp (b->event, a->event)) ? 1 + : 0); + return 0; +} + /* Describe the contents of map MAP, assuming that this map itself is reached by the sequence of prefix keys PREFIX (a string or vector). PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */ static void -describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) +describe_map (map, prefix, elt_describer, partial, shadow, + seen, nomenu, mention_shadow) register Lisp_Object map; Lisp_Object prefix; void (*elt_describer) P_ ((Lisp_Object, Lisp_Object)); @@ -3118,6 +3399,7 @@ describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) Lisp_Object shadow; Lisp_Object *seen; int nomenu; + int mention_shadow; { Lisp_Object tail, definition, event; Lisp_Object tem; @@ -3126,6 +3408,13 @@ describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) int first = 1; struct gcpro gcpro1, gcpro2, gcpro3; + /* These accumulate the values from sparse keymap bindings, + so we can sort them and handle them in order. */ + int length_needed = 0; + struct describe_map_elt *vect; + int slots_used = 0; + int i; + suppress = Qnil; if (partial) @@ -3137,6 +3426,12 @@ describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) kludge = Fmake_vector (make_number (1), Qnil); definition = Qnil; + for (tail = map; CONSP (tail); tail = XCDR (tail)) + length_needed++; + + vect = ((struct describe_map_elt *) + alloca (sizeof (struct describe_map_elt) * length_needed)); + GCPRO3 (prefix, definition, kludge); for (tail = map; CONSP (tail); tail = XCDR (tail)) @@ -3147,9 +3442,11 @@ describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) || CHAR_TABLE_P (XCAR (tail))) describe_vector (XCAR (tail), prefix, Qnil, elt_describer, partial, shadow, map, - (int *)0, 0, 1); + (int *)0, 0, 1, mention_shadow); else if (CONSP (XCAR (tail))) { + int this_shadowed = 0; + event = XCAR (XCAR (tail)); /* Ignore bindings whose "prefix" are not really valid events. @@ -3178,26 +3475,28 @@ describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) if (!NILP (shadow)) { tem = shadow_lookup (shadow, kludge, Qt); - if (!NILP (tem)) continue; + if (!NILP (tem)) + { + /* If both bindings are keymaps, this key is a prefix key, + so don't say it is shadowed. */ + if (KEYMAPP (definition) && KEYMAPP (tem)) + ; + /* Avoid generating duplicate entries if the + shadowed binding has the same definition. */ + else if (mention_shadow && !EQ (tem, definition)) + this_shadowed = 1; + else + continue; + } } tem = Flookup_key (map, kludge, Qt); if (!EQ (tem, definition)) continue; - if (first) - { - previous_description_column = 0; - insert ("\n", 1); - first = 0; - } - - /* THIS gets the string to describe the character EVENT. */ - insert1 (Fkey_description (kludge, prefix)); - - /* 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, Qnil); + vect[slots_used].event = event; + vect[slots_used].definition = definition; + vect[slots_used].shadowed = this_shadowed; + slots_used++; } else if (EQ (XCAR (tail), Qkeymap)) { @@ -3211,6 +3510,68 @@ describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu) } } + /* If we found some sparse map events, sort them. */ + + qsort (vect, slots_used, sizeof (struct describe_map_elt), + describe_map_compare); + + /* Now output them in sorted order. */ + + for (i = 0; i < slots_used; i++) + { + Lisp_Object start, end; + + if (first) + { + previous_description_column = 0; + insert ("\n", 1); + first = 0; + } + + ASET (kludge, 0, vect[i].event); + start = vect[i].event; + end = start; + + definition = vect[i].definition; + + /* Find consecutive chars that are identically defined. */ + if (INTEGERP (vect[i].event)) + { + while (i + 1 < slots_used + && EQ (vect[i+1].event, make_number (XINT (vect[i].event) + 1)) + && !NILP (Fequal (vect[i + 1].definition, definition)) + && vect[i].shadowed == vect[i + 1].shadowed) + i++; + end = vect[i].event; + } + + /* Now START .. END is the range to describe next. */ + + /* Insert the string to describe the event START. */ + insert1 (Fkey_description (kludge, prefix)); + + if (!EQ (start, end)) + { + insert (" .. ", 4); + + ASET (kludge, 0, end); + /* Insert the string to describe the character END. */ + insert1 (Fkey_description (kludge, prefix)); + } + + /* Print a description of the definition of this character. + elt_describer will take care of spacing out far enough + for alignment purposes. */ + (*elt_describer) (vect[i].definition, Qnil); + + if (vect[i].shadowed) + { + SET_PT (PT - 1); + insert_string ("\n (that binding is currently shadowed by another mode)"); + SET_PT (PT + 1); + } + } + UNGCPRO; } @@ -3225,7 +3586,8 @@ describe_vector_princ (elt, fun) 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. */) +This is text showing the elements of vector matched against indices. +DESCRIBER is the output function used; nil means use `princ'. */) (vector, describer) Lisp_Object vector, describer; { @@ -3235,7 +3597,7 @@ This is text showing the elements of vector matched against indices. */) specbind (Qstandard_output, Fcurrent_buffer ()); CHECK_VECTOR_OR_CHAR_TABLE (vector); describe_vector (vector, Qnil, describer, describe_vector_princ, 0, - Qnil, Qnil, (int *)0, 0, 0); + Qnil, Qnil, (int *)0, 0, 0, 0); return unbind_to (count, Qnil); } @@ -3277,7 +3639,8 @@ This is text showing the elements of vector matched against indices. */) static void describe_vector (vector, prefix, args, elt_describer, partial, shadow, entire_map, - indices, char_table_depth, keymap_p) + indices, char_table_depth, keymap_p, + mention_shadow) register Lisp_Object vector; Lisp_Object prefix, args; void (*elt_describer) P_ ((Lisp_Object, Lisp_Object)); @@ -3287,6 +3650,7 @@ describe_vector (vector, prefix, args, elt_describer, int *indices; int char_table_depth; int keymap_p; + int mention_shadow; { Lisp_Object definition; Lisp_Object tem2; @@ -3370,6 +3734,7 @@ describe_vector (vector, prefix, args, elt_describer, for (i = from; i < to; i++) { + int this_shadowed = 0; QUIT; if (CHAR_TABLE_P (vector)) @@ -3429,7 +3794,13 @@ describe_vector (vector, prefix, args, elt_describer, tem = shadow_lookup (shadow, kludge, Qt); - if (!NILP (tem)) continue; + if (!NILP (tem)) + { + if (mention_shadow) + this_shadowed = 1; + else + continue; + } } /* Ignore this definition if it is shadowed by an earlier @@ -3505,7 +3876,8 @@ describe_vector (vector, prefix, args, elt_describer, insert ("\n", 1); describe_vector (definition, prefix, args, elt_describer, partial, shadow, entire_map, - indices, char_table_depth + 1, keymap_p); + indices, char_table_depth + 1, keymap_p, + mention_shadow); continue; } @@ -3579,6 +3951,13 @@ describe_vector (vector, prefix, args, elt_describer, elt_describer will take care of spacing out far enough for alignment purposes. */ (*elt_describer) (definition, args); + + if (this_shadowed) + { + SET_PT (PT - 1); + insert_string (" (binding currently shadowed)"); + SET_PT (PT + 1); + } } /* For (sub) char-table, print `defalt' slot at last. */ @@ -3690,16 +4069,31 @@ don't alter it yourself. */); Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil); Fset_keymap_parent (Vminibuffer_local_completion_map, Vminibuffer_local_map); + DEFVAR_LISP ("minibuffer-local-filename-completion-map", + &Vminibuffer_local_filename_completion_map, + doc: /* Local keymap for minibuffer input with completion for filenames. */); + Vminibuffer_local_filename_completion_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_filename_completion_map, + Vminibuffer_local_completion_map); + + DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map, 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 ("minibuffer-local-must-match-filename-map", + &Vminibuffer_local_must_match_filename_map, + doc: /* Local keymap for minibuffer input with completion for filenames with exact match. */); + Vminibuffer_local_must_match_filename_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_must_match_filename_map, + Vminibuffer_local_must_match_map); + DEFVAR_LISP ("minor-mode-map-alist", &Vminor_mode_map_alist, 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. +key sequences and look up bindings if 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; @@ -3722,9 +4116,9 @@ the same way. The "active" keymaps in each alist are used before DEFVAR_LISP ("function-key-map", &Vfunction_key_map, - 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. + doc: /* Keymap that translates key sequences to key sequences during input. +This is used mainly for mapping ASCII function key sequences into +real Emacs function key events (symbols). The `read-key-sequence' function replaces any subsequence bound by `function-key-map' with its binding. More precisely, when the active @@ -3733,6 +4127,9 @@ keymaps have no binding for the current key sequence but `read-key-sequence' replaces the matching suffix with its binding, and continues with the new sequence. +If the binding is a function, it is called with one argument (the prompt) +and its return value (a key sequence) is used. + The events that come from bindings in `function-key-map' are not themselves looked up in `function-key-map'. @@ -3745,7 +4142,7 @@ key, typing `ESC O P x' would return [f1 x]. */); DEFVAR_LISP ("key-translation-map", &Vkey_translation_map, doc: /* Keymap of key translations that can override keymaps. This keymap works like `function-key-map', but comes after that, -and applies even for keys that have ordinary bindings. */); +and its non-prefix bindings override ordinary bindings. */); Vkey_translation_map = Qnil; staticpro (&Vmouse_events);