changeset 72889:25c755416160

* 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'.
author David Kastrup <dak@gnu.org>
date Fri, 15 Sep 2006 07:19:15 +0000
parents d688b3faf96b
children 5ba1cd1da822
files etc/ChangeLog etc/NEWS lispref/ChangeLog lispref/keymaps.texi src/ChangeLog src/Makefile.in src/keyboard.c src/keymap.c src/keymap.h
diffstat 9 files changed, 245 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- 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  <dak@gnu.org>
+
+	* NEWS: explain new behavior and arguments of `key-binding' and
+	`command-remapping'.
+
 2006-09-11  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* 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  <lorentey@elte.hu>
+2006-07-14  K,Aa(Broly L$,1 q(Brentey  <lorentey@elte.hu>
 
 	* HELLO: Update Hungarian sample.
 
--- 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
--- 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  <dak@gnu.org>
+
+	* 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  <rms@gnu.org>
 
 	* 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  <rms@gnu.org>
 
 	* display.texi (Display Table Format): Wording clarification.
@@ -4871,7 +4881,7 @@
 	(info): Add target.
 	(installall): Target removed.
 
-2001-10-31  Pavel Jan,Bm(Bk  <Pavel@Janik.cz>
+2001-10-31  Pavel Jan,Am(Bk  <Pavel@Janik.cz>
 
 	* tips.texi (Coding Conventions): Fix typo.
 
--- 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
--- 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  <dak@gnu.org>
+
+	* 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  <lekktu@gmail.com>
 
 	* indent.c (Fcurrent_column, Findent_to): Fix typos in docstring.
--- 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)
--- 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;
 
--- 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;
     }
 
--- 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);