/* 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.
#include <config.h>
-#define BUFFER_INLINE EXTERN_INLINE
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
-#include <setjmp.h>
#include <unistd.h>
#include <verify.h>
#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. */
struct buffer alignas (GCALIGNMENT) buffer_defaults;
-/* A Lisp_Object pointer to the above, used for staticpro */
-
-static Lisp_Object Vbuffer_defaults;
-
/* This structure marks which slots in a buffer have corresponding
default values in buffer_defaults.
Each such slot has a nonzero value in this structure.
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;
-/* A Lisp_Object pointer to the above, used for staticpro */
-static Lisp_Object Vbuffer_local_symbols;
-
/* Return the symbol of the per-buffer variable at offset OFFSET in
the buffer structure. */
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. */
-/* This used to be a variable, but is no longer,
- to prevent lossage due to user rplac'ing this alist or its elements. */
+/* Alist of all buffer names vs the buffers. This used to be
+ a Lisp-visible variable, but is no longer, to prevent lossage
+ due to user rplac'ing this alist or its elements. */
Lisp_Object Vbuffer_alist;
static Lisp_Object Qkill_buffer_query_functions;
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;
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
+CHECK_OVERLAY (Lisp_Object x)
+{
+ CHECK_TYPE (OVERLAYP (x), Qoverlayp, x);
+}
+
+/* These setters are used only in this file, so they can be private.
+ The public setters are inline functions defined in buffer.h. */
+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
-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)
{
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);
}
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));
See also `find-buffer-visiting'. */)
(register Lisp_Object filename)
{
- register Lisp_Object tail, buf, tem;
- Lisp_Object handler;
+ register Lisp_Object tail, buf, handler;
CHECK_STRING (filename);
filename = Fexpand_file_name (filename, Qnil);
return BUFFERP (handled_buf) ? handled_buf : Qnil;
}
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_LIVE_BUFFER (tail, buf)
{
- buf = Fcdr (XCAR (tail));
- if (!BUFFERP (buf)) continue;
if (!STRINGP (BVAR (XBUFFER (buf), filename))) continue;
- tem = Fstring_equal (BVAR (XBUFFER (buf), filename), filename);
- if (!NILP (tem))
+ if (!NILP (Fstring_equal (BVAR (XBUFFER (buf), filename), filename)))
return buf;
}
return Qnil;
Lisp_Object
get_truename_buffer (register Lisp_Object filename)
{
- register Lisp_Object tail, buf, tem;
+ register Lisp_Object tail, buf;
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_LIVE_BUFFER (tail, buf)
{
- buf = Fcdr (XCAR (tail));
- if (!BUFFERP (buf)) continue;
if (!STRINGP (BVAR (XBUFFER (buf), file_truename))) continue;
- tem = Fstring_equal (BVAR (XBUFFER (buf), file_truename), filename);
- if (!NILP (tem))
+ if (!NILP (Fstring_equal (BVAR (XBUFFER (buf), file_truename), filename)))
return buf;
}
return Qnil;
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);
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;
b->newline_cache = 0;
b->width_run_cache = 0;
+ b->bidi_paragraph_cache = 0;
bset_width_table (b, Qnil);
b->prevent_redisplay_optimizations_p = 1;
- /* Put this on the chain of all buffers including killed ones. */
- b->header.next.buffer = all_buffers;
- all_buffers = b;
-
/* An ordinary buffer normally doesn't need markers
to handle BEGV and ZV. */
bset_pt_marker (b, Qnil);
/* Put this in the alist of all live buffers. */
XSETBUFFER (buffer, b);
- Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buffer), Qnil));
+ Vbuffer_alist = nconc2 (Vbuffer_alist, list1 (Fcons (name, buffer)));
/* And run buffer-list-update-hook. */
if (!NILP (Vrun_hooks))
call1 (Vrun_hooks, Qbuffer_list_update_hook);
/* 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;
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)
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;
b->newline_cache = 0;
b->width_run_cache = 0;
+ b->bidi_paragraph_cache = 0;
bset_width_table (b, Qnil);
- /* Put this on the chain of all buffers including killed ones. */
- b->header.next.buffer = all_buffers;
- all_buffers = b;
-
name = Fcopy_sequence (name);
set_string_intervals (name, NULL);
bset_name (b, name);
/* Put this in the alist of all live buffers. */
XSETBUFFER (buf, b);
- Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil));
+ Vbuffer_alist = nconc2 (Vbuffer_alist, list1 (Fcons (name, buf)));
bset_mark (b, Fmake_marker ());
eassert (b == XBUFFER (Fmarker_buffer (ov->start)));
modify_overlay (b, marker_position (ov->start),
marker_position (ov->end));
- Fset_marker (ov->start, Qnil, Qnil);
- Fset_marker (ov->end, Qnil, Qnil);
+ unchain_marker (XMARKER (ov->start));
+ unchain_marker (XMARKER (ov->end));
}
{
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);
bset_filename (b, Qnil);
bset_file_truename (b, Qnil);
bset_directory (b, current_buffer ? BVAR (current_buffer, directory) : Qnil);
- b->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
+ b->modtime = make_timespec (0, UNKNOWN_MODTIME_NSECS);
b->modtime_size = -1;
XSETFASTINT (BVAR (b, save_length), 0);
b->last_window_start = 1;
result = Fdefault_value (variable);
break;
}
- default: abort ();
+ default: emacs_abort ();
}
return result;
return BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf) ? Qt : Qnil;
}
+DEFUN ("force-mode-line-update", Fforce_mode_line_update,
+ Sforce_mode_line_update, 0, 1, 0,
+ doc: /* Force redisplay of the current buffer's mode line and header line.
+With optional non-nil ALL, force redisplay of all mode lines and
+header lines. This function also forces recomputation of the
+menu bar menus and the frame title. */)
+ (Lisp_Object all)
+{
+ if (!NILP (all))
+ {
+ update_mode_lines = 10;
+ /* FIXME: This can't be right. */
+ current_buffer->prevent_redisplay_optimizations_p = true;
+ }
+ else if (buffer_window_count (current_buffer))
+ {
+ bset_update_mode_line (current_buffer);
+ current_buffer->prevent_redisplay_optimizations_p = true;
+ }
+ return all;
+}
+
DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p, Sset_buffer_modified_p,
1, 1, 0,
doc: /* Mark current buffer as modified or unmodified according to FLAG.
A non-nil FLAG means mark the buffer modified. */)
(Lisp_Object flag)
{
- Lisp_Object fn, buffer, window;
-
-#ifdef CLASH_DETECTION
- /* If buffer becoming modified, lock the file.
- If buffer becoming unmodified, unlock the file. */
-
- fn = BVAR (current_buffer, file_truename);
- /* Test buffer-file-name so that binding it to nil is effective. */
- if (!NILP (fn) && ! NILP (BVAR (current_buffer, filename)))
- {
- bool already = SAVE_MODIFF < MODIFF;
- if (!already && !NILP (flag))
- lock_file (fn);
- else if (already && NILP (flag))
- unlock_file (fn);
- }
-#endif /* CLASH_DETECTION */
-
- /* Here we have a problem. SAVE_MODIFF is used here to encode
- buffer-modified-p (as SAVE_MODIFF<MODIFF) as well as
- recent-auto-save-p (as SAVE_MODIFF<auto_save_modified). So if we
- modify SAVE_MODIFF to affect one, we may affect the other
- as well.
- E.g. if FLAG is nil we need to set SAVE_MODIFF to MODIFF, but
- if SAVE_MODIFF<auto_save_modified that means we risk changing
- recent-auto-save-p from t to nil.
- Vice versa, if FLAG is non-nil and 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++);
+ Frestore_buffer_modified_p (flag);
/* Set update_mode_lines only if buffer is displayed in some window.
Packages like jit-lock or lazy-lock preserve a buffer's 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))
- {
- ++update_mode_lines;
- current_buffer->prevent_redisplay_optimizations_p = 1;
- }
-
- return flag;
+ return Fforce_mode_line_update (Qnil);
}
DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
/* 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))
}
#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<MODIFF) as well as
+ recent-auto-save-p (as SAVE_MODIFF<auto_save_modified). So if we
+ modify SAVE_MODIFF to affect one, we may affect the other
+ as well.
+ E.g. if FLAG is nil we need to set SAVE_MODIFF to MODIFF, but
+ if SAVE_MODIFF<auto_save_modified that means we risk changing
+ recent-auto-save-p from t to nil.
+ Vice versa, if FLAG is non-nil and 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++);
+
return flag;
}
/* Catch redisplay's attention. Unless we do this, the mode lines for
any windows displaying current_buffer will stay unchanged. */
- update_mode_lines++;
+ update_mode_lines = 11;
XSETBUFFER (buf, current_buffer);
Fsetcar (Frassq (buf, Vbuffer_alist), newname);
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
exists, return the buffer `*scratch*' (creating it if necessary). */)
(register Lisp_Object buffer, Lisp_Object visible_ok, Lisp_Object frame)
{
- Lisp_Object Fset_buffer_major_mode (Lisp_Object buffer);
- 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))))
}
/* Consider alist of all buffers next. */
- tail = Vbuffer_alist;
- for (; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_LIVE_BUFFER (tail, buf)
{
- 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))))
Lisp_Object
other_buffer_safely (Lisp_Object buffer)
{
- Lisp_Object Fset_buffer_major_mode (Lisp_Object buffer);
Lisp_Object tail, buf;
- tail = Vbuffer_alist;
- 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) != ' '))
- return buf;
- }
+ FOR_EACH_LIVE_BUFFER (tail, buf)
+ if (candidate_buffer (buf, buffer))
+ return buf;
buf = Fget_buffer (build_string ("*scratch*"));
if (NILP (buf))
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
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);
}
}
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. */
- if (INTERACTIVE && !NILP (BVAR (b, filename))
- && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
- {
- GCPRO1 (buffer);
- tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ",
- BVAR (b, name), make_number (0)));
- UNGCPRO;
- if (NILP (tem))
- return Qnil;
- }
-
/* Run hooks with the buffer to be killed the current buffer. */
{
ptrdiff_t count = SPECPDL_INDEX ();
if (NILP (tem))
return unbind_to (count, Qnil);
+ /* Query if the buffer is still modified. */
+ if (INTERACTIVE && !NILP (BVAR (b, filename))
+ && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
+ {
+ GCPRO1 (buffer);
+ tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ",
+ BVAR (b, name), make_number (0)));
+ UNGCPRO;
+ if (NILP (tem))
+ return unbind_to (count, Qnil);
+ }
+
+ /* If the hooks have killed the buffer, exit now. */
+ if (!BUFFER_LIVE_P (b))
+ return unbind_to (count, Qt);
+
/* Then run the hooks. */
Frun_hooks (1, &Qkill_buffer_hook);
unbind_to (count, Qnil);
}
/* 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
since anything can happen within do_yes_or_no_p. */
/* Don't kill the minibuffer now current. */
- if (EQ (buffer, XWINDOW (minibuf_window)->buffer))
+ if (EQ (buffer, XWINDOW (minibuf_window)->contents))
return Qnil;
/* When we kill an ordinary buffer which shares it's buffer text
UNGCPRO;
/* Exit if we now have killed the base buffer (Bug#11665). */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
}
/* Run replace_buffer_in_windows before making another buffer current
since set-window-buffer-start-and-point will refuse to make another
buffer current if the selected window does not show the current
- buffer. (Bug#10114) */
+ buffer (bug#10114). */
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
/* If the buffer now current is shown in the minibuffer and our buffer
is the sole other buffer give up. */
XSETBUFFER (tem, current_buffer);
- if (EQ (tem, XWINDOW (minibuf_window)->buffer)
+ if (EQ (tem, XWINDOW (minibuf_window)->contents)
&& EQ (buffer, Fother_buffer (buffer, Qnil, Qnil)))
return Qnil;
/* 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
}
/* 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)
/* 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
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
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)
{
free_region_cache (b->width_run_cache);
b->width_run_cache = 0;
}
+ if (b->bidi_paragraph_cache)
+ {
+ free_region_cache (b->bidi_paragraph_cache);
+ b->bidi_paragraph_cache = 0;
+ }
bset_width_table (b, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
bset_undo_list (b, Qnil);
/* Run buffer-list-update-hook. */
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)
CHECK_BUFFER (buffer);
- if (STRINGP (BVAR (XBUFFER (buffer), name))
- && strcmp (SSDATA (BVAR (XBUFFER (buffer), name)), "*scratch*") == 0)
+ 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)
function = find_symbol_value (intern ("initial-major-mode"));
else
{
count = SPECPDL_INDEX ();
/* To select a nonfundamental mode,
- select the buffer temporarily and then call the mode function. */
+ select the buffer temporarily and then call the mode function. */
record_unwind_protect (save_excursion_restore, save_excursion_save ());
if (current_buffer == b)
return;
+ BUFFER_CHECK_INDIRECTION (b);
+
old_buf = current_buffer;
current_buffer = b;
- last_known_column_point = -1; /* invalidate indentation cache */
+ last_known_column_point = -1; /* Invalidate indentation cache. */
if (old_buf)
{
fetch_buffer_markers (b);
/* Look down buffer's list of local Lisp variables
- to find and update any that forward into C variables. */
+ to find and update any that forward into C variables. */
do
{
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. */)
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;
}
+void
+restore_buffer (Lisp_Object buffer_or_name)
+{
+ Fset_buffer (buffer_or_name);
+}
+
/* Set the current buffer to BUFFER provided if it is alive. */
-Lisp_Object
+void
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;
}
\f
DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
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.
current_buffer->clip_changed = 1; other_buffer->clip_changed = 1;
swapfield (newline_cache, struct region_cache *);
swapfield (width_run_cache, struct region_cache *);
+ swapfield (bidi_paragraph_cache, struct region_cache *);
current_buffer->prevent_redisplay_optimizations_p = 1;
other_buffer->prevent_redisplay_optimizations_p = 1;
swapfield (overlays_before, struct Lisp_Overlay *);
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
+ { /* Some of the C code expects that both window markers of a
+ live window points to that window's 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 w = selected_window, ws = Qnil;
Lisp_Object buf1, buf2;
XSETBUFFER (buf1, current_buffer); XSETBUFFER (buf2, other_buffer);
{
ws = Fcons (w, ws);
if (MARKERP (XWINDOW (w)->pointm)
- && (EQ (XWINDOW (w)->buffer, buf1)
- || EQ (XWINDOW (w)->buffer, buf2)))
+ && (EQ (XWINDOW (w)->contents, buf1)
+ || EQ (XWINDOW (w)->contents, buf2)))
Fset_marker (XWINDOW (w)->pointm,
make_number
- (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))),
- XWINDOW (w)->buffer);
+ (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))),
+ XWINDOW (w)->contents);
+ if (MARKERP (XWINDOW (w)->start)
+ && (EQ (XWINDOW (w)->contents, buf1)
+ || EQ (XWINDOW (w)->contents, buf2)))
+ Fset_marker (XWINDOW (w)->start,
+ make_number
+ (XBUFFER (XWINDOW (w)->contents)->last_window_start),
+ XWINDOW (w)->contents);
w = Fnext_window (w, Qt, Qt);
}
}
begv = BEGV, zv = ZV;
if (narrowed)
- Fwiden ();
+ error ("Changing multibyteness in a narrowed buffer");
+
+ invalidate_buffer_caches (current_buffer, BEGV, ZV);
if (NILP (flag))
{
/* Make sure no markers were put on the chain
while the chain value was incorrect. */
if (BUF_MARKERS (current_buffer))
- abort ();
+ emacs_abort ();
BUF_MARKERS (current_buffer) = markers;
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 = 10;
/* 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);
/* Force mode-line redisplay. Useful here because all major mode
commands call this function. */
- update_mode_lines++;
+ update_mode_lines = 12;
return Qnil;
}
static int
compare_overlays (const void *v1, const void *v2)
{
- const struct sortvec *s1 = (const struct sortvec *) v1;
- const struct sortvec *s2 = (const struct sortvec *) v2;
+ const struct sortvec *s1 = v1;
+ const struct sortvec *s2 = v2;
if (s1->priority != s2->priority)
return s1->priority < s2->priority ? -1 : 1;
if (s1->beg != s2->beg)
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;
}
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. */
for (i = 0; i < noverlays; i++)
overlay_vec[i] = sortvec[i].overlay;
+
+ SAFE_FREE ();
return (noverlays);
}
\f
static int
cmp_for_strings (const void *as1, const void *as2)
{
- struct sortstr *s1 = (struct sortstr *)as1;
- struct sortstr *s2 = (struct sortstr *)as2;
+ struct sortstr const *s1 = as1;
+ struct sortstr const *s2 = as2;
if (s1->size != s2->size)
return s2->size < s1->size ? -1 : 1;
if (s1->priority != s2->priority)
}
}
if (p != overlay_str_buf + total)
- abort ();
+ emacs_abort ();
if (pstr)
*pstr = overlay_str_buf;
return total;
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)
{
The fifth arg REAR-ADVANCE, if non-nil, makes the marker
for the rear of the overlay advance when text is inserted there
\(which means the text *is* included in the overlay). */)
- (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer, Lisp_Object front_advance, Lisp_Object rear_advance)
+ (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer,
+ Lisp_Object front_advance, Lisp_Object rear_advance)
{
Lisp_Object overlay;
struct buffer *b;
XSETBUFFER (buffer, current_buffer);
else
CHECK_BUFFER (buffer);
- if (MARKERP (beg)
- && ! EQ (Fmarker_buffer (beg), buffer))
- error ("Marker points into wrong buffer");
- if (MARKERP (end)
- && ! EQ (Fmarker_buffer (end), buffer))
- error ("Marker points into wrong buffer");
+
+ if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer))
+ signal_error ("Marker points into wrong buffer", beg);
+ if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
+ signal_error ("Marker points into wrong buffer", end);
CHECK_NUMBER_COERCE_MARKER (beg);
CHECK_NUMBER_COERCE_MARKER (end);
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);
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;
+ bset_redisplay (buf);
++BUF_OVERLAY_MODIFF (buf);
}
if (NILP (Fbuffer_live_p (buffer)))
error ("Attempt to move overlay to a dead buffer");
- if (MARKERP (beg)
- && ! EQ (Fmarker_buffer (beg), buffer))
- error ("Marker points into wrong buffer");
- if (MARKERP (end)
- && ! EQ (Fmarker_buffer (end), buffer))
- error ("Marker points into wrong buffer");
+ if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer))
+ signal_error ("Marker points into wrong buffer", beg);
+ if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
+ signal_error ("Marker points into wrong buffer", end);
CHECK_NUMBER_COERCE_MARKER (beg);
CHECK_NUMBER_COERCE_MARKER (end);
return unbind_to (count, Qnil);
}
+
+DEFUN ("delete-all-overlays", Fdelete_all_overlays, Sdelete_all_overlays, 0, 1, 0,
+ doc: /* Delete all overlays of BUFFER.
+BUFFER omitted or nil means delete all overlays of the current
+buffer. */)
+ (Lisp_Object buffer)
+{
+ register struct buffer *buf;
+
+ if (NILP (buffer))
+ buf = current_buffer;
+ else
+ {
+ CHECK_BUFFER (buffer);
+ buf = XBUFFER (buffer);
+ }
+
+ delete_all_overlays (buf);
+ return Qnil;
+}
\f
/* Overlay dissection functions. */
CHECK_NUMBER_COERCE_MARKER (pos);
+ if (!buffer_has_overlays ())
+ return Qnil;
+
len = 10;
/* We can't use alloca here because overlays_at can call xrealloc. */
overlay_vec = xmalloc (len * sizeof *overlay_vec);
/* 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);
CHECK_NUMBER_COERCE_MARKER (beg);
CHECK_NUMBER_COERCE_MARKER (end);
+ if (!buffer_has_overlays ())
+ return Qnil;
+
len = 10;
overlay_vec = xmalloc (len * sizeof *overlay_vec);
CHECK_NUMBER_COERCE_MARKER (pos);
+ if (!buffer_has_overlays ())
+ return make_number (ZV);
+
len = 10;
overlay_vec = xmalloc (len * sizeof *overlay_vec);
CHECK_NUMBER_COERCE_MARKER (pos);
+ if (!buffer_has_overlays ())
+ return make_number (BEGV);
+
/* At beginning of buffer, we know the answer;
avoid bug subtracting 1 below. */
if (XINT (pos) == BEGV)
for (; CONSP (hit_list); hit_list = XCDR (hit_list))
Fdelete_overlay (XCAR (hit_list));
}
-\f
-/* 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: abort ();
- }
-
- wrong_type_argument (predicate, newval);
-}
-
-\f
/***********************************************************************
Allocation with mmap
***********************************************************************/
#ifdef USE_MMAP_FOR_BUFFERS
-#include <sys/types.h>
#include <sys/mman.h>
#ifndef MAP_ANON
#define MAP_FAILED ((void *) -1)
#endif
-#include <stdio.h>
-
#if MAP_ANON == 0
#include <fcntl.h>
#endif
if (mmap_fd <= 0)
{
/* No anonymous mmap -- we need the file descriptor. */
- mmap_fd = open ("/dev/zero", O_RDONLY);
+ mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
if (mmap_fd == -1)
fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno));
}
mmap_find (void *start, void *end)
{
struct mmap_region *r;
- char *s = (char *) start, *e = (char *) end;
+ char *s = start, *e = end;
for (r = mmap_regions; r; r = r->next)
{
}
else
{
- struct mmap_region *r = (struct mmap_region *) p;
+ struct mmap_region *r = p;
r->nbytes_specified = nbytes;
r->nbytes_mapped = map;
{
void *p;
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
p = mmap_alloc ((void **) &b->text->beg, nbytes);
#elif defined REL_ALLOC
if (p == NULL)
{
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (nbytes);
}
- b->text->beg = (unsigned char *) p;
- UNBLOCK_INPUT;
+ b->text->beg = p;
+ unblock_input ();
}
/* Enlarge buffer B's text buffer by DELTA bytes. DELTA < 0 means
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
if (p == NULL)
{
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (nbytes);
}
- BUF_BEG_ADDR (b) = (unsigned char *) p;
- UNBLOCK_INPUT;
+ BUF_BEG_ADDR (b) = p;
+ unblock_input ();
}
static void
free_buffer_text (struct buffer *b)
{
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
mmap_free ((void **) &b->text->beg);
#endif
BUF_BEG_ADDR (b) = NULL;
- UNBLOCK_INPUT;
+ unblock_input ();
}
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);
/* 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);
- XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize);
- XSETBUFFER (Vbuffer_defaults, &buffer_defaults);
- XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize);
- XSETBUFFER (Vbuffer_local_symbols, &buffer_local_symbols);
+ /* 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*"));
+ 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! */
bset_buffer_file_coding_system (&buffer_defaults, Qnil);
XSETFASTINT (BVAR (&buffer_defaults, fill_column), 70);
XSETFASTINT (BVAR (&buffer_defaults, left_margin), 0);
- bset_cache_long_line_scans (&buffer_defaults, Qnil);
+ bset_cache_long_scans (&buffer_defaults, Qt);
bset_file_truename (&buffer_defaults, Qnil);
XSETFASTINT (BVAR (&buffer_defaults, display_count), 0);
XSETFASTINT (BVAR (&buffer_defaults, left_margin_cols), 0);
XSETFASTINT (BVAR (&buffer_local_flags, abbrev_table), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, cache_long_line_scans), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, cache_long_scans), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx;
/* Need more room? */
if (idx >= MAX_PER_BUFFER_VARS)
- abort ();
+ emacs_abort ();
last_per_buffer_idx = idx;
Vbuffer_alist = Qnil;
len++;
}
+ /* At this moment, we still don't know how to decode the directory
+ name. So, we keep the bytes in unibyte form so that file I/O
+ routines correctly get the original bytes. */
bset_directory (current_buffer, make_unibyte_string (pwd, len));
- if (! NILP (BVAR (&buffer_defaults, enable_multibyte_characters)))
- /* At this moment, we still don't know how to decode the
- directory name. So, we keep the bytes in multibyte form so
- that ENCODE_FILE correctly gets the original bytes. */
- bset_directory
- (current_buffer, string_to_multibyte (BVAR (current_buffer, directory)));
/* Add /: to the front of the name
if it would otherwise be treated as magic. */
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;
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;
- {
- /* I tried to do the job without a cast, but it seems impossible.
- union Lisp_Fwd *fwd; &(fwd->u_buffer_objfwd) = bo_fwd; */
- SET_SYMBOL_FWD (sym, (union Lisp_Fwd *)bo_fwd);
- }
+ SET_SYMBOL_FWD (sym, (union Lisp_Fwd *) bo_fwd);
XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym);
if (PER_BUFFER_IDX (offset) == 0)
/* Did a DEFVAR_PER_BUFFER without initializing the corresponding
- slot of buffer_local_flags */
- abort ();
+ slot of buffer_local_flags. */
+ emacs_abort ();
}
-/* initialize the buffer routines */
+/* Initialize the buffer routines. */
void
syms_of_buffer (void)
{
last_overlay_modification_hooks
= Fmake_vector (make_number (10), Qnil);
- staticpro (&Vbuffer_defaults);
- staticpro (&Vbuffer_local_symbols);
staticpro (&Qfundamental_mode);
staticpro (&Qmode_class);
staticpro (&QSFundamental);
DEFVAR_BUFFER_DEFAULTS ("default-tab-width",
tab_width,
doc: /* Default value of `tab-width' for buffers that do not override it.
+NOTE: This controls the display width of a TAB character, and not
+the size of an indentation step.
This is the same as (default-value 'tab-width). */);
DEFVAR_BUFFER_DEFAULTS ("default-case-fold-search",
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
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.
+NOTE: This controls the display width of a TAB character, and not
+the size of an indentation step.
This should be an integer greater than zero. */);
DEFVAR_PER_BUFFER ("ctl-arrow", &BVAR (current_buffer, ctl_arrow), Qnil,
`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'. */);
its value may not be a list of functions. */);
DEFVAR_PER_BUFFER ("buffer-file-name", &BVAR (current_buffer, filename),
- make_number (Lisp_String),
- doc: /* Name of file visited in current buffer, or nil if not visiting a file. */);
+ Qstringp,
+ doc: /* Name of file visited in current buffer, or nil if not visiting a file.
+This should be an absolute file name. */);
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. */);
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.
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,
- doc: /* Width of left marginal area for display of a buffer.
-A value of nil means no marginal area. */);
+ Qintegerp,
+ doc: /* Width in columns of left marginal area for display of a buffer.
+A value of nil means no marginal area.
+
+Setting this variable does not take effect until a new buffer is displayed
+in a window. To make the change take effect, call `set-window-buffer'. */);
DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols),
- Qnil,
- doc: /* Width of right marginal area for display of a buffer.
-A value of nil means no marginal area. */);
+ Qintegerp,
+ doc: /* Width in columns of right marginal area for display of a buffer.
+A value of nil means no marginal area.
+
+Setting this variable does not take effect until a new buffer is displayed
+in a window. To make the change take effect, call `set-window-buffer'. */);
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. */);
+A value of nil means to use the left fringe width from the window's frame.
+
+Setting this variable does not take effect until a new buffer is displayed
+in a window. To make the change take effect, call `set-window-buffer'. */);
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. */);
+A value of nil means to use the right fringe width from the window's frame.
+
+Setting this variable does not take effect until a new buffer is displayed
+in a window. To make the change take effect, call `set-window-buffer'. */);
DEFVAR_PER_BUFFER ("fringes-outside-margins", &BVAR (current_buffer, fringes_outside_margins),
Qnil,
doc: /* Non-nil means to display fringes outside display margins.
-A value of nil means to display fringes between margins and buffer text. */);
+A value of nil means to display fringes between margins and buffer text.
+
+Setting this variable does not take effect until a new buffer is displayed
+in a window. To make the change take effect, call `set-window-buffer'. */);
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. */);
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,
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,
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
modification time of the most recent save is different, this entry is
obsolete.
+An entry (t . 0) means means the buffer was previously unmodified but
+its time stamp was unknown because it was not associated with a file.
+An entry (t . -1) is similar, except that it means the buffer's visited
+file did not exist.
+
An entry (nil PROPERTY VALUE BEG . END) indicates that a text property
was modified between BEG and END. PROPERTY is the property name,
and VALUE is the old value.
An entry (apply DELTA BEG END FUN-NAME . ARGS) supports selective undo
in the active region. BEG and END is the range affected by this entry
-and DELTA is the number of bytes added or deleted in that range by
+and DELTA is the number of characters added or deleted in that range by
this change.
An entry (MARKER . DISTANCE) indicates that the marker MARKER
DEFVAR_PER_BUFFER ("mark-active", &BVAR (current_buffer, mark_active), Qnil,
doc: /* Non-nil means the mark and region are currently active in this buffer. */);
- DEFVAR_PER_BUFFER ("cache-long-line-scans", &BVAR (current_buffer, cache_long_line_scans), Qnil,
- doc: /* Non-nil means that Emacs should use caches to handle long lines more quickly.
+ DEFVAR_PER_BUFFER ("cache-long-scans", &BVAR (current_buffer, cache_long_scans), Qnil,
+ doc: /* Non-nil means that Emacs should use caches in attempt to speedup buffer scans.
Normally, the line-motion functions work by scanning the buffer for
newlines. Columnar operations (like `move-to-column' and
motion functions will take longer to execute. Emacs may also take
longer to update the display.
-If `cache-long-line-scans' is non-nil, these motion functions cache the
+If `cache-long-scans' is non-nil, these motion functions cache the
results of their scans, and consult the cache to avoid rescanning
regions of the buffer until the text is modified. The caches are most
beneficial when they prevent the most searching---that is, when the
buffer contains long lines and large regions of characters with the
same, fixed screen width.
-When `cache-long-line-scans' is non-nil, processing short lines will
+When `cache-long-scans' is non-nil, processing short lines will
become slightly slower (because of the overhead of consulting the
cache), and the caches will use memory roughly proportional to the
number of newlines and characters whose screen width varies.
+Bidirectional editing also requires buffer scans to find paragraph
+separators. If you have large paragraphs or no paragraph separators
+at all, these scans may be slow. If `cache-long-scans' is non-nil,
+results of these scans are cached. This doesn't help too much if
+paragraphs are of the reasonable (few thousands of characters) size.
+
The caches require no explicit maintenance; their accuracy is
maintained internally by the Emacs primitives. Enabling or disabling
the cache should not affect the behavior of any of the motion
property is an element in that list (or is a list with members in common).
If an element is a cons cell of the form (PROP . ELLIPSIS),
then characters with property value PROP are invisible,
-and they have an ellipsis as well if ELLIPSIS is non-nil. */);
+and they have an ellipsis as well if ELLIPSIS is non-nil.
+Setting this variable is very fast, much faster than scanning all the
+text in the buffer looking for properties to change. */);
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. */);
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'.
defsubr (&Sbuffer_local_value);
defsubr (&Sbuffer_local_variables);
defsubr (&Sbuffer_modified_p);
+ defsubr (&Sforce_mode_line_update);
defsubr (&Sset_buffer_modified_p);
defsubr (&Sbuffer_modified_tick);
defsubr (&Sbuffer_chars_modified_tick);
defsubr (&Soverlayp);
defsubr (&Smake_overlay);
defsubr (&Sdelete_overlay);
+ defsubr (&Sdelete_all_overlays);
defsubr (&Smove_overlay);
defsubr (&Soverlay_start);
defsubr (&Soverlay_end);