Commit 1138e742 authored by Ken Raeburn's avatar Ken Raeburn
Browse files

* buffer.c (fix_overlays_in_range, fix_overlays_before): Don't take the address

of the cdr part of a cons cell; instead, track the parent cell and call
XSETCDR, or set the variable for the head of the list if we haven't started
down the list yet.
parent 89fa1ef5
...@@ -3228,18 +3228,26 @@ fix_overlays_in_range (start, end) ...@@ -3228,18 +3228,26 @@ fix_overlays_in_range (start, end)
{ {
Lisp_Object overlay; Lisp_Object overlay;
Lisp_Object before_list, after_list; Lisp_Object before_list, after_list;
Lisp_Object *ptail, *pbefore = &before_list, *pafter = &after_list; /* These are either nil, indicating that before_list or after_list
should be assigned, or the cons cell the cdr of which should be
assigned. */
Lisp_Object beforep = Qnil, afterp = Qnil;
/* 'Parent', likewise, indicates a cons cell or
current_buffer->overlays_before or overlays_after, depending
which loop we're in. */
Lisp_Object tail, parent;
int startpos, endpos; int startpos, endpos;
/* This algorithm shifts links around instead of consing and GCing. /* This algorithm shifts links around instead of consing and GCing.
The loop invariant is that before_list (resp. after_list) is a The loop invariant is that before_list (resp. after_list) is a
well-formed list except that its last element, the one that well-formed list except that its last element, the CDR of beforep
*pbefore (resp. *pafter) points to, is still uninitialized. (resp. afterp) if beforep (afterp) isn't nil or before_list
So it's not a bug that before_list isn't initialized, although (after_list) if it is, is still uninitialized. So it's not a bug
it may look strange. */ that before_list isn't initialized, although it may look
for (ptail = &current_buffer->overlays_before; CONSP (*ptail);) strange. */
for (parent = Qnil, tail = current_buffer->overlays_before; CONSP (tail);)
{ {
overlay = XCAR (*ptail); overlay = XCAR (tail);
endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
if (endpos < start) if (endpos < start)
break; break;
...@@ -3261,22 +3269,32 @@ fix_overlays_in_range (start, end) ...@@ -3261,22 +3269,32 @@ fix_overlays_in_range (start, end)
recenter_overlay_lists will move it to the right place. */ recenter_overlay_lists will move it to the right place. */
if (endpos < XINT (current_buffer->overlay_center)) if (endpos < XINT (current_buffer->overlay_center))
{ {
*pafter = *ptail; if (NILP (afterp))
pafter = &XCDR (*ptail); after_list = tail;
else
XSETCDR (afterp, tail);
afterp = tail;
} }
else else
{ {
*pbefore = *ptail; if (NILP (beforep))
pbefore = &XCDR (*ptail); before_list = tail;
else
XSETCDR (beforep, tail);
beforep = tail;
} }
*ptail = XCDR (*ptail); if (NILP (parent))
current_buffer->overlays_before = XCDR (tail);
else
XSETCDR (parent, XCDR (tail));
tail = XCDR (tail);
} }
else else
ptail = &XCDR (*ptail); parent = tail, tail = XCDR (parent);
} }
for (ptail = &current_buffer->overlays_after; CONSP (*ptail);) for (parent = Qnil, tail = current_buffer->overlays_after; CONSP (tail);)
{ {
overlay = XCAR (*ptail); overlay = XCAR (tail);
startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
if (startpos >= end) if (startpos >= end)
break; break;
...@@ -3295,29 +3313,45 @@ fix_overlays_in_range (start, end) ...@@ -3295,29 +3313,45 @@ fix_overlays_in_range (start, end)
} }
if (endpos < XINT (current_buffer->overlay_center)) if (endpos < XINT (current_buffer->overlay_center))
{ {
*pafter = *ptail; if (NILP (afterp))
pafter = &XCDR (*ptail); after_list = tail;
else
XSETCDR (afterp, tail);
afterp = tail;
} }
else else
{ {
*pbefore = *ptail; if (NILP (beforep))
pbefore = &XCDR (*ptail); before_list = tail;
else
XSETCDR (beforep, tail);
beforep = tail;
} }
*ptail = XCDR (*ptail); if (NILP (parent))
current_buffer->overlays_after = XCDR (tail);
else
XSETCDR (parent, XCDR (tail));
tail = XCDR (tail);
} }
else else
ptail = &XCDR (*ptail); parent = tail, tail = XCDR (parent);
} }
/* Splice the constructed (wrong) lists into the buffer's lists, /* Splice the constructed (wrong) lists into the buffer's lists,
and let the recenter function make it sane again. */ and let the recenter function make it sane again. */
*pbefore = current_buffer->overlays_before; if (!NILP (beforep))
current_buffer->overlays_before = before_list; {
XSETCDR (beforep, current_buffer->overlays_before);
current_buffer->overlays_before = before_list;
}
recenter_overlay_lists (current_buffer, recenter_overlay_lists (current_buffer,
XINT (current_buffer->overlay_center)); XINT (current_buffer->overlay_center));
*pafter = current_buffer->overlays_after; if (!NILP (afterp))
current_buffer->overlays_after = after_list; {
XSETCDR (afterp, current_buffer->overlays_after);
current_buffer->overlays_after = after_list;
}
recenter_overlay_lists (current_buffer, recenter_overlay_lists (current_buffer,
XINT (current_buffer->overlay_center)); XINT (current_buffer->overlay_center));
} }
...@@ -3339,8 +3373,9 @@ fix_overlays_before (bp, prev, pos) ...@@ -3339,8 +3373,9 @@ fix_overlays_before (bp, prev, pos)
struct buffer *bp; struct buffer *bp;
int prev, pos; int prev, pos;
{ {
Lisp_Object *tailp = &bp->overlays_before; /* If parent is nil, replace overlays_before; otherwise, XCDR(parent). */
Lisp_Object *right_place; Lisp_Object tail = bp->overlays_before, parent = Qnil;
Lisp_Object right_pair;
int end; int end;
/* After the insertion, the several overlays may be in incorrect /* After the insertion, the several overlays may be in incorrect
...@@ -3354,45 +3389,60 @@ fix_overlays_before (bp, prev, pos) ...@@ -3354,45 +3389,60 @@ fix_overlays_before (bp, prev, pos)
in. It is where an overlay which end before POS exists. (i.e. an in. It is where an overlay which end before POS exists. (i.e. an
overlay whose ending marker is after-insertion-marker if disorder overlay whose ending marker is after-insertion-marker if disorder
exists). */ exists). */
while (!NILP (*tailp) while (!NILP (tail)
&& ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (*tailp)))) && ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail))))
>= pos)) >= pos))
tailp = &XCDR (*tailp); {
parent = tail;
tail = XCDR (tail);
}
/* If we don't find such an overlay, /* If we don't find such an overlay,
or the found one ends before PREV, or the found one ends before PREV,
or the found one is the last one in the list, or the found one is the last one in the list,
we don't have to fix anything. */ we don't have to fix anything. */
if (NILP (*tailp) if (NILP (tail)
|| end < prev || end < prev
|| NILP (XCDR (*tailp))) || NILP (XCDR (tail)))
return; return;
right_place = tailp; right_pair = parent;
tailp = &XCDR (*tailp); parent = tail;
tail = XCDR (tail);
/* Now, end position of overlays in the list *TAILP should be before /* Now, end position of overlays in the list TAIL should be before
or equal to PREV. In the loop, an overlay which ends at POS is or equal to PREV. In the loop, an overlay which ends at POS is
moved ahead to the place pointed by RIGHT_PLACE. If we found an moved ahead to the place indicated by the CDR of RIGHT_PAIR. If
overlay which ends before PREV, the remaining overlays are in we found an overlay which ends before PREV, the remaining
correct order. */ overlays are in correct order. */
while (!NILP (*tailp)) while (!NILP (tail))
{ {
end = OVERLAY_POSITION (OVERLAY_END (XCAR (*tailp))); end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail)));
if (end == pos) if (end == pos)
{ /* This overlay is disordered. */ { /* This overlay is disordered. */
Lisp_Object found = *tailp; Lisp_Object found = tail;
/* Unlink the found overlay. */ /* Unlink the found overlay. */
*tailp = XCDR (found); XSETCDR (parent, XCDR (found));
/* Move an overlay at RIGHT_PLACE to the next of the found one. */ /* Move an overlay at RIGHT_PLACE to the next of the found one,
XCDR (found) = *right_place; and link it into the right place. */
/* Link it into the right place. */ if (NILP (right_pair))
*right_place = found; {
XSETCDR (found, bp->overlays_before);
bp->overlays_before = found;
}
else
{
XSETCDR (found, XCDR (right_pair));
XSETCDR (right_pair, found);
}
} }
else if (end == prev) else if (end == prev)
tailp = &XCDR (*tailp); {
parent = tail;
tail = XCDR (tail);
}
else /* No more disordered overlay. */ else /* No more disordered overlay. */
break; break;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment