X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d16fb740912bf4874e7087f6f419427516047977..50650cb6887d99b01eeb1e686fc1f695c2a0c64a:/src/insdel.c diff --git a/src/insdel.c b/src/insdel.c index 80650be25a..4ad1074f5f 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1,13 +1,13 @@ /* Buffer insertion/deletion and gap motion for GNU Emacs. - Copyright (C) 1985-1986, 1993-1995, 1997-2015 Free Software + Copyright (C) 1985-1986, 1993-1995, 1997-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,11 +23,11 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#include "composite.h" #include "intervals.h" #include "character.h" #include "buffer.h" #include "window.h" -#include "blockinput.h" #include "region-cache.h" static void insert_from_string_1 (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t, @@ -126,7 +126,10 @@ gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, bool newgap) if (i == 0) break; /* If a quit is requested, stop copying now. - Change BYTEPOS to be where we have actually moved the gap to. */ + Change BYTEPOS to be where we have actually moved the gap to. + Note that this cannot happen when we are called to make the + gap larger or smaller, since make_gap_larger and + make_gap_smaller prevent QUIT by setting inhibit-quit. */ if (QUITP) { bytepos = new_s1; @@ -179,7 +182,10 @@ gap_right (ptrdiff_t charpos, ptrdiff_t bytepos) if (i == 0) break; /* If a quit is requested, stop copying now. - Change BYTEPOS to be where we have actually moved the gap to. */ + Change BYTEPOS to be where we have actually moved the gap to. + Note that this cannot happen when we are called to make the + gap larger or smaller, since make_gap_larger and + make_gap_smaller prevent QUIT by setting inhibit-quit. */ if (QUITP) { bytepos = new_s1; @@ -386,7 +392,9 @@ make_gap_larger (ptrdiff_t nbytes_added) enlarge_buffer_text (current_buffer, nbytes_added); - /* Prevent quitting in move_gap. */ + /* Prevent quitting in gap_left. We cannot allow a QUIT there, + because that would leave the buffer text in an inconsistent + state, with 2 gap holes instead of just one. */ tem = Vinhibit_quit; Vinhibit_quit = Qt; @@ -432,7 +440,9 @@ make_gap_smaller (ptrdiff_t nbytes_removed) if (GAP_SIZE - nbytes_removed < GAP_BYTES_MIN) nbytes_removed = GAP_SIZE - GAP_BYTES_MIN; - /* Prevent quitting in move_gap. */ + /* Prevent quitting in gap_right. We cannot allow a QUIT there, + because that would leave the buffer text in an inconsistent + state, with 2 gap holes instead of just one. */ tem = Vinhibit_quit; Vinhibit_quit = Qt; @@ -892,7 +902,6 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t nchars, ptrdiff_t nbytes, bool inherit, bool before_markers) { - struct gcpro gcpro1; ptrdiff_t outgoing_nbytes = nbytes; INTERVAL intervals; @@ -906,7 +915,6 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, = count_size_as_multibyte (SDATA (string) + pos_byte, nbytes); - GCPRO1 (string); /* Do this before moving and increasing the gap, because the before-change hooks might move the gap or make it smaller. */ @@ -916,7 +924,6 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, move_gap_both (PT, PT_BYTE); if (GAP_SIZE < outgoing_nbytes) make_gap (outgoing_nbytes - GAP_SIZE); - UNGCPRO; /* Copy the string text into the buffer, perhaps converting between single-byte and multibyte. */ @@ -1278,14 +1285,12 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, ptrdiff_t insbytes = SBYTES (new); ptrdiff_t from_byte, to_byte; ptrdiff_t nbytes_del, nchars_del; - struct gcpro gcpro1; INTERVAL intervals; ptrdiff_t outgoing_insbytes = insbytes; Lisp_Object deletion; check_markers (); - GCPRO1 (new); deletion = Qnil; if (prepare) @@ -1295,8 +1300,6 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, to = from + range_length; } - UNGCPRO; - /* Make args be valid. */ if (from < BEGV) from = BEGV; @@ -1321,8 +1324,6 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, outgoing_insbytes = count_size_as_multibyte (SDATA (new), insbytes); - GCPRO1 (new); - /* Make sure the gap is somewhere in or next to what we are deleting. */ if (from > GPT) gap_right (from, from_byte); @@ -1424,7 +1425,6 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, MODIFF++; CHARS_MODIFF = MODIFF; - UNGCPRO; signal_after_change (from, nchars_del, GPT - from); update_compositions (from, GPT, CHECK_BORDER); @@ -1561,7 +1561,6 @@ del_range_1 (ptrdiff_t from, ptrdiff_t to, bool prepare, bool ret_string) { ptrdiff_t from_byte, to_byte; Lisp_Object deletion; - struct gcpro gcpro1; /* Make args be valid */ if (from < BEGV) @@ -1583,10 +1582,8 @@ del_range_1 (ptrdiff_t from, ptrdiff_t to, bool prepare, bool ret_string) to_byte = CHAR_TO_BYTE (to); deletion = del_range_2 (from, from_byte, to, to_byte, ret_string); - GCPRO1 (deletion); signal_after_change (from, to - from, 0); update_compositions (from, from, CHECK_HEAD); - UNGCPRO; return deletion; } @@ -1778,6 +1775,18 @@ modify_text (ptrdiff_t start, ptrdiff_t end) bset_point_before_scroll (current_buffer, Qnil); } +/* Signal that we are about to make a change that may result in new + undo information. + */ +static void +run_undoable_change (void) +{ + if (EQ (BVAR (current_buffer, undo_list), Qt)) + return; + + call0 (Qundo_auto__undoable_change); +} + /* Check that it is okay to modify the buffer between START and END, which are char positions. @@ -1786,7 +1795,12 @@ modify_text (ptrdiff_t start, ptrdiff_t end) any modification properties the text may have. If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR - by holding its value temporarily in a marker. */ + by holding its value temporarily in a marker. + + This function runs Lisp, which means it can GC, which means it can + compact buffers, including the current buffer being worked on here. + So don't you dare calling this function while manipulating the gap, + or during some other similar "critical section". */ void prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, @@ -1799,6 +1813,8 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, if (!NILP (BVAR (current_buffer, read_only))) Fbarf_if_buffer_read_only (temp); + run_undoable_change(); + bset_redisplay (current_buffer); if (buffer_intervals (current_buffer)) @@ -1806,13 +1822,10 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, if (preserve_ptr) { Lisp_Object preserve_marker; - struct gcpro gcpro1; preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil); - GCPRO1 (preserve_marker); verify_interval_modification (current_buffer, start, end); *preserve_ptr = marker_position (preserve_marker); unchain_marker (XMARKER (preserve_marker)); - UNGCPRO; } else verify_interval_modification (current_buffer, start, end); @@ -1846,7 +1859,7 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, = call1 (Fsymbol_value (Qregion_extract_function), Qnil); signal_before_change (start, end, preserve_ptr); - Vdeactivate_mark = Qt; + Fset (Qdeactivate_mark, Qt); } /* Like above, but called when we know that the buffer text @@ -1970,7 +1983,6 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, Lisp_Object start, end; Lisp_Object start_marker, end_marker; Lisp_Object preserve_marker; - struct gcpro gcpro1, gcpro2, gcpro3; ptrdiff_t count = SPECPDL_INDEX (); struct rvoe_arg rvoe_arg; @@ -1979,7 +1991,6 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, preserve_marker = Qnil; start_marker = Qnil; end_marker = Qnil; - GCPRO3 (preserve_marker, start_marker, end_marker); specbind (Qinhibit_modification_hooks, Qt); @@ -2025,7 +2036,6 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, if (! NILP (end_marker)) free_marker (end_marker); RESTORE_VALUE; - UNGCPRO; unbind_to (count, Qnil); } @@ -2206,6 +2216,8 @@ syms_of_insdel (void) combine_after_change_list = Qnil; combine_after_change_buffer = Qnil; + DEFSYM (Qundo_auto__undoable_change, "undo-auto--undoable-change"); + DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls, doc: /* Used internally by the function `combine-after-change-calls' macro. */); Vcombine_after_change_calls = Qnil;