#include <config.h>
-#define BUFFER_INLINE EXTERN_INLINE
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
CHECK_TYPE (OVERLAYP (x), Qoverlayp, x);
}
-/* These setters are used only in this file, so they can be private. */
+/* 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 (buffer_file_coding_system) = val;
}
static void
-bset_cache_long_line_scans (struct buffer *b, Lisp_Object val)
-{
- b->INTERNAL_FIELD (cache_long_line_scans) = val;
-}
-static void
bset_case_fold_search (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (case_fold_search) = val;
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;
b->newline_cache = 0;
b->width_run_cache = 0;
+ b->bidi_paragraph_cache = 0;
bset_width_table (b, Qnil);
name = Fcopy_sequence (name);
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;
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;
+ 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
+ state by recording/restoring the state around blocks of code.
+ Setting update_mode_lines makes redisplay consider all windows
+ (on all frames). Stealth fontification of buffers not displayed
+ would incur additional redisplay costs if we'd set
+ update_modes_lines unconditionally.
+
+ 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 */
+ return Fforce_mode_line_update (Qnil);
+}
+DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
+ Srestore_buffer_modified_p, 1, 1, 0,
+ doc: /* Like `set-buffer-modified-p', with a difference concerning redisplay.
+It is not ensured that mode lines will be updated to show the modified
+state of the current buffer. Use with care. */)
+ (Lisp_Object flag)
+{
#ifdef CLASH_DETECTION
+ Lisp_Object fn;
+
/* If buffer becoming modified, lock the file.
If buffer becoming unmodified, unlock the file. */
or increase MODIFF. */
: MODIFF++);
- /* Set update_mode_lines only if buffer is displayed in some window.
- Packages like jit-lock or lazy-lock preserve a buffer's modified
- state by recording/restoring the state around blocks of code.
- Setting update_mode_lines makes redisplay consider all windows
- (on all frames). Stealth fontification of buffers not displayed
- would incur additional redisplay costs if we'd set
- update_modes_lines unconditionally.
-
- 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 */
- if (buffer_window_count (current_buffer))
- {
- ++update_mode_lines;
- current_buffer->prevent_redisplay_optimizations_p = 1;
- }
-
- return flag;
-}
-
-DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
- Srestore_buffer_modified_p, 1, 1, 0,
- doc: /* Like `set-buffer-modified-p', with a difference concerning redisplay.
-It is not ensured that mode lines will be updated to show the modified
-state of the current buffer. Use with care. */)
- (Lisp_Object flag)
-{
-#ifdef CLASH_DETECTION
- Lisp_Object fn;
-
- /* 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 */
-
- SAVE_MODIFF = NILP (flag) ? MODIFF : 0;
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);
/* 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. */
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
{
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);
if (narrowed)
error ("Changing multibyteness in a narrowed buffer");
+ invalidate_buffer_caches (current_buffer, BEGV, ZV);
+
if (NILP (flag))
{
ptrdiff_t pos, stop;
/* If buffer is shown in a window, let redisplay consider other windows. */
if (buffer_window_count (current_buffer))
- ++windows_or_buffers_changed;
+ windows_or_buffers_changed = 10;
/* Copy this buffer's new multibyte status
into all of its indirect buffers. */
/* 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)
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);
BUF_COMPUTE_UNCHANGED (buf, start, end);
- /* 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)->contents))
- 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;
- }
+ 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);
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)
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, 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;
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. */
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 */
+ slot of buffer_local_flags. */
emacs_abort ();
}
-/* initialize the buffer routines */
+/* Initialize the buffer routines. */
void
syms_of_buffer (void)
{
DEFVAR_PER_BUFFER ("buffer-file-name", &BVAR (current_buffer, filename),
Qstringp,
- doc: /* Name of file visited in current buffer, or nil if not visiting a file. */);
+ 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),
Qstringp,
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
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,
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);