From 00012b86257f33dd4e08e79b814f4a7ad6010713 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 6 Aug 2013 09:30:18 +0400 Subject: [PATCH] Invalidate region caches only if buffer text is going to be changed. * lisp.h (modify_region_1): Remove 3rd arg and rename to... (modify_text): ...new prototype. (prepare_to_modify_buffer_1): New prototype. * textprop.c (modify_region): Rename to... (modify_text_properties): ...new function. (add_text_properties_1, set_text_properties, Fremove_text_properties) (Fremove_list_of_text_properties): Adjust users. * insdel.c (modify_region_1): Remove 3rd arg and reimplement as... (modify_text): ...new function. (prepare_to_modify_buffer): Reimplement mostly as a wrapper for... (prepare_to_modify_buffer_1): ...new function. * casefiddle.c (casify_region): * editfns.c (Fsubst_char_in_region, Ftranslate_region_internal) (Ftranspose_regions): Use modify_text. --- src/ChangeLog | 18 ++++++++++++++++++ src/casefiddle.c | 2 +- src/editfns.c | 14 +++++++------- src/insdel.c | 32 ++++++++++++++++++-------------- src/lisp.h | 3 ++- src/textprop.c | 41 ++++++++++++++++++++++++++--------------- 6 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 35b5c1cfe5c..7b7d9b56cb5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2013-08-06 Dmitry Antipov + + Invalidate region caches only if buffer text is going to be changed. + * lisp.h (modify_region_1): Remove 3rd arg and rename to... + (modify_text): ...new prototype. + (prepare_to_modify_buffer_1): New prototype. + * textprop.c (modify_region): Rename to... + (modify_text_properties): ...new function. + (add_text_properties_1, set_text_properties, Fremove_text_properties) + (Fremove_list_of_text_properties): Adjust users. + * insdel.c (modify_region_1): Remove 3rd arg and reimplement as... + (modify_text): ...new function. + (prepare_to_modify_buffer): Reimplement mostly as a wrapper for... + (prepare_to_modify_buffer_1): ...new function. + * casefiddle.c (casify_region): + * editfns.c (Fsubst_char_in_region, Ftranslate_region_internal) + (Ftranspose_regions): Use modify_text. + 2013-08-05 Stefan Monnier * lisp.mk (lisp): Add nadvice.elc. diff --git a/src/casefiddle.c b/src/casefiddle.c index 7f5b99752fa..5a40790f87f 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c @@ -214,7 +214,7 @@ casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e) validate_region (&b, &e); start = XFASTINT (b); end = XFASTINT (e); - modify_region_1 (start, end, false); + modify_text (start, end); record_change (start, end - start); start_byte = CHAR_TO_BYTE (start); diff --git a/src/editfns.c b/src/editfns.c index 50bde90788d..90346a88eb2 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2928,7 +2928,7 @@ Both characters must have the same length of multi-byte form. */) else if (!changed) { changed = -1; - modify_region_1 (pos, XINT (end), false); + modify_text (pos, XINT (end)); if (! NILP (noundo)) { @@ -3104,7 +3104,7 @@ It returns the number of characters changed. */) pos = XINT (start); pos_byte = CHAR_TO_BYTE (pos); end_pos = XINT (end); - modify_region_1 (pos, end_pos, false); + modify_text (pos, end_pos); cnt = 0; for (; pos < end_pos; ) @@ -4615,7 +4615,7 @@ Transposing beyond buffer boundaries is an error. */) if (end1 == start2) /* adjacent regions */ { - modify_region_1 (start1, end2, false); + modify_text (start1, end2); record_change (start1, len1 + len2); tmp_interval1 = copy_intervals (cur_intv, start1, len1); @@ -4674,8 +4674,8 @@ Transposing beyond buffer boundaries is an error. */) { USE_SAFE_ALLOCA; - modify_region_1 (start1, end1, false); - modify_region_1 (start2, end2, false); + modify_text (start1, end1); + modify_text (start2, end2); record_change (start1, len1); record_change (start2, len2); tmp_interval1 = copy_intervals (cur_intv, start1, len1); @@ -4708,7 +4708,7 @@ Transposing beyond buffer boundaries is an error. */) { USE_SAFE_ALLOCA; - modify_region_1 (start1, end2, false); + modify_text (start1, end2); record_change (start1, (end2 - start1)); tmp_interval1 = copy_intervals (cur_intv, start1, len1); tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid); @@ -4741,7 +4741,7 @@ Transposing beyond buffer boundaries is an error. */) USE_SAFE_ALLOCA; record_change (start1, (end2 - start1)); - modify_region_1 (start1, end2, false); + modify_text (start1, end2); tmp_interval1 = copy_intervals (cur_intv, start1, len1); tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid); diff --git a/src/insdel.c b/src/insdel.c index 58c3e15c233..ac64299a997 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1756,27 +1756,22 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, return deletion; } -/* Call this if you're about to change the region of current buffer +/* Call this if you're about to change the text of current buffer from character positions START to END. This checks the read-only properties of the region, calls the necessary modification hooks, and warns the next redisplay that it should pay attention to that - area. - - If PRESERVE_CHARS_MODIFF, do not update CHARS_MODIFF. - Otherwise set CHARS_MODIFF to the new value of MODIFF. */ + area. */ void -modify_region_1 (ptrdiff_t start, ptrdiff_t end, bool preserve_chars_modiff) +modify_text (ptrdiff_t start, ptrdiff_t end) { prepare_to_modify_buffer (start, end, NULL); BUF_COMPUTE_UNCHANGED (current_buffer, start - 1, end); - if (MODIFF <= SAVE_MODIFF) record_first_change (); MODIFF++; - if (! preserve_chars_modiff) - CHARS_MODIFF = MODIFF; + CHARS_MODIFF = MODIFF; bset_point_before_scroll (current_buffer, Qnil); } @@ -1792,8 +1787,8 @@ modify_region_1 (ptrdiff_t start, ptrdiff_t end, bool preserve_chars_modiff) by holding its value temporarily in a marker. */ void -prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end, - ptrdiff_t *preserve_ptr) +prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, + ptrdiff_t *preserve_ptr) { struct buffer *base_buffer; @@ -1864,6 +1859,17 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end, } signal_before_change (start, end, preserve_ptr); + Vdeactivate_mark = Qt; +} + +/* Like above, but called when we know that the buffer text + will be modified and region caches should be invalidated. */ + +void +prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end, + ptrdiff_t *preserve_ptr) +{ + prepare_to_modify_buffer_1 (start, end, preserve_ptr); if (current_buffer->newline_cache) invalidate_region_cache (current_buffer, @@ -1873,10 +1879,8 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end, invalidate_region_cache (current_buffer, current_buffer->width_run_cache, start - BEG, Z - end); - - Vdeactivate_mark = Qt; } - + /* These macros work with an argument named `preserve_ptr' and a local variable named `preserve_marker'. */ diff --git a/src/lisp.h b/src/lisp.h index 085acb54348..8ca6d05a821 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3370,8 +3370,9 @@ extern void del_range_byte (ptrdiff_t, ptrdiff_t, bool); extern void del_range_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool); extern Lisp_Object del_range_2 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool); -extern void modify_region_1 (ptrdiff_t, ptrdiff_t, bool); +extern void modify_text (ptrdiff_t, ptrdiff_t); extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *); +extern void prepare_to_modify_buffer_1 (ptrdiff_t, ptrdiff_t, ptrdiff_t *); extern void signal_after_change (ptrdiff_t, ptrdiff_t, ptrdiff_t); extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); diff --git a/src/textprop.c b/src/textprop.c index 282ae11d4ac..b804f345047 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -93,15 +93,25 @@ text_read_only (Lisp_Object propval) xsignal0 (Qtext_read_only); } -/* Prepare to modify the region of BUFFER from START to END. */ +/* Prepare to modify the text properties of BUFFER from START to END. */ static void -modify_region (Lisp_Object buffer, Lisp_Object start, Lisp_Object end) +modify_text_properties (Lisp_Object buffer, Lisp_Object start, Lisp_Object end) { + ptrdiff_t b = XINT (start), e = XINT (end); struct buffer *buf = XBUFFER (buffer), *old = current_buffer; set_buffer_internal (buf); - modify_region_1 (XINT (start), XINT (end), true); + + prepare_to_modify_buffer_1 (b, e, NULL); + + BUF_COMPUTE_UNCHANGED (buf, b - 1, e); + if (MODIFF <= SAVE_MODIFF) + record_first_change (); + MODIFF++; + + bset_point_before_scroll (current_buffer, Qnil); + set_buffer_internal (old); } @@ -1213,9 +1223,9 @@ add_text_properties_1 (Lisp_Object start, Lisp_Object end, ptrdiff_t prev_total_length = TOTAL_LENGTH (i); ptrdiff_t prev_pos = i->position; - modify_region (object, start, end); + modify_text_properties (object, start, end); /* If someone called us recursively as a side effect of - modify_region, and changed the intervals behind our back + modify_text_properties, and changed the intervals behind our back (could happen if lock_file, called by prepare_to_modify_buffer, triggers redisplay, and that calls add-text-properties again in the same buffer), we cannot continue with I, because its @@ -1357,7 +1367,8 @@ into it. */) otherwise. */ Lisp_Object -set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object, Lisp_Object coherent_change_p) +set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties, + Lisp_Object object, Lisp_Object coherent_change_p) { register INTERVAL i; Lisp_Object ostart, oend; @@ -1403,7 +1414,7 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties, } if (BUFFERP (object) && !NILP (coherent_change_p)) - modify_region (object, start, end); + modify_text_properties (object, start, end); set_text_properties_1 (start, end, properties, object, i); @@ -1558,9 +1569,9 @@ Use `set-text-properties' if you want to remove all text properties. */) ptrdiff_t prev_total_length = TOTAL_LENGTH (i); ptrdiff_t prev_pos = i->position; - modify_region (object, start, end); + modify_text_properties (object, start, end); /* If someone called us recursively as a side effect of - modify_region, and changed the intervals behind our back + modify_text_properties, and changed the intervals behind our back (could happen if lock_file, called by prepare_to_modify_buffer, triggers redisplay, and that calls add-text-properties again in the same buffer), we cannot continue with I, because its @@ -1667,9 +1678,9 @@ Return t if any property was actually removed, nil otherwise. */) /* We are at the beginning of an interval, with len to scan. The flag `modified' records if changes have been made. - When object is a buffer, we must call modify_region before changes are - made and signal_after_change when we are done. - We call modify_region before calling remove_properties if modified == 0, + When object is a buffer, we must call modify_text_properties + before changes are made and signal_after_change when we are done. + We call modify_text_properties before calling remove_properties if modified == 0, and we call signal_after_change before returning if modified != 0. */ for (;;) { @@ -1693,7 +1704,7 @@ Return t if any property was actually removed, nil otherwise. */) else if (LENGTH (i) == len) { if (!modified && BUFFERP (object)) - modify_region (object, start, end); + modify_text_properties (object, start, end); remove_properties (Qnil, properties, i, object); if (BUFFERP (object)) signal_after_change (XINT (start), XINT (end) - XINT (start), @@ -1706,7 +1717,7 @@ Return t if any property was actually removed, nil otherwise. */) i = split_interval_left (i, len); copy_properties (unchanged, i); if (!modified && BUFFERP (object)) - modify_region (object, start, end); + modify_text_properties (object, start, end); remove_properties (Qnil, properties, i, object); if (BUFFERP (object)) signal_after_change (XINT (start), XINT (end) - XINT (start), @@ -1717,7 +1728,7 @@ Return t if any property was actually removed, nil otherwise. */) if (interval_has_some_properties_list (properties, i)) { if (!modified && BUFFERP (object)) - modify_region (object, start, end); + modify_text_properties (object, start, end); remove_properties (Qnil, properties, i, object); modified = 1; } -- 2.11.4.GIT