aboutsummaryrefslogtreecommitdiffstats
path: root/src/editfns.c
diff options
context:
space:
mode:
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 02ea2d2abb8..aa6ad457676 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2712,6 +2712,10 @@ Both characters must have the same length of multi-byte form. */)
2712 Lisp_Object start, end, fromchar, tochar, noundo; 2712 Lisp_Object start, end, fromchar, tochar, noundo;
2713{ 2713{
2714 register int pos, pos_byte, stop, i, len, end_byte; 2714 register int pos, pos_byte, stop, i, len, end_byte;
2715 /* Keep track of the first change in the buffer:
2716 if 0 we haven't found it yet.
2717 if < 0 we've found it and we've run the before-change-function.
2718 if > 0 we've actually performed it and the value is its position. */
2715 int changed = 0; 2719 int changed = 0;
2716 unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH]; 2720 unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
2717 unsigned char *p; 2721 unsigned char *p;
@@ -2724,6 +2728,8 @@ Both characters must have the same length of multi-byte form. */)
2724 int last_changed = 0; 2728 int last_changed = 0;
2725 int multibyte_p = !NILP (current_buffer->enable_multibyte_characters); 2729 int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
2726 2730
2731 restart:
2732
2727 validate_region (&start, &end); 2733 validate_region (&start, &end);
2728 CHECK_NUMBER (fromchar); 2734 CHECK_NUMBER (fromchar);
2729 CHECK_NUMBER (tochar); 2735 CHECK_NUMBER (tochar);
@@ -2761,7 +2767,7 @@ Both characters must have the same length of multi-byte form. */)
2761 That's faster than getting rid of things, 2767 That's faster than getting rid of things,
2762 and it prevents even the entry for a first change. 2768 and it prevents even the entry for a first change.
2763 Also inhibit locking the file. */ 2769 Also inhibit locking the file. */
2764 if (!NILP (noundo)) 2770 if (!changed && !NILP (noundo))
2765 { 2771 {
2766 record_unwind_protect (subst_char_in_region_unwind, 2772 record_unwind_protect (subst_char_in_region_unwind,
2767 current_buffer->undo_list); 2773 current_buffer->undo_list);
@@ -2795,10 +2801,14 @@ Both characters must have the same length of multi-byte form. */)
2795 && (len == 2 || (p[2] == fromstr[2] 2801 && (len == 2 || (p[2] == fromstr[2]
2796 && (len == 3 || p[3] == fromstr[3])))))) 2802 && (len == 3 || p[3] == fromstr[3]))))))
2797 { 2803 {
2798 if (! changed) 2804 if (changed < 0)
2805 /* We've already seen this and run the before-change-function;
2806 this time we only need to record the actual position. */
2807 changed = pos;
2808 else if (!changed)
2799 { 2809 {
2800 changed = pos; 2810 changed = -1;
2801 modify_region (current_buffer, changed, XINT (end)); 2811 modify_region (current_buffer, pos, XINT (end));
2802 2812
2803 if (! NILP (noundo)) 2813 if (! NILP (noundo))
2804 { 2814 {
@@ -2807,6 +2817,10 @@ Both characters must have the same length of multi-byte form. */)
2807 if (MODIFF - 1 == current_buffer->auto_save_modified) 2817 if (MODIFF - 1 == current_buffer->auto_save_modified)
2808 current_buffer->auto_save_modified++; 2818 current_buffer->auto_save_modified++;
2809 } 2819 }
2820
2821 /* The before-change-function may have moved the gap
2822 or even modified the buffer so we should start over. */
2823 goto restart;
2810 } 2824 }
2811 2825
2812 /* Take care of the case where the new character 2826 /* Take care of the case where the new character
@@ -2859,7 +2873,7 @@ Both characters must have the same length of multi-byte form. */)
2859 pos++; 2873 pos++;
2860 } 2874 }
2861 2875
2862 if (changed) 2876 if (changed > 0)
2863 { 2877 {
2864 signal_after_change (changed, 2878 signal_after_change (changed,
2865 last_changed - changed, last_changed - changed); 2879 last_changed - changed, last_changed - changed);