* buffer.c (syms_of_buffer) <fringe-indicator-alist>: Doc fix.
[bpt/emacs.git] / src / buffer.c
index 009d7de..adb85b8 100644 (file)
@@ -1,14 +1,15 @@
 /* Buffer manipulation primitives for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994,
                  1995, 1997, 1998, 1999, 2000, 2001, 2002,
-                 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +17,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
@@ -27,6 +26,7 @@ Boston, MA 02110-1301, USA.  */
 #include <sys/param.h>
 #include <errno.h>
 #include <stdio.h>
+#include <setjmp.h>
 
 #ifndef USE_CRT_DLL
 extern int errno;
@@ -152,6 +152,7 @@ Lisp_Object Qucs_set_table_for_input;
 int inhibit_modification_hooks;
 
 Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
+Lisp_Object Qpermanent_local_hook;
 
 Lisp_Object Qprotected_field;
 
@@ -266,17 +267,18 @@ assoc_ignore_text_properties (key, list)
 }
 
 DEFUN ("get-buffer", Fget_buffer, Sget_buffer, 1, 1, 0,
-       doc: /* Return the buffer named NAME (a string).
-If there is no live buffer named NAME, return nil.
-NAME may also be a buffer; if so, the value is that buffer.  */)
-     (name)
-     register Lisp_Object name;
+       doc: /* Return the buffer named BUFFER-OR-NAME.
+BUFFER-OR-NAME must be either a string or a buffer.  If BUFFER-OR-NAME
+is a string and there is no buffer with that name, return nil.  If
+BUFFER-OR-NAME is a buffer, return it as given.  */)
+     (buffer_or_name)
+     register Lisp_Object buffer_or_name;
 {
-  if (BUFFERP (name))
-    return name;
-  CHECK_STRING (name);
+  if (BUFFERP (buffer_or_name))
+    return buffer_or_name;
+  CHECK_STRING (buffer_or_name);
 
-  return Fcdr (assoc_ignore_text_properties (name, Vbuffer_alist));
+  return Fcdr (assoc_ignore_text_properties (buffer_or_name, Vbuffer_alist));
 }
 
 DEFUN ("get-file-buffer", Fget_file_buffer, Sget_file_buffer, 1, 1, 0,
@@ -333,22 +335,25 @@ get_truename_buffer (filename)
 int buffer_count;
 
 DEFUN ("get-buffer-create", Fget_buffer_create, Sget_buffer_create, 1, 1, 0,
-       doc: /* Return the buffer named NAME, or create such a buffer and return it.
-A new buffer is created if there is no live buffer named NAME.
-If NAME starts with a space, the new buffer does not keep undo information.
-If NAME is a buffer instead of a string, then it is the value returned.
-The value is never nil.  */)
-     (name)
-     register Lisp_Object name;
+       doc: /* Return the buffer specified by BUFFER-OR-NAME, creating a new one if needed.
+If BUFFER-OR-NAME is a string and a live buffer with that name exists,
+return that buffer.  If no such buffer exists, create a new buffer with
+that name and return it.  If BUFFER-OR-NAME starts with a space, the new
+buffer does not keep undo information.
+
+If BUFFER-OR-NAME is a buffer instead of a string, return it as given,
+even if it is dead.  The return value is never nil.  */)
+     (buffer_or_name)
+     register Lisp_Object buffer_or_name;
 {
-  register Lisp_Object buf;
+  register Lisp_Object buffer, name;
   register struct buffer *b;
 
-  buf = Fget_buffer (name);
-  if (!NILP (buf))
-    return buf;
+  buffer = Fget_buffer (buffer_or_name);
+  if (!NILP (buffer))
+    return buffer;
 
-  if (SCHARS (name) == 0)
+  if (SCHARS (buffer_or_name) == 0)
     error ("Empty string for buffer name is not allowed");
 
   b = allocate_buffer ();
@@ -402,7 +407,7 @@ The value is never nil.  */)
   b->begv_marker = Qnil;
   b->zv_marker = Qnil;
 
-  name = Fcopy_sequence (name);
+  name = Fcopy_sequence (buffer_or_name);
   STRING_SET_INTERVALS (name, NULL_INTERVAL);
   b->name = name;
 
@@ -416,17 +421,17 @@ The value is never nil.  */)
   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));
+  XSETBUFFER (buffer, b);
+  Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buffer), Qnil));
 
   /* An error in calling the function here (should someone redefine 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)))
-    /* buf is on buffer-alist, so no gcpro.  */
-    call1 (Qucs_set_table_for_input, buf);
+    /* buffer is on buffer-alist, so no gcpro.  */
+    call1 (Qucs_set_table_for_input, buffer);
 
-  return buf;
+  return buffer;
 }
 
 
@@ -494,12 +499,18 @@ clone_per_buffer_values (from, to)
 
   XSETBUFFER (to_buffer, to);
 
-  for (offset = PER_BUFFER_VAR_OFFSET (name) + sizeof (Lisp_Object);
+  /* buffer-local Lisp variables start at `undo_list',
+     tho only the ones from `name' on are GC'd normally.  */
+  for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
        offset < sizeof *to;
        offset += sizeof (Lisp_Object))
     {
       Lisp_Object obj;
 
+      /* Don't touch the `name' which should be unique for every buffer.  */
+      if (offset == PER_BUFFER_VAR_OFFSET (name))
+       continue;
+
       obj = PER_BUFFER_VALUE (from, offset);
       if (MARKERP (obj))
        {
@@ -693,7 +704,7 @@ reset_buffer (b)
   b->clip_changed = 0;
   b->prevent_redisplay_optimizations_p = 1;
   b->backed_up = Qnil;
-  b->auto_save_modified = 0;
+  BUF_AUTOSAVE_MODIFF (b) = 0;
   b->auto_save_failure_time = -1;
   b->auto_save_file_name = Qnil;
   b->read_only = Qnil;
@@ -761,13 +772,38 @@ reset_buffer_local_variables (b, permanent_too)
     b->local_var_alist = Qnil;
   else
     {
-      Lisp_Object tmp, last = Qnil;
+      Lisp_Object tmp, prop, last = Qnil;
       for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp))
        if (CONSP (XCAR (tmp))
            && SYMBOLP (XCAR (XCAR (tmp)))
-           && !NILP (Fget (XCAR (XCAR (tmp)), Qpermanent_local)))
-         /* If permanent-local, keep it.  */
-         last = tmp;
+           && !NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local)))
+         {
+           /* If permanent-local, keep it.  */
+           last = tmp;
+           if (EQ (prop, Qpermanent_local_hook))
+             {
+               /* This is a partially permanent hook variable.
+                  Preserve only the elements that want to be preserved.  */
+               Lisp_Object list, newlist;
+               list = XCDR (XCAR (tmp));
+               if (!CONSP (list))
+                 newlist = list;
+               else
+                 for (newlist = Qnil; CONSP (list); list = XCDR (list))
+                   {
+                     Lisp_Object elt = XCAR (list);
+                     /* Preserve element ELT if it's t,
+                        if it is a function with a `permanent-local-hook' property,
+                        or if it's not a symbol.  */
+                     if (! SYMBOLP (elt)
+                         || EQ (elt, Qt)
+                         || !NILP (Fget (elt, Qpermanent_local_hook)))
+                       newlist = Fcons (elt, newlist);
+                   }
+               XSETCDR (XCAR (tmp), Fnreverse (newlist));
+             }
+         }
+       /* Delete this local variable.  */
        else if (NILP (last))
          b->local_var_alist = XCDR (tmp);
        else
@@ -781,7 +817,9 @@ reset_buffer_local_variables (b, permanent_too)
   /* For each slot that has a default value,
      copy that into the slot.  */
 
-  for (offset = PER_BUFFER_VAR_OFFSET (name);
+  /* buffer-local Lisp variables start at `undo_list',
+     tho only the ones from `name' on are GC'd normally.  */
+  for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
        offset < sizeof *b;
        offset += sizeof (Lisp_Object))
     {
@@ -840,7 +878,8 @@ it is in the sequence to be tried) even if a buffer with that name exists.  */)
 \f
 DEFUN ("buffer-name", Fbuffer_name, Sbuffer_name, 0, 1, 0,
        doc: /* Return the name of BUFFER, as a string.
-With no argument or nil as argument, return the name of the current buffer.  */)
+BUFFER defaults to the current buffer.
+Return nil if BUFFER has been killed.  */)
      (buffer)
      register Lisp_Object buffer;
 {
@@ -898,12 +937,14 @@ is the default binding of the variable. */)
 {
   register struct buffer *buf;
   register Lisp_Object result;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
   CHECK_BUFFER (buffer);
   buf = XBUFFER (buffer);
 
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
+  XSETSYMBOL (variable, sym);
 
   /* Look in local_var_list */
   result = Fassoc (variable, buf->local_var_alist);
@@ -913,7 +954,9 @@ is the default binding of the variable. */)
       int found = 0;
 
       /* Look in special slots */
-      for (offset = PER_BUFFER_VAR_OFFSET (name);
+      /* buffer-local Lisp variables start at `undo_list',
+        tho only the ones from `name' on are GC'd normally.  */
+      for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
           offset < sizeof (struct buffer);
           /* sizeof EMACS_INT == sizeof Lisp_Object */
           offset += (sizeof (EMACS_INT)))
@@ -938,7 +981,7 @@ is the default binding of the variable. */)
       Lisp_Object current_alist_element;
 
       /* What binding is loaded right now?  */
-      valcontents = SYMBOL_VALUE (variable);
+      valcontents = sym->value;
       current_alist_element
        = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
 
@@ -1024,7 +1067,9 @@ No argument or nil as argument means use current buffer as BUFFER.  */)
   {
     int offset, idx;
 
-    for (offset = PER_BUFFER_VAR_OFFSET (name);
+    /* buffer-local Lisp variables start at `undo_list',
+       tho only the ones from `name' on are GC'd normally.  */
+    for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
         offset < sizeof (struct buffer);
         /* sizeof EMACS_INT == sizeof Lisp_Object */
         offset += (sizeof (EMACS_INT)))
@@ -1087,7 +1132,25 @@ A non-nil FLAG means mark the buffer modified.  */)
     }
 #endif /* CLASH_DETECTION */
 
-  SAVE_MODIFF = NILP (flag) ? MODIFF : 0;
+  /* Here we have a problem.  SAVE_MODIFF is used here to encode
+     buffer-modified-p (as SAVE_MODIFF<MODIFF) as well as
+     recent-auto-save-p (as SAVE_MODIFF<auto_save_modified).  So if we
+     modify SAVE_MODIFF to affect one, we may affect the other
+     as well.
+     E.g. if FLAG is nil we need to set SAVE_MODIFF to MODIFF, but
+     if SAVE_MODIFF<auto_save_modified that means we risk changing
+     recent-auto-save-p from t to nil.
+     Vice versa, if FLAG is non-nil and SAVE_MODIFF>=auto_save_modified
+     we risk changing recent-auto-save-p from nil to t.  */
+  SAVE_MODIFF = (NILP (flag)
+                /* FIXME: This unavoidably sets recent-auto-save-p to nil.  */
+                ? MODIFF
+                /* Let's try to preserve recent-auto-save-p.  */
+                : SAVE_MODIFF < MODIFF ? SAVE_MODIFF
+                /* If SAVE_MODIFF == auto_save_modified == MODIFF,
+                   we can either decrease SAVE_MODIFF and auto_save_modified
+                   or increase MODIFF.  */
+                : MODIFF++);
 
   /* Set update_mode_lines only if buffer is displayed in some window.
      Packages like jit-lock or lazy-lock preserve a buffer's modified
@@ -1343,38 +1406,39 @@ Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\
 The buffer being killed will be current while the hook is running.\n\
 See `kill-buffer'."
  */
-DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 1, 1, "bKill buffer: ",
-       doc: /* Kill the buffer BUFFER.
-The argument may be a buffer or the name of a buffer.
-With a nil argument, kill the current buffer.
-
-Value is t if the buffer is actually killed, nil otherwise.
-
-The functions in `kill-buffer-query-functions' are called with BUFFER as
-the current buffer.  If any of them returns nil, the buffer is not killed.
-
-The hook `kill-buffer-hook' is run before the buffer is actually killed.
-The buffer being killed will be current while the hook is running.
+DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ",
+       doc: /* Kill buffer BUFFER-OR-NAME.
+The argument may be a buffer or the name of an existing buffer.
+Argument nil or omitted means kill the current buffer.  Return t if the
+buffer is actually killed, nil otherwise.
+
+This function calls `replace-buffer-in-windows' for cleaning up all
+windows currently displaying the buffer to be killed.  The functions in
+`kill-buffer-query-functions' are called with the buffer to be killed as
+the current buffer.  If any of them returns nil, the buffer is not
+killed.  The hook `kill-buffer-hook' is run before the buffer is
+actually killed.  The buffer being killed will be current while the hook
+is running.
 
 Any processes that have this buffer as the `process-buffer' are killed
 with SIGHUP.  */)
-     (buffer)
-     Lisp_Object buffer;
+     (buffer_or_name)
+     Lisp_Object buffer_or_name;
 {
-  Lisp_Object buf;
+  Lisp_Object buffer;
   register struct buffer *b;
   register Lisp_Object tem;
   register struct Lisp_Marker *m;
   struct gcpro gcpro1;
 
-  if (NILP (buffer))
-    buf = Fcurrent_buffer ();
+  if (NILP (buffer_or_name))
+    buffer = Fcurrent_buffer ();
   else
-    buf = Fget_buffer (buffer);
-  if (NILP (buf))
-    nsberror (buffer);
+    buffer = Fget_buffer (buffer_or_name);
+  if (NILP (buffer))
+    nsberror (buffer_or_name);
 
-  b = XBUFFER (buf);
+  b = XBUFFER (buffer);
 
   /* Avoid trouble for buffer already dead.  */
   if (NILP (b->name))
@@ -1384,7 +1448,7 @@ with SIGHUP.  */)
   if (INTERACTIVE && !NILP (b->filename)
       && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
     {
-      GCPRO1 (buf);
+      GCPRO1 (buffer);
       tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ",
                                     b->name, make_number (0)));
       UNGCPRO;
@@ -1417,7 +1481,7 @@ with SIGHUP.  */)
      since anything can happen within do_yes_or_no_p.  */
 
   /* Don't kill the minibuffer now current.  */
-  if (EQ (buf, XWINDOW (minibuf_window)->buffer))
+  if (EQ (buffer, XWINDOW (minibuf_window)->buffer))
     return Qnil;
 
   if (NILP (b->name))
@@ -1430,16 +1494,16 @@ with SIGHUP.  */)
     {
       struct buffer *other;
 
-      GCPRO1 (buf);
+      GCPRO1 (buffer);
 
       for (other = all_buffers; other; other = other->next)
        /* all_buffers contains dead buffers too;
           don't re-kill them.  */
        if (other->base_buffer == b && !NILP (other->name))
          {
-           Lisp_Object buf;
-           XSETBUFFER (buf, other);
-           Fkill_buffer (buf);
+           Lisp_Object buffer;
+           XSETBUFFER (buffer, other);
+           Fkill_buffer (buffer);
          }
 
       UNGCPRO;
@@ -1450,7 +1514,7 @@ with SIGHUP.  */)
      and give up if so.  */
   if (b == current_buffer)
     {
-      tem = Fother_buffer (buf, Qnil, Qnil);
+      tem = Fother_buffer (buffer, Qnil, Qnil);
       Fset_buffer (tem);
       if (b == current_buffer)
        return Qnil;
@@ -1461,8 +1525,8 @@ with SIGHUP.  */)
   XSETBUFFER (tem, current_buffer);
   if (EQ (tem, XWINDOW (minibuf_window)->buffer))
     {
-      tem = Fother_buffer (buf, Qnil, Qnil);
-      if (EQ (buf, tem))
+      tem = Fother_buffer (buffer, Qnil, Qnil);
+      if (EQ (buffer, tem))
        return Qnil;
     }
 
@@ -1473,8 +1537,8 @@ with SIGHUP.  */)
   unlock_buffer (b);
 #endif /* CLASH_DETECTION */
 
-  GCPRO1 (buf);
-  kill_buffer_processes (buf);
+  GCPRO1 (buffer);
+  kill_buffer_processes (buffer);
   UNGCPRO;
 
   /* Killing buffer processes may run sentinels which may
@@ -1487,16 +1551,16 @@ with SIGHUP.  */)
 
   tem = Vinhibit_quit;
   Vinhibit_quit = Qt;
-  replace_buffer_in_all_windows (buf);
-  Vbuffer_alist = Fdelq (Frassq (buf, Vbuffer_alist), Vbuffer_alist);
-  frames_discard_buffer (buf);
+  replace_buffer_in_all_windows (buffer);
+  Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist);
+  frames_discard_buffer (buffer);
   Vinhibit_quit = tem;
 
   /* Delete any auto-save file, if we saved it in this session.
      But not if the buffer is modified.  */
   if (STRINGP (b->auto_save_file_name)
-      && b->auto_save_modified != 0
-      && BUF_SAVE_MODIFF (b) < b->auto_save_modified
+      && BUF_AUTOSAVE_MODIFF (b) != 0
+      && BUF_SAVE_MODIFF (b) < BUF_AUTOSAVE_MODIFF (b)
       && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
       && NILP (Fsymbol_value (intern ("auto-save-visited-file-name"))))
     {
@@ -1599,7 +1663,7 @@ record_buffer (buf)
   Vbuffer_alist = link;
 
   /* Effectively do a delq on buried_buffer_list.  */
-  
+
   prev = Qnil;
   for (link = XFRAME (frame)->buried_buffer_list; CONSP (link);
        link = XCDR (link))
@@ -1684,128 +1748,88 @@ the current buffer's major mode.  */)
   return unbind_to (count, Qnil);
 }
 
-/* If switching buffers in WINDOW would be an error, return
-   a C string saying what the error would be.  */
-
-char *
-no_switch_window (window)
-     Lisp_Object window;
-{
-  Lisp_Object tem;
-  if (EQ (minibuf_window, window))
-    return "Cannot switch buffers in minibuffer window";
-  tem = Fwindow_dedicated_p (window);
-  if (EQ (tem, Qt))
-    return "Cannot switch buffers in a dedicated window";
-  return NULL;
-}
-
 /* Switch to buffer BUFFER in the selected window.
    If NORECORD is non-nil, don't call record_buffer.  */
 
 Lisp_Object
-switch_to_buffer_1 (buffer, norecord)
-     Lisp_Object buffer, norecord;
+switch_to_buffer_1 (buffer_or_name, norecord)
+     Lisp_Object buffer_or_name, norecord;
 {
-  register Lisp_Object buf;
+  register Lisp_Object buffer;
 
-  if (NILP (buffer))
-    buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
+  if (NILP (buffer_or_name))
+    buffer = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
   else
     {
-      buf = Fget_buffer (buffer);
-      if (NILP (buf))
+      buffer = Fget_buffer (buffer_or_name);
+      if (NILP (buffer))
        {
-         buf = Fget_buffer_create (buffer);
-         Fset_buffer_major_mode (buf);
+         buffer = Fget_buffer_create (buffer_or_name);
+         Fset_buffer_major_mode (buffer);
        }
     }
-  Fset_buffer (buf);
+  Fset_buffer (buffer);
   if (NILP (norecord))
-    record_buffer (buf);
+    record_buffer (buffer);
 
   Fset_window_buffer (EQ (selected_window, minibuf_window)
                      ? Fnext_window (minibuf_window, Qnil, Qnil)
                      : selected_window,
-                     buf, Qnil);
+                     buffer, Qnil);
 
-  return buf;
+  return buffer;
 }
 
-DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "BSwitch to buffer: ",
-       doc: /* Select buffer BUFFER in the current window.
-If BUFFER does not identify an existing buffer,
-then this function creates a buffer with that name.
+DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2,
+       "(list (read-buffer-to-switch \"Switch to buffer: \"))",
+       doc: /* Make BUFFER-OR-NAME current and display it in selected window.
+BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
+nil.  Return the buffer switched to.
+
+If BUFFER-OR-NAME is a string and does not identify an existing
+buffer, create a new buffer with that name.  Interactively, if
+`confirm-nonexistent-file-or-buffer' is non-nil, request
+confirmation before creating a new buffer.  If BUFFER-OR-NAME is
+nil, switch to buffer returned by `other-buffer'.
 
-When called from Lisp, BUFFER may be a buffer, a string \(a buffer name),
-or nil.  If BUFFER is nil, then this function chooses a buffer
-using `other-buffer'.
-Optional second arg NORECORD non-nil means
-do not put this buffer at the front of the list of recently selected ones.
-This function returns the buffer it switched to.
+Optional second arg NORECORD non-nil means do not put this buffer
+at the front of the list of recently selected ones.  This
+function returns the buffer it switched to as a Lisp object.
+
+If the selected window is the minibuffer window or dedicated to
+its buffer, use `pop-to-buffer' for displaying the buffer.
 
 WARNING: This is NOT the way to work on another buffer temporarily
-within a Lisp program!  Use `set-buffer' instead.  That avoids messing with
-the window-buffer correspondences.  */)
-     (buffer, norecord)
-     Lisp_Object buffer, norecord;
+within a Lisp program!  Use `set-buffer' instead.  That avoids
+messing with the window-buffer correspondences.  */)
+     (buffer_or_name, norecord)
+     Lisp_Object buffer_or_name, norecord;
 {
   char *err;
 
-  if (EQ (buffer, Fwindow_buffer (selected_window)))
+  if (EQ (buffer_or_name, Fwindow_buffer (selected_window)))
     {
       /* Basically a NOP.  Avoid signalling an error in the case where
         the selected window is dedicated, or a minibuffer.  */
 
-      /* But do put this buffer at the front of the buffer list,
-        unless that has been inhibited.  Note that even if
-        BUFFER is at the front of the main buffer-list already,
-        we still want to move it to the front of the frame's buffer list.  */
+      /* But do put this buffer at the front of the buffer list, unless
+        that has been inhibited.  Note that even if BUFFER-OR-NAME is
+        at the front of the main buffer-list already, we still want to
+        move it to the front of the frame's buffer list.  */
       if (NILP (norecord))
-       record_buffer (buffer);
-      return Fset_buffer (buffer);
+       record_buffer (buffer_or_name);
+      return Fset_buffer (buffer_or_name);
     }
-
-  err = no_switch_window (selected_window);
-  if (err) error (err);
-
-  return switch_to_buffer_1 (buffer, norecord);
-}
-
-DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 3, 0,
-       doc: /* Select buffer BUFFER in some window, preferably a different one.
-BUFFER may be a buffer, a string \(a buffer name), or nil.
-If BUFFER is a string which is not the name of an existing buffer,
-then this function creates a buffer with that name.
-If BUFFER is nil, then it chooses some other buffer.
-If `pop-up-windows' is non-nil, windows can be split to do this.
-If optional second arg OTHER-WINDOW is non-nil, insist on finding another
-window even if BUFFER is already visible in the selected window,
-and ignore `same-window-regexps' and `same-window-buffer-names'.
-This function returns the buffer it switched to.
-This uses the function `display-buffer' as a subroutine; see the documentation
-of `display-buffer' for additional customization information.
-
-Optional third arg NORECORD non-nil means
-do not put this buffer at the front of the list of recently selected ones.  */)
-     (buffer, other_window, norecord)
-     Lisp_Object buffer, other_window, norecord;
-{
-  register Lisp_Object buf;
-  if (NILP (buffer))
-    buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
+  else if (EQ (minibuf_window, selected_window)
+          /* If `dedicated' is neither nil nor t, it means it's
+             dedicatedness can be overridden by an explicit request
+             such as a call to switch-to-buffer.  */
+          || EQ (Fwindow_dedicated_p (selected_window), Qt))
+    /* We can't use the selected window so let `pop-to-buffer' try some
+       other window. */
+    return call3 (intern ("pop-to-buffer"), buffer_or_name, Qnil, norecord);
   else
-    {
-      buf = Fget_buffer (buffer);
-      if (NILP (buf))
-       {
-         buf = Fget_buffer_create (buffer);
-         Fset_buffer_major_mode (buf);
-       }
-    }
-  Fset_buffer (buf);
-  Fselect_window (Fdisplay_buffer (buf, other_window, Qnil), norecord);
-  return buf;
+    return switch_to_buffer_1 (buffer_or_name, norecord);
 }
 
 DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
@@ -1917,12 +1941,14 @@ set_buffer_internal_1 (b)
 
   for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail))
     {
-      valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
-      if ((BUFFER_LOCAL_VALUEP (valcontents))
+      if (CONSP (XCAR (tail))
+         && SYMBOLP (XCAR (XCAR (tail)))
+         && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))),
+             (BUFFER_LOCAL_VALUEP (valcontents)))
          && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
              (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
-       /* Just reference the variable
-            to cause it to become set for this buffer.  */
+       /* Just reference the variable to cause it to become set for
+          this buffer.  */
        Fsymbol_value (XCAR (XCAR (tail)));
     }
 
@@ -1931,12 +1957,14 @@ set_buffer_internal_1 (b)
   if (old_buf)
     for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
       {
-       valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
-       if ((BUFFER_LOCAL_VALUEP (valcontents))
+       if (CONSP (tail)
+           && SYMBOLP (XCAR (XCAR (tail)))
+           && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))),
+               (BUFFER_LOCAL_VALUEP (valcontents)))
            && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
                (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
-         /* Just reference the variable
-               to cause it to become set for this buffer.  */
+         /* Just reference the variable to cause it to become set for
+            this buffer.  */
          Fsymbol_value (XCAR (XCAR (tail)));
       }
 }
@@ -2003,23 +2031,23 @@ set_buffer_temp (b)
 }
 
 DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
-       doc: /* Make the buffer BUFFER current for editing operations.
-BUFFER may be a buffer or the name of an existing buffer.
-See also `save-excursion' when you want to make a buffer current temporarily.
-This function does not display the buffer, so its effect ends
-when the current command terminates.
-Use `switch-to-buffer' or `pop-to-buffer' to switch buffers permanently.  */)
-     (buffer)
-     register Lisp_Object buffer;
+       doc: /* Make buffer BUFFER-OR-NAME current for editing operations.
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer.  See
+also `save-excursion' when you want to make a buffer current
+temporarily.  This function does not display the buffer, so its effect
+ends when the current command terminates.  Use `switch-to-buffer' or
+`pop-to-buffer' to switch buffers permanently.  */)
+     (buffer_or_name)
+     register Lisp_Object buffer_or_name;
 {
-  register Lisp_Object buf;
-  buf = Fget_buffer (buffer);
-  if (NILP (buf))
-    nsberror (buffer);
-  if (NILP (XBUFFER (buf)->name))
+  register Lisp_Object buffer;
+  buffer = Fget_buffer (buffer_or_name);
+  if (NILP (buffer))
+    nsberror (buffer_or_name);
+  if (NILP (XBUFFER (buffer)->name))
     error ("Selecting deleted buffer");
-  set_buffer_internal (XBUFFER (buf));
-  return buf;
+  set_buffer_internal (XBUFFER (buffer));
+  return buffer;
 }
 
 /* Set the current buffer to BUFFER provided it is alive.  */
@@ -2045,18 +2073,24 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
 }
 
 DEFUN ("bury-buffer", Fbury_buffer, Sbury_buffer, 0, 1, "",
-       doc: /* Put BUFFER at the end of the list of all buffers.
+       doc: /* Put BUFFER-OR-NAME at the end of the list of all buffers.
 There it is the least likely candidate for `other-buffer' to return;
-thus, the least likely buffer for \\[switch-to-buffer] to select by default.
-You can specify a buffer name as BUFFER, or an actual buffer object.
-If BUFFER is nil or omitted, bury the current buffer.
-Also, if BUFFER is nil or omitted, remove the current buffer from the
-selected window if it is displayed there.  */)
-     (buffer)
-     register Lisp_Object buffer;
+thus, the least likely buffer for \\[switch-to-buffer] to select by
+default.
+
+The argument may be a buffer name or an actual buffer object.  If
+BUFFER-OR-NAME is nil or omitted, bury the current buffer and remove it
+from the selected window if it is displayed there.  If the selected
+window is dedicated to its buffer, delete that window if there are other
+windows on the same frame.  If the selected window is the only window on
+its frame, iconify that frame.  */)
+     (buffer_or_name)
+     register Lisp_Object buffer_or_name;
 {
+  Lisp_Object buffer;
+
   /* Figure out what buffer we're going to bury.  */
-  if (NILP (buffer))
+  if (NILP (buffer_or_name))
     {
       Lisp_Object tem;
       XSETBUFFER (buffer, current_buffer);
@@ -2075,12 +2109,9 @@ selected window if it is displayed there.  */)
     }
   else
     {
-      Lisp_Object buf1;
-
-      buf1 = Fget_buffer (buffer);
-      if (NILP (buf1))
-       nsberror (buffer);
-      buffer = buf1;
+      buffer = Fget_buffer (buffer_or_name);
+      if (NILP (buffer))
+       nsberror (buffer_or_name);
     }
 
   /* Move buffer to the end of the buffer list.  Do nothing if the
@@ -2177,6 +2208,139 @@ advance_to_char_boundary (byte_pos)
   return byte_pos;
 }
 
+#ifdef REL_ALLOC
+extern void r_alloc_reset_variable P_ ((POINTER_TYPE *, POINTER_TYPE *));
+#endif /* REL_ALLOC */
+
+DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
+       1, 1, 0,
+       doc: /* Swap the text between current buffer and BUFFER.  */)
+     (buffer)
+     Lisp_Object buffer;
+{
+  struct buffer *other_buffer;
+  CHECK_BUFFER (buffer);
+  other_buffer = XBUFFER (buffer);
+
+  if (NILP (other_buffer->name))
+    error ("Cannot swap a dead buffer's text");    
+
+  /* Actually, it probably works just fine.
+   * if (other_buffer == current_buffer)
+   *   error ("Cannot swap a buffer's text with itself"); */
+
+  /* Actually, this may be workable as well, tho probably only if they're
+     *both* indirect.  */
+  if (other_buffer->base_buffer
+      || current_buffer->base_buffer)
+    error ("Cannot swap indirect buffers's text");
+
+  { /* This is probably harder to make work.  */
+    struct buffer *other;
+    for (other = all_buffers; other; other = other->next)
+      if (other->base_buffer == other_buffer
+         || other->base_buffer == current_buffer)
+       error ("One of the buffers to swap has indirect buffers");
+  }
+
+#define swapfield(field, type) \
+  do {                                                 \
+    type tmp##field = other_buffer->field;             \
+    other_buffer->field = current_buffer->field;       \
+    current_buffer->field = tmp##field;                        \
+  } while (0)
+
+  swapfield (own_text, struct buffer_text);
+  eassert (current_buffer->text == &current_buffer->own_text);
+  eassert (other_buffer->text == &other_buffer->own_text);
+#ifdef REL_ALLOC
+  r_alloc_reset_variable ((POINTER_TYPE **) &current_buffer->own_text.beg,
+                         (POINTER_TYPE **) &other_buffer->own_text.beg);
+  r_alloc_reset_variable ((POINTER_TYPE **) &other_buffer->own_text.beg,
+                         (POINTER_TYPE **) &current_buffer->own_text.beg);
+#endif /* REL_ALLOC */
+
+  swapfield (pt, EMACS_INT);
+  swapfield (pt_byte, EMACS_INT);
+  swapfield (begv, EMACS_INT);
+  swapfield (begv_byte, EMACS_INT);
+  swapfield (zv, EMACS_INT);
+  swapfield (zv_byte, EMACS_INT);
+  eassert (!current_buffer->base_buffer);
+  eassert (!other_buffer->base_buffer);
+  current_buffer->clip_changed = 1;    other_buffer->clip_changed = 1;
+  swapfield (newline_cache, struct region_cache *);
+  swapfield (width_run_cache, struct region_cache *);
+  current_buffer->prevent_redisplay_optimizations_p = 1;
+  other_buffer->prevent_redisplay_optimizations_p = 1;
+  swapfield (overlays_before, struct Lisp_Overlay *);
+  swapfield (overlays_after, struct Lisp_Overlay *);
+  swapfield (overlay_center, EMACS_INT);
+  swapfield (undo_list, Lisp_Object);
+  swapfield (mark, Lisp_Object);
+  swapfield (enable_multibyte_characters, Lisp_Object);
+  /* FIXME: Not sure what we should do with these *_marker fields.
+     Hopefully they're just nil anyway.  */
+  swapfield (pt_marker, Lisp_Object);
+  swapfield (begv_marker, Lisp_Object);
+  swapfield (zv_marker, Lisp_Object);
+  current_buffer->point_before_scroll = Qnil;
+  other_buffer->point_before_scroll = Qnil;
+
+  current_buffer->text->modiff++;        other_buffer->text->modiff++;
+  current_buffer->text->chars_modiff++;          other_buffer->text->chars_modiff++;
+  current_buffer->text->overlay_modiff++; other_buffer->text->overlay_modiff++;
+  current_buffer->text->beg_unchanged = current_buffer->text->gpt;
+  current_buffer->text->end_unchanged = current_buffer->text->gpt;
+  other_buffer->text->beg_unchanged = other_buffer->text->gpt;
+  other_buffer->text->end_unchanged = other_buffer->text->gpt;
+  {
+    struct Lisp_Marker *m;
+    for (m = BUF_MARKERS (current_buffer); m; m = m->next)
+      if (m->buffer == other_buffer)
+       m->buffer = current_buffer;
+      else
+       /* Since there's no indirect buffer in sight, markers on
+          BUF_MARKERS(buf) should either be for `buf' or dead.  */
+       eassert (!m->buffer);
+    for (m = BUF_MARKERS (other_buffer); m; m = m->next)
+      if (m->buffer == current_buffer)
+       m->buffer = other_buffer;
+      else
+       /* Since there's no indirect buffer in sight, markers on
+          BUF_MARKERS(buf) should either be for `buf' or dead.  */
+       eassert (!m->buffer);
+  }
+  { /* Some of the C code expects that w->buffer == w->pointm->buffer.
+       So since we just swapped the markers between the two buffers, we need
+       to undo the effect of this swap for window markers.  */
+    Lisp_Object w = Fselected_window (), ws = Qnil;
+    Lisp_Object buf1, buf2;
+    XSETBUFFER (buf1, current_buffer); XSETBUFFER (buf2, other_buffer);
+
+    while (NILP (Fmemq (w, ws)))
+      {
+       ws = Fcons (w, ws);
+       if (MARKERP (XWINDOW (w)->pointm)
+           && (EQ (XWINDOW (w)->buffer, buf1)
+               || EQ (XWINDOW (w)->buffer, buf2)))
+         Fset_marker (XWINDOW (w)->pointm,
+                      make_number (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))),
+                      XWINDOW (w)->buffer);
+       w = Fnext_window (w, Qt, Qt);
+      }
+  }
+
+  if (current_buffer->text->intervals)
+    (eassert (EQ (current_buffer->text->intervals->up.obj, buffer)),
+     XSETBUFFER (current_buffer->text->intervals->up.obj, current_buffer));
+  if (other_buffer->text->intervals)
+    (eassert (EQ (other_buffer->text->intervals->up.obj, Fcurrent_buffer ())),
+     XSETBUFFER (other_buffer->text->intervals->up.obj, other_buffer));
+
+  return Qnil;
+}
+
 DEFUN ("set-buffer-multibyte", Fset_buffer_multibyte, Sset_buffer_multibyte,
        1, 1, 0,
        doc: /* Set the multibyte flag of the current buffer to FLAG.
@@ -2263,7 +2427,7 @@ current buffer is cleared.  */)
            p++, pos++;
          else if (CHAR_BYTE8_HEAD_P (*p))
            {
-             c = STRING_CHAR_AND_LENGTH (p, stop - pos, bytes);
+             c = STRING_CHAR_AND_LENGTH (p, bytes);
              /* Delete all bytes for this 8-bit character but the
                 last one, and change the last one to the charcter
                 code.  */
@@ -2333,7 +2497,9 @@ current buffer is cleared.  */)
 
          if (ASCII_BYTE_P (*p))
            p++, pos++;
-         else if (EQ (flag, Qt) && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0)
+         else if (EQ (flag, Qt)
+                  && ! CHAR_BYTE8_HEAD_P (*p)
+                  && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0)
            p += bytes, pos += bytes;
          else
            {
@@ -2513,18 +2679,19 @@ static void
 swap_out_buffer_local_variables (b)
      struct buffer *b;
 {
-  Lisp_Object oalist, alist, sym, tem, buffer;
+  Lisp_Object oalist, alist, sym, buffer;
 
   XSETBUFFER (buffer, b);
   oalist = b->local_var_alist;
 
   for (alist = oalist; CONSP (alist); alist = XCDR (alist))
     {
-      sym = XCAR (XCAR (alist));
-
-      /* Need not do anything if some other buffer's binding is now encached.  */
-      tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer;
-      if (EQ (tem, buffer))
+      if (CONSP (XCAR (alist))
+         && (sym = XCAR (XCAR (alist)), SYMBOLP (sym))
+         /* Need not do anything if some other buffer's binding is
+            now encached.  */
+         && EQ (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer,
+                buffer))
        {
          /* Symbol is set up for this buffer's old local value:
             swap it out!  */
@@ -2561,8 +2728,8 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
      int extend;
      Lisp_Object **vec_ptr;
      int *len_ptr;
-     int *next_ptr;
-     int *prev_ptr;
+     EMACS_INT *next_ptr;
+     EMACS_INT *prev_ptr;
      int change_req;
 {
   Lisp_Object overlay, start, end;
@@ -2680,8 +2847,9 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
   return idx;
 }
 \f
-/* Find all the overlays in the current buffer that overlap the range BEG-END
-   or are empty at BEG.
+/* Find all the overlays in the current buffer that overlap the range
+   BEG-END, or are empty at BEG, or are empty at END provided END
+   denotes the position at the end of the current buffer.
 
    Return the number found, and store them in a vector in *VEC_PTR.
    Store in *LEN_PTR the size allocated for the vector.
@@ -2716,6 +2884,7 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
   int next = ZV;
   int prev = BEGV;
   int inhibit_storing = 0;
+  int end_is_Z = end == Z;
 
   for (tail = current_buffer->overlays_before; tail; tail = tail->next)
     {
@@ -2733,10 +2902,12 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
          break;
        }
       startpos = OVERLAY_POSITION (ostart);
-      /* Count an interval if it either overlaps the range
-        or is empty at the start of the range.  */
+      /* Count an interval if it overlaps the range, is empty at the
+        start of the range, or is empty at END provided END denotes the
+        end of the buffer.  */
       if ((beg < endpos && startpos < end)
-         || (startpos == endpos && beg == endpos))
+         || (startpos == endpos
+             && (beg == endpos || (end_is_Z && endpos == end))))
        {
          if (idx == len)
            {
@@ -2781,10 +2952,12 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
          break;
        }
       endpos = OVERLAY_POSITION (oend);
-      /* Count an interval if it either overlaps the range
-        or is empty at the start of the range.  */
+      /* Count an interval if it overlaps the range, is empty at the
+        start of the range, or is empty at END provided END denotes the
+        end of the buffer.  */
       if ((beg < endpos && startpos < end)
-         || (startpos == endpos && beg == endpos))
+         || (startpos == endpos
+             && (beg == endpos || (end_is_Z && endpos == end))))
        {
          if (idx == len)
            {
@@ -3967,7 +4140,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), 1, &overlay_vec, &len,
-                          (int *) 0, (int *) 0, 0);
+                          (EMACS_INT *) 0, (EMACS_INT *) 0, 0);
 
   /* Make a list of them all.  */
   result = Flist (noverlays, overlay_vec);
@@ -3980,8 +4153,9 @@ DEFUN ("overlays-in", Foverlays_in, Soverlays_in, 2, 2, 0,
        doc: /* Return a list of the overlays that overlap the region BEG ... END.
 Overlap means that at least one character is contained within the overlay
 and also contained within the specified region.
-Empty overlays are included in the result if they are located at BEG
-or between BEG and END.  */)
+Empty overlays are included in the result if they are located at BEG,
+between BEG and END, or at END provided END denotes the position at the
+end of the buffer.  */)
      (beg, end)
      Lisp_Object beg, end;
 {
@@ -4017,7 +4191,7 @@ the value is (point-max).  */)
      Lisp_Object pos;
 {
   int noverlays;
-  int endpos;
+  EMACS_INT endpos;
   Lisp_Object *overlay_vec;
   int len;
   int i;
@@ -4031,14 +4205,14 @@ the value is (point-max).  */)
      Store the length in len.
      endpos gets the position where the next overlay starts.  */
   noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
-                          &endpos, (int *) 0, 1);
+                          &endpos, (EMACS_INT *) 0, 1);
 
   /* If any of these overlays ends before endpos,
      use its ending point instead.  */
   for (i = 0; i < noverlays; i++)
     {
       Lisp_Object oend;
-      int oendpos;
+      EMACS_INT oendpos;
 
       oend = OVERLAY_END (overlay_vec[i]);
       oendpos = OVERLAY_POSITION (oend);
@@ -4059,7 +4233,7 @@ the value is (point-min).  */)
      Lisp_Object pos;
 {
   int noverlays;
-  int prevpos;
+  EMACS_INT prevpos;
   Lisp_Object *overlay_vec;
   int len;
 
@@ -4077,7 +4251,7 @@ the value is (point-min).  */)
      Store the length in len.
      prevpos gets the position of the previous change.  */
   noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
-                          (int *) 0, &prevpos, 1);
+                          (EMACS_INT *) 0, &prevpos, 1);
 
   xfree (overlay_vec);
   return make_number (prevpos);
@@ -4200,8 +4374,10 @@ add_overlay_mod_hooklist (functionlist, overlay)
   if (last_overlay_modification_hooks_used == oldsize)
     last_overlay_modification_hooks = larger_vector 
       (last_overlay_modification_hooks, oldsize * 2, Qnil);
-  AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = functionlist;
-  AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = overlay;
+  ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used,
+       functionlist); last_overlay_modification_hooks_used++;
+  ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used,
+       overlay);      last_overlay_modification_hooks_used++;
 }
 \f
 /* Run the modification-hooks of overlays that include
@@ -4409,32 +4585,21 @@ evaporate_overlays (pos)
    in the slot with offset OFFSET.  */
 
 void
-buffer_slot_type_mismatch (sym, type)
-     Lisp_Object sym;
+buffer_slot_type_mismatch (newval, type)
+     Lisp_Object newval;
      int type;
 {
-  char *type_name;
+  Lisp_Object predicate;
 
   switch (type)
     {
-    case Lisp_Int:
-      type_name = "integers";
-      break;
-
-    case Lisp_String:
-      type_name = "strings";
-      break;
-
-    case Lisp_Symbol:
-      type_name = "symbols";
-      break;
-
-    default:
-      abort ();
+    case_Lisp_Int:    predicate = Qintegerp; break;
+    case Lisp_String: predicate = Qstringp;  break;
+    case Lisp_Symbol: predicate = Qsymbolp;  break;
+    default: abort ();
     }
 
-  error ("Only %s should be stored in the buffer-local variable %s",
-        type_name, SDATA (SYMBOL_NAME (sym)));
+  wrong_type_argument (predicate, newval);
 }
 
 \f
@@ -4939,9 +5104,7 @@ alloc_buffer_text (b, nbytes)
    shrink it.  */
 
 void
-enlarge_buffer_text (b, delta)
-     struct buffer *b;
-     int delta;
+enlarge_buffer_text (struct buffer *b, EMACS_INT delta)
 {
   POINTER_TYPE *p;
   size_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
@@ -5019,7 +5182,7 @@ init_buffer_once ()
   /* Must do these before making the first buffer! */
 
   /* real setup is done in bindings.el */
-  buffer_defaults.mode_line_format = build_string ("%-");
+  buffer_defaults.mode_line_format = make_pure_c_string ("%-");
   buffer_defaults.header_line_format = Qnil;
   buffer_defaults.abbrev_mode = Qnil;
   buffer_defaults.overwrite_mode = Qnil;
@@ -5041,6 +5204,7 @@ init_buffer_once ()
 
   XSETFASTINT (buffer_defaults.tab_width, 8);
   buffer_defaults.truncate_lines = Qnil;
+  buffer_defaults.word_wrap = Qnil;
   buffer_defaults.ctl_arrow = Qt;
   buffer_defaults.direction_reversed = Qnil;
   buffer_defaults.cursor_type = Qt;
@@ -5113,6 +5277,7 @@ init_buffer_once ()
 #endif
   XSETFASTINT (buffer_local_flags.tab_width, idx); ++idx;
   XSETFASTINT (buffer_local_flags.truncate_lines, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.word_wrap, idx); ++idx;
   XSETFASTINT (buffer_local_flags.ctl_arrow, idx); ++idx;
   XSETFASTINT (buffer_local_flags.fill_column, idx); ++idx;
   XSETFASTINT (buffer_local_flags.left_margin, idx); ++idx;
@@ -5157,28 +5322,27 @@ init_buffer_once ()
   current_buffer = 0;
   all_buffers = 0;
 
-  QSFundamental = build_string ("Fundamental");
+  QSFundamental = make_pure_c_string ("Fundamental");
 
-  Qfundamental_mode = intern ("fundamental-mode");
+  Qfundamental_mode = intern_c_string ("fundamental-mode");
   buffer_defaults.major_mode = Qfundamental_mode;
 
-  Qmode_class = intern ("mode-class");
+  Qmode_class = intern_c_string ("mode-class");
 
-  Qprotected_field = intern ("protected-field");
+  Qprotected_field = intern_c_string ("protected-field");
 
-  Qpermanent_local = intern ("permanent-local");
+  Qpermanent_local = intern_c_string ("permanent-local");
 
-  Qkill_buffer_hook = intern ("kill-buffer-hook");
+  Qkill_buffer_hook = intern_c_string ("kill-buffer-hook");
   Fput (Qkill_buffer_hook, Qpermanent_local, Qt);
 
-  Qucs_set_table_for_input = intern ("ucs-set-table-for-input");
-
-  Vprin1_to_string_buffer = Fget_buffer_create (build_string (" prin1"));
+  Qucs_set_table_for_input = intern_c_string ("ucs-set-table-for-input");
 
   /* super-magic invisible buffer */
+  Vprin1_to_string_buffer = Fget_buffer_create (make_pure_c_string (" prin1"));
   Vbuffer_alist = Qnil;
 
-  Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
+  Fset_buffer (Fget_buffer_create (make_pure_c_string ("*scratch*")));
 
   inhibit_modification_hooks = 0;
 }
@@ -5212,18 +5376,18 @@ init_buffer ()
   if (!pwd)
     fatal ("`get_current_dir_name' failed: %s\n", strerror (errno));
 
-#ifndef VMS
   /* Maybe this should really use some standard subroutine
      whose definition is filename syntax dependent.  */
   len = strlen (pwd);
   if (!(IS_DIRECTORY_SEP (pwd[len - 1])))
     {
       /* Grow buffer to add directory separator and '\0'.  */
-      pwd = (char *) xrealloc (pwd, len + 2);
+      pwd = (char *) realloc (pwd, len + 2);
+      if (!pwd)
+       fatal ("`get_current_dir_name' failed: %s\n", strerror (errno));
       pwd[len] = DIRECTORY_SEP;
       pwd[len + 1] = '\0';
     }
-#endif /* not VMS */
 
   current_buffer->directory = make_unibyte_string (pwd, strlen (pwd));
   if (! NILP (buffer_defaults.enable_multibyte_characters))
@@ -5307,42 +5471,45 @@ syms_of_buffer ()
   staticpro (&Vbuffer_alist);
   staticpro (&Qprotected_field);
   staticpro (&Qpermanent_local);
+  Qpermanent_local_hook = intern_c_string ("permanent-local-hook");
+  staticpro (&Qpermanent_local_hook);
   staticpro (&Qkill_buffer_hook);
-  Qoverlayp = intern ("overlayp");
+  Qoverlayp = intern_c_string ("overlayp");
   staticpro (&Qoverlayp);
-  Qevaporate = intern ("evaporate");
+  Qevaporate = intern_c_string ("evaporate");
   staticpro (&Qevaporate);
-  Qmodification_hooks = intern ("modification-hooks");
+  Qmodification_hooks = intern_c_string ("modification-hooks");
   staticpro (&Qmodification_hooks);
-  Qinsert_in_front_hooks = intern ("insert-in-front-hooks");
+  Qinsert_in_front_hooks = intern_c_string ("insert-in-front-hooks");
   staticpro (&Qinsert_in_front_hooks);
-  Qinsert_behind_hooks = intern ("insert-behind-hooks");
+  Qinsert_behind_hooks = intern_c_string ("insert-behind-hooks");
   staticpro (&Qinsert_behind_hooks);
-  Qget_file_buffer = intern ("get-file-buffer");
+  Qget_file_buffer = intern_c_string ("get-file-buffer");
   staticpro (&Qget_file_buffer);
-  Qpriority = intern ("priority");
+  Qpriority = intern_c_string ("priority");
   staticpro (&Qpriority);
-  Qwindow = intern ("window");
+  Qwindow = intern_c_string ("window");
   staticpro (&Qwindow);
-  Qbefore_string = intern ("before-string");
+  Qbefore_string = intern_c_string ("before-string");
   staticpro (&Qbefore_string);
-  Qafter_string = intern ("after-string");
+  Qafter_string = intern_c_string ("after-string");
   staticpro (&Qafter_string);
-  Qfirst_change_hook = intern ("first-change-hook");
+  Qfirst_change_hook = intern_c_string ("first-change-hook");
   staticpro (&Qfirst_change_hook);
-  Qbefore_change_functions = intern ("before-change-functions");
+  Qbefore_change_functions = intern_c_string ("before-change-functions");
   staticpro (&Qbefore_change_functions);
-  Qafter_change_functions = intern ("after-change-functions");
+  Qafter_change_functions = intern_c_string ("after-change-functions");
   staticpro (&Qafter_change_functions);
+  /* The next one is initialized in init_buffer_once.  */
   staticpro (&Qucs_set_table_for_input);
 
-  Qkill_buffer_query_functions = intern ("kill-buffer-query-functions");
+  Qkill_buffer_query_functions = intern_c_string ("kill-buffer-query-functions");
   staticpro (&Qkill_buffer_query_functions);
 
   Fput (Qprotected_field, Qerror_conditions,
-       Fcons (Qprotected_field, Fcons (Qerror, Qnil)));
+       pure_cons (Qprotected_field, pure_cons (Qerror, Qnil)));
   Fput (Qprotected_field, Qerror_message,
-       build_string ("Attempt to modify a protected field"));
+       make_pure_c_string ("Attempt to modify a protected field"));
 
   /* All these use DEFVAR_LISP_NOPRO because the slots in
      buffer_defaults will all be marked via Vbuffer_defaults.  */
@@ -5558,23 +5725,27 @@ A string is printed verbatim in the mode line except for %-constructs:
 Decimal digits after the % specify field width to which to pad.  */);
 
   DEFVAR_LISP_NOPRO ("default-major-mode", &buffer_defaults.major_mode,
-                    doc: /* *Major mode for new buffers.  Defaults to `fundamental-mode'.
-A value of nil means use current buffer's major mode,
-provided it is not marked as "special".
-
-When a mode is used by default, `find-file' switches to it
-before it reads the contents into the buffer and before
-it finishes setting up the buffer.  Thus, the mode and
-its hooks should not expect certain variables such as
-`buffer-read-only' and `buffer-file-coding-system' to be set up.  */);
+                    doc: /* *Value of `major-mode' for new buffers.  */);
 
   DEFVAR_PER_BUFFER ("major-mode", &current_buffer->major_mode,
                     make_number (Lisp_Symbol),
-                    doc: /* Symbol for current buffer's major mode.  */);
+                    doc: /* Symbol for current buffer's major mode.
+The default value (normally `fundamental-mode') affects new buffers.
+A value of nil means to use the current buffer's major mode, provided
+it is not marked as "special".
+
+When a mode is used by default, `find-file' switches to it before it
+reads the contents into the buffer and before it finishes setting up
+the buffer.  Thus, the mode and its hooks should not expect certain
+variables such as `buffer-read-only' and `buffer-file-coding-system'
+to be set up.  */);
 
   DEFVAR_PER_BUFFER ("mode-name", &current_buffer->mode_name,
                      Qnil,
-                    doc: /* Pretty name of current buffer's major mode (a string).  */);
+                    doc: /* Pretty name of current buffer's major mode.
+Usually a string, but can use any of the constructs for `mode-line-format',
+which see.
+Format with `format-mode-line' to produce a string value.  */);
 
   DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
                     doc: /* Local (mode-specific) abbrev table of current buffer.  */);
@@ -5587,17 +5758,17 @@ its hooks should not expect certain variables such as
                     doc: /* *Non-nil if searches and matches should ignore case.  */);
 
   DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* *Column beyond which automatic line-wrapping should happen.
 Interactively, you can set the buffer local value using \\[set-fill-column].  */);
 
   DEFVAR_PER_BUFFER ("left-margin", &current_buffer->left_margin,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* *Column for the default `indent-line-function' to indent to.
 Linefeed indents to this column in Fundamental mode.  */);
 
   DEFVAR_PER_BUFFER ("tab-width", &current_buffer->tab_width,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* *Distance between tab stops (for display of tab characters), in columns.  */);
 
   DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow, Qnil,
@@ -5618,7 +5789,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;
+  XSYMBOL (intern_c_string ("enable-multibyte-characters"))->constant = 1;
 
   DEFVAR_PER_BUFFER ("buffer-file-coding-system",
                     &current_buffer->buffer_file_coding_system, Qnil,
@@ -5650,6 +5821,18 @@ Note that this is overridden by the variable
 `truncate-partial-width-windows' if that variable is non-nil
 and this buffer is not full-frame width.  */);
 
+  DEFVAR_PER_BUFFER ("word-wrap", &current_buffer->word_wrap, Qnil,
+                    doc: /* *Non-nil means to use word-wrapping for continuation lines.
+When word-wrapping is on, continuation lines are wrapped at the space
+or tab character nearest to the right window edge.
+If nil, continuation lines are wrapped at the right screen edge.
+
+This variable has no effect if long lines are truncated (see
+`truncate-lines' and `truncate-partial-width-windows').  If you use
+word-wrapping, you might want to reduce the value of
+`truncate-partial-width-windows', since wrapping can make text readable
+in narrower windows.  */);
+
 #ifdef DOS_NT
   DEFVAR_PER_BUFFER ("buffer-file-type", &current_buffer->buffer_file_type,
                     Qnil,
@@ -5696,9 +5879,14 @@ If it is nil, that means don't auto-save this buffer.  */);
 Backing up is done before the first time the file is saved.  */);
 
   DEFVAR_PER_BUFFER ("buffer-saved-size", &current_buffer->save_length,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* Length of current buffer when last read in, saved or auto-saved.
-0 initially.  */);
+0 initially.
+-1 means auto-saving turned off until next real save.
+
+If you set this to -2, that means don't turn off auto-saving in this buffer
+if its text size shrinks.   If you use `buffer-swap-text' on a buffer,
+you probably should set this to -2 in that buffer.  */);
 
   DEFVAR_PER_BUFFER ("selective-display", &current_buffer->selective_display,
                     Qnil,
@@ -5711,7 +5899,7 @@ in a file, save the ^M as a newline.  */);
 
 #ifndef old
   DEFVAR_PER_BUFFER ("selective-display-ellipses",
-                   &current_buffer->selective_display_ellipses,
+                    &current_buffer->selective_display_ellipses,
                     Qnil,
                     doc: /* Non-nil means display ... on previous line when a line is invisible.  */);
 #endif
@@ -5844,14 +6032,14 @@ fringe indicator.
 
 INDICATOR specifies the logical indicator type which is one of the
 following symbols: `truncation' , `continuation', `overlay-arrow',
-`top', `bottom', `up', `down', `one-line', `empty-line', or `unknown'.
+`top', `bottom', `top-bottom', `up', `down', empty-line', or `unknown'.
 
-BITMAPS is list of symbols (LEFT RIGHT [LEFT1 RIGHT1]) which specifies
+BITMAPS is list of symbols (LEFT RIGHT [LEFT1 RIGHT1]) which specifies
 the actual bitmap shown in the left or right fringe for the logical
 indicator.  LEFT and RIGHT are the bitmaps shown in the left and/or
 right fringe for the specific indicator.  The LEFT1 or RIGHT1 bitmaps
-are used only for the `bottom' and `one-line' indicators when the last
-\(only) line in has no final newline.  BITMAPS may also be a single
+are used only for the `bottom' and `top-bottom' indicators when the
+last (only) line has no final newline.  BITMAPS may also be a single
 symbol which is used in both left and right fringes.  */);
 
   DEFVAR_PER_BUFFER ("fringe-cursor-alist",
@@ -5876,10 +6064,10 @@ If you move point off the bottom, the window scrolls automatically.
 This variable controls how far it scrolls.  The value nil, the default,
 means scroll to center point.  A fraction means scroll to put point
 that fraction of the window's height from the bottom of the window.
-When the value is 0.0, point goes at the bottom line, which in the simple
-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
-scrolls by a full window height.  Meaningful values are
+When the value is 0.0, point goes at the bottom line, which in the
+simple 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 scrolls by a full window height.  Meaningful values are
 between 0.0 and 1.0, inclusive.  */);
 
   DEFVAR_PER_BUFFER ("scroll-down-aggressively",
@@ -5889,10 +6077,10 @@ If you move point off the top, the window scrolls automatically.
 This variable controls how far it scrolls.  The value nil, the default,
 means scroll to center point.  A fraction means scroll to put point
 that fraction of the window's height from the top of the window.
-When the value is 0.0, point goes at the top line, which in the simple
-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
-scrolls by a full window height.  Meaningful values are
+When the value is 0.0, point goes at the top line, which in the
+simple 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 scrolls by a full window height.  Meaningful values are
 between 0.0 and 1.0, inclusive.  */);
 
 /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
@@ -5909,8 +6097,8 @@ No information is given about the length of the text after the change.
 Buffer changes made while executing the `before-change-functions'
 don't call any before-change or after-change functions.
 That's because these variables are temporarily set to nil.
-As a result, a hook function cannot straightforwardly alter the value of
-these variables.  See the Emacs Lisp manual for a way of
+As a result, a hook function cannot straightforwardly alter the
+value of these variables.  See the Emacs Lisp manual for a way of
 accomplishing an equivalent result by using other variables.
 
 If an unhandled error happens in running these functions,
@@ -5930,8 +6118,8 @@ and the post-change beginning and end are at the same place.)
 Buffer changes made while executing the `after-change-functions'
 don't call any before-change or after-change functions.
 That's because these variables are temporarily set to nil.
-As a result, a hook function cannot straightforwardly alter the value of
-these variables.  See the Emacs Lisp manual for a way of
+As a result, a hook function cannot straightforwardly alter the
+value of these variables.  See the Emacs Lisp manual for a way of
 accomplishing an equivalent result by using other variables.
 
 If an unhandled error happens in running these functions,
@@ -6055,18 +6243,11 @@ to the value obtained by calling `current-time'.
 If the buffer has never been shown in a window, the value is nil.  */);
 
   DEFVAR_LISP ("transient-mark-mode", &Vtransient_mark_mode,
-              doc: /* *Non-nil means deactivate the mark when the buffer contents change.
-Non-nil also enables highlighting of the region whenever the mark is active.
-The variable `highlight-nonselected-windows' controls whether to highlight
-all windows or just the selected window.
-
-If the value is `lambda', that enables Transient Mark mode temporarily
-until the next buffer modification.  If a command sets the value to `only',
-that enables Transient Mark mode for the following command only.
-During that following command, the value of `transient-mark-mode'
-is `identity'.  If it is still `identity' at the end of that command,
-it changes to nil.  */);
+              doc: /* */);
   Vtransient_mark_mode = Qnil;
+  /* The docstring is in simple.el.  If we put it here, it would be
+     overwritten when transient-mark-mode is defined using
+     define-minor-mode.  */
 
   DEFVAR_LISP ("inhibit-read-only", &Vinhibit_read_only,
               doc: /* *Non-nil means disregard read-only status of buffers or characters.
@@ -6090,13 +6271,15 @@ Values are interpreted as follows:
   (hbar . HEIGHT) display a horizontal bar cursor with height HEIGHT
   ANYTHING ELSE          display a hollow box cursor
 
-When the buffer is displayed in a nonselected window,
-this variable has no effect; the cursor appears as a hollow box.  */);
+When the buffer is displayed in a non-selected window, the
+cursor's appearance is instead controlled by the variable
+`cursor-in-non-selected-windows'.  */);
 
   DEFVAR_PER_BUFFER ("line-spacing",
                     &current_buffer->extra_line_spacing, Qnil,
                     doc: /* Additional space to put between lines when displaying a buffer.
-The space is measured in pixels, and put below lines on window systems.
+The space is measured in pixels, and put below lines on graphic displays,
+see `display-graphic-p'.
 If value is a floating point number, it specifies the spacing relative
 to the default frame line height.  A value of nil means add no extra space.  */);
 
@@ -6115,7 +6298,7 @@ If any of them returns nil, the buffer is not killed.  */);
               doc: /* Normal hook run before changing the major mode of a buffer.
 The function `kill-all-local-variables' runs this before doing anything else.  */);
   Vchange_major_mode_hook = Qnil;
-  Qchange_major_mode_hook = intern ("change-major-mode-hook");
+  Qchange_major_mode_hook = intern_c_string ("change-major-mode-hook");
   staticpro (&Qchange_major_mode_hook);
 
   defsubr (&Sbuffer_live_p);
@@ -6141,12 +6324,12 @@ The function `kill-all-local-variables' runs this before doing anything else.  *
   defsubr (&Skill_buffer);
   defsubr (&Sset_buffer_major_mode);
   defsubr (&Sswitch_to_buffer);
-  defsubr (&Spop_to_buffer);
   defsubr (&Scurrent_buffer);
   defsubr (&Sset_buffer);
   defsubr (&Sbarf_if_buffer_read_only);
   defsubr (&Sbury_buffer);
   defsubr (&Serase_buffer);
+  defsubr (&Sbuffer_swap_text);
   defsubr (&Sset_buffer_multibyte);
   defsubr (&Skill_all_local_variables);
 
@@ -6177,7 +6360,7 @@ keys_of_buffer ()
 
   /* This must not be in syms_of_buffer, because Qdisabled is not
      initialized when that function gets called.  */
-  Fput (intern ("erase-buffer"), Qdisabled, Qt);
+  Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt);
 }
 
 /* arch-tag: e48569bf-69a9-4b65-a23b-8e68769436e1