X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/c752cfa916879f7415990855b52862dd585242ec..cfbf790d80eaa399afceecd9a6c3e2e76bca59b0:/src/buffer.c?ds=inline
diff --git a/src/buffer.c b/src/buffer.c
index 187277d663..aa3fcf8c23 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,6 +1,7 @@
/* Buffer manipulation primitives for GNU Emacs.
-Copyright (C) 1985-1989, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
@@ -26,7 +27,6 @@ along with GNU Emacs. If not, see . */
#include
#include
#include
-#include
#include
#include
@@ -44,7 +44,7 @@ along with GNU Emacs. If not, see . */
#include "keymap.h"
#include "frame.h"
-struct buffer *current_buffer; /* the current buffer */
+struct buffer *current_buffer; /* The current buffer. */
/* First buffer in chain of all buffers (in reverse order of creation).
Threaded through ->header.next.buffer. */
@@ -74,12 +74,12 @@ struct buffer alignas (GCALIGNMENT) buffer_defaults;
and the corresponding slot in buffer_defaults is not used.
If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
- zero, that is a bug */
+ zero, that is a bug. */
struct buffer buffer_local_flags;
/* This structure holds the names of symbols whose values may be
- buffer-local. It is indexed and accessed in the same way as the above. */
+ buffer-local. It is indexed and accessed in the same way as the above. */
struct buffer alignas (GCALIGNMENT) buffer_local_symbols;
@@ -108,7 +108,7 @@ static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay,
static void swap_out_buffer_local_variables (struct buffer *b);
static void reset_buffer_local_variables (struct buffer *, bool);
-/* Alist of all buffer names vs the buffers. */
+/* Alist of all buffer names vs the buffers. */
/* This used to be a variable, but is no longer,
to prevent lossage due to user rplac'ing this alist or its elements. */
Lisp_Object Vbuffer_alist;
@@ -127,7 +127,7 @@ static Lisp_Object Qpermanent_local_hook;
static Lisp_Object Qprotected_field;
-static Lisp_Object QSFundamental; /* A string "Fundamental" */
+static Lisp_Object QSFundamental; /* A string "Fundamental". */
static Lisp_Object Qkill_buffer_hook;
static Lisp_Object Qbuffer_list_update_hook;
@@ -151,230 +151,227 @@ static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t);
static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool);
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
bset_abbrev_mode (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (abbrev_mode) = val;
}
-static inline void
+static void
bset_abbrev_table (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (abbrev_table) = val;
}
-static inline void
+static void
bset_auto_fill_function (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (auto_fill_function) = val;
}
-static inline void
+static void
bset_auto_save_file_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (auto_save_file_format) = val;
}
-static inline void
+static void
bset_auto_save_file_name (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (auto_save_file_name) = val;
}
-static inline void
+static void
bset_backed_up (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (backed_up) = val;
}
-static inline void
+static void
bset_begv_marker (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (begv_marker) = val;
}
-static inline void
+static void
bset_bidi_display_reordering (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (bidi_display_reordering) = val;
}
-static inline void
+static void
bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (buffer_file_coding_system) = val;
}
-static inline void
+static void
bset_cache_long_line_scans (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (cache_long_line_scans) = val;
}
-static inline void
+static void
bset_case_fold_search (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (case_fold_search) = val;
}
-static inline void
+static void
bset_ctl_arrow (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (ctl_arrow) = val;
}
-static inline void
+static void
bset_cursor_in_non_selected_windows (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (cursor_in_non_selected_windows) = val;
}
-static inline void
+static void
bset_cursor_type (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (cursor_type) = val;
}
-static inline void
+static void
bset_display_table (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (display_table) = val;
}
-static inline void
+static void
bset_extra_line_spacing (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (extra_line_spacing) = val;
}
-static inline void
+static void
bset_file_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (file_format) = val;
}
-static inline void
+static void
bset_file_truename (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (file_truename) = val;
}
-static inline void
+static void
bset_fringe_cursor_alist (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (fringe_cursor_alist) = val;
}
-static inline void
+static void
bset_fringe_indicator_alist (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (fringe_indicator_alist) = val;
}
-static inline void
+static void
bset_fringes_outside_margins (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (fringes_outside_margins) = val;
}
-static inline void
+static void
bset_header_line_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (header_line_format) = val;
}
-static inline void
+static void
bset_indicate_buffer_boundaries (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (indicate_buffer_boundaries) = val;
}
-static inline void
+static void
bset_indicate_empty_lines (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (indicate_empty_lines) = val;
}
-static inline void
+static void
bset_invisibility_spec (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (invisibility_spec) = val;
}
-static inline void
+static void
bset_left_fringe_width (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (left_fringe_width) = val;
}
-static inline void
+static void
bset_major_mode (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (major_mode) = val;
}
-static inline void
+static void
bset_mark (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (mark) = val;
}
-static inline void
+static void
bset_minor_modes (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (minor_modes) = val;
}
-static inline void
+static void
bset_mode_line_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (mode_line_format) = val;
}
-static inline void
+static void
bset_mode_name (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (mode_name) = val;
}
-static inline void
+static void
bset_name (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (name) = val;
}
-static inline void
+static void
bset_overwrite_mode (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (overwrite_mode) = val;
}
-static inline void
+static void
bset_pt_marker (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (pt_marker) = val;
}
-static inline void
+static void
bset_right_fringe_width (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (right_fringe_width) = val;
}
-static inline void
+static void
bset_save_length (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (save_length) = val;
}
-static inline void
+static void
bset_scroll_bar_width (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_bar_width) = val;
}
-static inline void
+static void
bset_scroll_down_aggressively (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_down_aggressively) = val;
}
-static inline void
+static void
bset_scroll_up_aggressively (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_up_aggressively) = val;
}
-static inline void
+static void
bset_selective_display (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (selective_display) = val;
}
-static inline void
+static void
bset_selective_display_ellipses (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (selective_display_ellipses) = val;
}
-static inline void
+static void
bset_vertical_scroll_bar_type (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (vertical_scroll_bar_type) = val;
}
-static inline void
+static void
bset_word_wrap (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (word_wrap) = val;
}
-static inline void
+static void
bset_zv_marker (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (zv_marker) = val;
}
-/* For debugging; temporary. See set_buffer_internal. */
-/* Lisp_Object Qlisp_mode, Vcheck_symbol; */
-
void
nsberror (Lisp_Object spec)
{
@@ -388,7 +385,7 @@ DEFUN ("buffer-live-p", Fbuffer_live_p, Sbuffer_live_p, 1, 1, 0,
Value is nil if OBJECT is not a buffer or if it has been killed. */)
(Lisp_Object object)
{
- return ((BUFFERP (object) && ! NILP (BVAR (XBUFFER (object), name)))
+ return ((BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object)))
? Qt : Qnil);
}
@@ -407,7 +404,6 @@ followed by the rest of the buffers. */)
Lisp_Object framelist, prevlist, tail;
Lisp_Object args[3];
- CHECK_FRAME (frame);
framelist = Fcopy_sequence (XFRAME (frame)->buffer_list);
prevlist = Fnreverse (Fcopy_sequence
(XFRAME (frame)->buried_buffer_list));
@@ -549,13 +545,15 @@ even if it is dead. The return value is never nil. */)
b->base_buffer = NULL;
/* No one shares the text with us now. */
b->indirections = 0;
+ /* No one shows us now. */
+ b->window_count = 0;
BUF_GAP_SIZE (b) = 20;
- BLOCK_INPUT;
+ block_input ();
/* We allocate extra 1-byte at the tail and keep it always '\0' for
anchoring a search. */
alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1);
- UNBLOCK_INPUT;
+ unblock_input ();
if (! BUF_BEG_ADDR (b))
buffer_memory_full (BUF_GAP_SIZE (b) + 1);
@@ -575,6 +573,7 @@ even if it is dead. The return value is never nil. */)
BUF_CHARS_MODIFF (b) = 1;
BUF_OVERLAY_MODIFF (b) = 1;
BUF_SAVE_MODIFF (b) = 1;
+ BUF_COMPACT (b) = 1;
set_buffer_intervals (b, NULL);
BUF_UNCHANGED_MODIFIED (b) = 1;
BUF_OVERLAY_UNCHANGED_MODIFIED (b) = 1;
@@ -652,13 +651,13 @@ copy_overlays (struct buffer *b, struct Lisp_Overlay *list)
/* Set an appropriate overlay of B. */
-static inline void
+static void
set_buffer_overlays_before (struct buffer *b, struct Lisp_Overlay *o)
{
b->overlays_before = o;
}
-static inline void
+static void
set_buffer_overlays_after (struct buffer *b, struct Lisp_Overlay *o)
{
b->overlays_after = o;
@@ -776,7 +775,7 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
base_buffer = Fget_buffer (base_buffer);
if (NILP (base_buffer))
error ("No such buffer: `%s'", SDATA (tem));
- if (NILP (BVAR (XBUFFER (base_buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (base_buffer)))
error ("Base buffer has been killed");
if (SCHARS (name) == 0)
@@ -796,6 +795,8 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
b->indirections = -1;
/* Notify base buffer that we share the text now. */
b->base_buffer->indirections++;
+ /* Always -1 for an indirect buffer. */
+ b->window_count = -1;
b->pt = b->base_buffer->pt;
b->begv = b->base_buffer->begv;
@@ -898,6 +899,8 @@ delete_all_overlays (struct buffer *b)
{
struct Lisp_Overlay *ov, *next;
+ /* FIXME: Since each drop_overlay will scan BUF_MARKERS to unlink its
+ markers, we have an unneeded O(N^2) behavior here. */
for (ov = b->overlays_before; ov; ov = next)
{
drop_overlay (b, ov);
@@ -1336,15 +1339,19 @@ DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p, Sset_buffer_modified_p,
A non-nil FLAG means mark the buffer modified. */)
(Lisp_Object flag)
{
- Lisp_Object fn, buffer, window;
+ Lisp_Object fn;
#ifdef CLASH_DETECTION
/* If buffer becoming modified, lock the file.
If buffer becoming unmodified, unlock the file. */
- fn = BVAR (current_buffer, file_truename);
+ struct buffer *b = current_buffer->base_buffer
+ ? current_buffer->base_buffer
+ : current_buffer;
+
+ fn = BVAR (b, file_truename);
/* Test buffer-file-name so that binding it to nil is effective. */
- if (!NILP (fn) && ! NILP (BVAR (current_buffer, filename)))
+ if (!NILP (fn) && ! NILP (BVAR (b, filename)))
{
bool already = SAVE_MODIFF < MODIFF;
if (!already && !NILP (flag))
@@ -1385,9 +1392,7 @@ A non-nil FLAG means mark the buffer modified. */)
Ideally, I think there should be another mechanism for fontifying
buffers without "modifying" buffers, or redisplay should be
smarter about updating the `*' in mode lines. --gerd */
- XSETBUFFER (buffer, current_buffer);
- window = Fget_buffer_window (buffer, Qt);
- if (WINDOWP (window))
+ if (buffer_window_count (current_buffer))
{
++update_mode_lines;
current_buffer->prevent_redisplay_optimizations_p = 1;
@@ -1525,6 +1530,16 @@ This does not change the name of the visited file (if any). */)
return BVAR (current_buffer, name);
}
+/* True if B can be used as 'other-than-BUFFER' buffer. */
+
+static bool
+candidate_buffer (Lisp_Object b, Lisp_Object buffer)
+{
+ return (BUFFERP (b) && !EQ (b, buffer)
+ && BUFFER_LIVE_P (XBUFFER (b))
+ && !BUFFER_HIDDEN_P (XBUFFER (b)));
+}
+
DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 3, 0,
doc: /* Return most recently selected buffer other than BUFFER.
Buffers not visible in windows are preferred to visible buffers, unless
@@ -1538,23 +1553,15 @@ list first, followed by the list of all buffers. If no other buffer
exists, return the buffer `*scratch*' (creating it if necessary). */)
(register Lisp_Object buffer, Lisp_Object visible_ok, Lisp_Object frame)
{
- Lisp_Object tail, buf, pred;
- Lisp_Object notsogood = Qnil;
+ struct frame *f = decode_any_frame (frame);
+ Lisp_Object tail = f->buffer_list, pred = f->buffer_predicate;
+ Lisp_Object buf, notsogood = Qnil;
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_FRAME (frame);
-
- pred = frame_buffer_predicate (frame);
/* Consider buffers that have been seen in the frame first. */
- tail = XFRAME (frame)->buffer_list;
for (; CONSP (tail); tail = XCDR (tail))
{
buf = XCAR (tail);
- if (BUFFERP (buf) && !EQ (buf, buffer)
- && !NILP (BVAR (XBUFFER (buf), name))
- && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')
+ if (candidate_buffer (buf, buffer)
/* If the frame has a buffer_predicate, disregard buffers that
don't fit the predicate. */
&& (NILP (pred) || !NILP (call1 (pred, buf))))
@@ -1572,9 +1579,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */)
for (; CONSP (tail); tail = XCDR (tail))
{
buf = Fcdr (XCAR (tail));
- if (BUFFERP (buf) && !EQ (buf, buffer)
- && !NILP (BVAR (XBUFFER (buf), name))
- && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')
+ if (candidate_buffer (buf, buffer)
/* If the frame has a buffer_predicate, disregard buffers that
don't fit the predicate. */
&& (NILP (pred) || !NILP (call1 (pred, buf))))
@@ -1610,13 +1615,10 @@ other_buffer_safely (Lisp_Object buffer)
{
Lisp_Object tail, buf;
- tail = Vbuffer_alist;
- for (; CONSP (tail); tail = XCDR (tail))
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
{
buf = Fcdr (XCAR (tail));
- if (BUFFERP (buf) && !EQ (buf, buffer)
- && !NILP (BVAR (XBUFFER (buf), name))
- && (SREF (BVAR (XBUFFER (buf), name), 0) != ' '))
+ if (candidate_buffer (buf, buffer))
return buf;
}
@@ -1658,20 +1660,13 @@ No argument or nil as argument means do this for the current buffer. */)
void
compact_buffer (struct buffer *buffer)
{
- /* Verify indirection counters. */
- if (buffer->base_buffer)
- {
- eassert (buffer->indirections == -1);
- eassert (buffer->base_buffer->indirections > 0);
- }
- else
- eassert (buffer->indirections >= 0);
+ BUFFER_CHECK_INDIRECTION (buffer);
/* Skip dead buffers, indirect buffers and buffers
which aren't changed since last compaction. */
- if (!NILP (buffer->INTERNAL_FIELD (name))
+ if (BUFFER_LIVE_P (buffer)
&& (buffer->base_buffer == NULL)
- && (buffer->text->compact != buffer->text->modiff))
+ && (BUF_COMPACT (buffer) != BUF_MODIFF (buffer)))
{
/* If a buffer's undo list is Qt, that means that undo is
turned off in that buffer. Calling truncate_undo_list on
@@ -1684,19 +1679,15 @@ compact_buffer (struct buffer *buffer)
if (!buffer->text->inhibit_shrinking)
{
/* If a buffer's gap size is more than 10% of the buffer
- size, or larger than 2000 bytes, then shrink it
- accordingly. Keep a minimum size of 20 bytes. */
- int size = min (2000, max (20, (buffer->text->z_byte / 10)));
-
- if (buffer->text->gap_size > size)
- {
- struct buffer *save_current = current_buffer;
- current_buffer = buffer;
- make_gap (-(buffer->text->gap_size - size));
- current_buffer = save_current;
- }
+ size, or larger than GAP_BYTES_DFL bytes, then shrink it
+ accordingly. Keep a minimum size of GAP_BYTES_MIN bytes. */
+ ptrdiff_t size = clip_to_bounds (GAP_BYTES_MIN,
+ BUF_Z_BYTE (buffer) / 10,
+ GAP_BYTES_DFL);
+ if (BUF_GAP_SIZE (buffer) > size)
+ make_gap_1 (buffer, -(BUF_GAP_SIZE (buffer) - size));
}
- buffer->text->compact = buffer->text->modiff;
+ BUF_COMPACT (buffer) = BUF_MODIFF (buffer);
}
}
@@ -1734,7 +1725,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
b = XBUFFER (buffer);
/* Avoid trouble for buffer already dead. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qnil;
/* Query if the buffer is still modified. */
@@ -1770,7 +1761,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
}
/* If the hooks have killed the buffer, exit now. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
/* We have no more questions to ask. Verify that it is valid
@@ -1802,7 +1793,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
UNGCPRO;
/* Exit if we now have killed the base buffer (Bug#11665). */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
}
@@ -1813,7 +1804,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
replace_buffer_in_windows (buffer);
/* Exit if replacing the buffer in windows has killed our buffer. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
/* Make this buffer not be current. Exit if it is the sole visible
@@ -1846,7 +1837,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Killing buffer processes may run sentinels which may have killed
our buffer. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
/* These may run Lisp code and into infinite loops (if someone
@@ -1878,7 +1869,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
}
/* Deleting an auto-save file could have killed our buffer. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
if (b->base_buffer)
@@ -1886,12 +1877,16 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Unchain all markers that belong to this indirect buffer.
Don't unchain the markers that belong to the base buffer
or its other indirect buffers. */
- for (m = BUF_MARKERS (b); m; )
+ struct Lisp_Marker **mp = &BUF_MARKERS (b);
+ while ((m = *mp))
{
- struct Lisp_Marker *next = m->next;
if (m->buffer == b)
- unchain_marker (m);
- m = next;
+ {
+ m->buffer = NULL;
+ *mp = m->next;
+ }
+ else
+ mp = &m->next;
}
}
else
@@ -1908,8 +1903,12 @@ cleaning up all windows currently displaying the buffer to be killed. */)
BUF_MARKERS (b) = NULL;
set_buffer_intervals (b, NULL);
- /* Perhaps we should explicitly free the interval tree here... */
+ /* Perhaps we should explicitly free the interval tree here... */
}
+ /* Since we've unlinked the markers, the overlays can't be here any more
+ either. */
+ b->overlays_before = NULL;
+ b->overlays_after = NULL;
/* Reset the local variables, so that this buffer's local values
won't be protected from GC. They would be protected
@@ -1920,17 +1919,23 @@ cleaning up all windows currently displaying the buffer to be killed. */)
bset_name (b, Qnil);
- BLOCK_INPUT;
+ block_input ();
if (b->base_buffer)
{
/* Notify our base buffer that we don't share the text anymore. */
eassert (b->indirections == -1);
b->base_buffer->indirections--;
eassert (b->base_buffer->indirections >= 0);
+ /* Make sure that we wasn't confused. */
+ eassert (b->window_count == -1);
}
else
- /* No one shares our buffer text, can free it. */
- free_buffer_text (b);
+ {
+ /* Make sure that no one shows us. */
+ eassert (b->window_count == 0);
+ /* No one shares our buffer text, can free it. */
+ free_buffer_text (b);
+ }
if (b->newline_cache)
{
@@ -1943,7 +1948,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
b->width_run_cache = 0;
}
bset_width_table (b, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
bset_undo_list (b, Qnil);
/* Run buffer-list-update-hook. */
@@ -2037,7 +2042,7 @@ DEFUN ("bury-buffer-internal", Fbury_buffer_internal, Sbury_buffer_internal,
DEFUN ("set-buffer-major-mode", Fset_buffer_major_mode, Sset_buffer_major_mode, 1, 1, 0,
doc: /* Set an appropriate major mode for BUFFER.
For the *scratch* buffer, use `initial-major-mode', otherwise choose a mode
-according to `default-major-mode'.
+according to the default value of `major-mode'.
Use this function before selecting the buffer, since it may need to inspect
the current buffer's major mode. */)
(Lisp_Object buffer)
@@ -2047,7 +2052,7 @@ the current buffer's major mode. */)
CHECK_BUFFER (buffer);
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
error ("Attempt to set major mode for a dead buffer");
if (strcmp (SSDATA (BVAR (XBUFFER (buffer), name)), "*scratch*") == 0)
@@ -2102,6 +2107,8 @@ set_buffer_internal_1 (register struct buffer *b)
if (current_buffer == b)
return;
+ BUFFER_CHECK_INDIRECTION (b);
+
old_buf = current_buffer;
current_buffer = b;
last_known_column_point = -1; /* invalidate indentation cache */
@@ -2173,7 +2180,7 @@ set_buffer_temp (struct buffer *b)
DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
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
+also `with-current-buffer' 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. */)
@@ -2183,7 +2190,7 @@ ends when the current command terminates. Use `switch-to-buffer' or
buffer = Fget_buffer (buffer_or_name);
if (NILP (buffer))
nsberror (buffer_or_name);
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
error ("Selecting deleted buffer");
set_buffer_internal (XBUFFER (buffer));
return buffer;
@@ -2194,7 +2201,7 @@ ends when the current command terminates. Use `switch-to-buffer' or
Lisp_Object
set_buffer_if_live (Lisp_Object buffer)
{
- if (! NILP (BVAR (XBUFFER (buffer), name)))
+ if (BUFFER_LIVE_P (XBUFFER (buffer)))
set_buffer_internal (XBUFFER (buffer));
return Qnil;
}
@@ -2289,7 +2296,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
CHECK_BUFFER (buffer);
other_buffer = XBUFFER (buffer);
- if (NILP (BVAR (other_buffer, name)))
+ if (!BUFFER_LIVE_P (other_buffer))
error ("Cannot swap a dead buffer's text");
/* Actually, it probably works just fine.
@@ -2461,7 +2468,7 @@ current buffer is cleared. */)
begv = BEGV, zv = ZV;
if (narrowed)
- Fwiden ();
+ error ("Changing multibyteness in a narrowed buffer");
if (NILP (flag))
{
@@ -2677,15 +2684,16 @@ current buffer is cleared. */)
UNGCPRO;
- /* Changing the multibyteness of a buffer means that all windows
- showing that buffer must be updated thoroughly. */
current_buffer->prevent_redisplay_optimizations_p = 1;
- ++windows_or_buffers_changed;
+
+ /* If buffer is shown in a window, let redisplay consider other windows. */
+ if (buffer_window_count (current_buffer))
+ ++windows_or_buffers_changed;
/* Copy this buffer's new multibyte status
into all of its indirect buffers. */
FOR_EACH_BUFFER (other)
- if (other->base_buffer == current_buffer && !NILP (BVAR (other, name)))
+ if (other->base_buffer == current_buffer && BUFFER_LIVE_P (other))
{
BVAR (other, enable_multibyte_characters)
= BVAR (current_buffer, enable_multibyte_characters);
@@ -3131,8 +3139,8 @@ compare_overlays (const void *v1, const void *v2)
between "equal" overlays. The result can still change between
invocations of Emacs, but it won't change in the middle of
`find_field' (bug#6830). */
- if (XHASH (s1->overlay) != XHASH (s2->overlay))
- return XHASH (s1->overlay) < XHASH (s2->overlay) ? -1 : 1;
+ if (!EQ (s1->overlay, s2->overlay))
+ return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1;
return 0;
}
@@ -3143,7 +3151,10 @@ ptrdiff_t
sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
{
ptrdiff_t i, j;
- struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec);
+ USE_SAFE_ALLOCA;
+ struct sortvec *sortvec;
+
+ SAFE_NALLOCA (sortvec, 1, noverlays);
/* Put the valid and relevant overlays into sortvec. */
@@ -3189,6 +3200,8 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
for (i = 0; i < noverlays; i++)
overlay_vec[i] = sortvec[i].overlay;
+
+ SAFE_FREE ();
return (noverlays);
}
@@ -3686,7 +3699,6 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end)
beforep->next = current_buffer->overlays_before;
set_buffer_overlays_before (current_buffer, before_list);
}
- recenter_overlay_lists (current_buffer, current_buffer->overlay_center);
if (afterp)
{
@@ -3844,17 +3856,16 @@ for the rear of the overlay advance when text is inserted there
end = OVERLAY_END (overlay);
if (OVERLAY_POSITION (end) < b->overlay_center)
{
- if (b->overlays_after)
- XOVERLAY (overlay)->next = b->overlays_after;
+ eassert (b->overlays_after || (XOVERLAY (overlay)->next == NULL));
+ XOVERLAY (overlay)->next = b->overlays_after;
set_buffer_overlays_after (b, XOVERLAY (overlay));
}
else
{
- if (b->overlays_before)
- XOVERLAY (overlay)->next = b->overlays_before;
+ eassert (b->overlays_before || (XOVERLAY (overlay)->next == NULL));
+ XOVERLAY (overlay)->next = b->overlays_before;
set_buffer_overlays_before (b, XOVERLAY (overlay));
}
-
/* This puts it in the right list, and in the right order. */
recenter_overlay_lists (b, b->overlay_center);
@@ -3878,17 +3889,17 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
BUF_COMPUTE_UNCHANGED (buf, start, end);
- /* If this is a buffer not in the selected window,
- we must do other windows. */
- if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
- windows_or_buffers_changed = 1;
- /* 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;
+ /* If BUF is visible, consider updating the display if ... */
+ if (buffer_window_count (buf) > 0)
+ {
+ /* ... it's visible in other window than selected, */
+ if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
+ windows_or_buffers_changed = 1;
+ /* ... or if we modify an overlay at the end of the buffer
+ and so 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);
}
@@ -4138,7 +4149,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,
- 0, 0, 0);
+ NULL, NULL, 0);
/* Make a list of them all. */
result = Flist (noverlays, overlay_vec);
@@ -4567,27 +4578,7 @@ evaporate_overlays (ptrdiff_t pos)
for (; CONSP (hit_list); hit_list = XCDR (hit_list))
Fdelete_overlay (XCAR (hit_list));
}
-
-/* Somebody has tried to store a value with an unacceptable type
- in the slot with offset OFFSET. */
-
-void
-buffer_slot_type_mismatch (Lisp_Object newval, int type)
-{
- Lisp_Object predicate;
- switch (type)
- {
- case_Lisp_Int: predicate = Qintegerp; break;
- case Lisp_String: predicate = Qstringp; break;
- case Lisp_Symbol: predicate = Qsymbolp; break;
- default: emacs_abort ();
- }
-
- wrong_type_argument (predicate, newval);
-}
-
-
/***********************************************************************
Allocation with mmap
***********************************************************************/
@@ -5029,7 +5020,7 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
{
void *p;
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
p = mmap_alloc ((void **) &b->text->beg, nbytes);
#elif defined REL_ALLOC
@@ -5040,12 +5031,12 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
if (p == NULL)
{
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (nbytes);
}
b->text->beg = (unsigned char *) p;
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Enlarge buffer B's text buffer by DELTA bytes. DELTA < 0 means
@@ -5057,7 +5048,7 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
void *p;
ptrdiff_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
+ delta);
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
p = mmap_realloc ((void **) &b->text->beg, nbytes);
#elif defined REL_ALLOC
@@ -5068,12 +5059,12 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
if (p == NULL)
{
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (nbytes);
}
BUF_BEG_ADDR (b) = (unsigned char *) p;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5082,7 +5073,7 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
static void
free_buffer_text (struct buffer *b)
{
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
mmap_free ((void **) &b->text->beg);
@@ -5093,7 +5084,7 @@ free_buffer_text (struct buffer *b)
#endif
BUF_BEG_ADDR (b) = NULL;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5106,11 +5097,6 @@ void
init_buffer_once (void)
{
int idx;
- /* If you add, remove, or reorder Lisp_Objects in a struct buffer, make
- sure that this is still correct. Otherwise, mark_vectorlike may not
- trace all Lisp_Objects in buffer_defaults and buffer_local_symbols. */
- const int pvecsize
- = (offsetof (struct buffer, own_text) - header_size) / word_size;
memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags);
@@ -5128,13 +5114,16 @@ init_buffer_once (void)
/* No one will share the text with these buffers, but let's play it safe. */
buffer_defaults.indirections = 0;
buffer_local_symbols.indirections = 0;
+ /* Likewise no one will display them. */
+ buffer_defaults.window_count = 0;
+ buffer_local_symbols.window_count = 0;
set_buffer_intervals (&buffer_defaults, NULL);
set_buffer_intervals (&buffer_local_symbols, NULL);
/* This is not strictly necessary, but let's make them initialized. */
bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*"));
bset_name (&buffer_local_symbols, build_pure_c_string (" *buffer-local-symbols*"));
- XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize);
- XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize);
+ BUFFER_PVEC_INIT (&buffer_defaults);
+ BUFFER_PVEC_INIT (&buffer_local_symbols);
/* Set up the default values of various buffer slots. */
/* Must do these before making the first buffer! */
@@ -5363,25 +5352,23 @@ init_buffer (void)
free (pwd);
}
-/* Similar to defvar_lisp but define a variable whose value is the Lisp
- Object stored in the current buffer. address is the address of the slot
- in the buffer that is current now. */
-
-/* TYPE is nil for a general Lisp variable.
- An integer specifies a type; then only Lisp values
- with that type code are allowed (except that nil is allowed too).
- LNAME is the Lisp-level variable name.
- VNAME is the name of the buffer slot.
- DOC is a dummy where you write the doc string as a comment. */
-#define DEFVAR_PER_BUFFER(lname, vname, type, doc) \
- do { \
- static struct Lisp_Buffer_Objfwd bo_fwd; \
- defvar_per_buffer (&bo_fwd, lname, vname, type); \
+/* Similar to defvar_lisp but define a variable whose value is the
+ Lisp_Object stored in the current buffer. LNAME is the Lisp-level
+ variable name. VNAME is the name of the buffer slot. PREDICATE
+ is nil for a general Lisp variable. If PREDICATE is non-nil, then
+ only Lisp values that satisfies the PREDICATE are allowed (except
+ that nil is allowed too). DOC is a dummy where you write the doc
+ string as a comment. */
+
+#define DEFVAR_PER_BUFFER(lname, vname, predicate, doc) \
+ do { \
+ static struct Lisp_Buffer_Objfwd bo_fwd; \
+ defvar_per_buffer (&bo_fwd, lname, vname, predicate); \
} while (0)
static void
defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
- Lisp_Object *address, Lisp_Object type)
+ Lisp_Object *address, Lisp_Object predicate)
{
struct Lisp_Symbol *sym;
int offset;
@@ -5391,7 +5378,7 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
bo_fwd->type = Lisp_Fwd_Buffer_Obj;
bo_fwd->offset = offset;
- bo_fwd->slottype = type;
+ bo_fwd->predicate = predicate;
sym->declared_special = 1;
sym->redirect = SYMBOL_FORWARDED;
{
@@ -5654,7 +5641,7 @@ Decimal digits after the % specify field width to which to pad. */);
doc: /* Value of `major-mode' for new buffers. */);
DEFVAR_PER_BUFFER ("major-mode", &BVAR (current_buffer, major_mode),
- make_number (Lisp_Symbol),
+ Qsymbolp,
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
@@ -5685,17 +5672,17 @@ Use the command `abbrev-mode' to change this variable. */);
doc: /* Non-nil if searches and matches should ignore case. */);
DEFVAR_PER_BUFFER ("fill-column", &BVAR (current_buffer, fill_column),
- make_number (Lisp_Int0),
+ Qintegerp,
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", &BVAR (current_buffer, left_margin),
- make_number (Lisp_Int0),
+ Qintegerp,
doc: /* Column for the default `indent-line-function' to indent to.
Linefeed indents to this column in Fundamental mode. */);
DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width),
- make_number (Lisp_Int0),
+ Qintegerp,
doc: /* Distance between tab stops (for display of tab characters), in columns.
This should be an integer greater than zero. */);
@@ -5780,7 +5767,7 @@ visual lines rather than logical lines. See the documentation of
`visual-line-mode'. */);
DEFVAR_PER_BUFFER ("default-directory", &BVAR (current_buffer, directory),
- make_number (Lisp_String),
+ Qstringp,
doc: /* Name of default directory of current buffer. Should end with slash.
To interactively change the default directory, use command `cd'. */);
@@ -5793,18 +5780,18 @@ NOTE: This variable is not a hook;
its value may not be a list of functions. */);
DEFVAR_PER_BUFFER ("buffer-file-name", &BVAR (current_buffer, filename),
- make_number (Lisp_String),
+ Qstringp,
doc: /* Name of file visited in current buffer, or nil if not visiting a file. */);
DEFVAR_PER_BUFFER ("buffer-file-truename", &BVAR (current_buffer, file_truename),
- make_number (Lisp_String),
+ Qstringp,
doc: /* Abbreviated truename of file visited in current buffer, or nil if none.
The truename of a file is calculated by `file-truename'
and then abbreviated with `abbreviate-file-name'. */);
DEFVAR_PER_BUFFER ("buffer-auto-save-file-name",
&BVAR (current_buffer, auto_save_file_name),
- make_number (Lisp_String),
+ Qstringp,
doc: /* Name of file for auto-saving current buffer.
If it is nil, that means don't auto-save this buffer. */);
@@ -5816,7 +5803,7 @@ 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", &BVAR (current_buffer, save_length),
- make_number (Lisp_Int0),
+ Qintegerp,
doc: /* Length of current buffer when last read in, saved or auto-saved.
0 initially.
-1 means auto-saving turned off until next real save.
@@ -5886,23 +5873,23 @@ In addition, a char-table has six extra slots to control the display of:
See also the functions `display-table-slot' and `set-display-table-slot'. */);
DEFVAR_PER_BUFFER ("left-margin-width", &BVAR (current_buffer, left_margin_cols),
- Qnil,
+ Qintegerp,
doc: /* Width of left marginal area for display of a buffer.
A value of nil means no marginal area. */);
DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols),
- Qnil,
+ Qintegerp,
doc: /* Width of right marginal area for display of a buffer.
A value of nil means no marginal area. */);
DEFVAR_PER_BUFFER ("left-fringe-width", &BVAR (current_buffer, left_fringe_width),
- Qnil,
+ Qintegerp,
doc: /* Width of this buffer's left fringe (in pixels).
A value of 0 means no left fringe is shown in this buffer's window.
A value of nil means to use the left fringe width from the window's frame. */);
DEFVAR_PER_BUFFER ("right-fringe-width", &BVAR (current_buffer, right_fringe_width),
- Qnil,
+ Qintegerp,
doc: /* Width of this buffer's right fringe (in pixels).
A value of 0 means no right fringe is shown in this buffer's window.
A value of nil means to use the right fringe width from the window's frame. */);
@@ -5913,7 +5900,7 @@ A value of nil means to use the right fringe width from the window's frame. */)
A value of nil means to display fringes between margins and buffer text. */);
DEFVAR_PER_BUFFER ("scroll-bar-width", &BVAR (current_buffer, scroll_bar_width),
- Qnil,
+ Qintegerp,
doc: /* Width of this buffer's scroll bars in pixels.
A value of nil means to use the scroll bar width from the window's frame. */);
@@ -5993,7 +5980,7 @@ BITMAP is the corresponding fringe bitmap shown for the logical
cursor type. */);
DEFVAR_PER_BUFFER ("scroll-up-aggressively",
- &BVAR (current_buffer, scroll_up_aggressively), Qnil,
+ &BVAR (current_buffer, scroll_up_aggressively), Qfloatp,
doc: /* How far to scroll windows upward.
If you move point off the bottom, the window scrolls automatically.
This variable controls how far it scrolls. The value nil, the default,
@@ -6006,7 +5993,7 @@ window scrolls by a full window height. Meaningful values are
between 0.0 and 1.0, inclusive. */);
DEFVAR_PER_BUFFER ("scroll-down-aggressively",
- &BVAR (current_buffer, scroll_down_aggressively), Qnil,
+ &BVAR (current_buffer, scroll_down_aggressively), Qfloatp,
doc: /* How far to scroll windows downward.
If you move point off the top, the window scrolls automatically.
This variable controls how far it scrolls. The value nil, the default,
@@ -6018,10 +6005,6 @@ simple case that you moved off with C-b means scrolling just one line.
window scrolls by a full window height. Meaningful values are
between 0.0 and 1.0, inclusive. */);
-/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
- "Don't ask.");
-*/
-
DEFVAR_LISP ("before-change-functions", Vbefore_change_functions,
doc: /* List of functions to call before each text change.
Two arguments are passed to each function: the positions of
@@ -6160,7 +6143,7 @@ then characters with property value PROP are invisible,
and they have an ellipsis as well if ELLIPSIS is non-nil. */);
DEFVAR_PER_BUFFER ("buffer-display-count",
- &BVAR (current_buffer, display_count), Qnil,
+ &BVAR (current_buffer, display_count), Qintegerp,
doc: /* A number incremented each time this buffer is displayed in a window.
The function `set-window-buffer' increments it. */);
@@ -6204,22 +6187,22 @@ is a member of the list. */);
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 height
+ 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
+ ANYTHING ELSE display a hollow box cursor
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",
- &BVAR (current_buffer, extra_line_spacing), Qnil,
+ &BVAR (current_buffer, extra_line_spacing), Qnumberp,
doc: /* Additional space to put between lines when displaying a buffer.
The space is measured in pixels, and put below lines on graphic displays,
see `display-graphic-p'.