#include <config.h>
-#define BUFFER_INLINE EXTERN_INLINE
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
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;
b->INTERNAL_FIELD (buffer_file_coding_system) = val;
}
static void
-bset_cache_long_line_scans (struct buffer *b, Lisp_Object val)
+bset_cache_long_scans (struct buffer *b, Lisp_Object val)
{
- b->INTERNAL_FIELD (cache_long_line_scans) = val;
+ b->INTERNAL_FIELD (cache_long_scans) = val;
}
static void
bset_case_fold_search (struct buffer *b, Lisp_Object val)
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->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 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);
b->newline_cache = 0;
b->width_run_cache = 0;
+ b->bidi_paragraph_cache = 0;
bset_width_table (b, Qnil);
name = Fcopy_sequence (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));
}
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;
}
/* 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 (candidate_buffer (buf, buffer)
/* If the frame has a buffer_predicate, disregard buffers that
don't fit the predicate. */
{
Lisp_Object tail, buf;
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
- {
- buf = Fcdr (XCAR (tail));
- if (candidate_buffer (buf, buffer))
- return buf;
- }
+ FOR_EACH_LIVE_BUFFER (tail, buf)
+ if (candidate_buffer (buf, buffer))
+ return buf;
buf = Fget_buffer (build_string ("*scratch*"));
if (NILP (buf))
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);
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 ();
bset_undo_list (b, Qnil);
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 ());
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
{
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 (BUFFER_LIVE_P (XBUFFER (buffer)))
set_buffer_internal (XBUFFER (buffer));
- return Qnil;
}
\f
DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
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 *);
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);
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)
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)
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);
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);
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);
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)
Lisp_Object *copy = alloca (size * sizeof *copy);
ptrdiff_t i;
- memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents,
+ memcpy (copy, XVECTOR (last_overlay_modification_hooks)->u.contents,
size * word_size);
gcpro1.var = copy;
gcpro1.nvars = size;
#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;
memory_full (nbytes);
}
- b->text->beg = (unsigned char *) p;
+ b->text->beg = p;
unblock_input ();
}
memory_full (nbytes);
}
- BUF_BEG_ADDR (b) = (unsigned char *) p;
+ BUF_BEG_ADDR (b) = p;
unblock_input ();
}
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, Qnil);
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;
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)
DEFVAR_PER_BUFFER ("left-margin-width", &BVAR (current_buffer, left_margin_cols),
Qintegerp,
- doc: /* Width of left marginal area for display of a buffer.
+ 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
DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols),
Qintegerp,
- doc: /* Width of right marginal area for display of a buffer.
+ 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
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), Qintegerp,