(X_IO_BUG): Defined.
[bpt/emacs.git] / src / buffer.c
index 038c5ae..8ebfe98 100644 (file)
@@ -1635,6 +1635,109 @@ recenter_overlay_lists (buf, pos)
 
   XFASTINT (buf->overlay_center) = pos;
 }
+
+/* Fix up overlays that were garbled as a result of permuting markers
+   in the range START through END.  Any overlay with at least one
+   endpoint in this range will need to be unlinked from the overlay
+   list and reinserted in its proper place.
+   Such an overlay might even have negative size at this point.
+   If so, we'll reverse the endpoints.  Can you think of anything
+   better to do in this situation?  */
+void
+fix_overlays_in_range (start, end)
+     register int start, end;
+{
+  Lisp_Object tem, overlay;
+  Lisp_Object before_list, after_list;
+  Lisp_Object *ptail, *pbefore = &before_list, *pafter = &after_list;
+  int startpos, endpos;
+
+  /* This algorithm shifts links around instead of consing and GCing.
+     The loop invariant is that before_list (resp. after_list) is a
+     well-formed list except that its last element, the one that
+     *pbefore (resp. *pafter) points to, is still uninitialized.
+     So it's not a bug that before_list isn't initialized, although
+     it may look strange.  */
+  for (ptail = &current_buffer->overlays_before; CONSP (*ptail);)
+    {
+      overlay = XCONS (*ptail)->car;
+      endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
+      if (endpos < start)
+       break;
+      startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
+      if (endpos < end
+         || (startpos >= start && startpos < end))
+       {
+         /* If the overlay is backwards, fix that now.  */
+         if (startpos > endpos)
+           {
+             int tem;
+             Fset_marker (OVERLAY_START (overlay), endpos, Qnil);
+             Fset_marker (OVERLAY_END (overlay), startpos, Qnil);
+             tem = startpos; startpos = endpos; endpos = tem;
+           }
+         /* Add it to the end of the wrong list.  Later on,
+            recenter_overlay_lists will move it to the right place.  */
+         if (endpos < XINT (current_buffer->overlay_center))
+           {
+             *pafter = *ptail;
+             pafter = &XCONS (*ptail)->cdr;
+           }
+         else
+           {
+             *pbefore = *ptail;
+             pbefore = &XCONS (*ptail)->cdr;
+           }
+         *ptail = XCONS (*ptail)->cdr;
+       }
+      else
+       ptail = &XCONS (*ptail)->cdr;
+    }
+  for (ptail = &current_buffer->overlays_after; CONSP (*ptail);)
+    {
+      overlay = XCONS (*ptail)->car;
+      startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
+      if (startpos >= end)
+       break;
+      endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
+      if (startpos >= start
+         || (endpos >= start && endpos < end))
+       {
+         if (startpos > endpos)
+           {
+             int tem;
+             Fset_marker (OVERLAY_START (overlay), endpos, Qnil);
+             Fset_marker (OVERLAY_END (overlay), startpos, Qnil);
+             tem = startpos; startpos = endpos; endpos = tem;
+           }
+         if (endpos < XINT (current_buffer->overlay_center))
+           {
+             *pafter = *ptail;
+             pafter = &XCONS (*ptail)->cdr;
+           }
+         else
+           {
+             *pbefore = *ptail;
+             pbefore = &XCONS (*ptail)->cdr;
+           }
+         *ptail = XCONS (*ptail)->cdr;
+       }
+      else
+       ptail = &XCONS (*ptail)->cdr;
+    }
+
+  /* Splice the constructed (wrong) lists into the buffer's lists,
+     and let the recenter function make it sane again.  */
+  *pbefore = current_buffer->overlays_before;
+  current_buffer->overlays_before = before_list;
+  recenter_overlay_lists (current_buffer,
+                         XINT (current_buffer->overlay_center));
+
+  *pafter = current_buffer->overlays_after;
+  current_buffer->overlays_after = after_list;
+  recenter_overlay_lists (current_buffer,
+                         XINT (current_buffer->overlay_center));
+}
 \f
 DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
   "Return t if OBJECT is an overlay.")
@@ -2031,7 +2134,14 @@ verify_overlay_modification (start, end)
 {
   Lisp_Object prop, overlay, tail;
   int insertion = EQ (start, end);
+  int tail_copied;
+  struct gcpro gcpro1, gcpro2;
+
+  overlay = Qnil;
+  tail = Qnil;
+  GCPRO2 (overlay, tail);
 
+  tail_copied = 0;
   for (tail = current_buffer->overlays_before;
        CONSP (tail);
        tail = XCONS (tail)->cdr)
@@ -2053,7 +2163,9 @@ verify_overlay_modification (start, end)
          if (!NILP (prop))
            {
              /* Copy TAIL in case the hook recenters the overlay lists.  */
-             tail = Fcopy_sequence (tail);
+             if (!tail_copied)
+               tail = Fcopy_sequence (tail);
+             tail_copied = 1;
              call_overlay_mod_hooks (prop, overlay, start, end);
            }
        }
@@ -2062,7 +2174,9 @@ verify_overlay_modification (start, end)
          prop = Foverlay_get (overlay, Qinsert_behind_hooks);
          if (!NILP (prop))
            {
-             tail = Fcopy_sequence (tail);
+             if (!tail_copied)
+               tail = Fcopy_sequence (tail);
+             tail_copied = 1;
              call_overlay_mod_hooks (prop, overlay, start, end);
            }
        }
@@ -2073,12 +2187,15 @@ verify_overlay_modification (start, end)
          prop = Foverlay_get (overlay, Qmodification_hooks);
          if (!NILP (prop))
            {
-             tail = Fcopy_sequence (tail);
+             if (!tail_copied)
+               tail = Fcopy_sequence (tail);
+             tail_copied = 1;
              call_overlay_mod_hooks (prop, overlay, start, end);
            }
        }
     }
 
+  tail_copied = 0;
   for (tail = current_buffer->overlays_after;
        CONSP (tail);
        tail = XCONS (tail)->cdr)
@@ -2099,7 +2216,9 @@ verify_overlay_modification (start, end)
          prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
          if (!NILP (prop))
            {
-             tail = Fcopy_sequence (tail);
+             if (!tail_copied)
+               tail = Fcopy_sequence (tail);
+             tail_copied = 1;
              call_overlay_mod_hooks (prop, overlay, start, end);
            }
        }
@@ -2108,7 +2227,9 @@ verify_overlay_modification (start, end)
          prop = Foverlay_get (overlay, Qinsert_behind_hooks);
          if (!NILP (prop))
            {
-             tail = Fcopy_sequence (tail);
+             if (!tail_copied)
+               tail = Fcopy_sequence (tail);
+             tail_copied = 1;
              call_overlay_mod_hooks (prop, overlay, start, end);
            }
        }
@@ -2119,11 +2240,15 @@ verify_overlay_modification (start, end)
          prop = Foverlay_get (overlay, Qmodification_hooks);
          if (!NILP (prop))
            {
-             tail = Fcopy_sequence (tail);
+             if (!tail_copied)
+               tail = Fcopy_sequence (tail);
+             tail_copied = 1;
              call_overlay_mod_hooks (prop, overlay, start, end);
            }
        }
     }
+
+  UNGCPRO;
 }
 
 static void