+ noverlays = j;
+
+ /* Sort the overlays into the proper order: increasing priority. */
+
+ if (noverlays > 1)
+ qsort (sortvec, noverlays, sizeof (struct sortvec), compare_overlays);
+
+ for (i = 0; i < noverlays; i++)
+ overlay_vec[i] = sortvec[i].overlay;
+ return (noverlays);
+}
+\f
+/* Shift overlays in BUF's overlay lists, to center the lists at POS. */
+
+void
+recenter_overlay_lists (buf, pos)
+ struct buffer *buf;
+ int pos;
+{
+ Lisp_Object overlay, tail, next, prev, beg, end;
+
+ /* See if anything in overlays_before should move to overlays_after. */
+
+ /* We don't strictly need prev in this loop; it should always be nil.
+ But we use it for symmetry and in case that should cease to be true
+ with some future change. */
+ prev = Qnil;
+ for (tail = buf->overlays_before;
+ CONSP (tail);
+ prev = tail, tail = next)
+ {
+ next = XCONS (tail)->cdr;
+ overlay = XCONS (tail)->car;
+
+ /* If the overlay is not valid, get rid of it. */
+ if (!OVERLAY_VALID (overlay))
+#if 1
+ abort ();
+#else
+ {
+ /* Splice the cons cell TAIL out of overlays_before. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_before = next;
+ tail = prev;
+ continue;
+ }
+#endif
+
+ beg = OVERLAY_START (overlay);
+ end = OVERLAY_END (overlay);
+
+ if (OVERLAY_POSITION (end) > pos)
+ {
+ /* OVERLAY needs to be moved. */
+ int where = OVERLAY_POSITION (beg);
+ Lisp_Object other, other_prev;
+
+ /* Splice the cons cell TAIL out of overlays_before. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_before = next;
+
+ /* Search thru overlays_after for where to put it. */
+ other_prev = Qnil;
+ for (other = buf->overlays_after;
+ CONSP (other);
+ other_prev = other, other = XCONS (other)->cdr)
+ {
+ Lisp_Object otherbeg, otheroverlay, follower;
+ int win;
+
+ otheroverlay = XCONS (other)->car;
+ if (! OVERLAY_VALID (otheroverlay))
+ abort ();
+
+ otherbeg = OVERLAY_START (otheroverlay);
+ if (OVERLAY_POSITION (otherbeg) >= where)
+ break;
+ }
+
+ /* Add TAIL to overlays_after before OTHER. */
+ XCONS (tail)->cdr = other;
+ if (!NILP (other_prev))
+ XCONS (other_prev)->cdr = tail;
+ else
+ buf->overlays_after = tail;
+ tail = prev;
+ }
+ else
+ /* We've reached the things that should stay in overlays_before.
+ All the rest of overlays_before must end even earlier,
+ so stop now. */
+ break;
+ }
+
+ /* See if anything in overlays_after should be in overlays_before. */
+ prev = Qnil;
+ for (tail = buf->overlays_after;
+ CONSP (tail);
+ prev = tail, tail = next)
+ {
+ next = XCONS (tail)->cdr;
+ overlay = XCONS (tail)->car;
+
+ /* If the overlay is not valid, get rid of it. */
+ if (!OVERLAY_VALID (overlay))
+#if 1
+ abort ();
+#else
+ {
+ /* Splice the cons cell TAIL out of overlays_after. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_after = next;
+ tail = prev;
+ continue;
+ }
+#endif
+
+ beg = OVERLAY_START (overlay);
+ end = OVERLAY_END (overlay);
+
+ /* Stop looking, when we know that nothing further
+ can possibly end before POS. */
+ if (OVERLAY_POSITION (beg) > pos)
+ break;
+
+ if (OVERLAY_POSITION (end) <= pos)
+ {
+ /* OVERLAY needs to be moved. */
+ int where = OVERLAY_POSITION (end);
+ Lisp_Object other, other_prev;
+
+ /* Splice the cons cell TAIL out of overlays_after. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_after = next;
+
+ /* Search thru overlays_before for where to put it. */
+ other_prev = Qnil;
+ for (other = buf->overlays_before;
+ CONSP (other);
+ other_prev = other, other = XCONS (other)->cdr)
+ {
+ Lisp_Object otherend, otheroverlay;
+ int win;
+
+ otheroverlay = XCONS (other)->car;
+ if (! OVERLAY_VALID (otheroverlay))
+ abort ();
+
+ otherend = OVERLAY_END (otheroverlay);
+ if (OVERLAY_POSITION (otherend) <= where)
+ break;
+ }
+
+ /* Add TAIL to overlays_before before OTHER. */
+ XCONS (tail)->cdr = other;
+ if (!NILP (other_prev))
+ XCONS (other_prev)->cdr = tail;
+ else
+ buf->overlays_before = tail;
+ tail = prev;
+ }
+ }
+
+ XFASTINT (buf->overlay_center) = pos;
+}
+\f
+DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
+ "Return t if OBJECT is an overlay.")
+ (object)
+ Lisp_Object object;
+{
+ return (OVERLAYP (object) ? Qt : Qnil);
+}
+
+DEFUN ("make-overlay", Fmake_overlay, Smake_overlay, 2, 3, 0,
+ "Create a new overlay with range BEG to END in BUFFER.\n\
+If omitted, BUFFER defaults to the current buffer.\n\
+BEG and END may be integers or markers.")
+ (beg, end, buffer)
+ Lisp_Object beg, end, buffer;
+{
+ Lisp_Object overlay;
+ struct buffer *b;
+
+ if (NILP (buffer))
+ XSET (buffer, Lisp_Buffer, current_buffer);
+ else
+ CHECK_BUFFER (buffer, 2);
+ if (MARKERP (beg)
+ && ! EQ (Fmarker_buffer (beg), buffer))
+ error ("Marker points into wrong buffer");
+ if (MARKERP (end)
+ && ! EQ (Fmarker_buffer (end), buffer))
+ error ("Marker points into wrong buffer");
+
+ CHECK_NUMBER_COERCE_MARKER (beg, 1);
+ CHECK_NUMBER_COERCE_MARKER (end, 1);
+
+ if (XINT (beg) > XINT (end))
+ {
+ Lisp_Object temp = beg;
+ beg = end; end = temp;
+ }
+
+ b = XBUFFER (buffer);
+
+ beg = Fset_marker (Fmake_marker (), beg, buffer);
+ end = Fset_marker (Fmake_marker (), end, buffer);
+
+ overlay = Fcons (Fcons (beg, end), Qnil);
+ XSETTYPE (overlay, Lisp_Overlay);
+
+ /* Put the new overlay on the wrong list. */
+ end = OVERLAY_END (overlay);
+ if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
+ b->overlays_after = Fcons (overlay, b->overlays_after);
+ else
+ b->overlays_before = Fcons (overlay, b->overlays_before);
+
+ /* This puts it in the right list, and in the right order. */
+ recenter_overlay_lists (b, XINT (b->overlay_center));
+
+ /* We don't need to redisplay the region covered by the overlay, because
+ the overlay has no properties at the moment. */
+
+ return overlay;
+}
+
+DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0,
+ "Set the endpoints of OVERLAY to BEG and END in BUFFER.\n\
+If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.\n\
+If BUFFER is omitted, and OVERLAY is in no buffer, put it in the current\n\
+buffer.")
+ (overlay, beg, end, buffer)
+ Lisp_Object overlay, beg, end, buffer;
+{
+ struct buffer *b, *ob;
+ Lisp_Object obuffer;
+ int count = specpdl_ptr - specpdl;
+
+ CHECK_OVERLAY (overlay, 0);
+ if (NILP (buffer))
+ buffer = Fmarker_buffer (OVERLAY_START (overlay));
+ if (NILP (buffer))
+ XSET (buffer, Lisp_Buffer, current_buffer);
+ CHECK_BUFFER (buffer, 3);
+
+ if (MARKERP (beg)
+ && ! EQ (Fmarker_buffer (beg), buffer))
+ error ("Marker points into wrong buffer");
+ if (MARKERP (end)
+ && ! EQ (Fmarker_buffer (end), buffer))
+ error ("Marker points into wrong buffer");
+
+ CHECK_NUMBER_COERCE_MARKER (beg, 1);
+ CHECK_NUMBER_COERCE_MARKER (end, 1);
+
+ specbind (Qinhibit_quit, Qt);
+
+ if (XINT (beg) > XINT (end))
+ {
+ Lisp_Object temp = beg;
+ beg = end; end = temp;
+ }
+
+ obuffer = Fmarker_buffer (OVERLAY_START (overlay));
+ b = XBUFFER (buffer);
+ ob = XBUFFER (obuffer);
+
+ /* If the overlay has changed buffers, do a thorough redisplay. */
+ if (!EQ (buffer, obuffer))
+ windows_or_buffers_changed = 1;
+ else
+ /* Redisplay the area the overlay has just left, or just enclosed. */
+ {
+ Lisp_Object o_beg;
+ Lisp_Object o_end;
+ int change_beg, change_end;
+
+ o_beg = OVERLAY_START (overlay);
+ o_end = OVERLAY_END (overlay);
+ o_beg = OVERLAY_POSITION (o_beg);
+ o_end = OVERLAY_POSITION (o_end);
+
+ if (XINT (o_beg) == XINT (beg))
+ redisplay_region (b, XINT (o_end), XINT (end));
+ else if (XINT (o_end) == XINT (end))
+ redisplay_region (b, XINT (o_beg), XINT (beg));
+ else
+ {
+ if (XINT (beg) < XINT (o_beg)) o_beg = beg;
+ if (XINT (end) > XINT (o_end)) o_end = end;
+ redisplay_region (b, XINT (o_beg), XINT (o_end));
+ }
+ }
+
+ if (!NILP (obuffer))
+ {
+ ob->overlays_before = Fdelq (overlay, ob->overlays_before);
+ ob->overlays_after = Fdelq (overlay, ob->overlays_after);
+ }
+
+ Fset_marker (OVERLAY_START (overlay), beg, buffer);
+ Fset_marker (OVERLAY_END (overlay), end, buffer);
+
+ /* Put the overlay on the wrong list. */
+ end = OVERLAY_END (overlay);
+ if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
+ b->overlays_after = Fcons (overlay, b->overlays_after);
+ else
+ b->overlays_before = Fcons (overlay, b->overlays_before);
+
+ /* This puts it in the right list, and in the right order. */
+ recenter_overlay_lists (b, XINT (b->overlay_center));
+
+ return unbind_to (count, overlay);
+}
+
+DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
+ "Delete the overlay OVERLAY from its buffer.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ Lisp_Object buffer;
+ struct buffer *b;
+ int count = specpdl_ptr - specpdl;
+
+ CHECK_OVERLAY (overlay, 0);
+
+ buffer = Fmarker_buffer (OVERLAY_START (overlay));
+ if (NILP (buffer))
+ return Qnil;
+
+ b = XBUFFER (buffer);
+
+ specbind (Qinhibit_quit, Qt);
+
+ b->overlays_before = Fdelq (overlay, b->overlays_before);
+ b->overlays_after = Fdelq (overlay, b->overlays_after);
+
+ redisplay_region (b,
+ marker_position (OVERLAY_START (overlay)),
+ marker_position (OVERLAY_END (overlay)));
+
+ Fset_marker (OVERLAY_START (overlay), Qnil, Qnil);
+ Fset_marker (OVERLAY_END (overlay), Qnil, Qnil);
+
+ return unbind_to (count, Qnil);
+}
+\f
+/* Overlay dissection functions. */
+
+DEFUN ("overlay-start", Foverlay_start, Soverlay_start, 1, 1, 0,
+ "Return the position at which OVERLAY starts.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return (Fmarker_position (OVERLAY_START (overlay)));
+}
+
+DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
+ "Return the position at which OVERLAY ends.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return (Fmarker_position (OVERLAY_END (overlay)));
+}
+
+DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
+ "Return the buffer OVERLAY belongs to.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return Fmarker_buffer (OVERLAY_START (overlay));
+}
+
+DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0,
+ "Return a list of the properties on OVERLAY.\n\
+This is a copy of OVERLAY's plist; modifying its conses has no effect on\n\
+OVERLAY.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return Fcopy_sequence (Fcdr_safe (XCONS (overlay)->cdr));
+}
+
+\f
+DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
+ "Return a list of the overlays that contain position POS.")
+ (pos)
+ Lisp_Object pos;
+{
+ int noverlays;
+ int endpos;
+ Lisp_Object *overlay_vec;
+ int len;
+ Lisp_Object result;
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ len = 10;
+ overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
+
+ /* Put all the overlays we want in a vector in overlay_vec.
+ Store the length in len. */
+ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &endpos);
+
+ /* Make a list of them all. */
+ result = Flist (noverlays, overlay_vec);
+
+ xfree (overlay_vec);
+ return result;
+}
+
+DEFUN ("next-overlay-change", Fnext_overlay_change, Snext_overlay_change,
+ 1, 1, 0,
+ "Return the next position after POS where an overlay starts or ends.")
+ (pos)
+ Lisp_Object pos;
+{
+ int noverlays;
+ int endpos;
+ Lisp_Object *overlay_vec;
+ int len;
+ Lisp_Object result;
+ int i;
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ len = 10;
+ overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
+
+ /* Put all the overlays we want in a vector in overlay_vec.
+ Store the length in len.
+ endpos gets the position where the next overlay starts. */
+ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &endpos);
+
+ /* If any of these overlays ends before endpos,
+ use its ending point instead. */
+ for (i = 0; i < noverlays; i++)
+ {
+ Lisp_Object oend;
+ int oendpos;
+
+ oend = OVERLAY_END (overlay_vec[i]);
+ oendpos = OVERLAY_POSITION (oend);
+ if (oendpos < endpos)
+ endpos = oendpos;
+ }
+
+ xfree (overlay_vec);
+ return make_number (endpos);
+}
+\f
+/* These functions are for debugging overlays. */
+
+DEFUN ("overlay-lists", Foverlay_lists, Soverlay_lists, 0, 0, 0,
+ "Return a pair of lists giving all the overlays of the current buffer.\n\
+The car has all the overlays before the overlay center;\n\
+the cdr has all the overlays before the overlay center.\n\
+Recentering overlays moves overlays between these lists.\n\
+The lists you get are copies, so that changing them has no effect.\n\
+However, the overlays you get are the real objects that the buffer uses.")
+ ()
+{
+ Lisp_Object before, after;
+ before = current_buffer->overlays_before;
+ if (CONSP (before))
+ before = Fcopy_sequence (before);
+ after = current_buffer->overlays_after;
+ if (CONSP (after))
+ after = Fcopy_sequence (after);
+
+ return Fcons (before, after);
+}
+
+DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
+ "Recenter the overlays of the current buffer around position POS.")
+ (pos)
+ Lisp_Object pos;
+{
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ recenter_overlay_lists (current_buffer, XINT (pos));
+ return Qnil;
+}
+\f
+DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0,
+ "Get the property of overlay OVERLAY with property name NAME.")
+ (overlay, prop)
+ Lisp_Object overlay, prop;
+{
+ Lisp_Object plist;
+
+ CHECK_OVERLAY (overlay, 0);
+
+ for (plist = Fcdr_safe (XCONS (overlay)->cdr);
+ CONSP (plist) && CONSP (XCONS (plist)->cdr);
+ plist = XCONS (XCONS (plist)->cdr)->cdr)
+ {
+ if (EQ (XCONS (plist)->car, prop))
+ return XCONS (XCONS (plist)->cdr)->car;
+ }
+
+ return Qnil;
+}
+
+DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
+ "Set one property of overlay OVERLAY: give property PROP value VALUE.")
+ (overlay, prop, value)
+ Lisp_Object overlay, prop, value;
+{
+ Lisp_Object plist, tail;
+
+ CHECK_OVERLAY (overlay, 0);
+
+ tail = Fmarker_buffer (OVERLAY_START (overlay));
+ if (! NILP (tail))
+ redisplay_region (XMARKER (OVERLAY_START (overlay))->buffer,
+ marker_position (OVERLAY_START (overlay)),
+ marker_position (OVERLAY_END (overlay)));
+
+ plist = Fcdr_safe (XCONS (overlay)->cdr);
+
+ for (tail = plist;
+ CONSP (tail) && CONSP (XCONS (tail)->cdr);
+ tail = XCONS (XCONS (tail)->cdr)->cdr)
+ {
+ if (EQ (XCONS (tail)->car, prop))
+ return XCONS (XCONS (tail)->cdr)->car = value;
+ }
+
+ if (! CONSP (XCONS (overlay)->cdr))
+ XCONS (overlay)->cdr = Fcons (Qnil, Qnil);
+
+ XCONS (XCONS (overlay)->cdr)->cdr
+ = Fcons (prop, Fcons (value, plist));