Subject: bug#48042: 26.3; Macros don't work with french-postfix input method

From: Gregory Heytings <[email-masked]>
Date: Fri, 14 May 2021 13:38:03 +0000

>
> Bother: AFAIK, current-input-method non-nil means the user activated an 
> input method, it doesn't mean we are in the middle of typing a key 
> sequence that will yield a character via the input method.  That is, a 
> user could activate an input method, but still keep typing just ASCII 
> characters.  So why is this condition correct here to avoid recording 
> input more than once?
>

I'm not sure I understand your question.  With an input method is 
activated and characters that are not "reprocessed" by the input method 
are typed, they are not added to the unread-command-events list, so this 
part of the code (which is entered with the goto reread_for_input_method 
above) is simply not executed.  When they are "reprocessed", they are 
added to unread-command-events, but the keys typed in by the user have 
already been recorded.

Until commit 30a6b1f814, that part of the code (if (!recorded)...) did not 
exist, and my patch simply restores the behavior that quail.el expects by 
skipping it.  Note that in 2015 you yourself described that commit as a 
"naïve attempt at fixing" the problem.

I attach an even better patch, which removes the condition that a keyboard 
macro is being defined.  Now the keys displayed in C-h l are also correct.

>
> This is why I tried to have a variable that quail.el binds while 
> actually processing keys.  I'd appreciate some explanation for why that 
> didn't work 100% in the case in point (it still avoided recording twice 
> some of the keys, so it isn't entirely wrong).
>

I don't claim to understand everything, but what I see is that 
unread-command-events is also used (set) in quail-update-translation, 
quail-next-translation, quail-prev-translation, 
quail-next-translation-block, quail-prev-translation-block and 
quail-minibuffer-message.

From aabb9d7a2fc8bd0f24429d0b632ef11950a65fba Mon Sep 17 00:00:00 2001
From: Gregory Heytings <[email-masked]>
Date: Fri, 14 May 2021 13:23:12 +0000
Subject: [PATCH] Fix key recording bug when an input method is activated

* src/keyboard.c (read_char): Do not record character again when an
input method is activated (Bug#48042).
(record_char): Partly revert 03e3440dbb.

* lisp/international/quail.el (quail-start-translation,
quail-start-conversion): Partly revert 03e3440dbb.
---
 lisp/international/quail.el | 20 ++++----------------
 src/keyboard.c              |  9 ++++++---
 2 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index fff06deee8..6c2088a95b 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -1385,13 +1385,12 @@ quail-start-translation
 	     ;; (generated-events nil)     ;FIXME: What is this?
 	     (input-method-function nil)
 	     (modified-p (buffer-modified-p))
-	     last-command-event last-command this-command inhibit-record)
+	     last-command-event last-command this-command)
 	(setq quail-current-key ""
 	      quail-current-str ""
 	      quail-translating t)
 	(if key
-	    (setq unread-command-events (cons key unread-command-events)
-                  inhibit-record t))
+	    (setq unread-command-events (cons key unread-command-events)))
 	(while quail-translating
 	  (set-buffer-modified-p modified-p)
 	  (quail-show-guidance)
@@ -1400,13 +1399,8 @@ quail-start-translation
 				     (or input-method-previous-message "")
 				     quail-current-str
 				     quail-guidance-str)))
-                 ;; We inhibit record_char only for the first key,
-                 ;; because it was already recorded before read_char
-                 ;; called quail-input-method.
-                 (inhibit--record-char inhibit-record)
 		 (keyseq (read-key-sequence prompt nil nil t))
 		 (cmd (lookup-key (quail-translation-keymap) keyseq)))
-            (setq inhibit-record nil)
 	    (if (if key
 		    (and (commandp cmd) (not (eq cmd 'quail-other-command)))
 		  (eq cmd 'quail-self-insert-command))
@@ -1450,15 +1444,14 @@ quail-start-conversion
 	     ;; (generated-events nil)     ;FIXME: What is this?
 	     (input-method-function nil)
 	     (modified-p (buffer-modified-p))
-	     last-command-event last-command this-command inhibit-record)
+	     last-command-event last-command this-command)
 	(setq quail-current-key ""
 	      quail-current-str ""
 	      quail-translating t
 	      quail-converting t
 	      quail-conversion-str "")
 	(if key
-	    (setq unread-command-events (cons key unread-command-events)
-                  inhibit-record t))
+	    (setq unread-command-events (cons key unread-command-events)))
 	(while quail-converting
 	  (set-buffer-modified-p modified-p)
 	  (or quail-translating
@@ -1474,13 +1467,8 @@ quail-start-conversion
 				     quail-conversion-str
 				     quail-current-str
 				     quail-guidance-str)))
-                 ;; We inhibit record_char only for the first key,
-                 ;; because it was already recorded before read_char
-                 ;; called quail-input-method.
-                 (inhibit--record-char inhibit-record)
 		 (keyseq (read-key-sequence prompt nil nil t))
 		 (cmd (lookup-key (quail-conversion-keymap) keyseq)))
-            (setq inhibit-record nil)
 	    (if (if key (commandp cmd) (eq cmd 'quail-self-insert-command))
 		(progn
 		  (setq last-command-event (aref keyseq (1- (length keyseq)))
diff --git a/src/keyboard.c b/src/keyboard.c
index 47b5e59024..6849229bb2 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -3097,8 +3097,12 @@ read_char (int commandflag, Lisp_Object map,
     }
   /* When we consume events from the various unread-*-events lists, we
      bypass the code that records input, so record these events now if
-     they were not recorded already.  */
-  if (!recorded)
+     they were not recorded already.
+     Don't record events when an input method is activated however,
+     quail.el puts keys back in unread-command-events to handle them
+     again, but the keys actually typed by the user have already been
+     recorded.  */
+  if (!recorded && NILP (Fsymbol_value (Qcurrent_input_method)))
     {
       record_char (c);
       recorded = true;
@@ -3233,7 +3237,6 @@ help_char_p (Lisp_Object c)
 static void
 record_char (Lisp_Object c)
 {
-  /* quail.el binds this to avoid recording keys twice.  */
   if (inhibit_record_char)
     return;
 
-- 
2.30.2