Merge from emacs-24; up to 2014-04-02T16:17:08Z!dmantipov@yandex.ru
[bpt/emacs.git] / src / buffer.c
index 5853024..a22c6d7 100644 (file)
@@ -1,7 +1,6 @@
 /* Buffer manipulation primitives for GNU Emacs.
 
-Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation,
-Inc.
+Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -20,8 +19,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define BUFFER_INLINE EXTERN_INLINE
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/param.h>
@@ -156,7 +153,8 @@ CHECK_OVERLAY (Lisp_Object x)
   CHECK_TYPE (OVERLAYP (x), Qoverlayp, x);
 }
 
-/* These setters are used only in this file, so they can be private.  */
+/* These setters are used only in this file, so they can be private.
+   The public setters are inline functions defined in buffer.h.  */
 static void
 bset_abbrev_mode (struct buffer *b, Lisp_Object val)
 {
@@ -203,11 +201,6 @@ bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
   b->INTERNAL_FIELD (buffer_file_coding_system) = val;
 }
 static void
-bset_cache_long_scans (struct buffer *b, Lisp_Object val)
-{
-  b->INTERNAL_FIELD (cache_long_scans) = val;
-}
-static void
 bset_case_fold_search (struct buffer *b, Lisp_Object val)
 {
   b->INTERNAL_FIELD (case_fold_search) = val;
@@ -579,7 +572,8 @@ even if it is dead.  The return value is never nil.  */)
   BUF_END_UNCHANGED (b) = 0;
   BUF_BEG_UNCHANGED (b) = 0;
   *(BUF_GPT_ADDR (b)) = *(BUF_Z_ADDR (b)) = 0; /* Put an anchor '\0'.  */
-  b->text->inhibit_shrinking = 0;
+  b->text->inhibit_shrinking = false;
+  b->text->redisplay = false;
 
   b->newline_cache = 0;
   b->width_run_cache = 0;
@@ -888,8 +882,8 @@ drop_overlay (struct buffer *b, struct Lisp_Overlay *ov)
   eassert (b == XBUFFER (Fmarker_buffer (ov->start)));
   modify_overlay (b, marker_position (ov->start),
                  marker_position (ov->end));
-  Fset_marker (ov->start, Qnil, Qnil);
-  Fset_marker (ov->end, Qnil, Qnil);
+  unchain_marker (XMARKER (ov->start));
+  unchain_marker (XMARKER (ov->end));
 
 }
 
@@ -933,7 +927,7 @@ reset_buffer (register struct buffer *b)
   bset_filename (b, Qnil);
   bset_file_truename (b, Qnil);
   bset_directory (b, current_buffer ? BVAR (current_buffer, directory) : Qnil);
-  b->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
+  b->modtime = make_timespec (0, UNKNOWN_MODTIME_NSECS);
   b->modtime_size = -1;
   XSETFASTINT (BVAR (b, save_length), 0);
   b->last_window_start = 1;
@@ -1334,15 +1328,59 @@ No argument or nil as argument means use current buffer as BUFFER.  */)
   return BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf) ? Qt : Qnil;
 }
 
+DEFUN ("force-mode-line-update", Fforce_mode_line_update,
+       Sforce_mode_line_update, 0, 1, 0,
+       doc: /* Force redisplay of the current buffer's mode line and header line.
+With optional non-nil ALL, force redisplay of all mode lines and
+header lines.  This function also forces recomputation of the
+menu bar menus and the frame title.  */)
+     (Lisp_Object all)
+{
+  if (!NILP (all))
+    {
+      update_mode_lines = 10;
+      /* FIXME: This can't be right.  */
+      current_buffer->prevent_redisplay_optimizations_p = true;
+    }
+  else if (buffer_window_count (current_buffer))
+    {
+      bset_update_mode_line (current_buffer);
+      current_buffer->prevent_redisplay_optimizations_p = true;
+    }
+  return all;
+}
+
 DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p, Sset_buffer_modified_p,
        1, 1, 0,
        doc: /* Mark current buffer as modified or unmodified according to FLAG.
 A non-nil FLAG means mark the buffer modified.  */)
   (Lisp_Object flag)
+{
+  Frestore_buffer_modified_p (flag);
+
+  /* Set update_mode_lines only if buffer is displayed in some window.
+     Packages like jit-lock or lazy-lock preserve a buffer's modified
+     state by recording/restoring the state around blocks of code.
+     Setting update_mode_lines makes redisplay consider all windows
+     (on all frames).  Stealth fontification of buffers not displayed
+     would incur additional redisplay costs if we'd set
+     update_modes_lines unconditionally.
+
+     Ideally, I think there should be another mechanism for fontifying
+     buffers without "modifying" buffers, or redisplay should be
+     smarter about updating the `*' in mode lines.  --gerd  */
+  return Fforce_mode_line_update (Qnil);
+}
+
+DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
+       Srestore_buffer_modified_p, 1, 1, 0,
+       doc: /* Like `set-buffer-modified-p', with a difference concerning redisplay.
+It is not ensured that mode lines will be updated to show the modified
+state of the current buffer.  Use with care.  */)
+  (Lisp_Object flag)
 {
   Lisp_Object fn;
 
-#ifdef CLASH_DETECTION
   /* If buffer becoming modified, lock the file.
      If buffer becoming unmodified, unlock the file.  */
 
@@ -1360,7 +1398,6 @@ A non-nil FLAG means mark the buffer modified.  */)
       else if (already && NILP (flag))
        unlock_file (fn);
     }
-#endif /* CLASH_DETECTION */
 
   /* Here we have a problem.  SAVE_MODIFF is used here to encode
      buffer-modified-p (as SAVE_MODIFF<MODIFF) as well as
@@ -1382,52 +1419,6 @@ A non-nil FLAG means mark the buffer 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
-     state by recording/restoring the state around blocks of code.
-     Setting update_mode_lines makes redisplay consider all windows
-     (on all frames).  Stealth fontification of buffers not displayed
-     would incur additional redisplay costs if we'd set
-     update_modes_lines unconditionally.
-
-     Ideally, I think there should be another mechanism for fontifying
-     buffers without "modifying" buffers, or redisplay should be
-     smarter about updating the `*' in mode lines.  --gerd  */
-  if (buffer_window_count (current_buffer))
-    {
-      ++update_mode_lines;
-      current_buffer->prevent_redisplay_optimizations_p = 1;
-    }
-
-  return flag;
-}
-
-DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
-       Srestore_buffer_modified_p, 1, 1, 0,
-       doc: /* Like `set-buffer-modified-p', with a difference concerning redisplay.
-It is not ensured that mode lines will be updated to show the modified
-state of the current buffer.  Use with care.  */)
-  (Lisp_Object flag)
-{
-#ifdef CLASH_DETECTION
-  Lisp_Object fn;
-
-  /* If buffer becoming modified, lock the file.
-     If buffer becoming unmodified, unlock the file.  */
-
-  fn = BVAR (current_buffer, file_truename);
-  /* Test buffer-file-name so that binding it to nil is effective.  */
-  if (!NILP (fn) && ! NILP (BVAR (current_buffer, filename)))
-    {
-      bool already = SAVE_MODIFF < MODIFF;
-      if (!already && !NILP (flag))
-       lock_file (fn);
-      else if (already && NILP (flag))
-       unlock_file (fn);
-    }
-#endif /* CLASH_DETECTION */
-
-  SAVE_MODIFF = NILP (flag) ? MODIFF : 0;
   return flag;
 }
 
@@ -1515,7 +1506,7 @@ This does not change the name of the visited file (if any).  */)
 
   /* Catch redisplay's attention.  Unless we do this, the mode lines for
      any windows displaying current_buffer will stay unchanged.  */
-  update_mode_lines++;
+  update_mode_lines = 11;
 
   XSETBUFFER (buf, current_buffer);
   Fsetcar (Frassq (buf, Vbuffer_alist), newname);
@@ -1800,7 +1791,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
   /* Run replace_buffer_in_windows before making another buffer current
      since set-window-buffer-start-and-point will refuse to make another
      buffer current if the selected window does not show the current
-     buffer.  (Bug#10114) */
+     buffer (bug#10114).  */
   replace_buffer_in_windows (buffer);
 
   /* Exit if replacing the buffer in windows has killed our buffer.  */
@@ -1826,10 +1817,8 @@ cleaning up all windows currently displaying the buffer to be killed. */)
 
   /* Now there is no question: we can kill the buffer.  */
 
-#ifdef CLASH_DETECTION
   /* Unlock this buffer's file, if it is locked.  */
   unlock_buffer (b);
-#endif /* CLASH_DETECTION */
 
   GCPRO1 (buffer);
   kill_buffer_processes (buffer);
@@ -1874,6 +1863,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
 
   if (b->base_buffer)
     {
+      INTERVAL i;
       /* Unchain all markers that belong to this indirect buffer.
         Don't unchain the markers that belong to the base buffer
         or its other indirect buffers.  */
@@ -1888,6 +1878,14 @@ cleaning up all windows currently displaying the buffer to be killed. */)
          else
            mp = &m->next;
        }
+      /* Intervals should be owned by the base buffer (Bug#16502).  */
+      i = buffer_intervals (b);
+      if (i)
+       {
+         Lisp_Object owner;
+         XSETBUFFER (owner, b->base_buffer);
+         set_interval_object (i, owner);
+       }
     }
   else
     {
@@ -2076,7 +2074,7 @@ the current buffer's major mode.  */)
   count = SPECPDL_INDEX ();
 
   /* To select a nonfundamental mode,
-     select the buffer temporarily and then call the mode function. */
+     select the buffer temporarily and then call the mode function.  */
 
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
 
@@ -2116,7 +2114,7 @@ set_buffer_internal_1 (register struct buffer *b)
 
   old_buf = current_buffer;
   current_buffer = b;
-  last_known_column_point = -1;   /* invalidate indentation cache */
+  last_known_column_point = -1;   /* Invalidate indentation cache.  */
 
   if (old_buf)
     {
@@ -2140,7 +2138,7 @@ set_buffer_internal_1 (register struct buffer *b)
   fetch_buffer_markers (b);
 
   /* Look down buffer's list of local Lisp variables
-     to find and update any that forward into C variables. */
+     to find and update any that forward into C variables.  */
 
   do
     {
@@ -2184,11 +2182,12 @@ set_buffer_temp (struct buffer *b)
 
 DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
        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 `with-current-buffer' when you want to make a buffer current
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer.
+See also `with-current-buffer' 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.  */)
+`pop-to-buffer' to switch buffers permanently.
+The return value is the buffer made current.  */)
   (register Lisp_Object buffer_or_name)
 {
   register Lisp_Object buffer;
@@ -2258,7 +2257,7 @@ validate_region (register Lisp_Object *b, register Lisp_Object *e)
     }
 
   if (! (BEGV <= XINT (*b) && XINT (*e) <= ZV))
-    args_out_of_range (*b, *e);
+    args_out_of_range_3 (Fcurrent_buffer (), *b, *e);
 }
 \f
 /* Advance BYTE_POS up to a character boundary
@@ -2489,6 +2488,8 @@ current buffer is cleared.  */)
   if (narrowed)
     error ("Changing multibyteness in a narrowed buffer");
 
+  invalidate_buffer_caches (current_buffer, BEGV, ZV);
+
   if (NILP (flag))
     {
       ptrdiff_t pos, stop;
@@ -2707,7 +2708,7 @@ current buffer is cleared.  */)
 
   /* If buffer is shown in a window, let redisplay consider other windows.  */
   if (buffer_window_count (current_buffer))
-    ++windows_or_buffers_changed;
+    windows_or_buffers_changed = 10;
 
   /* Copy this buffer's new multibyte status
      into all of its indirect buffers.  */
@@ -2767,7 +2768,7 @@ the normal hook `change-major-mode-hook'.  */)
 
   /* Force mode-line redisplay.  Useful here because all major mode
      commands call this function.  */
-  update_mode_lines++;
+  update_mode_lines = 12;
 
   return Qnil;
 }
@@ -3141,6 +3142,7 @@ struct sortvec
   Lisp_Object overlay;
   ptrdiff_t beg, end;
   EMACS_INT priority;
+  EMACS_INT spriority;         /* Secondary priority.  */
 };
 
 static int
@@ -3148,19 +3150,28 @@ compare_overlays (const void *v1, const void *v2)
 {
   const struct sortvec *s1 = v1;
   const struct sortvec *s2 = v2;
+  /* Return 1 if s1 should take precedence, -1 if v2 should take precedence,
+     and 0 if they're equal.  */
   if (s1->priority != s2->priority)
     return s1->priority < s2->priority ? -1 : 1;
-  if (s1->beg != s2->beg)
-    return s1->beg < s2->beg ? -1 : 1;
-  if (s1->end != s2->end)
+  /* If the priority is equal, give precedence to the one not covered by the
+     other.  If neither covers the other, obey spriority.  */
+  else if (s1->beg < s2->beg)
+    return (s1->end < s2->end && s1->spriority > s2->spriority ? 1 : -1);
+  else if (s1->beg > s2->beg)
+    return (s1->end > s2->end && s1->spriority < s2->spriority ? -1 : 1);
+  else if (s1->end != s2->end)
     return s2->end < s1->end ? -1 : 1;
-  /* Avoid the non-determinism of qsort by choosing an arbitrary ordering
-     between "equal" overlays.  The result can still change between
-     invocations of Emacs, but it won't change in the middle of
-     `find_field' (bug#6830).  */
-  if (!EQ (s1->overlay, s2->overlay))
+  else if (s1->spriority != s2->spriority)
+    return (s1->spriority < s2->spriority ? -1 : 1);
+  else if (EQ (s1->overlay, s2->overlay))
+    return 0;
+  else
+    /* Avoid the non-determinism of qsort by choosing an arbitrary ordering
+       between "equal" overlays.  The result can still change between
+       invocations of Emacs, but it won't change in the middle of
+       `find_field' (bug#6830).  */
     return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1;
-  return 0;
 }
 
 /* Sort an array of overlays by priority.  The array is modified in place.
@@ -3203,10 +3214,23 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
          sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
          sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
          tem = Foverlay_get (overlay, Qpriority);
-         if (INTEGERP (tem))
-           sortvec[j].priority = XINT (tem);
-         else
-           sortvec[j].priority = 0;
+         if (NILP (tem))
+           {
+             sortvec[j].priority = 0;
+             sortvec[j].spriority = 0;
+           }
+         else if (INTEGERP (tem))
+           {
+             sortvec[j].priority = XINT (tem);
+             sortvec[j].spriority = 0;
+           }
+         else if (CONSP (tem))
+           {
+             Lisp_Object car = XCAR (tem);
+             Lisp_Object cdr = XCDR (tem);
+             sortvec[j].priority  = INTEGERP (car) ? XINT (car) : 0;
+             sortvec[j].spriority = INTEGERP (cdr) ? XINT (cdr) : 0;
+           }
          j++;
        }
     }
@@ -3825,7 +3849,7 @@ DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
 }
 
 DEFUN ("make-overlay", Fmake_overlay, Smake_overlay, 2, 5, 0,
-       doc: /* Create a new overlay with range BEG to END in BUFFER.
+       doc: /* Create a new overlay with range BEG to END in BUFFER and return it.
 If omitted, BUFFER defaults to the current buffer.
 BEG and END may be integers or markers.
 The fourth arg FRONT-ADVANCE, if non-nil, makes the marker
@@ -3834,7 +3858,8 @@ for the front of the overlay advance when text is inserted there
 The fifth arg REAR-ADVANCE, if non-nil, makes the marker
 for the rear of the overlay advance when text is inserted there
 \(which means the text *is* included in the overlay).  */)
-  (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer, Lisp_Object front_advance, Lisp_Object rear_advance)
+  (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer,
+   Lisp_Object front_advance, Lisp_Object rear_advance)
 {
   Lisp_Object overlay;
   struct buffer *b;
@@ -3843,12 +3868,11 @@ for the rear of the overlay advance when text is inserted there
     XSETBUFFER (buffer, current_buffer);
   else
     CHECK_BUFFER (buffer);
-  if (MARKERP (beg)
-      && ! EQ (Fmarker_buffer (beg), buffer))
-    error ("Marker points into wrong buffer");
-  if (MARKERP (end)
-      && ! EQ (Fmarker_buffer (end), buffer))
-    error ("Marker points into wrong buffer");
+
+  if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer))
+    signal_error ("Marker points into wrong buffer", beg);
+  if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
+    signal_error ("Marker points into wrong buffer", end);
 
   CHECK_NUMBER_COERCE_MARKER (beg);
   CHECK_NUMBER_COERCE_MARKER (end);
@@ -3908,17 +3932,7 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
 
   BUF_COMPUTE_UNCHANGED (buf, start, end);
 
-  /* If BUF is visible, consider updating the display if ...  */
-  if (buffer_window_count (buf) > 0)
-    {
-      /* ... it's visible in other window than selected,  */
-      if (buf != XBUFFER (XWINDOW (selected_window)->contents))
-       windows_or_buffers_changed = 1;
-      /* ... or if we modify an overlay at the end of the buffer
-        and so we cannot be sure that window end is still valid.  */
-      else if (end >= ZV && start <= ZV)
-       windows_or_buffers_changed = 1;
-    }
+  bset_redisplay (buf);
 
   ++BUF_OVERLAY_MODIFF (buf);
 }
@@ -3974,12 +3988,10 @@ buffer.  */)
   if (NILP (Fbuffer_live_p (buffer)))
     error ("Attempt to move overlay to a dead buffer");
 
-  if (MARKERP (beg)
-      && ! EQ (Fmarker_buffer (beg), buffer))
-    error ("Marker points into wrong buffer");
-  if (MARKERP (end)
-      && ! EQ (Fmarker_buffer (end), buffer))
-    error ("Marker points into wrong buffer");
+  if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer))
+    signal_error ("Marker points into wrong buffer", beg);
+  if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
+    signal_error ("Marker points into wrong buffer", end);
 
   CHECK_NUMBER_COERCE_MARKER (beg);
   CHECK_NUMBER_COERCE_MARKER (end);
@@ -4161,6 +4173,9 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
 
   CHECK_NUMBER_COERCE_MARKER (pos);
 
+  if (!buffer_has_overlays ())
+    return Qnil;
+
   len = 10;
   /* We can't use alloca here because overlays_at can call xrealloc.  */
   overlay_vec = xmalloc (len * sizeof *overlay_vec);
@@ -4193,6 +4208,9 @@ end of the buffer.  */)
   CHECK_NUMBER_COERCE_MARKER (beg);
   CHECK_NUMBER_COERCE_MARKER (end);
 
+  if (!buffer_has_overlays ())
+    return Qnil;
+
   len = 10;
   overlay_vec = xmalloc (len * sizeof *overlay_vec);
 
@@ -4221,6 +4239,9 @@ the value is (point-max).  */)
 
   CHECK_NUMBER_COERCE_MARKER (pos);
 
+  if (!buffer_has_overlays ())
+    return make_number (ZV);
+
   len = 10;
   overlay_vec = xmalloc (len * sizeof *overlay_vec);
 
@@ -4260,6 +4281,9 @@ the value is (point-min).  */)
 
   CHECK_NUMBER_COERCE_MARKER (pos);
 
+  if (!buffer_has_overlays ())
+    return make_number (BEGV);
+
   /* At beginning of buffer, we know the answer;
      avoid bug subtracting 1 below.  */
   if (XINT (pos) == BEGV)
@@ -5177,7 +5201,7 @@ init_buffer_once (void)
   bset_buffer_file_coding_system (&buffer_defaults, Qnil);
   XSETFASTINT (BVAR (&buffer_defaults, fill_column), 70);
   XSETFASTINT (BVAR (&buffer_defaults, left_margin), 0);
-  bset_cache_long_scans (&buffer_defaults, Qnil);
+  bset_cache_long_scans (&buffer_defaults, Qt);
   bset_file_truename (&buffer_defaults, Qnil);
   XSETFASTINT (BVAR (&buffer_defaults, display_count), 0);
   XSETFASTINT (BVAR (&buffer_defaults, left_margin_cols), 0);
@@ -5341,13 +5365,10 @@ init_buffer (void)
       len++;
     }
 
+  /* At this moment, we still don't know how to decode the directory
+     name.  So, we keep the bytes in unibyte form so that file I/O
+     routines correctly get the original bytes.  */
   bset_directory (current_buffer, make_unibyte_string (pwd, len));
-  if (! NILP (BVAR (&buffer_defaults, enable_multibyte_characters)))
-    /* At this moment, we still don't know how to decode the
-       directory name.  So, we keep the bytes in multibyte form so
-       that ENCODE_FILE correctly gets the original bytes.  */
-    bset_directory
-      (current_buffer, string_to_multibyte (BVAR (current_buffer, directory)));
 
   /* Add /: to the front of the name
      if it would otherwise be treated as magic.  */
@@ -5402,12 +5423,12 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
 
   if (PER_BUFFER_IDX (offset) == 0)
     /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
-       slot of buffer_local_flags */
+       slot of buffer_local_flags */
     emacs_abort ();
 }
 
 
-/* initialize the buffer routines */
+/* Initialize the buffer routines.  */
 void
 syms_of_buffer (void)
 {
@@ -5797,7 +5818,8 @@ its value may not be a list of functions.  */);
 
   DEFVAR_PER_BUFFER ("buffer-file-name", &BVAR (current_buffer, filename),
                     Qstringp,
-                    doc: /* Name of file visited in current buffer, or nil if not visiting a file.  */);
+                    doc: /* Name of file visited in current buffer, or nil if not visiting a file.
+This should be an absolute file name.  */);
 
   DEFVAR_PER_BUFFER ("buffer-file-truename", &BVAR (current_buffer, file_truename),
                     Qstringp,
@@ -5890,7 +5912,7 @@ See also the functions `display-table-slot' and `set-display-table-slot'.  */);
 
   DEFVAR_PER_BUFFER ("left-margin-width", &BVAR (current_buffer, left_margin_cols),
                     Qintegerp,
-                    doc: /* Width of left marginal area for display of a buffer.
+                    doc: /* Width in columns of left marginal area for display of a buffer.
 A value of nil means no marginal area.
 
 Setting this variable does not take effect until a new buffer is displayed
@@ -5898,7 +5920,7 @@ in a window.  To make the change take effect, call `set-window-buffer'.  */);
 
   DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols),
                     Qintegerp,
-                    doc: /* Width of right marginal area for display of a buffer.
+                    doc: /* Width in columns of right marginal area for display of a buffer.
 A value of nil means no marginal area.
 
 Setting this variable does not take effect until a new buffer is displayed
@@ -6127,6 +6149,8 @@ If the value of the variable is t, undo information is not recorded.  */);
   DEFVAR_PER_BUFFER ("cache-long-scans", &BVAR (current_buffer, cache_long_scans), Qnil,
                     doc: /* Non-nil means that Emacs should use caches in attempt to speedup buffer scans.
 
+There is no reason to set this to nil except for debugging purposes.
+
 Normally, the line-motion functions work by scanning the buffer for
 newlines.  Columnar operations (like `move-to-column' and
 `compute-motion') also work by scanning the buffer, summing character
@@ -6176,13 +6200,16 @@ same format as a regular save would use.  */);
   DEFVAR_PER_BUFFER ("buffer-invisibility-spec",
                     &BVAR (current_buffer, invisibility_spec), Qnil,
                     doc: /* Invisibility spec of this buffer.
-The default is t, which means that text is invisible
-if it has a non-nil `invisible' property.
-If the value is a list, a text character is invisible if its `invisible'
-property is an element in that list (or is a list with members in common).
-If an element is a cons cell of the form (PROP . ELLIPSIS),
-then characters with property value PROP are invisible,
-and they have an ellipsis as well if ELLIPSIS is non-nil.  */);
+The default is t, which means that text is invisible if it has a non-nil
+`invisible' property.
+This variable can also be a list.  The list can have two kinds of elements:
+`ATOM' and `(ATOM . ELLIPSIS)'.  A text character is invisible if its
+`invisible' property is `ATOM', or has an `invisible' property that is a list
+that contains `ATOM'.
+If the `(ATOM . ELLIPSIS)' form is used, and `ELLIPSIS' is non-nil, an
+ellipsis will be displayed after the invisible characters.
+Setting this variable is very fast, much faster than scanning all the text in
+the buffer looking for properties to change.  */);
 
   DEFVAR_PER_BUFFER ("buffer-display-count",
                     &BVAR (current_buffer, display_count), Qintegerp,
@@ -6276,9 +6303,9 @@ The function `kill-all-local-variables' runs this before doing anything else.  *
 
   DEFVAR_LISP ("buffer-list-update-hook", Vbuffer_list_update_hook,
               doc: /* Hook run when the buffer list changes.
-Functions running this hook are `get-buffer-create',
+Functions running this hook are, `get-buffer-create',
 `make-indirect-buffer', `rename-buffer', `kill-buffer',
-and `bury-buffer-internal'.  */);
+`bury-buffer-internal' and `select-window'.  */);
   Vbuffer_list_update_hook = Qnil;
   DEFSYM (Qbuffer_list_update_hook, "buffer-list-update-hook");
 
@@ -6295,6 +6322,7 @@ and `bury-buffer-internal'.  */);
   defsubr (&Sbuffer_local_value);
   defsubr (&Sbuffer_local_variables);
   defsubr (&Sbuffer_modified_p);
+  defsubr (&Sforce_mode_line_update);
   defsubr (&Sset_buffer_modified_p);
   defsubr (&Sbuffer_modified_tick);
   defsubr (&Sbuffer_chars_modified_tick);