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.
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
(@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
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
#include "puresize.h"
#include "intervals.h"
#include "keymap.h"
+#include "window.h"
/* The number of elements in keymap vectors. */
#define DENSE_TABLE_SIZE (0200)
/* 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. */
/* 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.
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);
-#ifdef HAVE_MOUSE
- if (VECTORP (key) && ASIZE (key) > 0)
+ 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 map, object;
+ 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);
- object = Fnth (make_number(4), pos);
+ /* We are not interested in locations without event data */
- 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 (EVENT_HAS_PARAMETERS (event)) {
+ Lisp_Object kind;
- if (!NILP (Fkeymapp (map)))
- {
- value = Flookup_key (map, key, accept_default);
- if (! NILP (value) && !INTEGERP (value))
- goto done;
- }
- }
+ kind = EVENT_HEAD_KIND (EVENT_HEAD (event));
+ if (EQ (kind, Qmouse_click))
+ position = EVENT_START (event);
+ }
}
-#endif /* HAVE_MOUSE */
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
+ /* 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))
}
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))
{
- 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;
}
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;
}
value = Flookup_key (current_global_map, key, accept_default);
done:
+ unbind_to (count, Qnil);
+
UNGCPRO;
if (NILP (value) || INTEGERP (value))
return Qnil;
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;
}
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;
}