summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2018-06-23 14:03:10 +0300
committerEli Zaretskii <eliz@gnu.org>2018-06-23 14:03:10 +0300
commitecc29fbd5a73b55d4624c240b8a2d0a01d699e47 (patch)
tree258ea4edb175fcff9bd9213c85fa34351537b47c
parent8182d648cb18fb048495c761db7c21fbf3c2a624 (diff)
downloademacs-ecc29fbd5a73b55d4624c240b8a2d0a01d699e47.tar.gz
Improve responsiveness while in 'replace-buffer-contents'
* src/editfns.c (buffer_chars_equal): Avoid calling buf_charpos_to_bytepos when the buffer is plain-ASCII. Suggested by Milan Stanojević <mstanojevic@janestreet.com>. Call maybe_quit to improve responsiveness. (Freplace_buffer_contents): Call maybe_quit. Warn in the doc string that the function could be slow. (Bug#31888)
-rw-r--r--src/editfns.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/editfns.c b/src/editfns.c
index d15ae59029d..7c58391eb18 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3147,7 +3147,9 @@ SOURCE can be a buffer or a string that names a buffer.
Interactively, prompt for SOURCE.
As far as possible the replacement is non-destructive, i.e. existing
buffer contents, markers, properties, and overlays in the current
-buffer stay intact. */)
+buffer stay intact.
+Warning: this function can be slow if there's a large number of small
+differences between the two buffers. */)
(Lisp_Object source)
{
struct buffer *a = current_buffer;
@@ -3227,11 +3229,16 @@ buffer stay intact. */)
walk backwards, we don’t have to keep the positions in sync. */
while (i >= 0 || j >= 0)
{
+ /* Allow the user to quit if this gets too slow. */
+ maybe_quit ();
+
/* Check whether there is a change (insertion or deletion)
before the current position. */
if ((i > 0 && bit_is_set (ctx.deletions, i - 1)) ||
(j > 0 && bit_is_set (ctx.insertions, j - 1)))
{
+ maybe_quit ();
+
ptrdiff_t end_a = min_a + i;
ptrdiff_t end_b = min_b + j;
/* Find the beginning of the current change run. */
@@ -3305,14 +3312,20 @@ buffer_chars_equal (struct context *ctx,
eassert (pos_b >= BUF_BEGV (ctx->buffer_b));
eassert (pos_b < BUF_ZV (ctx->buffer_b));
+ bool a_unibyte = BUF_ZV (ctx->buffer_a) == BUF_ZV_BYTE (ctx->buffer_a);
+ bool b_unibyte = BUF_ZV (ctx->buffer_b) == BUF_ZV_BYTE (ctx->buffer_b);
+
+ /* Allow the user to escape out of a slow compareseq call. */
+ maybe_quit ();
+
ptrdiff_t bpos_a =
- NILP (BVAR (ctx->buffer_a, enable_multibyte_characters))
- ? pos_a
- : buf_charpos_to_bytepos (ctx->buffer_a, pos_a);
+ a_unibyte ? pos_a : buf_charpos_to_bytepos (ctx->buffer_a, pos_a);
ptrdiff_t bpos_b =
- NILP (BVAR (ctx->buffer_b, enable_multibyte_characters))
- ? pos_b
- : buf_charpos_to_bytepos (ctx->buffer_b, pos_b);
+ b_unibyte ? pos_b : buf_charpos_to_bytepos (ctx->buffer_b, pos_b);
+
+ if (a_unibyte && b_unibyte)
+ return BUF_FETCH_BYTE (ctx->buffer_a, bpos_a)
+ == BUF_FETCH_BYTE (ctx->buffer_b, bpos_b);
return BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_a, bpos_a)
== BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_b, bpos_b);