(syms_of_buffer): Doc fix.
[bpt/emacs.git] / src / buffer.c
index e781d25..1246867 100644 (file)
@@ -1,5 +1,5 @@
 /* Buffer manipulation primitives for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995, 1997, 1998
+   Copyright (C) 1985,86,87,88,89,93,94,95,97,98, 1999
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -153,6 +153,9 @@ Lisp_Object Qfirst_change_hook;
 Lisp_Object Qbefore_change_functions;
 Lisp_Object Qafter_change_functions;
 
+/* If nonzero, all modification hooks are suppressed.  */
+int inhibit_modification_hooks;
+
 Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
 
 Lisp_Object Qprotected_field;
@@ -463,6 +466,9 @@ NAME should be a string which is not the name of an existing buffer.")
   b->mark = Fmake_marker ();
   b->name = name;
 
+  /* The multibyte status belongs to the base buffer.  */
+  b->enable_multibyte_characters = b->base_buffer->enable_multibyte_characters;
+
   /* Make sure the base buffer has markers for its narrowing.  */
   if (NILP (b->base_buffer->pt_marker))
     {
@@ -527,6 +533,7 @@ reset_buffer (b)
   b->file_format = Qnil;
   b->last_selected_window = Qnil;
   XSETINT (b->display_count, 0);
+  b->display_time = Qnil;
   b->extra2 = Qnil;
   b->extra3 = Qnil;
   b->enable_multibyte_characters = buffer_defaults.enable_multibyte_characters;
@@ -803,7 +810,8 @@ A non-nil FLAG means mark the buffer modified.")
      If buffer becoming unmodified, unlock the file.  */
 
   fn = current_buffer->file_truename;
-  if (!NILP (fn))
+  /* Test buffer-file-name so that binding it to nil is effective.  */
+  if (!NILP (fn) && ! NILP (current_buffer->filename))
     {
       already = SAVE_MODIFF < MODIFF;
       if (!already && !NILP (flag))
@@ -889,26 +897,31 @@ This does not change the name of the visited file (if any).")
   return current_buffer->name;
 }
 
-DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 2, 0,
+DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 3, 0,
   "Return most recently selected buffer other than BUFFER.\n\
 Buffers not visible in windows are preferred to visible buffers,\n\
 unless optional second argument VISIBLE-OK is non-nil.\n\
+If the optional third argument FRAME is non-nil, use that frame's\n\
+buffer list instead of the selected frame's buffer list.\n\
 If no other buffer exists, the buffer `*scratch*' is returned.\n\
 If BUFFER is omitted or nil, some interesting buffer is returned.")
-  (buffer, visible_ok)
-     register Lisp_Object buffer, visible_ok;
+  (buffer, visible_ok, frame)
+     register Lisp_Object buffer, visible_ok, frame;
 {
   Lisp_Object Fset_buffer_major_mode ();
   register Lisp_Object tail, buf, notsogood, tem, pred, add_ons;
   notsogood = Qnil;
 
+  if (NILP (frame))
+    frame = Fselected_frame ();
+
   tail = Vbuffer_alist;
-  pred = frame_buffer_predicate ();
+  pred = frame_buffer_predicate (frame);
 
   /* Consider buffers that have been seen in the selected frame
      before other buffers.  */
     
-  tem = frame_buffer_list ();
+  tem = frame_buffer_list (frame);
   add_ons = Qnil;
   while (CONSP (tem))
     {
@@ -1110,7 +1123,7 @@ with SIGHUP.")
      and give up if so.  */
   if (b == current_buffer)
     {
-      tem = Fother_buffer (buf, Qnil);
+      tem = Fother_buffer (buf, Qnil, Qnil);
       Fset_buffer (tem);
       if (b == current_buffer)
        return Qnil;
@@ -1218,6 +1231,8 @@ record_buffer (buf)
      Lisp_Object buf;
 {
   register Lisp_Object link, prev;
+  Lisp_Object frame;
+  frame = Fselected_frame ();
 
   prev = Qnil;
   for (link = Vbuffer_alist; CONSP (link); link = XCONS (link)->cdr)
@@ -1241,7 +1256,8 @@ record_buffer (buf)
   /* Now move this buffer to the front of frame_buffer_list also.  */
 
   prev = Qnil;
-  for (link = frame_buffer_list (); CONSP (link); link = XCONS (link)->cdr)
+  for (link = frame_buffer_list (frame); CONSP (link);
+       link = XCONS (link)->cdr)
     {
       if (EQ (XCONS (link)->car, buf))
        break;
@@ -1253,15 +1269,16 @@ record_buffer (buf)
   if (CONSP (link))
     {
       if (NILP (prev))
-       set_frame_buffer_list (XCONS (frame_buffer_list ())->cdr);
+       set_frame_buffer_list (frame,
+                              XCONS (frame_buffer_list (frame))->cdr);
       else
        XCONS (prev)->cdr = XCONS (XCONS (prev)->cdr)->cdr;
        
-      XCONS (link)->cdr = frame_buffer_list ();
-      set_frame_buffer_list (link);
+      XCONS (link)->cdr = frame_buffer_list (frame);
+      set_frame_buffer_list (frame, link);
     }
   else
-    set_frame_buffer_list (Fcons (buf, frame_buffer_list ()));
+    set_frame_buffer_list (frame, Fcons (buf, frame_buffer_list (frame)));
 }
 
 DEFUN ("set-buffer-major-mode", Fset_buffer_major_mode, Sset_buffer_major_mode, 1, 1, 0,
@@ -1316,7 +1333,7 @@ the window-buffer correspondences.")
     error ("Cannot switch buffers in a dedicated window");
 
   if (NILP (buffer))
-    buf = Fother_buffer (Fcurrent_buffer (), Qnil);
+    buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
   else
     {
       buf = Fget_buffer (buffer);
@@ -1354,7 +1371,7 @@ do not put this buffer at the front of the list of recently selected ones.")
 {
   register Lisp_Object buf;
   if (NILP (buffer))
-    buf = Fother_buffer (Fcurrent_buffer (), Qnil);
+    buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
   else
     {
       buf = Fget_buffer (buffer);
@@ -1620,7 +1637,7 @@ selected window if it is displayed there.")
       XSETBUFFER (buffer, current_buffer);
 
       /* If we're burying the current buffer, unshow it.  */
-      Fswitch_to_buffer (Fother_buffer (buffer, Qnil), Qnil);
+      Fswitch_to_buffer (Fother_buffer (buffer, Qnil, Qnil), Qnil);
     }
   else
     {
@@ -1721,6 +1738,10 @@ but the contents viewed as characters do change.")
      Lisp_Object flag;
 {
   Lisp_Object tail, markers;
+  struct buffer *other;
+
+  if (current_buffer->base_buffer)
+    error ("Cannot do `set-buffer-multibyte' on an indirect buffer");
 
   /* Do nothing if nothing actually changes.  */
   if (NILP (flag) == NILP (current_buffer->enable_multibyte_characters))
@@ -1822,6 +1843,12 @@ but the contents viewed as characters do change.")
 
          tail = XMARKER (tail)->chain;
        }
+
+      /* Make sure no markers were put on the chain
+        while the chain value was incorrect.  */
+      if (! EQ (BUF_MARKERS (current_buffer), Qnil))
+       abort ();
+
       BUF_MARKERS (current_buffer) = markers;
 
       /* Do this last, so it can calculate the new correspondences
@@ -1829,6 +1856,13 @@ but the contents viewed as characters do change.")
       set_intervals_multibyte (1);
     }
 
+  /* Copy this buffer's new multibyte status
+     into all of its indirect buffers.  */
+  for (other = all_buffers; other; other = other->next)
+    if (other->base_buffer == current_buffer && !NILP (other->name))
+      other->enable_multibyte_characters
+       = current_buffer->enable_multibyte_characters;
+
   return flag;
 }
 \f
@@ -3845,6 +3879,7 @@ init_buffer_once ()
   buffer_defaults.cache_long_line_scans = Qnil;
   buffer_defaults.file_truename = Qnil;
   XSETFASTINT (buffer_defaults.display_count, 0);
+  buffer_defaults.display_time = Qnil;
 
   /* Assign the local-flags to the slots that have default values.
      The local flag is a bit that is used in the buffer
@@ -3871,6 +3906,7 @@ init_buffer_once ()
   XSETINT (buffer_local_flags.invisibility_spec, -1);
   XSETINT (buffer_local_flags.file_format, -1);
   XSETINT (buffer_local_flags.display_count, -1);
+  XSETINT (buffer_local_flags.display_time, -1);
   XSETINT (buffer_local_flags.enable_multibyte_characters, -1);
 
   XSETFASTINT (buffer_local_flags.mode_line_format, 1);
@@ -3925,6 +3961,8 @@ init_buffer_once ()
   Vbuffer_alist = Qnil;
 
   Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
+
+  inhibit_modification_hooks = 0;
 }
 
 void
@@ -3942,7 +3980,8 @@ init_buffer ()
 
   /* If PWD is accurate, use it instead of calling getwd.  This is faster
      when PWD is right, and may avoid a fatal error.  */
-  if ((pwd = getenv ("PWD")) != 0 && IS_DIRECTORY_SEP (*pwd)
+  if ((pwd = getenv ("PWD")) != 0
+      && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
       && stat (pwd, &pwdstat) == 0
       && stat (".", &dotstat) == 0
       && dotstat.st_ino == pwdstat.st_ino
@@ -4063,12 +4102,12 @@ This is the same as (default-value 'ctl-arrow).");
    DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
              &buffer_defaults.enable_multibyte_characters,
      "Default value of `enable-multibyte-characters' for buffers not overriding it.\n\
- This is the same as (default-value 'enable-multibyte-characters).");
+This is the same as (default-value 'enable-multibyte-characters).");
  
    DEFVAR_LISP_NOPRO ("default-buffer-file-coding-system",
              &buffer_defaults.buffer_file_coding_system,
      "Default value of `buffer-file-coding-system' for buffers not overriding it.\n\
- This is the same as (default-value 'buffer-file-coding-system).");
+This is the same as (default-value 'buffer-file-coding-system).");
  
   DEFVAR_LISP_NOPRO ("default-truncate-lines",
              &buffer_defaults.truncate_lines,
@@ -4164,7 +4203,7 @@ Automatically becomes buffer-local when set in any fashion.");
 
   DEFVAR_PER_BUFFER ("case-fold-search", &current_buffer->case_fold_search,
                     Qnil,
-    "*Non-nil if searches should ignore case.\n\
+    "*Non-nil if searches and matches should ignore case.\n\
 Automatically becomes buffer-local when set in any fashion.");
 
   DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
@@ -4193,17 +4232,29 @@ in the current display table (if there is one).");
   DEFVAR_PER_BUFFER ("enable-multibyte-characters",
                     &current_buffer->enable_multibyte_characters,
                     make_number (-1),
-    "*Non-nil means the buffer contents are regarded as multi-byte form\n\
-of characters, not a binary code.  This affects the display, file I/O,\n\
-and behaviors of various editing commands.");
+    "*Non-nil means the buffer contents are regarded as multi-byte characters.\n\
+Otherwise they are regarded as unibyte.  This affects the display,\n\
+file I/O and the behavior of various editing commands.\n\
+\n\
+This variable is buffer-local but you cannot set it directly;\n\
+use the function `set-buffer-multibyte' to change a buffer's representation.\n\
+Changing its default value with `setq-default' is supported.\n\
+See also variable `default-enable-multibyte-characters' and Info node\n\
+`(elisp)Text Representations'.");
 
   DEFVAR_PER_BUFFER ("buffer-file-coding-system",
                     &current_buffer->buffer_file_coding_system, Qnil,
     "Coding system to be used for encoding the buffer contents on saving.\n\
-If it is nil, the buffer is saved without any code conversion unless\n\
-some coding system is specified in `file-coding-system-alist'\n\
+This variable applies to saving the buffer, and also to `write-region'\n\
+and other functions that use `write-region'.\n\
+It does not apply to sending output to subprocesses, however.\n\
+\n\
+If this is nil, the buffer is saved without any code conversion\n\
+unless some coding system is specified in `file-coding-system-alist'\n\
 for the buffer file.\n\
 \n\
+The variable `coding-system-for-write', if non-nil, overrides this variable.\n\
+\n\
 This variable is never applied to a way of decoding\n\
 a file while reading it.");
 
@@ -4380,7 +4431,11 @@ don't call any before-change or after-change functions.\n\
 That's because these variables are temporarily set to nil.\n\
 As a result, a hook function cannot straightforwardly alter the value of\n\
 these variables.  See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.");
+accomplishing an equivalent result by using other variables.\n\
+\n\
+If an unhandled error happens in running these functions,\n\
+the variable's value remains nil.  That prevents the error\n\
+from happening repeatedly and making Emacs nonfunctional.");
   Vbefore_change_functions = Qnil;
 
   DEFVAR_LISP ("after-change-functions", &Vafter_change_functions,
@@ -4397,8 +4452,11 @@ don't call any before-change or after-change functions.\n\
 That's because these variables are temporarily set to nil.\n\
 As a result, a hook function cannot straightforwardly alter the value of\n\
 these variables.  See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.");
-
+accomplishing an equivalent result by using other variables.\n\
+\n\
+If an unhandled error happens in running these functions,\n\
+the variable's value remains nil.  That prevents the error\n\
+from happening repeatedly and making Emacs nonfunctional.");
   Vafter_change_functions = Qnil;
 
   DEFVAR_LISP ("first-change-hook", &Vfirst_change_hook,
@@ -4410,6 +4468,7 @@ The functions are run using the `run-hooks' function.");
         but make-docfile can find it in this comment.  */
   DEFVAR_PER_BUFFER ("buffer-undo-list", &current_buffer->undo_list, Qnil,
     "List of undo entries in current buffer.\n\
+This variable is always local in all buffers.\n\
 Recent changes come first; older changes follow newer.\n\
 \n\
 An entry (BEG . END) represents an insertion which begins at\n\
@@ -4478,16 +4537,19 @@ the cache should not affect the behavior of any of the motion\n\
 functions; it should only affect their performance.");
 
   DEFVAR_PER_BUFFER ("point-before-scroll", &current_buffer->point_before_scroll, Qnil,
-  "Value of point before the last series of scroll operations, or nil.");
+  "Value of point before the last series of scroll operations, or nil.\n\
+This variable is always local in all buffers.");
 
   DEFVAR_PER_BUFFER ("buffer-file-format", &current_buffer->file_format, Qnil,
     "List of formats to use when saving this buffer.\n\
+This variable is always local in all buffers.\n\
 Formats are defined by `format-alist'.  This variable is\n\
 set when a file is visited.  Automatically local in all buffers.");
 
   DEFVAR_PER_BUFFER ("buffer-invisibility-spec",
                     &current_buffer->invisibility_spec, Qnil,
   "Invisibility spec of this buffer.\n\
+This variable is always local in all buffers.\n\
 The default is t, which means that text is invisible\n\
 if it has a non-nil `invisible' property.\n\
 If the value is a list, a text character is invisible if its `invisible'\n\
@@ -4498,7 +4560,17 @@ and they have an ellipsis as well if ELLIPSIS is non-nil.");
 
   DEFVAR_PER_BUFFER ("buffer-display-count",
                     &current_buffer->display_count, Qnil,
-  "A number incremented each time the buffer is displayed in a window.");
+  "A number incremented each time this buffer is displayed in a window.\n\
+This variable is always local in all buffers.\n\
+The function `set-window-buffer increments it.");
+
+  DEFVAR_PER_BUFFER ("buffer-display-time",
+                    &current_buffer->display_time, Qnil,
+  "Time stamp updated each time this buffer is displayed in a window.\n\
+This variable is always local in all buffers.\n\
+The function `set-window-buffer' updates this variable\n\
+to the value obtained by calling `current-time'.\n\
+If the buffer has never been shown in a window, the value is nil.");
 
   DEFVAR_LISP ("transient-mark-mode", &Vtransient_mark_mode,
     "*Non-nil means deactivate the mark when the buffer contents change.\n\