From 0aec5b8a5607505c1b492c10b67214f52f33972a Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Fri, 12 Jan 2018 16:31:35 +0000 Subject: [PATCH] Make Fzlib_decompress_region always call the change hooks in a balanced way. This means there will be exactly one call of each of before- and after-change-functions, regardless of whether or not the decompression succeeds, and these calls will refer to corresponding buffer regions. src/decompress.c (struct decompress_unwind_data): add a new field, orig. (unwind_decompress): Use del_range_2 and update_compositions in place of del_range, to avoid unwanted change hook calls. Call signal_after_change for the failed case. (Fzlib_decompress_region): Call modify_txt for a before-change-functions. Set the new field orig of unwind_data to the region's start. Use del_range_2 and update_compositions in place of del_range to avoid unwanted change hook calls. Call signal_after_change for the successful case. --- src/decompress.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/decompress.c b/src/decompress.c index 41de6da1dd2..6f75f821c40 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "buffer.h" +#include "composite.h" #include @@ -66,7 +67,7 @@ init_zlib_functions (void) struct decompress_unwind_data { - ptrdiff_t old_point, start, nbytes; + ptrdiff_t old_point, orig, start, nbytes; z_stream *stream; }; @@ -76,10 +77,19 @@ unwind_decompress (void *ddata) struct decompress_unwind_data *data = ddata; inflateEnd (data->stream); - /* Delete any uncompressed data already inserted on error. */ + /* Delete any uncompressed data already inserted on error, but + without calling the change hooks. */ if (data->start) - del_range (data->start, data->start + data->nbytes); - + { + del_range_2 (data->start, data->start, /* byte, char offsets the same */ + data->start + data->nbytes, data->start + data->nbytes, + 0); + update_compositions (data->start, data->start, CHECK_HEAD); + /* "Balance" the before-change-functions call, which would + otherwise be left "hanging". */ + signal_after_change (data->orig, data->start - data->orig, + data->start - data->orig); + } /* Put point where it was, or if the buffer has shrunk because the compressed data is bigger than the uncompressed, at point-max. */ @@ -141,6 +151,10 @@ This function can be called only in unibyte buffers. */) the same. */ istart = XINT (start); iend = XINT (end); + + /* Do the following before manipulating the gap. */ + modify_text (istart, iend); + move_gap_both (iend, iend); stream.zalloc = Z_NULL; @@ -154,6 +168,7 @@ This function can be called only in unibyte buffers. */) if (inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK) return Qnil; + unwind_data.orig = istart; unwind_data.start = iend; unwind_data.stream = &stream; unwind_data.old_point = PT; @@ -196,7 +211,11 @@ This function can be called only in unibyte buffers. */) unwind_data.start = 0; /* Delete the compressed data. */ - del_range (istart, iend); + del_range_2 (istart, istart, /* byte and char offsets are the same. */ + iend, iend, 0); + + signal_after_change (istart, iend - istart, unwind_data.nbytes); + update_compositions (istart, istart, CHECK_HEAD); return unbind_to (count, Qt); } -- 2.11.4.GIT