Merge from emacs--devo--0
[bpt/emacs.git] / src / buffer.c
index 3450e88..e9c3c47 100644 (file)
@@ -1,7 +1,7 @@
 /* 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 Free Software Foundation, Inc.
+                 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -32,10 +32,6 @@ Boston, MA 02110-1301, USA.  */
 extern int errno;
 #endif
 
-#ifndef MAXPATHLEN
-/* in 4.1 [probably SunOS? -stef] , param.h fails to define this. */
-#define MAXPATHLEN 1024
-#endif /* not MAXPATHLEN */
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -150,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;
 
@@ -376,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;
@@ -490,7 +490,7 @@ static void
 clone_per_buffer_values (from, to)
      struct buffer *from, *to;
 {
-  Lisp_Object to_buffer, tem;
+  Lisp_Object to_buffer;
   int offset;
 
   XSETBUFFER (to_buffer, to);
@@ -943,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
@@ -1150,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",
@@ -1364,7 +1389,8 @@ with SIGHUP.  */)
     /* First run the query functions; if any query is answered no,
        don't kill the buffer.  */
     arglist[0] = Qkill_buffer_query_functions;
-    if (NILP (Frun_hook_with_args_until_failure (1, arglist)))
+    tem = Frun_hook_with_args_until_failure (1, arglist);
+    if (NILP (tem))
       return unbind_to (count, Qnil);
 
     /* Then run the hooks.  */
@@ -1685,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);
@@ -1727,9 +1762,6 @@ do not put this buffer at the front of the list of recently selected ones.  */)
        }
     }
   Fset_buffer (buf);
-  if (NILP (norecord))
-    /* Why bother ?  Fselect_window will do it for us anyway.  -stef  */
-    record_buffer (buf);
   Fselect_window (Fdisplay_buffer (buf, other_window, Qnil), norecord);
   return buf;
 }
@@ -1968,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;
 }
 
@@ -2121,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");
@@ -2133,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);
@@ -2349,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.  */
@@ -2408,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
@@ -2487,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
@@ -3576,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;
@@ -3671,6 +3714,10 @@ modify_overlay (buf, start, end)
   /* If multiple windows show this buffer, we must do other windows.  */
   else if (buffer_shared > 1)
     windows_or_buffers_changed = 1;
+  /* If we modify an overlay at the end of the buffer, we cannot
+     be sure that window end is still valid.  */
+  else if (end >= ZV && start <= ZV)
+    windows_or_buffers_changed = 1;
 
   ++BUF_OVERLAY_MODIFF (buf);
 }
@@ -3957,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;
 {
@@ -3998,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;
 {
@@ -4112,6 +4161,7 @@ DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
              == OVERLAY_POSITION (OVERLAY_END (overlay))))
        Fdelete_overlay (overlay);
     }
+
   return value;
 }
 \f
@@ -5015,6 +5065,8 @@ init_buffer_once ()
   buffer_defaults.vertical_scroll_bar_type = Qt;
   buffer_defaults.indicate_empty_lines = Qnil;
   buffer_defaults.indicate_buffer_boundaries = Qnil;
+  buffer_defaults.fringe_indicator_alist = Qnil;
+  buffer_defaults.fringe_cursor_alist = Qnil;
   buffer_defaults.scroll_up_aggressively = Qnil;
   buffer_defaults.scroll_down_aggressively = Qnil;
   buffer_defaults.display_time = Qnil;
@@ -5086,6 +5138,8 @@ init_buffer_once ()
   XSETFASTINT (buffer_local_flags.vertical_scroll_bar_type, idx); ++idx;
   XSETFASTINT (buffer_local_flags.indicate_empty_lines, idx); ++idx;
   XSETFASTINT (buffer_local_flags.indicate_buffer_boundaries, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.fringe_indicator_alist, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.fringe_cursor_alist, idx); ++idx;
   XSETFASTINT (buffer_local_flags.scroll_up_aggressively, idx); ++idx;
   XSETFASTINT (buffer_local_flags.scroll_down_aggressively, idx); ++idx;
   XSETFASTINT (buffer_local_flags.header_line_format, idx); ++idx;
@@ -5131,11 +5185,9 @@ init_buffer_once ()
 void
 init_buffer ()
 {
-  char buf[MAXPATHLEN + 1];
   char *pwd;
-  struct stat dotstat, pwdstat;
   Lisp_Object temp;
-  int rc;
+  int len;
 
 #ifdef USE_MMAP_FOR_BUFFERS
  {
@@ -5154,40 +5206,28 @@ init_buffer ()
   if (NILP (buffer_defaults.enable_multibyte_characters))
     Fset_buffer_multibyte (Qnil);
 
-  /* If PWD is accurate, use it instead of calling getwd.  PWD is
-     sometimes a nicer name, and using it may avoid a fatal error if a
-     parent directory is searchable but not readable.  */
-  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
-      && dotstat.st_dev == pwdstat.st_dev
-      && strlen (pwd) < MAXPATHLEN)
-    strcpy (buf, pwd);
-#ifdef HAVE_GETCWD
-  else if (getcwd (buf, MAXPATHLEN+1) == 0)
-    fatal ("`getcwd' failed: %s\n", strerror (errno));
-#else
-  else if (getwd (buf) == 0)
-    fatal ("`getwd' failed: %s\n", buf);
-#endif
+  pwd = get_current_dir_name ();
+
+  if (!pwd)
+    fatal ("`get_current_dir_name' failed: %s\n", strerror (errno));
 
 #ifndef VMS
   /* Maybe this should really use some standard subroutine
      whose definition is filename syntax dependent.  */
-  rc = strlen (buf);
-  if (!(IS_DIRECTORY_SEP (buf[rc - 1])))
+  len = strlen (pwd);
+  if (!(IS_DIRECTORY_SEP (pwd[len - 1])))
     {
-      buf[rc] = DIRECTORY_SEP;
-      buf[rc + 1] = '\0';
+      /* Grow buffer to add directory separator and '\0'.  */
+      pwd = (char *) xrealloc (pwd, len + 2);
+      pwd[len] = DIRECTORY_SEP;
+      pwd[len + 1] = '\0';
     }
 #endif /* not VMS */
 
-  current_buffer->directory = make_unibyte_string (buf, strlen (buf));
+  current_buffer->directory = make_unibyte_string (pwd, strlen (pwd));
   if (! NILP (buffer_defaults.enable_multibyte_characters))
-    /* At this momemnt, we still don't know how to decode the
-       direcotry name.  So, we keep the bytes in multibyte form so
+    /* 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.  */
     current_buffer->directory
       = string_to_multibyte (current_buffer->directory);
@@ -5206,6 +5246,8 @@ init_buffer ()
 
   temp = get_minibuffer (0);
   XBUFFER (temp)->directory = current_buffer->directory;
+
+  free (pwd);
 }
 
 /* initialize the buffer routines */
@@ -5391,17 +5433,27 @@ This is the same as (default-value 'indicate-empty-lines).  */);
                     doc: /* Default value of `indicate-buffer-boundaries' for buffers that don't override it.
 This is the same as (default-value 'indicate-buffer-boundaries).  */);
 
+  DEFVAR_LISP_NOPRO ("default-fringe-indicator-alist",
+                    &buffer_defaults.fringe_indicator_alist,
+                    doc: /* Default value of `fringe-indicator-alist' for buffers that don't override it.
+This is the same as (default-value 'fringe-indicator-alist').  */);
+
+  DEFVAR_LISP_NOPRO ("default-fringe-cursor-alist",
+                    &buffer_defaults.fringe_cursor_alist,
+                    doc: /* Default value of `fringe-cursor-alist' for buffers that don't override it.
+This is the same as (default-value 'fringe-cursor-alist').  */);
+
   DEFVAR_LISP_NOPRO ("default-scroll-up-aggressively",
                     &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,
@@ -5453,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
@@ -5494,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,
@@ -5736,6 +5789,40 @@ left fringe, the bottom angle bitmap in right fringe, and both arrow
 bitmaps in right fringe.  To show just the angle bitmaps in the left
 fringe, but no arrow bitmaps, use ((top .  left) (bottom . left)).  */);
 
+  DEFVAR_PER_BUFFER ("fringe-indicator-alist",
+                    &current_buffer->fringe_indicator_alist, Qnil,
+                    doc: /* *Mapping from logical to physical fringe indicator bitmaps.
+The value is an alist where each element (INDICATOR . BITMAPS)
+specifies the fringe bitmaps used to display a specific logical
+fringe indicator.
+
+INDICATOR specifies the logical indicator type which is one of the
+following symbols: `truncation' , `continuation', `overlay-arrow',
+`top', `bottom', `up', `down', `one-line', `empty-line', or `unknown'.
+
+BITMAPS is list of symbols (LEFT RIGHT [LEFT1 RIGHT1]) which specifies
+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
+symbol which is used in both left and right fringes.  */);
+
+  DEFVAR_PER_BUFFER ("fringe-cursor-alist",
+                    &current_buffer->fringe_cursor_alist, Qnil,
+                    doc: /* *Mapping from logical to physical fringe cursor bitmaps.
+The value is an alist where each element (CURSOR . BITMAP)
+specifies the fringe bitmaps used to display a specific logical
+cursor type in the fringe.
+
+CURSOR specifies the logical cursor type which is one of the following
+symbols: `box' , `hollow', `bar', `hbar', or `hollow-small'.  The last
+one is used to show a hollow cursor on narrow lines display lines
+where the normal hollow cursor will not fit.
+
+BITMAP is the corresponding fringe bitmap shown for the logical
+cursor type.  */);
+
   DEFVAR_PER_BUFFER ("scroll-up-aggressively",
                     &current_buffer->scroll_up_aggressively, Qnil,
                     doc: /* How far to scroll windows upward.
@@ -5847,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.  */);
 
@@ -5965,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);
@@ -5992,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);