From: Stefan Monnier Date: Wed, 10 Apr 2024 16:15:26 +0000 (-0400) Subject: (en/decode_coding_object): Fix `after-change-functions` X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=41b195fc08d8cac3caa5519580473d495e1f91d1;p=emacs.git (en/decode_coding_object): Fix `after-change-functions` 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) --- diff --git a/src/coding.c b/src/coding.c index c51ceb95475..b21f2ecf00a 100644 --- a/src/coding.c +++ b/src/coding.c @@ -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. diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index a14a5f90b65..a7fcef86209 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -428,9 +428,17 @@ ;;; 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) @@ -488,6 +496,12 @@ (+ 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 @@ -496,8 +510,28 @@ #'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