master 0c83d2cdbb1 1/2: Fix 'current-active-maps' for 4-element position list

Eli Zaretskii <[email protected]> Thu, 23 Jul 2026 02:54:02 -0400 (EDT)
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 0c83d2cdbb121698fa3c4685ad68bd918a08b81a
Author: Spencer Baugh <[email protected]>
Commit: Eli Zaretskii <[email protected]>

    Fix 'current-active-maps' for 4-element position list
    
    'current-active-maps' called POSN_BUFFER_POSN to get the buffer
    location out of a position list.  But POSN_BUFFER_POSN is not
    correct: to get the buffer location you need the more
    complicated logic in 'posn-point', you can't just take the 5th
    element of POSN.  Fix it by calling 'posn-point' instead, which
    is now moved to C for this purpose.
    * src/keyboard.c (Fposn_point): New function, moved from
    subr.el.
    (syms_of_keyboard): Defsubr it.
    * lisp/subr.el (posn-point): Delete; moved to C.
    * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Add the
    new C implementation of 'posn-point'.
    * src/keymap.c (Fcurrent_active_maps): Call 'posn-point' instead
    of 'POSN_BUFFER_POSN'.  (Bug#81386)
---
 lisp/emacs-lisp/byte-opt.el |  2 +-
 lisp/subr.el                | 13 -------------
 src/keyboard.c              | 24 ++++++++++++++++++++++++
 src/keymap.c                |  3 ++-
 4 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 7ed71346451..a596dee6844 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1771,7 +1771,7 @@ See Info node `(elisp) Integer Basics'."
          ;; json.c
          json-serialize json-parse-string
          ;; keyboard.c
-         posn-at-point posn-at-x-y
+         posn-at-point posn-at-x-y posn-point
          ;; keymap.c
          copy-keymap keymap-parent keymap-prompt make-keymap make-sparse-keymap
          ;; lread.c
diff --git a/lisp/subr.el b/lisp/subr.el
index 16e91934382..60a57688f73 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2013,19 +2013,6 @@ and `event-end' functions."
 		(nth 1 position))))
     (and (symbolp area) area)))
 
-(defun posn-point (position)
-  "Return the buffer location in POSITION.
-POSITION should be a list of the form returned by the `event-start'
-and `event-end' functions.
-Returns nil if POSITION does not correspond to any buffer location (e.g.
-a click on a scroll bar)."
-  (declare (side-effect-free t))
-  (or (nth 5 position)
-      (let ((pt (nth 1 position)))
-        (or (car-safe pt)
-            ;; Apparently this can also be `vertical-scroll-bar' (bug#13979).
-            (if (integerp pt) pt)))))
-
 (defun posn-set-point (position)
   "Move point to POSITION.
 Select the corresponding window as well."
diff --git a/src/keyboard.c b/src/keyboard.c
index 3d18d20b56e..8eb2e84b280 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -13096,6 +13096,29 @@ The `posn-' functions access elements of such lists.  */)
   return tem;
 }
 
+DEFUN ("posn-point", Fposn_point, Sposn_point, 1, 1, 0,
+       doc: /* Return the buffer location in POSITION.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions.
+Returns nil if POSITION does not correspond to any buffer location (e.g.
+a click on a scroll bar).  */)
+  (Lisp_Object position)
+{
+  Lisp_Object posn = POSN_BUFFER_POSN (position);
+  if (!NILP (posn))
+    return posn;
+  /* POSITION is a short position list (such as returned by
+     `event--posn-at-point') without a POSN_BUFFER_POSN; fall back to
+     the location in POSN_POSN. */
+  posn = POSN_POSN (position);
+  if (CONSP (posn))
+    return XCAR (posn);
+  /* Apparently this can also be `vertical-scroll-bar' (bug#13979).  */
+  if (INTEGERP (posn))
+    return posn;
+  return Qnil;
+}
+
 /* Set up a new kboard object with reasonable initial values.
    TYPE is a window system for which this keyboard is used.  */
 
@@ -13731,6 +13754,7 @@ This is effective only in `noninteractive' sessions.  */);
   defsubr (&Scurrent_input_mode);
   defsubr (&Sposn_at_point);
   defsubr (&Sposn_at_x_y);
+  defsubr (&Sposn_point);
 
   defsubr (&Sread_char);
   defsubr (&Sread_char_exclusive);
diff --git a/src/keymap.c b/src/keymap.c
index a42cec854dd..ec0b966d435 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -1742,7 +1742,7 @@ means to return the active maps for that window's buffer.  */)
 		}
 	    }
 
-	  Lisp_Object buffer_posn = POSN_BUFFER_POSN (position);
+	  Lisp_Object buffer_posn = Fposn_point (position);
 	  /* Then, if the click was in the buffer, get the local
 	     text-property keymap of the place clicked on.  */
 
@@ -3481,6 +3481,7 @@ that describe key bindings.  That is why the default is nil.  */);
 
   DEFSYM (Qkey_parse, "key-parse");
   DEFSYM (Qkey_valid_p, "key-valid-p");
+  DEFSYM (Qposn_point, "posn-point");
   DEFSYM (Qnon_key_event, "non-key-event");
   DEFSYM (Qprinc, "princ");
   DEFSYM (Qsuppress_keymap, "suppress-keymap");