/* Buffer insertion/deletion and gap motion for GNU Emacs.
- Copyright (C) 1985-1986, 1993-1995, 1997-2011
+ Copyright (C) 1985-1986, 1993-1995, 1997-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "lisp.h"
#include "intervals.h"
-#include "buffer.h"
#include "character.h"
+#include "buffer.h"
#include "window.h"
#include "blockinput.h"
#include "region-cache.h"
-#ifndef NULL
-#define NULL 0
-#endif
-
-static void insert_from_string_1 (Lisp_Object string,
- ptrdiff_t pos, ptrdiff_t pos_byte,
- ptrdiff_t nchars, ptrdiff_t nbytes,
- int inherit, int before_markers);
-static void insert_from_buffer_1 (struct buffer *buf,
- ptrdiff_t from, ptrdiff_t nchars,
- int inherit);
-static void gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, int newgap);
-static void gap_right (ptrdiff_t charpos, ptrdiff_t bytepos);
-
-static Lisp_Object Fcombine_after_change_execute (void);
+static void insert_from_string_1 (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t,
+ ptrdiff_t, bool, bool);
+static void insert_from_buffer_1 (struct buffer *, ptrdiff_t, ptrdiff_t, bool);
+static void gap_left (ptrdiff_t, ptrdiff_t, bool);
+static void gap_right (ptrdiff_t, ptrdiff_t);
/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
describing changes which happened while combine_after_change_calls
- was nonzero. We use this to decide how to call them
+ was non-nil. We use this to decide how to call them
once the deferral ends.
In each element.
Lisp_Object Qinhibit_modification_hooks;
static void signal_before_change (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
-\f
-#define CHECK_MARKERS() \
- do \
- { \
- if (check_markers_debug_flag) \
- check_markers (); \
- } \
- while (0)
+
+/* Also used in marker.c to enable expensive marker checks. */
+
+#ifdef MARKER_DEBUG
static void
check_markers (void)
{
- register struct Lisp_Marker *tail;
- int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
+ struct Lisp_Marker *tail;
+ bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
{
if (tail->buffer->text != current_buffer->text)
- abort ();
+ emacs_abort ();
if (tail->charpos > Z)
- abort ();
+ emacs_abort ();
if (tail->bytepos > Z_BYTE)
- abort ();
+ emacs_abort ();
if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
- abort ();
+ emacs_abort ();
}
}
-\f
+
+#else /* not MARKER_DEBUG */
+
+#define check_markers() do { } while (0)
+
+#endif /* MARKER_DEBUG */
+
/* Move gap to position CHARPOS.
Note that this can quit! */
/* Move the gap to a position less than the current GPT.
BYTEPOS describes the new position as a byte position,
and CHARPOS is the corresponding char position.
- If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
+ If NEWGAP, then don't update beg_unchanged and end_unchanged. */
static void
-gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, int newgap)
+gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, bool newgap)
{
- register unsigned char *to, *from;
- register ptrdiff_t i;
+ unsigned char *to, *from;
+ ptrdiff_t i;
ptrdiff_t new_s1;
if (!newgap)
was specified or may be where a quit was detected. */
GPT_BYTE = bytepos;
GPT = charpos;
- if (bytepos < charpos)
- abort ();
+ eassert (charpos <= bytepos);
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
QUIT;
}
GPT = charpos;
GPT_BYTE = bytepos;
- if (bytepos < charpos)
- abort ();
+ eassert (charpos <= bytepos);
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
QUIT;
}
for (m = BUF_MARKERS (current_buffer); m; m = m->next)
{
charpos = m->charpos;
-
- if (charpos > Z)
- abort ();
+ eassert (charpos <= Z);
/* If the marker is after the deletion,
relocate by number of chars / bytes deleted. */
static void
adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
- ptrdiff_t to, ptrdiff_t to_byte, int before_markers)
+ ptrdiff_t to, ptrdiff_t to_byte, bool before_markers)
{
struct Lisp_Marker *m;
- int adjusted = 0;
+ bool adjusted = 0;
ptrdiff_t nchars = to - from;
ptrdiff_t nbytes = to_byte - from_byte;
}
}
- CHECK_MARKERS ();
+ check_markers ();
}
\f
ptrdiff_t
copy_text (const unsigned char *from_addr, unsigned char *to_addr,
- ptrdiff_t nbytes, int from_multibyte, int to_multibyte)
+ ptrdiff_t nbytes, bool from_multibyte, bool to_multibyte)
{
if (from_multibyte == to_multibyte)
{
void
insert_1 (const char *string, ptrdiff_t nbytes,
- int inherit, int prepare, int before_markers)
+ bool inherit, bool prepare, bool before_markers)
{
insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
nbytes, inherit, prepare, before_markers);
void
insert_1_both (const char *string,
ptrdiff_t nchars, ptrdiff_t nbytes,
- int inherit, int prepare, int before_markers)
+ bool inherit, bool prepare, bool before_markers)
{
if (nchars == 0)
return;
#ifdef BYTE_COMBINING_DEBUG
if (count_combining_before (string, nbytes, PT, PT_BYTE)
|| count_combining_after (string, nbytes, PT, PT_BYTE))
- abort ();
+ emacs_abort ();
#endif
/* Record deletion of the surrounding text that combines with
Z_BYTE += nbytes;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
/* The insert may have been in the unchanged region, so check again. */
if (Z - GPT < END_UNCHANGED)
PT + nchars, PT_BYTE + nbytes,
before_markers);
- if (BUF_INTERVALS (current_buffer) != 0)
+ if (buffer_intervals (current_buffer))
offset_intervals (current_buffer, PT, nchars);
- if (!inherit && BUF_INTERVALS (current_buffer) != 0)
+ if (!inherit && buffer_intervals (current_buffer))
set_text_properties (make_number (PT), make_number (PT + nchars),
Qnil, Qnil, Qnil);
adjust_point (nchars, nbytes);
- CHECK_MARKERS ();
+ check_markers ();
}
\f
/* Insert the part of the text of STRING, a Lisp object assumed to be
void
insert_from_string (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
- ptrdiff_t length, ptrdiff_t length_byte, int inherit)
+ ptrdiff_t length, ptrdiff_t length_byte, bool inherit)
{
ptrdiff_t opoint = PT;
insert_from_string_before_markers (Lisp_Object string,
ptrdiff_t pos, ptrdiff_t pos_byte,
ptrdiff_t length, ptrdiff_t length_byte,
- int inherit)
+ bool inherit)
{
ptrdiff_t opoint = PT;
static void
insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
ptrdiff_t nchars, ptrdiff_t nbytes,
- int inherit, int before_markers)
+ bool inherit, bool before_markers)
{
struct gcpro gcpro1;
ptrdiff_t outgoing_nbytes = nbytes;
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
|| count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
- abort ();
+ emacs_abort ();
#endif
record_insert (PT, nchars);
Z_BYTE += outgoing_nbytes;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
/* The insert may have been in the unchanged region, so check again. */
if (Z - GPT < END_UNCHANGED)
offset_intervals (current_buffer, PT, nchars);
- intervals = STRING_INTERVALS (string);
+ intervals = string_intervals (string);
/* Get the intervals for the part of the string we are inserting. */
if (nbytes < SBYTES (string))
intervals = copy_intervals (intervals, pos, nchars);
adjust_point (nchars, outgoing_nbytes);
- CHECK_MARKERS ();
+ check_markers ();
}
\f
/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
Z_BYTE += nbytes;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
adjust_overlays_for_insert (GPT - nchars, nchars);
adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
GPT, GPT_BYTE, 0);
- if (BUF_INTERVALS (current_buffer) != 0)
+ if (buffer_intervals (current_buffer))
{
offset_intervals (current_buffer, GPT - nchars, nchars);
- graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
+ graft_intervals_into_buffer (NULL, GPT - nchars, nchars,
current_buffer, 0);
}
if (GPT - nchars < PT)
adjust_point (nchars, nbytes);
- CHECK_MARKERS ();
+ check_markers ();
}
\f
/* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
void
insert_from_buffer (struct buffer *buf,
- ptrdiff_t charpos, ptrdiff_t nchars, int inherit)
+ ptrdiff_t charpos, ptrdiff_t nchars, bool inherit)
{
ptrdiff_t opoint = PT;
static void
insert_from_buffer_1 (struct buffer *buf,
- ptrdiff_t from, ptrdiff_t nchars, int inherit)
+ ptrdiff_t from, ptrdiff_t nchars, bool inherit)
{
ptrdiff_t chunk, chunk_expanded;
ptrdiff_t from_byte = buf_charpos_to_bytepos (buf, from);
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
|| count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
- abort ();
+ emacs_abort ();
#endif
record_insert (PT, nchars);
Z_BYTE += outgoing_nbytes;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
/* The insert may have been in the unchanged region, so check again. */
if (Z - GPT < END_UNCHANGED)
PT_BYTE + outgoing_nbytes,
0);
- if (BUF_INTERVALS (current_buffer) != 0)
+ if (buffer_intervals (current_buffer))
offset_intervals (current_buffer, PT, nchars);
/* Get the intervals for the part of the string we are inserting. */
- intervals = BUF_INTERVALS (buf);
+ intervals = buffer_intervals (buf);
if (nchars < BUF_Z (buf) - BUF_BEG (buf))
{
if (buf == current_buffer && PT <= from)
#ifdef BYTE_COMBINING_DEBUG
if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
|| count_combining_after (GPT_ADDR, len_byte, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
if (STRINGP (prev_text))
adjust_overlays_for_insert (from, len - nchars_del);
else if (len < nchars_del)
adjust_overlays_for_delete (from, nchars_del - len);
- if (BUF_INTERVALS (current_buffer) != 0)
- {
- offset_intervals (current_buffer, from, len - nchars_del);
- }
+
+ if (buffer_intervals (current_buffer))
+ offset_intervals (current_buffer, from, len - nchars_del);
if (from < PT)
adjust_point (len - nchars_del, len_byte - nbytes_del);
if (Z - GPT < END_UNCHANGED)
END_UNCHANGED = Z - GPT;
- CHECK_MARKERS ();
+ check_markers ();
if (len == 0)
evaporate_overlays (from);
}
\f
/* Replace the text from character positions FROM to TO with NEW,
- If PREPARE is nonzero, call prepare_to_modify_buffer.
+ If PREPARE, call prepare_to_modify_buffer.
If INHERIT, the newly inserted text should inherit text properties
from the surrounding non-deleted text. */
void
replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
- int prepare, int inherit, int markers)
+ bool prepare, bool inherit, bool markers)
{
ptrdiff_t inschars = SCHARS (new);
ptrdiff_t insbytes = SBYTES (new);
ptrdiff_t outgoing_insbytes = insbytes;
Lisp_Object deletion;
- CHECK_MARKERS ();
+ check_markers ();
GCPRO1 (new);
deletion = Qnil;
UNGCPRO;
- /* Make args be valid */
+ /* Make args be valid. */
if (from < BEGV)
from = BEGV;
if (to > ZV)
GPT_BYTE = from_byte;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
if (GPT - BEG < BEG_UNCHANGED)
BEG_UNCHANGED = GPT - BEG;
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
|| count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
if (! EQ (BVAR (current_buffer, undo_list), Qt))
Z_BYTE += outgoing_insbytes;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
/* Adjust the overlay center as needed. This must be done after
adjusting the markers that bound the overlays. */
/* Get the intervals for the part of the string we are inserting--
not including the combined-before bytes. */
- intervals = STRING_INTERVALS (new);
+ intervals = string_intervals (new);
/* Insert those intervals. */
graft_intervals_into_buffer (intervals, from, inschars,
current_buffer, inherit);
if (outgoing_insbytes == 0)
evaporate_overlays (from);
- CHECK_MARKERS ();
+ check_markers ();
MODIFF++;
CHARS_MODIFF = MODIFF;
Note that this does not yet handle markers quite right.
- If MARKERS is nonzero, relocate markers.
+ If MARKERS, relocate markers.
Unlike most functions at this level, never call
prepare_to_modify_buffer and never call signal_after_change. */
replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
ptrdiff_t to, ptrdiff_t to_byte,
const char *ins, ptrdiff_t inschars, ptrdiff_t insbytes,
- int markers)
+ bool markers)
{
ptrdiff_t nbytes_del, nchars_del;
- CHECK_MARKERS ();
+ check_markers ();
nchars_del = to - from;
nbytes_del = to_byte - from_byte;
GPT_BYTE = from_byte;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
if (GPT - BEG < BEG_UNCHANGED)
BEG_UNCHANGED = GPT - BEG;
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
|| count_combining_after (GPT_ADDR, insbytes, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
GAP_SIZE -= insbytes;
Z_BYTE += insbytes;
if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
/* Adjust the overlay center as needed. This must be done after
adjusting the markers that bound the overlays. */
if (insbytes == 0)
evaporate_overlays (from);
- CHECK_MARKERS ();
+ check_markers ();
MODIFF++;
CHARS_MODIFF = MODIFF;
RET_STRING says to return the deleted text. */
Lisp_Object
-del_range_1 (ptrdiff_t from, ptrdiff_t to, int prepare, int ret_string)
+del_range_1 (ptrdiff_t from, ptrdiff_t to, bool prepare, bool ret_string)
{
ptrdiff_t from_byte, to_byte;
Lisp_Object deletion;
/* Like del_range_1 but args are byte positions, not char positions. */
void
-del_range_byte (ptrdiff_t from_byte, ptrdiff_t to_byte, int prepare)
+del_range_byte (ptrdiff_t from_byte, ptrdiff_t to_byte, bool prepare)
{
ptrdiff_t from, to;
void
del_range_both (ptrdiff_t from, ptrdiff_t from_byte,
- ptrdiff_t to, ptrdiff_t to_byte, int prepare)
+ ptrdiff_t to, ptrdiff_t to_byte, bool prepare)
{
/* Make args be valid */
if (from_byte < BEGV_BYTE)
/* Delete a range of text, specified both as character positions
and byte positions. FROM and TO are character positions,
while FROM_BYTE and TO_BYTE are byte positions.
- If RET_STRING is true, the deleted area is returned as a string. */
+ If RET_STRING, the deleted area is returned as a string. */
Lisp_Object
del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
- ptrdiff_t to, ptrdiff_t to_byte, int ret_string)
+ ptrdiff_t to, ptrdiff_t to_byte, bool ret_string)
{
- register ptrdiff_t nbytes_del, nchars_del;
+ ptrdiff_t nbytes_del, nchars_del;
Lisp_Object deletion;
- CHECK_MARKERS ();
+ check_markers ();
nchars_del = to - from;
nbytes_del = to_byte - from_byte;
#ifdef BYTE_COMBINING_DEBUG
if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
Z_BYTE - to_byte, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
needs to access the previous gap contents. */
*(GPT_ADDR) = 0;
- if (GPT_BYTE < GPT)
- abort ();
+ eassert (GPT <= GPT_BYTE);
if (GPT - BEG < BEG_UNCHANGED)
BEG_UNCHANGED = GPT - BEG;
if (Z - GPT < END_UNCHANGED)
END_UNCHANGED = Z - GPT;
- CHECK_MARKERS ();
+ check_markers ();
evaporate_overlays (from);
and warns the next redisplay that it should pay attention to that
area.
- If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
+ If PRESERVE_CHARS_MODIFF, do not update CHARS_MODIFF.
Otherwise set CHARS_MODIFF to the new value of MODIFF. */
void
modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end,
- int preserve_chars_modiff)
+ bool preserve_chars_modiff)
{
struct buffer *old_buffer = current_buffer;
- if (buffer != old_buffer)
- set_buffer_internal (buffer);
+ set_buffer_internal (buffer);
prepare_to_modify_buffer (start, end, NULL);
if (! preserve_chars_modiff)
CHARS_MODIFF = MODIFF;
- BVAR (buffer, point_before_scroll) = Qnil;
+ bset_point_before_scroll (buffer, Qnil);
- if (buffer != old_buffer)
- set_buffer_internal (old_buffer);
+ set_buffer_internal (old_buffer);
}
\f
/* Check that it is okay to modify the buffer between START and END,
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
++windows_or_buffers_changed;
- if (BUF_INTERVALS (current_buffer) != 0)
+ if (buffer_intervals (current_buffer))
{
if (preserve_ptr)
{
XSETCDR (rvoe_arg, Qt);
}
- if (current_buffer->overlays_before || current_buffer->overlays_after)
+ if (buffer_has_overlays ())
{
PRESERVE_VALUE;
report_overlay_modification (FETCH_START, FETCH_END, 0,
just record the args that we were going to use. */
if (! NILP (Vcombine_after_change_calls)
&& NILP (Vbefore_change_functions)
- && !current_buffer->overlays_before
- && !current_buffer->overlays_after)
+ && !buffer_has_overlays ())
{
Lisp_Object elt;
XSETCDR (rvoe_arg, Qt);
}
- if (current_buffer->overlays_before || current_buffer->overlays_after)
+ if (buffer_has_overlays ())
report_overlay_modification (make_number (charpos),
make_number (charpos + lenins),
1,
return Qnil;
}
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ record_unwind_current_buffer ();
Fset_buffer (combine_after_change_buffer);
combine_after_change_list = Qnil;
combine_after_change_buffer = Qnil;
- DEFVAR_BOOL ("check-markers-debug-flag", check_markers_debug_flag,
- doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
- check_markers_debug_flag = 0;
DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
doc: /* Used internally by the `combine-after-change-calls' macro. */);
Vcombine_after_change_calls = Qnil;