]> git.eshelyaron.com Git - emacs.git/commitdiff
(en/decode_coding_object): Fix `after-change-functions`
authorStefan Monnier <monnier@iro.umontreal.ca>
Wed, 10 Apr 2024 16:15:26 +0000 (12:15 -0400)
committerEshel Yaron <me@eshelyaron.com>
Wed, 10 Apr 2024 20:31:07 +0000 (22:31 +0200)
For `en/decode-coding-string/region`, `after-change-functions`
were either not run at all, or run only after deleting the text
but not after inserting it.

* src/coding.c (decode_coding_object, encode_coding_object): Run the
after-change-functions after inserting the result.

* test/src/editfns-tests.el (sanity-check-change-functions-with-op):
New macro.
(sanity-check-change-functions-errors): New function.
(editfns-tests--before/after-change-functions): Use them to add
cases for `en/decode-coding-string/region`.

(cherry picked from commit 36cb16556c60bf4e703764eefd4fb6668ccc37cc)

src/coding.c
test/src/editfns-tests.el

index c51ceb95475a5487324e4397e1688bc921aeb970..b21f2ecf00aa1b24e4fb22c099d3964cbe2cb963 100644 (file)
@@ -8109,7 +8109,7 @@ decode_coding_object (struct coding_system *coding,
       set_buffer_internal (XBUFFER (src_object));
       if (from != GPT)
        move_gap_both (from, from_byte);
-      if (EQ (src_object, dst_object))
+      if (BASE_EQ (src_object, dst_object))
        {
          struct Lisp_Marker *tail;
 
@@ -8121,8 +8121,9 @@ decode_coding_object (struct coding_system *coding,
            }
          saved_pt = PT, saved_pt_byte = PT_BYTE;
          TEMP_SET_PT_BOTH (from, from_byte);
-         current_buffer->text->inhibit_shrinking = 1;
-         del_range_both (from, from_byte, to, to_byte, 1);
+         current_buffer->text->inhibit_shrinking = true;
+         prepare_to_modify_buffer (from, to, NULL);
+         del_range_2 (from, from_byte, to, to_byte, false);
          coding->src_pos = -chars;
          coding->src_pos_byte = -bytes;
        }
@@ -8148,6 +8149,13 @@ decode_coding_object (struct coding_system *coding,
     }
   else if (BUFFERP (dst_object))
     {
+      if (!BASE_EQ (src_object, dst_object))
+       {
+         struct buffer *current = current_buffer;
+         set_buffer_internal (XBUFFER (dst_object));
+         prepare_to_modify_buffer (PT, PT, NULL);
+         set_buffer_internal (current);
+       }
       code_conversion_save (0, 0);
       coding->dst_object = dst_object;
       coding->dst_pos = BUF_PT (XBUFFER (dst_object));
@@ -8168,7 +8176,14 @@ decode_coding_object (struct coding_system *coding,
   decode_coding (coding);
 
   if (BUFFERP (coding->dst_object))
-    set_buffer_internal (XBUFFER (coding->dst_object));
+    {
+      set_buffer_internal (XBUFFER (coding->dst_object));
+      signal_after_change (coding->dst_pos,
+                          BASE_EQ (src_object, dst_object) ? to - from : 0,
+                          coding->produced_char);
+      update_compositions (coding->dst_pos,
+                          coding->dst_pos + coding->produced_char, CHECK_ALL);
+    }
 
   if (! NILP (CODING_ATTR_POST_READ (attrs)))
     {
@@ -8373,7 +8388,12 @@ encode_coding_object (struct coding_system *coding,
       if (same_buffer)
        {
          saved_pt = PT, saved_pt_byte = PT_BYTE;
-         coding->src_object = del_range_1 (from, to, 1, 1);
+         /* Run 'prepare_to_modify_buffer' by hand because we don't want
+            to run the after-change hooks yet.  */
+         prepare_to_modify_buffer (from, to, &from);
+         coding->src_object = del_range_2 (from, CHAR_TO_BYTE (from),
+                                           to, CHAR_TO_BYTE (to),
+                                           true);
          coding->src_pos = 0;
          coding->src_pos_byte = 0;
        }
@@ -8404,11 +8424,12 @@ encode_coding_object (struct coding_system *coding,
        {
          struct buffer *current = current_buffer;
 
-         set_buffer_temp (XBUFFER (dst_object));
+         set_buffer_internal (XBUFFER (dst_object));
+         prepare_to_modify_buffer (PT, PT, NULL);
          coding->dst_pos = PT;
          coding->dst_pos_byte = PT_BYTE;
          move_gap_both (coding->dst_pos, coding->dst_pos_byte);
-         set_buffer_temp (current);
+         set_buffer_internal (current);
        }
       coding->dst_multibyte
        = ! NILP (BVAR (XBUFFER (dst_object), enable_multibyte_characters));
@@ -8446,6 +8467,16 @@ encode_coding_object (struct coding_system *coding,
          xfree (coding->destination);
        }
     }
+  else if (BUFFERP (coding->dst_object))
+    {
+      struct buffer *current = current_buffer;
+      set_buffer_internal (XBUFFER (dst_object));
+      signal_after_change (coding->dst_pos, same_buffer ? to - from : 0,
+                          coding->produced_char);
+      update_compositions (coding->dst_pos,
+                          coding->dst_pos + coding->produced_char, CHECK_ALL);
+      set_buffer_internal (current);
+    }
 
   if (saved_pt >= 0)
     {
@@ -9510,7 +9541,7 @@ not fully specified.)  */)
 
 DEFUN ("encode-coding-region", Fencode_coding_region, Sencode_coding_region,
        3, 4, "r\nzCoding system: ",
-       doc: /* Encode the current region using th specified coding system.
+       doc: /* Encode the current region using the specified coding system.
 Interactively, prompt for the coding system to encode the region, and
 replace the region with the bytes that are the result of the encoding.
 
index a14a5f90b65c0eeccee524b6e7d12553bab0a8bd..a7fcef86209385170293348fa6807a926a669e40 100644 (file)
 
 ;;; Try and catch `*-changes-functions' bugs!
 
-(defvar sanity-check--verbose nil)
+(defvar sanity-check-change-functions-verbose nil)
+(defvar sanity-check-change-functions-op nil)
+(defmacro sanity-check-change-functions-with-op (op &rest body)
+  (declare (debug t) (indent 1))
+  `(let ((sanity-check-change-functions-op ,op))
+     (sanity-check--message "%S..." sanity-check-change-functions-op)
+     ,@body
+     (sanity-check--message "%S...done" sanity-check-change-functions-op)))
+
 (defun sanity-check--message (&rest args)
-  (if sanity-check--verbose (apply #'message args)))
+  (if sanity-check-change-functions-verbose (apply #'message args)))
 
 (defvar-local sanity-check-change-functions-beg 0)
 (defvar-local sanity-check-change-functions-end 0)
           (+ sanity-check-change-functions-buffer-size offset)))
   (sanity-check-change-functions-check-size))
 
+(defun sanity-check-change-functions-errors ()
+  (sanity-check-change-functions-check-size)
+  (if sanity-check-change-functions-errors
+      (cons sanity-check-change-functions-op
+            sanity-check-change-functions-errors)))
+
 (ert-deftest editfns-tests--before/after-change-functions ()
   (with-temp-buffer
     (add-hook 'before-change-functions
               #'sanity-check-change-functions-after nil t)
 
     ;; Bug#65451
-    (insert "utf-8-unix\n\nUTF")
-    (call-interactively 'dabbrev-expand)
-    (should (null sanity-check-change-functions-errors))))
+    (sanity-check-change-functions-with-op 'DABBREV-EXPAND
+      (insert "utf-8-unix\n\nUTF")
+      (call-interactively 'dabbrev-expand)
+      (should (null (sanity-check-change-functions-errors))))
+
+    (let ((beg (point)))
+      (sanity-check-change-functions-with-op 'ENCODE-CODING-REGION
+        (insert "ééé")
+        (encode-coding-region beg (point) 'utf-8)
+        (should (null (sanity-check-change-functions-errors))))
+      
+      (sanity-check-change-functions-with-op 'DECODE-CODING-REGION
+        (decode-coding-region beg (point) 'utf-8)
+        (should (null (sanity-check-change-functions-errors)))))
+
+    (sanity-check-change-functions-with-op 'ENCODE-CODING-STRING
+      (encode-coding-string "ééé" 'utf-8 nil (current-buffer))
+      (should (null (sanity-check-change-functions-errors))))
+
+    (sanity-check-change-functions-with-op 'DECODE-CODING-STRING
+      (decode-coding-string "\303\251\303\251\303\251"
+                            'utf-8 nil (current-buffer))
+      (should (null (sanity-check-change-functions-errors))))))
 
 ;;; editfns-tests.el ends here