diff options
| author | Richard M. Stallman | 2004-12-21 11:31:24 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2004-12-21 11:31:24 +0000 |
| commit | 137e23eabdbee787601e927b48d4c0e714e5f192 (patch) | |
| tree | 56cfc4d0c8ca434f3dc945df2a3514dffbd17869 /src/undo.c | |
| parent | 3c7e66a8a779703a4dccad2be562f0073e44f966 (diff) | |
| download | emacs-137e23eabdbee787601e927b48d4c0e714e5f192.tar.gz emacs-137e23eabdbee787601e927b48d4c0e714e5f192.zip | |
(truncate_undo_list): Return void.
Take just one argument, the buffer.
Make it current, and inhibit recursive GC.
Access and update the undo list directly; return void.
Refer to the undo...limit variables directly.
Test undo_outer_limit only after counting the whole current command.
When it's exceeded, call the function in undo-outer-limit-function.
(undo_limit, undo_strong_limit, undo_outer_limit): Moved from alloc.c.
(Vundo_outer_limit_function): New variable.
(syms_of_undo): Define undo-limit, undo-strong-limit
and undo-outer-limit here, and undo-outer-limit-function.
Doc fixes.
Diffstat (limited to 'src/undo.c')
| -rw-r--r-- | src/undo.c | 154 |
1 files changed, 119 insertions, 35 deletions
diff --git a/src/undo.c b/src/undo.c index 9fdc46a3b13..d2f89c36a2a 100644 --- a/src/undo.c +++ b/src/undo.c | |||
| @@ -24,6 +24,16 @@ Boston, MA 02111-1307, USA. */ | |||
| 24 | #include "buffer.h" | 24 | #include "buffer.h" |
| 25 | #include "commands.h" | 25 | #include "commands.h" |
| 26 | 26 | ||
| 27 | /* Limits controlling how much undo information to keep. */ | ||
| 28 | |||
| 29 | EMACS_INT undo_limit; | ||
| 30 | EMACS_INT undo_strong_limit; | ||
| 31 | EMACS_INT undo_outer_limit; | ||
| 32 | |||
| 33 | /* Function to call when undo_outer_limit is exceeded. */ | ||
| 34 | |||
| 35 | Lisp_Object Vundo_outer_limit_function; | ||
| 36 | |||
| 27 | /* Last buffer for which undo information was recorded. */ | 37 | /* Last buffer for which undo information was recorded. */ |
| 28 | Lisp_Object last_undo_buffer; | 38 | Lisp_Object last_undo_buffer; |
| 29 | 39 | ||
| @@ -291,31 +301,35 @@ but another undo command will undo to the previous boundary. */) | |||
| 291 | } | 301 | } |
| 292 | 302 | ||
| 293 | /* At garbage collection time, make an undo list shorter at the end, | 303 | /* At garbage collection time, make an undo list shorter at the end, |
| 294 | returning the truncated list. | 304 | returning the truncated list. How this is done depends on the |
| 295 | MINSIZE, MAXSIZE and LIMITSIZE are the limits on size allowed, | 305 | variables undo-limit, undo-strong-limit and undo-outer-limit. |
| 296 | as described below. | 306 | In some cases this works by calling undo-outer-limit-function. */ |
| 297 | In practice, these are the values of undo-limit, | 307 | |
| 298 | undo-strong-limit, and undo-outer-limit. */ | 308 | void |
| 299 | 309 | truncate_undo_list (b) | |
| 300 | Lisp_Object | 310 | struct buffer *b; |
| 301 | truncate_undo_list (list, minsize, maxsize, limitsize) | ||
| 302 | Lisp_Object list; | ||
| 303 | int minsize, maxsize, limitsize; | ||
| 304 | { | 311 | { |
| 312 | Lisp_Object list; | ||
| 305 | Lisp_Object prev, next, last_boundary; | 313 | Lisp_Object prev, next, last_boundary; |
| 306 | int size_so_far = 0; | 314 | int size_so_far = 0; |
| 307 | 315 | ||
| 316 | /* Make sure that calling undo-outer-limit-function | ||
| 317 | won't cause another GC. */ | ||
| 318 | int count = inhibit_garbage_collection (); | ||
| 319 | |||
| 320 | /* Make the buffer current to get its local values of variables such | ||
| 321 | as undo_limit. Also so that Vundo_outer_limit_function can | ||
| 322 | tell which buffer to operate on. */ | ||
| 323 | record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); | ||
| 324 | set_buffer_internal (b); | ||
| 325 | |||
| 326 | list = b->undo_list; | ||
| 327 | |||
| 308 | prev = Qnil; | 328 | prev = Qnil; |
| 309 | next = list; | 329 | next = list; |
| 310 | last_boundary = Qnil; | 330 | last_boundary = Qnil; |
| 311 | 331 | ||
| 312 | /* Always preserve at least the most recent undo record | 332 | /* If the first element is an undo boundary, skip past it. */ |
| 313 | unless it is really horribly big. | ||
| 314 | If the first element is an undo boundary, skip past it. | ||
| 315 | |||
| 316 | Skip, skip, skip the undo, skip, skip, skip the undo, | ||
| 317 | Skip, skip, skip the undo, skip to the undo bound'ry. | ||
| 318 | (Get it? "Skip to my Loo?") */ | ||
| 319 | if (CONSP (next) && NILP (XCAR (next))) | 333 | if (CONSP (next) && NILP (XCAR (next))) |
| 320 | { | 334 | { |
| 321 | /* Add in the space occupied by this element and its chain link. */ | 335 | /* Add in the space occupied by this element and its chain link. */ |
| @@ -326,6 +340,12 @@ truncate_undo_list (list, minsize, maxsize, limitsize) | |||
| 326 | next = XCDR (next); | 340 | next = XCDR (next); |
| 327 | } | 341 | } |
| 328 | 342 | ||
| 343 | /* Always preserve at least the most recent undo record | ||
| 344 | unless it is really horribly big. | ||
| 345 | |||
| 346 | Skip, skip, skip the undo, skip, skip, skip the undo, | ||
| 347 | Skip, skip, skip the undo, skip to the undo bound'ry. */ | ||
| 348 | |||
| 329 | while (CONSP (next) && ! NILP (XCAR (next))) | 349 | while (CONSP (next) && ! NILP (XCAR (next))) |
| 330 | { | 350 | { |
| 331 | Lisp_Object elt; | 351 | Lisp_Object elt; |
| @@ -341,35 +361,52 @@ truncate_undo_list (list, minsize, maxsize, limitsize) | |||
| 341 | + SCHARS (XCAR (elt))); | 361 | + SCHARS (XCAR (elt))); |
| 342 | } | 362 | } |
| 343 | 363 | ||
| 344 | /* If we reach LIMITSIZE before the first boundary, | ||
| 345 | we're heading for memory full, so truncate the list to nothing. */ | ||
| 346 | if (size_so_far > limitsize) | ||
| 347 | return Qnil; | ||
| 348 | |||
| 349 | /* Advance to next element. */ | 364 | /* Advance to next element. */ |
| 350 | prev = next; | 365 | prev = next; |
| 351 | next = XCDR (next); | 366 | next = XCDR (next); |
| 352 | } | 367 | } |
| 353 | 368 | ||
| 369 | /* If by the first boundary we have already passed undo_outer_limit, | ||
| 370 | we're heading for memory full, so offer to clear out the list. */ | ||
| 371 | if (size_so_far > undo_outer_limit | ||
| 372 | && !NILP (Vundo_outer_limit_function)) | ||
| 373 | { | ||
| 374 | Lisp_Object temp = last_undo_buffer; | ||
| 375 | |||
| 376 | /* Normally the function this calls is undo-outer-limit-truncate. */ | ||
| 377 | if (! NILP (call1 (Vundo_outer_limit_function, | ||
| 378 | make_number (size_so_far)))) | ||
| 379 | { | ||
| 380 | /* The function is responsible for making | ||
| 381 | any desired changes in buffer-undo-list. */ | ||
| 382 | unbind_to (count, Qnil); | ||
| 383 | return; | ||
| 384 | } | ||
| 385 | /* That function probably used the minibuffer, and if so, that | ||
| 386 | changed last_undo_buffer. Change it back so that we don't | ||
| 387 | force next change to make an undo boundary here. */ | ||
| 388 | last_undo_buffer = temp; | ||
| 389 | } | ||
| 390 | |||
| 354 | if (CONSP (next)) | 391 | if (CONSP (next)) |
| 355 | last_boundary = prev; | 392 | last_boundary = prev; |
| 356 | 393 | ||
| 357 | /* Keep more if it fits. */ | 394 | /* Keep additional undo data, if it fits in the limits. */ |
| 358 | while (CONSP (next)) | 395 | while (CONSP (next)) |
| 359 | { | 396 | { |
| 360 | Lisp_Object elt; | 397 | Lisp_Object elt; |
| 361 | elt = XCAR (next); | 398 | elt = XCAR (next); |
| 362 | 399 | ||
| 363 | /* When we get to a boundary, decide whether to truncate | 400 | /* When we get to a boundary, decide whether to truncate |
| 364 | either before or after it. The lower threshold, MINSIZE, | 401 | either before or after it. The lower threshold, undo_limit, |
| 365 | tells us to truncate after it. If its size pushes past | 402 | tells us to truncate after it. If its size pushes past |
| 366 | the higher threshold MAXSIZE as well, we truncate before it. */ | 403 | the higher threshold undo_strong_limit, we truncate before it. */ |
| 367 | if (NILP (elt)) | 404 | if (NILP (elt)) |
| 368 | { | 405 | { |
| 369 | if (size_so_far > maxsize) | 406 | if (size_so_far > undo_strong_limit) |
| 370 | break; | 407 | break; |
| 371 | last_boundary = prev; | 408 | last_boundary = prev; |
| 372 | if (size_so_far > minsize) | 409 | if (size_so_far > undo_limit) |
| 373 | break; | 410 | break; |
| 374 | } | 411 | } |
| 375 | 412 | ||
| @@ -390,16 +427,15 @@ truncate_undo_list (list, minsize, maxsize, limitsize) | |||
| 390 | 427 | ||
| 391 | /* If we scanned the whole list, it is short enough; don't change it. */ | 428 | /* If we scanned the whole list, it is short enough; don't change it. */ |
| 392 | if (NILP (next)) | 429 | if (NILP (next)) |
| 393 | return list; | 430 | ; |
| 394 | |||
| 395 | /* Truncate at the boundary where we decided to truncate. */ | 431 | /* Truncate at the boundary where we decided to truncate. */ |
| 396 | if (!NILP (last_boundary)) | 432 | else if (!NILP (last_boundary)) |
| 397 | { | 433 | XSETCDR (last_boundary, Qnil); |
| 398 | XSETCDR (last_boundary, Qnil); | 434 | /* There's nothing we decided to keep, so clear it out. */ |
| 399 | return list; | ||
| 400 | } | ||
| 401 | else | 435 | else |
| 402 | return Qnil; | 436 | b->undo_list = Qnil; |
| 437 | |||
| 438 | unbind_to (count, Qnil); | ||
| 403 | } | 439 | } |
| 404 | 440 | ||
| 405 | DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0, | 441 | DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0, |
| @@ -563,6 +599,54 @@ syms_of_undo () | |||
| 563 | 599 | ||
| 564 | defsubr (&Sprimitive_undo); | 600 | defsubr (&Sprimitive_undo); |
| 565 | defsubr (&Sundo_boundary); | 601 | defsubr (&Sundo_boundary); |
| 602 | |||
| 603 | DEFVAR_INT ("undo-limit", &undo_limit, | ||
| 604 | doc: /* Keep no more undo information once it exceeds this size. | ||
| 605 | This limit is applied when garbage collection happens. | ||
| 606 | When a previous command increases the total undo list size past this | ||
| 607 | value, the earlier commands that came before it are forgotten. | ||
| 608 | |||
| 609 | The size is counted as the number of bytes occupied, | ||
| 610 | which includes both saved text and other data. */); | ||
| 611 | undo_limit = 20000; | ||
| 612 | |||
| 613 | DEFVAR_INT ("undo-strong-limit", &undo_strong_limit, | ||
| 614 | doc: /* Don't keep more than this much size of undo information. | ||
| 615 | This limit is applied when garbage collection happens. | ||
| 616 | When a previous command increases the total undo list size past this | ||
| 617 | value, that command and the earlier commands that came before it are forgotten. | ||
| 618 | However, the most recent buffer-modifying command's undo info | ||
| 619 | is never discarded for this reason. | ||
| 620 | |||
| 621 | The size is counted as the number of bytes occupied, | ||
| 622 | which includes both saved text and other data. */); | ||
| 623 | undo_strong_limit = 30000; | ||
| 624 | |||
| 625 | DEFVAR_INT ("undo-outer-limit", &undo_outer_limit, | ||
| 626 | doc: /* Outer limit on size of undo information for one command. | ||
| 627 | At garbage collection time, if the current command has produced | ||
| 628 | more than this much undo information, it asks you whether to delete | ||
| 629 | the information. This is a last-ditch limit to prevent memory overflow. | ||
| 630 | |||
| 631 | The size is counted as the number of bytes occupied, | ||
| 632 | which includes both saved text and other data. | ||
| 633 | |||
| 634 | In fact, this calls the function which is the value of | ||
| 635 | `undo-outer-limit-function' with one argument, the size. | ||
| 636 | The text above describes the behavior of the function | ||
| 637 | that variable usually specifies. */); | ||
| 638 | undo_outer_limit = 300000; | ||
| 639 | |||
| 640 | DEFVAR_LISP ("undo-outer-limit-function", &Vundo_outer_limit_function, | ||
| 641 | doc: /* Function to call when an undo list exceeds `undo-outer-limit'. | ||
| 642 | This function is called with one argument, the current undo list size | ||
| 643 | for the most recent command (since the last undo boundary). | ||
| 644 | If the function returns t, that means truncation has been fully handled. | ||
| 645 | If it returns nil, the other forms of truncation are done. | ||
| 646 | |||
| 647 | Garbage collection is inhibited around the call to this function, | ||
| 648 | so it must make sure not to do a lot of consing. */); | ||
| 649 | Vundo_outer_limit_function = Qnil; | ||
| 566 | } | 650 | } |
| 567 | 651 | ||
| 568 | /* arch-tag: d546ee01-4aed-4ffb-bb8b-eefaae50d38a | 652 | /* arch-tag: d546ee01-4aed-4ffb-bb8b-eefaae50d38a |