summaryrefslogtreecommitdiff
path: root/src/editfns.c
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2006-08-04 15:22:09 +0000
committerStefan Monnier <monnier@iro.umontreal.ca>2006-08-04 15:22:09 +0000
commit0f2e2a3bbc74a84038de18603e5d734f38fa9db4 (patch)
tree7e3ff691dea8e026c5e3dfacfd90af0679de3bf1 /src/editfns.c
parent316a275a1e626f7689affcf96f4e98953a6b5c97 (diff)
downloademacs-0f2e2a3bbc74a84038de18603e5d734f38fa9db4.tar.gz
(Fsubst_char_in_region): Redo the setup work after running
the before-change-functions since they may have altered the buffer.
Diffstat (limited to 'src/editfns.c')
-rw-r--r--src/editfns.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/editfns.c b/src/editfns.c
index e692204c702..8ac61f3d006 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2691,6 +2691,10 @@ Both characters must have the same length of multi-byte form. */)
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;
@@ -2703,6 +2707,8 @@ Both characters must have the same length of multi-byte form. */)
int last_changed = 0;
int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
+ restart:
+
validate_region (&start, &end);
CHECK_NUMBER (fromchar);
CHECK_NUMBER (tochar);
@@ -2740,7 +2746,7 @@ Both characters must have the same length of multi-byte form. */)
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);
@@ -2774,10 +2780,14 @@ Both characters must have the same length of multi-byte form. */)
&& (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))
{
@@ -2786,6 +2796,10 @@ Both characters must have the same length of multi-byte form. */)
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
@@ -2838,7 +2852,7 @@ Both characters must have the same length of multi-byte form. */)
pos++;
}
- if (changed)
+ if (changed > 0)
{
signal_after_change (changed,
last_changed - changed, last_changed - changed);