diff options
| author | Bill Wohler | 2012-11-24 19:43:02 -0800 |
|---|---|---|
| committer | Bill Wohler | 2012-11-24 19:43:02 -0800 |
| commit | 5244bc019bf7376caff3bb198ff674e0ad9fb0e6 (patch) | |
| tree | 02ee1615e904771f692ec2957c79a08ae029a13d /src/undo.c | |
| parent | 9f7e719509474e92f85955e22e57ffeebd4e96f3 (diff) | |
| parent | c07a6ded1df2f4156badc9add2953579622c3722 (diff) | |
| download | emacs-5244bc019bf7376caff3bb198ff674e0ad9fb0e6.tar.gz emacs-5244bc019bf7376caff3bb198ff674e0ad9fb0e6.zip | |
Merge from trunk.
Diffstat (limited to 'src/undo.c')
| -rw-r--r-- | src/undo.c | 108 |
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 | ||
| 4 | This file is part of GNU Emacs. | 4 | This 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. */ |
| 32 | static struct buffer *last_boundary_buffer; | 33 | static struct buffer *last_boundary_buffer; |
| 33 | static EMACS_INT last_boundary_position; | 34 | static ptrdiff_t last_boundary_position; |
| 34 | 35 | ||
| 35 | Lisp_Object Qinhibit_read_only; | 36 | Lisp_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 | ||
| 53 | static void | 54 | static void |
| 54 | record_point (EMACS_INT pt) | 55 | record_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 | ||
| 115 | void | 117 | void |
| 116 | record_insert (EMACS_INT beg, EMACS_INT length) | 118 | record_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 | ||
| 150 | void | 152 | void |
| 151 | record_delete (EMACS_INT beg, Lisp_Object string) | 153 | record_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 | ||
| 178 | void | 181 | void |
| 179 | record_marker_adjustment (Lisp_Object marker, EMACS_INT adjustment) | 182 | record_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 | ||
| 201 | void | 205 | void |
| 202 | record_change (EMACS_INT beg, EMACS_INT length) | 206 | record_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 | ||
| 235 | void | 240 | void |
| 236 | record_property_change (EMACS_INT beg, EMACS_INT length, | 241 | record_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 | |||
| 447 | static _Noreturn void | ||
| 448 | user_error (const char *msg) | ||
| 449 | { | ||
| 450 | xsignal1 (Quser_error, build_string (msg)); | ||
| 451 | } | ||
| 452 | |||
| 439 | 453 | ||
| 440 | DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0, | 454 | DEFUN ("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); |