(find-dired-filter): Propertize all text down to eob.
[bpt/emacs.git] / src / insdel.c
index 5bec29e..7f15f7d 100644 (file)
@@ -1,6 +1,6 @@
 /* Buffer insertion/deletion and gap motion for GNU Emacs.
 /* Buffer insertion/deletion and gap motion for GNU Emacs.
-   Copyright (C) 1985, 86,93,94,95,97,98, 1999, 2000, 2001
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 
 #include <config.h>
 
 
 #include <config.h>
@@ -79,23 +79,19 @@ static int check_markers_debug_flag;
 void
 check_markers ()
 {
 void
 check_markers ()
 {
-  register Lisp_Object tail;
+  register struct Lisp_Marker *tail;
   int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 
   int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 
-  tail = BUF_MARKERS (current_buffer);
-
-  while (! NILP (tail))
+  for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
     {
     {
-      if (XMARKER (tail)->buffer->text != current_buffer->text)
+      if (tail->buffer->text != current_buffer->text)
        abort ();
        abort ();
-      if (XMARKER (tail)->charpos > Z)
+      if (tail->charpos > Z)
        abort ();
        abort ();
-      if (XMARKER (tail)->bytepos > Z_BYTE)
+      if (tail->bytepos > Z_BYTE)
        abort ();
        abort ();
-      if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (XMARKER (tail)->bytepos)))
+      if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
        abort ();
        abort ();
-
-      tail = XMARKER (tail)->chain;
     }
 }
 \f
     }
 }
 \f
@@ -350,11 +346,8 @@ adjust_markers_for_delete (from, from_byte, to, to_byte)
   register struct Lisp_Marker *m;
   register int charpos;
 
   register struct Lisp_Marker *m;
   register int charpos;
 
-  marker = BUF_MARKERS (current_buffer);
-
-  while (!NILP (marker))
+  for (m = BUF_MARKERS (current_buffer); m; m = m->next)
     {
     {
-      m = XMARKER (marker);
       charpos = m->charpos;
 
       if (charpos > Z)
       charpos = m->charpos;
 
       if (charpos > Z)
@@ -371,16 +364,19 @@ adjust_markers_for_delete (from, from_byte, to, to_byte)
       else if (charpos > from)
        {
          if (! m->insertion_type)
       else if (charpos > from)
        {
          if (! m->insertion_type)
-           /* Normal markers will end up at the beginning of the
+           /* Normal markers will end up at the beginning of the
               re-inserted text after undoing a deletion, and must be
               re-inserted text after undoing a deletion, and must be
-              adjusted to move them to the correct place.  */ 
+              adjusted to move them to the correct place.  */
+             XSETMISC (marker, m);
            record_marker_adjustment (marker, from - charpos);
            record_marker_adjustment (marker, from - charpos);
+           }
          else if (charpos < to)
          else if (charpos < to)
-           /* Before-insertion markers will automatically move forward
+           /* Before-insertion markers will automatically move forward
               upon re-inserting the deleted text, so we have to arrange
               for them to move backward to the correct position.  */
               upon re-inserting the deleted text, so we have to arrange
               for them to move backward to the correct position.  */
+             XSETMISC (marker, m);
            record_marker_adjustment (marker, charpos - to);
            record_marker_adjustment (marker, charpos - to);
-
+           }
          m->charpos = from;
          m->bytepos = from_byte;
        }
          m->charpos = from;
          m->bytepos = from_byte;
        }
@@ -392,10 +388,9 @@ adjust_markers_for_delete (from, from_byte, to, to_byte)
             incorrectly make MARKER move forward, so we arrange for it
             to then move backward to the correct place at the beginning
             of the deleted region.  */
             incorrectly make MARKER move forward, so we arrange for it
             to then move backward to the correct place at the beginning
             of the deleted region.  */
+         XSETMISC (marker, m);
          record_marker_adjustment (marker, to - from);
        }
          record_marker_adjustment (marker, to - from);
        }
-
-      marker = m->chain;
     }
 }
 
     }
 }
 
@@ -413,17 +408,13 @@ adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
      register int from, from_byte, to, to_byte;
      int before_markers;
 {
      register int from, from_byte, to, to_byte;
      int before_markers;
 {
-  Lisp_Object marker;
+  struct Lisp_Marker *m;
   int adjusted = 0;
   int nchars = to - from;
   int nbytes = to_byte - from_byte;
 
   int adjusted = 0;
   int nchars = to - from;
   int nbytes = to_byte - from_byte;
 
-  marker = BUF_MARKERS (current_buffer);
-
-  while (!NILP (marker))
+  for (m = BUF_MARKERS (current_buffer); m; m = m->next)
     {
     {
-      register struct Lisp_Marker *m = XMARKER (marker);
-
       /* In a single-byte buffer, a marker's two positions must be
         equal.  */
       if (Z == Z_BYTE)
       /* In a single-byte buffer, a marker's two positions must be
         equal.  */
       if (Z == Z_BYTE)
@@ -447,14 +438,16 @@ adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
          m->bytepos += nbytes;
          m->charpos += nchars;
        }
          m->bytepos += nbytes;
          m->charpos += nchars;
        }
-
-      marker = m->chain;
     }
 
   /* Adjusting only markers whose insertion-type is t may result in
     }
 
   /* Adjusting only markers whose insertion-type is t may result in
-     disordered overlays in the slot `overlays_before'.  */
+     - disordered start and end in overlays, and 
+     - disordered overlays in the slot `overlays_before' of current_buffer.  */
   if (adjusted)
   if (adjusted)
-    fix_overlays_before (current_buffer, from, to);
+    {
+      fix_start_end_in_overlays(from, to);
+      fix_overlays_before (current_buffer, from, to);
+    }
 }
 
 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
 }
 
 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
@@ -490,15 +483,13 @@ adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
                            new_chars, new_bytes)
      int from, from_byte, old_chars, old_bytes, new_chars, new_bytes;
 {
                            new_chars, new_bytes)
      int from, from_byte, old_chars, old_bytes, new_chars, new_bytes;
 {
-  Lisp_Object marker = BUF_MARKERS (current_buffer);
+  register struct Lisp_Marker *m;
   int prev_to_byte = from_byte + old_bytes;
   int diff_chars = new_chars - old_chars;
   int diff_bytes = new_bytes - old_bytes;
 
   int prev_to_byte = from_byte + old_bytes;
   int diff_chars = new_chars - old_chars;
   int diff_bytes = new_bytes - old_bytes;
 
-  while (!NILP (marker))
+  for (m = BUF_MARKERS (current_buffer); m; m = m->next)
     {
     {
-      register struct Lisp_Marker *m = XMARKER (marker);
-
       if (m->bytepos >= prev_to_byte)
        {
          m->charpos += diff_chars;
       if (m->bytepos >= prev_to_byte)
        {
          m->charpos += diff_chars;
@@ -509,8 +500,6 @@ adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
          m->charpos = from;
          m->bytepos = from_byte;
        }
          m->charpos = from;
          m->bytepos = from_byte;
        }
-
-      marker = m->chain;
     }
 
   CHECK_MARKERS ();
     }
 
   CHECK_MARKERS ();
@@ -536,7 +525,7 @@ make_gap_larger (nbytes_added)
      That won't work because so many places use `int'.
 
      Make sure we don't introduce overflows in the calculation.  */
      That won't work because so many places use `int'.
 
      Make sure we don't introduce overflows in the calculation.  */
-     
+
   if (Z_BYTE - BEG_BYTE + GAP_SIZE
       >= (((EMACS_INT) 1 << (min (VALBITS, BITS_PER_INT) - 1)) - 1
          - nbytes_added))
   if (Z_BYTE - BEG_BYTE + GAP_SIZE
       >= (((EMACS_INT) 1 << (min (VALBITS, BITS_PER_INT) - 1)) - 1
          - nbytes_added))
@@ -573,7 +562,7 @@ make_gap_larger (nbytes_added)
 }
 
 
 }
 
 
-/* Make the gap NBYTES_REMOVED bytes shorted.  */
+/* Make the gap NBYTES_REMOVED bytes shorter.  */
 
 void
 make_gap_smaller (nbytes_removed)
 
 void
 make_gap_smaller (nbytes_removed)
@@ -654,7 +643,7 @@ make_gap (nbytes_added)
 int
 copy_text (from_addr, to_addr, nbytes,
           from_multibyte, to_multibyte)
 int
 copy_text (from_addr, to_addr, nbytes,
           from_multibyte, to_multibyte)
-     unsigned char *from_addr;
+     const unsigned char *from_addr;
      unsigned char *to_addr;
      int nbytes;
      int from_multibyte, to_multibyte;
      unsigned char *to_addr;
      int nbytes;
      int from_multibyte, to_multibyte;
@@ -723,7 +712,7 @@ copy_text (from_addr, to_addr, nbytes,
 
 int
 count_size_as_multibyte (ptr, nbytes)
 
 int
 count_size_as_multibyte (ptr, nbytes)
-     unsigned char *ptr;
+     const unsigned char *ptr;
      int nbytes;
 {
   int i;
      int nbytes;
 {
   int i;
@@ -755,14 +744,15 @@ count_size_as_multibyte (ptr, nbytes)
 
 void
 insert (string, nbytes)
 
 void
 insert (string, nbytes)
-     register unsigned char *string;
+     register const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
     {
      register int nbytes;
 {
   if (nbytes > 0)
     {
-      int opoint = PT;
-      insert_1 (string, nbytes, 0, 1, 0);
-      signal_after_change (opoint, 0, PT - opoint);
+      int len = chars_in_text (string, nbytes), opoint;
+      insert_1_both (string, len, nbytes, 0, 1, 0);
+      opoint = PT - len;
+      signal_after_change (opoint, 0, len);
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
@@ -771,14 +761,15 @@ insert (string, nbytes)
 
 void
 insert_and_inherit (string, nbytes)
 
 void
 insert_and_inherit (string, nbytes)
-     register unsigned char *string;
+     register const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
     {
      register int nbytes;
 {
   if (nbytes > 0)
     {
-      int opoint = PT;
-      insert_1 (string, nbytes, 1, 1, 0);
-      signal_after_change (opoint, 0, PT - opoint);
+      int len = chars_in_text (string, nbytes), opoint;
+      insert_1_both (string, len, nbytes, 1, 1, 0);
+      opoint = PT - len;
+      signal_after_change (opoint, 0, len);
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
@@ -807,7 +798,7 @@ insert_char (c)
 
 void
 insert_string (s)
 
 void
 insert_string (s)
-     char *s;
+     const char *s;
 {
   insert (s, strlen (s));
 }
 {
   insert (s, strlen (s));
 }
@@ -819,15 +810,15 @@ insert_string (s)
 
 void
 insert_before_markers (string, nbytes)
 
 void
 insert_before_markers (string, nbytes)
-     unsigned char *string;
+     const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
     {
      register int nbytes;
 {
   if (nbytes > 0)
     {
-      int opoint = PT;
-
-      insert_1 (string, nbytes, 0, 1, 1);
-      signal_after_change (opoint, 0, PT - opoint);
+      int len = chars_in_text (string, nbytes), opoint;
+      insert_1_both (string, len, nbytes, 0, 1, 1);
+      opoint = PT - len;
+      signal_after_change (opoint, 0, len);
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
@@ -836,15 +827,15 @@ insert_before_markers (string, nbytes)
 
 void
 insert_before_markers_and_inherit (string, nbytes)
 
 void
 insert_before_markers_and_inherit (string, nbytes)
-     unsigned char *string;
+     const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
     {
      register int nbytes;
 {
   if (nbytes > 0)
     {
-      int opoint = PT;
-
-      insert_1 (string, nbytes, 1, 1, 1);
-      signal_after_change (opoint, 0, PT - opoint);
+      int len = chars_in_text (string, nbytes), opoint;
+      insert_1_both (string, len, nbytes, 1, 1, 1);
+      opoint = PT - len;
+      signal_after_change (opoint, 0, len);
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
       update_compositions (opoint, PT, CHECK_BORDER);
     }
 }
@@ -853,7 +844,7 @@ insert_before_markers_and_inherit (string, nbytes)
 
 void
 insert_1 (string, nbytes, inherit, prepare, before_markers)
 
 void
 insert_1 (string, nbytes, inherit, prepare, before_markers)
-     register unsigned char *string;
+     register const unsigned char *string;
      register int nbytes;
      int inherit, prepare, before_markers;
 {
      register int nbytes;
      int inherit, prepare, before_markers;
 {
@@ -871,12 +862,12 @@ insert_1 (string, nbytes, inherit, prepare, before_markers)
 
 int
 count_combining_before (string, length, pos, pos_byte)
 
 int
 count_combining_before (string, length, pos, pos_byte)
-     unsigned char *string;
+     const unsigned char *string;
      int length;
      int pos, pos_byte;
 {
   int len, combining_bytes;
      int length;
      int pos, pos_byte;
 {
   int len, combining_bytes;
-  unsigned char *p;
+  const unsigned char *p;
 
   if (NILP (current_buffer->enable_multibyte_characters))
     return 0;
 
   if (NILP (current_buffer->enable_multibyte_characters))
     return 0;
@@ -918,7 +909,7 @@ count_combining_before (string, length, pos, pos_byte)
 
 int
 count_combining_after (string, length, pos, pos_byte)
 
 int
 count_combining_after (string, length, pos, pos_byte)
-     unsigned char *string;
+     const unsigned char *string;
      int length;
      int pos, pos_byte;
 {
      int length;
      int pos, pos_byte;
 {
@@ -984,13 +975,13 @@ count_combining_after (string, length, pos, pos_byte)
 
 void
 insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
 
 void
 insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
-     register unsigned char *string;
+     register const unsigned char *string;
      register int nchars, nbytes;
      int inherit, prepare, before_markers;
 {
   if (nchars == 0)
     return;
      register int nchars, nbytes;
      int inherit, prepare, before_markers;
 {
   if (nchars == 0)
     return;
-  
+
   if (NILP (current_buffer->enable_multibyte_characters))
     nchars = nbytes;
 
   if (NILP (current_buffer->enable_multibyte_characters))
     nchars = nbytes;
 
@@ -1016,6 +1007,7 @@ insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
      will add up to the right stuff in the undo list.  */
   record_insert (PT, nchars);
   MODIFF++;
      will add up to the right stuff in the undo list.  */
   record_insert (PT, nchars);
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
 
   bcopy (string, GPT_ADDR, nbytes);
 
 
   bcopy (string, GPT_ADDR, nbytes);
 
@@ -1068,6 +1060,10 @@ insert_from_string (string, pos, pos_byte, length, length_byte, inherit)
      int inherit;
 {
   int opoint = PT;
      int inherit;
 {
   int opoint = PT;
+
+  if (SCHARS (string) == 0)
+    return;
+
   insert_from_string_1 (string, pos, pos_byte, length, length_byte,
                        inherit, 0);
   signal_after_change (opoint, 0, PT - opoint);
   insert_from_string_1 (string, pos, pos_byte, length, length_byte,
                        inherit, 0);
   signal_after_change (opoint, 0, PT - opoint);
@@ -1085,6 +1081,10 @@ insert_from_string_before_markers (string, pos, pos_byte,
      int inherit;
 {
   int opoint = PT;
      int inherit;
 {
   int opoint = PT;
+
+  if (SCHARS (string) == 0)
+    return;
+
   insert_from_string_1 (string, pos, pos_byte, length, length_byte,
                        inherit, 1);
   signal_after_change (opoint, 0, PT - opoint);
   insert_from_string_1 (string, pos, pos_byte, length, length_byte,
                        inherit, 1);
   signal_after_change (opoint, 0, PT - opoint);
@@ -1111,7 +1111,7 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
     outgoing_nbytes = nchars;
   else if (! STRING_MULTIBYTE (string))
     outgoing_nbytes
     outgoing_nbytes = nchars;
   else if (! STRING_MULTIBYTE (string))
     outgoing_nbytes
-      = count_size_as_multibyte (&XSTRING (string)->data[pos_byte],
+      = count_size_as_multibyte (SDATA (string) + pos_byte,
                                 nbytes);
 
   GCPRO1 (string);
                                 nbytes);
 
   GCPRO1 (string);
@@ -1128,7 +1128,7 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
 
   /* Copy the string text into the buffer, perhaps converting
      between single-byte and multibyte.  */
 
   /* Copy the string text into the buffer, perhaps converting
      between single-byte and multibyte.  */
-  copy_text (XSTRING (string)->data + pos_byte, GPT_ADDR, nbytes,
+  copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
             STRING_MULTIBYTE (string),
             ! NILP (current_buffer->enable_multibyte_characters));
 
             STRING_MULTIBYTE (string),
             ! NILP (current_buffer->enable_multibyte_characters));
 
@@ -1145,6 +1145,7 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
 
   record_insert (PT, nchars);
   MODIFF++;
 
   record_insert (PT, nchars);
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
 
   GAP_SIZE -= outgoing_nbytes;
   GPT += nchars;
 
   GAP_SIZE -= outgoing_nbytes;
   GPT += nchars;
@@ -1169,11 +1170,11 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
 
   offset_intervals (current_buffer, PT, nchars);
 
 
   offset_intervals (current_buffer, PT, nchars);
 
-  intervals = XSTRING (string)->intervals;
+  intervals = STRING_INTERVALS (string);
   /* Get the intervals for the part of the string we are inserting.  */
   /* Get the intervals for the part of the string we are inserting.  */
-  if (nbytes < STRING_BYTES (XSTRING (string)))
+  if (nbytes < SBYTES (string))
     intervals = copy_intervals (intervals, pos, nchars);
     intervals = copy_intervals (intervals, pos, nchars);
-                              
+
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, PT, nchars,
                               current_buffer, inherit);
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, PT, nchars,
                               current_buffer, inherit);
@@ -1239,13 +1240,13 @@ insert_from_buffer_1 (buf, from, nchars, inherit)
 
       if (chunk < incoming_nbytes)
        outgoing_after_gap
 
       if (chunk < incoming_nbytes)
        outgoing_after_gap
-         = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, 
+         = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
                                                       from_byte + chunk),
                                     incoming_nbytes - chunk);
 
       outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
     }
                                                       from_byte + chunk),
                                     incoming_nbytes - chunk);
 
       outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
     }
-  
+
   /* Make sure point-max won't overflow after this insertion.  */
   XSETINT (temp, outgoing_nbytes + Z);
   if (outgoing_nbytes + Z != XINT (temp))
   /* Make sure point-max won't overflow after this insertion.  */
   XSETINT (temp, outgoing_nbytes + Z);
   if (outgoing_nbytes + Z != XINT (temp))
@@ -1296,6 +1297,7 @@ insert_from_buffer_1 (buf, from, nchars, inherit)
 
   record_insert (PT, nchars);
   MODIFF++;
 
   record_insert (PT, nchars);
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
 
   GAP_SIZE -= outgoing_nbytes;
   GPT += nchars;
 
   GAP_SIZE -= outgoing_nbytes;
   GPT += nchars;
@@ -1329,7 +1331,7 @@ insert_from_buffer_1 (buf, from, nchars, inherit)
        from += nchars;
       intervals = copy_intervals (intervals, from, nchars);
     }
        from += nchars;
       intervals = copy_intervals (intervals, from, nchars);
     }
-                              
+
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
 
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
 
@@ -1358,8 +1360,8 @@ adjust_after_replace (from, from_byte, prev_text, len, len_byte)
 
   if (STRINGP (prev_text))
     {
 
   if (STRINGP (prev_text))
     {
-      nchars_del = XSTRING (prev_text)->size;
-      nbytes_del = STRING_BYTES (XSTRING (prev_text));
+      nchars_del = SCHARS (prev_text);
+      nbytes_del = SBYTES (prev_text);
     }
 
   /* Update various buffer positions for the new text.  */
     }
 
   /* Update various buffer positions for the new text.  */
@@ -1404,6 +1406,7 @@ adjust_after_replace (from, from_byte, prev_text, len, len_byte)
   if (len == 0)
     evaporate_overlays (from);
   MODIFF++;
   if (len == 0)
     evaporate_overlays (from);
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
 }
 
 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
 }
 
 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
@@ -1454,6 +1457,7 @@ adjust_after_replace_noundo (from, from_byte, nchars_del, nbytes_del, len, len_b
   if (len == 0)
     evaporate_overlays (from);
   MODIFF++;
   if (len == 0)
     evaporate_overlays (from);
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
 }
 
 /* Record undo information, adjust markers and position keepers for an
 }
 
 /* Record undo information, adjust markers and position keepers for an
@@ -1475,7 +1479,7 @@ adjust_after_insert (from, from_byte, to, to_byte, newlen)
   Z -= len; Z_BYTE -= len_byte;
   adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
 }
   Z -= len; Z_BYTE -= len_byte;
   adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
 }
-
+\f
 /* Replace the text from character positions FROM to TO with NEW,
    If PREPARE is nonzero, call prepare_to_modify_buffer.
    If INHERIT, the newly inserted text should inherit text properties
 /* Replace the text from character positions FROM to TO with NEW,
    If PREPARE is nonzero, call prepare_to_modify_buffer.
    If INHERIT, the newly inserted text should inherit text properties
@@ -1493,8 +1497,8 @@ replace_range (from, to, new, prepare, inherit, markers)
      Lisp_Object new;
      int from, to, prepare, inherit, markers;
 {
      Lisp_Object new;
      int from, to, prepare, inherit, markers;
 {
-  int inschars = XSTRING (new)->size;
-  int insbytes = STRING_BYTES (XSTRING (new));
+  int inschars = SCHARS (new);
+  int insbytes = SBYTES (new);
   int from_byte, to_byte;
   int nbytes_del, nchars_del;
   register Lisp_Object temp;
   int from_byte, to_byte;
   int nbytes_del, nchars_del;
   register Lisp_Object temp;
@@ -1539,7 +1543,7 @@ replace_range (from, to, new, prepare, inherit, markers)
     outgoing_insbytes = inschars;
   else if (! STRING_MULTIBYTE (new))
     outgoing_insbytes
     outgoing_insbytes = inschars;
   else if (! STRING_MULTIBYTE (new))
     outgoing_insbytes
-      = count_size_as_multibyte (XSTRING (new)->data, insbytes);
+      = count_size_as_multibyte (SDATA (new), insbytes);
 
   /* Make sure point-max won't overflow after this insertion.  */
   XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
 
   /* Make sure point-max won't overflow after this insertion.  */
   XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
@@ -1567,7 +1571,7 @@ replace_range (from, to, new, prepare, inherit, markers)
   Z_BYTE -= nbytes_del;
   GPT = from;
   GPT_BYTE = from_byte;
   Z_BYTE -= nbytes_del;
   GPT = from;
   GPT_BYTE = from_byte;
-  *(GPT_ADDR) = 0;             /* Put an anchor.  */
+  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
 
   if (GPT_BYTE < GPT)
     abort ();
 
   if (GPT_BYTE < GPT)
     abort ();
@@ -1582,7 +1586,7 @@ replace_range (from, to, new, prepare, inherit, markers)
 
   /* Copy the string text into the buffer, perhaps converting
      between single-byte and multibyte.  */
 
   /* Copy the string text into the buffer, perhaps converting
      between single-byte and multibyte.  */
-  copy_text (XSTRING (new)->data, GPT_ADDR, insbytes,
+  copy_text (SDATA (new), GPT_ADDR, insbytes,
             STRING_MULTIBYTE (new),
             ! NILP (current_buffer->enable_multibyte_characters));
 
             STRING_MULTIBYTE (new),
             ! NILP (current_buffer->enable_multibyte_characters));
 
@@ -1629,7 +1633,7 @@ replace_range (from, to, new, prepare, inherit, markers)
 
   /* Get the intervals for the part of the string we are inserting--
      not including the combined-before bytes.  */
 
   /* Get the intervals for the part of the string we are inserting--
      not including the combined-before bytes.  */
-  intervals = XSTRING (new)->intervals;
+  intervals = STRING_INTERVALS (new);
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, from, inschars,
                               current_buffer, inherit);
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, from, inschars,
                               current_buffer, inherit);
@@ -1646,12 +1650,134 @@ replace_range (from, to, new, prepare, inherit, markers)
   CHECK_MARKERS ();
 
   MODIFF++;
   CHECK_MARKERS ();
 
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
   UNGCPRO;
 
   signal_after_change (from, nchars_del, GPT - from);
   update_compositions (from, GPT, CHECK_BORDER);
 }
 \f
   UNGCPRO;
 
   signal_after_change (from, nchars_del, GPT - from);
   update_compositions (from, GPT, CHECK_BORDER);
 }
 \f
+/* Replace the text from character positions FROM to TO with
+   the text in INS of length INSCHARS.
+   Keep the text properties that applied to the old characters
+   (extending them to all the new chars if there are more new chars).
+
+   Note that this does not yet handle markers quite right.
+
+   If MARKERS is nonzero, relocate markers.
+
+   Unlike most functions at this level, never call
+   prepare_to_modify_buffer and never call signal_after_change.  */
+
+void
+replace_range_2 (from, from_byte, to, to_byte, ins, inschars, insbytes, markers)
+     int from, from_byte, to, to_byte;
+     char *ins;
+     int inschars, insbytes, markers;
+{
+  int nbytes_del, nchars_del;
+  Lisp_Object temp;
+
+  CHECK_MARKERS ();
+
+  nchars_del = to - from;
+  nbytes_del = to_byte - from_byte;
+
+  if (nbytes_del <= 0 && insbytes == 0)
+    return;
+
+  /* Make sure point-max won't overflow after this insertion.  */
+  XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
+  if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
+    error ("Maximum buffer size exceeded");
+
+  /* Make sure the gap is somewhere in or next to what we are deleting.  */
+  if (from > GPT)
+    gap_right (from, from_byte);
+  if (to < GPT)
+    gap_left (to, to_byte, 0);
+
+  GAP_SIZE += nbytes_del;
+  ZV -= nchars_del;
+  Z -= nchars_del;
+  ZV_BYTE -= nbytes_del;
+  Z_BYTE -= nbytes_del;
+  GPT = from;
+  GPT_BYTE = from_byte;
+  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
+
+  if (GPT_BYTE < GPT)
+    abort ();
+
+  if (GPT - BEG < BEG_UNCHANGED)
+    BEG_UNCHANGED = GPT - BEG;
+  if (Z - GPT < END_UNCHANGED)
+    END_UNCHANGED = Z - GPT;
+
+  if (GAP_SIZE < insbytes)
+    make_gap (insbytes - GAP_SIZE);
+
+  /* Copy the replacement text into the buffer.  */
+  bcopy (ins, GPT_ADDR, insbytes);
+
+#ifdef BYTE_COMBINING_DEBUG
+  /* We have copied text into the gap, but we have not marked
+     it as part of the buffer.  So we can use the old FROM and FROM_BYTE
+     here, for both the previous text and the following text.
+     Meanwhile, GPT_ADDR does point to
+     the text that has been stored by copy_text.  */
+  if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
+      || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
+    abort ();
+#endif
+
+  GAP_SIZE -= insbytes;
+  GPT += inschars;
+  ZV += inschars;
+  Z += inschars;
+  GPT_BYTE += insbytes;
+  ZV_BYTE += insbytes;
+  Z_BYTE += insbytes;
+  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
+
+  if (GPT_BYTE < GPT)
+    abort ();
+
+  /* Adjust the overlay center as needed.  This must be done after
+     adjusting the markers that bound the overlays.  */
+  if (nchars_del != inschars)
+    {
+      adjust_overlays_for_insert (from, inschars);
+      adjust_overlays_for_delete (from + inschars, nchars_del);
+    }
+
+  /* Adjust markers for the deletion and the insertion.  */
+  if (markers
+      && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
+    adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
+                               inschars, insbytes);
+
+  offset_intervals (current_buffer, from, inschars - nchars_del);
+
+  /* Relocate point as if it were a marker.  */
+  if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
+    {
+      if (PT < to)
+       /* PT was within the deleted text.  Move it to FROM.  */
+       adjust_point (from - PT, from_byte - PT_BYTE);
+      else
+       adjust_point (inschars - nchars_del, insbytes - nbytes_del);
+    }
+
+  if (insbytes == 0)
+    evaporate_overlays (from);
+
+  CHECK_MARKERS ();
+
+  MODIFF++;
+  CHARS_MODIFF = MODIFF;
+}
+\f
 /* Delete characters in current buffer
    from FROM up to (but not including) TO.
    If TO comes before FROM, we delete nothing.  */
 /* Delete characters in current buffer
    from FROM up to (but not including) TO.
    If TO comes before FROM, we delete nothing.  */
@@ -1831,6 +1957,7 @@ del_range_2 (from, from_byte, to, to_byte, ret_string)
   if (! EQ (current_buffer->undo_list, Qt))
     record_delete (from, deletion);
   MODIFF++;
   if (! EQ (current_buffer->undo_list, Qt))
     record_delete (from, deletion);
   MODIFF++;
+  CHARS_MODIFF = MODIFF;
 
   /* Relocate point as if it were a marker.  */
   if (from < PT)
 
   /* Relocate point as if it were a marker.  */
   if (from < PT)
@@ -1850,7 +1977,7 @@ del_range_2 (from, from_byte, to, to_byte, ret_string)
   Z -= nchars_del;
   GPT = from;
   GPT_BYTE = from_byte;
   Z -= nchars_del;
   GPT = from;
   GPT_BYTE = from_byte;
-  *(GPT_ADDR) = 0;             /* Put an anchor.  */
+  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
 
   if (GPT_BYTE < GPT)
     abort ();
 
   if (GPT_BYTE < GPT)
     abort ();
@@ -1871,12 +1998,15 @@ del_range_2 (from, from_byte, to, to_byte, ret_string)
    character positions START to END.  This checks the read-only
    properties of the region, calls the necessary modification hooks,
    and warns the next redisplay that it should pay attention to that
    character positions START to END.  This checks the read-only
    properties of the region, calls the necessary modification hooks,
    and warns the next redisplay that it should pay attention to that
-   area.  */
+   area.
+
+   If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
+   Otherwise set CHARS_MODIFF to the new value of MODIFF.  */
 
 void
 
 void
-modify_region (buffer, start, end)
+modify_region (buffer, start, end, preserve_chars_modiff)
      struct buffer *buffer;
      struct buffer *buffer;
-     int start, end;
+     int start, end, preserve_chars_modiff;
 {
   struct buffer *old_buffer = current_buffer;
 
 {
   struct buffer *old_buffer = current_buffer;
 
@@ -1890,6 +2020,8 @@ modify_region (buffer, start, end)
   if (MODIFF <= SAVE_MODIFF)
     record_first_change ();
   MODIFF++;
   if (MODIFF <= SAVE_MODIFF)
     record_first_change ();
   MODIFF++;
+  if (! preserve_chars_modiff)
+    CHARS_MODIFF = MODIFF;
 
   buffer->point_before_scroll = Qnil;
 
 
   buffer->point_before_scroll = Qnil;
 
@@ -1912,6 +2044,8 @@ prepare_to_modify_buffer (start, end, preserve_ptr)
      int start, end;
      int *preserve_ptr;
 {
      int start, end;
      int *preserve_ptr;
 {
+  struct buffer *base_buffer;
+
   if (!NILP (current_buffer->read_only))
     Fbarf_if_buffer_read_only ();
 
   if (!NILP (current_buffer->read_only))
     Fbarf_if_buffer_read_only ();
 
@@ -1930,27 +2064,33 @@ prepare_to_modify_buffer (start, end, preserve_ptr)
          GCPRO1 (preserve_marker);
          verify_interval_modification (current_buffer, start, end);
          *preserve_ptr = marker_position (preserve_marker);
          GCPRO1 (preserve_marker);
          verify_interval_modification (current_buffer, start, end);
          *preserve_ptr = marker_position (preserve_marker);
-         unchain_marker (preserve_marker);
+         unchain_marker (XMARKER (preserve_marker));
          UNGCPRO;
        }
       else
        verify_interval_modification (current_buffer, start, end);
     }
 
          UNGCPRO;
        }
       else
        verify_interval_modification (current_buffer, start, end);
     }
 
+  /* For indirect buffers, use the base buffer to check clashes.  */
+  if (current_buffer->base_buffer != 0)
+    base_buffer = current_buffer->base_buffer;
+  else
+    base_buffer = current_buffer;
+
 #ifdef CLASH_DETECTION
 #ifdef CLASH_DETECTION
-  if (!NILP (current_buffer->file_truename)
+  if (!NILP (base_buffer->file_truename)
       /* Make binding buffer-file-name to nil effective.  */
       /* Make binding buffer-file-name to nil effective.  */
-      && !NILP (current_buffer->filename)
+      && !NILP (base_buffer->filename)
       && SAVE_MODIFF >= MODIFF)
       && SAVE_MODIFF >= MODIFF)
-    lock_file (current_buffer->file_truename);
+    lock_file (base_buffer->file_truename);
 #else
   /* At least warn if this file has changed on disk since it was visited.  */
 #else
   /* At least warn if this file has changed on disk since it was visited.  */
-  if (!NILP (current_buffer->filename)
+  if (!NILP (base_buffer->filename)
       && SAVE_MODIFF >= MODIFF
       && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
       && SAVE_MODIFF >= MODIFF
       && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
-      && !NILP (Ffile_exists_p (current_buffer->filename)))
+      && !NILP (Ffile_exists_p (base_buffer->filename)))
     call1 (intern ("ask-user-about-supersession-threat"),
     call1 (intern ("ask-user-about-supersession-threat"),
-          current_buffer->filename);
+          base_buffer->filename);
 #endif /* not CLASH_DETECTION */
 
   signal_before_change (start, end, preserve_ptr);
 #endif /* not CLASH_DETECTION */
 
   signal_before_change (start, end, preserve_ptr);
@@ -1978,7 +2118,7 @@ prepare_to_modify_buffer (start, end, preserve_ptr)
   if (! NILP (preserve_marker))                                        \
     {                                                          \
       *preserve_ptr = marker_position (preserve_marker);       \
   if (! NILP (preserve_marker))                                        \
     {                                                          \
       *preserve_ptr = marker_position (preserve_marker);       \
-      unchain_marker (preserve_marker);                                \
+      unchain_marker (XMARKER (preserve_marker));              \
     }
 
 #define PRESERVE_START_END                     \
     }
 
 #define PRESERVE_START_END                     \
@@ -2075,8 +2215,7 @@ signal_before_change (start_int, end_int, preserve_ptr)
       UNGCPRO;
     }
 
       UNGCPRO;
     }
 
-  if (!NILP (current_buffer->overlays_before)
-      || !NILP (current_buffer->overlays_after))
+  if (current_buffer->overlays_before || current_buffer->overlays_after)
     {
       PRESERVE_VALUE;
       report_overlay_modification (FETCH_START, FETCH_END, 0,
     {
       PRESERVE_VALUE;
       report_overlay_modification (FETCH_START, FETCH_END, 0,
@@ -2110,8 +2249,8 @@ signal_after_change (charpos, lendel, lenins)
      just record the args that we were going to use.  */
   if (! NILP (Vcombine_after_change_calls)
       && NILP (Vbefore_change_functions)
      just record the args that we were going to use.  */
   if (! NILP (Vcombine_after_change_calls)
       && NILP (Vbefore_change_functions)
-      && NILP (current_buffer->overlays_before)
-      && NILP (current_buffer->overlays_after))
+      && !current_buffer->overlays_before
+      && !current_buffer->overlays_after)
     {
       Lisp_Object elt;
 
     {
       Lisp_Object elt;
 
@@ -2129,7 +2268,7 @@ signal_after_change (charpos, lendel, lenins)
       return;
     }
 
       return;
     }
 
-  if (!NILP (combine_after_change_list)) 
+  if (!NILP (combine_after_change_list))
     Fcombine_after_change_execute ();
 
   if (!NILP (Vafter_change_functions))
     Fcombine_after_change_execute ();
 
   if (!NILP (Vafter_change_functions))
@@ -2176,8 +2315,7 @@ signal_after_change (charpos, lendel, lenins)
       UNGCPRO;
     }
 
       UNGCPRO;
     }
 
-  if (!NILP (current_buffer->overlays_before)
-      || !NILP (current_buffer->overlays_after))
+  if (current_buffer->overlays_before || current_buffer->overlays_after)
     report_overlay_modification (make_number (charpos),
                                 make_number (charpos + lenins),
                                 1,
     report_overlay_modification (make_number (charpos),
                                 make_number (charpos + lenins),
                                 1,
@@ -2205,7 +2343,7 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
        doc: /* This function is for use internally in `combine-after-change-calls'.  */)
      ()
 {
        doc: /* This function is for use internally in `combine-after-change-calls'.  */)
      ()
 {
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   int beg, end, change;
   int begpos, endpos;
   Lisp_Object tail;
   int beg, end, change;
   int begpos, endpos;
   Lisp_Object tail;
@@ -2213,6 +2351,17 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
   if (NILP (combine_after_change_list))
     return Qnil;
 
   if (NILP (combine_after_change_list))
     return Qnil;
 
+  /* It is rare for combine_after_change_buffer to be invalid, but
+     possible.  It can happen when combine-after-change-calls is
+     non-nil, and insertion calls a file handler (e.g. through
+     lock_file) which scribbles into a temp file -- cyd  */
+  if (!BUFFERP (combine_after_change_buffer)
+      || NILP (XBUFFER (combine_after_change_buffer)->name))
+    {
+      combine_after_change_list = Qnil;
+      return Qnil;
+    }
+
   record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
 
   Fset_buffer (combine_after_change_buffer);
   record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
 
   Fset_buffer (combine_after_change_buffer);
@@ -2260,7 +2409,7 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
      that was changed.  */
   begpos = BEG + beg;
   endpos = Z - end;
      that was changed.  */
   begpos = BEG + beg;
   endpos = Z - end;
-  
+
   /* We are about to handle these, so discard them.  */
   combine_after_change_list = Qnil;
 
   /* We are about to handle these, so discard them.  */
   combine_after_change_list = Qnil;
 
@@ -2278,6 +2427,7 @@ void
 syms_of_insdel ()
 {
   staticpro (&combine_after_change_list);
 syms_of_insdel ()
 {
   staticpro (&combine_after_change_list);
+  staticpro (&combine_after_change_buffer);
   combine_after_change_list = Qnil;
   combine_after_change_buffer = Qnil;
 
   combine_after_change_list = Qnil;
   combine_after_change_buffer = Qnil;
 
@@ -2298,3 +2448,6 @@ as well as hooks attached to text properties and overlays.  */);
 
   defsubr (&Scombine_after_change_execute);
 }
 
   defsubr (&Scombine_after_change_execute);
 }
+
+/* arch-tag: 9b34b886-47d7-465e-a234-299af411b23d
+   (do not change this comment) */