(x_set_frame_alpha): Fix logic.
[bpt/emacs.git] / src / buffer.c
index ad76c18..2ba2192 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
+                 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>
 
@@ -42,7 +41,7 @@ extern int errno;
 #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"
@@ -107,12 +106,14 @@ static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS];
 
 int last_per_buffer_idx;
 
-Lisp_Object Fset_buffer ();
-void set_buffer_internal ();
-void set_buffer_internal_1 ();
-static void call_overlay_mod_hooks ();
-static void swap_out_buffer_local_variables ();
-static void reset_buffer_local_variables ();
+EXFUN (Fset_buffer, 1);
+void set_buffer_internal P_ ((struct buffer *b));
+void set_buffer_internal_1 P_ ((struct buffer *b));
+static void call_overlay_mod_hooks P_ ((Lisp_Object list, Lisp_Object overlay,
+                                       int after, Lisp_Object arg1,
+                                       Lisp_Object arg2, Lisp_Object arg3));
+static void swap_out_buffer_local_variables P_ ((struct buffer *b));
+static void reset_buffer_local_variables P_ ((struct buffer *b, int permanent_too));
 
 /* Alist of all buffer names vs the buffers. */
 /* This used to be a variable, but is no longer,
@@ -150,6 +151,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;
 
@@ -173,6 +175,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 *));
 
+extern char * emacs_strerror P_ ((int));
 
 /* For debugging; temporary.  See set_buffer_internal.  */
 /* Lisp_Object Qlisp_mode, Vcheck_symbol; */
@@ -491,12 +494,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))
        {
@@ -716,7 +725,7 @@ reset_buffer (b)
    it does not treat permanent locals consistently.
    Instead, use Fkill_all_local_variables.
 
-   If PERMANENT_TOO is 1, then we reset permanent built-in
+   If PERMANENT_TOO is 1, then we reset permanent
    buffer-local variables.  If PERMANENT_TOO is 0,
    we preserve those.  */
 
@@ -754,7 +763,48 @@ reset_buffer_local_variables (b, permanent_too)
 #endif
 
   /* Reset all (or most) per-buffer variables to their defaults.  */
-  b->local_var_alist = Qnil;
+  if (permanent_too)
+    b->local_var_alist = Qnil;
+  else
+    {
+      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 (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
+         XSETCDR (last, XCDR (tmp));
+    }
+
   for (i = 0; i < last_per_buffer_idx; ++i)
     if (permanent_too || buffer_permanent_local_flags[i] == 0)
       SET_PER_BUFFER_VALUE_P (b, i, 0);
@@ -762,7 +812,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))
     {
@@ -879,12 +931,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);
@@ -894,7 +948,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)))
@@ -919,7 +975,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);
 
@@ -1005,7 +1061,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)))
@@ -1169,7 +1227,9 @@ buffer as BUFFER.  */)
 }
 \f
 DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2,
-       "sRename buffer (to new name): \nP",
+       "(list (read-string \"Rename buffer (to new name): \" \
+             nil 'buffer-name-history (buffer-name (current-buffer))) \
+             current-prefix-arg)",
        doc: /* Change current buffer's name to NEWNAME (a string).
 If second arg UNIQUE is nil or omitted, it is an error if a
 buffer named NEWNAME already exists.
@@ -1578,7 +1638,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))
@@ -1711,7 +1771,8 @@ switch_to_buffer_1 (buffer, norecord)
   return buf;
 }
 
-DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "BSwitch to buffer: ",
+DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2,
+       "(list (read-buffer-to-switch \"Switch 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.
@@ -1746,47 +1807,14 @@ the window-buffer correspondences.  */)
     }
 
   err = no_switch_window (selected_window);
-  if (err) error (err);
+  if (err)
+    /* If can't display in current window, let pop-to-buffer
+       try some other window. */
+    return call3 (intern ("pop-to-buffer"), buffer, Qnil, norecord);
 
   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
-    {
-      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;
-}
-
 DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
        doc: /* Return the current buffer as a Lisp object.  */)
      ()
@@ -2156,13 +2184,110 @@ advance_to_char_boundary (byte_pos)
   return byte_pos;
 }
 
+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);
+
+  /* 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);
+  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);
+  if (MARKERP (current_buffer->mark) && XMARKER (current_buffer->mark)->buffer)
+    XMARKER (current_buffer->mark)->buffer = current_buffer;
+  if (MARKERP (other_buffer->mark) && XMARKER (other_buffer->mark)->buffer)
+    XMARKER (other_buffer->mark)->buffer = other_buffer;
+  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 = current_buffer->text->gpt;
+  other_buffer->text->end_unchanged = current_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;
+    for (m = BUF_MARKERS (other_buffer); m; m = m->next)
+      if (m->buffer == current_buffer)
+       m->buffer = other_buffer;
+  }
+  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.
-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)
@@ -2236,11 +2361,11 @@ current buffer is cleared.  */)
              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, stop - pos, bytes);
              /* Delete all bytes for this 8-bit character but the
                 last one, and change the last one to the charcter
                 code.  */
@@ -2255,6 +2380,11 @@ current buffer is cleared.  */)
                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));
@@ -2263,13 +2393,14 @@ current buffer is cleared.  */)
     {
       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.
-        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;
@@ -2288,6 +2419,7 @@ current buffer is cleared.  */)
       pos = BEG;
       stop = GPT;
       p = BEG_ADDR;
+      pend = GPT_ADDR;
       while (1)
        {
          int bytes;
@@ -2297,16 +2429,21 @@ current buffer is cleared.  */)
              if (pos == Z)
                break;
              p = GAP_END_ADDR;
+             pend = Z_ADDR;
              stop = Z;
            }
 
-         if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes))
+         if (ASCII_BYTE_P (*p))
+           p++, pos++;
+         else if (EQ (flag, Qt) && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0)
            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--;
@@ -2320,6 +2457,7 @@ current buffer is cleared.  */)
                zv += bytes;
              if (pos <= pt)
                pt += bytes;
+             pend = Z_ADDR;
              stop = Z;
            }
        }
@@ -2451,14 +2589,10 @@ The first thing this function does is run
 the normal hook `change-major-mode-hook'.  */)
      ()
 {
-  register Lisp_Object alist, sym, tem;
-  Lisp_Object oalist;
-
   if (!NILP (Vrun_hooks))
     call1 (Vrun_hooks, Qchange_major_mode_hook);
-  oalist = current_buffer->local_var_alist;
 
-  /* Make sure none of the bindings in oalist
+  /* Make sure none of the bindings in local_var_alist
      remain swapped in, in their symbols.  */
 
   swap_out_buffer_local_variables (current_buffer);
@@ -2467,20 +2601,6 @@ the normal hook `change-major-mode-hook'.  */)
 
   reset_buffer_local_variables (current_buffer, 0);
 
-  /* Any which are supposed to be permanent,
-     make local again, with the same values they had.  */
-
-  for (alist = oalist; CONSP (alist); alist = XCDR (alist))
-    {
-      sym = XCAR (XCAR (alist));
-      tem = Fget (sym, Qpermanent_local);
-      if (! NILP (tem))
-       {
-         Fmake_local_variable (sym);
-         Fset (sym, XCDR (XCAR (alist)));
-       }
-    }
-
   /* Force mode-line redisplay.  Useful here because all major mode
      commands call this function.  */
   update_mode_lines++;
@@ -2543,8 +2663,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;
@@ -2662,8 +2782,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.
@@ -2698,6 +2819,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)
     {
@@ -2715,10 +2837,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)
            {
@@ -2763,10 +2887,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)
            {
@@ -2845,7 +2971,7 @@ overlay_touches_p (pos)
       int endpos;
 
       XSETMISC (overlay ,tail);
-      if (!GC_OVERLAYP (overlay))
+      if (!OVERLAYP (overlay))
        abort ();
 
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -2860,7 +2986,7 @@ overlay_touches_p (pos)
       int startpos;
 
       XSETMISC (overlay, tail);
-      if (!GC_OVERLAYP (overlay))
+      if (!OVERLAYP (overlay))
        abort ();
 
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
@@ -3949,7 +4075,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);
@@ -3962,8 +4088,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;
 {
@@ -3999,7 +4126,7 @@ the value is (point-max).  */)
      Lisp_Object pos;
 {
   int noverlays;
-  int endpos;
+  EMACS_INT endpos;
   Lisp_Object *overlay_vec;
   int len;
   int i;
@@ -4013,14 +4140,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);
@@ -4041,7 +4168,7 @@ the value is (point-min).  */)
      Lisp_Object pos;
 {
   int noverlays;
-  int prevpos;
+  EMACS_INT prevpos;
   Lisp_Object *overlay_vec;
   int len;
 
@@ -4059,7 +4186,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);
@@ -4182,8 +4309,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
@@ -4391,32 +4520,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
@@ -4921,9 +5039,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
@@ -5023,6 +5139,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;
@@ -5095,6 +5212,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;
@@ -5289,6 +5407,8 @@ syms_of_buffer ()
   staticpro (&Vbuffer_alist);
   staticpro (&Qprotected_field);
   staticpro (&Qpermanent_local);
+  Qpermanent_local_hook = intern ("permanent-local-hook");
+  staticpro (&Qpermanent_local_hook);
   staticpro (&Qkill_buffer_hook);
   Qoverlayp = intern ("overlayp");
   staticpro (&Qoverlayp);
@@ -5316,6 +5436,7 @@ syms_of_buffer ()
   staticpro (&Qbefore_change_functions);
   Qafter_change_functions = intern ("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");
@@ -5556,7 +5677,9 @@ its hooks should not expect certain variables such as
 
   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.  See `mode-line-format' for other possible forms.
+Use the function `format-mode-line' to get the value as a string.  */);
 
   DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
                     doc: /* Local (mode-specific) abbrev table of current buffer.  */);
@@ -5632,6 +5755,15 @@ 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').  */);
+
 #ifdef DOS_NT
   DEFVAR_PER_BUFFER ("buffer-file-type", &current_buffer->buffer_file_type,
                     Qnil,
@@ -6037,18 +6169,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.
@@ -6123,12 +6248,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);