]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid moving point while analyzing text conversion
authorPo Lu <luangruo@yahoo.com>
Fri, 3 Nov 2023 03:32:17 +0000 (11:32 +0800)
committerPo Lu <luangruo@yahoo.com>
Fri, 3 Nov 2023 03:34:40 +0000 (11:34 +0800)
* lisp/simple.el (analyze-text-conversion): If neither calling
p-s-i-h nor calling p-t-c-h yields a change to point, return it
to its location before analyze-text-conversion was called.

* src/keyboard.c (kbd_buffer_get_event): See that text
conversion events are uniformly delivered prior to keyboard
events arriving in unison.

lisp/simple.el
src/keyboard.c

index 30208debc2af9a0f96dcdb4d75d794cef018f0cf..96cdedb4f3863d2d0296845387baa21caec21dbe 100644 (file)
@@ -11169,7 +11169,12 @@ place.  If undo information is being recorded, make sure
 `undo-auto-current-boundary-timer' will run within the next 5
 seconds."
   (interactive)
-  (let ((any-nonephemeral nil))
+  ;; One important consideration to bear in mind when adjusting this
+  ;; code is to _never_ move point in reaction to an edit so long as
+  ;; the additional processing undertaken by this function does not
+  ;; also edit the buffer text.
+  (let ((any-nonephemeral nil)
+        point-moved)
     ;; The list must be processed in reverse.
     (dolist (edit (reverse text-conversion-edits))
       ;; Filter out ephemeral edits and deletions after point.  Here, we
@@ -11177,6 +11182,9 @@ seconds."
       ;; can be identified.
       (when (stringp (nth 3 edit))
         (with-current-buffer (car edit)
+          ;; Record that the point hasn't been moved by the execution
+          ;; of a post command or text conversion hook.
+          (setq point-moved nil)
           (if (not (eq (nth 1 edit) (nth 2 edit)))
               ;; Process this insertion.  (nth 3 edit) is the text which
               ;; was inserted.
@@ -11192,7 +11200,8 @@ seconds."
                      ;; Save the current undo list to figure out
                      ;; whether or not auto-fill has actually taken
                      ;; place.
-                     (old-undo-list buffer-undo-list))
+                     (old-undo-list buffer-undo-list)
+                     (old-point (point)))
                 (save-excursion
                   (if (and auto-fill-function newline-p)
                       (progn (goto-char (nth 2 edit))
@@ -11211,10 +11220,22 @@ seconds."
                             (not (eq old-undo-list
                                      buffer-undo-list)))))
                 (goto-char (nth 2 edit))
-                (let ((last-command-event end))
+                (let ((last-command-event end)
+                      (point (point)))
                   (unless (run-hook-with-args-until-success
                            'post-text-conversion-hook)
-                    (run-hooks 'post-self-insert-hook))))
+                    (run-hooks 'post-self-insert-hook))
+                  (when (not (eq (point) point))
+                    (setq point-moved t)))
+                ;; If post-self-insert-hook doesn't move the point,
+                ;; restore it to its previous location.  Generally,
+                ;; the call to goto-char upon processing the last edit
+                ;; recorded text-conversion-edit will see to this, but
+                ;; if the input method sets point expressly, no edit
+                ;; will be recorded, and point will wind up away from
+                ;; where the input method believes it is.
+                (unless point-moved
+                  (goto-char old-point)))
             ;; Process this deletion before point.  (nth 2 edit) is the
             ;; text which was deleted.  Input methods typically prefer
             ;; to edit words instead of deleting characters off their
index 003340c3e58b3362f91b6f17530fb3909815cf9d..13cb7835dff4bd5ba7447095982fc4e3e2400561 100644 (file)
@@ -3993,6 +3993,19 @@ kbd_buffer_get_event (KBOARD **kbp,
       if (CONSP (Vunread_command_events))
        break;
 
+#ifdef HAVE_TEXT_CONVERSION
+      /* That text conversion events take priority over keyboard
+        events, since input methods frequently send them immediately
+        after edits, with the assumption that this order of events
+        will be observed.  */
+
+      if (detect_conversion_events ())
+       {
+         had_pending_conversion_events = true;
+         break;
+       }
+#endif /* HAVE_TEXT_CONVERSION */
+
       if (kbd_fetch_ptr != kbd_store_ptr)
        break;
       if (some_mouse_moved ())
@@ -4020,13 +4033,6 @@ kbd_buffer_get_event (KBOARD **kbp,
          had_pending_selection_requests = true;
          break;
        }
-#endif
-#ifdef HAVE_TEXT_CONVERSION
-      if (detect_conversion_events ())
-       {
-         had_pending_conversion_events = true;
-         break;
-       }
 #endif
       if (end_time)
        {