Removed %T in mode-line-format. Trivial documentation changes.
[bpt/emacs.git] / src / buffer.c
index 95876c1..fa5a9c8 100644 (file)
@@ -1,5 +1,5 @@
 /* Buffer manipulation primitives for GNU Emacs.
-   Copyright (C) 1985,86,87,88,89,93,94,95,97,98, 1999, 2000, 2001, 2002
+   Copyright (C) 1985,86,87,88,89,93,94,95,97,98, 1999, 2000, 2001, 02, 03, 2004
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -32,7 +32,7 @@ extern int errno;
 #endif
 
 #ifndef MAXPATHLEN
-/* in 4.1, param.h fails to define this. */
+/* in 4.1 [probably SunOS? -stef] , param.h fails to define this. */
 #define MAXPATHLEN 1024
 #endif /* not MAXPATHLEN */
 
@@ -67,7 +67,7 @@ struct buffer *all_buffers;
    Setting the default value also goes through the alist of buffers
    and stores into each buffer that does not say it has a local value.  */
 
-struct buffer buffer_defaults;
+DECL_ALIGN (struct buffer, buffer_defaults);
 
 /* A Lisp_Object pointer to the above, used for staticpro */
 
@@ -89,10 +89,6 @@ static Lisp_Object Vbuffer_defaults;
    If a slot is -2, then there is no DEFVAR_PER_BUFFER for it,
    but there is a default value which is copied into each buffer.
 
-   If a slot in this structure is negative, then even though there may
-   be a DEFVAR_PER_BUFFER for the slot, there is no default value for it;
-   and the corresponding slot in buffer_defaults is not used.
-
    If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
    zero, that is a bug */
 
@@ -101,7 +97,8 @@ struct buffer buffer_local_flags;
 /* This structure holds the names of symbols whose values may be
    buffer-local.  It is indexed and accessed in the same way as the above. */
 
-struct buffer buffer_local_symbols;
+DECL_ALIGN (struct buffer, buffer_local_symbols);
+
 /* A Lisp_Object pointer to the above, used for staticpro */
 static Lisp_Object Vbuffer_local_symbols;
 
@@ -150,6 +147,7 @@ Lisp_Object Vinhibit_read_only;
 /* List of functions to call that can query about killing a buffer.
    If any of these functions returns nil, we don't kill it.  */
 Lisp_Object Vkill_buffer_query_functions;
+Lisp_Object Qkill_buffer_query_functions;
 
 /* List of functions to call before changing an unmodified buffer.  */
 Lisp_Object Vfirst_change_hook;
@@ -182,8 +180,8 @@ Lisp_Object Qinsert_behind_hooks;
 
 static void alloc_buffer_text P_ ((struct buffer *, size_t));
 static void free_buffer_text P_ ((struct buffer *b));
-static Lisp_Object copy_overlays P_ ((struct buffer *, Lisp_Object));
-static void modify_overlay P_ ((struct buffer *, int, int));
+static struct Lisp_Overlay * copy_overlays P_ ((struct buffer *, struct Lisp_Overlay *));
+static void modify_overlay P_ ((struct buffer *, EMACS_INT, EMACS_INT));
 
 
 /* For debugging; temporary.  See set_buffer_internal.  */
@@ -412,17 +410,18 @@ The value is never nil.  */)
   reset_buffer_local_variables (b, 1);
 
   b->mark = Fmake_marker ();
-  BUF_MARKERS (b) = Qnil;
+  BUF_MARKERS (b) = NULL;
   b->name = name;
 
   /* Put this in the alist of all live buffers.  */
   XSETBUFFER (buf, b);
   Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil));
 
-  /* Fixme:  Protect against errors, which would trigger infinite
-     regress?  */
+  /* An error in calling the function here (should someone redfine it)
+     can lead to infinite regress until you run out of stack.  rms
+     says that's not worth protecting against.  */
   if (!NILP (Ffboundp (Qucs_set_table_for_input)))
-    /* buff is on buffer-alist, so no gcpro */
+    /* buf is on buffer-alist, so no gcpro.  */
     call1 (Qucs_set_table_for_input, buf);
 
   return buf;
@@ -432,21 +431,22 @@ The value is never nil.  */)
 /* Return a list of overlays which is a copy of the overlay list
    LIST, but for buffer B.  */
 
-static Lisp_Object
+static struct Lisp_Overlay *
 copy_overlays (b, list)
      struct buffer *b;
-     Lisp_Object list;
+     struct Lisp_Overlay *list;
 {
-  Lisp_Object result, buffer;
+  Lisp_Object buffer;
+  struct Lisp_Overlay *result = NULL, *tail = NULL;
 
   XSETBUFFER (buffer, b);
 
-  for (result = Qnil; CONSP (list); list = XCDR (list))
+  for (; list; list = list->next)
     {
       Lisp_Object overlay, start, end, old_overlay;
-      int charpos;
+      EMACS_INT charpos;
 
-      old_overlay = XCAR (list);
+      XSETMISC (old_overlay, list);
       charpos = marker_position (OVERLAY_START (old_overlay));
       start = Fmake_marker ();
       Fset_marker (start, make_number (charpos), buffer);
@@ -464,13 +464,17 @@ copy_overlays (b, list)
       OVERLAY_START (overlay) = start;
       OVERLAY_END (overlay) = end;
       OVERLAY_PLIST (overlay) = Fcopy_sequence (OVERLAY_PLIST (old_overlay));
-      
-      result = Fcons (overlay, result);
+      XOVERLAY (overlay)->next = NULL;
+
+      if (tail)
+       tail = tail->next = XOVERLAY (overlay);
+      else
+       result = tail = XOVERLAY (overlay);
     }
 
-  return Fnreverse (result);
+  return result;
 }
-     
+
 
 /* Clone per-buffer values of buffer FROM.
 
@@ -487,7 +491,7 @@ clone_per_buffer_values (from, to)
   int offset;
 
   XSETBUFFER (to_buffer, to);
-  
+
   for (offset = PER_BUFFER_VAR_OFFSET (name) + sizeof (Lisp_Object);
        offset < sizeof *to;
        offset += sizeof (Lisp_Object))
@@ -507,7 +511,7 @@ clone_per_buffer_values (from, to)
     }
 
   bcopy (from->local_flags, to->local_flags, sizeof to->local_flags);
-  
+
   to->overlays_before = copy_overlays (to, from->overlays_before);
   to->overlays_after = copy_overlays (to, from->overlays_after);
 }
@@ -623,8 +627,36 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
   return buf;
 }
 
+void
+delete_all_overlays (b)
+     struct buffer *b;
+{
+  Lisp_Object overlay;
+
+  /* `reset_buffer' blindly sets the list of overlays to NULL, so we
+     have to empty the list, otherwise we end up with overlays that
+     think they belong to this buffer while the buffer doesn't know about
+     them any more.  */
+  while (b->overlays_before)
+    {
+      XSETMISC (overlay, b->overlays_before);
+      Fdelete_overlay (overlay);
+    }
+  while (b->overlays_after)
+    {
+      XSETMISC (overlay, b->overlays_after);
+      Fdelete_overlay (overlay);
+    }
+  eassert (b->overlays_before == NULL);
+  eassert (b->overlays_after == NULL);
+}
+
 /* Reinitialize everything about a buffer except its name and contents
-   and local variables.  */
+   and local variables. 
+   If called on an already-initialized buffer, the list of overlays
+   should be deleted before calling this function, otherwise we end up
+   with overlays that claim to belong to the buffer but the buffer
+   claims it doesn't belong to it.  */
 
 void
 reset_buffer (b)
@@ -644,9 +676,9 @@ reset_buffer (b)
   b->auto_save_failure_time = -1;
   b->auto_save_file_name = Qnil;
   b->read_only = Qnil;
-  b->overlays_before = Qnil;
-  b->overlays_after = Qnil;
-  XSETFASTINT (b->overlay_center, 1);
+  b->overlays_before = NULL;
+  b->overlays_after = NULL;
+  b->overlay_center = BEG;
   b->mark_active = Qnil;
   b->point_before_scroll = Qnil;
   b->file_format = Qnil;
@@ -683,7 +715,6 @@ reset_buffer_local_variables (b, permanent_too)
      We ignore it here.  */
   b->major_mode = Qfundamental_mode;
   b->keymap = Qnil;
-  b->abbrev_table = Vfundamental_mode_abbrev_table;
   b->mode_name = QSFundamental;
   b->minor_modes = Qnil;
 
@@ -816,7 +847,7 @@ If BUFFER is not indirect, return nil.  */)
 }
 
 DEFUN ("buffer-local-value", Fbuffer_local_value,
-       Sbuffer_local_value, 2, 2, 0, 
+       Sbuffer_local_value, 2, 2, 0,
        doc: /* Return the value of VARIABLE in BUFFER.
 If VARIABLE does not have a buffer-local binding in BUFFER, the value
 is the default binding of variable. */)
@@ -833,7 +864,7 @@ is the default binding of variable. */)
 
   /* Look in local_var_list */
   result = Fassoc (symbol, buf->local_var_alist);
-  if (NILP (result)) 
+  if (NILP (result))
     {
       int offset, idx;
       int found = 0;
@@ -846,8 +877,8 @@ is the default binding of variable. */)
        {
          idx = PER_BUFFER_IDX (offset);
          if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
-             && SYMBOLP (PER_BUFFER_SYMBOL (offset)) 
-             && EQ (PER_BUFFER_SYMBOL (offset), symbol)) 
+             && SYMBOLP (PER_BUFFER_SYMBOL (offset))
+             && EQ (PER_BUFFER_SYMBOL (offset), symbol))
            {
              result = PER_BUFFER_VALUE (buf, offset);
              found = 1;
@@ -1005,7 +1036,7 @@ A non-nil FLAG means mark the buffer modified.  */)
 #endif /* CLASH_DETECTION */
 
   SAVE_MODIFF = NILP (flag) ? MODIFF : 0;
-  
+
   /* Set update_mode_lines only if buffer is displayed in some window.
      Packages like jit-lock or lazy-lock preserve a buffer's modified
      state by recording/restoring the state around blocks of code.
@@ -1024,7 +1055,7 @@ A non-nil FLAG means mark the buffer modified.  */)
       ++update_mode_lines;
       current_buffer->prevent_redisplay_optimizations_p = 1;
     }
-  
+
   return flag;
 }
 
@@ -1038,7 +1069,7 @@ state of the current buffer.  Use with care.  */)
 {
 #ifdef CLASH_DETECTION
   Lisp_Object fn;
-  
+
   /* If buffer becoming modified, lock the file.
      If buffer becoming unmodified, unlock the file.  */
 
@@ -1053,7 +1084,7 @@ state of the current buffer.  Use with care.  */)
        unlock_file (fn);
     }
 #endif /* CLASH_DETECTION */
-  
+
   SAVE_MODIFF = NILP (flag) ? MODIFF : 0;
   return flag;
 }
@@ -1152,7 +1183,7 @@ If BUFFER is omitted or nil, some interesting buffer is returned.  */)
 
   /* Consider buffers that have been seen in the selected frame
      before other buffers.  */
-    
+
   tem = frame_buffer_list (frame);
   add_ons = Qnil;
   while (CONSP (tem))
@@ -1168,6 +1199,10 @@ If BUFFER is omitted or nil, some interesting buffer is returned.  */)
       buf = Fcdr (XCAR (tail));
       if (EQ (buf, buffer))
        continue;
+      if (NILP (buf))
+       continue;
+      if (NILP (XBUFFER (buf)->name))
+       continue;
       if (SREF (XBUFFER (buf)->name, 0) == ' ')
        continue;
       /* If the selected frame has a buffer_predicate,
@@ -1293,8 +1328,8 @@ with SIGHUP.  */)
       && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
     {
       GCPRO1 (buf);
-      tem = do_yes_or_no_p (format1 ("Buffer %s modified; kill anyway? ",
-                                    SDATA (b->name)));
+      tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ",
+                                    b->name, make_number (0)));
       UNGCPRO;
       if (NILP (tem))
        return Qnil;
@@ -1303,19 +1338,16 @@ with SIGHUP.  */)
   /* Run hooks with the buffer to be killed the current buffer.  */
   {
     int count = SPECPDL_INDEX ();
-    Lisp_Object list;
+    Lisp_Object arglist[1];
 
     record_unwind_protect (save_excursion_restore, save_excursion_save ());
     set_buffer_internal (b);
 
     /* First run the query functions; if any query is answered no,
        don't kill the buffer.  */
-    for (list = Vkill_buffer_query_functions; CONSP (list); list = XCDR (list))
-      {
-       tem = call0 (XCAR (list));
-       if (NILP (tem))
-         return unbind_to (count, Qnil);
-      }
+    arglist[0] = Qkill_buffer_query_functions;
+    if (NILP (Frun_hook_with_args_until_failure (1, arglist)))
+      return unbind_to (count, Qnil);
 
     /* Then run the hooks.  */
     Frun_hooks (1, &Qkill_buffer_hook);
@@ -1354,7 +1386,7 @@ with SIGHUP.  */)
 
       UNGCPRO;
     }
-  
+
   /* Make this buffer not be current.
      In the process, notice if this is the sole visible buffer
      and give up if so.  */
@@ -1384,6 +1416,7 @@ with SIGHUP.  */)
 #endif /* CLASH_DETECTION */
 
   kill_buffer_processes (buf);
+  clear_charpos_cache (b);
 
   tem = Vinhibit_quit;
   Vinhibit_quit = Qt;
@@ -1397,7 +1430,8 @@ with SIGHUP.  */)
   if (STRINGP (b->auto_save_file_name)
       && b->auto_save_modified != 0
       && BUF_SAVE_MODIFF (b) < b->auto_save_modified
-      && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
+      && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
+      && NILP (Fsymbol_value (intern ("auto-save-visited-file-name"))))
     {
       Lisp_Object tem;
       tem = Fsymbol_value (intern ("delete-auto-save-files"));
@@ -1410,28 +1444,26 @@ with SIGHUP.  */)
       /* Unchain all markers that belong to this indirect buffer.
         Don't unchain the markers that belong to the base buffer
         or its other indirect buffers.  */
-      for (tem = BUF_MARKERS (b); !NILP (tem); )
+      for (m = BUF_MARKERS (b); m; )
        {
-         Lisp_Object next;
-         m = XMARKER (tem);
-         next = m->chain;
+         struct Lisp_Marker *next = m->next;
          if (m->buffer == b)
-           unchain_marker (tem);
-         tem = next;
+           unchain_marker (m);
+         m = next;
        }
     }
   else
     {
       /* Unchain all markers of this buffer and its indirect buffers.
         and leave them pointing nowhere.  */
-      for (tem = BUF_MARKERS (b); !NILP (tem); )
+      for (m = BUF_MARKERS (b); m; )
        {
-         m = XMARKER (tem);
+         struct Lisp_Marker *next = m->next;
          m->buffer = 0;
-         tem = m->chain;
-         m->chain = Qnil;
+         m->next = NULL;
+         m = next;
        }
-      BUF_MARKERS (b) = Qnil;
+      BUF_MARKERS (b) = NULL;
       BUF_INTERVALS (b) = NULL_INTERVAL;
 
       /* Perhaps we should explicitly free the interval tree here... */
@@ -1495,7 +1527,7 @@ record_buffer (buf)
     Vbuffer_alist = XCDR (Vbuffer_alist);
   else
     XSETCDR (prev, XCDR (XCDR (prev)));
-       
+
   XSETCDR (link, Vbuffer_alist);
   Vbuffer_alist = link;
 
@@ -1519,7 +1551,7 @@ record_buffer (buf)
                               XCDR (frame_buffer_list (frame)));
       else
        XSETCDR (prev, XCDR (XCDR (prev)));
-       
+
       XSETCDR (link, frame_buffer_list (frame));
       set_frame_buffer_list (frame, link);
     }
@@ -1549,7 +1581,7 @@ the current buffer's major mode.  */)
          && NILP (Fget (current_buffer->major_mode, Qmode_class)))
        function = current_buffer->major_mode;
     }
-  
+
   if (NILP (function) || EQ (function, Qfundamental_mode))
     return Qnil;
 
@@ -1609,7 +1641,7 @@ switch_to_buffer_1 (buffer, norecord)
   Fset_window_buffer (EQ (selected_window, minibuf_window)
                      ? Fnext_window (minibuf_window, Qnil, Qnil)
                      : selected_window,
-                     buf);
+                     buf, Qnil);
 
   return buf;
 }
@@ -1628,6 +1660,11 @@ the window-buffer correspondences.  */)
 {
   char *err;
 
+  if (EQ (buffer, Fwindow_buffer (selected_window)))
+    /* Basically a NOP.  Avoid signalling an error if the selected window
+       is dedicated, or a minibuffer, ...  */
+    return Fset_buffer (buffer);
+
   err = no_switch_window (selected_window);
   if (err) error (err);
 
@@ -1662,9 +1699,9 @@ do not put this buffer at the front of the list of recently selected ones.  */)
     }
   Fset_buffer (buf);
   if (NILP (norecord))
-    /* This seems bogus since Fselect_window will call record_buffer anyway.  */
+    /* Why bother ?  Fselect_window will do it for us anyway.  -stef  */
     record_buffer (buf);
-  Fselect_window (Fdisplay_buffer (buf, other_window, Qnil));
+  Fselect_window (Fdisplay_buffer (buf, other_window, Qnil), norecord);
   return buf;
 }
 
@@ -1709,7 +1746,7 @@ set_buffer_internal_1 (b)
   if (b->text->beg == NULL)
     enlarge_buffer_text (b, 0);
 #endif /* USE_MMAP_FOR_BUFFERS */
-  
+
   if (current_buffer == b)
     return;
 
@@ -1775,7 +1812,7 @@ set_buffer_internal_1 (b)
   /* Look down buffer's list of local Lisp variables
      to find and update any that forward into C variables. */
 
-  for (tail = b->local_var_alist; !NILP (tail); tail = XCDR (tail))
+  for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail))
     {
       valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
       if ((BUFFER_LOCAL_VALUEP (valcontents)
@@ -1790,7 +1827,7 @@ set_buffer_internal_1 (b)
   /* Do the same with any others that were local to the previous buffer */
 
   if (old_buf)
-    for (tail = old_buf->local_var_alist; !NILP (tail); tail = XCDR (tail))
+    for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
       {
        valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
        if ((BUFFER_LOCAL_VALUEP (valcontents)
@@ -1937,7 +1974,7 @@ selected window if it is displayed there.  */)
   else
     {
       Lisp_Object buf1;
-      
+
       buf1 = Fget_buffer (buffer);
       if (NILP (buf1))
        nsberror (buffer);
@@ -2048,11 +2085,11 @@ but the contents viewed as characters do change.  */)
      (flag)
      Lisp_Object flag;
 {
-  Lisp_Object tail, markers;
+  struct Lisp_Marker *tail, *markers;
   struct buffer *other;
   int undo_enabled_p = !EQ (current_buffer->undo_list, Qt);
-  int begv = BEGV, zv = ZV;
-  int narrowed = (BEG != begv || Z != zv);
+  int begv, zv;
+  int narrowed = (BEG != BEGV || Z != ZV);
   int modified_p = !NILP (Fbuffer_modified_p (Qnil));
 
   if (current_buffer->base_buffer)
@@ -2070,6 +2107,11 @@ but the contents viewed as characters do change.  */)
   /* If the cached position is for this buffer, clear it out.  */
   clear_charpos_cache (current_buffer);
 
+  if (NILP (flag))
+    begv = BEGV_BYTE, zv = ZV_BYTE;
+  else
+    begv = BEGV, zv = ZV;
+
   if (narrowed)
     Fwiden ();
 
@@ -2090,12 +2132,9 @@ but the contents viewed as characters do change.  */)
       GPT = GPT_BYTE;
       TEMP_SET_PT_BOTH (PT_BYTE, PT_BYTE);
 
-      tail = BUF_MARKERS (current_buffer);
-      while (! NILP (tail))
-       {
-         XMARKER (tail)->charpos = XMARKER (tail)->bytepos;
-         tail = XMARKER (tail)->chain;
-       }
+      
+      for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
+       tail->charpos = tail->bytepos;
 
       /* Convert multibyte form of 8-bit characters to unibyte.  */
       pos = BEG;
@@ -2175,7 +2214,7 @@ but the contents viewed as characters do change.  */)
              p = GAP_END_ADDR;
              stop = Z;
            }
-             
+
          if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes))
            p += bytes, pos += bytes;
          else
@@ -2243,20 +2282,17 @@ but the contents viewed as characters do change.  */)
       /* This prevents BYTE_TO_CHAR (that is, buf_bytepos_to_charpos) from
         getting confused by the markers that have not yet been updated.
         It is also a signal that it should never create a marker.  */
-      BUF_MARKERS (current_buffer) = Qnil;
+      BUF_MARKERS (current_buffer) = NULL;
 
-      while (! NILP (tail))
+      for (; tail; tail = tail->next)
        {
-         XMARKER (tail)->bytepos
-           = advance_to_char_boundary (XMARKER (tail)->bytepos);
-         XMARKER (tail)->charpos = BYTE_TO_CHAR (XMARKER (tail)->bytepos);
-
-         tail = XMARKER (tail)->chain;
+         tail->bytepos = advance_to_char_boundary (tail->bytepos);
+         tail->charpos = BYTE_TO_CHAR (tail->bytepos);
        }
 
       /* Make sure no markers were put on the chain
         while the chain value was incorrect.  */
-      if (! EQ (BUF_MARKERS (current_buffer), Qnil))
+      if (BUF_MARKERS (current_buffer))
        abort ();
 
       BUF_MARKERS (current_buffer) = markers;
@@ -2288,6 +2324,17 @@ but the contents viewed as characters do change.  */)
   if (!modified_p && !NILP (Fbuffer_modified_p (Qnil)))
     Fset_buffer_modified_p (Qnil);
 
+#ifdef subprocesses
+  /* Update coding systems of this buffer's process (if any).  */
+  {
+    Lisp_Object process;
+
+    process = Fget_buffer_process (Fcurrent_buffer ());
+    if (PROCESSP (process))
+      setup_process_coding_systems (process);
+  }
+#endif /* subprocesses */
+
   return flag;
 }
 \f
@@ -2328,7 +2375,7 @@ the normal hook `change-major-mode-hook'.  */)
 
   /* Any which are supposed to be permanent,
      make local again, with the same values they had.  */
-     
+
   for (alist = oalist; !NILP (alist); alist = XCDR (alist))
     {
       sym = XCAR (XCAR (alist));
@@ -2390,7 +2437,7 @@ swap_out_buffer_local_variables (b)
 }
 \f
 /* 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.  
+   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.
@@ -2413,7 +2460,7 @@ swap_out_buffer_local_variables (b)
 
 int
 overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
-     int pos;
+     EMACS_INT pos;
      int extend;
      Lisp_Object **vec_ptr;
      int *len_ptr;
@@ -2421,7 +2468,8 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
      int *prev_ptr;
      int change_req;
 {
-  Lisp_Object tail, overlay, start, end;
+  Lisp_Object overlay, start, end;
+  struct Lisp_Overlay *tail;
   int idx = 0;
   int len = *len_ptr;
   Lisp_Object *vec = *vec_ptr;
@@ -2429,13 +2477,11 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
   int prev = BEGV;
   int inhibit_storing = 0;
 
-  for (tail = current_buffer->overlays_before;
-       GC_CONSP (tail);
-       tail = XCDR (tail))
+  for (tail = current_buffer->overlays_before; tail; tail = tail->next)
     {
       int startpos, endpos;
 
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
 
       start = OVERLAY_START (overlay);
       end = OVERLAY_END (overlay);
@@ -2482,13 +2528,11 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
        next = startpos;
     }
 
-  for (tail = current_buffer->overlays_after;
-       GC_CONSP (tail);
-       tail = XCDR (tail))
+  for (tail = current_buffer->overlays_after; tail; tail = tail->next)
     {
       int startpos, endpos;
 
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
 
       start = OVERLAY_START (overlay);
       end = OVERLAY_END (overlay);
@@ -2542,7 +2586,7 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
 /* Find all the overlays in the current buffer that overlap the range BEG-END
    or are empty at BEG.
 
-   Return the number found, and store them in a vector in *VEC_PTR.  
+   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.
@@ -2558,7 +2602,7 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
    and we store only as many overlays as will fit.
    But we still return the total number of overlays.  */
 
-int
+static int
 overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
      int beg, end;
      int extend;
@@ -2567,7 +2611,8 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
      int *next_ptr;
      int *prev_ptr;
 {
-  Lisp_Object tail, overlay, ostart, oend;
+  Lisp_Object overlay, ostart, oend;
+  struct Lisp_Overlay *tail;
   int idx = 0;
   int len = *len_ptr;
   Lisp_Object *vec = *vec_ptr;
@@ -2575,13 +2620,11 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
   int prev = BEGV;
   int inhibit_storing = 0;
 
-  for (tail = current_buffer->overlays_before;
-       GC_CONSP (tail);
-       tail = XCDR (tail))
+  for (tail = current_buffer->overlays_before; tail; tail = tail->next)
     {
       int startpos, endpos;
 
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
 
       ostart = OVERLAY_START (overlay);
       oend = OVERLAY_END (overlay);
@@ -2625,13 +2668,11 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
        next = startpos;
     }
 
-  for (tail = current_buffer->overlays_after;
-       GC_CONSP (tail);
-       tail = XCDR (tail))
+  for (tail = current_buffer->overlays_after; tail; tail = tail->next)
     {
       int startpos, endpos;
 
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
 
       ostart = OVERLAY_START (overlay);
       oend = OVERLAY_END (overlay);
@@ -2691,7 +2732,7 @@ mouse_face_overlay_overlaps (overlay)
   int end = OVERLAY_POSITION (OVERLAY_END (overlay));
   int n, i, size;
   Lisp_Object *v, tem;
-  
+
   size = 10;
   v = (Lisp_Object *) alloca (size * sizeof *v);
   n = overlays_in (start, end, 0, &v, &size, NULL, NULL);
@@ -2717,14 +2758,14 @@ int
 overlay_touches_p (pos)
      int pos;
 {
-  Lisp_Object tail, overlay;
+  Lisp_Object overlay;
+  struct Lisp_Overlay *tail;
 
-  for (tail = current_buffer->overlays_before; GC_CONSP (tail);
-       tail = XCDR (tail))
+  for (tail = current_buffer->overlays_before; tail; tail = tail->next)
     {
       int endpos;
 
-      overlay = XCAR (tail);
+      XSETMISC (overlay ,tail);
       if (!GC_OVERLAYP (overlay))
        abort ();
 
@@ -2735,12 +2776,11 @@ overlay_touches_p (pos)
        return 1;
     }
 
-  for (tail = current_buffer->overlays_after; GC_CONSP (tail);
-       tail = XCDR (tail))
+  for (tail = current_buffer->overlays_after; tail; tail = tail->next)
     {
       int startpos;
 
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
       if (!GC_OVERLAYP (overlay))
        abort ();
 
@@ -2935,21 +2975,21 @@ record_overlay_string (ssl, str, str2, pri, size)
 
 int
 overlay_strings (pos, w, pstr)
-     int pos;
+     EMACS_INT pos;
      struct window *w;
      unsigned char **pstr;
 {
-  Lisp_Object ov, overlay, window, str;
+  Lisp_Object overlay, window, str;
+  struct Lisp_Overlay *ov;
   int startpos, endpos;
   int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 
   overlay_heads.used = overlay_heads.bytes = 0;
   overlay_tails.used = overlay_tails.bytes = 0;
-  for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
+  for (ov = current_buffer->overlays_before; ov; ov = ov->next)
     {
-      overlay = XCAR (ov);
-      if (!OVERLAYP (overlay))
-       abort ();
+      XSETMISC (overlay, ov);
+      eassert (OVERLAYP (overlay));
 
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -2974,11 +3014,10 @@ overlay_strings (pos, w, pstr)
                               Foverlay_get (overlay, Qpriority),
                               endpos - startpos);
     }
-  for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
+  for (ov = current_buffer->overlays_after; ov; ov = ov->next)
     {
-      overlay = XCAR (ov);
-      if (!OVERLAYP (overlay))
-       abort ();
+      XSETMISC (overlay, ov);
+      eassert (OVERLAYP (overlay));
 
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -3063,22 +3102,21 @@ overlay_strings (pos, w, pstr)
 void
 recenter_overlay_lists (buf, pos)
      struct buffer *buf;
-     int pos;
+     EMACS_INT pos;
 {
-  Lisp_Object overlay, tail, next, prev, beg, end;
+  Lisp_Object overlay, beg, end;
+  struct Lisp_Overlay *prev, *tail, *next;
 
   /* 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)
+  prev = NULL;
+  for (tail = buf->overlays_before; tail; prev = tail, tail = next)
     {
-      next = XCDR (tail);
-      overlay = XCAR (tail);
+      next = tail->next;
+      XSETMISC (overlay, tail);
 
       /* If the overlay is not valid, get rid of it.  */
       if (!OVERLAY_VALID (overlay))
@@ -3103,25 +3141,23 @@ recenter_overlay_lists (buf, pos)
        {
          /* OVERLAY needs to be moved.  */
          int where = OVERLAY_POSITION (beg);
-         Lisp_Object other, other_prev;
+         struct Lisp_Overlay *other, *other_prev;
 
          /* Splice the cons cell TAIL out of overlays_before.  */
-         if (!NILP (prev))
-           XSETCDR (prev, next);
+         if (prev)
+           prev->next = 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 = XCDR (other))
+         other_prev = NULL;
+         for (other = buf->overlays_after; other;
+              other_prev = other, other = other->next)
            {
              Lisp_Object otherbeg, otheroverlay;
 
-             otheroverlay = XCAR (other);
-             if (! OVERLAY_VALID (otheroverlay))
-               abort ();
+             XSETMISC (otheroverlay, other);
+             eassert (OVERLAY_VALID (otheroverlay));
 
              otherbeg = OVERLAY_START (otheroverlay);
              if (OVERLAY_POSITION (otherbeg) >= where)
@@ -3129,9 +3165,9 @@ recenter_overlay_lists (buf, pos)
            }
 
          /* Add TAIL to overlays_after before OTHER.  */
-         XSETCDR (tail, other);
-         if (!NILP (other_prev))
-           XSETCDR (other_prev, tail);
+         tail->next = other;
+         if (other_prev)
+           other_prev->next = tail;
          else
            buf->overlays_after = tail;
          tail = prev;
@@ -3144,13 +3180,11 @@ recenter_overlay_lists (buf, pos)
     }
 
   /* See if anything in overlays_after should be in overlays_before.  */
-  prev = Qnil;
-  for (tail = buf->overlays_after;
-       CONSP (tail);
-       prev = tail, tail = next)
+  prev = NULL;
+  for (tail = buf->overlays_after; tail; prev = tail, tail = next)
     {
-      next = XCDR (tail);
-      overlay = XCAR (tail);
+      next = tail->next;
+      XSETMISC (overlay, tail);
 
       /* If the overlay is not valid, get rid of it.  */
       if (!OVERLAY_VALID (overlay))
@@ -3180,25 +3214,23 @@ recenter_overlay_lists (buf, pos)
        {
          /* OVERLAY needs to be moved.  */
          int where = OVERLAY_POSITION (end);
-         Lisp_Object other, other_prev;
+         struct Lisp_Overlay *other, *other_prev;
 
          /* Splice the cons cell TAIL out of overlays_after.  */
-         if (!NILP (prev))
-           XSETCDR (prev, next);
+         if (prev)
+           prev->next = 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 = XCDR (other))
+         other_prev = NULL;
+         for (other = buf->overlays_before; other;
+              other_prev = other, other = other->next)
            {
              Lisp_Object otherend, otheroverlay;
 
-             otheroverlay = XCAR (other);
-             if (! OVERLAY_VALID (otheroverlay))
-               abort ();
+             XSETMISC (otheroverlay, other);
+             eassert (OVERLAY_VALID (otheroverlay));
 
              otherend = OVERLAY_END (otheroverlay);
              if (OVERLAY_POSITION (otherend) <= where)
@@ -3206,45 +3238,43 @@ recenter_overlay_lists (buf, pos)
            }
 
          /* Add TAIL to overlays_before before OTHER.  */
-         XSETCDR (tail, other);
-         if (!NILP (other_prev))
-           XSETCDR (other_prev, tail);
+         tail->next = other;
+         if (other_prev)
+           other_prev->next = tail;
          else
            buf->overlays_before = tail;
          tail = prev;
        }
     }
 
-  XSETFASTINT (buf->overlay_center, pos);
+  buf->overlay_center = pos;
 }
 
 void
 adjust_overlays_for_insert (pos, length)
-     int pos;
-     int length;
+     EMACS_INT pos;
+     EMACS_INT length;
 {
   /* After an insertion, the lists are still sorted properly,
      but we may need to update the value of the overlay center.  */
-  if (XFASTINT (current_buffer->overlay_center) >= pos)
-    XSETFASTINT (current_buffer->overlay_center,
-                XFASTINT (current_buffer->overlay_center) + length);
+  if (current_buffer->overlay_center >= pos)
+    current_buffer->overlay_center += length;
 }
 
 void
 adjust_overlays_for_delete (pos, length)
-     int pos;
-     int length;
+     EMACS_INT pos;
+     EMACS_INT length;
 {
-  if (XFASTINT (current_buffer->overlay_center) < pos)
+  if (current_buffer->overlay_center < pos)
     /* The deletion was to our right.  No change needed; the before- and
        after-lists are still consistent.  */
     ;
-  else if (XFASTINT (current_buffer->overlay_center) > pos + length)
+  else if (current_buffer->overlay_center > pos + length)
     /* The deletion was to our left.  We need to adjust the center value
        to account for the change in position, but the lists are consistent
        given the new value.  */
-    XSETFASTINT (current_buffer->overlay_center,
-                XFASTINT (current_buffer->overlay_center) - length);
+    current_buffer->overlay_center -= length;
   else
     /* We're right in the middle.  There might be things on the after-list
        that now belong on the before-list.  Recentering will move them,
@@ -3264,15 +3294,15 @@ fix_overlays_in_range (start, end)
      register int start, end;
 {
   Lisp_Object overlay;
-  Lisp_Object before_list, after_list;
+  struct Lisp_Overlay *before_list, *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;
+  struct Lisp_Overlay *beforep = NULL, *afterp = NULL;
   /* 'Parent', likewise, indicates a cons cell or
      current_buffer->overlays_before or overlays_after, depending
      which loop we're in.  */
-  Lisp_Object tail, parent;
+  struct Lisp_Overlay *tail, *parent;
   int startpos, endpos;
 
   /* This algorithm shifts links around instead of consing and GCing.
@@ -3282,9 +3312,9 @@ fix_overlays_in_range (start, end)
      (after_list) if it is, is still uninitialized.  So it's not a bug
      that before_list isn't initialized, although it may look
      strange.  */
-  for (parent = Qnil, tail = current_buffer->overlays_before; CONSP (tail);)
+  for (parent = NULL, tail = current_buffer->overlays_before; tail;)
     {
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
       if (endpos < start)
        break;
@@ -3304,34 +3334,34 @@ fix_overlays_in_range (start, end)
            }
          /* 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))
+         if (endpos < current_buffer->overlay_center)
            {
-             if (NILP (afterp))
+             if (!afterp)
                after_list = tail;
              else
-               XSETCDR (afterp, tail);
+               afterp->next = tail;
              afterp = tail;
            }
          else
            {
-             if (NILP (beforep))
+             if (!beforep)
                before_list = tail;
              else
-               XSETCDR (beforep, tail);
+               beforep->next = tail;
              beforep = tail;
            }
-         if (NILP (parent))
-           current_buffer->overlays_before = XCDR (tail);
+         if (!parent)
+           current_buffer->overlays_before = tail->next;
          else
-           XSETCDR (parent, XCDR (tail));
-         tail = XCDR (tail);
+           parent->next = tail->next;
+         tail = tail->next;
        }
       else
-       parent = tail, tail = XCDR (parent);
+       parent = tail, tail = parent->next;
     }
-  for (parent = Qnil, tail = current_buffer->overlays_after; CONSP (tail);)
+  for (parent = NULL, tail = current_buffer->overlays_after; tail;)
     {
-      overlay = XCAR (tail);
+      XSETMISC (overlay, tail);
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
       if (startpos >= end)
        break;
@@ -3348,49 +3378,47 @@ fix_overlays_in_range (start, end)
                           Qnil);
              tem = startpos; startpos = endpos; endpos = tem;
            }
-         if (endpos < XINT (current_buffer->overlay_center))
+         if (endpos < current_buffer->overlay_center)
            {
-             if (NILP (afterp))
+             if (!afterp)
                after_list = tail;
              else
-               XSETCDR (afterp, tail);
+               afterp->next = tail;
              afterp = tail;
            }
          else
            {
-             if (NILP (beforep))
+             if (!beforep)
                before_list = tail;
              else
-               XSETCDR (beforep, tail);
+               beforep->next = tail;
              beforep = tail;
            }
-         if (NILP (parent))
-           current_buffer->overlays_after = XCDR (tail);
+         if (!parent)
+           current_buffer->overlays_after = tail->next;
          else
-           XSETCDR (parent, XCDR (tail));
-         tail = XCDR (tail);
+           parent->next = tail->next;
+         tail = tail->next;
        }
       else
-       parent = tail, tail = XCDR (parent);
+       parent = tail, tail = parent->next;
     }
 
   /* Splice the constructed (wrong) lists into the buffer's lists,
      and let the recenter function make it sane again.  */
-  if (!NILP (beforep))
+  if (beforep)
     {
-      XSETCDR (beforep, current_buffer->overlays_before);
+      beforep->next = current_buffer->overlays_before;
       current_buffer->overlays_before = before_list;
     }
-  recenter_overlay_lists (current_buffer,
-                         XINT (current_buffer->overlay_center));
+  recenter_overlay_lists (current_buffer, current_buffer->overlay_center);
 
-  if (!NILP (afterp))
+  if (afterp)
     {
-      XSETCDR (afterp, current_buffer->overlays_after);
+      afterp->next = current_buffer->overlays_after;
       current_buffer->overlays_after = after_list;
     }
-  recenter_overlay_lists (current_buffer,
-                         XINT (current_buffer->overlay_center));
+  recenter_overlay_lists (current_buffer, current_buffer->overlay_center);
 }
 
 /* We have two types of overlay: the one whose ending marker is
@@ -3408,12 +3436,12 @@ fix_overlays_in_range (start, end)
 void
 fix_overlays_before (bp, prev, pos)
      struct buffer *bp;
-     int prev, pos;
+     EMACS_INT prev, pos;
 {
-  /* If parent is nil, replace overlays_before; otherwise, XCDR(parent).  */
-  Lisp_Object tail = bp->overlays_before, parent = Qnil;
-  Lisp_Object right_pair;
-  int end;
+  /* If parent is nil, replace overlays_before; otherwise, parent->next.  */
+  struct Lisp_Overlay *tail = bp->overlays_before, *parent = NULL, *right_pair;
+  Lisp_Object tem;
+  EMACS_INT end;
 
   /* After the insertion, the several overlays may be in incorrect
      order.  The possibility is that, in the list `overlays_before',
@@ -3426,60 +3454,59 @@ fix_overlays_before (bp, prev, pos)
      in.  It is where an overlay which end before POS exists. (i.e. an
      overlay whose ending marker is after-insertion-marker if disorder
      exists).  */
-  while (!NILP (tail)
-        && ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail))))
-            >= pos))
+  while (tail
+        && (XSETMISC (tem, tail),
+            (end = OVERLAY_POSITION (OVERLAY_END (tem))) >= pos))
     {
       parent = tail;
-      tail = XCDR (tail);
+      tail = tail->next;
     }
 
   /* If we don't find such an overlay,
      or the found one ends before PREV,
      or the found one is the last one in the list,
      we don't have to fix anything.  */
-  if (NILP (tail)
-      || end < prev
-      || NILP (XCDR (tail)))
+  if (!tail || end < prev || !tail->next)
     return;
 
   right_pair = parent;
   parent = tail;
-  tail = XCDR (tail);
+  tail = tail->next;
 
   /* 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
      moved ahead to the place indicated by the CDR of RIGHT_PAIR.  If
      we found an overlay which ends before PREV, the remaining
      overlays are in correct order.  */
-  while (!NILP (tail))
+  while (tail)
     {
-      end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail)));
+      XSETMISC (tem, tail);
+      end = OVERLAY_POSITION (OVERLAY_END (tem));
 
       if (end == pos)
        {                       /* This overlay is disordered. */
-         Lisp_Object found = tail;
+         struct Lisp_Overlay *found = tail;
 
          /* Unlink the found overlay.  */
-         tail = XCDR (found);
-         XSETCDR (parent, tail);
+         tail = found->next;
+         parent->next = tail;
          /* Move an overlay at RIGHT_PLACE to the next of the found one,
             and link it into the right place.  */
-         if (NILP (right_pair))
+         if (!right_pair)
            {
-             XSETCDR (found, bp->overlays_before);
+             found->next = bp->overlays_before;
              bp->overlays_before = found;
            }
          else
            {
-             XSETCDR (found, XCDR (right_pair));
-             XSETCDR (right_pair, found);
+             found->next = right_pair->next;
+             right_pair->next = found;
            }
        }
       else if (end == prev)
        {
          parent = tail;
-         tail = XCDR (tail);
+         tail = tail->next;
        }
       else                     /* No more disordered overlay. */
        break;
@@ -3544,16 +3571,25 @@ rear delimiter advance when text is inserted there.  */)
   XOVERLAY (overlay)->start = beg;
   XOVERLAY (overlay)->end = end;
   XOVERLAY (overlay)->plist = Qnil;
+  XOVERLAY (overlay)->next = NULL;
 
-  /* Put the new overlay on the wrong list.  */ 
+  /* 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);
+  if (OVERLAY_POSITION (end) < b->overlay_center)
+    {
+      if (b->overlays_after)
+       XOVERLAY (overlay)->next = b->overlays_after;
+      b->overlays_after = XOVERLAY (overlay);
+    }
   else
-    b->overlays_before = Fcons (overlay, b->overlays_before);
+    {
+      if (b->overlays_before)
+       XOVERLAY (overlay)->next = b->overlays_before;
+      b->overlays_before = XOVERLAY (overlay);
+    }
 
   /* This puts it in the right list, and in the right order.  */
-  recenter_overlay_lists (b, XINT (b->overlay_center));
+  recenter_overlay_lists (b, b->overlay_center);
 
   /* We don't need to redisplay the region covered by the overlay, because
      the overlay has no properties at the moment.  */
@@ -3566,7 +3602,7 @@ rear delimiter advance when text is inserted there.  */)
 static void
 modify_overlay (buf, start, end)
      struct buffer *buf;
-     int start, end;
+     EMACS_INT start, end;
 {
   if (start > end)
     {
@@ -3576,7 +3612,7 @@ modify_overlay (buf, start, end)
     }
 
   BUF_COMPUTE_UNCHANGED (buf, start, end);
-  
+
   /* If this is a buffer not in the selected window,
      we must do other windows.  */
   if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
@@ -3591,6 +3627,24 @@ modify_overlay (buf, start, end)
 \f
 Lisp_Object Fdelete_overlay ();
 
+static struct Lisp_Overlay *
+unchain_overlay (list, overlay)
+     struct Lisp_Overlay *list, *overlay;
+{
+  struct Lisp_Overlay *tmp, *prev;
+  for (tmp = list, prev = NULL; tmp; prev = tmp, tmp = tmp->next)
+    if (tmp == overlay)
+      {
+       if (prev)
+         prev->next = tmp->next;
+       else
+         list = tmp->next;
+       overlay->next = NULL;
+       break;
+      }
+  return list;
+}
+
 DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0,
        doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER.
 If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.
@@ -3675,22 +3729,31 @@ buffer.  */)
 
   if (!NILP (obuffer))
     {
-      ob->overlays_before = Fdelq (overlay, ob->overlays_before);
-      ob->overlays_after  = Fdelq (overlay, ob->overlays_after);
+      ob->overlays_before
+       = unchain_overlay (ob->overlays_before, XOVERLAY (overlay));
+      ob->overlays_after
+       = unchain_overlay (ob->overlays_after, XOVERLAY (overlay));
+      eassert (XOVERLAY (overlay)->next == NULL);
     }
 
   Fset_marker (OVERLAY_START (overlay), beg, buffer);
   Fset_marker (OVERLAY_END   (overlay), end, buffer);
 
-  /* Put the overlay on the wrong list.  */ 
+  /* 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);
+  if (OVERLAY_POSITION (end) < b->overlay_center)
+    {
+      XOVERLAY (overlay)->next = b->overlays_after;
+      b->overlays_after = XOVERLAY (overlay);
+    }
   else
-    b->overlays_before = Fcons (overlay, b->overlays_before);
+    {
+      XOVERLAY (overlay)->next = b->overlays_before;
+      b->overlays_before = XOVERLAY (overlay);
+    }
 
   /* This puts it in the right list, and in the right order.  */
-  recenter_overlay_lists (b, XINT (b->overlay_center));
+  recenter_overlay_lists (b, b->overlay_center);
 
   return unbind_to (count, overlay);
 }
@@ -3712,9 +3775,10 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
 
   b = XBUFFER (buffer);
   specbind (Qinhibit_quit, Qt);
-  
-  b->overlays_before = Fdelq (overlay, b->overlays_before);
-  b->overlays_after = Fdelq (overlay, b->overlays_after);
+
+  b->overlays_before = unchain_overlay (b->overlays_before,XOVERLAY (overlay));
+  b->overlays_after  = unchain_overlay (b->overlays_after, XOVERLAY (overlay));
+  eassert (XOVERLAY (overlay)->next == NULL);
   modify_overlay (b,
                  marker_position (OVERLAY_START (overlay)),
                  marker_position (OVERLAY_END   (overlay)));
@@ -3922,19 +3986,25 @@ The lists you get are copies, so that changing them has no effect.
 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);
+  struct Lisp_Overlay *ol;
+  Lisp_Object before = Qnil, after = Qnil, tmp;
+  for (ol = current_buffer->overlays_before; ol; ol = ol->next)
+    {
+      XSETMISC (tmp, ol);
+      before = Fcons (tmp, before);
+    }
+  for (ol = current_buffer->overlays_after; ol; ol = ol->next)
+    {
+      XSETMISC (tmp, ol);
+      after = Fcons (tmp, after);
+    }
+  return Fcons (Fnreverse (before), Fnreverse (after));
 }
 
 DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
-       doc: /* Recenter the overlays of the current buffer around position POS.  */)
+       doc: /* Recenter the overlays of the current buffer around position POS.
+That makes overlay lookup faster for positions near POS (but perhaps slower
+for positions far away from POS).  */)
      (pos)
      Lisp_Object pos;
 {
@@ -4028,8 +4098,8 @@ add_overlay_mod_hooklist (functionlist, overlay)
             XVECTOR (last_overlay_modification_hooks)->contents,
             sizeof (Lisp_Object) * oldsize);
     }
-  XVECTOR (last_overlay_modification_hooks)->contents[last_overlay_modification_hooks_used++] = functionlist;
-  XVECTOR (last_overlay_modification_hooks)->contents[last_overlay_modification_hooks_used++] = overlay;
+  AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = functionlist;
+  AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = overlay;
 }
 \f
 /* Run the modification-hooks of overlays that include
@@ -4052,156 +4122,125 @@ report_overlay_modification (start, end, after, arg1, arg2, arg3)
      int after;
      Lisp_Object arg1, arg2, arg3;
 {
-  Lisp_Object prop, overlay, tail;
+  Lisp_Object prop, overlay;
+  struct Lisp_Overlay *tail;
   /* 1 if this change is an insertion.  */
   int insertion = (after ? XFASTINT (arg3) == 0 : EQ (start, end));
-  int tail_copied;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   overlay = Qnil;
-  tail = Qnil;
-  GCPRO5 (overlay, tail, arg1, arg2, arg3);
-
-  if (after)
-    {
-      /* Call the functions recorded in last_overlay_modification_hooks
-        rather than scanning the overlays again.
-        First copy the vector contents, in case some of these hooks
-        do subsequent modification of the buffer.  */
-      int size = last_overlay_modification_hooks_used;
-      Lisp_Object *copy = (Lisp_Object *) alloca (size * sizeof (Lisp_Object));
-      int i;
-
-      bcopy (XVECTOR (last_overlay_modification_hooks)->contents,
-            copy, size * sizeof (Lisp_Object));
-      gcpro1.var = copy;
-      gcpro1.nvars = size;
+  tail = NULL;
 
-      for (i = 0; i < size;)
-       {
-         Lisp_Object prop, overlay;
-         prop = copy[i++];
-         overlay = copy[i++];
-         call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
-       }
-      UNGCPRO;
-      return;
-    }
+  /* We used to run the functions as soon as we found them and only register
+     them in last_overlay_modification_hooks for the purpose of the `after'
+     case.  But running elisp code as we traverse the list of overlays is
+     painful because the list can be modified by the elisp code so we had to
+     copy at several places.  We now simply do a read-only traversal that
+     only collects the functions to run and we run them afterwards.  It's
+     simpler, especially since all the code was already there.  -stef  */
 
-  /* We are being called before a change.
-     Scan the overlays to find the functions to call.  */
-  last_overlay_modification_hooks_used = 0;
-  tail_copied = 0;
-  for (tail = current_buffer->overlays_before;
-       CONSP (tail);
-       tail = XCDR (tail))
+  if (!after)
     {
-      int startpos, endpos;
-      Lisp_Object ostart, oend;
-
-      overlay = XCAR (tail);
-
-      ostart = OVERLAY_START (overlay);
-      oend = OVERLAY_END (overlay);
-      endpos = OVERLAY_POSITION (oend);
-      if (XFASTINT (start) > endpos)
-       break;
-      startpos = OVERLAY_POSITION (ostart);
-      if (insertion && (XFASTINT (start) == startpos
-                       || XFASTINT (end) == startpos))
+      /* We are being called before a change.
+        Scan the overlays to find the functions to call.  */
+      last_overlay_modification_hooks_used = 0;
+      for (tail = current_buffer->overlays_before; tail; tail = tail->next)
        {
-         prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
-         if (!NILP (prop))
+         int startpos, endpos;
+         Lisp_Object ostart, oend;
+
+         XSETMISC (overlay, tail);
+
+         ostart = OVERLAY_START (overlay);
+         oend = OVERLAY_END (overlay);
+         endpos = OVERLAY_POSITION (oend);
+         if (XFASTINT (start) > endpos)
+           break;
+         startpos = OVERLAY_POSITION (ostart);
+         if (insertion && (XFASTINT (start) == startpos
+                           || XFASTINT (end) == startpos))
            {
-             /* Copy TAIL in case the hook recenters the overlay lists.  */
-             if (!tail_copied)
-               tail = Fcopy_sequence (tail);
-             tail_copied = 1;
-             call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+             prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
+             if (!NILP (prop))
+               add_overlay_mod_hooklist (prop, overlay);
            }
-       }
-      if (insertion && (XFASTINT (start) == endpos
-                       || XFASTINT (end) == endpos))
-       {
-         prop = Foverlay_get (overlay, Qinsert_behind_hooks);
-         if (!NILP (prop))
+         if (insertion && (XFASTINT (start) == endpos
+                           || XFASTINT (end) == endpos))
            {
-             if (!tail_copied)
-               tail = Fcopy_sequence (tail);
-             tail_copied = 1;
-             call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+             prop = Foverlay_get (overlay, Qinsert_behind_hooks);
+             if (!NILP (prop))
+               add_overlay_mod_hooklist (prop, overlay);
            }
-       }
-      /* Test for intersecting intervals.  This does the right thing
-        for both insertion and deletion.  */
-      if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
-       {
-         prop = Foverlay_get (overlay, Qmodification_hooks);
-         if (!NILP (prop))
+         /* Test for intersecting intervals.  This does the right thing
+            for both insertion and deletion.  */
+         if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
            {
-             if (!tail_copied)
-               tail = Fcopy_sequence (tail);
-             tail_copied = 1;
-             call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+             prop = Foverlay_get (overlay, Qmodification_hooks);
+             if (!NILP (prop))
+               add_overlay_mod_hooklist (prop, overlay);
            }
        }
-    }
-
-  tail_copied = 0;
-  for (tail = current_buffer->overlays_after;
-       CONSP (tail);
-       tail = XCDR (tail))
-    {
-      int startpos, endpos;
-      Lisp_Object ostart, oend;
-
-      overlay = XCAR (tail);
-
-      ostart = OVERLAY_START (overlay);
-      oend = OVERLAY_END (overlay);
-      startpos = OVERLAY_POSITION (ostart);
-      endpos = OVERLAY_POSITION (oend);
-      if (XFASTINT (end) < startpos)
-       break;
-      if (insertion && (XFASTINT (start) == startpos
-                       || XFASTINT (end) == startpos))
+      
+      for (tail = current_buffer->overlays_after; tail; tail = tail->next)
        {
-         prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
-         if (!NILP (prop))
+         int startpos, endpos;
+         Lisp_Object ostart, oend;
+
+         XSETMISC (overlay, tail);
+
+         ostart = OVERLAY_START (overlay);
+         oend = OVERLAY_END (overlay);
+         startpos = OVERLAY_POSITION (ostart);
+         endpos = OVERLAY_POSITION (oend);
+         if (XFASTINT (end) < startpos)
+           break;
+         if (insertion && (XFASTINT (start) == startpos
+                           || XFASTINT (end) == startpos))
            {
-             if (!tail_copied)
-               tail = Fcopy_sequence (tail);
-             tail_copied = 1;
-             call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+             prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
+             if (!NILP (prop))
+               add_overlay_mod_hooklist (prop, overlay);
            }
-       }
-      if (insertion && (XFASTINT (start) == endpos
-                       || XFASTINT (end) == endpos))
-       {
-         prop = Foverlay_get (overlay, Qinsert_behind_hooks);
-         if (!NILP (prop))
+         if (insertion && (XFASTINT (start) == endpos
+                           || XFASTINT (end) == endpos))
            {
-             if (!tail_copied)
-               tail = Fcopy_sequence (tail);
-             tail_copied = 1;
-             call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+             prop = Foverlay_get (overlay, Qinsert_behind_hooks);
+             if (!NILP (prop))
+               add_overlay_mod_hooklist (prop, overlay);
            }
-       }
-      /* Test for intersecting intervals.  This does the right thing
-        for both insertion and deletion.  */
-      if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
-       {
-         prop = Foverlay_get (overlay, Qmodification_hooks);
-         if (!NILP (prop))
+         /* Test for intersecting intervals.  This does the right thing
+            for both insertion and deletion.  */
+         if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
            {
-             if (!tail_copied)
-               tail = Fcopy_sequence (tail);
-             tail_copied = 1;
-             call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+             prop = Foverlay_get (overlay, Qmodification_hooks);
+             if (!NILP (prop))
+               add_overlay_mod_hooklist (prop, overlay);
            }
        }
     }
 
+  GCPRO4 (overlay, arg1, arg2, arg3);
+  {
+    /* Call the functions recorded in last_overlay_modification_hooks.
+       First copy the vector contents, in case some of these hooks
+       do subsequent modification of the buffer.  */
+    int size = last_overlay_modification_hooks_used;
+    Lisp_Object *copy = (Lisp_Object *) alloca (size * sizeof (Lisp_Object));
+    int i;
+
+    bcopy (XVECTOR (last_overlay_modification_hooks)->contents,
+          copy, size * sizeof (Lisp_Object));
+    gcpro1.var = copy;
+    gcpro1.nvars = size;
+
+    for (i = 0; i < size;)
+      {
+       Lisp_Object prop, overlay;
+       prop = copy[i++];
+       overlay = copy[i++];
+       call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
+      }
+  }
   UNGCPRO;
 }
 
@@ -4214,8 +4253,6 @@ call_overlay_mod_hooks (list, overlay, after, arg1, arg2, arg3)
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   GCPRO4 (list, arg1, arg2, arg3);
-  if (! after)
-    add_overlay_mod_hooklist (list, overlay);
 
   while (CONSP (list))
     {
@@ -4232,17 +4269,17 @@ call_overlay_mod_hooks (list, overlay, after, arg1, arg2, arg3)
    property is set.  */
 void
 evaporate_overlays (pos)
-     int pos;
+     EMACS_INT pos;
 {
-  Lisp_Object tail, overlay, hit_list;
+  Lisp_Object overlay, hit_list;
+  struct Lisp_Overlay *tail;
 
   hit_list = Qnil;
-  if (pos <= XFASTINT (current_buffer->overlay_center))
-    for (tail = current_buffer->overlays_before; CONSP (tail);
-        tail = XCDR (tail))
+  if (pos <= current_buffer->overlay_center)
+    for (tail = current_buffer->overlays_before; tail; tail = tail->next)
       {
        int endpos;
-       overlay = XCAR (tail);
+       XSETMISC (overlay, tail);
        endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
        if (endpos < pos)
          break;
@@ -4251,11 +4288,10 @@ evaporate_overlays (pos)
          hit_list = Fcons (overlay, hit_list);
       }
   else
-    for (tail = current_buffer->overlays_after; CONSP (tail);
-        tail = XCDR (tail))
+    for (tail = current_buffer->overlays_after; tail; tail = tail->next)
       {
        int startpos;
-       overlay = XCAR (tail);
+       XSETMISC (overlay, tail);
        startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
        if (startpos > pos)
          break;
@@ -4276,21 +4312,21 @@ buffer_slot_type_mismatch (offset)
 {
   Lisp_Object sym;
   char *type_name;
-  
+
   switch (XINT (PER_BUFFER_TYPE (offset)))
     {
     case Lisp_Int:
       type_name = "integers";
       break;
-      
+
     case Lisp_String:
       type_name = "strings";
       break;
-      
+
     case Lisp_Symbol:
       type_name = "symbols";
       break;
-      
+
     default:
       abort ();
     }
@@ -4353,7 +4389,7 @@ struct mmap_region
 {
   /* User-specified size.  */
   size_t nbytes_specified;
-  
+
   /* Number of bytes mapped */
   size_t nbytes_mapped;
 
@@ -4444,7 +4480,7 @@ mmap_find (start, end)
 {
   struct mmap_region *r;
   char *s = (char *) start, *e = (char *) end;
-  
+
   for (r = mmap_regions; r; r = r->next)
     {
       char *rstart = (char *) r;
@@ -4478,7 +4514,7 @@ mmap_free_1 (r)
     r->prev->next = r->next;
   else
     mmap_regions = r->next;
-  
+
   if (munmap ((POINTER_TYPE *) r, r->nbytes_mapped) == -1)
     {
       fprintf (stderr, "munmap: %s\n", emacs_strerror (errno));
@@ -4516,7 +4552,7 @@ mmap_enlarge (r, npages)
   else if (npages > 0)
     {
       nbytes = npages * mmap_page_size;
-      
+
       /* Try to map additional pages at the end of the region.  We
         cannot do this if the address range is already occupied by
         something else because mmap deletes any previous mapping.
@@ -4524,7 +4560,7 @@ mmap_enlarge (r, npages)
       if (!MMAP_ALLOCATED_P (region_end, region_end + nbytes))
        {
          POINTER_TYPE *p;
-      
+
          p = mmap (region_end, nbytes, PROT_READ | PROT_WRITE,
                    MAP_ANON | MAP_PRIVATE | MAP_FIXED, mmap_fd, 0);
          if (p == MAP_FAILED)
@@ -4605,7 +4641,7 @@ mmap_alloc (var, nbytes)
   map = ROUND (nbytes + MMAP_REGION_STRUCT_SIZE, mmap_page_size);
   p = mmap (NULL, map, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
            mmap_fd, 0);
-  
+
   if (p == MAP_FAILED)
     {
       if (errno != ENOMEM)
@@ -4615,7 +4651,7 @@ mmap_alloc (var, nbytes)
   else
     {
       struct mmap_region *r = (struct mmap_region *) p;
-      
+
       r->nbytes_specified = nbytes;
       r->nbytes_mapped = map;
       r->var = var;
@@ -4624,10 +4660,10 @@ mmap_alloc (var, nbytes)
       if (r->next)
        r->next->prev = r;
       mmap_regions = r;
-      
+
       p = MMAP_USER_AREA (p);
     }
-  
+
   return *var = p;
 }
 
@@ -4643,12 +4679,12 @@ mmap_realloc (var, nbytes)
      size_t nbytes;
 {
   POINTER_TYPE *result;
-  
+
   mmap_init ();
 
   if (*var == NULL)
     result = mmap_alloc (var, nbytes);
-  else if (nbytes == 0) 
+  else if (nbytes == 0)
     {
       mmap_free (var);
       result = mmap_alloc (var, nbytes);
@@ -4657,7 +4693,7 @@ mmap_realloc (var, nbytes)
     {
       struct mmap_region *r = MMAP_REGION (*var);
       size_t room = r->nbytes_mapped - MMAP_REGION_STRUCT_SIZE;
-      
+
       if (room < nbytes)
        {
          /* Must enlarge.  */
@@ -4718,7 +4754,7 @@ mmap_free (var)
      POINTER_TYPE **var;
 {
   mmap_init ();
-  
+
   if (*var)
     {
       mmap_free_1 (MMAP_REGION (*var));
@@ -4747,11 +4783,11 @@ mmap_init ()
   if (mmap_initialized_p)
     return;
   mmap_initialized_p = 1;
-  
+
 #if MAP_ANON != 0
   mmap_fd = -1;
 #endif
-  
+
   mmap_page_size = getpagesize ();
 }
 
@@ -4778,7 +4814,7 @@ alloc_buffer_text (b, nbytes)
      size_t nbytes;
 {
   POINTER_TYPE *p;
-  
+
   BLOCK_INPUT;
 #if defined USE_MMAP_FOR_BUFFERS
   p = mmap_alloc ((POINTER_TYPE **) &b->text->beg, nbytes);
@@ -4787,7 +4823,7 @@ alloc_buffer_text (b, nbytes)
 #else
   p = xmalloc (nbytes);
 #endif
-  
+
   if (p == NULL)
     {
       UNBLOCK_INPUT;
@@ -4817,7 +4853,7 @@ enlarge_buffer_text (b, delta)
 #else
   p = xrealloc (b->text->beg, nbytes);
 #endif
-  
+
   if (p == NULL)
     {
       UNBLOCK_INPUT;
@@ -4844,7 +4880,7 @@ free_buffer_text (b)
 #else
   xfree (b->text->beg);
 #endif
-  
+
   BUF_BEG_ADDR (b) = NULL;
   UNBLOCK_INPUT;
 }
@@ -4895,9 +4931,9 @@ init_buffer_once ()
   buffer_defaults.undo_list = Qnil;
   buffer_defaults.mark_active = Qnil;
   buffer_defaults.file_format = Qnil;
-  buffer_defaults.overlays_before = Qnil;
-  buffer_defaults.overlays_after = Qnil;
-  XSETFASTINT (buffer_defaults.overlay_center, BEG);
+  buffer_defaults.overlays_before = NULL;
+  buffer_defaults.overlays_after = NULL;
+  buffer_defaults.overlay_center = BEG;
 
   XSETFASTINT (buffer_defaults.tab_width, 8);
   buffer_defaults.truncate_lines = Qnil;
@@ -4916,7 +4952,15 @@ init_buffer_once ()
   buffer_defaults.cache_long_line_scans = Qnil;
   buffer_defaults.file_truename = Qnil;
   XSETFASTINT (buffer_defaults.display_count, 0);
+  XSETFASTINT (buffer_defaults.left_margin_cols, 0);
+  XSETFASTINT (buffer_defaults.right_margin_cols, 0);
+  buffer_defaults.left_fringe_width = Qnil;
+  buffer_defaults.right_fringe_width = Qnil;
+  buffer_defaults.fringes_outside_margins = Qnil;
+  buffer_defaults.scroll_bar_width = Qnil;
+  buffer_defaults.vertical_scroll_bar_type = Qt;
   buffer_defaults.indicate_empty_lines = Qnil;
+  buffer_defaults.indicate_buffer_boundaries = Qnil;
   buffer_defaults.scroll_up_aggressively = Qnil;
   buffer_defaults.scroll_down_aggressively = Qnil;
   buffer_defaults.display_time = Qnil;
@@ -4975,12 +5019,18 @@ init_buffer_once ()
   XSETFASTINT (buffer_local_flags.cache_long_line_scans, idx); ++idx;
   XSETFASTINT (buffer_local_flags.category_table, idx); ++idx;
   XSETFASTINT (buffer_local_flags.direction_reversed, idx); ++idx;
-  XSETFASTINT (buffer_local_flags.buffer_file_coding_system, idx); 
+  XSETFASTINT (buffer_local_flags.buffer_file_coding_system, idx);
   /* Make this one a permanent local.  */
   buffer_permanent_local_flags[idx++] = 1;
-  XSETFASTINT (buffer_local_flags.left_margin_width, idx); ++idx;
-  XSETFASTINT (buffer_local_flags.right_margin_width, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.left_margin_cols, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.right_margin_cols, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.left_fringe_width, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.right_fringe_width, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.fringes_outside_margins, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.scroll_bar_width, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.vertical_scroll_bar_type, idx); ++idx;
   XSETFASTINT (buffer_local_flags.indicate_empty_lines, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.indicate_buffer_boundaries, idx); ++idx;
   XSETFASTINT (buffer_local_flags.scroll_up_aggressively, idx); ++idx;
   XSETFASTINT (buffer_local_flags.scroll_down_aggressively, idx); ++idx;
   XSETFASTINT (buffer_local_flags.header_line_format, idx); ++idx;
@@ -4991,7 +5041,7 @@ init_buffer_once ()
   if (idx >= MAX_PER_BUFFER_VARS)
     abort ();
   last_per_buffer_idx = idx;
-  
+
   Vbuffer_alist = Qnil;
   current_buffer = 0;
   all_buffers = 0;
@@ -5008,6 +5058,7 @@ init_buffer_once ()
   Qpermanent_local = intern ("permanent-local");
 
   Qkill_buffer_hook = intern ("kill-buffer-hook");
+  Fput (Qkill_buffer_hook, Qpermanent_local, Qt);
 
   Qucs_set_table_for_input = intern ("ucs-set-table-for-input");
 
@@ -5036,13 +5087,13 @@ init_buffer ()
       text pointers will have been set to null in the dumped Emacs.
       Map new memory.  */
    struct buffer *b;
-   
+
    for (b = all_buffers; b; b = b->next)
      if (b->text->beg == NULL)
        enlarge_buffer_text (b, 0);
  }
 #endif /* USE_MMAP_FOR_BUFFERS */
-  
+
   Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
   if (NILP (buffer_defaults.enable_multibyte_characters))
     Fset_buffer_multibyte (Qnil);
@@ -5140,6 +5191,9 @@ syms_of_buffer ()
   staticpro (&Qafter_change_functions);
   staticpro (&Qucs_set_table_for_input);
 
+  Qkill_buffer_query_functions = intern ("kill-buffer-query-functions");
+  staticpro (&Qkill_buffer_query_functions);
+
   Fput (Qprotected_field, Qerror_conditions,
        Fcons (Qprotected_field, Fcons (Qerror, Qnil)));
   Fput (Qprotected_field, Qerror_message,
@@ -5179,19 +5233,19 @@ This is the same as (default-value 'ctl-arrow).  */);
 
    DEFVAR_LISP_NOPRO ("default-direction-reversed",
                      &buffer_defaults.direction_reversed,
-                     doc: /* Default value of `direction_reversed' for buffers that do not override it.
+                     doc: /* Default value of `direction-reversed' for buffers that do not override it.
 This is the same as (default-value 'direction-reversed).  */);
+
    DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
                      &buffer_defaults.enable_multibyte_characters,
                      doc: /* *Default value of `enable-multibyte-characters' for buffers not overriding it.
 This is the same as (default-value 'enable-multibyte-characters).  */);
+
    DEFVAR_LISP_NOPRO ("default-buffer-file-coding-system",
                      &buffer_defaults.buffer_file_coding_system,
                      doc: /* Default value of `buffer-file-coding-system' for buffers not overriding it.
 This is the same as (default-value 'buffer-file-coding-system).  */);
+
   DEFVAR_LISP_NOPRO ("default-truncate-lines",
                     &buffer_defaults.truncate_lines,
                     doc: /* Default value of `truncate-lines' for buffers that do not override it.
@@ -5218,7 +5272,7 @@ This is the same as (default-value 'tab-width).  */);
 This is the same as (default-value 'case-fold-search).  */);
 
 #ifdef DOS_NT
-  DEFVAR_LISP_NOPRO ("default-buffer-file-type", 
+  DEFVAR_LISP_NOPRO ("default-buffer-file-type",
                     &buffer_defaults.buffer_file_type,
                     doc: /* Default file type for buffers that do not override it.
 This is the same as (default-value 'buffer-file-type).
@@ -5226,39 +5280,69 @@ The file type is nil for text, t for binary.  */);
 #endif
 
   DEFVAR_LISP_NOPRO ("default-left-margin-width",
-                    &buffer_defaults.left_margin_width,
+                    &buffer_defaults.left_margin_cols,
                     doc: /* Default value of `left-margin-width' for buffers that don't override it.
 This is the same as (default-value 'left-margin-width).  */);
 
   DEFVAR_LISP_NOPRO ("default-right-margin-width",
-                    &buffer_defaults.right_margin_width,
-                    doc: /* Default value of `right_margin_width' for buffers that don't override it.
+                    &buffer_defaults.right_margin_cols,
+                    doc: /* Default value of `right-margin-width' for buffers that don't override it.
 This is the same as (default-value 'right-margin-width).  */);
-  
+
+  DEFVAR_LISP_NOPRO ("default-left-fringe-width",
+                    &buffer_defaults.left_fringe_width,
+                    doc: /* Default value of `left-fringe-width' for buffers that don't override it.
+This is the same as (default-value 'left-fringe-width).  */);
+
+  DEFVAR_LISP_NOPRO ("default-right-fringe-width",
+                    &buffer_defaults.right_fringe_width,
+                    doc: /* Default value of `right-fringe-width' for buffers that don't override it.
+This is the same as (default-value 'right-fringe-width).  */);
+
+  DEFVAR_LISP_NOPRO ("default-fringes-outside-margins",
+                    &buffer_defaults.fringes_outside_margins,
+                    doc: /* Default value of `fringes-outside-margins' for buffers that don't override it.
+This is the same as (default-value 'fringes-outside-margins).  */);
+
+  DEFVAR_LISP_NOPRO ("default-scroll-bar-width",
+                    &buffer_defaults.scroll_bar_width,
+                    doc: /* Default value of `scroll-bar-width' for buffers that don't override it.
+This is the same as (default-value 'scroll-bar-width).  */);
+
+  DEFVAR_LISP_NOPRO ("default-vertical-scroll-bar",
+                    &buffer_defaults.vertical_scroll_bar_type,
+                    doc: /* Default value of `vertical-scroll-bar' for buffers that don't override it.
+This is the same as (default-value 'vertical-scroll-bar).  */);
+
   DEFVAR_LISP_NOPRO ("default-indicate-empty-lines",
                     &buffer_defaults.indicate_empty_lines,
                     doc: /* Default value of `indicate-empty-lines' for buffers that don't override it.
 This is the same as (default-value 'indicate-empty-lines).  */);
-  
+
+  DEFVAR_LISP_NOPRO ("default-indicate-buffer-boundaries",
+                    &buffer_defaults.indicate_buffer_boundaries,
+                    doc: /* Default value of `indicate-buffer-boundaries' for buffers that don't override it.
+This is the same as (default-value 'indicate-buffer-boundaries).  */);
+
   DEFVAR_LISP_NOPRO ("default-scroll-up-aggressively",
                     &buffer_defaults.scroll_up_aggressively,
                     doc: /* Default value of `scroll-up-aggressively'.
 This value applies in buffers that don't have their own local values.
 This variable is an alias for (default-value 'scroll-up-aggressively).  */);
-  
+
   DEFVAR_LISP_NOPRO ("default-scroll-down-aggressively",
                     &buffer_defaults.scroll_down_aggressively,
                     doc: /* Default value of `scroll-down-aggressively'.
 This value applies in buffers that don't have their own local values.
 This variable is an alias for (default-value 'scroll-down-aggressively).  */);
-  
+
   DEFVAR_PER_BUFFER ("header-line-format",
                     &current_buffer->header_line_format,
                     Qnil,
                     doc: /* Analogous to `mode-line-format', but controls the header line.
 The header line appears, optionally, at the top of a window;
 the mode line appears at the bottom.  */);
-  
+
   DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format,
                     Qnil,
                     doc: /* Template for displaying mode line for current buffer.
@@ -5269,7 +5353,7 @@ For a symbol, its value is used (but it is ignored if t or nil).
  A string appearing directly as the value of a symbol is processed verbatim
  in that the %-constructs below are not recognized.
  Note that unless the symbol is marked as a `risky-local-variable', all
- properties in any strings, as well as all :eval and :propertize forms 
+ properties in any strings, as well as all :eval and :propertize forms
  in the value of that symbol will be ignored.
 For a list of the form `(:eval FORM)', FORM is evaluated and the result
  is used as a mode line element.  Be careful--FORM should not load any files,
@@ -5297,6 +5381,8 @@ A string is printed verbatim in the mode line except for %-constructs:
   %c -- print the current column number (this makes editing slower).
         To make the column number update correctly in all cases,
        `column-number-mode' must be non-nil.
+  %i -- print the size of the buffer.
+  %I -- like %i, but use k, M, G, etc., to abbreviate.
   %p -- print percent of buffer above top of window, or Top, Bot or All.
   %P -- print percent of buffer above bottom of window, perhaps plus Top,
         or print Bottom or All.
@@ -5349,7 +5435,7 @@ in the current display table (if there is one).  */);
 
   DEFVAR_PER_BUFFER ("enable-multibyte-characters",
                     &current_buffer->enable_multibyte_characters,
-                    make_number (-1),
+                    Qnil,
                     doc: /* Non-nil means the buffer contents are regarded as multi-byte characters.
 Otherwise they are regarded as unibyte.  This affects the display,
 file I/O and the behavior of various editing commands.
@@ -5359,6 +5445,7 @@ use the function `set-buffer-multibyte' to change a buffer's representation.
 Changing its default value with `setq-default' is supported.
 See also variable `default-enable-multibyte-characters' and Info node
 `(elisp)Text Representations'.  */);
+  XSYMBOL (intern ("enable-multibyte-characters"))->constant = 1;
 
   DEFVAR_PER_BUFFER ("buffer-file-coding-system",
                     &current_buffer->buffer_file_coding_system, Qnil,
@@ -5502,22 +5589,59 @@ In addition, a char-table has six extra slots to control the display of:
 
 See also the functions `display-table-slot' and `set-display-table-slot'.  */);
 
-  DEFVAR_PER_BUFFER ("left-margin-width", &current_buffer->left_margin_width,
+  DEFVAR_PER_BUFFER ("left-margin-width", &current_buffer->left_margin_cols,
                     Qnil,
                     doc: /* *Width of left marginal area for display of a buffer.
 A value of nil means no marginal area.  */);
-  
-  DEFVAR_PER_BUFFER ("right-margin-width", &current_buffer->right_margin_width,
+
+  DEFVAR_PER_BUFFER ("right-margin-width", &current_buffer->right_margin_cols,
                     Qnil,
                     doc: /* *Width of right marginal area for display of a buffer.
 A value of nil means no marginal area.  */);
-  
+
+  DEFVAR_PER_BUFFER ("left-fringe-width", &current_buffer->left_fringe_width,
+                    Qnil,
+                    doc: /* *Width of this buffer's left fringe (in pixels).
+A value of 0 means no left fringe is shown in this buffer's window.
+A value of nil means to use the left fringe width from the window's frame.  */);
+
+  DEFVAR_PER_BUFFER ("right-fringe-width", &current_buffer->right_fringe_width,
+                    Qnil,
+                    doc: /* *Width of this buffer's right fringe (in pixels).
+A value of 0 means no right fringe is shown in this buffer's window.
+A value of nil means to use the right fringe width from the window's frame.  */);
+
+  DEFVAR_PER_BUFFER ("fringes-outside-margins", &current_buffer->fringes_outside_margins,
+                    Qnil,
+                    doc: /* *Non-nil means to display fringes outside display margins.
+A value of nil means to display fringes between margins and buffer text.  */);
+
+  DEFVAR_PER_BUFFER ("scroll-bar-width", &current_buffer->scroll_bar_width,
+                    Qnil,
+                    doc: /* *Width of this buffer's scroll bars in pixels.
+A value of nil means to use the scroll bar width from the window's frame.  */);
+
+  DEFVAR_PER_BUFFER ("vertical-scroll-bar", &current_buffer->vertical_scroll_bar_type,
+                    Qnil,
+                    doc: /* *Position of this buffer's vertical scroll bar.
+A value of left or right means to place the vertical scroll bar at that side
+of the window; a value of nil means that this window has no vertical scroll bar.
+A value of t means to use the vertical scroll bar type from the window's frame.  */);
+
   DEFVAR_PER_BUFFER ("indicate-empty-lines",
                     &current_buffer->indicate_empty_lines, Qnil,
                     doc: /* *Visually indicate empty lines after the buffer end.
 If non-nil, a bitmap is displayed in the left fringe of a window on
 window-systems.  */);
-  
+
+  DEFVAR_PER_BUFFER ("indicate-buffer-boundaries",
+                    &current_buffer->indicate_buffer_boundaries, Qnil,
+                    doc: /* *Visually indicate buffer boundaries and scrolling.
+If non-nil, the first and last line of the buffer are marked in the left and
+right fringe of a window on window-systems.
+In addition, if value is t, the top and bottom line of the window are marked
+with up and down arrow bitmaps in the right fringe if window can be scrolled.  */);
+
   DEFVAR_PER_BUFFER ("scroll-up-aggressively",
                     &current_buffer->scroll_up_aggressively, Qnil,
                     doc: /* How far to scroll windows upward.
@@ -5530,7 +5654,7 @@ case that you moved off with C-f means scrolling just one line.  1.0 means
 point goes at the top, so that in that simple case, the window
 window scrolls by a full window height.  Meaningful values are
 between 0.0 and 1.0, inclusive.  */);
-  
+
   DEFVAR_PER_BUFFER ("scroll-down-aggressively",
                     &current_buffer->scroll_down_aggressively, Qnil,
                     doc: /* How far to scroll windows downward.
@@ -5543,7 +5667,7 @@ case that you moved off with C-b means scrolling just one line.  1.0 means
 point goes at the bottom, so that in that simple case, the window
 window scrolls by a full window height.  Meaningful values are
 between 0.0 and 1.0, inclusive.  */);
-  
+
 /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
     "Don't ask.");
 */
@@ -5663,7 +5787,7 @@ functions; it should only affect their performance.  */);
   DEFVAR_PER_BUFFER ("buffer-file-format", &current_buffer->file_format, Qnil,
                     doc: /* List of formats to use when saving this buffer.
 Formats are defined by `format-alist'.  This variable is
-set when a file is visited.  Automatically local in all buffers.  */);
+set when a file is visited.  */);
 
   DEFVAR_PER_BUFFER ("buffer-invisibility-spec",
                     &current_buffer->invisibility_spec, Qnil,
@@ -5786,3 +5910,6 @@ keys_of_buffer ()
      initialized when that function gets called.  */
   Fput (intern ("erase-buffer"), Qdisabled, Qt);
 }
+
+/* arch-tag: e48569bf-69a9-4b65-a23b-8e68769436e1
+   (do not change this comment) */