aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-08-05 14:07:00 -0700
committerPaul Eggert2016-08-05 14:07:00 -0700
commit1a86b5d6074d26d1a3a978cb52b2147b6f359694 (patch)
tree5b609435fb29b6f62766ddd51d8649013913970e /src
parentc5823cdae3de078e6db58df25769011ef3e52f36 (diff)
parentd4c6774f40b6ae1fad091f66e8e43913bc9a2724 (diff)
downloademacs-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.c13
-rw-r--r--src/undo.c56
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. */
32static Lisp_Object pending_boundary; 32static 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. */
37static void 35static void
38prepare_record (void) 36prepare_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. */
51static void 47static void
52record_point (ptrdiff_t pt) 48record_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 ();