diff options
| author | Paul Eggert | 2016-08-05 14:07:00 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-08-05 14:07:00 -0700 |
| commit | 1a86b5d6074d26d1a3a978cb52b2147b6f359694 (patch) | |
| tree | 5b609435fb29b6f62766ddd51d8649013913970e /src | |
| parent | c5823cdae3de078e6db58df25769011ef3e52f36 (diff) | |
| parent | d4c6774f40b6ae1fad091f66e8e43913bc9a2724 (diff) | |
| download | emacs-1a86b5d6074d26d1a3a978cb52b2147b6f359694.tar.gz emacs-1a86b5d6074d26d1a3a978cb52b2147b6f359694.zip | |
Merge from origin/emacs-25
d4c6774 Fix missing point information in undo
3a9d629 Avoid crashes when buffer modification hooks clobber match data
178b2f5 Note combine-and-quote-strings doesn't shell quote
dec7567 Explain when package-initialize isn't called
113d1e2 Fix escaping in sh-indent-after-continuation docstr
80e2044 ; * etc/NEWS: Improve previous change.
5bb9e6c ; * etc/NEWS: Document how to avoid horizontal scroll bars.
38f4b8e Clarify the documentation of back-references in replacements
Diffstat (limited to 'src')
| -rw-r--r-- | src/search.c | 13 | ||||
| -rw-r--r-- | src/undo.c | 56 |
2 files changed, 43 insertions, 26 deletions
diff --git a/src/search.c b/src/search.c index 7f2b4f9840c..7c4a02491db 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -2677,6 +2677,14 @@ since only regular expressions have distinguished subexpressions. */) | |||
| 2677 | xfree (substed); | 2677 | xfree (substed); |
| 2678 | } | 2678 | } |
| 2679 | 2679 | ||
| 2680 | /* The functions below modify the buffer, so they could trigger | ||
| 2681 | various modification hooks (see signal_before_change and | ||
| 2682 | signal_after_change), which might clobber the match data we need | ||
| 2683 | to adjust after the replacement. If that happens, we error out. */ | ||
| 2684 | ptrdiff_t sub_start = search_regs.start[sub]; | ||
| 2685 | ptrdiff_t sub_end = search_regs.end[sub]; | ||
| 2686 | unsigned num_regs = search_regs.num_regs; | ||
| 2687 | |||
| 2680 | /* Replace the old text with the new in the cleanest possible way. */ | 2688 | /* Replace the old text with the new in the cleanest possible way. */ |
| 2681 | replace_range (search_regs.start[sub], search_regs.end[sub], | 2689 | replace_range (search_regs.start[sub], search_regs.end[sub], |
| 2682 | newtext, 1, 0, 1); | 2690 | newtext, 1, 0, 1); |
| @@ -2690,6 +2698,11 @@ since only regular expressions have distinguished subexpressions. */) | |||
| 2690 | Fupcase_initials_region (make_number (search_regs.start[sub]), | 2698 | Fupcase_initials_region (make_number (search_regs.start[sub]), |
| 2691 | make_number (newpoint)); | 2699 | make_number (newpoint)); |
| 2692 | 2700 | ||
| 2701 | if (search_regs.start[sub] != sub_start | ||
| 2702 | || search_regs.end[sub] != sub_end | ||
| 2703 | || search_regs.num_regs != num_regs) | ||
| 2704 | error ("Match data clobbered by buffer modification hooks"); | ||
| 2705 | |||
| 2693 | /* Adjust search data for this change. */ | 2706 | /* Adjust search data for this change. */ |
| 2694 | { | 2707 | { |
| 2695 | ptrdiff_t oldend = search_regs.end[sub]; | 2708 | ptrdiff_t oldend = search_regs.end[sub]; |
diff --git a/src/undo.c b/src/undo.c index be5b2702054..ed69a62844c 100644 --- a/src/undo.c +++ b/src/undo.c | |||
| @@ -31,25 +31,21 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 31 | an undo-boundary. */ | 31 | an undo-boundary. */ |
| 32 | static Lisp_Object pending_boundary; | 32 | static Lisp_Object pending_boundary; |
| 33 | 33 | ||
| 34 | /* Record point as it was at beginning of this command (if necessary) | 34 | /* Prepare the undo info for recording a change. */ |
| 35 | and prepare the undo info for recording a change. | ||
| 36 | Prepare the undo info for recording a change. */ | ||
| 37 | static void | 35 | static void |
| 38 | prepare_record (void) | 36 | prepare_record (void) |
| 39 | { | 37 | { |
| 40 | /* Allocate a cons cell to be the undo boundary after this command. */ | 38 | /* Allocate a cons cell to be the undo boundary after this command. */ |
| 41 | if (NILP (pending_boundary)) | 39 | if (NILP (pending_boundary)) |
| 42 | pending_boundary = Fcons (Qnil, Qnil); | 40 | pending_boundary = Fcons (Qnil, Qnil); |
| 43 | |||
| 44 | if (MODIFF <= SAVE_MODIFF) | ||
| 45 | record_first_change (); | ||
| 46 | } | 41 | } |
| 47 | 42 | ||
| 48 | /* Record point as it was at beginning of this command. | 43 | /* Record point, if necessary, as it was at beginning of this command. |
| 49 | PT is the position of point that will naturally occur as a result of the | 44 | BEG is the position of point that will naturally occur as a result |
| 50 | undo record that will be added just after this command terminates. */ | 45 | of the undo record that will be added just after this command |
| 46 | terminates. */ | ||
| 51 | static void | 47 | static void |
| 52 | record_point (ptrdiff_t pt) | 48 | record_point (ptrdiff_t beg) |
| 53 | { | 49 | { |
| 54 | /* Don't record position of pt when undo_inhibit_record_point holds. */ | 50 | /* Don't record position of pt when undo_inhibit_record_point holds. */ |
| 55 | if (undo_inhibit_record_point) | 51 | if (undo_inhibit_record_point) |
| @@ -57,16 +53,28 @@ record_point (ptrdiff_t pt) | |||
| 57 | 53 | ||
| 58 | bool at_boundary; | 54 | bool at_boundary; |
| 59 | 55 | ||
| 56 | /* Check whether we are at a boundary now, in case we record the | ||
| 57 | first change. FIXME: This check is currently dependent on being | ||
| 58 | called before record_first_change, but could be made not to by | ||
| 59 | ignoring timestamp undo entries */ | ||
| 60 | at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) | 60 | at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) |
| 61 | || NILP (XCAR (BVAR (current_buffer, undo_list))); | 61 | || NILP (XCAR (BVAR (current_buffer, undo_list))); |
| 62 | 62 | ||
| 63 | prepare_record (); | 63 | /* If this is the first change since save, then record this.*/ |
| 64 | if (MODIFF <= SAVE_MODIFF) | ||
| 65 | record_first_change (); | ||
| 64 | 66 | ||
| 65 | /* If we are just after an undo boundary, and | 67 | /* We may need to record point if we are immediately after a |
| 66 | point wasn't at start of deleted range, record where it was. */ | 68 | boundary, so that this will be restored correctly after undo. We |
| 67 | if (at_boundary) | 69 | do not need to do this if point is at the start of a change |
| 70 | region since it will be restored there anyway, and we must not do | ||
| 71 | this if the buffer has changed since the last command, since the | ||
| 72 | value of point that we have will be for that buffer, not this.*/ | ||
| 73 | if (at_boundary | ||
| 74 | && point_before_last_command_or_undo != beg | ||
| 75 | && buffer_before_last_command_or_undo == current_buffer ) | ||
| 68 | bset_undo_list (current_buffer, | 76 | bset_undo_list (current_buffer, |
| 69 | Fcons (make_number (pt), | 77 | Fcons (make_number (point_before_last_command_or_undo), |
| 70 | BVAR (current_buffer, undo_list))); | 78 | BVAR (current_buffer, undo_list))); |
| 71 | } | 79 | } |
| 72 | 80 | ||
| @@ -85,6 +93,8 @@ record_insert (ptrdiff_t beg, ptrdiff_t length) | |||
| 85 | 93 | ||
| 86 | prepare_record (); | 94 | prepare_record (); |
| 87 | 95 | ||
| 96 | record_point (beg); | ||
| 97 | |||
| 88 | /* If this is following another insertion and consecutive with it | 98 | /* If this is following another insertion and consecutive with it |
| 89 | in the buffer, combine the two. */ | 99 | in the buffer, combine the two. */ |
| 90 | if (CONSP (BVAR (current_buffer, undo_list))) | 100 | if (CONSP (BVAR (current_buffer, undo_list))) |
| @@ -120,9 +130,7 @@ record_marker_adjustments (ptrdiff_t from, ptrdiff_t to) | |||
| 120 | register struct Lisp_Marker *m; | 130 | register struct Lisp_Marker *m; |
| 121 | register ptrdiff_t charpos, adjustment; | 131 | register ptrdiff_t charpos, adjustment; |
| 122 | 132 | ||
| 123 | /* Allocate a cons cell to be the undo boundary after this command. */ | 133 | prepare_record(); |
| 124 | if (NILP (pending_boundary)) | ||
| 125 | pending_boundary = Fcons (Qnil, Qnil); | ||
| 126 | 134 | ||
| 127 | for (m = BUF_MARKERS (current_buffer); m; m = m->next) | 135 | for (m = BUF_MARKERS (current_buffer); m; m = m->next) |
| 128 | { | 136 | { |
| @@ -163,19 +171,17 @@ record_delete (ptrdiff_t beg, Lisp_Object string, bool record_markers) | |||
| 163 | if (EQ (BVAR (current_buffer, undo_list), Qt)) | 171 | if (EQ (BVAR (current_buffer, undo_list), Qt)) |
| 164 | return; | 172 | return; |
| 165 | 173 | ||
| 166 | if (point_before_last_command_or_undo != beg | 174 | prepare_record (); |
| 167 | && buffer_before_last_command_or_undo == current_buffer) | 175 | |
| 168 | record_point (point_before_last_command_or_undo); | 176 | record_point (beg); |
| 169 | 177 | ||
| 170 | if (PT == beg + SCHARS (string)) | 178 | if (PT == beg + SCHARS (string)) |
| 171 | { | 179 | { |
| 172 | XSETINT (sbeg, -beg); | 180 | XSETINT (sbeg, -beg); |
| 173 | prepare_record (); | ||
| 174 | } | 181 | } |
| 175 | else | 182 | else |
| 176 | { | 183 | { |
| 177 | XSETFASTINT (sbeg, beg); | 184 | XSETFASTINT (sbeg, beg); |
| 178 | prepare_record (); | ||
| 179 | } | 185 | } |
| 180 | 186 | ||
| 181 | /* primitive-undo assumes marker adjustments are recorded | 187 | /* primitive-undo assumes marker adjustments are recorded |
| @@ -234,9 +240,7 @@ record_property_change (ptrdiff_t beg, ptrdiff_t length, | |||
| 234 | if (EQ (BVAR (buf, undo_list), Qt)) | 240 | if (EQ (BVAR (buf, undo_list), Qt)) |
| 235 | return; | 241 | return; |
| 236 | 242 | ||
| 237 | /* Allocate a cons cell to be the undo boundary after this command. */ | 243 | prepare_record(); |
| 238 | if (NILP (pending_boundary)) | ||
| 239 | pending_boundary = Fcons (Qnil, Qnil); | ||
| 240 | 244 | ||
| 241 | if (MODIFF <= SAVE_MODIFF) | 245 | if (MODIFF <= SAVE_MODIFF) |
| 242 | record_first_change (); | 246 | record_first_change (); |