diff src/keymap.c @ 90602:b5c13d1564a9

Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 437-446) - Update from CVS - lisp/url/url-methods.el: Fix format error when http_proxy is empty string - Merge from gnus--rel--5.10 * gnus--rel--5.10 (patch 137-140) - Update from CVS Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-111
author Miles Bader <miles@gnu.org>
date Wed, 20 Sep 2006 06:04:23 +0000
parents a1a25ac6c88a f9742f561ed9
children bb0e318b7c53
line wrap: on
line diff
--- a/src/keymap.c	Thu Sep 14 09:24:00 2006 +0000
+++ b/src/keymap.c	Wed Sep 20 06:04:23 2006 +0000
@@ -23,6 +23,9 @@
 
 #include <config.h>
 #include <stdio.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
@@ -34,6 +37,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)
@@ -1249,17 +1253,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. */
@@ -1585,7 +1595,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.
@@ -1599,55 +1609,83 @@
 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) && VECTORP (key))
     {
-      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 */
+	= 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)) {
+	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))
@@ -1655,12 +1693,70 @@
     }
   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;
+
+	  /* 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;
 	}
@@ -1677,10 +1773,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;
 	}
@@ -1689,6 +1784,8 @@
   value = Flookup_key (current_global_map, key, accept_default);
 
  done:
+  unbind_to (count, Qnil);
+
   UNGCPRO;
   if (NILP (value) || INTEGERP (value))
     return Qnil;
@@ -1699,7 +1796,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;
     }
 
@@ -2449,7 +2546,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;
     }