X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/b17f53abc28496125965f36147b76ea5f6a2b4fb..5dcde606e32d1794f8268ea51cd2d1746e45a311:/src/buffer.c diff --git a/src/buffer.c b/src/buffer.c index 58e2bd9e4c..a0acad309a 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,14 +1,15 @@ /* 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, 2006, 2007 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +17,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 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., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ #include @@ -27,6 +26,7 @@ Boston, MA 02110-1301, USA. */ #include #include #include +#include #ifndef USE_CRT_DLL extern int errno; @@ -42,7 +42,7 @@ extern int errno; #include "window.h" #include "commands.h" #include "buffer.h" -#include "charset.h" +#include "character.h" #include "region-cache.h" #include "indent.h" #include "blockinput.h" @@ -152,6 +152,7 @@ Lisp_Object Qucs_set_table_for_input; int inhibit_modification_hooks; Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local; +Lisp_Object Qpermanent_local_hook; Lisp_Object Qprotected_field; @@ -175,6 +176,7 @@ static struct Lisp_Overlay * copy_overlays P_ ((struct buffer *, struct Lisp_Ove static void modify_overlay P_ ((struct buffer *, EMACS_INT, EMACS_INT)); static Lisp_Object buffer_lisp_local_variables P_ ((struct buffer *)); +extern char * emacs_strerror P_ ((int)); /* For debugging; temporary. See set_buffer_internal. */ /* Lisp_Object Qlisp_mode, Vcheck_symbol; */ @@ -265,17 +267,18 @@ assoc_ignore_text_properties (key, list) } DEFUN ("get-buffer", Fget_buffer, Sget_buffer, 1, 1, 0, - doc: /* Return the buffer named NAME (a string). -If there is no live buffer named NAME, return nil. -NAME may also be a buffer; if so, the value is that buffer. */) - (name) - register Lisp_Object name; + doc: /* Return the buffer named BUFFER-OR-NAME. +BUFFER-OR-NAME must be either a string or a buffer. If BUFFER-OR-NAME +is a string and there is no buffer with that name, return nil. If +BUFFER-OR-NAME is a buffer, return it as given. */) + (buffer_or_name) + register Lisp_Object buffer_or_name; { - if (BUFFERP (name)) - return name; - CHECK_STRING (name); + if (BUFFERP (buffer_or_name)) + return buffer_or_name; + CHECK_STRING (buffer_or_name); - return Fcdr (assoc_ignore_text_properties (name, Vbuffer_alist)); + return Fcdr (assoc_ignore_text_properties (buffer_or_name, Vbuffer_alist)); } DEFUN ("get-file-buffer", Fget_file_buffer, Sget_file_buffer, 1, 1, 0, @@ -332,22 +335,25 @@ get_truename_buffer (filename) int buffer_count; DEFUN ("get-buffer-create", Fget_buffer_create, Sget_buffer_create, 1, 1, 0, - doc: /* Return the buffer named NAME, or create such a buffer and return it. -A new buffer is created if there is no live buffer named NAME. -If NAME starts with a space, the new buffer does not keep undo information. -If NAME is a buffer instead of a string, then it is the value returned. -The value is never nil. */) - (name) - register Lisp_Object name; + doc: /* Return the buffer specified by BUFFER-OR-NAME, creating a new one if needed. +If BUFFER-OR-NAME is a string and a live buffer with that name exists, +return that buffer. If no such buffer exists, create a new buffer with +that name and return it. If BUFFER-OR-NAME starts with a space, the new +buffer does not keep undo information. + +If BUFFER-OR-NAME is a buffer instead of a string, return it as given, +even if it is dead. The return value is never nil. */) + (buffer_or_name) + register Lisp_Object buffer_or_name; { - register Lisp_Object buf; + register Lisp_Object buffer, name; register struct buffer *b; - buf = Fget_buffer (name); - if (!NILP (buf)) - return buf; + buffer = Fget_buffer (buffer_or_name); + if (!NILP (buffer)) + return buffer; - if (SCHARS (name) == 0) + if (SCHARS (buffer_or_name) == 0) error ("Empty string for buffer name is not allowed"); b = allocate_buffer (); @@ -401,7 +407,7 @@ The value is never nil. */) b->begv_marker = Qnil; b->zv_marker = Qnil; - name = Fcopy_sequence (name); + name = Fcopy_sequence (buffer_or_name); STRING_SET_INTERVALS (name, NULL_INTERVAL); b->name = name; @@ -415,17 +421,17 @@ The value is never nil. */) b->name = name; /* Put this in the alist of all live buffers. */ - XSETBUFFER (buf, b); - Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil)); + XSETBUFFER (buffer, b); + Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buffer), Qnil)); /* An error in calling the function here (should someone redefine it) can lead to infinite regress until you run out of stack. rms says that's not worth protecting against. */ if (!NILP (Ffboundp (Qucs_set_table_for_input))) - /* buf is on buffer-alist, so no gcpro. */ - call1 (Qucs_set_table_for_input, buf); + /* buffer is on buffer-alist, so no gcpro. */ + call1 (Qucs_set_table_for_input, buffer); - return buf; + return buffer; } @@ -493,12 +499,18 @@ clone_per_buffer_values (from, to) XSETBUFFER (to_buffer, to); - for (offset = PER_BUFFER_VAR_OFFSET (name) + sizeof (Lisp_Object); + /* buffer-local Lisp variables start at `undo_list', + tho only the ones from `name' on are GC'd normally. */ + for (offset = PER_BUFFER_VAR_OFFSET (undo_list); offset < sizeof *to; offset += sizeof (Lisp_Object)) { Lisp_Object obj; + /* Don't touch the `name' which should be unique for every buffer. */ + if (offset == PER_BUFFER_VAR_OFFSET (name)) + continue; + obj = PER_BUFFER_VALUE (from, offset); if (MARKERP (obj)) { @@ -692,7 +704,7 @@ reset_buffer (b) b->clip_changed = 0; b->prevent_redisplay_optimizations_p = 1; b->backed_up = Qnil; - b->auto_save_modified = 0; + BUF_AUTOSAVE_MODIFF (b) = 0; b->auto_save_failure_time = -1; b->auto_save_file_name = Qnil; b->read_only = Qnil; @@ -760,13 +772,38 @@ reset_buffer_local_variables (b, permanent_too) b->local_var_alist = Qnil; else { - Lisp_Object tmp, last = Qnil; + Lisp_Object tmp, prop, last = Qnil; for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp)) if (CONSP (XCAR (tmp)) && SYMBOLP (XCAR (XCAR (tmp))) - && !NILP (Fget (XCAR (XCAR (tmp)), Qpermanent_local))) - /* If permanent-local, keep it. */ - last = tmp; + && !NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local))) + { + /* If permanent-local, keep it. */ + last = tmp; + if (EQ (prop, Qpermanent_local_hook)) + { + /* This is a partially permanent hook variable. + Preserve only the elements that want to be preserved. */ + Lisp_Object list, newlist; + list = XCDR (XCAR (tmp)); + if (!CONSP (list)) + newlist = list; + else + for (newlist = Qnil; CONSP (list); list = XCDR (list)) + { + Lisp_Object elt = XCAR (list); + /* Preserve element ELT if it's t, + if it is a function with a `permanent-local-hook' property, + or if it's not a symbol. */ + if (! SYMBOLP (elt) + || EQ (elt, Qt) + || !NILP (Fget (elt, Qpermanent_local_hook))) + newlist = Fcons (elt, newlist); + } + XSETCDR (XCAR (tmp), Fnreverse (newlist)); + } + } + /* Delete this local variable. */ else if (NILP (last)) b->local_var_alist = XCDR (tmp); else @@ -780,7 +817,9 @@ reset_buffer_local_variables (b, permanent_too) /* For each slot that has a default value, copy that into the slot. */ - for (offset = PER_BUFFER_VAR_OFFSET (name); + /* buffer-local Lisp variables start at `undo_list', + tho only the ones from `name' on are GC'd normally. */ + for (offset = PER_BUFFER_VAR_OFFSET (undo_list); offset < sizeof *b; offset += sizeof (Lisp_Object)) { @@ -839,7 +878,8 @@ it is in the sequence to be tried) even if a buffer with that name exists. */) DEFUN ("buffer-name", Fbuffer_name, Sbuffer_name, 0, 1, 0, doc: /* Return the name of BUFFER, as a string. -With no argument or nil as argument, return the name of the current buffer. */) +BUFFER defaults to the current buffer. +Return nil if BUFFER has been killed. */) (buffer) register Lisp_Object buffer; { @@ -897,12 +937,14 @@ is the default binding of the variable. */) { register struct buffer *buf; register Lisp_Object result; + struct Lisp_Symbol *sym; CHECK_SYMBOL (variable); CHECK_BUFFER (buffer); buf = XBUFFER (buffer); - variable = indirect_variable (variable); + sym = indirect_variable (XSYMBOL (variable)); + XSETSYMBOL (variable, sym); /* Look in local_var_list */ result = Fassoc (variable, buf->local_var_alist); @@ -912,7 +954,9 @@ is the default binding of the variable. */) int found = 0; /* Look in special slots */ - for (offset = PER_BUFFER_VAR_OFFSET (name); + /* buffer-local Lisp variables start at `undo_list', + tho only the ones from `name' on are GC'd normally. */ + for (offset = PER_BUFFER_VAR_OFFSET (undo_list); offset < sizeof (struct buffer); /* sizeof EMACS_INT == sizeof Lisp_Object */ offset += (sizeof (EMACS_INT))) @@ -937,7 +981,7 @@ is the default binding of the variable. */) Lisp_Object current_alist_element; /* What binding is loaded right now? */ - valcontents = SYMBOL_VALUE (variable); + valcontents = sym->value; current_alist_element = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); @@ -1023,7 +1067,9 @@ No argument or nil as argument means use current buffer as BUFFER. */) { int offset, idx; - for (offset = PER_BUFFER_VAR_OFFSET (name); + /* buffer-local Lisp variables start at `undo_list', + tho only the ones from `name' on are GC'd normally. */ + for (offset = PER_BUFFER_VAR_OFFSET (undo_list); offset < sizeof (struct buffer); /* sizeof EMACS_INT == sizeof Lisp_Object */ offset += (sizeof (EMACS_INT))) @@ -1086,7 +1132,25 @@ A non-nil FLAG means mark the buffer modified. */) } #endif /* CLASH_DETECTION */ - SAVE_MODIFF = NILP (flag) ? MODIFF : 0; + /* Here we have a problem. SAVE_MODIFF is used here to encode + buffer-modified-p (as SAVE_MODIFF=auto_save_modified + we risk changing recent-auto-save-p from nil to t. */ + SAVE_MODIFF = (NILP (flag) + /* FIXME: This unavoidably sets recent-auto-save-p to nil. */ + ? MODIFF + /* Let's try to preserve recent-auto-save-p. */ + : SAVE_MODIFF < MODIFF ? SAVE_MODIFF + /* If SAVE_MODIFF == auto_save_modified == MODIFF, + we can either decrease SAVE_MODIFF and auto_save_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 @@ -1342,38 +1406,39 @@ Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\ The buffer being killed will be current while the hook is running.\n\ See `kill-buffer'." */ -DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 1, 1, "bKill buffer: ", - doc: /* Kill the buffer BUFFER. -The argument may be a buffer or the name of a buffer. -With a nil argument, kill the current buffer. - -Value is t if the buffer is actually killed, nil otherwise. - -The functions in `kill-buffer-query-functions' are called with BUFFER as -the current buffer. If any of them returns nil, the buffer is not killed. - -The hook `kill-buffer-hook' is run before the buffer is actually killed. -The buffer being killed will be current while the hook is running. +DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", + doc: /* Kill buffer BUFFER-OR-NAME. +The argument may be a buffer or the name of an existing buffer. +Argument nil or omitted means kill the current buffer. Return t if the +buffer is actually killed, nil otherwise. + +This function calls `replace-buffer-in-windows' for cleaning up all +windows currently displaying the buffer to be killed. The functions in +`kill-buffer-query-functions' are called with the buffer to be killed as +the current buffer. If any of them returns nil, the buffer is not +killed. The hook `kill-buffer-hook' is run before the buffer is +actually killed. The buffer being killed will be current while the hook +is running. Any processes that have this buffer as the `process-buffer' are killed with SIGHUP. */) - (buffer) - Lisp_Object buffer; + (buffer_or_name) + Lisp_Object buffer_or_name; { - Lisp_Object buf; + Lisp_Object buffer; register struct buffer *b; register Lisp_Object tem; register struct Lisp_Marker *m; struct gcpro gcpro1; - if (NILP (buffer)) - buf = Fcurrent_buffer (); + if (NILP (buffer_or_name)) + buffer = Fcurrent_buffer (); else - buf = Fget_buffer (buffer); - if (NILP (buf)) - nsberror (buffer); + buffer = Fget_buffer (buffer_or_name); + if (NILP (buffer)) + nsberror (buffer_or_name); - b = XBUFFER (buf); + b = XBUFFER (buffer); /* Avoid trouble for buffer already dead. */ if (NILP (b->name)) @@ -1383,7 +1448,7 @@ with SIGHUP. */) if (INTERACTIVE && !NILP (b->filename) && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) { - GCPRO1 (buf); + GCPRO1 (buffer); tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ", b->name, make_number (0))); UNGCPRO; @@ -1416,7 +1481,7 @@ with SIGHUP. */) since anything can happen within do_yes_or_no_p. */ /* Don't kill the minibuffer now current. */ - if (EQ (buf, XWINDOW (minibuf_window)->buffer)) + if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) return Qnil; if (NILP (b->name)) @@ -1429,16 +1494,16 @@ with SIGHUP. */) { struct buffer *other; - GCPRO1 (buf); + GCPRO1 (buffer); for (other = all_buffers; other; other = other->next) /* all_buffers contains dead buffers too; don't re-kill them. */ if (other->base_buffer == b && !NILP (other->name)) { - Lisp_Object buf; - XSETBUFFER (buf, other); - Fkill_buffer (buf); + Lisp_Object buffer; + XSETBUFFER (buffer, other); + Fkill_buffer (buffer); } UNGCPRO; @@ -1449,7 +1514,7 @@ with SIGHUP. */) and give up if so. */ if (b == current_buffer) { - tem = Fother_buffer (buf, Qnil, Qnil); + tem = Fother_buffer (buffer, Qnil, Qnil); Fset_buffer (tem); if (b == current_buffer) return Qnil; @@ -1460,8 +1525,8 @@ with SIGHUP. */) XSETBUFFER (tem, current_buffer); if (EQ (tem, XWINDOW (minibuf_window)->buffer)) { - tem = Fother_buffer (buf, Qnil, Qnil); - if (EQ (buf, tem)) + tem = Fother_buffer (buffer, Qnil, Qnil); + if (EQ (buffer, tem)) return Qnil; } @@ -1472,8 +1537,8 @@ with SIGHUP. */) unlock_buffer (b); #endif /* CLASH_DETECTION */ - GCPRO1 (buf); - kill_buffer_processes (buf); + GCPRO1 (buffer); + kill_buffer_processes (buffer); UNGCPRO; /* Killing buffer processes may run sentinels which may @@ -1486,16 +1551,16 @@ with SIGHUP. */) tem = Vinhibit_quit; Vinhibit_quit = Qt; - replace_buffer_in_all_windows (buf); - Vbuffer_alist = Fdelq (Frassq (buf, Vbuffer_alist), Vbuffer_alist); - frames_discard_buffer (buf); + replace_buffer_in_all_windows (buffer); + Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); + frames_discard_buffer (buffer); Vinhibit_quit = tem; /* Delete any auto-save file, if we saved it in this session. But not if the buffer is modified. */ if (STRINGP (b->auto_save_file_name) - && b->auto_save_modified != 0 - && BUF_SAVE_MODIFF (b) < b->auto_save_modified + && BUF_AUTOSAVE_MODIFF (b) != 0 + && BUF_SAVE_MODIFF (b) < BUF_AUTOSAVE_MODIFF (b) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b) && NILP (Fsymbol_value (intern ("auto-save-visited-file-name")))) { @@ -1598,7 +1663,7 @@ record_buffer (buf) Vbuffer_alist = link; /* Effectively do a delq on buried_buffer_list. */ - + prev = Qnil; for (link = XFRAME (frame)->buried_buffer_list; CONSP (link); link = XCDR (link)) @@ -1683,128 +1748,88 @@ the current buffer's major mode. */) return unbind_to (count, Qnil); } -/* If switching buffers in WINDOW would be an error, return - a C string saying what the error would be. */ - -char * -no_switch_window (window) - Lisp_Object window; -{ - Lisp_Object tem; - if (EQ (minibuf_window, window)) - return "Cannot switch buffers in minibuffer window"; - tem = Fwindow_dedicated_p (window); - if (EQ (tem, Qt)) - return "Cannot switch buffers in a dedicated window"; - return NULL; -} - /* Switch to buffer BUFFER in the selected window. If NORECORD is non-nil, don't call record_buffer. */ Lisp_Object -switch_to_buffer_1 (buffer, norecord) - Lisp_Object buffer, norecord; +switch_to_buffer_1 (buffer_or_name, norecord) + Lisp_Object buffer_or_name, norecord; { - register Lisp_Object buf; + register Lisp_Object buffer; - if (NILP (buffer)) - buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil); + if (NILP (buffer_or_name)) + buffer = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil); else { - buf = Fget_buffer (buffer); - if (NILP (buf)) + buffer = Fget_buffer (buffer_or_name); + if (NILP (buffer)) { - buf = Fget_buffer_create (buffer); - Fset_buffer_major_mode (buf); + buffer = Fget_buffer_create (buffer_or_name); + Fset_buffer_major_mode (buffer); } } - Fset_buffer (buf); + Fset_buffer (buffer); if (NILP (norecord)) - record_buffer (buf); + record_buffer (buffer); Fset_window_buffer (EQ (selected_window, minibuf_window) ? Fnext_window (minibuf_window, Qnil, Qnil) : selected_window, - buf, Qnil); + buffer, Qnil); - return buf; + return buffer; } -DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "BSwitch to buffer: ", - doc: /* Select buffer BUFFER in the current window. -If BUFFER does not identify an existing buffer, -then this function creates a buffer with that name. +DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, + "(list (read-buffer-to-switch \"Switch to buffer: \"))", + doc: /* Make BUFFER-OR-NAME current and display it in selected window. +BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or +nil. Return the buffer switched to. + +If BUFFER-OR-NAME is a string and does not identify an existing +buffer, create a new buffer with that name. Interactively, if +`confirm-nonexistent-file-or-buffer' is non-nil, request +confirmation before creating a new buffer. If BUFFER-OR-NAME is +nil, switch to buffer returned by `other-buffer'. -When called from Lisp, BUFFER may be a buffer, a string \(a buffer name), -or nil. If BUFFER is nil, then this function chooses a buffer -using `other-buffer'. -Optional second arg NORECORD non-nil means -do not put this buffer at the front of the list of recently selected ones. -This function returns the buffer it switched to. +Optional second arg NORECORD non-nil means do not put this buffer +at the front of the list of recently selected ones. This +function returns the buffer it switched to as a Lisp object. + +If the selected window is the minibuffer window or dedicated to +its buffer, use `pop-to-buffer' for displaying the buffer. WARNING: This is NOT the way to work on another buffer temporarily -within a Lisp program! Use `set-buffer' instead. That avoids messing with -the window-buffer correspondences. */) - (buffer, norecord) - Lisp_Object buffer, norecord; +within a Lisp program! Use `set-buffer' instead. That avoids +messing with the window-buffer correspondences. */) + (buffer_or_name, norecord) + Lisp_Object buffer_or_name, norecord; { char *err; - if (EQ (buffer, Fwindow_buffer (selected_window))) + if (EQ (buffer_or_name, Fwindow_buffer (selected_window))) { /* 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. */ + /* But do put this buffer at the front of the buffer list, unless + that has been inhibited. Note that even if BUFFER-OR-NAME 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); + record_buffer (buffer_or_name); + return Fset_buffer (buffer_or_name); } - - err = no_switch_window (selected_window); - if (err) error (err); - - return switch_to_buffer_1 (buffer, norecord); -} - -DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 3, 0, - doc: /* Select buffer BUFFER in some window, preferably a different one. -BUFFER may be a buffer, a string \(a buffer name), or nil. -If BUFFER is a string which is not the name of an existing buffer, -then this function creates a buffer with that name. -If BUFFER is nil, then it chooses some other buffer. -If `pop-up-windows' is non-nil, windows can be split to do this. -If optional second arg OTHER-WINDOW is non-nil, insist on finding another -window even if BUFFER is already visible in the selected window, -and ignore `same-window-regexps' and `same-window-buffer-names'. -This function returns the buffer it switched to. -This uses the function `display-buffer' as a subroutine; see the documentation -of `display-buffer' for additional customization information. - -Optional third arg NORECORD non-nil means -do not put this buffer at the front of the list of recently selected ones. */) - (buffer, other_window, norecord) - Lisp_Object buffer, other_window, norecord; -{ - register Lisp_Object buf; - if (NILP (buffer)) - buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil); + else if (EQ (minibuf_window, selected_window) + /* If `dedicated' is neither nil nor t, it means it's + dedicatedness can be overridden by an explicit request + such as a call to switch-to-buffer. */ + || EQ (Fwindow_dedicated_p (selected_window), Qt)) + /* We can't use the selected window so let `pop-to-buffer' try some + other window. */ + return call3 (intern ("pop-to-buffer"), buffer_or_name, Qnil, norecord); else - { - buf = Fget_buffer (buffer); - if (NILP (buf)) - { - buf = Fget_buffer_create (buffer); - Fset_buffer_major_mode (buf); - } - } - Fset_buffer (buf); - Fselect_window (Fdisplay_buffer (buf, other_window, Qnil), norecord); - return buf; + return switch_to_buffer_1 (buffer_or_name, norecord); } DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0, @@ -1916,12 +1941,14 @@ set_buffer_internal_1 (b) for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail)) { - valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))); - if ((BUFFER_LOCAL_VALUEP (valcontents)) + if (CONSP (XCAR (tail)) + && SYMBOLP (XCAR (XCAR (tail))) + && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))), + (BUFFER_LOCAL_VALUEP (valcontents))) && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) - /* Just reference the variable - to cause it to become set for this buffer. */ + /* Just reference the variable to cause it to become set for + this buffer. */ Fsymbol_value (XCAR (XCAR (tail))); } @@ -1930,12 +1957,14 @@ set_buffer_internal_1 (b) if (old_buf) for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail)) { - valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))); - if ((BUFFER_LOCAL_VALUEP (valcontents)) + if (CONSP (tail) + && SYMBOLP (XCAR (XCAR (tail))) + && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))), + (BUFFER_LOCAL_VALUEP (valcontents))) && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) - /* Just reference the variable - to cause it to become set for this buffer. */ + /* Just reference the variable to cause it to become set for + this buffer. */ Fsymbol_value (XCAR (XCAR (tail))); } } @@ -2002,23 +2031,23 @@ set_buffer_temp (b) } DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0, - doc: /* Make the buffer BUFFER current for editing operations. -BUFFER may be a buffer or the name of an existing buffer. -See also `save-excursion' 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. */) - (buffer) - register Lisp_Object buffer; + 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 `save-excursion' 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. */) + (buffer_or_name) + register Lisp_Object buffer_or_name; { - register Lisp_Object buf; - buf = Fget_buffer (buffer); - if (NILP (buf)) - nsberror (buffer); - if (NILP (XBUFFER (buf)->name)) + register Lisp_Object buffer; + buffer = Fget_buffer (buffer_or_name); + if (NILP (buffer)) + nsberror (buffer_or_name); + if (NILP (XBUFFER (buffer)->name)) error ("Selecting deleted buffer"); - set_buffer_internal (XBUFFER (buf)); - return buf; + set_buffer_internal (XBUFFER (buffer)); + return buffer; } /* Set the current buffer to BUFFER provided it is alive. */ @@ -2044,18 +2073,24 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only, } DEFUN ("bury-buffer", Fbury_buffer, Sbury_buffer, 0, 1, "", - doc: /* Put BUFFER at the end of the list of all buffers. + doc: /* Put BUFFER-OR-NAME at the end of the list of all buffers. There it is the least likely candidate for `other-buffer' to return; -thus, the least likely buffer for \\[switch-to-buffer] to select by default. -You can specify a buffer name as BUFFER, or an actual buffer object. -If BUFFER is nil or omitted, bury the current buffer. -Also, if BUFFER is nil or omitted, remove the current buffer from the -selected window if it is displayed there. */) - (buffer) - register Lisp_Object buffer; +thus, the least likely buffer for \\[switch-to-buffer] to select by +default. + +The argument may be a buffer name or an actual buffer object. If +BUFFER-OR-NAME is nil or omitted, bury the current buffer and remove it +from the selected window if it is displayed there. If the selected +window is dedicated to its buffer, delete that window if there are other +windows on the same frame. If the selected window is the only window on +its frame, iconify that frame. */) + (buffer_or_name) + register Lisp_Object buffer_or_name; { + Lisp_Object buffer; + /* Figure out what buffer we're going to bury. */ - if (NILP (buffer)) + if (NILP (buffer_or_name)) { Lisp_Object tem; XSETBUFFER (buffer, current_buffer); @@ -2074,12 +2109,9 @@ selected window if it is displayed there. */) } else { - Lisp_Object buf1; - - buf1 = Fget_buffer (buffer); - if (NILP (buf1)) - nsberror (buffer); - buffer = buf1; + buffer = Fget_buffer (buffer_or_name); + if (NILP (buffer)) + nsberror (buffer_or_name); } /* Move buffer to the end of the buffer list. Do nothing if the @@ -2176,13 +2208,148 @@ advance_to_char_boundary (byte_pos) return byte_pos; } +#ifdef REL_ALLOC +extern void r_alloc_reset_variable P_ ((POINTER_TYPE *, POINTER_TYPE *)); +#endif /* REL_ALLOC */ + +DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, + 1, 1, 0, + doc: /* Swap the text between current buffer and BUFFER. */) + (buffer) + Lisp_Object buffer; +{ + struct buffer *other_buffer; + CHECK_BUFFER (buffer); + other_buffer = XBUFFER (buffer); + + if (NILP (other_buffer->name)) + error ("Cannot swap a dead buffer's text"); + + /* Actually, it probably works just fine. + * if (other_buffer == current_buffer) + * error ("Cannot swap a buffer's text with itself"); */ + + /* Actually, this may be workable as well, tho probably only if they're + *both* indirect. */ + if (other_buffer->base_buffer + || current_buffer->base_buffer) + error ("Cannot swap indirect buffers's text"); + + { /* This is probably harder to make work. */ + struct buffer *other; + for (other = all_buffers; other; other = other->next) + if (other->base_buffer == other_buffer + || other->base_buffer == current_buffer) + error ("One of the buffers to swap has indirect buffers"); + } + +#define swapfield(field, type) \ + do { \ + type tmp##field = other_buffer->field; \ + other_buffer->field = current_buffer->field; \ + current_buffer->field = tmp##field; \ + } while (0) + + swapfield (own_text, struct buffer_text); + eassert (current_buffer->text == ¤t_buffer->own_text); + eassert (other_buffer->text == &other_buffer->own_text); +#ifdef REL_ALLOC + r_alloc_reset_variable ((POINTER_TYPE **) ¤t_buffer->own_text.beg, + (POINTER_TYPE **) &other_buffer->own_text.beg); + r_alloc_reset_variable ((POINTER_TYPE **) &other_buffer->own_text.beg, + (POINTER_TYPE **) ¤t_buffer->own_text.beg); +#endif /* REL_ALLOC */ + + swapfield (pt, EMACS_INT); + swapfield (pt_byte, EMACS_INT); + swapfield (begv, EMACS_INT); + swapfield (begv_byte, EMACS_INT); + swapfield (zv, EMACS_INT); + swapfield (zv_byte, EMACS_INT); + eassert (!current_buffer->base_buffer); + eassert (!other_buffer->base_buffer); + current_buffer->clip_changed = 1; other_buffer->clip_changed = 1; + swapfield (newline_cache, struct region_cache *); + swapfield (width_run_cache, struct region_cache *); + current_buffer->prevent_redisplay_optimizations_p = 1; + other_buffer->prevent_redisplay_optimizations_p = 1; + swapfield (overlays_before, struct Lisp_Overlay *); + swapfield (overlays_after, struct Lisp_Overlay *); + swapfield (overlay_center, EMACS_INT); + swapfield (undo_list, Lisp_Object); + swapfield (mark, Lisp_Object); + swapfield (enable_multibyte_characters, Lisp_Object); + /* FIXME: Not sure what we should do with these *_marker fields. + Hopefully they're just nil anyway. */ + swapfield (pt_marker, Lisp_Object); + swapfield (begv_marker, Lisp_Object); + swapfield (zv_marker, Lisp_Object); + current_buffer->point_before_scroll = Qnil; + other_buffer->point_before_scroll = Qnil; + + current_buffer->text->modiff++; other_buffer->text->modiff++; + current_buffer->text->chars_modiff++; other_buffer->text->chars_modiff++; + current_buffer->text->overlay_modiff++; other_buffer->text->overlay_modiff++; + current_buffer->text->beg_unchanged = current_buffer->text->gpt; + current_buffer->text->end_unchanged = current_buffer->text->gpt; + other_buffer->text->beg_unchanged = other_buffer->text->gpt; + other_buffer->text->end_unchanged = other_buffer->text->gpt; + { + struct Lisp_Marker *m; + for (m = BUF_MARKERS (current_buffer); m; m = m->next) + if (m->buffer == other_buffer) + m->buffer = current_buffer; + else + /* Since there's no indirect buffer in sight, markers on + BUF_MARKERS(buf) should either be for `buf' or dead. */ + eassert (!m->buffer); + for (m = BUF_MARKERS (other_buffer); m; m = m->next) + if (m->buffer == current_buffer) + m->buffer = other_buffer; + else + /* Since there's no indirect buffer in sight, markers on + BUF_MARKERS(buf) should either be for `buf' or dead. */ + eassert (!m->buffer); + } + { /* Some of the C code expects that w->buffer == w->pointm->buffer. + So since we just swapped the markers between the two buffers, we need + to undo the effect of this swap for window markers. */ + Lisp_Object w = Fselected_window (), ws = Qnil; + Lisp_Object buf1, buf2; + XSETBUFFER (buf1, current_buffer); XSETBUFFER (buf2, other_buffer); + + while (NILP (Fmemq (w, ws))) + { + ws = Fcons (w, ws); + if (MARKERP (XWINDOW (w)->pointm) + && (EQ (XWINDOW (w)->buffer, buf1) + || EQ (XWINDOW (w)->buffer, buf2))) + Fset_marker (XWINDOW (w)->pointm, + make_number (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))), + XWINDOW (w)->buffer); + w = Fnext_window (w, Qt, Qt); + } + } + + if (current_buffer->text->intervals) + (eassert (EQ (current_buffer->text->intervals->up.obj, buffer)), + XSETBUFFER (current_buffer->text->intervals->up.obj, current_buffer)); + if (other_buffer->text->intervals) + (eassert (EQ (other_buffer->text->intervals->up.obj, Fcurrent_buffer ())), + XSETBUFFER (other_buffer->text->intervals->up.obj, other_buffer)); + + return Qnil; +} + DEFUN ("set-buffer-multibyte", Fset_buffer_multibyte, Sset_buffer_multibyte, 1, 1, 0, doc: /* Set the multibyte flag of the current buffer to FLAG. If FLAG is t, this makes the buffer a multibyte buffer. If FLAG is nil, this makes the buffer a single-byte buffer. -The buffer contents remain unchanged as a sequence of bytes -but the contents viewed as characters do change. +In these cases, the buffer contents remain unchanged as a sequence of +bytes but the contents viewed as characters do change. +If FLAG is `to', this makes the buffer a multibyte buffer by changing +all eight-bit bytes to eight-bit characters. If the multibyte flag was really changed, undo information of the current buffer is cleared. */) (flag) @@ -2256,11 +2423,11 @@ current buffer is cleared. */) p = GAP_END_ADDR; stop = Z; } - if (MULTIBYTE_STR_AS_UNIBYTE_P (p, bytes)) - p += bytes, pos += bytes; - else + if (ASCII_BYTE_P (*p)) + p++, pos++; + else if (CHAR_BYTE8_HEAD_P (*p)) { - c = STRING_CHAR (p, stop - pos); + c = STRING_CHAR_AND_LENGTH (p, bytes); /* Delete all bytes for this 8-bit character but the last one, and change the last one to the charcter code. */ @@ -2275,6 +2442,11 @@ current buffer is cleared. */) zv -= bytes; stop = Z; } + else + { + bytes = BYTES_BY_CHAR_HEAD (*p); + p += bytes, pos += bytes; + } } if (narrowed) Fnarrow_to_region (make_number (begv), make_number (zv)); @@ -2283,13 +2455,14 @@ current buffer is cleared. */) { int pt = PT; int pos, stop; - unsigned char *p; + unsigned char *p, *pend; /* Be sure not to have a multibyte sequence striding over the GAP. - Ex: We change this: "...abc\201 _GAP_ \241def..." - to: "...abc _GAP_ \201\241def..." */ + Ex: We change this: "...abc\302 _GAP_ \241def..." + to: "...abc _GAP_ \302\241def..." */ - if (GPT_BYTE > 1 && GPT_BYTE < Z_BYTE + if (EQ (flag, Qt) + && GPT_BYTE > 1 && GPT_BYTE < Z_BYTE && ! CHAR_HEAD_P (*(GAP_END_ADDR))) { unsigned char *p = GPT_ADDR - 1; @@ -2308,6 +2481,7 @@ current buffer is cleared. */) pos = BEG; stop = GPT; p = BEG_ADDR; + pend = GPT_ADDR; while (1) { int bytes; @@ -2317,16 +2491,23 @@ current buffer is cleared. */) if (pos == Z) break; p = GAP_END_ADDR; + pend = Z_ADDR; stop = Z; } - if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes)) + if (ASCII_BYTE_P (*p)) + p++, pos++; + else if (EQ (flag, Qt) + && ! CHAR_BYTE8_HEAD_P (*p) + && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0) p += bytes, pos += bytes; else { unsigned char tmp[MAX_MULTIBYTE_LENGTH]; + int c; - bytes = CHAR_STRING (*p, tmp); + c = BYTE8_TO_CHAR (*p); + bytes = CHAR_STRING (c, tmp); *p = tmp[0]; TEMP_SET_PT_BOTH (pos + 1, pos + 1); bytes--; @@ -2340,6 +2521,7 @@ current buffer is cleared. */) zv += bytes; if (pos <= pt) pt += bytes; + pend = Z_ADDR; stop = Z; } } @@ -2497,18 +2679,19 @@ static void swap_out_buffer_local_variables (b) struct buffer *b; { - Lisp_Object oalist, alist, sym, tem, buffer; + Lisp_Object oalist, alist, sym, buffer; XSETBUFFER (buffer, b); oalist = b->local_var_alist; for (alist = oalist; CONSP (alist); alist = XCDR (alist)) { - sym = XCAR (XCAR (alist)); - - /* Need not do anything if some other buffer's binding is now encached. */ - tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer; - if (EQ (tem, buffer)) + if (CONSP (XCAR (alist)) + && (sym = XCAR (XCAR (alist)), SYMBOLP (sym)) + /* Need not do anything if some other buffer's binding is + now encached. */ + && EQ (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer, + buffer)) { /* Symbol is set up for this buffer's old local value: swap it out! */ @@ -2545,8 +2728,8 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req) int extend; Lisp_Object **vec_ptr; int *len_ptr; - int *next_ptr; - int *prev_ptr; + EMACS_INT *next_ptr; + EMACS_INT *prev_ptr; int change_req; { Lisp_Object overlay, start, end; @@ -2664,8 +2847,9 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req) return idx; } -/* Find all the overlays in the current buffer that overlap the range BEG-END - or are empty at BEG. +/* Find all the overlays in the current buffer that overlap the range + BEG-END, or are empty at BEG, or are empty at END provided END + denotes the position at the end of the current buffer. Return the number found, and store them in a vector in *VEC_PTR. Store in *LEN_PTR the size allocated for the vector. @@ -2700,6 +2884,7 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr) int next = ZV; int prev = BEGV; int inhibit_storing = 0; + int end_is_Z = end == Z; for (tail = current_buffer->overlays_before; tail; tail = tail->next) { @@ -2717,10 +2902,12 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr) break; } startpos = OVERLAY_POSITION (ostart); - /* Count an interval if it either overlaps the range - or is empty at the start of the range. */ + /* Count an interval if it overlaps the range, is empty at the + start of the range, or is empty at END provided END denotes the + end of the buffer. */ if ((beg < endpos && startpos < end) - || (startpos == endpos && beg == endpos)) + || (startpos == endpos + && (beg == endpos || (end_is_Z && endpos == end)))) { if (idx == len) { @@ -2765,10 +2952,12 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr) break; } endpos = OVERLAY_POSITION (oend); - /* Count an interval if it either overlaps the range - or is empty at the start of the range. */ + /* Count an interval if it overlaps the range, is empty at the + start of the range, or is empty at END provided END denotes the + end of the buffer. */ if ((beg < endpos && startpos < end) - || (startpos == endpos && beg == endpos)) + || (startpos == endpos + && (beg == endpos || (end_is_Z && endpos == end)))) { if (idx == len) { @@ -2847,7 +3036,7 @@ overlay_touches_p (pos) int endpos; XSETMISC (overlay ,tail); - if (!GC_OVERLAYP (overlay)) + if (!OVERLAYP (overlay)) abort (); endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); @@ -2862,7 +3051,7 @@ overlay_touches_p (pos) int startpos; XSETMISC (overlay, tail); - if (!GC_OVERLAYP (overlay)) + if (!OVERLAYP (overlay)) abort (); startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); @@ -3951,7 +4140,7 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0, /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. */ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, - (int *) 0, (int *) 0, 0); + (EMACS_INT *) 0, (EMACS_INT *) 0, 0); /* Make a list of them all. */ result = Flist (noverlays, overlay_vec); @@ -3964,8 +4153,9 @@ DEFUN ("overlays-in", Foverlays_in, Soverlays_in, 2, 2, 0, doc: /* Return a list of the overlays that overlap the region BEG ... END. Overlap means that at least one character is contained within the overlay and also contained within the specified region. -Empty overlays are included in the result if they are located at BEG -or between BEG and END. */) +Empty overlays are included in the result if they are located at BEG, +between BEG and END, or at END provided END denotes the position at the +end of the buffer. */) (beg, end) Lisp_Object beg, end; { @@ -4001,7 +4191,7 @@ the value is (point-max). */) Lisp_Object pos; { int noverlays; - int endpos; + EMACS_INT endpos; Lisp_Object *overlay_vec; int len; int i; @@ -4015,14 +4205,14 @@ the value is (point-max). */) Store the length in len. endpos gets the position where the next overlay starts. */ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, - &endpos, (int *) 0, 1); + &endpos, (EMACS_INT *) 0, 1); /* If any of these overlays ends before endpos, use its ending point instead. */ for (i = 0; i < noverlays; i++) { Lisp_Object oend; - int oendpos; + EMACS_INT oendpos; oend = OVERLAY_END (overlay_vec[i]); oendpos = OVERLAY_POSITION (oend); @@ -4043,7 +4233,7 @@ the value is (point-min). */) Lisp_Object pos; { int noverlays; - int prevpos; + EMACS_INT prevpos; Lisp_Object *overlay_vec; int len; @@ -4061,7 +4251,7 @@ the value is (point-min). */) Store the length in len. prevpos gets the position of the previous change. */ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, - (int *) 0, &prevpos, 1); + (EMACS_INT *) 0, &prevpos, 1); xfree (overlay_vec); return make_number (prevpos); @@ -4184,8 +4374,10 @@ add_overlay_mod_hooklist (functionlist, overlay) if (last_overlay_modification_hooks_used == oldsize) last_overlay_modification_hooks = larger_vector (last_overlay_modification_hooks, oldsize * 2, Qnil); - AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = functionlist; - AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = overlay; + ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used, + functionlist); last_overlay_modification_hooks_used++; + ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used, + overlay); last_overlay_modification_hooks_used++; } /* Run the modification-hooks of overlays that include @@ -4393,32 +4585,21 @@ evaporate_overlays (pos) in the slot with offset OFFSET. */ void -buffer_slot_type_mismatch (sym, type) - Lisp_Object sym; +buffer_slot_type_mismatch (newval, type) + Lisp_Object newval; int type; { - char *type_name; + Lisp_Object predicate; switch (type) { - case Lisp_Int: - type_name = "integers"; - break; - - case Lisp_String: - type_name = "strings"; - break; - - case Lisp_Symbol: - type_name = "symbols"; - break; - - default: - abort (); + case_Lisp_Int: predicate = Qintegerp; break; + case Lisp_String: predicate = Qstringp; break; + case Lisp_Symbol: predicate = Qsymbolp; break; + default: abort (); } - error ("Only %s should be stored in the buffer-local variable %s", - type_name, SDATA (SYMBOL_NAME (sym))); + wrong_type_argument (predicate, newval); } @@ -4923,9 +5104,7 @@ alloc_buffer_text (b, nbytes) shrink it. */ void -enlarge_buffer_text (b, delta) - struct buffer *b; - int delta; +enlarge_buffer_text (struct buffer *b, EMACS_INT delta) { POINTER_TYPE *p; size_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1 @@ -5003,7 +5182,7 @@ init_buffer_once () /* Must do these before making the first buffer! */ /* real setup is done in bindings.el */ - buffer_defaults.mode_line_format = build_string ("%-"); + buffer_defaults.mode_line_format = make_pure_c_string ("%-"); buffer_defaults.header_line_format = Qnil; buffer_defaults.abbrev_mode = Qnil; buffer_defaults.overwrite_mode = Qnil; @@ -5025,6 +5204,7 @@ init_buffer_once () XSETFASTINT (buffer_defaults.tab_width, 8); buffer_defaults.truncate_lines = Qnil; + buffer_defaults.word_wrap = Qnil; buffer_defaults.ctl_arrow = Qt; buffer_defaults.direction_reversed = Qnil; buffer_defaults.cursor_type = Qt; @@ -5097,6 +5277,7 @@ init_buffer_once () #endif XSETFASTINT (buffer_local_flags.tab_width, idx); ++idx; XSETFASTINT (buffer_local_flags.truncate_lines, idx); ++idx; + XSETFASTINT (buffer_local_flags.word_wrap, idx); ++idx; XSETFASTINT (buffer_local_flags.ctl_arrow, idx); ++idx; XSETFASTINT (buffer_local_flags.fill_column, idx); ++idx; XSETFASTINT (buffer_local_flags.left_margin, idx); ++idx; @@ -5141,28 +5322,27 @@ init_buffer_once () current_buffer = 0; all_buffers = 0; - QSFundamental = build_string ("Fundamental"); + QSFundamental = make_pure_c_string ("Fundamental"); - Qfundamental_mode = intern ("fundamental-mode"); + Qfundamental_mode = intern_c_string ("fundamental-mode"); buffer_defaults.major_mode = Qfundamental_mode; - Qmode_class = intern ("mode-class"); + Qmode_class = intern_c_string ("mode-class"); - Qprotected_field = intern ("protected-field"); + Qprotected_field = intern_c_string ("protected-field"); - Qpermanent_local = intern ("permanent-local"); + Qpermanent_local = intern_c_string ("permanent-local"); - Qkill_buffer_hook = intern ("kill-buffer-hook"); + Qkill_buffer_hook = intern_c_string ("kill-buffer-hook"); Fput (Qkill_buffer_hook, Qpermanent_local, Qt); - Qucs_set_table_for_input = intern ("ucs-set-table-for-input"); - - Vprin1_to_string_buffer = Fget_buffer_create (build_string (" prin1")); + Qucs_set_table_for_input = intern_c_string ("ucs-set-table-for-input"); /* super-magic invisible buffer */ + Vprin1_to_string_buffer = Fget_buffer_create (make_pure_c_string (" prin1")); Vbuffer_alist = Qnil; - Fset_buffer (Fget_buffer_create (build_string ("*scratch*"))); + Fset_buffer (Fget_buffer_create (make_pure_c_string ("*scratch*"))); inhibit_modification_hooks = 0; } @@ -5196,18 +5376,18 @@ init_buffer () 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. */ len = strlen (pwd); if (!(IS_DIRECTORY_SEP (pwd[len - 1]))) { /* Grow buffer to add directory separator and '\0'. */ - pwd = (char *) xrealloc (pwd, len + 2); + pwd = (char *) realloc (pwd, len + 2); + if (!pwd) + fatal ("`get_current_dir_name' failed: %s\n", strerror (errno)); pwd[len] = DIRECTORY_SEP; pwd[len + 1] = '\0'; } -#endif /* not VMS */ current_buffer->directory = make_unibyte_string (pwd, strlen (pwd)); if (! NILP (buffer_defaults.enable_multibyte_characters)) @@ -5291,42 +5471,45 @@ syms_of_buffer () staticpro (&Vbuffer_alist); staticpro (&Qprotected_field); staticpro (&Qpermanent_local); + Qpermanent_local_hook = intern_c_string ("permanent-local-hook"); + staticpro (&Qpermanent_local_hook); staticpro (&Qkill_buffer_hook); - Qoverlayp = intern ("overlayp"); + Qoverlayp = intern_c_string ("overlayp"); staticpro (&Qoverlayp); - Qevaporate = intern ("evaporate"); + Qevaporate = intern_c_string ("evaporate"); staticpro (&Qevaporate); - Qmodification_hooks = intern ("modification-hooks"); + Qmodification_hooks = intern_c_string ("modification-hooks"); staticpro (&Qmodification_hooks); - Qinsert_in_front_hooks = intern ("insert-in-front-hooks"); + Qinsert_in_front_hooks = intern_c_string ("insert-in-front-hooks"); staticpro (&Qinsert_in_front_hooks); - Qinsert_behind_hooks = intern ("insert-behind-hooks"); + Qinsert_behind_hooks = intern_c_string ("insert-behind-hooks"); staticpro (&Qinsert_behind_hooks); - Qget_file_buffer = intern ("get-file-buffer"); + Qget_file_buffer = intern_c_string ("get-file-buffer"); staticpro (&Qget_file_buffer); - Qpriority = intern ("priority"); + Qpriority = intern_c_string ("priority"); staticpro (&Qpriority); - Qwindow = intern ("window"); + Qwindow = intern_c_string ("window"); staticpro (&Qwindow); - Qbefore_string = intern ("before-string"); + Qbefore_string = intern_c_string ("before-string"); staticpro (&Qbefore_string); - Qafter_string = intern ("after-string"); + Qafter_string = intern_c_string ("after-string"); staticpro (&Qafter_string); - Qfirst_change_hook = intern ("first-change-hook"); + Qfirst_change_hook = intern_c_string ("first-change-hook"); staticpro (&Qfirst_change_hook); - Qbefore_change_functions = intern ("before-change-functions"); + Qbefore_change_functions = intern_c_string ("before-change-functions"); staticpro (&Qbefore_change_functions); - Qafter_change_functions = intern ("after-change-functions"); + Qafter_change_functions = intern_c_string ("after-change-functions"); staticpro (&Qafter_change_functions); + /* The next one is initialized in init_buffer_once. */ staticpro (&Qucs_set_table_for_input); - Qkill_buffer_query_functions = intern ("kill-buffer-query-functions"); + Qkill_buffer_query_functions = intern_c_string ("kill-buffer-query-functions"); staticpro (&Qkill_buffer_query_functions); Fput (Qprotected_field, Qerror_conditions, - Fcons (Qprotected_field, Fcons (Qerror, Qnil))); + pure_cons (Qprotected_field, pure_cons (Qerror, Qnil))); Fput (Qprotected_field, Qerror_message, - build_string ("Attempt to modify a protected field")); + make_pure_c_string ("Attempt to modify a protected field")); /* All these use DEFVAR_LISP_NOPRO because the slots in buffer_defaults will all be marked via Vbuffer_defaults. */ @@ -5542,23 +5725,27 @@ A string is printed verbatim in the mode line except for %-constructs: 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'. -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 -it finishes setting up the buffer. Thus, the mode and -its hooks should not expect certain variables such as -`buffer-read-only' and `buffer-file-coding-system' to be set up. */); + doc: /* *Value of `major-mode' for new buffers. */); DEFVAR_PER_BUFFER ("major-mode", ¤t_buffer->major_mode, make_number (Lisp_Symbol), - doc: /* Symbol for current buffer's major mode. */); + doc: /* Symbol for current buffer's major mode. +The default value (normally `fundamental-mode') affects new buffers. +A value of nil means to use the 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 it finishes setting up +the buffer. Thus, the mode and its hooks should not expect certain +variables such as `buffer-read-only' and `buffer-file-coding-system' +to be set up. */); DEFVAR_PER_BUFFER ("mode-name", ¤t_buffer->mode_name, Qnil, - doc: /* Pretty name of current buffer's major mode (a string). */); + doc: /* Pretty name of current buffer's major mode. +Usually a string, but can use any of the constructs for `mode-line-format', +which see. +Format with `format-mode-line' to produce a string value. */); DEFVAR_PER_BUFFER ("local-abbrev-table", ¤t_buffer->abbrev_table, Qnil, doc: /* Local (mode-specific) abbrev table of current buffer. */); @@ -5571,17 +5758,17 @@ its hooks should not expect certain variables such as doc: /* *Non-nil if searches and matches should ignore case. */); DEFVAR_PER_BUFFER ("fill-column", ¤t_buffer->fill_column, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* *Column beyond which automatic line-wrapping should happen. Interactively, you can set the buffer local value using \\[set-fill-column]. */); DEFVAR_PER_BUFFER ("left-margin", ¤t_buffer->left_margin, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* *Column for the default `indent-line-function' to indent to. Linefeed indents to this column in Fundamental mode. */); DEFVAR_PER_BUFFER ("tab-width", ¤t_buffer->tab_width, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* *Distance between tab stops (for display of tab characters), in columns. */); DEFVAR_PER_BUFFER ("ctl-arrow", ¤t_buffer->ctl_arrow, Qnil, @@ -5602,7 +5789,7 @@ use the function `set-buffer-multibyte' to change a buffer's representation. Changing its default value with `setq-default' is supported. See also variable `default-enable-multibyte-characters' and Info node `(elisp)Text Representations'. */); - XSYMBOL (intern ("enable-multibyte-characters"))->constant = 1; + XSYMBOL (intern_c_string ("enable-multibyte-characters"))->constant = 1; DEFVAR_PER_BUFFER ("buffer-file-coding-system", ¤t_buffer->buffer_file_coding_system, Qnil, @@ -5634,6 +5821,18 @@ Note that this is overridden by the variable `truncate-partial-width-windows' if that variable is non-nil and this buffer is not full-frame width. */); + DEFVAR_PER_BUFFER ("word-wrap", ¤t_buffer->word_wrap, Qnil, + doc: /* *Non-nil means to use word-wrapping for continuation lines. +When word-wrapping is on, continuation lines are wrapped at the space +or tab character nearest to the right window edge. +If nil, continuation lines are wrapped at the right screen edge. + +This variable has no effect if long lines are truncated (see +`truncate-lines' and `truncate-partial-width-windows'). If you use +word-wrapping, you might want to reduce the value of +`truncate-partial-width-windows', since wrapping can make text readable +in narrower windows. */); + #ifdef DOS_NT DEFVAR_PER_BUFFER ("buffer-file-type", ¤t_buffer->buffer_file_type, Qnil, @@ -5680,9 +5879,14 @@ If it is nil, that means don't auto-save this buffer. */); Backing up is done before the first time the file is saved. */); DEFVAR_PER_BUFFER ("buffer-saved-size", ¤t_buffer->save_length, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* Length of current buffer when last read in, saved or auto-saved. -0 initially. */); +0 initially. +-1 means auto-saving turned off until next real save. + +If you set this to -2, that means don't turn off auto-saving in this buffer +if its text size shrinks. If you use `buffer-swap-text' on a buffer, +you probably should set this to -2 in that buffer. */); DEFVAR_PER_BUFFER ("selective-display", ¤t_buffer->selective_display, Qnil, @@ -5695,7 +5899,7 @@ in a file, save the ^M as a newline. */); #ifndef old DEFVAR_PER_BUFFER ("selective-display-ellipses", - ¤t_buffer->selective_display_ellipses, + ¤t_buffer->selective_display_ellipses, Qnil, doc: /* Non-nil means display ... on previous line when a line is invisible. */); #endif @@ -5860,10 +6064,10 @@ If you move point off the bottom, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, means scroll to center point. A fraction means scroll to put point that fraction of the window's height from the bottom of the window. -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 -scrolls by a full window height. Meaningful values are +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 scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); DEFVAR_PER_BUFFER ("scroll-down-aggressively", @@ -5873,10 +6077,10 @@ If you move point off the top, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, means scroll to center point. A fraction means scroll to put point that fraction of the window's height from the top of the window. -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 -scrolls by a full window height. Meaningful values are +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 scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol, @@ -5893,8 +6097,8 @@ No information is given about the length of the text after the change. Buffer changes made while executing the `before-change-functions' don't call any before-change or after-change functions. That's because these variables are temporarily set to nil. -As a result, a hook function cannot straightforwardly alter the value of -these variables. See the Emacs Lisp manual for a way of +As a result, a hook function cannot straightforwardly alter the +value of these variables. See the Emacs Lisp manual for a way of accomplishing an equivalent result by using other variables. If an unhandled error happens in running these functions, @@ -5914,8 +6118,8 @@ and the post-change beginning and end are at the same place.) Buffer changes made while executing the `after-change-functions' don't call any before-change or after-change functions. That's because these variables are temporarily set to nil. -As a result, a hook function cannot straightforwardly alter the value of -these variables. See the Emacs Lisp manual for a way of +As a result, a hook function cannot straightforwardly alter the +value of these variables. See the Emacs Lisp manual for a way of accomplishing an equivalent result by using other variables. If an unhandled error happens in running these functions, @@ -6039,18 +6243,11 @@ to the value obtained by calling `current-time'. If the buffer has never been shown in a window, the value is nil. */); DEFVAR_LISP ("transient-mark-mode", &Vtransient_mark_mode, - doc: /* *Non-nil means deactivate the mark when the buffer contents change. -Non-nil also enables highlighting of the region whenever the mark is active. -The variable `highlight-nonselected-windows' controls whether to highlight -all windows or just the selected window. - -If the value is `lambda', that enables Transient Mark mode temporarily -until the next buffer modification. If a command sets the value to `only', -that enables Transient Mark mode for the following command only. -During that following command, the value of `transient-mark-mode' -is `identity'. If it is still `identity' at the end of that command, -it changes to nil. */); + doc: /* */); Vtransient_mark_mode = Qnil; + /* The docstring is in simple.el. If we put it here, it would be + overwritten when transient-mark-mode is defined using + define-minor-mode. */ DEFVAR_LISP ("inhibit-read-only", &Vinhibit_read_only, doc: /* *Non-nil means disregard read-only status of buffers or characters. @@ -6074,13 +6271,15 @@ Values are interpreted as follows: (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. */); +When the buffer is displayed in a non-selected window, the +cursor's appearance is instead controlled by the variable +`cursor-in-non-selected-windows'. */); DEFVAR_PER_BUFFER ("line-spacing", ¤t_buffer->extra_line_spacing, Qnil, doc: /* Additional space to put between lines when displaying a buffer. -The space is measured in pixels, and put below lines on window systems. +The space is measured in pixels, and put below lines on graphic displays, +see `display-graphic-p'. If value is a floating point number, it specifies the spacing relative to the default frame line height. A value of nil means add no extra space. */); @@ -6099,7 +6298,7 @@ If any of them returns nil, the buffer is not killed. */); 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"); + Qchange_major_mode_hook = intern_c_string ("change-major-mode-hook"); staticpro (&Qchange_major_mode_hook); defsubr (&Sbuffer_live_p); @@ -6125,12 +6324,12 @@ The function `kill-all-local-variables' runs this before doing anything else. * defsubr (&Skill_buffer); defsubr (&Sset_buffer_major_mode); defsubr (&Sswitch_to_buffer); - defsubr (&Spop_to_buffer); defsubr (&Scurrent_buffer); defsubr (&Sset_buffer); defsubr (&Sbarf_if_buffer_read_only); defsubr (&Sbury_buffer); defsubr (&Serase_buffer); + defsubr (&Sbuffer_swap_text); defsubr (&Sset_buffer_multibyte); defsubr (&Skill_all_local_variables); @@ -6161,7 +6360,7 @@ keys_of_buffer () /* This must not be in syms_of_buffer, because Qdisabled is not initialized when that function gets called. */ - Fput (intern ("erase-buffer"), Qdisabled, Qt); + Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt); } /* arch-tag: e48569bf-69a9-4b65-a23b-8e68769436e1