Merge from emacs--devo--0
[bpt/emacs.git] / src / buffer.c
index e4d846c..e9c3c47 100644 (file)
@@ -146,6 +146,9 @@ Lisp_Object Vinhibit_read_only;
 Lisp_Object Vkill_buffer_query_functions;
 Lisp_Object Qkill_buffer_query_functions;
 
+/* Hook run before changing a major mode.  */
+Lisp_Object Vchange_major_mode_hook, Qchange_major_mode_hook;
+
 /* List of functions to call before changing an unmodified buffer.  */
 Lisp_Object Vfirst_change_hook;
 
@@ -372,6 +375,7 @@ The value is never nil.  */)
   BUF_ZV_BYTE (b) = BEG_BYTE;
   BUF_Z_BYTE (b) = BEG_BYTE;
   BUF_MODIFF (b) = 1;
+  BUF_CHARS_MODIFF (b) = 1;
   BUF_OVERLAY_MODIFF (b) = 1;
   BUF_SAVE_MODIFF (b) = 1;
   BUF_INTERVALS (b) = 0;
@@ -939,10 +943,10 @@ is the default binding of the variable. */)
       result = XCDR (result);
     }
 
-  if (EQ (result, Qunbound))
-    return Fsignal (Qvoid_variable, Fcons (variable, Qnil));
+  if (!EQ (result, Qunbound))
+    return result;
 
-  return result;
+  xsignal1 (Qvoid_variable, variable);
 }
 
 /* Return an alist of the Lisp-level buffer-local bindings of
@@ -1146,6 +1150,31 @@ No argument or nil as argument means use current buffer as BUFFER.  */)
 
   return make_number (BUF_MODIFF (buf));
 }
+
+DEFUN ("buffer-chars-modified-tick", Fbuffer_chars_modified_tick,
+       Sbuffer_chars_modified_tick, 0, 1, 0,
+       doc: /* Return BUFFER's character-change tick counter.
+Each buffer has a character-change tick counter, which is set to the
+value of the buffer's tick counter \(see `buffer-modified-tick'), each
+time text in that buffer is inserted or deleted.  By comparing the
+values returned by two individual calls of `buffer-chars-modified-tick',
+you can tell whether a character change occurred in that buffer in
+between these calls.  No argument or nil as argument means use current
+buffer as BUFFER.  */)
+     (buffer)
+     register Lisp_Object buffer;
+{
+  register struct buffer *buf;
+  if (NILP (buffer))
+    buf = current_buffer;
+  else
+    {
+      CHECK_BUFFER (buffer);
+      buf = XBUFFER (buffer);
+    }
+
+  return make_number (BUF_CHARS_MODIFF (buf));
+}
 \f
 DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2,
        "sRename buffer (to new name): \nP",
@@ -1682,9 +1711,18 @@ the window-buffer correspondences.  */)
   char *err;
 
   if (EQ (buffer, Fwindow_buffer (selected_window)))
-    /* Basically a NOP.  Avoid signalling an error if the selected window
-       is dedicated, or a minibuffer, ...  */
-    return Fset_buffer (buffer);
+    {
+      /* 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.  */
+      if (NILP (norecord))
+       record_buffer (buffer);
+      return Fset_buffer (buffer);
+    }
 
   err = no_switch_window (selected_window);
   if (err) error (err);
@@ -1962,7 +2000,7 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
 {
   if (!NILP (current_buffer->read_only)
       && NILP (Vinhibit_read_only))
-    Fsignal (Qbuffer_read_only, (Fcons (Fcurrent_buffer (), Qnil)));
+    xsignal1 (Qbuffer_read_only, Fcurrent_buffer ());
   return Qnil;
 }
 
@@ -2115,10 +2153,11 @@ current buffer is cleared.  */)
 {
   struct Lisp_Marker *tail, *markers;
   struct buffer *other;
-  int undo_enabled_p = !EQ (current_buffer->undo_list, Qt);
   int begv, zv;
   int narrowed = (BEG != BEGV || Z != ZV);
   int modified_p = !NILP (Fbuffer_modified_p (Qnil));
+  Lisp_Object old_undo = current_buffer->undo_list;
+  struct gcpro gcpro1;
 
   if (current_buffer->base_buffer)
     error ("Cannot do `set-buffer-multibyte' on an indirect buffer");
@@ -2127,10 +2166,11 @@ current buffer is cleared.  */)
   if (NILP (flag) == NILP (current_buffer->enable_multibyte_characters))
     return flag;
 
-  /* It would be better to update the list,
-     but this is good enough for now.  */
-  if (undo_enabled_p)
-    current_buffer->undo_list = Qt;
+  GCPRO1 (old_undo);
+
+  /* Don't record these buffer changes.  We will put a special undo entry
+     instead.  */
+  current_buffer->undo_list = Qt;
 
   /* If the cached position is for this buffer, clear it out.  */
   clear_charpos_cache (current_buffer);
@@ -2343,8 +2383,17 @@ current buffer is cleared.  */)
       set_intervals_multibyte (1);
     }
 
-  if (undo_enabled_p)
-    current_buffer->undo_list = Qnil;
+  if (!EQ (old_undo, Qt))
+    {
+      /* Represent all the above changes by a special undo entry.  */
+      extern Lisp_Object Qapply;
+      current_buffer->undo_list = Fcons (list3 (Qapply,
+                                               intern ("set-buffer-multibyte"),
+                                               NILP (flag) ? Qt : Qnil),
+                                        old_undo);
+    }
+
+  UNGCPRO;
 
   /* Changing the multibyteness of a buffer means that all windows
      showing that buffer must be updated thoroughly.  */
@@ -2402,7 +2451,7 @@ the normal hook `change-major-mode-hook'.  */)
   Lisp_Object oalist;
 
   if (!NILP (Vrun_hooks))
-    call1 (Vrun_hooks, intern ("change-major-mode-hook"));
+    call1 (Vrun_hooks, Qchange_major_mode_hook);
   oalist = current_buffer->local_var_alist;
 
   /* Make sure none of the bindings in oalist
@@ -2481,10 +2530,10 @@ swap_out_buffer_local_variables (b)
    Return the number found, and store them in a vector in *VEC_PTR.
    Store in *LEN_PTR the size allocated for the vector.
    Store in *NEXT_PTR the next position after POS where an overlay starts,
-     or ZV if there are no more overlays.
+     or ZV if there are no more overlays between POS and ZV.
    Store in *PREV_PTR the previous position before POS where an overlay ends,
      or where an overlay starts which ends at or after POS;
-     or BEGV if there are no such overlays.
+     or BEGV if there are no such overlays from BEGV to POS.
    NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
 
    *VEC_PTR and *LEN_PTR should contain a valid vector and size
@@ -3570,10 +3619,10 @@ 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
 for the front of the overlay advance when text is inserted there
-(which means the text *is not* included in the overlay).
+\(which means the text *is not* included in the overlay).
 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).  */)
+\(which means the text *is* included in the overlay).  */)
      (beg, end, buffer, front_advance, rear_advance)
      Lisp_Object beg, end, buffer;
      Lisp_Object front_advance, rear_advance;
@@ -3955,7 +4004,8 @@ or between BEG and END.  */)
 DEFUN ("next-overlay-change", Fnext_overlay_change, Snext_overlay_change,
        1, 1, 0,
        doc: /* Return the next position after POS where an overlay starts or ends.
-If there are no more overlay boundaries after POS, return (point-max).  */)
+If there are no overlay boundaries from POS to (point-max),
+the value is (point-max).  */)
      (pos)
      Lisp_Object pos;
 {
@@ -3996,7 +4046,8 @@ If there are no more overlay boundaries after POS, return (point-max).  */)
 DEFUN ("previous-overlay-change", Fprevious_overlay_change,
        Sprevious_overlay_change, 1, 1, 0,
        doc: /* Return the previous position before POS where an overlay starts or ends.
-If there are no more overlay boundaries before POS, return (point-min).  */)
+If there are no overlay boundaries from (point-min) to POS,
+the value is (point-min).  */)
      (pos)
      Lisp_Object pos;
 {
@@ -5396,13 +5447,13 @@ This is the same as (default-value 'fringe-cursor-alist').  */);
                     &buffer_defaults.scroll_up_aggressively,
                     doc: /* Default value of `scroll-up-aggressively'.
 This value applies in buffers that don't have their own local values.
-This variable is an alias for (default-value 'scroll-up-aggressively).  */);
+This is the same as (default-value 'scroll-up-aggressively).  */);
 
   DEFVAR_LISP_NOPRO ("default-scroll-down-aggressively",
                     &buffer_defaults.scroll_down_aggressively,
                     doc: /* Default value of `scroll-down-aggressively'.
 This value applies in buffers that don't have their own local values.
-This variable is an alias for (default-value 'scroll-down-aggressively).  */);
+This is the same as (default-value 'scroll-down-aggressively).  */);
 
   DEFVAR_PER_BUFFER ("header-line-format",
                     &current_buffer->header_line_format,
@@ -5454,18 +5505,19 @@ A string is printed verbatim in the mode line except for %-constructs:
   %p -- print percent of buffer above top of window, or Top, Bot or All.
   %P -- print percent of buffer above bottom of window, perhaps plus Top,
         or print Bottom or All.
-  %m -- print the mode name.
   %n -- print Narrow if appropriate.
-  %z -- print mnemonics of buffer, terminal, and keyboard coding systems.
+  %t -- visited file is text or binary (if OS supports this distinction).
+  %z -- print mnemonics of keyboard, terminal, and buffer coding systems.
   %Z -- like %z, but including the end-of-line format.
+  %e -- print error message about full memory.
   %[ -- print one [ for each recursive editing level.  %] similar.
   %% -- print %.   %- -- print infinitely many dashes.
 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'.
-nil here means use current buffer's major mode, provided it is not
-marked as "special".
+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
@@ -5495,7 +5547,7 @@ 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),
-                    doc: /* *Column for the default indent-line-function to indent to.
+                    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,
@@ -5753,7 +5805,7 @@ the actual bitmap shown in the left or right fringe for the logical
 indicator.  LEFT and RIGHT are the bitmaps shown in the left and/or
 right fringe for the specific indicator.  The LEFT1 or RIGHT1 bitmaps
 are used only for the `bottom' and `one-line' indicators when the last
-(only) line in has no final newline.  BITMAPS may also be a single
+\(only) line in has no final newline.  BITMAPS may also be a single
 symbol which is used in both left and right fringes.  */);
 
   DEFVAR_PER_BUFFER ("fringe-cursor-alist",
@@ -5882,8 +5934,8 @@ An entry of the form POSITION indicates that point was at the buffer
 location given by the integer.  Undoing an entry of this form places
 point at POSITION.
 
-nil marks undo boundaries.  The undo command treats the changes
-between two undo boundaries as a single step to be undone.
+Entries with value `nil' mark undo boundaries.  The undo command treats
+the changes between two undo boundaries as a single step to be undone.
 
 If the value of the variable is t, undo information is not recorded.  */);
 
@@ -6000,17 +6052,24 @@ this variable has no effect; the cursor appears as a hollow box.  */);
                     doc: /* Additional space to put between lines when displaying a buffer.
 The space is measured in pixels, and put below lines on window systems.
 If value is a floating point number, it specifies the spacing relative
-to the default frame line height.  */);
+to the default frame line height.  A value of nil means add no extra space.  */);
 
   DEFVAR_PER_BUFFER ("cursor-in-non-selected-windows",
                     &current_buffer->cursor_in_non_selected_windows, Qnil,
     doc: /* *Cursor type to display in non-selected windows.
-t means to use hollow box cursor.  See `cursor-type' for other values.  */);
+The value t means to use hollow box cursor.  See `cursor-type' for other values.  */);
 
   DEFVAR_LISP ("kill-buffer-query-functions", &Vkill_buffer_query_functions,
               doc: /* List of functions called with no args to query before killing a buffer.  */);
   Vkill_buffer_query_functions = Qnil;
 
+  DEFVAR_LISP ("change-major-mode-hook", &Vchange_major_mode_hook,
+              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");
+  staticpro (&Qchange_major_mode_hook);
+
   defsubr (&Sbuffer_live_p);
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
@@ -6027,6 +6086,7 @@ t means to use hollow box cursor.  See `cursor-type' for other values.  */);
   defsubr (&Sbuffer_modified_p);
   defsubr (&Sset_buffer_modified_p);
   defsubr (&Sbuffer_modified_tick);
+  defsubr (&Sbuffer_chars_modified_tick);
   defsubr (&Srename_buffer);
   defsubr (&Sother_buffer);
   defsubr (&Sbuffer_enable_undo);