emacs-pretest-bug
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: subst-char-in-region broken when a before-change function reads buff


From: Stefan Monnier
Subject: Re: subst-char-in-region broken when a before-change function reads buffer contents
Date: Thu, 03 Aug 2006 11:59:27 -0400
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

> When I put a function calling buffer-substring into the
> before-change-functions hook, then subst-chars-in-region sometimes
> produces wrong results.

Good catch.  Does the patch below help?


        Stefan


--- orig/src/editfns.c
+++ mod/src/editfns.c
@@ -2706,6 +2706,10 @@
      Lisp_Object start, end, fromchar, tochar, noundo;
 {
   register int pos, pos_byte, stop, i, len, end_byte;
+  /* Keep track of the first change in the buffer:
+     if 0 we haven't found it yet.
+     if < 0 we've found it and we've run the before-change-function.
+     if > 0 we've actually performed it and the value is its position.  */
   int changed = 0;
   unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
   unsigned char *p;
@@ -2718,6 +2722,8 @@
   int last_changed = 0;
   int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
 
+ restart:
+
   validate_region (&start, &end);
   CHECK_NUMBER (fromchar);
   CHECK_NUMBER (tochar);
@@ -2755,7 +2761,7 @@
      That's faster than getting rid of things,
      and it prevents even the entry for a first change.
      Also inhibit locking the file.  */
-  if (!NILP (noundo))
+  if (!changed && !NILP (noundo))
     {
       record_unwind_protect (subst_char_in_region_unwind,
                             current_buffer->undo_list);
@@ -2789,9 +2795,13 @@
                  && (len == 2 || (p[2] == fromstr[2]
                                 && (len == 3 || p[3] == fromstr[3]))))))
        {
-         if (! changed)
+         if (changed < 0)
+           /* We've already seen this and run the before-change-function;
+              this time we only need to record the actual position. */
+           changed = pos;
+         else if (!changed)
            {
-             changed = pos;
-             modify_region (current_buffer, changed, XINT (end));
+             changed = -1;
+             modify_region (current_buffer, pos, XINT (end));
 
              if (! NILP (noundo))
@@ -2801,6 +2811,10 @@
                  if (MODIFF - 1 == current_buffer->auto_save_modified)
                    current_buffer->auto_save_modified++;
                }
+
+             /* The before-change-function may have moved the gap
+                or even modified the buffer so we should start over. */
+             goto restart;
            }
 
          /* Take care of the case where the new character
@@ -2853,7 +2867,7 @@
       pos++;
     }
 
-  if (changed)
+  if (changed > 0)
     {
       signal_after_change (changed,
                           last_changed - changed, last_changed - changed);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]