aboutsummaryrefslogtreecommitdiffstats
path: root/src/undo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/undo.c')
-rw-r--r--src/undo.c108
1 files changed, 68 insertions, 40 deletions
diff --git a/src/undo.c b/src/undo.c
index 7e121e8b27d..e878ef4dcf9 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -1,5 +1,5 @@
1/* undo handling for GNU Emacs. 1/* undo handling for GNU Emacs.
2 Copyright (C) 1990, 1993-1994, 2000-2011 Free Software Foundation, Inc. 2 Copyright (C) 1990, 1993-1994, 2000-2012 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -18,8 +18,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18 18
19 19
20#include <config.h> 20#include <config.h>
21#include <setjmp.h> 21
22#include "lisp.h" 22#include "lisp.h"
23#include "character.h"
23#include "buffer.h" 24#include "buffer.h"
24#include "commands.h" 25#include "commands.h"
25#include "window.h" 26#include "window.h"
@@ -30,7 +31,7 @@ static struct buffer *last_undo_buffer;
30 31
31/* Position of point last time we inserted a boundary. */ 32/* Position of point last time we inserted a boundary. */
32static struct buffer *last_boundary_buffer; 33static struct buffer *last_boundary_buffer;
33static EMACS_INT last_boundary_position; 34static ptrdiff_t last_boundary_position;
34 35
35Lisp_Object Qinhibit_read_only; 36Lisp_Object Qinhibit_read_only;
36 37
@@ -51,7 +52,7 @@ static Lisp_Object pending_boundary;
51 undo record that will be added just after this command terminates. */ 52 undo record that will be added just after this command terminates. */
52 53
53static void 54static void
54record_point (EMACS_INT pt) 55record_point (ptrdiff_t pt)
55{ 56{
56 int at_boundary; 57 int at_boundary;
57 58
@@ -103,8 +104,9 @@ record_point (EMACS_INT pt)
103 if (at_boundary 104 if (at_boundary
104 && current_buffer == last_boundary_buffer 105 && current_buffer == last_boundary_buffer
105 && last_boundary_position != pt) 106 && last_boundary_position != pt)
106 BVAR (current_buffer, undo_list) 107 bset_undo_list (current_buffer,
107 = Fcons (make_number (last_boundary_position), BVAR (current_buffer, undo_list)); 108 Fcons (make_number (last_boundary_position),
109 BVAR (current_buffer, undo_list)));
108} 110}
109 111
110/* Record an insertion that just happened or is about to happen, 112/* Record an insertion that just happened or is about to happen,
@@ -113,7 +115,7 @@ record_point (EMACS_INT pt)
113 because we don't need to record the contents.) */ 115 because we don't need to record the contents.) */
114 116
115void 117void
116record_insert (EMACS_INT beg, EMACS_INT length) 118record_insert (ptrdiff_t beg, ptrdiff_t length)
117{ 119{
118 Lisp_Object lbeg, lend; 120 Lisp_Object lbeg, lend;
119 121
@@ -140,15 +142,15 @@ record_insert (EMACS_INT beg, EMACS_INT length)
140 142
141 XSETFASTINT (lbeg, beg); 143 XSETFASTINT (lbeg, beg);
142 XSETINT (lend, beg + length); 144 XSETINT (lend, beg + length);
143 BVAR (current_buffer, undo_list) = Fcons (Fcons (lbeg, lend), 145 bset_undo_list (current_buffer,
144 BVAR (current_buffer, undo_list)); 146 Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list)));
145} 147}
146 148
147/* Record that a deletion is about to take place, 149/* Record that a deletion is about to take place,
148 of the characters in STRING, at location BEG. */ 150 of the characters in STRING, at location BEG. */
149 151
150void 152void
151record_delete (EMACS_INT beg, Lisp_Object string) 153record_delete (ptrdiff_t beg, Lisp_Object string)
152{ 154{
153 Lisp_Object sbeg; 155 Lisp_Object sbeg;
154 156
@@ -166,8 +168,9 @@ record_delete (EMACS_INT beg, Lisp_Object string)
166 record_point (beg); 168 record_point (beg);
167 } 169 }
168 170
169 BVAR (current_buffer, undo_list) 171 bset_undo_list
170 = Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list)); 172 (current_buffer,
173 Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list)));
171} 174}
172 175
173/* Record the fact that MARKER is about to be adjusted by ADJUSTMENT. 176/* Record the fact that MARKER is about to be adjusted by ADJUSTMENT.
@@ -176,7 +179,7 @@ record_delete (EMACS_INT beg, Lisp_Object string)
176 won't be inverted automatically by undoing the buffer modification. */ 179 won't be inverted automatically by undoing the buffer modification. */
177 180
178void 181void
179record_marker_adjustment (Lisp_Object marker, EMACS_INT adjustment) 182record_marker_adjustment (Lisp_Object marker, ptrdiff_t adjustment)
180{ 183{
181 if (EQ (BVAR (current_buffer, undo_list), Qt)) 184 if (EQ (BVAR (current_buffer, undo_list), Qt))
182 return; 185 return;
@@ -189,9 +192,10 @@ record_marker_adjustment (Lisp_Object marker, EMACS_INT adjustment)
189 Fundo_boundary (); 192 Fundo_boundary ();
190 last_undo_buffer = current_buffer; 193 last_undo_buffer = current_buffer;
191 194
192 BVAR (current_buffer, undo_list) 195 bset_undo_list
193 = Fcons (Fcons (marker, make_number (adjustment)), 196 (current_buffer,
194 BVAR (current_buffer, undo_list)); 197 Fcons (Fcons (marker, make_number (adjustment)),
198 BVAR (current_buffer, undo_list)));
195} 199}
196 200
197/* Record that a replacement is about to take place, 201/* Record that a replacement is about to take place,
@@ -199,7 +203,7 @@ record_marker_adjustment (Lisp_Object marker, EMACS_INT adjustment)
199 The replacement must not change the number of characters. */ 203 The replacement must not change the number of characters. */
200 204
201void 205void
202record_change (EMACS_INT beg, EMACS_INT length) 206record_change (ptrdiff_t beg, ptrdiff_t length)
203{ 207{
204 record_delete (beg, make_buffer_string (beg, beg + length, 1)); 208 record_delete (beg, make_buffer_string (beg, beg + length, 1));
205 record_insert (beg, length); 209 record_insert (beg, length);
@@ -224,16 +228,17 @@ record_first_change (void)
224 if (base_buffer->base_buffer) 228 if (base_buffer->base_buffer)
225 base_buffer = base_buffer->base_buffer; 229 base_buffer = base_buffer->base_buffer;
226 230
227 BVAR (current_buffer, undo_list) = 231 bset_undo_list
228 Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)), 232 (current_buffer,
229 BVAR (current_buffer, undo_list)); 233 Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)),
234 BVAR (current_buffer, undo_list)));
230} 235}
231 236
232/* Record a change in property PROP (whose old value was VAL) 237/* Record a change in property PROP (whose old value was VAL)
233 for LENGTH characters starting at position BEG in BUFFER. */ 238 for LENGTH characters starting at position BEG in BUFFER. */
234 239
235void 240void
236record_property_change (EMACS_INT beg, EMACS_INT length, 241record_property_change (ptrdiff_t beg, ptrdiff_t length,
237 Lisp_Object prop, Lisp_Object value, 242 Lisp_Object prop, Lisp_Object value,
238 Lisp_Object buffer) 243 Lisp_Object buffer)
239{ 244{
@@ -264,7 +269,8 @@ record_property_change (EMACS_INT beg, EMACS_INT length,
264 XSETINT (lbeg, beg); 269 XSETINT (lbeg, beg);
265 XSETINT (lend, beg + length); 270 XSETINT (lend, beg + length);
266 entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend)))); 271 entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend))));
267 BVAR (current_buffer, undo_list) = Fcons (entry, BVAR (current_buffer, undo_list)); 272 bset_undo_list (current_buffer,
273 Fcons (entry, BVAR (current_buffer, undo_list)));
268 274
269 current_buffer = obuf; 275 current_buffer = obuf;
270} 276}
@@ -287,11 +293,12 @@ but another undo command will undo to the previous boundary. */)
287 /* If we have preallocated the cons cell to use here, 293 /* If we have preallocated the cons cell to use here,
288 use that one. */ 294 use that one. */
289 XSETCDR (pending_boundary, BVAR (current_buffer, undo_list)); 295 XSETCDR (pending_boundary, BVAR (current_buffer, undo_list));
290 BVAR (current_buffer, undo_list) = pending_boundary; 296 bset_undo_list (current_buffer, pending_boundary);
291 pending_boundary = Qnil; 297 pending_boundary = Qnil;
292 } 298 }
293 else 299 else
294 BVAR (current_buffer, undo_list) = Fcons (Qnil, BVAR (current_buffer, undo_list)); 300 bset_undo_list (current_buffer,
301 Fcons (Qnil, BVAR (current_buffer, undo_list)));
295 } 302 }
296 last_boundary_position = PT; 303 last_boundary_position = PT;
297 last_boundary_buffer = current_buffer; 304 last_boundary_buffer = current_buffer;
@@ -308,16 +315,16 @@ truncate_undo_list (struct buffer *b)
308{ 315{
309 Lisp_Object list; 316 Lisp_Object list;
310 Lisp_Object prev, next, last_boundary; 317 Lisp_Object prev, next, last_boundary;
311 int size_so_far = 0; 318 EMACS_INT size_so_far = 0;
312 319
313 /* Make sure that calling undo-outer-limit-function 320 /* Make sure that calling undo-outer-limit-function
314 won't cause another GC. */ 321 won't cause another GC. */
315 int count = inhibit_garbage_collection (); 322 ptrdiff_t count = inhibit_garbage_collection ();
316 323
317 /* Make the buffer current to get its local values of variables such 324 /* Make the buffer current to get its local values of variables such
318 as undo_limit. Also so that Vundo_outer_limit_function can 325 as undo_limit. Also so that Vundo_outer_limit_function can
319 tell which buffer to operate on. */ 326 tell which buffer to operate on. */
320 record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); 327 record_unwind_current_buffer ();
321 set_buffer_internal (b); 328 set_buffer_internal (b);
322 329
323 list = BVAR (b, undo_list); 330 list = BVAR (b, undo_list);
@@ -432,10 +439,17 @@ truncate_undo_list (struct buffer *b)
432 XSETCDR (last_boundary, Qnil); 439 XSETCDR (last_boundary, Qnil);
433 /* There's nothing we decided to keep, so clear it out. */ 440 /* There's nothing we decided to keep, so clear it out. */
434 else 441 else
435 BVAR (b, undo_list) = Qnil; 442 bset_undo_list (b, Qnil);
436 443
437 unbind_to (count, Qnil); 444 unbind_to (count, Qnil);
438} 445}
446
447static _Noreturn void
448user_error (const char *msg)
449{
450 xsignal1 (Quser_error, build_string (msg));
451}
452
439 453
440DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0, 454DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
441 doc: /* Undo N records from the front of the list LIST. 455 doc: /* Undo N records from the front of the list LIST.
@@ -444,8 +458,8 @@ Return what remains of the list. */)
444{ 458{
445 struct gcpro gcpro1, gcpro2; 459 struct gcpro gcpro1, gcpro2;
446 Lisp_Object next; 460 Lisp_Object next;
447 int count = SPECPDL_INDEX (); 461 ptrdiff_t count = SPECPDL_INDEX ();
448 register int arg; 462 register EMACS_INT arg;
449 Lisp_Object oldlist; 463 Lisp_Object oldlist;
450 int did_apply = 0; 464 int did_apply = 0;
451 465
@@ -497,10 +511,23 @@ Return what remains of the list. */)
497 cdr = XCDR (next); 511 cdr = XCDR (next);
498 if (EQ (car, Qt)) 512 if (EQ (car, Qt))
499 { 513 {
500 /* Element (t high . low) records previous modtime. */ 514 /* Element (t . TIME) records previous modtime.
515 Preserve any flag of NONEXISTENT_MODTIME_NSECS or
516 UNKNOWN_MODTIME_NSECS. */
501 struct buffer *base_buffer = current_buffer; 517 struct buffer *base_buffer = current_buffer;
502 time_t mod_time; 518 EMACS_TIME mod_time;
503 CONS_TO_INTEGER (cdr, time_t, mod_time); 519
520 if (CONSP (cdr)
521 && CONSP (XCDR (cdr))
522 && CONSP (XCDR (XCDR (cdr)))
523 && CONSP (XCDR (XCDR (XCDR (cdr))))
524 && INTEGERP (XCAR (XCDR (XCDR (XCDR (cdr)))))
525 && XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) < 0)
526 mod_time =
527 (make_emacs_time
528 (0, XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000));
529 else
530 mod_time = lisp_time_argument (cdr);
504 531
505 if (current_buffer->base_buffer) 532 if (current_buffer->base_buffer)
506 base_buffer = current_buffer->base_buffer; 533 base_buffer = current_buffer->base_buffer;
@@ -508,7 +535,7 @@ Return what remains of the list. */)
508 /* If this records an obsolete save 535 /* If this records an obsolete save
509 (not matching the actual disk file) 536 (not matching the actual disk file)
510 then don't mark unmodified. */ 537 then don't mark unmodified. */
511 if (mod_time != base_buffer->modtime) 538 if (EMACS_TIME_NE (mod_time, base_buffer->modtime))
512 continue; 539 continue;
513#ifdef CLASH_DETECTION 540#ifdef CLASH_DETECTION
514 Funlock_buffer (); 541 Funlock_buffer ();
@@ -528,7 +555,7 @@ Return what remains of the list. */)
528 end = Fcdr (cdr); 555 end = Fcdr (cdr);
529 556
530 if (XINT (beg) < BEGV || XINT (end) > ZV) 557 if (XINT (beg) < BEGV || XINT (end) > ZV)
531 error ("Changes to be undone are outside visible portion of buffer"); 558 user_error ("Changes to be undone are outside visible portion of buffer");
532 Fput_text_property (beg, end, prop, val, Qnil); 559 Fput_text_property (beg, end, prop, val, Qnil);
533 } 560 }
534 else if (INTEGERP (car) && INTEGERP (cdr)) 561 else if (INTEGERP (car) && INTEGERP (cdr))
@@ -537,7 +564,7 @@ Return what remains of the list. */)
537 564
538 if (XINT (car) < BEGV 565 if (XINT (car) < BEGV
539 || XINT (cdr) > ZV) 566 || XINT (cdr) > ZV)
540 error ("Changes to be undone are outside visible portion of buffer"); 567 user_error ("Changes to be undone are outside visible portion of buffer");
541 /* Set point first thing, so that undoing this undo 568 /* Set point first thing, so that undoing this undo
542 does not send point back to where it is now. */ 569 does not send point back to where it is now. */
543 Fgoto_char (car); 570 Fgoto_char (car);
@@ -588,14 +615,14 @@ Return what remains of the list. */)
588 if (pos < 0) 615 if (pos < 0)
589 { 616 {
590 if (-pos < BEGV || -pos > ZV) 617 if (-pos < BEGV || -pos > ZV)
591 error ("Changes to be undone are outside visible portion of buffer"); 618 user_error ("Changes to be undone are outside visible portion of buffer");
592 SET_PT (-pos); 619 SET_PT (-pos);
593 Finsert (1, &membuf); 620 Finsert (1, &membuf);
594 } 621 }
595 else 622 else
596 { 623 {
597 if (pos < BEGV || pos > ZV) 624 if (pos < BEGV || pos > ZV)
598 error ("Changes to be undone are outside visible portion of buffer"); 625 user_error ("Changes to be undone are outside visible portion of buffer");
599 SET_PT (pos); 626 SET_PT (pos);
600 627
601 /* Now that we record marker adjustments 628 /* Now that we record marker adjustments
@@ -627,8 +654,9 @@ Return what remains of the list. */)
627 will work right. */ 654 will work right. */
628 if (did_apply 655 if (did_apply
629 && EQ (oldlist, BVAR (current_buffer, undo_list))) 656 && EQ (oldlist, BVAR (current_buffer, undo_list)))
630 BVAR (current_buffer, undo_list) 657 bset_undo_list
631 = Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list)); 658 (current_buffer,
659 Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list)));
632 660
633 UNGCPRO; 661 UNGCPRO;
634 return unbind_to (count, list); 662 return unbind_to (count, list);