emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: local keymap patch for key-binding


From: David Kastrup
Subject: Re: local keymap patch for key-binding
Date: Tue, 12 Sep 2006 17:21:51 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

David Kastrup <address@hidden> writes:

> If you thing it reasonable that key-binding should also react to
> bona-fide events _not_ wrapped in an array, I can do this easily
> enough in the change I am working on.

Ok, here is my current patch (incidentally: why doesn't it work to use
PCL-CVS to do a multi-file diff? It ignores the marked files, just
working on the current line).  I have added an additional argument to
key-binding and documented it (that required changes in keymap.h and
callers of key-binding from C in keyboard.c).

As far as I can tell, this works with all key sequences.  If people
agree that this is reasonable, I would install it.  I'd be glad if
someone looked it over with regard to the SPECDCL and garbage
collection protection: I don't feel comfortable about those.  I also
copied code from keyboard.c that aborts if the current frame is not
live and can't be returned to.  No idea whether this is required (I
assume it was put there to avoid a busy lockup when Emacs got its
frame killed or something) or even a good idea.

Anybody have an opinion about that?

If people think this is the right way to go, I can install it.  I have
verified it with quite a few tries.  However, I have not yet tested
the LOCATION argument.  It should come in handy for mouse.el and
follow-link.

Index: src/keyboard.c
===================================================================
RCS file: /sources/emacs/emacs/src/keyboard.c,v
retrieving revision 1.875
diff -c -r1.875 keyboard.c
*** src/keyboard.c      10 Sep 2006 21:10:50 -0000      1.875
--- src/keyboard.c      12 Sep 2006 15:08:14 -0000
***************
*** 7516,7522 ****
        Lisp_Object prefix;
  
        if (!NILP (tem))
!       tem = Fkey_binding (tem, Qnil, Qnil);
  
        prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
        if (CONSP (prefix))
--- 7516,7522 ----
        Lisp_Object prefix;
  
        if (!NILP (tem))
!       tem = Fkey_binding (tem, Qnil, Qnil, Qnil);
  
        prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
        if (CONSP (prefix))
***************
*** 9125,9140 ****
                          if (!EQ (map_here, orig_local_map))
                            {
                              orig_local_map = map_here;
!                             keybuf[t] = key;
!                             mock_input = t + 1;
! 
!                             goto replay_sequence;
                            }
                          map_here = get_local_map (XINT (pos),
                                                     current_buffer, Qkeymap);
                          if (!EQ (map_here, orig_keymap))
                            {
                              orig_keymap = map_here;
                              keybuf[t] = key;
                              mock_input = t + 1;
  
--- 9125,9143 ----
                          if (!EQ (map_here, orig_local_map))
                            {
                              orig_local_map = map_here;
!                             ++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;
  
Index: src/keymap.c
===================================================================
RCS file: /sources/emacs/emacs/src/keymap.c,v
retrieving revision 1.333
diff -c -r1.333 keymap.c
*** src/keymap.c        11 Sep 2006 13:03:40 -0000      1.333
--- src/keymap.c        12 Sep 2006 15:08:18 -0000
***************
*** 28,33 ****
--- 28,35 ----
  #include "buffer.h"
  #include "charset.h"
  #include "keyboard.h"
+ #include "frame.h"
+ #include "window.h"
  #include "termhooks.h"
  #include "blockinput.h"
  #include "puresize.h"
***************
*** 1226,1232 ****
      return Qnil;
  
    ASET (command_remapping_vector, 1, command);
!   return Fkey_binding (command_remapping_vector, Qnil, Qt);
  }
  
  /* Value is number if KEY is too long; nil if valid but has no definition. */
--- 1228,1234 ----
      return Qnil;
  
    ASET (command_remapping_vector, 1, command);
!   return Fkey_binding (command_remapping_vector, Qnil, Qt, Qnil);
  }
  
  /* Value is number if KEY is too long; nil if valid but has no definition. */
***************
*** 1552,1558 ****
  
  /* GC is possible in this function if it autoloads a keymap.  */
  
! DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 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.
--- 1554,1560 ----
  
  /* GC is possible in this function if it autoloads a keymap.  */
  
! 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,1620 ****
  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;
  {
    Lisp_Object *maps, value;
    int nmaps, i;
!   struct gcpro gcpro1;
  
!   GCPRO1 (key);
  
! #ifdef HAVE_MOUSE
!   if (VECTORP (key) && ASIZE (key) > 0)
      {
!       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;
  
!         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;
            }
        }
      }
! #endif /* HAVE_MOUSE  */
! 
!   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))
      {
        value = Flookup_key (Voverriding_local_map, key, accept_default);
        if (! NILP (value) && !INTEGERP (value))
--- 1568,1660 ----
  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.
! 
! 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 LOCATION is non-nil, it
! will used in place of KEY for determining mouse-dependent keymaps, but
! it will still be KEY that is looked up.
!   */)
! (key, accept_default, no_remap, location)
!   Lisp_Object key, accept_default, no_remap, location;
  {
    Lisp_Object *maps, value;
    int nmaps, i;
!   struct gcpro gcpro1, gcpro2;
!   int count = SPECPDL_INDEX ();
! 
!   GCPRO2 (key, location);
  
!   if (NILP (location))
!     location = key;
  
!   if (VECTORP(location) && ASIZE(location) > 0)
      {
!       if (SYMBOLP (AREF(location,0)) && ASIZE(location) > 1)
!       location = AREF(location,1);
!       else
!       location = AREF(location,0);
!     }
  
!   /* We are not interested in locations without event data */
  
!   if (!EVENT_HAS_PARAMETERS (location))
!     location = Qnil;
  
!   /* 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 (! NILP (location))
!     {
!       Lisp_Object kind;
!       Lisp_Object string;
!       
!       kind = EVENT_HEAD_KIND (EVENT_HEAD (location));
!       if (EQ (kind, Qmouse_click))
!       {
!         Lisp_Object window, posn;
!         
!         window = POSN_WINDOW (EVENT_START (location));
!         posn   = POSN_POSN (EVENT_START (location));
!         
!         /* Key sequences beginning with mouse clicks are
!            read using the keymaps in the buffer clicked on,
!            not the current buffer.  If we're at the
!            beginning of a key sequence, switch buffers.  */
!         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 reading the key sequence.  Note that we can't
!                use save_excursion_{save,restore} here, because they
!                save point as well as the current buffer; we don't
!                want to save point, because redisplay may change it,
!                to accommodate a Fset_window_start or something.
!             */
!             
!             record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
!             
!             if (! FRAME_LIVE_P (XFRAME (selected_frame)))
!               Fkill_emacs (Qnil);
!             
!             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))
      {
        value = Flookup_key (Voverriding_local_map, key, accept_default);
        if (! NILP (value) && !INTEGERP (value))
***************
*** 1622,1633 ****
      }
    else
      {
!       Lisp_Object local;
  
!       local = get_local_map (PT, current_buffer, Qkeymap);
!       if (! NILP (local))
        {
!         value = Flookup_key (local, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
            goto done;
        }
--- 1662,1741 ----
      }
    else
      {
!       Lisp_Object keymap, local_map;
  
!       local_map = get_local_map (PT, current_buffer, Qlocal_map); 
!       keymap = get_local_map (PT, current_buffer, Qkeymap); 
! 
!       if (! NILP(location))
        {
!         Lisp_Object kind;
!         Lisp_Object string;
! 
!         kind = EVENT_HEAD_KIND (EVENT_HEAD (location));
!         if (EQ (kind, Qmouse_click))
!           {
!             Lisp_Object window, posn;
! 
!             window = POSN_WINDOW      (EVENT_START (location));
!             posn   = POSN_POSN (EVENT_START (location));
! 
!             /* For a mouse click, get the local text-property keymap
!                of the place clicked on, rather than point.  */
! 
!             if (CONSP (XCDR (location)))
!               {
!                 Lisp_Object start, pos;
! 
!                 start = EVENT_START (location);
! 
!                 if (CONSP (start) && POSN_INBUFFER_P (start))
!                   {
!                     pos = POSN_BUFFER_POSN (start);
!                     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 (EVENT_START (location)),
!                 (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,1653 ****
              goto done;
          }
  
!       local = get_local_map (PT, current_buffer, Qlocal_map);
!       if (! NILP (local))
        {
!         value = Flookup_key (local, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
            goto done;
        }
--- 1752,1760 ----
              goto done;
          }
  
!       if (! NILP (local_map))
        {
!         value = Flookup_key (local_map, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
            goto done;
        }
***************
*** 1656,1661 ****
--- 1763,1770 ----
    value = Flookup_key (current_global_map, key, accept_default);
  
   done:
+   unbind_to (count, Qnil);
+ 
    UNGCPRO;
    if (NILP (value) || INTEGERP (value))
      return Qnil;
Index: src/keymap.h
===================================================================
RCS file: /sources/emacs/emacs/src/keymap.h,v
retrieving revision 1.14
diff -c -r1.14 keymap.h
*** src/keymap.h        6 Feb 2006 15:23:21 -0000       1.14
--- src/keymap.h        12 Sep 2006 15:08:18 -0000
***************
*** 30,36 ****
  EXFUN (Fdefine_key, 3);
  EXFUN (Flookup_key, 3);
  EXFUN (Fcommand_remapping, 1);
! EXFUN (Fkey_binding, 3);
  EXFUN (Fkey_description, 2);
  EXFUN (Fsingle_key_description, 2);
  EXFUN (Fwhere_is_internal, 5);
--- 30,36 ----
  EXFUN (Fdefine_key, 3);
  EXFUN (Flookup_key, 3);
  EXFUN (Fcommand_remapping, 1);
! EXFUN (Fkey_binding, 4);
  EXFUN (Fkey_description, 2);
  EXFUN (Fsingle_key_description, 2);
  EXFUN (Fwhere_is_internal, 5);

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

reply via email to

[Prev in Thread] Current Thread [Next in Thread]