* buffer.c (Fmove_overlay): If the overlay is in no buffer and the
[bpt/emacs.git] / src / buffer.c
index 6617ee9..2104226 100644 (file)
@@ -36,6 +36,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "buffer.h"
 #include "syntax.h"
 #include "indent.h"
+#include "blockinput.h"
 
 struct buffer *current_buffer;         /* the current buffer */
 
@@ -97,10 +98,6 @@ static Lisp_Object Vbuffer_local_symbols;
    buffer_slot_type_mismatch will signal an error.  */
 struct buffer buffer_local_types;
 
-/* Nonzero means don't allow modification of protected fields.  */
-
-int check_protected_fields;
-
 Lisp_Object Fset_buffer ();
 void set_buffer_internal ();
 
@@ -113,6 +110,8 @@ Lisp_Object Vbuffer_alist;
 Lisp_Object Vbefore_change_function;
 Lisp_Object Vafter_change_function;
 
+Lisp_Object Vtransient_mark_mode;
+
 /* List of functions to call before changing an unmodified buffer.  */
 Lisp_Object Vfirst_change_hook;
 Lisp_Object Qfirst_change_hook;
@@ -125,6 +124,8 @@ Lisp_Object QSFundamental;  /* A string "Fundamental" */
 
 Lisp_Object Qkill_buffer_hook;
 
+Lisp_Object Qoverlayp;
+
 /* For debugging; temporary.  See set_buffer_internal.  */
 /* Lisp_Object Qlisp_mode, Vcheck_symbol; */
 
@@ -199,12 +200,12 @@ The value is never nil.")
   if (!NILP (buf))
     return buf;
 
-  b = (struct buffer *) malloc (sizeof (struct buffer));
-  if (!b)
-    memory_full ();
+  b = (struct buffer *) xmalloc (sizeof (struct buffer));
 
   BUF_GAP_SIZE (b) = 20;
+  BLOCK_INPUT;
   BUFFER_ALLOC (BUF_BEG_ADDR (b), BUF_GAP_SIZE (b));
+  UNBLOCK_INPUT;
   if (! BUF_BEG_ADDR (b))
     memory_full ();
 
@@ -275,7 +276,9 @@ reset_buffer (b)
   b->auto_save_modified = 0;
   b->auto_save_file_name = Qnil;
   b->read_only = Qnil;
-  b->fieldlist = Qnil;
+  b->overlays_before = Qnil;
+  b->overlays_after = Qnil;
+  XFASTINT (b->overlay_center) = 1;
 
   /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
   INITIALIZE_INTERVAL (b, NULL_INTERVAL);
@@ -283,7 +286,7 @@ reset_buffer (b)
   reset_buffer_local_variables(b);
 }
 
-reset_buffer_local_variables(b)
+reset_buffer_local_variables (b)
      register struct buffer *b;
 {
   register int offset;
@@ -301,6 +304,7 @@ reset_buffer_local_variables(b)
   b->upcase_table = Vascii_upcase_table;
   b->case_canon_table = Vascii_downcase_table;
   b->case_eqv_table = Vascii_upcase_table;
+  b->mark_active = Qnil;
 #if 0
   b->sort_table = XSTRING (Vascii_sort_table);
   b->folding_sort_table = XSTRING (Vascii_folding_sort_table);
@@ -749,7 +753,9 @@ with `delete-process'.")
   /* Perhaps we should explicitly free the interval tree here... */
 
   b->name = Qnil;
+  BLOCK_INPUT;
   BUFFER_FREE (BUF_BEG_ADDR (b));
+  UNBLOCK_INPUT;
   b->undo_list = Qnil;
 
   return Qt;
@@ -1145,8 +1151,16 @@ a non-nil `permanent-local' property are not eliminated by this function.")
             Set it up for the current buffer with the default value.  */
 
          tem = XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->cdr;
+         /* Store the symbol's current value into the alist entry
+            it is currently set up for.  This is so that, if the
+            local is marked permanent, and we make it local again below,
+            we don't lose the value.  */
+         XCONS (XCONS (tem)->car)->cdr = XCONS (XSYMBOL (sym)->value)->car;
+         /* Switch to the symbol's default-value alist entry.  */
          XCONS (tem)->car = tem;
+         /* Mark it as current for the current buffer.  */
          XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->car = Fcurrent_buffer ();
+         /* Store the current value into any forwarding in the symbol.  */
          store_symval_forwarding (sym, XCONS (XSYMBOL (sym)->value)->car,
                                   XCONS (tem)->cdr);
        }
@@ -1181,65 +1195,601 @@ a non-nil `permanent-local' property are not eliminated by this function.")
   return Qnil;
 }
 \f
-DEFUN ("region-fields", Fregion_fields, Sregion_fields, 2, 4, "", 
-  "Return list of fields overlapping a given portion of a buffer.\n\
-The portion is specified by arguments START, END and BUFFER.\n\
-BUFFER defaults to the current buffer.\n\
-Optional 4th arg ERROR-CHECK non nil means just report an error\n\
-if any protected fields overlap this portion.")
-  (start, end, buffer, error_check)
-     Lisp_Object start, end, buffer, error_check;
+/* Find all the overlays in the current buffer that contain position POS.
+   Return the number found, and store them in a vector in *VEC_PTR.  
+   Store in *LEN_PTR the size allocated for the vector.
+   Store in *NEXT_PTR the next position after POS where an overlay starts,
+     or ZV if there are no more overlays.
+
+   *VEC_PTR and *LEN_PTR should contain a valid vector and size
+   when this function is called.  */
+
+int
+overlays_at (pos, vec_ptr, len_ptr, next_ptr)
+     int pos;
+     Lisp_Object **vec_ptr;
+     int *len_ptr;
+     int *next_ptr;
 {
-  register int start_loc, end_loc;
-  Lisp_Object fieldlist;
-  Lisp_Object collector;
+  Lisp_Object tail, overlay, start, end, result;
+  int idx = 0;
+  int len = *len_ptr;
+  Lisp_Object *vec = *vec_ptr;
+  int next = ZV;
+  for (tail = current_buffer->overlays_before;
+       CONSP (tail);
+       tail = XCONS (tail)->cdr)
+    {
+      int startpos;
 
-  if (NILP (buffer))
-    fieldlist = current_buffer->fieldlist;
-  else
+      overlay = XCONS (tail)->car;
+      if (! OVERLAY_VALID (overlay))
+       abort ();
+
+      start = OVERLAY_START (overlay);
+      end = OVERLAY_END (overlay);
+      if (OVERLAY_POSITION (end) <= pos)
+       break;
+      startpos = OVERLAY_POSITION (start);
+      if (startpos <= pos)
+       {
+         if (idx == len)
+           {
+             *len_ptr = len *= 2;
+             vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
+             *vec_ptr = vec;
+           }
+         vec[idx++] = overlay;
+       }
+      else if (startpos < next)
+       next = startpos;
+    }
+
+  for (tail = current_buffer->overlays_after;
+       CONSP (tail);
+       tail = XCONS (tail)->cdr)
     {
-      CHECK_BUFFER (buffer, 1);
-      fieldlist = XBUFFER (buffer)->fieldlist;
+      int startpos;
+
+      overlay = XCONS (tail)->car;
+      if (! OVERLAY_VALID (overlay))
+       abort ();
+
+      start = OVERLAY_START (overlay);
+      end = OVERLAY_END (overlay);
+      startpos = OVERLAY_POSITION (start);
+      if (pos < startpos)
+       {
+         if (startpos < next)
+           next = startpos;
+         break;
+       }
+      if (pos < OVERLAY_POSITION (end))
+       {
+         if (idx == len)
+           {
+             *len_ptr = len *= 2;
+             vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
+             *vec_ptr = vec;
+           }
+         vec[idx++] = overlay;
+       }
     }
 
-  CHECK_NUMBER_COERCE_MARKER (start, 2);
-  start_loc = XINT (start);
+  *next_ptr = next;
+  return idx;
+}
+\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;
 
-  CHECK_NUMBER_COERCE_MARKER (end, 2);
-  end_loc = XINT (end);
-  
-  collector = Qnil;
-  
-  while (XTYPE (fieldlist) == Lisp_Cons)
+  /* 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)
     {
-      register Lisp_Object field;
-      register int field_start, field_end;
+      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
 
-      field = XCONS (fieldlist)->car;
-      field_start = marker_position (FIELD_START_MARKER (field)) - 1;
-      field_end = marker_position (FIELD_END_MARKER (field));
+      beg = OVERLAY_START (overlay);
+      end = OVERLAY_END (overlay);
 
-      if ((start_loc < field_start && end_loc > field_start)
-         || (start_loc >= field_start && start_loc < field_end))
+      if (OVERLAY_POSITION (end) > pos)
        {
-         if (!NILP (error_check))
+         /* 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)
            {
-             if (!NILP (FIELD_PROTECTED_FLAG (field)))
-               {
-                 struct gcpro gcpro1;
-                 GCPRO1 (fieldlist);
-                 Fsignal (Qprotected_field, Fcons (field, Qnil));
-                 UNGCPRO;
-               }
+             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
-           collector = Fcons (field, collector);
+           buf->overlays_after = tail;
+         tail = prev;
        }
-      
-      fieldlist = XCONS (fieldlist)->cdr;
+      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;
     }
 
-  return collector;
+  /* 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);
+  CHECK_BUFFER (buffer, 2);
+
+  b = XBUFFER (buffer);
+
+  if (MARKERP (beg))
+    {
+      if (! EQ (Fmarker_buffer (beg), buffer))
+       error ("Marker points into wrong buffer");
+      else
+       beg = Fcopy_marker (beg);
+    }
+  else
+    beg = Fset_marker (Fmake_marker (), beg, buffer);
+  if (MARKERP (end))
+    {
+      if (! EQ (Fmarker_buffer (end), buffer))
+       error ("Marker points into wrong buffer");
+      else
+       end = Fcopy_marker (end);
+    }
+  else
+    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;
+
+  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);
+  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);
+
+  /* Redisplay the area the overlay has just left, or just enclosed.  */
+  {
+    Lisp_Object o_beg = OVERLAY_START (overlay);
+    Lisp_Object o_end = OVERLAY_END   (overlay);
+    int change_beg, change_end;
+
+    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));
+      }
+  }
+
+  b->overlays_before = Fdelq (overlay, b->overlays_before);
+  b->overlays_after  = Fdelq (overlay, b->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 overlay;
+}
+
+DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
+  "Delete the overlay OVERLAY from its buffer.")
+  (overlay)
+     Lisp_Object overlay;
+{
+  struct buffer *b;
+
+  CHECK_OVERLAY (overlay, 0);
+
+  b = XBUFFER (Fmarker_buffer (OVERLAY_START (overlay)));
+
+  b->overlays_before = Fdelq (overlay, b->overlays_before);
+  b->overlays_after  = Fdelq (overlay, b->overlays_after);
+
+  redisplay_region (b,
+                   OVERLAY_POSITION (OVERLAY_START (overlay)),
+                   OVERLAY_POSITION (OVERLAY_END   (overlay)));
+
+  Fset_marker (OVERLAY_START (overlay), Qnil, Qnil);
+  Fset_marker (OVERLAY_END   (overlay), Qnil, Qnil);
+
+  return 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 overays 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), &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), &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);
+
+  redisplay_region (XMARKER (OVERLAY_START (overlay))->buffer,
+                   OVERLAY_POSITION (OVERLAY_START (overlay)),
+                   OVERLAY_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));
+
+  return value;
 }
 \f
 /* Somebody has tried to store NEWVAL into the buffer-local slot with
@@ -1296,8 +1846,11 @@ init_buffer_once ()
 #endif
   buffer_defaults.abbrev_table = Qnil;
   buffer_defaults.display_table = Qnil;
-  buffer_defaults.fieldlist = Qnil;
   buffer_defaults.undo_list = Qnil;
+  buffer_defaults.mark_active = Qnil;
+  buffer_defaults.overlays_before = Qnil;
+  buffer_defaults.overlays_after = Qnil;
+  XFASTINT (buffer_defaults.overlay_center) = 1;
 
   XFASTINT (buffer_defaults.tab_width) = 8;
   buffer_defaults.truncate_lines = Qnil;
@@ -1325,6 +1878,7 @@ init_buffer_once ()
   XFASTINT (buffer_local_flags.major_mode) = -1;
   XFASTINT (buffer_local_flags.mode_name) = -1;
   XFASTINT (buffer_local_flags.undo_list) = -1;
+  XFASTINT (buffer_local_flags.mark_active) = -1;
 
   XFASTINT (buffer_local_flags.mode_line_format) = 1;
   XFASTINT (buffer_local_flags.abbrev_mode) = 2;
@@ -1342,7 +1896,6 @@ init_buffer_once ()
   XFASTINT (buffer_local_flags.left_margin) = 0x800;
   XFASTINT (buffer_local_flags.abbrev_table) = 0x1000;
   XFASTINT (buffer_local_flags.display_table) = 0x2000;
-  XFASTINT (buffer_local_flags.fieldlist) = 0x4000;
   XFASTINT (buffer_local_flags.syntax_table) = 0x8000;
 
   Vbuffer_alist = Qnil;
@@ -1401,6 +1954,8 @@ init_buffer ()
 /* initialize the buffer routines */
 syms_of_buffer ()
 {
+  extern Lisp_Object Qdisabled;
+
   staticpro (&Vbuffer_defaults);
   staticpro (&Vbuffer_local_symbols);
   staticpro (&Qfundamental_mode);
@@ -1410,12 +1965,17 @@ syms_of_buffer ()
   staticpro (&Qprotected_field);
   staticpro (&Qpermanent_local);
   staticpro (&Qkill_buffer_hook);
+  staticpro (&Qoverlayp);
+
+  Qoverlayp = intern ("overlayp");
 
   Fput (Qprotected_field, Qerror_conditions,
        Fcons (Qprotected_field, Fcons (Qerror, Qnil)));
   Fput (Qprotected_field, Qerror_message,
        build_string ("Attempt to modify a protected field"));
 
+  Fput (intern ("erase-buffer"), Qdisabled, Qt);
+
   /* All these use DEFVAR_LISP_NOPRO because the slots in
      buffer_defaults will all be marked via Vbuffer_defaults.  */
 
@@ -1465,6 +2025,7 @@ This is the same as (default-value 'case-fold-search).");
 /* This doc string is too long for cpp; cpp dies if it isn't in a comment.
    But make-docfile finds it!
   DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format,
+    Qnil,
     "Template for displaying mode line for current buffer.\n\
 Each buffer has its own value of this variable.\n\
 Value may be a string, a symbol or a list or cons cell.\n\
@@ -1484,7 +2045,7 @@ A string is printed verbatim in the mode line except for %-constructs:\n\
    or when it is found in a cons-cell or a list)\n\
   %b -- print buffer name.      %f -- print visited file name.\n\
   %* -- print *, % or hyphen.   %m -- print value of mode-name (obsolete).\n\
-  %s -- print process status.   %M -- print value of global-mode-string. (obs)\n\
+  %s -- print process status.   %l -- print the current line number.\n\
   %p -- print percent of buffer above top of window, or top, bot or all.\n\
   %n -- print Narrow if appropriate.\n\
   %[ -- print one [ for each recursive editing level.  %] similar.\n\
@@ -1604,6 +2165,10 @@ Automatically becomes buffer-local when set in any fashion.");
 
   DEFVAR_PER_BUFFER ("overwrite-mode", &current_buffer->overwrite_mode, Qnil,
     "Non-nil if self-insertion should replace existing text.\n\
+If non-nil and not `overwrite-mode-binary', self-insertion still\n\
+inserts at the end of a line, and inserts when point is before a tab,\n\
+until the tab is filled in.\n\
+If `overwrite-mode-binary', self-insertion replaces newlines and tabs too.\n\
 Automatically becomes buffer-local when set in any fashion.");
 
   DEFVAR_PER_BUFFER ("buffer-display-table", &current_buffer->display_table,
@@ -1612,25 +2177,20 @@ Automatically becomes buffer-local when set in any fashion.");
 Automatically becomes buffer-local when set in any fashion.\n\
 The display table is a vector created with `make-display-table'.\n\
 The first 256 elements control how to display each possible text character.\n\
-The value should be a \"rope\" (see `make-rope') or nil;\n\
+Each value should be a vector of characters or nil;\n\
 nil means display the character in the default fashion.\n\
-The remaining five elements are ropes that control the display of\n\
-  the end of a truncated screen line (element 256);\n\
-  the end of a continued line (element 257);\n\
-  the escape character used to display character codes in octal (element 258);\n\
-  the character used as an arrow for control characters (element 259);\n\
-  the decoration indicating the presence of invisible lines (element 260).\n\
+The remaining five elements control the display of\n\
+  the end of a truncated screen line (element 256, a single character);\n\
+  the end of a continued line (element 257, a single character);\n\
+  the escape character used to display character codes in octal\n\
+    (element 258, a single character);\n\
+  the character used as an arrow for control characters (element 259,\n\
+    a single character);\n\
+  the decoration indicating the presence of invisible lines (element 260,\n\
+    a vector of characters).\n\
 If this variable is nil, the value of `standard-display-table' is used.\n\
 Each window can have its own, overriding display table.");
 
-  DEFVAR_PER_BUFFER ("buffer-field-list", &current_buffer->fieldlist, Qnil,
-    "List of fields in the current buffer.  See `add-field'.");
-
-  DEFVAR_BOOL ("check-protected-fields", &check_protected_fields,
-    "Non-nil means don't allow modification of a protected field.\n\
-See `add-field'.");
-  check_protected_fields = 0;
-
 /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
     "Don't ask.");
 */
@@ -1687,11 +2247,22 @@ An entry (nil PROP VAL BEG . END) indicates that a text property\n\
 was modified between BEG and END.  PROP is the property name,\n\
 and VAL is the old value.\n\
 \n\
+An entry of the form POSITION indicates that point was at the buffer\n\
+location given by the integer.  Undoing an entry of this form places\n\
+point at POSITION.\n\
+\n\
 nil marks undo boundaries.  The undo command treats the changes\n\
 between two undo boundaries as a single step to be undone.\n\
 \n\
-If the value of the variable is t, undo information is not recorded.\n\
-");
+If the value of the variable is t, undo information is not recorded.");
+
+  DEFVAR_PER_BUFFER ("mark-active", &current_buffer->mark_active, Qnil, 
+    "Non-nil means the mark and region are currently active in this buffer.\n\
+Automatically local in all buffers.");
+
+  DEFVAR_LISP ("transient-mark-mode", &Vtransient_mark_mode,
+    "*Non-nil means deactivate the mark when the buffer contents change.");
+  Vtransient_mark_mode = Qnil;
 
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
@@ -1719,7 +2290,21 @@ If the value of the variable is t, undo information is not recorded.\n\
   defsubr (&Sbury_buffer);
   defsubr (&Slist_buffers);
   defsubr (&Skill_all_local_variables);
-  defsubr (&Sregion_fields);
+
+  defsubr (&Soverlayp);
+  defsubr (&Smake_overlay);
+  defsubr (&Sdelete_overlay);
+  defsubr (&Smove_overlay);
+  defsubr (&Soverlay_start);
+  defsubr (&Soverlay_end);
+  defsubr (&Soverlay_buffer);
+  defsubr (&Soverlay_properties);
+  defsubr (&Soverlays_at);
+  defsubr (&Snext_overlay_change);
+  defsubr (&Soverlay_recenter);
+  defsubr (&Soverlay_lists);
+  defsubr (&Soverlay_get);
+  defsubr (&Soverlay_put);
 }
 
 keys_of_buffer ()