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

From: Gregory Heytings <[email-masked]>
Date: Fri, 14 May 2021 09:29:08 +0000

This was an interesting bug.  Let's first define a recipe to make it more 
apparent:

C-x C-m C-\ french-postfix RET C-x ( pa^te'_a`_l'Unicode RET C-x ) C-x e

This should insert "pâté_à_l'Unicode".  It worked as expected with Emacs 
21-24.

After commit 30a6b1f814, which was the result of the discussion in 
http://lists.gnu.org/archive/html/emacs-devel/2015-08/msg00193.html , and 
before commit 03e3440dbb, it inserts "paâtteé__aà__l'UUnniiccocododee". 
This is what one gets in Emacs 25 and 26.  This is not surprising, as the 
recipe in that discussion and quail.el both use unread-command-events, but 
expect an opposite effect.

After commit 03e3440dbb, which was the result of bug#32108, it inserts 
"pâtté__à__l'Unnicocdode".  This is what one gets in Emacs 27 (and 28 till 
now).

I attach a patch to fix that bug.  I checked that the recipes that led to 
the two above commits still work correctly, and that it does not introduce 
regressions with make check.

Note that the inhibit--record-char variable, which was introduced by 
commit 03e3440dbb, is, after applying that patch, only used once, namely 
in lisp/term/xterm.el, as a result of bug#44908.  It is not used in ELPA 
or MELPA.  I'm not convinced that bug#44908 is a sufficient reason to keep 
that variable.

From 359a644498df85a1b063bfb0aace3df34adac3e0 Mon Sep 17 00:00:00 2001
From: Gregory Heytings <[email-masked]>
Date: Fri, 14 May 2021 09:20:03 +0000
Subject: [PATCH] Fix input method bug when recording keyboard macros

* src/keyboard.c (read_char): Do not record character again when
defining a keyboard macro with an input method 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              |  7 +++++--
 2 files changed, 9 insertions(+), 18 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..f72c0870fe 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -3098,7 +3098,11 @@ 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)
+  if (!recorded &&
+      /* However, don't record events when a keyboard macro is being
+         defined and an input method is activated (Bug#48042).  */
+      ! (! NILP (KVAR (current_kboard, defining_kbd_macro)) &&
+         ! 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