/* Buffer manipulation primitives for GNU Emacs.
- Copyright (C) 1985, 86, 87, 88, 89, 93, 94, 95, 97, 98, 99,
- 2000, 01, 02, 03, 04, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994,
+ 1995, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
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>
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;
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;
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);
Sbuffer_local_value, 2, 2, 0,
doc: /* Return the value of VARIABLE in BUFFER.
If VARIABLE does not have a buffer-local binding in BUFFER, the value
-is the default binding of variable. */)
- (symbol, buffer)
- register Lisp_Object symbol;
+is the default binding of the variable. */)
+ (variable, buffer)
+ register Lisp_Object variable;
register Lisp_Object buffer;
{
register struct buffer *buf;
register Lisp_Object result;
- CHECK_SYMBOL (symbol);
+ CHECK_SYMBOL (variable);
CHECK_BUFFER (buffer);
buf = XBUFFER (buffer);
+ if (SYMBOLP (variable))
+ variable = indirect_variable (variable);
+
/* Look in local_var_list */
- result = Fassoc (symbol, buf->local_var_alist);
+ result = Fassoc (variable, buf->local_var_alist);
if (NILP (result))
{
int offset, idx;
idx = PER_BUFFER_IDX (offset);
if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
&& SYMBOLP (PER_BUFFER_SYMBOL (offset))
- && EQ (PER_BUFFER_SYMBOL (offset), symbol))
+ && EQ (PER_BUFFER_SYMBOL (offset), variable))
{
result = PER_BUFFER_VALUE (buf, offset);
found = 1;
}
if (!found)
- result = Fdefault_value (symbol);
+ result = Fdefault_value (variable);
}
else
{
Lisp_Object current_alist_element;
/* What binding is loaded right now? */
- valcontents = SYMBOL_VALUE (symbol);
+ valcontents = SYMBOL_VALUE (variable);
current_alist_element
= XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
result = XCDR (result);
}
- if (EQ (result, Qunbound))
- return Fsignal (Qvoid_variable, Fcons (symbol, Qnil));
+ if (!EQ (result, Qunbound))
+ return result;
- return result;
+ xsignal1 (Qvoid_variable, variable);
}
/* Return an alist of the Lisp-level buffer-local bindings of
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",
/* 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. */
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);
}
}
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;
}
{
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;
}
{
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");
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);
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. */
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
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
doc: /* Create a new overlay with range BEG to END in BUFFER.
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
-front delimiter advance when text is inserted there.
-The fifth arg REAR-ADVANCE, if non-nil, makes the
-rear delimiter advance when text is inserted there. */)
+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).
+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). */)
(beg, end, buffer, front_advance, rear_advance)
Lisp_Object beg, end, buffer;
Lisp_Object front_advance, rear_advance;
/* 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);
}
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;
{
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;
{
== OVERLAY_POSITION (OVERLAY_END (overlay))))
Fdelete_overlay (overlay);
}
+
return value;
}
\f
buffer_defaults.direction_reversed = Qnil;
buffer_defaults.cursor_type = Qt;
buffer_defaults.extra_line_spacing = Qnil;
+ buffer_defaults.cursor_in_non_selected_windows = Qt;
#ifdef DOS_NT
buffer_defaults.buffer_file_type = Qnil; /* TEXT */
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;
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;
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
{
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);
temp = get_minibuffer (0);
XBUFFER (temp)->directory = current_buffer->directory;
+
+ free (pwd);
}
/* initialize the buffer routines */
doc: /* Default value of `line-spacing' for buffers that don't override it.
This is the same as (default-value 'line-spacing). */);
+ DEFVAR_LISP_NOPRO ("default-cursor-in-non-selected-windows",
+ &buffer_defaults.cursor_in_non_selected_windows,
+ doc: /* Default value of `cursor-in-non-selected-windows'.
+This is the same as (default-value 'cursor-in-non-selected-windows). */);
+
DEFVAR_LISP_NOPRO ("default-abbrev-mode",
&buffer_defaults.abbrev_mode,
doc: /* Default value of `abbrev-mode' for buffers that do not override it.
doc: /* Default value of `ctl-arrow' for buffers that do not override it.
This is the same as (default-value 'ctl-arrow). */);
- DEFVAR_LISP_NOPRO ("default-direction-reversed",
- &buffer_defaults.direction_reversed,
- doc: /* Default value of `direction-reversed' for buffers that do not override it.
+ DEFVAR_LISP_NOPRO ("default-direction-reversed",
+ &buffer_defaults.direction_reversed,
+ doc: /* Default value of `direction-reversed' for buffers that do not override it.
This is the same as (default-value 'direction-reversed). */);
- DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
- &buffer_defaults.enable_multibyte_characters,
- doc: /* *Default value of `enable-multibyte-characters' for buffers not overriding it.
+ DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
+ &buffer_defaults.enable_multibyte_characters,
+ doc: /* *Default value of `enable-multibyte-characters' for buffers not overriding it.
This is the same as (default-value 'enable-multibyte-characters). */);
- DEFVAR_LISP_NOPRO ("default-buffer-file-coding-system",
- &buffer_defaults.buffer_file_coding_system,
- doc: /* Default value of `buffer-file-coding-system' for buffers not overriding it.
+ DEFVAR_LISP_NOPRO ("default-buffer-file-coding-system",
+ &buffer_defaults.buffer_file_coding_system,
+ doc: /* Default value of `buffer-file-coding-system' for buffers not overriding it.
This is the same as (default-value 'buffer-file-coding-system). */);
DEFVAR_LISP_NOPRO ("default-truncate-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'.
%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.
+ %t -- visited file is text or binary (if OS supports this distinction).
%z -- print mnemonics of buffer, terminal, and keyboard 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. */);
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",
+ ¤t_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",
+ ¤t_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",
¤t_buffer->scroll_up_aggressively, Qnil,
doc: /* How far to scroll windows upward.
When the value is 0.0, point goes at the bottom line, which in the simple
case that you moved off with C-f means scrolling just one line. 1.0 means
point goes at the top, so that in that simple case, the window
-window scrolls by a full window height. Meaningful values are
+scrolls by a full window height. Meaningful values are
between 0.0 and 1.0, inclusive. */);
DEFVAR_PER_BUFFER ("scroll-down-aggressively",
When the value is 0.0, point goes at the top line, which in the simple
case that you moved off with C-b means scrolling just one line. 1.0 means
point goes at the bottom, so that in that simple case, the window
-window scrolls by a full window height. Meaningful values are
+scrolls by a full window height. Meaningful values are
between 0.0 and 1.0, inclusive. */);
/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
doc: /* Cursor to use when this buffer is in the selected window.
Values are interpreted as follows:
- t use the cursor specified for the frame
- nil don't display a cursor
- box display a filled box cursor
- hollow display a hollow box cursor
- bar display a vertical bar cursor with default width
- (bar . WIDTH) display a vertical bar cursor with width WIDTH
- hbar display a horizontal bar cursor with default width
- (hbar . WIDTH) display a horizontal bar cursor with width WIDTH
- ANYTHING ELSE display a hollow box cursor.
+ t use the cursor specified for the frame
+ nil don't display a cursor
+ box display a filled box cursor
+ hollow display a hollow box cursor
+ bar display a vertical bar cursor with default width
+ (bar . WIDTH) display a vertical bar cursor with width WIDTH
+ hbar display a horizontal bar cursor with default height
+ (hbar . HEIGHT) display a horizontal bar cursor with height HEIGHT
+ ANYTHING ELSE display a hollow box cursor
When the buffer is displayed in a nonselected window,
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. nil means add no extra space. */);
DEFVAR_PER_BUFFER ("cursor-in-non-selected-windows",
- ¤t_buffer->cursor_in_non_selected_windows, Qt,
+ ¤t_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. */);
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);
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);