# HG changeset patch # User David Kastrup # Date 1158304755 0 # Node ID 25c755416160252b69fcb8933ae720f425ecdd62 # Parent d688b3faf96b1a0eefe6179e3b06c23e9ac14311 * NEWS: explain new behavior and arguments of `key-binding' and `command-remapping'. * keymaps.texi (Active Keymaps): Adapt description to use `get-char-property' instead `get-text-property'. Explain how mouse events change this. Explain the new optional argument of `key-binding' and its mouse-dependent lookup. (Searching Keymaps): Adapt description similarly. Explain the new optional argument of `command-remapping'. * Makefile.in (keymap.o): Add "keymap.h" and "window.h" dependencies. * keymap.c: include "window.h". (Fcommand_remapping): New optional POSITION argument. (Fkey_binding): New optional POSITION argument. Completely rework handling of mouse clicks to get the same order of keymaps as `read-key-sequence' and heed POSITION. Also temporarily switch buffers to location of mouse click and back. * keyboard.c (command_loop_1): Adjust call of `Fcommand_remapping' for additional argument. (parse_menu_item): Adjust call of `Fkey_binding' for additional argument. (read_key_sequence): If there are both `local-map' and `keymap' text properties at some buffer position, heed both. * keymap.h: Declare additional optional arguments of `Fcommand_remapping' and `Fkey_binding'. diff -r d688b3faf96b -r 25c755416160 etc/ChangeLog --- a/etc/ChangeLog Fri Sep 15 03:55:23 2006 +0000 +++ b/etc/ChangeLog Fri Sep 15 07:19:15 2006 +0000 @@ -1,3 +1,8 @@ +2006-09-15 David Kastrup + + * NEWS: explain new behavior and arguments of `key-binding' and + `command-remapping'. + 2006-09-11 Paul Eggert * NEWS: In terminal-oriented subshells, the EMACS environment @@ -102,7 +107,7 @@ * PROBLEMS: Emacs now requires ws2_32.dll on Windows. -2006-07-14 K,Aa(Broly L,Bu(Brentey +2006-07-14 K,Aa(Broly L$,1 q(Brentey * HELLO: Update Hungarian sample. diff -r d688b3faf96b -r 25c755416160 etc/NEWS --- a/etc/NEWS Fri Sep 15 03:55:23 2006 +0000 +++ b/etc/NEWS Fri Sep 15 07:19:15 2006 +0000 @@ -4681,6 +4681,12 @@ text properties, according to their stickiness. This also means that it works with empty overlays. The same hold for the `local-map' property. +*** `key-binding' will now look up mouse-specific bindings. The +keymaps consulted by `key-binding' will get adapted if the key +sequence is started with a mouse event. Instead of letting the click +position be determined from the key sequence itself, it is also +possible to specify it with an optional argument explicitly. + *** Dense keymaps now handle inheritance correctly. Previously a dense keymap would hide all of the simple-char key diff -r d688b3faf96b -r 25c755416160 lispref/ChangeLog --- a/lispref/ChangeLog Fri Sep 15 03:55:23 2006 +0000 +++ b/lispref/ChangeLog Fri Sep 15 07:19:15 2006 +0000 @@ -1,3 +1,12 @@ +2006-09-15 David Kastrup + + * keymaps.texi (Active Keymaps): Adapt description to use + `get-char-property' instead `get-text-property'. Explain how + mouse events change this. Explain the new optional argument of + `key-binding' and its mouse-dependent lookup. + (Searching Keymaps): Adapt description similarly. Explain the new + optional argument of `command-remapping'. + 2006-09-14 Richard Stallman * keymaps.texi (Searching Keymaps): Clarification. @@ -10,6 +19,7 @@ (Basic Char Syntax, General Escape Syntax) (Ctl-Char Syntax, Meta-Char Syntax): New subnodes. +>>>>>>> 1.751 2006-09-11 Richard Stallman * display.texi (Display Table Format): Wording clarification. @@ -4871,7 +4881,7 @@ (info): Add target. (installall): Target removed. -2001-10-31 Pavel Jan,Bm(Bk +2001-10-31 Pavel Jan,Am(Bk * tips.texi (Coding Conventions): Fix typo. diff -r d688b3faf96b -r 25c755416160 lispref/keymaps.texi --- a/lispref/keymaps.texi Fri Sep 15 03:55:23 2006 +0000 +++ b/lispref/keymaps.texi Fri Sep 15 07:19:15 2006 +0000 @@ -576,6 +576,16 @@ input key sequence in all these keymaps. @xref{Searching Keymaps}, for more details of this procedure. +This process is somewhat modified for mouse events: the local modes and +keymaps of the buffer corresponding to the mouse click position are +searched instead, text properties are taken from the mouse click +position in the buffer rather than point, and if the click happens on a +string embedded with a @code{display}, @code{before-string}, or +@code{after-string} text property (@pxref{Special Properties}) or +overlay property (@pxref{Overlay Properties}), any non-@code{nil} maps +specified with text properties of this string are searched instead of +those of the buffer. + The @dfn{global keymap} holds the bindings of keys that are defined regardless of the current buffer, such as @kbd{C-f}. The variable @code{global-map} holds this keymap, which is always active. @@ -632,25 +642,27 @@ non-@code{nil} then it pays attention to them. @end defun -@defun key-binding key &optional accept-defaults no-remap -This function returns the binding for @var{key} according to the -current active keymaps. The result is @code{nil} if @var{key} is -undefined in the keymaps. +@defun key-binding key &optional accept-defaults no-remap position +This function returns the binding for @var{key} according to the current +active keymaps. The result is @code{nil} if @var{key} is undefined in +the keymaps. If @var{key} is a key sequence started with the mouse, the +consulted maps will be changed accordingly. @c Emacs 19 feature The argument @var{accept-defaults} controls checking for default bindings, as in @code{lookup-key} (above). -When @var{key} is a vector containing an input event, such as a mouse -click, @code{key-binding} first looks for the binding in the keymaps -that would be active at the position where the click was done. - When commands are remapped (@pxref{Remapping Commands}), @code{key-binding} normally processes command remappings so as to returns the remapped command that will actually be executed. However, if @var{no-remap} is non-@code{nil}, @code{key-binding} ignores remappings and returns the binding directly specified for @var{key}. +If @var{position} is non-@code{nil}, it specifies either a buffer +position or a position like those returned from @code{event-start}. In +this case, @var{position} instead of @var{key} determines the +click-specific maps. + An error is signaled if @var{key} is not a string or a vector. @example @@ -674,21 +686,24 @@ (@var{find-in} overriding-terminal-local-map) (if overriding-local-map (@var{find-in} overriding-local-map) - (or (@var{find-in} (get-text-property (point) 'keymap)) + (or (@var{find-in} (get-char-property (point) 'keymap)) (@var{find-in-any} emulation-mode-map-alists) (@var{find-in-any} minor-mode-overriding-map-alist) (@var{find-in-any} minor-mode-map-alist) (if (get-text-property (point) 'local-map) - (@var{find-in} (get-text-property (point) 'local-map)) + (@var{find-in} (get-char-property (point) 'local-map)) (@var{find-in} (current-local-map)))))) (@var{find-in} (current-global-map))) @end lisp @noindent -The @var{find-in} and @var{find-in-any} are pseudo functions that -search in one keymap and in an alist of keymaps, respectively. -(Searching a single keymap for a binding is called @dfn{key lookup}; -see @ref{Key Lookup}.) +The @var{find-in} and @var{find-in-any} are pseudo functions that search +in one keymap and in an alist of keymaps, respectively. (Searching a +single keymap for a binding is called @dfn{key lookup}; see @ref{Key +Lookup}.) Mouse events on strings will use text properties from the +string if non-@code{nil} instead of the buffer. Also, point and current +buffer for mouse-based events are switched to correspond to the position +of the event start while performing the lookup. @enumerate @item @@ -1450,11 +1465,13 @@ if an ordinary binding specifies @code{my-kill-line}, this keymap will remap it to @code{my-other-kill-line}. -@defun command-remapping command -This function returns the remapping for @var{command} (a symbol), -given the current active keymaps. If @var{command} is not remapped -(which is the usual situation), or not a symbol, the function returns -@code{nil}. +@defun command-remapping command &optional position +This function returns the remapping for @var{command} (a symbol), given +the current active keymaps. If @var{command} is not remapped (which is +the usual situation), or not a symbol, the function returns @code{nil}. +@code{position} can optionally specify a buffer position or a position +like those returned from @code{event-start}: in that case, the active +maps are changed like they are in @code{key-binding}. @end defun @node Translation Keymaps diff -r d688b3faf96b -r 25c755416160 src/ChangeLog --- a/src/ChangeLog Fri Sep 15 03:55:23 2006 +0000 +++ b/src/ChangeLog Fri Sep 15 07:19:15 2006 +0000 @@ -1,3 +1,25 @@ +2006-09-15 David Kastrup + + * Makefile.in (keymap.o): Add "keymap.h" and "window.h" + dependencies. + + * keymap.c: include "window.h". + (Fcommand_remapping): New optional POSITION argument. + (Fkey_binding): New optional POSITION argument. Completely rework + handling of mouse clicks to get the same order of keymaps as + `read-key-sequence' and heed POSITION. Also temporarily switch + buffers to location of mouse click and back. + + * keyboard.c (command_loop_1): Adjust call of `Fcommand_remapping' + for additional argument. + (parse_menu_item): Adjust call of `Fkey_binding' for additional + argument. + (read_key_sequence): If there are both `local-map' and `keymap' + text properties at some buffer position, heed both. + + * keymap.h: Declare additional optional arguments of + `Fcommand_remapping' and `Fkey_binding'. + 2006-09-15 Juanma Barranquero * indent.c (Fcurrent_column, Findent_to): Fix typos in docstring. diff -r d688b3faf96b -r 25c755416160 src/Makefile.in --- a/src/Makefile.in Fri Sep 15 03:55:23 2006 +0000 +++ b/src/Makefile.in Fri Sep 15 07:19:15 2006 +0000 @@ -1146,7 +1146,8 @@ systty.h systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \ atimer.h xterm.h puresize.h msdos.h keymap.h w32term.h macterm.h $(config_h) keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \ - atimer.h systime.h puresize.h charset.h intervals.h $(config_h) + atimer.h systime.h puresize.h charset.h intervals.h keymap.h window.h \ + $(config_h) lastfile.o: lastfile.c $(config_h) macros.o: macros.c window.h buffer.h commands.h macros.h keyboard.h \ dispextern.h $(config_h) diff -r d688b3faf96b -r 25c755416160 src/keyboard.c --- a/src/keyboard.c Fri Sep 15 03:55:23 2006 +0000 +++ b/src/keyboard.c Fri Sep 15 07:19:15 2006 +0000 @@ -1674,7 +1674,7 @@ if (SYMBOLP (cmd)) { Lisp_Object cmd1; - if (cmd1 = Fcommand_remapping (cmd), !NILP (cmd1)) + if (cmd1 = Fcommand_remapping (cmd, Qnil), !NILP (cmd1)) cmd = cmd1; } @@ -7517,7 +7517,7 @@ Lisp_Object prefix; if (!NILP (tem)) - tem = Fkey_binding (tem, Qnil, Qnil); + tem = Fkey_binding (tem, Qnil, Qnil, Qnil); prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ); if (CONSP (prefix)) @@ -9134,16 +9134,19 @@ if (!EQ (map_here, orig_local_map)) { orig_local_map = map_here; - keybuf[t] = key; - mock_input = t + 1; - - goto replay_sequence; + ++localized_local_map; } + map_here = get_local_map (XINT (pos), current_buffer, Qkeymap); if (!EQ (map_here, orig_keymap)) { orig_keymap = map_here; + ++localized_local_map; + } + + if (localized_local_map > 1) + { keybuf[t] = key; mock_input = t + 1; diff -r d688b3faf96b -r 25c755416160 src/keymap.c --- a/src/keymap.c Fri Sep 15 03:55:23 2006 +0000 +++ b/src/keymap.c Fri Sep 15 07:19:15 2006 +0000 @@ -33,6 +33,7 @@ #include "puresize.h" #include "intervals.h" #include "keymap.h" +#include "window.h" /* The number of elements in keymap vectors. */ #define DENSE_TABLE_SIZE (0200) @@ -1216,17 +1217,23 @@ /* This function may GC (it calls Fkey_binding). */ -DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 1, 0, +DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 2, 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; +Returns nil if COMMAND is not remapped (or not a symbol). + +If the optional argument POSITION is non-nil, it specifies a mouse +position as returned by `event-start' and `event-end', and the +remapping occurs in the keymaps associated with it. It can also be a +number or marker, in which case the keymap properties at the specified +buffer position instead of point are used. */) + (command, position) + Lisp_Object command, position; { if (!SYMBOLP (command)) return Qnil; ASET (command_remapping_vector, 1, command); - return Fkey_binding (command_remapping_vector, Qnil, Qt); + return Fkey_binding (command_remapping_vector, Qnil, Qt, position); } /* Value is number if KEY is too long; nil if valid but has no definition. */ @@ -1552,7 +1559,7 @@ /* 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. @@ -1566,55 +1573,86 @@ 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; - - GCPRO1 (key); - -#ifdef HAVE_MOUSE - if (VECTORP (key) && ASIZE (key) > 0) + struct gcpro gcpro1, gcpro2; + int count = SPECPDL_INDEX (); + + GCPRO2 (key, position); + + if (NILP (position)) { - Lisp_Object ev, pos; - if ((ev = AREF (key, 0), CONSP (ev)) - && SYMBOLP (XCAR (ev)) - && CONSP (XCDR (ev)) - && (pos = XCAR (XCDR (ev)), CONSP (pos)) - && XINT (Flength (pos)) == 10 - && INTEGERP (XCAR (XCDR (pos)))) + Lisp_Object event; + /* mouse events may have a symbolic prefix indicating the + scrollbar or mode line */ + if (SYMBOLP (AREF (key, 0)) && ASIZE (key) > 1) + event = AREF (key, 1); + else + event = AREF (key, 0); + + /* We are not interested in locations without event data */ + + if (EVENT_HAS_PARAMETERS (event)) { + Lisp_Object kind; + + kind = EVENT_HEAD_KIND (EVENT_HEAD (event)); + if (EQ (kind, Qmouse_click)) + position = EVENT_START (event); + } + } + + /* 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) { - Lisp_Object map, object; - - object = Fnth (make_number(4), pos); - - if (CONSP (object)) - map = Fget_char_property (XCDR (object), Qkeymap, XCAR (object)); - else - map = Fget_char_property (XCAR (XCDR (pos)), Qkeymap, - Fwindow_buffer (XCAR (pos))); - - if (!NILP (Fkeymapp (map))) - { - value = Flookup_key (map, key, accept_default); - if (! NILP (value) && !INTEGERP (value)) - goto done; - } + /* 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)); } } -#endif /* HAVE_MOUSE */ - - if (!NILP (current_kboard->Voverriding_terminal_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)) 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)) @@ -1622,12 +1660,72 @@ } else { - Lisp_Object local; - - local = get_local_map (PT, current_buffer, Qkeymap); - if (! NILP (local)) + Lisp_Object keymap, local_map; + EMACS_INT pt; + + 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)) { - value = Flookup_key (local, key, accept_default); + Lisp_Object string, window; + + window = POSN_WINDOW (position); + + /* 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 (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 (keymap, key, accept_default); if (! NILP (value) && !INTEGERP (value)) goto done; } @@ -1644,10 +1742,9 @@ 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; } @@ -1656,6 +1753,8 @@ value = Flookup_key (current_global_map, key, accept_default); done: + unbind_to (count, Qnil); + UNGCPRO; if (NILP (value) || INTEGERP (value)) return Qnil; @@ -1666,7 +1765,7 @@ if (NILP (no_remap) && SYMBOLP (value)) { Lisp_Object value1; - if (value1 = Fcommand_remapping (value), !NILP (value1)) + if (value1 = Fcommand_remapping (value, position), !NILP (value1)) value = value1; } @@ -2467,7 +2566,7 @@ if (NILP (no_remap) && SYMBOLP (definition)) { Lisp_Object tem; - if (tem = Fcommand_remapping (definition), !NILP (tem)) + if (tem = Fcommand_remapping (definition, Qnil), !NILP (tem)) return Qnil; } diff -r d688b3faf96b -r 25c755416160 src/keymap.h --- a/src/keymap.h Fri Sep 15 03:55:23 2006 +0000 +++ b/src/keymap.h Fri Sep 15 07:19:15 2006 +0000 @@ -29,8 +29,8 @@ EXFUN (Fkeymap_prompt, 1); EXFUN (Fdefine_key, 3); EXFUN (Flookup_key, 3); -EXFUN (Fcommand_remapping, 1); -EXFUN (Fkey_binding, 3); +EXFUN (Fcommand_remapping, 2); +EXFUN (Fkey_binding, 4); EXFUN (Fkey_description, 2); EXFUN (Fsingle_key_description, 2); EXFUN (Fwhere_is_internal, 5);