]> code.delx.au - gnu-emacs/blobdiff - src/buffer.c
(verify_overlay_modification): New function.
[gnu-emacs] / src / buffer.c
index ddfab45d14868b400e0d409004b957790af5865b..ce07c2a21d3effab79e96c35aaf55c16ca7c22fd 100644 (file)
@@ -1,5 +1,5 @@
 /* Buffer manipulation primitives for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1992, 1993
+   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -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 */
 
@@ -99,6 +100,7 @@ struct buffer buffer_local_types;
 
 Lisp_Object Fset_buffer ();
 void set_buffer_internal ();
+static void call_overlay_mod_hooks ();
 
 /* Alist of all buffer names vs the buffers. */
 /* This used to be a variable, but is no longer,
@@ -111,6 +113,11 @@ Lisp_Object Vafter_change_function;
 
 Lisp_Object Vtransient_mark_mode;
 
+/* t means ignore all read-only text properties.
+   A list means ignore such a property if its value is a member of the list.
+   Any non-nil value means ignore buffer-read-only.  */
+Lisp_Object Vinhibit_read_only;
+
 /* List of functions to call before changing an unmodified buffer.  */
 Lisp_Object Vfirst_change_hook;
 Lisp_Object Qfirst_change_hook;
@@ -123,6 +130,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; */
 
@@ -276,6 +285,7 @@ reset_buffer (b)
   b->overlays_before = Qnil;
   b->overlays_after = Qnil;
   XFASTINT (b->overlay_center) = 1;
+  b->mark_active = Qnil;
 
   /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
   INITIALIZE_INTERVAL (b, NULL_INTERVAL);
@@ -301,7 +311,6 @@ 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);
@@ -328,13 +337,16 @@ reset_buffer_local_variables (b)
    rename the buffer properly.  */
 
 DEFUN ("generate-new-buffer-name", Fgenerate_new_buffer_name, Sgenerate_new_buffer_name,
-  1, 1, 0,
+  1, 2, 0,
   "Return a string that is the name of no existing buffer based on NAME.\n\
 If there is no live buffer named NAME, then return NAME.\n\
 Otherwise modify name by appending `<NUMBER>', incrementing NUMBER\n\
-until an unused name is found, and then return that name.")
- (name)
-     register Lisp_Object name;
+until an unused name is found, and then return that name.\n\
+Optional second argument IGNORE specifies a name that is okay to use\n\
+\(if it is in the sequence to be tried)\n\
+even if a buffer with that name exists.")
+ (name, ignore)
+     register Lisp_Object name, ignore;
 {
   register Lisp_Object gentemp, tem;
   int count;
@@ -351,6 +363,9 @@ until an unused name is found, and then return that name.")
     {
       sprintf (number, "<%d>", ++count);
       gentemp = concat2 (name, build_string (number));
+      tem = Fstring_equal (gentemp, ignore);
+      if (!NILP (tem))
+       return gentemp;
       tem = Fget_buffer (gentemp);
       if (NILP (tem))
        return gentemp;
@@ -533,7 +548,7 @@ This does not change the name of the visited file (if any).")
   if (!NILP (tem))
     {
       if (!NILP (unique))
-       name = Fgenerate_new_buffer_name (name);
+       name = Fgenerate_new_buffer_name (name, current_buffer->name);
       else
        error ("Buffer name \"%s\" is in use", XSTRING (name)->data);
     }
@@ -571,7 +586,7 @@ If BUFFER is omitted or nil, some interesting buffer is returned.")
       if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
        continue;
       if (NILP (visible_ok))
-       tem = Fget_buffer_window (buf, Qnil);
+       tem = Fget_buffer_window (buf, Qt);
       else
        tem = Qnil;
       if (NILP (tem))
@@ -822,7 +837,7 @@ the window-buffer correspondences.")
                      : selected_window,
                      buf);
 
-  return Qnil;
+  return buf;
 }
 
 DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 2, 0,
@@ -842,7 +857,7 @@ window even if BUFFER is already visible in the selected window.")
   Fset_buffer (buf);
   record_buffer (buf);
   Fselect_window (Fdisplay_buffer (buf, other));
-  return Qnil;
+  return buf;
 }
 
 DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
@@ -930,7 +945,8 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
   "Signal a `buffer-read-only' error if the current buffer is read-only.")
   ()
 {
-  while (!NILP (current_buffer->read_only))
+  if (!NILP (current_buffer->read_only)
+      && NILP (Vinhibit_read_only))
     Fsignal (Qbuffer_read_only, (Fcons (Fcurrent_buffer (), Qnil)));
   return Qnil;
 }
@@ -1020,9 +1036,10 @@ list_buffers_1 (files)
   register Lisp_Object tail, tem, buf;
   Lisp_Object col1, col2, col3, minspace;
   register struct buffer *old = current_buffer, *b;
-  int desired_point = 0;
+  Lisp_Object desired_point;
   Lisp_Object other_file_symbol;
 
+  desired_point = Qnil;
   other_file_symbol = intern ("list-buffers-directory");
 
   XFASTINT (col1) = 19;
@@ -1055,7 +1072,7 @@ list_buffers_1 (files)
        continue;
       /* Identify the current buffer. */
       if (b == old)
-       desired_point = point;
+       XFASTINT (desired_point) = point;
       write_string (b == old ? "." : " ", -1);
       /* Identify modified buffers */
       write_string (BUF_MODIFF (b) > b->save_modified ? "*" : " ", -1);
@@ -1091,11 +1108,7 @@ list_buffers_1 (files)
 
   current_buffer->read_only = Qt;
   set_buffer_internal (old);
-/* Foo.  This doesn't work since temp_output_buffer_show sets point to 1
-  if (desired_point)
-    XBUFFER (Vstandard_output)->text.pointloc = desired_point;
- */
-  return Qnil;
+  return desired_point;
 }
 
 DEFUN ("list-buffers", Flist_buffers, Slist_buffers, 0, 1, "P",
@@ -1109,9 +1122,20 @@ The R column contains a % for buffers that are read-only.")
   (files)
      Lisp_Object files;
 {
-  internal_with_output_to_temp_buffer ("*Buffer List*",
-                                      list_buffers_1, files);
-  return Qnil;
+  Lisp_Object desired_point;
+
+  desired_point =
+    internal_with_output_to_temp_buffer ("*Buffer List*",
+                                        list_buffers_1, files);
+
+  if (NUMBERP (desired_point))
+    {
+      int count = specpdl_ptr - specpdl;
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      Fset_buffer (build_string ("*Buffer List*"));
+      SET_PT (XINT (desired_point));
+      return unbind_to (count, Qnil);
+    }
 }
 
 DEFUN ("kill-all-local-variables", Fkill_all_local_variables, Skill_all_local_variables,
@@ -1148,8 +1172,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);
        }
@@ -1187,14 +1219,21 @@ a non-nil `permanent-local' property are not eliminated by this function.")
 /* 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.
+   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.  */
+   when this function is called.
+
+   If EXTEND is non-zero, we make the vector bigger if necessary.
+   If EXTEND is zero, we never extend the vector,
+   and we store only as many overlays as will fit.
+   But we still return the total number of overlays.  */
 
 int
-overlays_at (pos, vec_ptr, len_ptr, next_ptr)
+overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr)
      int pos;
+     int extend;
      Lisp_Object **vec_ptr;
      int *len_ptr;
      int *next_ptr;
@@ -1204,15 +1243,17 @@ overlays_at (pos, vec_ptr, len_ptr, next_ptr)
   int len = *len_ptr;
   Lisp_Object *vec = *vec_ptr;
   int next = ZV;
-  int startpos;
+  int inhibit_storing = 0;
 
   for (tail = current_buffer->overlays_before;
        CONSP (tail);
        tail = XCONS (tail)->cdr)
     {
+      int startpos;
+
       overlay = XCONS (tail)->car;
       if (! OVERLAY_VALID (overlay))
-       continue;
+       abort ();
 
       start = OVERLAY_START (overlay);
       end = OVERLAY_END (overlay);
@@ -1223,11 +1264,22 @@ overlays_at (pos, vec_ptr, len_ptr, next_ptr)
        {
          if (idx == len)
            {
-             *len_ptr = len *= 2;
-             vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
-             *vec_ptr = vec;
+             /* The supplied vector is full.
+                Either make it bigger, or don't store any more in it.  */
+             if (extend)
+               {
+                 *len_ptr = len *= 2;
+                 vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
+                 *vec_ptr = vec;
+               }
+             else
+               inhibit_storing = 1;
            }
-         vec[idx++] = overlay;
+
+         if (!inhibit_storing)
+           vec[idx] = overlay;
+         /* Keep counting overlays even if we can't return them all.  */
+         idx++;
        }
       else if (startpos < next)
        next = startpos;
@@ -1237,28 +1289,38 @@ overlays_at (pos, vec_ptr, len_ptr, next_ptr)
        CONSP (tail);
        tail = XCONS (tail)->cdr)
     {
+      int startpos;
+
       overlay = XCONS (tail)->car;
       if (! OVERLAY_VALID (overlay))
-       continue;
+       abort ();
 
       start = OVERLAY_START (overlay);
       end = OVERLAY_END (overlay);
       startpos = OVERLAY_POSITION (start);
-      if (startpos > pos)
+      if (pos < startpos)
        {
          if (startpos < next)
            next = startpos;
          break;
        }
-      if (OVERLAY_POSITION (end) > pos)
+      if (pos < OVERLAY_POSITION (end))
        {
          if (idx == len)
            {
-             *len_ptr = len *= 2;
-             vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
-             *vec_ptr = vec;
+             if (extend)
+               {
+                 *len_ptr = len *= 2;
+                 vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
+                 *vec_ptr = vec;
+               }
+             else
+               inhibit_storing = 1;
            }
-         vec[idx++] = overlay;
+
+         if (!inhibit_storing)
+           vec[idx] = overlay;
+         idx++;
        }
     }
 
@@ -1266,11 +1328,11 @@ overlays_at (pos, vec_ptr, len_ptr, next_ptr)
   return idx;
 }
 \f
-/* Shift overlays in the current buffer's overlay lists,
-   to center the lists at POS.  */
+/* Shift overlays in BUF's overlay lists, to center the lists at POS.  */
 
 void
-recenter_overlay_lists (pos)
+recenter_overlay_lists (buf, pos)
+     struct buffer *buf;
      int pos;
 {
   Lisp_Object overlay, tail, next, prev, beg, end;
@@ -1281,7 +1343,7 @@ recenter_overlay_lists (pos)
      But we use it for symmetry and in case that should cease to be true
      with some future change.  */
   prev = Qnil;
-  for (tail = current_buffer->overlays_before;
+  for (tail = buf->overlays_before;
        CONSP (tail);
        prev = tail, tail = next)
     {
@@ -1290,15 +1352,19 @@ recenter_overlay_lists (pos)
 
       /* 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
-           current_buffer->overlays_before = next;
+           buf->overlays_before = next;
          tail = prev;
          continue;
        }
+#endif
 
       beg = OVERLAY_START (overlay);
       end = OVERLAY_END (overlay);
@@ -1313,11 +1379,11 @@ recenter_overlay_lists (pos)
          if (!NILP (prev))
            XCONS (prev)->cdr = next;
          else
-           current_buffer->overlays_before = next;
+           buf->overlays_before = next;
 
          /* Search thru overlays_after for where to put it.  */
          other_prev = Qnil;
-         for (other = current_buffer->overlays_after;
+         for (other = buf->overlays_after;
               CONSP (other);
               other_prev = other, other = XCONS (other)->cdr)
            {
@@ -1326,7 +1392,7 @@ recenter_overlay_lists (pos)
 
              otheroverlay = XCONS (other)->car;
              if (! OVERLAY_VALID (otheroverlay))
-               continue;
+               abort ();
 
              otherbeg = OVERLAY_START (otheroverlay);
              if (OVERLAY_POSITION (otherbeg) >= where)
@@ -1338,7 +1404,7 @@ recenter_overlay_lists (pos)
          if (!NILP (other_prev))
            XCONS (other_prev)->cdr = tail;
          else
-           current_buffer->overlays_after = tail;
+           buf->overlays_after = tail;
          tail = prev;
        }
       else
@@ -1350,7 +1416,7 @@ recenter_overlay_lists (pos)
 
   /* See if anything in overlays_after should be in overlays_before.  */
   prev = Qnil;
-  for (tail = current_buffer->overlays_after;
+  for (tail = buf->overlays_after;
        CONSP (tail);
        prev = tail, tail = next)
     {
@@ -1359,15 +1425,19 @@ recenter_overlay_lists (pos)
 
       /* 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
-           current_buffer->overlays_after = next;
+           buf->overlays_after = next;
          tail = prev;
          continue;
        }
+#endif
 
       beg = OVERLAY_START (overlay);
       end = OVERLAY_END (overlay);
@@ -1387,11 +1457,11 @@ recenter_overlay_lists (pos)
          if (!NILP (prev))
            XCONS (prev)->cdr = next;
          else
-           current_buffer->overlays_after = next;
+           buf->overlays_after = next;
 
          /* Search thru overlays_before for where to put it.  */
          other_prev = Qnil;
-         for (other = current_buffer->overlays_before;
+         for (other = buf->overlays_before;
               CONSP (other);
               other_prev = other, other = XCONS (other)->cdr)
            {
@@ -1400,7 +1470,7 @@ recenter_overlay_lists (pos)
 
              otheroverlay = XCONS (other)->car;
              if (! OVERLAY_VALID (otheroverlay))
-               continue;
+               abort ();
 
              otherend = OVERLAY_END (otheroverlay);
              if (OVERLAY_POSITION (otherend) <= where)
@@ -1412,88 +1482,243 @@ recenter_overlay_lists (pos)
          if (!NILP (other_prev))
            XCONS (other_prev)->cdr = tail;
          else
-           current_buffer->overlays_before = tail;
+           buf->overlays_before = tail;
          tail = prev;
        }
     }
 
-  XFASTINT (current_buffer->overlay_center) = pos;
+  XFASTINT (buf->overlay_center) = pos;
 }
 \f
-DEFUN ("make-overlay", Fmake_overlay, Smake_overlay, 2, 2, 0,
-  "Create a new overlay in the current buffer, with range BEG to END.\n\
+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)
-     Lisp_Object beg, end;
+  (beg, end, buffer)
+     Lisp_Object beg, end, buffer;
 {
   Lisp_Object overlay;
+  struct buffer *b;
 
-  if (MARKERP (beg) && XBUFFER (Fmarker_buffer (beg)) != current_buffer)
+  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) && XBUFFER (Fmarker_buffer (end)) != current_buffer)
+  if (MARKERP (end)
+      && ! EQ (Fmarker_buffer (end), buffer))
     error ("Marker points into wrong buffer");
 
-  overlay = Fcons (Fcons (Fcopy_marker (beg), Fcopy_marker (end)), Qnil);
+  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 (current_buffer->overlay_center))
-    current_buffer->overlays_after
-      = Fcons (overlay, current_buffer->overlays_after);
+  if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
+    b->overlays_after = Fcons (overlay, b->overlays_after);
   else
-    current_buffer->overlays_before
-      = Fcons (overlay, current_buffer->overlays_before);
+    b->overlays_before = Fcons (overlay, b->overlays_before);
 
   /* This puts it in the right list, and in the right order.  */
-  recenter_overlay_lists (XINT (current_buffer->overlay_center));
+  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, 3, 0,
-  "Set the endpoints of OVERLAY to BEG and END.")
-  (overlay, beg, end)
-     Lisp_Object overlay, beg, end;
+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;
 {
-  if (!OVERLAY_VALID (overlay))
-    error ("Invalid overlay object");
+  struct buffer *b, *ob;
+  Lisp_Object obuffer;
+  int count = specpdl_ptr - specpdl;
 
-  current_buffer->overlays_before
-    = Fdelq (overlay, current_buffer->overlays_before);
-  current_buffer->overlays_after
-    = Fdelq (overlay, current_buffer->overlays_after);
+  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);
 
-  Fset_marker (OVERLAY_START (overlay), beg, Qnil);
-  Fset_marker (OVERLAY_END (overlay), end, Qnil);
+  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 = 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));
+       }
+    }
+
+  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 (current_buffer->overlay_center))
-    current_buffer->overlays_after
-      = Fcons (overlay, current_buffer->overlays_after);
+  if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
+    b->overlays_after = Fcons (overlay, b->overlays_after);
   else
-    current_buffer->overlays_before
-      = Fcons (overlay, current_buffer->overlays_before);
+    b->overlays_before = Fcons (overlay, b->overlays_before);
 
   /* This puts it in the right list, and in the right order.  */
-  recenter_overlay_lists (XINT (current_buffer->overlay_center));
+  recenter_overlay_lists (b, XINT (b->overlay_center));
 
-  return overlay;
+  return unbind_to (count, overlay);
 }
 
 DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
-  "Delete the overlay OVERLAY from the current buffer.")
+  "Delete the overlay OVERLAY from its buffer.")
   (overlay)
+     Lisp_Object overlay;
 {
-  current_buffer->overlays_before
-    = Fdelq (overlay, current_buffer->overlays_before);
-  current_buffer->overlays_after
-    = Fdelq (overlay, current_buffer->overlays_after);
-  return Qnil;
+  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,
+                   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 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 overays that contain position POS.")
+  "Return a list of the overlays that contain position POS.")
   (pos)
      Lisp_Object pos;
 {
@@ -1510,7 +1735,7 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
 
   /* 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);
+  noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &endpos);
 
   /* Make a list of them all.  */
   result = Flist (noverlays, overlay_vec);
@@ -1540,7 +1765,7 @@ DEFUN ("next-overlay-change", Fnext_overlay_change, Snext_overlay_change,
   /* 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);
+  noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &endpos);
 
   /* If any of these overlays ends before endpos,
      use its ending point instead.  */
@@ -1588,7 +1813,7 @@ DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
 {
   CHECK_NUMBER_COERCE_MARKER (pos, 0);
 
-  recenter_overlay_lists (XINT (pos));
+  recenter_overlay_lists (current_buffer, XINT (pos));
   return Qnil;
 }
 \f
@@ -1598,13 +1823,18 @@ DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0,
      Lisp_Object overlay, prop;
 {
   Lisp_Object plist;
-  for (plist = Fcdr_safe (Fcdr_safe (overlay));
+
+  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,
@@ -1614,7 +1844,13 @@ DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
 {
   Lisp_Object plist, tail;
 
-  plist = Fcdr_safe (Fcdr_safe (overlay));
+  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);
@@ -1633,6 +1869,100 @@ DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
   return value;
 }
 \f
+/* Run the modification-hooks of overlays that include
+   any part of the text in START to END.
+   Run the insert-before-hooks of overlay starting at END,
+   and the insert-after-hooks of overlay ending at START.  */
+
+void
+verify_overlay_modification (start, end)
+     Lisp_Object start, end;
+{
+  Lisp_Object prop, overlay, tail;
+  int insertion = EQ (start, end);
+
+  for (tail = current_buffer->overlays_before;
+       CONSP (tail);
+       tail = XCONS (tail)->cdr)
+    {
+      int startpos, endpos;
+      int ostart, oend;
+
+      overlay = XCONS (tail)->car;
+
+      ostart = OVERLAY_START (overlay);
+      oend = OVERLAY_END (overlay);
+      endpos = OVERLAY_POSITION (oend);
+      if (XFASTINT (start) > endpos)
+       break;
+      startpos = OVERLAY_POSITION (ostart);
+      if (XFASTINT (end) == startpos && insertion)
+       {
+         prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
+         call_overlay_mod_hooks (prop, overlay, start, end);
+       }
+      if (XFASTINT (start) == endpos && insertion)
+       {
+         prop = Foverlay_get (overlay, Qinsert_behind_hooks);
+         call_overlay_mod_hooks (prop, overlay, start, end);
+       }
+      if (insertion
+         ? (XFASTINT (start) > startpos && XFASTINT (end) < endpos)
+         : (XFASTINT (start) >= startpos && XFASTINT (end) <= endpos))
+       {
+         prop = Foverlay_get (overlay, Qmodification_hooks);
+         call_overlay_mod_hooks (prop, overlay, start, end);
+       }
+    }
+
+  for (tail = current_buffer->overlays_after;
+       CONSP (tail);
+       tail = XCONS (tail)->cdr)
+    {
+      int startpos, endpos;
+      int ostart, oend;
+
+      overlay = XCONS (tail)->car;
+
+      ostart = OVERLAY_START (overlay);
+      oend = OVERLAY_END (overlay);
+      startpos = OVERLAY_POSITION (ostart);
+      if (XFASTINT (end) < startpos)
+       break;
+      if (XFASTINT (end) == startpos && insertion)
+       {
+         prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
+         call_overlay_mod_hooks (prop, overlay, start, end);
+       }
+      if (XFASTINT (start) == endpos && insertion)
+       {
+         prop = Foverlay_get (overlay, Qinsert_behind_hooks);
+         call_overlay_mod_hooks (prop, overlay, start, end);
+       }
+      if (insertion
+         ? (XFASTINT (start) > startpos && XFASTINT (end) < endpos)
+         : (XFASTINT (start) >= startpos && XFASTINT (end) <= endpos))
+       {
+         prop = Foverlay_get (overlay, Qmodification_hooks);
+         call_overlay_mod_hooks (prop, overlay, start, end);
+       }
+    }
+}
+
+static void
+call_overlay_mod_hooks (list, overlay, start, end)
+     Lisp_Object list, overlay, start, end;
+{
+  struct gcpro gcpro1;
+  GCPRO1 (list);
+  while (!NILP (list))
+    {
+      call3 (Fcar (list), overlay, start, end);
+      list = Fcdr (list);
+    }
+  UNGCPRO;
+}
+\f
 /* Somebody has tried to store NEWVAL into the buffer-local slot with
    offset XUINT (valcontents), and NEWVAL has an unacceptable type.  */
 void
@@ -1768,6 +2098,7 @@ init_buffer ()
   char buf[MAXPATHLEN+1];
   char *pwd;
   struct stat dotstat, pwdstat;
+  Lisp_Object temp;
 
   Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
 
@@ -1790,6 +2121,9 @@ init_buffer ()
     strcat (buf, "/");
 #endif /* not VMS */
   current_buffer->directory = build_string (buf);
+
+  temp = get_minibuffer (0);
+  XBUFFER (temp)->directory = current_buffer->directory;
 }
 
 /* initialize the buffer routines */
@@ -1806,6 +2140,9 @@ 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)));
@@ -1883,7 +2220,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\
@@ -2015,14 +2352,17 @@ 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.");
 
@@ -2099,6 +2439,14 @@ Automatically local in all buffers.");
     "*Non-nil means deactivate the mark when the buffer contents change.");
   Vtransient_mark_mode = Qnil;
 
+  DEFVAR_LISP ("inhibit-read-only", &Vinhibit_read_only,
+    "*Non-nil means disregard read-only status of buffers or characters.\n\
+If the value is t, disregard `buffer-read-only' and all `read-only'\n\
+text properties.  If the value is a list, disregard `buffer-read-only'\n\
+and disregard a `read-only' text property if the property value\n\
+is a member of the list.");
+  Vinhibit_read_only = Qnil;
+
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
   defsubr (&Sget_file_buffer);
@@ -2126,9 +2474,14 @@ Automatically local in all buffers.");
   defsubr (&Slist_buffers);
   defsubr (&Skill_all_local_variables);
 
+  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);