(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`.
This commit is contained in:
Stefan Monnier 2024-04-10 12:15:26 -04:00
parent 15bafc0432
commit 36cb16556c
2 changed files with 78 additions and 13 deletions

View 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.

View file

@ -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