(translate_char): Accept list of translation tables.
[bpt/emacs.git] / src / insdel.c
index 1f3cff6..405b383 100644 (file)
@@ -1,5 +1,5 @@
 /* Buffer insertion/deletion and gap motion for GNU Emacs.
-   Copyright (C) 1985, 86,93,94,95,97,98, 1999, 2000, 2001
+   Copyright (C) 1985, 86,93,94,95,97,98, 1999, 2000, 01, 2003
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -79,23 +79,19 @@ static int check_markers_debug_flag;
 void
 check_markers ()
 {
-  register Lisp_Object tail;
+  register struct Lisp_Marker *tail;
   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 ();
-      if (XMARKER (tail)->charpos > Z)
+      if (tail->charpos > Z)
        abort ();
-      if (XMARKER (tail)->bytepos > Z_BYTE)
+      if (tail->bytepos > Z_BYTE)
        abort ();
-      if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (XMARKER (tail)->bytepos)))
+      if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
        abort ();
-
-      tail = XMARKER (tail)->chain;
     }
 }
 \f
@@ -350,11 +346,8 @@ adjust_markers_for_delete (from, from_byte, to, to_byte)
   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)
@@ -371,16 +364,19 @@ adjust_markers_for_delete (from, from_byte, to, to_byte)
       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
-              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);
+           }
          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.  */
+             XSETMISC (marker, m);
            record_marker_adjustment (marker, charpos - to);
-
+           }
          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.  */
+         XSETMISC (marker, m);
          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;
 {
-  Lisp_Object marker;
+  struct Lisp_Marker *m;
   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)
@@ -447,8 +438,6 @@ adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
          m->bytepos += nbytes;
          m->charpos += nchars;
        }
-
-      marker = m->chain;
     }
 
   /* Adjusting only markers whose insertion-type is t may result in
@@ -490,15 +479,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;
 {
-  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;
 
-  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;
@@ -509,8 +496,6 @@ adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
          m->charpos = from;
          m->bytepos = from_byte;
        }
-
-      marker = m->chain;
     }
 
   CHECK_MARKERS ();
@@ -536,7 +521,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.  */
-     
+
   if (Z_BYTE - BEG_BYTE + GAP_SIZE
       >= (((EMACS_INT) 1 << (min (VALBITS, BITS_PER_INT) - 1)) - 1
          - nbytes_added))
@@ -573,7 +558,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)
@@ -654,7 +639,7 @@ make_gap (nbytes_added)
 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;
@@ -674,7 +659,7 @@ copy_text (from_addr, to_addr, nbytes,
        {
          int thislen, c;
          c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen);
-         if (!SINGLE_BYTE_CHAR_P (c))
+         if (!ASCII_CHAR_P (c))
            c = multibyte_char_to_unibyte (c, tbl);
          *to_addr++ = c;
          from_addr += thislen;
@@ -712,7 +697,7 @@ copy_text (from_addr, to_addr, nbytes,
 
 int
 count_size_as_multibyte (ptr, nbytes)
-     unsigned char *ptr;
+     const unsigned char *ptr;
      int nbytes;
 {
   int i;
@@ -744,7 +729,7 @@ count_size_as_multibyte (ptr, nbytes)
 
 void
 insert (string, nbytes)
-     register unsigned char *string;
+     register const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
@@ -760,7 +745,7 @@ insert (string, nbytes)
 
 void
 insert_and_inherit (string, nbytes)
-     register unsigned char *string;
+     register const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
@@ -796,7 +781,7 @@ insert_char (c)
 
 void
 insert_string (s)
-     char *s;
+     const char *s;
 {
   insert (s, strlen (s));
 }
@@ -808,7 +793,7 @@ insert_string (s)
 
 void
 insert_before_markers (string, nbytes)
-     unsigned char *string;
+     const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
@@ -825,7 +810,7 @@ insert_before_markers (string, nbytes)
 
 void
 insert_before_markers_and_inherit (string, nbytes)
-     unsigned char *string;
+     const unsigned char *string;
      register int nbytes;
 {
   if (nbytes > 0)
@@ -842,7 +827,7 @@ insert_before_markers_and_inherit (string, nbytes)
 
 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;
 {
@@ -860,12 +845,12 @@ insert_1 (string, nbytes, inherit, prepare, before_markers)
 
 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;
-  unsigned char *p;
+  const unsigned char *p;
 
   if (NILP (current_buffer->enable_multibyte_characters))
     return 0;
@@ -907,7 +892,7 @@ count_combining_before (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;
 {
@@ -973,13 +958,13 @@ count_combining_after (string, length, pos, pos_byte)
 
 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;
-  
+
   if (NILP (current_buffer->enable_multibyte_characters))
     nchars = nbytes;
 
@@ -1020,6 +1005,10 @@ insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
   if (GPT_BYTE < GPT)
     abort ();
 
+  /* The insert may have been in the unchanged region, so check again. */
+  if (Z - GPT < END_UNCHANGED)
+    END_UNCHANGED = Z - GPT;
+
   adjust_overlays_for_insert (PT, nchars);
   adjust_markers_for_insert (PT, PT_BYTE,
                             PT + nchars, PT_BYTE + nbytes,
@@ -1037,47 +1026,6 @@ insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
   CHECK_MARKERS ();
 }
 \f
-/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
-   starting at GPT_ADDR.  This funciton assumes PT == GPT.  */
-
-void
-insert_from_gap (nchars, nbytes)
-     register int nchars, nbytes;
-{
-  if (PT != GPT)
-    abort ();
-
-  if (NILP (current_buffer->enable_multibyte_characters))
-    nchars = nbytes;
-
-  record_insert (PT, nchars);
-  MODIFF++;
-
-  GAP_SIZE -= nbytes;
-  GPT += nchars;
-  ZV += nchars;
-  Z += nchars;
-  GPT_BYTE += nbytes;
-  ZV_BYTE += nbytes;
-  Z_BYTE += nbytes;
-  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
-
-  if (GPT_BYTE < GPT)
-    abort ();
-
-  adjust_overlays_for_insert (PT, nchars);
-  adjust_markers_for_insert (PT, PT_BYTE,
-                            PT + nchars, PT_BYTE + nbytes,
-                            0);
-
-  if (BUF_INTERVALS (current_buffer) != 0)
-    offset_intervals (current_buffer, PT, nchars);
-
-  adjust_point (nchars, nbytes);
-
-  CHECK_MARKERS ();
-}
-\f
 /* Insert the part of the text of STRING, a Lisp object assumed to be
    of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
    starting at position POS / POS_BYTE.  If the text of STRING has properties,
@@ -1137,7 +1085,7 @@ insert_from_string_1 (string, pos, pos_byte, nchars, 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);
@@ -1154,7 +1102,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_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));
 
@@ -1184,6 +1132,10 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
   if (GPT_BYTE < GPT)
     abort ();
 
+  /* The insert may have been in the unchanged region, so check again. */
+  if (Z - GPT < END_UNCHANGED)
+    END_UNCHANGED = Z - GPT;
+
   adjust_overlays_for_insert (PT, nchars);
   adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
                             PT_BYTE + outgoing_nbytes,
@@ -1191,16 +1143,60 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
 
   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.  */
-  if (nbytes < STRING_BYTES (XSTRING (string)))
+  if (nbytes < SBYTES (string))
     intervals = copy_intervals (intervals, pos, nchars);
-                              
+
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, PT, nchars,
                               current_buffer, inherit);
 
   adjust_point (nchars, outgoing_nbytes);
+
+  CHECK_MARKERS ();
+}
+\f
+/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
+   starting at GPT_ADDR.  */
+
+void
+insert_from_gap (nchars, nbytes)
+     register int nchars, nbytes;
+{
+  if (NILP (current_buffer->enable_multibyte_characters))
+    nchars = nbytes;
+
+  record_insert (GPT, nchars);
+  MODIFF++;
+
+  GAP_SIZE -= nbytes;
+  GPT += nchars;
+  ZV += nchars;
+  Z += nchars;
+  GPT_BYTE += nbytes;
+  ZV_BYTE += nbytes;
+  Z_BYTE += nbytes;
+  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
+
+  if (GPT_BYTE < GPT)
+    abort ();
+
+  adjust_overlays_for_insert (GPT - nchars, nchars);
+  adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
+                            GPT, GPT_BYTE, 0);
+
+  if (BUF_INTERVALS (current_buffer) != 0)
+    {
+      offset_intervals (current_buffer, GPT - nchars, nchars);
+      graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
+                                  current_buffer, 0);
+    }
+
+  if (GPT - nchars < PT)
+    adjust_point (nchars, nbytes);
+
+  CHECK_MARKERS ();
 }
 \f
 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
@@ -1261,13 +1257,13 @@ insert_from_buffer_1 (buf, from, nchars, inherit)
 
       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;
     }
-  
+
   /* Make sure point-max won't overflow after this insertion.  */
   XSETINT (temp, outgoing_nbytes + Z);
   if (outgoing_nbytes + Z != XINT (temp))
@@ -1331,6 +1327,10 @@ insert_from_buffer_1 (buf, from, nchars, inherit)
   if (GPT_BYTE < GPT)
     abort ();
 
+  /* The insert may have been in the unchanged region, so check again. */
+  if (Z - GPT < END_UNCHANGED)
+    END_UNCHANGED = Z - GPT;
+
   adjust_overlays_for_insert (PT, nchars);
   adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
                             PT_BYTE + outgoing_nbytes,
@@ -1347,7 +1347,7 @@ insert_from_buffer_1 (buf, from, nchars, inherit)
        from += nchars;
       intervals = copy_intervals (intervals, from, nchars);
     }
-                              
+
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
 
@@ -1376,8 +1376,8 @@ adjust_after_replace (from, from_byte, prev_text, len, len_byte)
 
   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.  */
@@ -1511,8 +1511,8 @@ replace_range (from, to, new, 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;
@@ -1557,7 +1557,7 @@ replace_range (from, to, new, prepare, inherit, markers)
     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);
@@ -1600,7 +1600,7 @@ replace_range (from, to, new, prepare, inherit, markers)
 
   /* 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));
 
@@ -1647,7 +1647,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.  */
-  intervals = XSTRING (new)->intervals;
+  intervals = STRING_INTERVALS (new);
   /* Insert those intervals.  */
   graft_intervals_into_buffer (intervals, from, inschars,
                               current_buffer, inherit);
@@ -1948,7 +1948,7 @@ prepare_to_modify_buffer (start, end, preserve_ptr)
          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
@@ -1996,7 +1996,7 @@ prepare_to_modify_buffer (start, end, preserve_ptr)
   if (! NILP (preserve_marker))                                        \
     {                                                          \
       *preserve_ptr = marker_position (preserve_marker);       \
-      unchain_marker (preserve_marker);                                \
+      unchain_marker (XMARKER (preserve_marker));              \
     }
 
 #define PRESERVE_START_END                     \
@@ -2093,8 +2093,7 @@ signal_before_change (start_int, end_int, preserve_ptr)
       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,
@@ -2128,8 +2127,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)
-      && NILP (current_buffer->overlays_before)
-      && NILP (current_buffer->overlays_after))
+      && !current_buffer->overlays_before
+      && !current_buffer->overlays_after)
     {
       Lisp_Object elt;
 
@@ -2147,7 +2146,7 @@ signal_after_change (charpos, lendel, lenins)
       return;
     }
 
-  if (!NILP (combine_after_change_list)) 
+  if (!NILP (combine_after_change_list))
     Fcombine_after_change_execute ();
 
   if (!NILP (Vafter_change_functions))
@@ -2194,8 +2193,7 @@ signal_after_change (charpos, lendel, lenins)
       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,
@@ -2223,7 +2221,7 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
        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;
@@ -2278,7 +2276,7 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
      that was changed.  */
   begpos = BEG + beg;
   endpos = Z - end;
-  
+
   /* We are about to handle these, so discard them.  */
   combine_after_change_list = Qnil;