#include "lisp.h"
#include "intervals.h"
#include "buffer.h"
+#include "charset.h"
#include "window.h"
#include "blockinput.h"
static void adjust_markers ();
static void adjust_point ();
+Lisp_Object Fcombine_after_change_execute ();
+
+/* Non-nil means don't call the after-change-functions right away,
+ just record an element in Vcombine_after_change_calls_list. */
+Lisp_Object Vcombine_after_change_calls;
+
+/* 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
+ once the deferral ends.
+
+ In each element.
+ BEG-UNCHANGED is the number of chars before the changed range.
+ END-UNCHANGED is the number of chars after the changed range,
+ and CHANGE-AMOUNT is the number of characters inserted by the change
+ (negative for a deletion). */
+Lisp_Object combine_after_change_list;
+
+/* Buffer which combine_after_change_list is about. */
+Lisp_Object combine_after_change_buffer;
+
/* Move gap to position `pos'.
Note that this can quit! */
if (!newgap)
{
- if (unchanged_modified == MODIFF)
+ if (unchanged_modified == MODIFF
+ && overlay_unchanged_modified == OVERLAY_MODIFF)
{
beg_unchanged = pos;
end_unchanged = Z - pos - 1;
or may be where a quit was detected. */
adjust_markers (pos + 1, GPT, GAP_SIZE);
GPT = pos + 1;
+ if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
QUIT;
}
pos--;
- if (unchanged_modified == MODIFF)
+ if (unchanged_modified == MODIFF
+ && overlay_unchanged_modified == OVERLAY_MODIFF)
+
{
beg_unchanged = pos;
end_unchanged = Z - pos - 1;
adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
GPT = pos + 1;
+ if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
QUIT;
}
but then this range contains no markers. */
if (mpos > from + amount && mpos <= from)
{
- record_marker_adjustment (marker, from + amount - mpos);
- mpos = from + amount;
+ int before = mpos;
+ int after = from + amount;
+
+ mpos = after;
+
+ /* Compute the before and after positions
+ as buffer positions. */
+ if (before > GPT + GAP_SIZE)
+ before -= GAP_SIZE;
+ else if (before > GPT)
+ before = GPT;
+
+ if (after > GPT + GAP_SIZE)
+ after -= GAP_SIZE;
+ else if (after > GPT)
+ after = GPT;
+
+ record_marker_adjustment (marker, after - before);
}
}
if (mpos > from && mpos <= to)
register int pos, amount;
{
Lisp_Object marker;
+ int adjusted = 0;
marker = BUF_MARKERS (current_buffer);
{
register struct Lisp_Marker *m = XMARKER (marker);
if (m->insertion_type && m->bufpos == pos)
- m->bufpos += amount;
+ {
+ m->bufpos += amount;
+ adjusted = 1;
+ }
marker = m->chain;
}
+ if (adjusted)
+ /* Adjusting only markers whose insertion-type is t may result in
+ disordered overlays in the slot `overlays_before'. */
+ fix_overlays_before (current_buffer, pos, pos + amount);
}
/* Add the specified amount to point. This is used only when the value
error ("Buffer exceeds maximum size");
BLOCK_INPUT;
- result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
+ /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
+ result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment + 1));
if (result == 0)
{
GAP_SIZE += old_gap_size;
GPT = real_gap_loc;
+ /* Put an anchor. */
+ *(Z_ADDR) = 0;
+
Vinhibit_quit = tem;
}
\f
GPT += length;
ZV += length;
Z += length;
+ if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
adjust_overlays_for_insert (PT, length);
adjust_markers_for_insert (PT, length);
adjust_point (length);
GPT += length;
ZV += length;
Z += length;
+ if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
adjust_overlays_for_insert (PT, length);
adjust_markers_for_insert (PT, length);
GPT += length;
ZV += length;
Z += length;
+ if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
adjust_overlays_for_insert (PT, length);
adjust_markers_for_insert (PT, length);
adjust_point (length);
void
insert_char (c)
- unsigned char c;
+ int c;
{
- insert (&c, 1);
+ unsigned char workbuf[4], *str;
+ int len = CHAR_STRING (c, workbuf, str);
+
+ insert (str, len);
}
/* Insert the null-terminated string S before point */
ZV -= numdel;
Z -= numdel;
GPT = from;
+ *(GPT_ADDR) = 0; /* Put an anchor. */
if (GPT - BEG < beg_unchanged)
beg_unchanged = GPT - BEG;
prepare_to_modify_buffer (start, end);
- if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
+ if (start - 1 < beg_unchanged
+ || (unchanged_modified == MODIFF
+ && overlay_unchanged_modified == OVERLAY_MODIFF))
beg_unchanged = start - 1;
if (Z - end < end_unchanged
- || unchanged_modified == MODIFF)
+ || (unchanged_modified == MODIFF
+ && overlay_unchanged_modified == OVERLAY_MODIFF))
end_unchanged = Z - end;
if (MODIFF <= SAVE_MODIFF)
signal_after_change (pos, lendel, lenins)
int pos, lendel, lenins;
{
+ /* If we are deferring calls to the after-change functions
+ and there are no before-change functions,
+ just record the args that we were going to use. */
+ if (! NILP (Vcombine_after_change_calls)
+ && NILP (Vbefore_change_function) && NILP (Vbefore_change_functions)
+ && NILP (current_buffer->overlays_before)
+ && NILP (current_buffer->overlays_after))
+ {
+ Lisp_Object elt;
+
+ if (!NILP (combine_after_change_list)
+ && current_buffer != XBUFFER (combine_after_change_buffer))
+ Fcombine_after_change_execute ();
+
+ elt = Fcons (make_number (pos - BEG),
+ Fcons (make_number (Z - (pos - lendel + lenins)),
+ Fcons (make_number (lenins - lendel), Qnil)));
+ combine_after_change_list
+ = Fcons (elt, combine_after_change_list);
+ combine_after_change_buffer = Fcurrent_buffer ();
+
+ return;
+ }
+
+ if (!NILP (combine_after_change_list))
+ Fcombine_after_change_execute ();
+
/* Run the after-change-function if any.
We don't bother "binding" this variable to nil
because it is obsolete anyway and new code should not use it. */
if (lendel == 0)
report_interval_modification (pos, pos + lenins);
}
+
+Lisp_Object
+Fcombine_after_change_execute_1 (val)
+ Lisp_Object val;
+{
+ Vcombine_after_change_calls = val;
+ return val;
+}
+
+DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
+ Scombine_after_change_execute, 0, 0, 0,
+ "This function is for use internally in `combine-after-change-calls'.")
+ ()
+{
+ register Lisp_Object val;
+ int count = specpdl_ptr - specpdl;
+ int beg, end, change;
+ int begpos, endpos;
+ Lisp_Object tail;
+
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
+ Fset_buffer (combine_after_change_buffer);
+
+ /* # chars unchanged at beginning of buffer. */
+ beg = Z - BEG;
+ /* # chars unchanged at end of buffer. */
+ end = beg;
+ /* Total amount of insertion (negative for deletion). */
+ change = 0;
+
+ /* Scan the various individual changes,
+ accumulating the range info in BEG, END and CHANGE. */
+ for (tail = combine_after_change_list; CONSP (tail);
+ tail = XCONS (tail)->cdr)
+ {
+ Lisp_Object elt;
+ int thisbeg, thisend, thischange;
+
+ /* Extract the info from the next element. */
+ elt = XCONS (tail)->car;
+ if (! CONSP (elt))
+ continue;
+ thisbeg = XINT (XCONS (elt)->car);
+
+ elt = XCONS (elt)->cdr;
+ if (! CONSP (elt))
+ continue;
+ thisend = XINT (XCONS (elt)->car);
+
+ elt = XCONS (elt)->cdr;
+ if (! CONSP (elt))
+ continue;
+ thischange = XINT (XCONS (elt)->car);
+
+ /* Merge this range into the accumulated range. */
+ change += thischange;
+ if (thisbeg < beg)
+ beg = thisbeg;
+ if (thisend < end)
+ end = thisend;
+ }
+
+ /* Get the current start and end positions of the range
+ that was changed. */
+ begpos = BEG + beg;
+ endpos = Z - end;
+
+ /* We are about to handle these, so discard them. */
+ combine_after_change_list = Qnil;
+
+ /* Now run the after-change functions for real.
+ Turn off the flag that defers them. */
+ record_unwind_protect (Fcombine_after_change_execute_1,
+ Vcombine_after_change_calls);
+ signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
+
+ return unbind_to (count, val);
+}
+\f
+syms_of_insdel ()
+{
+ staticpro (&combine_after_change_list);
+ combine_after_change_list = Qnil;
+
+ DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
+ "Used internally by the `combine-after-change-calls' macro.");
+ Vcombine_after_change_calls = Qnil;
+
+ defsubr (&Scombine_after_change_execute);
+}