(enlarge_buffer_text): Fix int -> EMACS_INT.
[bpt/emacs.git] / src / buffer.c
index 8cd13b0..021867c 100644 (file)
@@ -1,7 +1,8 @@
 /* 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.
 
@@ -42,7 +43,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"
@@ -99,17 +100,6 @@ DECL_ALIGN (struct buffer, buffer_local_symbols);
 /* A Lisp_Object pointer to the above, used for staticpro */
 static Lisp_Object Vbuffer_local_symbols;
 
-/* This structure holds the required types for the values in the
-   buffer-local slots.  If a slot contains Qnil, then the
-   corresponding buffer slot may contain a value of any type.  If a
-   slot contains an integer, then prospective values' tags must be
-   equal to that integer (except nil is always allowed).
-   When a tag does not match, the function
-   buffer_slot_type_mismatch will signal an error.
-
-   If a slot here contains -1, the corresponding variable is read-only.  */
-struct buffer buffer_local_types;
-
 /* Flags indicating which built-in buffer-local variables
    are permanent locals.  */
 static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS];
@@ -118,12 +108,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,
@@ -161,6 +153,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;
 
@@ -184,6 +177,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; */
@@ -359,9 +353,7 @@ The value is never nil.  */)
   if (SCHARS (name) == 0)
     error ("Empty string for buffer name is not allowed");
 
-  b = (struct buffer *) allocate_buffer ();
-
-  b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
+  b = allocate_buffer ();
 
   /* An ordinary buffer uses its own struct buffer_text.  */
   b->text = &b->own_text;
@@ -416,10 +408,7 @@ The value is never nil.  */)
   STRING_SET_INTERVALS (name, NULL_INTERVAL);
   b->name = name;
 
-  if (SREF (name, 0) != ' ')
-    b->undo_list = Qnil;
-  else
-    b->undo_list = Qt;
+  b->undo_list = (SREF (name, 0) != ' ') ? Qnil : Qt;
 
   reset_buffer (b);
   reset_buffer_local_variables (b, 1);
@@ -507,7 +496,9 @@ 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) + sizeof (Lisp_Object);
        offset < sizeof *to;
        offset += sizeof (Lisp_Object))
     {
@@ -565,13 +556,11 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
   if (SCHARS (name) == 0)
     error ("Empty string for buffer name is not allowed");
 
-  b = (struct buffer *) allocate_buffer ();
-  b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
+  b = allocate_buffer ();
 
-  if (XBUFFER (base_buffer)->base_buffer)
-    b->base_buffer = XBUFFER (base_buffer)->base_buffer;
-  else
-    b->base_buffer = XBUFFER (base_buffer);
+  b->base_buffer = (XBUFFER (base_buffer)->base_buffer
+                   ? XBUFFER (base_buffer)->base_buffer
+                   : XBUFFER (base_buffer));
 
   /* Use the base buffer's text object.  */
   b->text = b->base_buffer->text;
@@ -734,7 +723,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.  */
 
@@ -772,7 +761,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);
@@ -780,7 +810,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))
     {
@@ -902,8 +934,7 @@ is the default binding of the variable. */)
   CHECK_BUFFER (buffer);
   buf = XBUFFER (buffer);
 
-  if (SYMBOLP (variable))
-    variable = indirect_variable (variable);
+  variable = indirect_variable (variable);
 
   /* Look in local_var_list */
   result = Fassoc (variable, buf->local_var_alist);
@@ -913,7 +944,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)))
@@ -1024,7 +1057,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)))
@@ -1188,7 +1223,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.
@@ -1597,7 +1634,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))
@@ -1765,7 +1802,10 @@ 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);
 }
@@ -1916,8 +1956,7 @@ set_buffer_internal_1 (b)
   for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail))
     {
       valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
-      if ((BUFFER_LOCAL_VALUEP (valcontents)
-          || SOME_BUFFER_LOCAL_VALUEP (valcontents))
+      if ((BUFFER_LOCAL_VALUEP (valcontents))
          && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
              (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
        /* Just reference the variable
@@ -1931,8 +1970,7 @@ set_buffer_internal_1 (b)
     for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
       {
        valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
-       if ((BUFFER_LOCAL_VALUEP (valcontents)
-            || SOME_BUFFER_LOCAL_VALUEP (valcontents))
+       if ((BUFFER_LOCAL_VALUEP (valcontents))
            && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
                (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
          /* Just reference the variable
@@ -2177,13 +2215,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)
@@ -2257,11 +2392,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.  */
@@ -2276,6 +2411,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));
@@ -2284,13 +2424,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;
@@ -2309,6 +2450,7 @@ current buffer is cleared.  */)
       pos = BEG;
       stop = GPT;
       p = BEG_ADDR;
+      pend = GPT_ADDR;
       while (1)
        {
          int bytes;
@@ -2318,16 +2460,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--;
@@ -2341,6 +2488,7 @@ current buffer is cleared.  */)
                zv += bytes;
              if (pos <= pt)
                pt += bytes;
+             pend = Z_ADDR;
              stop = Z;
            }
        }
@@ -2472,14 +2620,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);
@@ -2488,20 +2632,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; !NILP (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++;
@@ -2521,32 +2651,17 @@ swap_out_buffer_local_variables (b)
   XSETBUFFER (buffer, b);
   oalist = b->local_var_alist;
 
-  for (alist = oalist; !NILP (alist); alist = XCDR (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 (BUFFERP (tem) && XBUFFER (tem) == current_buffer)
+      if (EQ (tem, buffer))
        {
-         /* Symbol is set up for this buffer's old local value.
-            Set it up for the current buffer with the default value.  */
-
-         tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->cdr;
-         /* Store the symbol's current value into the alist entry
-            it is currently set up for.  This is so that, if the
-            local is marked permanent, and we make it local again
-            later in Fkill_all_local_variables, we don't lose the value.  */
-         XSETCDR (XCAR (tem),
-                  do_symval_forwarding (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->realvalue));
-         /* Switch to the symbol's default-value alist entry.  */
-         XSETCAR (tem, tem);
-         /* Mark it as current for buffer B.  */
-         XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer = buffer;
-         /* Store the current value into any forwarding in the symbol.  */
-         store_symval_forwarding (sym,
-                                  XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->realvalue,
-                                  XCDR (tem), NULL);
+         /* Symbol is set up for this buffer's old local value:
+            swap it out!  */
+         swap_in_global_binding (sym);
        }
     }
 }
@@ -2579,8 +2694,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;
@@ -2698,8 +2813,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.
@@ -2734,6 +2850,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)
     {
@@ -2751,10 +2868,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)
            {
@@ -2799,10 +2918,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)
            {
@@ -2881,7 +3002,7 @@ overlay_touches_p (pos)
       int endpos;
 
       XSETMISC (overlay ,tail);
-      if (!GC_OVERLAYP (overlay))
+      if (!OVERLAYP (overlay))
        abort ();
 
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -2896,7 +3017,7 @@ overlay_touches_p (pos)
       int startpos;
 
       XSETMISC (overlay, tail);
-      if (!GC_OVERLAYP (overlay))
+      if (!OVERLAYP (overlay))
        abort ();
 
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
@@ -3967,7 +4088,7 @@ OVERLAY.  */)
 
 \f
 DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
-       doc: /* Return a list of the overlays that contain position POS.  */)
+       doc: /* Return a list of the overlays that contain the character at POS.  */)
      (pos)
      Lisp_Object pos;
 {
@@ -3985,7 +4106,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);
@@ -3998,8 +4119,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;
 {
@@ -4035,7 +4157,7 @@ the value is (point-max).  */)
      Lisp_Object pos;
 {
   int noverlays;
-  int endpos;
+  EMACS_INT endpos;
   Lisp_Object *overlay_vec;
   int len;
   int i;
@@ -4049,14 +4171,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);
@@ -4077,7 +4199,7 @@ the value is (point-min).  */)
      Lisp_Object pos;
 {
   int noverlays;
-  int prevpos;
+  EMACS_INT prevpos;
   Lisp_Object *overlay_vec;
   int len;
 
@@ -4095,7 +4217,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);
@@ -4216,17 +4338,12 @@ add_overlay_mod_hooklist (functionlist, overlay)
   int oldsize = XVECTOR (last_overlay_modification_hooks)->size;
 
   if (last_overlay_modification_hooks_used == oldsize)
-    {
-      Lisp_Object old;
-      old = last_overlay_modification_hooks;
-      last_overlay_modification_hooks
-       = Fmake_vector (make_number (oldsize * 2), Qnil);
-      bcopy (XVECTOR (old)->contents,
-            XVECTOR (last_overlay_modification_hooks)->contents,
-            sizeof (Lisp_Object) * oldsize);
-    }
-  AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = functionlist;
-  AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = overlay;
+    last_overlay_modification_hooks = larger_vector 
+      (last_overlay_modification_hooks, oldsize * 2, Qnil);
+  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
@@ -4434,13 +4551,13 @@ evaporate_overlays (pos)
    in the slot with offset OFFSET.  */
 
 void
-buffer_slot_type_mismatch (offset)
-     int offset;
+buffer_slot_type_mismatch (sym, type)
+     Lisp_Object sym;
+     int type;
 {
-  Lisp_Object sym;
   char *type_name;
 
-  switch (XINT (PER_BUFFER_TYPE (offset)))
+  switch (type)
     {
     case Lisp_Int:
       type_name = "integers";
@@ -4458,7 +4575,6 @@ buffer_slot_type_mismatch (offset)
       abort ();
     }
 
-  sym = PER_BUFFER_SYMBOL (offset);
   error ("Only %s should be stored in the buffer-local variable %s",
         type_name, SDATA (SYMBOL_NAME (sym)));
 }
@@ -4965,9 +5081,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
@@ -5036,7 +5150,9 @@ init_buffer_once ()
   buffer_local_symbols.text = &buffer_local_symbols.own_text;
   BUF_INTERVALS (&buffer_defaults) = 0;
   BUF_INTERVALS (&buffer_local_symbols) = 0;
+  XSETPVECTYPE (&buffer_defaults, PVEC_BUFFER);
   XSETBUFFER (Vbuffer_defaults, &buffer_defaults);
+  XSETPVECTYPE (&buffer_local_symbols, PVEC_BUFFER);
   XSETBUFFER (Vbuffer_local_symbols, &buffer_local_symbols);
 
   /* Set up the default values of various buffer slots.  */
@@ -5275,6 +5391,46 @@ init_buffer ()
   free (pwd);
 }
 
+/* Similar to defvar_lisp but define a variable whose value is the Lisp
+   Object stored in the current buffer.  address is the address of the slot
+   in the buffer that is current now. */
+
+/* TYPE is nil for a general Lisp variable.
+   An integer specifies a type; then only LIsp values
+   with that type code are allowed (except that nil is allowed too).
+   LNAME is the LIsp-level variable name.
+   VNAME is the name of the buffer slot.
+   DOC is a dummy where you write the doc string as a comment.  */
+#define DEFVAR_PER_BUFFER(lname, vname, type, doc)  \
+ defvar_per_buffer (lname, vname, type, 0)
+
+static void
+defvar_per_buffer (namestring, address, type, doc)
+     char *namestring;
+     Lisp_Object *address;
+     Lisp_Object type;
+     char *doc;
+{
+  Lisp_Object sym, val;
+  int offset;
+
+  sym = intern (namestring);
+  val = allocate_misc ();
+  offset = (char *)address - (char *)current_buffer;
+
+  XMISCTYPE (val) = Lisp_Misc_Buffer_Objfwd;
+  XBUFFER_OBJFWD (val)->offset = offset;
+  XBUFFER_OBJFWD (val)->slottype = type;
+  SET_SYMBOL_VALUE (sym, val);
+  PER_BUFFER_SYMBOL (offset) = sym;
+
+  if (PER_BUFFER_IDX (offset) == 0)
+    /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
+       slot of buffer_local_flags */
+    abort ();
+}
+
+
 /* initialize the buffer routines */
 void
 syms_of_buffer ()
@@ -5291,6 +5447,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);
@@ -5318,6 +5476,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");
@@ -5558,7 +5717,12 @@ 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.  */);
 
   DEFVAR_PER_BUFFER ("abbrev-mode", &current_buffer->abbrev_mode, Qnil,
                     doc: /* Non-nil turns on automatic expansion of abbrevs as they are inserted.  */);
@@ -6128,6 +6292,7 @@ The function `kill-all-local-variables' runs this before doing anything else.  *
   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);