]> code.delx.au - gnu-emacs/blobdiff - src/buffer.c
Fix for Bug#5984.
[gnu-emacs] / src / buffer.c
index 6cbaabf85eceec63ae2e8dac325d7ec2c77027f3..a0acad309af557c58fd40b49c55ae9d32e0612d4 100644 (file)
@@ -1,15 +1,15 @@
 /* Buffer manipulation primitives for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994,
                  1995, 1997, 1998, 1999, 2000, 2001, 2002,
 /* 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, 2008
+                 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
                  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
 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
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,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
 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>
 
 
 #include <config.h>
 
@@ -28,6 +26,7 @@ Boston, MA 02110-1301, USA.  */
 #include <sys/param.h>
 #include <errno.h>
 #include <stdio.h>
 #include <sys/param.h>
 #include <errno.h>
 #include <stdio.h>
+#include <setjmp.h>
 
 #ifndef USE_CRT_DLL
 extern int errno;
 
 #ifndef USE_CRT_DLL
 extern int errno;
@@ -43,7 +42,7 @@ extern int errno;
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
-#include "charset.h"
+#include "character.h"
 #include "region-cache.h"
 #include "indent.h"
 #include "blockinput.h"
 #include "region-cache.h"
 #include "indent.h"
 #include "blockinput.h"
@@ -153,6 +152,7 @@ Lisp_Object Qucs_set_table_for_input;
 int inhibit_modification_hooks;
 
 Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
 int inhibit_modification_hooks;
 
 Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
+Lisp_Object Qpermanent_local_hook;
 
 Lisp_Object Qprotected_field;
 
 
 Lisp_Object Qprotected_field;
 
@@ -176,6 +176,7 @@ static struct Lisp_Overlay * copy_overlays P_ ((struct buffer *, struct Lisp_Ove
 static void modify_overlay P_ ((struct buffer *, EMACS_INT, EMACS_INT));
 static Lisp_Object buffer_lisp_local_variables P_ ((struct buffer *));
 
 static void modify_overlay P_ ((struct buffer *, EMACS_INT, EMACS_INT));
 static Lisp_Object buffer_lisp_local_variables P_ ((struct buffer *));
 
+extern char * emacs_strerror P_ ((int));
 
 /* For debugging; temporary.  See set_buffer_internal.  */
 /* Lisp_Object Qlisp_mode, Vcheck_symbol; */
 
 /* For debugging; temporary.  See set_buffer_internal.  */
 /* Lisp_Object Qlisp_mode, Vcheck_symbol; */
@@ -266,17 +267,18 @@ assoc_ignore_text_properties (key, list)
 }
 
 DEFUN ("get-buffer", Fget_buffer, Sget_buffer, 1, 1, 0,
 }
 
 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,
 }
 
 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,
 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;
 
   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 ();
     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;
 
   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;
 
   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.  */
   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)))
 
   /* 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);
 
 
   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;
 
        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))
        {
       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->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;
   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
     {
     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)))
       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
        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 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))
     {
        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.
 \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;
 {
      (buffer)
      register Lisp_Object buffer;
 {
@@ -898,12 +937,14 @@ is the default binding of the variable. */)
 {
   register struct buffer *buf;
   register Lisp_Object result;
 {
   register struct buffer *buf;
   register Lisp_Object result;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
   CHECK_BUFFER (buffer);
   buf = XBUFFER (buffer);
 
 
   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);
 
   /* 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 */
       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)))
           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?  */
       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);
 
       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;
 
   {
     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)))
         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 */
 
     }
 #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
 
   /* 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'."
  */
 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.  */)
 
 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;
 
   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
   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))
 
   /* 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))
     {
   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;
       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.  */
      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))
     return Qnil;
 
   if (NILP (b->name))
@@ -1430,16 +1494,16 @@ with SIGHUP.  */)
     {
       struct buffer *other;
 
     {
       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))
          {
 
       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;
          }
 
       UNGCPRO;
@@ -1450,7 +1514,7 @@ with SIGHUP.  */)
      and give up if so.  */
   if (b == current_buffer)
     {
      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;
       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))
     {
   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;
     }
 
        return Qnil;
     }
 
@@ -1473,8 +1537,8 @@ with SIGHUP.  */)
   unlock_buffer (b);
 #endif /* CLASH_DETECTION */
 
   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
   UNGCPRO;
 
   /* Killing buffer processes may run sentinels which may
@@ -1487,16 +1551,16 @@ with SIGHUP.  */)
 
   tem = Vinhibit_quit;
   Vinhibit_quit = Qt;
 
   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)
   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"))))
     {
       && 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.  */
   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))
   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);
 }
 
   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 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
     {
   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))
   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,
 
   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
 
 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;
 
 {
   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.  */
 
     {
       /* 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))
       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
   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,
 }
 
 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))
     {
 
   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))))
          && (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)));
     }
 
        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))
       {
   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))))
            && (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)));
       }
 }
          Fsymbol_value (XCAR (XCAR (tail)));
       }
 }
@@ -2003,23 +2031,23 @@ set_buffer_temp (b)
 }
 
 DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
 }
 
 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");
     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.  */
 }
 
 /* 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, "",
 }
 
 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;
 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.  */
   /* Figure out what buffer we're going to bury.  */
-  if (NILP (buffer))
+  if (NILP (buffer_or_name))
     {
       Lisp_Object tem;
       XSETBUFFER (buffer, current_buffer);
     {
       Lisp_Object tem;
       XSETBUFFER (buffer, current_buffer);
@@ -2075,12 +2109,9 @@ selected window if it is displayed there.  */)
     }
   else
     {
     }
   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
     }
 
   /* Move buffer to the end of the buffer list.  Do nothing if the
@@ -2177,13 +2208,148 @@ advance_to_char_boundary (byte_pos)
   return 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.
 If FLAG is t, this makes the buffer a multibyte buffer.
 If FLAG is nil, this makes the buffer a single-byte buffer.
 DEFUN ("set-buffer-multibyte", Fset_buffer_multibyte, Sset_buffer_multibyte,
        1, 1, 0,
        doc: /* Set the multibyte flag of the current buffer to FLAG.
 If FLAG is t, this makes the buffer a multibyte buffer.
 If FLAG is nil, this makes the buffer a single-byte buffer.
-The buffer contents remain unchanged as a sequence of bytes
-but the contents viewed as characters do change.
+In these cases, the buffer contents remain unchanged as a sequence of
+bytes but the contents viewed as characters do change.
+If FLAG is `to', this makes the buffer a multibyte buffer by changing
+all eight-bit bytes to eight-bit characters.
 If the multibyte flag was really changed, undo information of the
 current buffer is cleared.  */)
      (flag)
 If the multibyte flag was really changed, undo information of the
 current buffer is cleared.  */)
      (flag)
@@ -2257,11 +2423,11 @@ current buffer is cleared.  */)
              p = GAP_END_ADDR;
              stop = Z;
            }
              p = GAP_END_ADDR;
              stop = Z;
            }
-         if (MULTIBYTE_STR_AS_UNIBYTE_P (p, bytes))
-           p += bytes, pos += bytes;
-         else
+         if (ASCII_BYTE_P (*p))
+           p++, pos++;
+         else if (CHAR_BYTE8_HEAD_P (*p))
            {
            {
-             c = STRING_CHAR (p, stop - pos);
+             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.  */
              /* Delete all bytes for this 8-bit character but the
                 last one, and change the last one to the charcter
                 code.  */
@@ -2276,6 +2442,11 @@ current buffer is cleared.  */)
                zv -= bytes;
              stop = Z;
            }
                zv -= bytes;
              stop = Z;
            }
+         else
+           {
+             bytes = BYTES_BY_CHAR_HEAD (*p);
+             p += bytes, pos += bytes;
+           }
        }
       if (narrowed)
        Fnarrow_to_region (make_number (begv), make_number (zv));
        }
       if (narrowed)
        Fnarrow_to_region (make_number (begv), make_number (zv));
@@ -2284,13 +2455,14 @@ current buffer is cleared.  */)
     {
       int pt = PT;
       int pos, stop;
     {
       int pt = PT;
       int pos, stop;
-      unsigned char *p;
+      unsigned char *p, *pend;
 
       /* Be sure not to have a multibyte sequence striding over the GAP.
 
       /* Be sure not to have a multibyte sequence striding over the GAP.
-        Ex: We change this: "...abc\201 _GAP_ \241def..."
-            to: "...abc _GAP_ \201\241def..."  */
+        Ex: We change this: "...abc\302 _GAP_ \241def..."
+            to: "...abc _GAP_ \302\241def..."  */
 
 
-      if (GPT_BYTE > 1 && GPT_BYTE < Z_BYTE
+      if (EQ (flag, Qt)
+         && GPT_BYTE > 1 && GPT_BYTE < Z_BYTE
          && ! CHAR_HEAD_P (*(GAP_END_ADDR)))
        {
          unsigned char *p = GPT_ADDR - 1;
          && ! CHAR_HEAD_P (*(GAP_END_ADDR)))
        {
          unsigned char *p = GPT_ADDR - 1;
@@ -2309,6 +2481,7 @@ current buffer is cleared.  */)
       pos = BEG;
       stop = GPT;
       p = BEG_ADDR;
       pos = BEG;
       stop = GPT;
       p = BEG_ADDR;
+      pend = GPT_ADDR;
       while (1)
        {
          int bytes;
       while (1)
        {
          int bytes;
@@ -2318,16 +2491,23 @@ current buffer is cleared.  */)
              if (pos == Z)
                break;
              p = GAP_END_ADDR;
              if (pos == Z)
                break;
              p = GAP_END_ADDR;
+             pend = Z_ADDR;
              stop = Z;
            }
 
              stop = Z;
            }
 
-         if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes))
+         if (ASCII_BYTE_P (*p))
+           p++, pos++;
+         else if (EQ (flag, Qt)
+                  && ! CHAR_BYTE8_HEAD_P (*p)
+                  && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0)
            p += bytes, pos += bytes;
          else
            {
              unsigned char tmp[MAX_MULTIBYTE_LENGTH];
            p += bytes, pos += bytes;
          else
            {
              unsigned char tmp[MAX_MULTIBYTE_LENGTH];
+             int c;
 
 
-             bytes = CHAR_STRING (*p, tmp);
+             c = BYTE8_TO_CHAR (*p);
+             bytes = CHAR_STRING (c, tmp);
              *p = tmp[0];
              TEMP_SET_PT_BOTH (pos + 1, pos + 1);
              bytes--;
              *p = tmp[0];
              TEMP_SET_PT_BOTH (pos + 1, pos + 1);
              bytes--;
@@ -2341,6 +2521,7 @@ current buffer is cleared.  */)
                zv += bytes;
              if (pos <= pt)
                pt += bytes;
                zv += bytes;
              if (pos <= pt)
                pt += bytes;
+             pend = Z_ADDR;
              stop = Z;
            }
        }
              stop = Z;
            }
        }
@@ -2498,18 +2679,19 @@ static void
 swap_out_buffer_local_variables (b)
      struct buffer *b;
 {
 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))
     {
 
   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!  */
        {
          /* Symbol is set up for this buffer's old local value:
             swap it out!  */
@@ -2546,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 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;
      int change_req;
 {
   Lisp_Object overlay, start, end;
@@ -2665,8 +2847,9 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
   return idx;
 }
 \f
   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.
 
    Return the number found, and store them in a vector in *VEC_PTR.
    Store in *LEN_PTR the size allocated for the vector.
@@ -2701,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 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)
     {
 
   for (tail = current_buffer->overlays_before; tail; tail = tail->next)
     {
@@ -2718,10 +2902,12 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
          break;
        }
       startpos = OVERLAY_POSITION (ostart);
          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)
       if ((beg < endpos && startpos < end)
-         || (startpos == endpos && beg == endpos))
+         || (startpos == endpos
+             && (beg == endpos || (end_is_Z && endpos == end))))
        {
          if (idx == len)
            {
        {
          if (idx == len)
            {
@@ -2766,10 +2952,12 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
          break;
        }
       endpos = OVERLAY_POSITION (oend);
          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)
       if ((beg < endpos && startpos < end)
-         || (startpos == endpos && beg == endpos))
+         || (startpos == endpos
+             && (beg == endpos || (end_is_Z && endpos == end))))
        {
          if (idx == len)
            {
        {
          if (idx == len)
            {
@@ -2848,7 +3036,7 @@ overlay_touches_p (pos)
       int endpos;
 
       XSETMISC (overlay ,tail);
       int endpos;
 
       XSETMISC (overlay ,tail);
-      if (!GC_OVERLAYP (overlay))
+      if (!OVERLAYP (overlay))
        abort ();
 
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
        abort ();
 
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -2863,7 +3051,7 @@ overlay_touches_p (pos)
       int startpos;
 
       XSETMISC (overlay, tail);
       int startpos;
 
       XSETMISC (overlay, tail);
-      if (!GC_OVERLAYP (overlay))
+      if (!OVERLAYP (overlay))
        abort ();
 
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
        abort ();
 
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
@@ -3952,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,
   /* 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);
 
   /* Make a list of them all.  */
   result = Flist (noverlays, overlay_vec);
@@ -3965,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.
        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;
 {
      (beg, end)
      Lisp_Object beg, end;
 {
@@ -4002,7 +4191,7 @@ the value is (point-max).  */)
      Lisp_Object pos;
 {
   int noverlays;
      Lisp_Object pos;
 {
   int noverlays;
-  int endpos;
+  EMACS_INT endpos;
   Lisp_Object *overlay_vec;
   int len;
   int i;
   Lisp_Object *overlay_vec;
   int len;
   int i;
@@ -4016,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,
      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;
 
   /* 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);
 
       oend = OVERLAY_END (overlay_vec[i]);
       oendpos = OVERLAY_POSITION (oend);
@@ -4044,7 +4233,7 @@ the value is (point-min).  */)
      Lisp_Object pos;
 {
   int noverlays;
      Lisp_Object pos;
 {
   int noverlays;
-  int prevpos;
+  EMACS_INT prevpos;
   Lisp_Object *overlay_vec;
   int len;
 
   Lisp_Object *overlay_vec;
   int len;
 
@@ -4062,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,
      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);
 
   xfree (overlay_vec);
   return make_number (prevpos);
@@ -4185,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);
   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
 }
 \f
 /* Run the modification-hooks of overlays that include
@@ -4394,32 +4585,21 @@ evaporate_overlays (pos)
    in the slot with offset OFFSET.  */
 
 void
    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;
 {
      int type;
 {
-  char *type_name;
+  Lisp_Object predicate;
 
   switch (type)
     {
 
   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
 }
 
 \f
@@ -4924,9 +5104,7 @@ alloc_buffer_text (b, nbytes)
    shrink it.  */
 
 void
    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
 {
   POINTER_TYPE *p;
   size_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
@@ -5004,7 +5182,7 @@ init_buffer_once ()
   /* Must do these before making the first buffer! */
 
   /* real setup is done in bindings.el */
   /* 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;
   buffer_defaults.header_line_format = Qnil;
   buffer_defaults.abbrev_mode = Qnil;
   buffer_defaults.overwrite_mode = Qnil;
@@ -5026,6 +5204,7 @@ init_buffer_once ()
 
   XSETFASTINT (buffer_defaults.tab_width, 8);
   buffer_defaults.truncate_lines = Qnil;
 
   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;
   buffer_defaults.ctl_arrow = Qt;
   buffer_defaults.direction_reversed = Qnil;
   buffer_defaults.cursor_type = Qt;
@@ -5098,6 +5277,7 @@ init_buffer_once ()
 #endif
   XSETFASTINT (buffer_local_flags.tab_width, idx); ++idx;
   XSETFASTINT (buffer_local_flags.truncate_lines, idx); ++idx;
 #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;
   XSETFASTINT (buffer_local_flags.ctl_arrow, idx); ++idx;
   XSETFASTINT (buffer_local_flags.fill_column, idx); ++idx;
   XSETFASTINT (buffer_local_flags.left_margin, idx); ++idx;
@@ -5142,28 +5322,27 @@ init_buffer_once ()
   current_buffer = 0;
   all_buffers = 0;
 
   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;
 
   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);
 
   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 */
 
   /* super-magic invisible buffer */
+  Vprin1_to_string_buffer = Fget_buffer_create (make_pure_c_string (" prin1"));
   Vbuffer_alist = Qnil;
 
   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;
 }
 
   inhibit_modification_hooks = 0;
 }
@@ -5197,18 +5376,18 @@ init_buffer ()
   if (!pwd)
     fatal ("`get_current_dir_name' failed: %s\n", strerror (errno));
 
   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'.  */
   /* 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';
     }
       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))
 
   current_buffer->directory = make_unibyte_string (pwd, strlen (pwd));
   if (! NILP (buffer_defaults.enable_multibyte_characters))
@@ -5292,42 +5471,45 @@ syms_of_buffer ()
   staticpro (&Vbuffer_alist);
   staticpro (&Qprotected_field);
   staticpro (&Qpermanent_local);
   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);
   staticpro (&Qkill_buffer_hook);
-  Qoverlayp = intern ("overlayp");
+  Qoverlayp = intern_c_string ("overlayp");
   staticpro (&Qoverlayp);
   staticpro (&Qoverlayp);
-  Qevaporate = intern ("evaporate");
+  Qevaporate = intern_c_string ("evaporate");
   staticpro (&Qevaporate);
   staticpro (&Qevaporate);
-  Qmodification_hooks = intern ("modification-hooks");
+  Qmodification_hooks = intern_c_string ("modification-hooks");
   staticpro (&Qmodification_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);
   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);
   staticpro (&Qinsert_behind_hooks);
-  Qget_file_buffer = intern ("get-file-buffer");
+  Qget_file_buffer = intern_c_string ("get-file-buffer");
   staticpro (&Qget_file_buffer);
   staticpro (&Qget_file_buffer);
-  Qpriority = intern ("priority");
+  Qpriority = intern_c_string ("priority");
   staticpro (&Qpriority);
   staticpro (&Qpriority);
-  Qwindow = intern ("window");
+  Qwindow = intern_c_string ("window");
   staticpro (&Qwindow);
   staticpro (&Qwindow);
-  Qbefore_string = intern ("before-string");
+  Qbefore_string = intern_c_string ("before-string");
   staticpro (&Qbefore_string);
   staticpro (&Qbefore_string);
-  Qafter_string = intern ("after-string");
+  Qafter_string = intern_c_string ("after-string");
   staticpro (&Qafter_string);
   staticpro (&Qafter_string);
-  Qfirst_change_hook = intern ("first-change-hook");
+  Qfirst_change_hook = intern_c_string ("first-change-hook");
   staticpro (&Qfirst_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);
   staticpro (&Qbefore_change_functions);
-  Qafter_change_functions = intern ("after-change-functions");
+  Qafter_change_functions = intern_c_string ("after-change-functions");
   staticpro (&Qafter_change_functions);
   staticpro (&Qafter_change_functions);
+  /* The next one is initialized in init_buffer_once.  */
   staticpro (&Qucs_set_table_for_input);
 
   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,
   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,
   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.  */
 
   /* All these use DEFVAR_LISP_NOPRO because the slots in
      buffer_defaults will all be marked via Vbuffer_defaults.  */
@@ -5543,24 +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,
 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),
 
   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.
 
   DEFVAR_PER_BUFFER ("mode-name", &current_buffer->mode_name,
                      Qnil,
                     doc: /* Pretty name of current buffer's major mode.
-Usually a string.  See `mode-line-format' for other possible forms.  */);
+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.  */);
 
   DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
                     doc: /* Local (mode-specific) abbrev table of current buffer.  */);
@@ -5573,17 +5758,17 @@ Usually a string.  See `mode-line-format' for other possible forms.  */);
                     doc: /* *Non-nil if searches and matches should ignore case.  */);
 
   DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
                     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,
                     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,
                     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,
                     doc: /* *Distance between tab stops (for display of tab characters), in columns.  */);
 
   DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow, Qnil,
@@ -5604,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'.  */);
 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,
 
   DEFVAR_PER_BUFFER ("buffer-file-coding-system",
                     &current_buffer->buffer_file_coding_system, Qnil,
@@ -5636,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.  */);
 
 `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,
 #ifdef DOS_NT
   DEFVAR_PER_BUFFER ("buffer-file-type", &current_buffer->buffer_file_type,
                     Qnil,
@@ -5682,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,
 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.
                     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,
 
   DEFVAR_PER_BUFFER ("selective-display", &current_buffer->selective_display,
                     Qnil,
@@ -5697,7 +5899,7 @@ in a file, save the ^M as a newline.  */);
 
 #ifndef old
   DEFVAR_PER_BUFFER ("selective-display-ellipses",
 
 #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
                     Qnil,
                     doc: /* Non-nil means display ... on previous line when a line is invisible.  */);
 #endif
@@ -5862,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.
 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",
 between 0.0 and 1.0, inclusive.  */);
 
   DEFVAR_PER_BUFFER ("scroll-down-aggressively",
@@ -5875,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.
 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,
 between 0.0 and 1.0, inclusive.  */);
 
 /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
@@ -5895,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.
 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,
 accomplishing an equivalent result by using other variables.
 
 If an unhandled error happens in running these functions,
@@ -5916,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.
 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,
 accomplishing an equivalent result by using other variables.
 
 If an unhandled error happens in running these functions,
@@ -6041,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,
 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;
   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.
 
   DEFVAR_LISP ("inhibit-read-only", &Vinhibit_read_only,
               doc: /* *Non-nil means disregard read-only status of buffers or characters.
@@ -6076,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
 
   (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.
 
   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.  */);
 
 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.  */);
 
@@ -6101,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;
               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);
   staticpro (&Qchange_major_mode_hook);
 
   defsubr (&Sbuffer_live_p);
@@ -6127,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 (&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 (&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);
 
   defsubr (&Sset_buffer_multibyte);
   defsubr (&Skill_all_local_variables);
 
@@ -6163,7 +6360,7 @@ keys_of_buffer ()
 
   /* This must not be in syms_of_buffer, because Qdisabled is not
      initialized when that function gets called.  */
 
   /* 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
 }
 
 /* arch-tag: e48569bf-69a9-4b65-a23b-8e68769436e1