1 /* undo handling for GNU Emacs.
2 Copyright (C) 1990, 1993, 1994, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
29 /* Limits controlling how much undo information to keep. */
32 EMACS_INT undo_strong_limit
;
34 Lisp_Object Vundo_outer_limit
;
36 /* Function to call when undo_outer_limit is exceeded. */
38 Lisp_Object Vundo_outer_limit_function
;
40 /* Last buffer for which undo information was recorded. */
41 Lisp_Object last_undo_buffer
;
43 Lisp_Object Qinhibit_read_only
;
45 /* Marker for function call undo list elements. */
49 /* The first time a command records something for undo.
50 it also allocates the undo-boundary object
51 which will be added to the list at the end of the command.
52 This ensures we can't run out of space while trying to make
54 Lisp_Object pending_boundary
;
56 /* Nonzero means do not record point in record_point. */
58 int undo_inhibit_record_point
;
60 /* Record point as it was at beginning of this command (if necessary)
61 and prepare the undo info for recording a change.
62 PT is the position of point that will naturally occur as a result of the
63 undo record that will be added just after this command terminates. */
71 /* Don't record position of pt when undo_inhibit_record_point holds.
72 Needed to avoid inserting a position record in buffer-undo-list
73 when last_point_position has not been set up correctly by
74 command_loop_1, for example, when running a repeat-repeat-char
76 if (undo_inhibit_record_point
)
79 /* Allocate a cons cell to be the undo boundary after this command. */
80 if (NILP (pending_boundary
))
81 pending_boundary
= Fcons (Qnil
, Qnil
);
83 if (!BUFFERP (last_undo_buffer
)
84 || current_buffer
!= XBUFFER (last_undo_buffer
))
86 XSETBUFFER (last_undo_buffer
, current_buffer
);
88 if (CONSP (current_buffer
->undo_list
))
90 /* Set AT_BOUNDARY to 1 only when we have nothing other than
91 marker adjustment before undo boundary. */
93 Lisp_Object tail
= current_buffer
->undo_list
, elt
;
101 if (NILP (elt
) || ! (CONSP (elt
) && MARKERP (XCAR (elt
))))
105 at_boundary
= NILP (elt
);
110 if (MODIFF
<= SAVE_MODIFF
)
111 record_first_change ();
113 /* If we are just after an undo boundary, and
114 point wasn't at start of deleted range, record where it was. */
116 && BUFFERP (last_point_position_buffer
)
117 /* If we're called from batch mode, this could be nil. */
118 && current_buffer
== XBUFFER (last_point_position_buffer
))
120 /* If we have switched windows, use the point value
121 from the window we are in. */
122 if (! EQ (last_point_position_window
, selected_window
))
123 last_point_position
= marker_position (XWINDOW (selected_window
)->pointm
);
125 if (last_point_position
!= pt
)
126 current_buffer
->undo_list
127 = Fcons (make_number (last_point_position
), current_buffer
->undo_list
);
131 /* Record an insertion that just happened or is about to happen,
132 for LENGTH characters at position BEG.
133 (It is possible to record an insertion before or after the fact
134 because we don't need to record the contents.) */
137 record_insert (beg
, length
)
140 Lisp_Object lbeg
, lend
;
142 if (EQ (current_buffer
->undo_list
, Qt
))
147 /* If this is following another insertion and consecutive with it
148 in the buffer, combine the two. */
149 if (CONSP (current_buffer
->undo_list
))
152 elt
= XCAR (current_buffer
->undo_list
);
154 && INTEGERP (XCAR (elt
))
155 && INTEGERP (XCDR (elt
))
156 && XINT (XCDR (elt
)) == beg
)
158 XSETCDR (elt
, make_number (beg
+ length
));
163 XSETFASTINT (lbeg
, beg
);
164 XSETINT (lend
, beg
+ length
);
165 current_buffer
->undo_list
= Fcons (Fcons (lbeg
, lend
),
166 current_buffer
->undo_list
);
169 /* Record that a deletion is about to take place,
170 of the characters in STRING, at location BEG. */
173 record_delete (beg
, string
)
179 if (EQ (current_buffer
->undo_list
, Qt
))
182 if (PT
== beg
+ SCHARS (string
))
184 XSETINT (sbeg
, -beg
);
189 XSETFASTINT (sbeg
, beg
);
193 current_buffer
->undo_list
194 = Fcons (Fcons (string
, sbeg
), current_buffer
->undo_list
);
197 /* Record the fact that MARKER is about to be adjusted by ADJUSTMENT.
198 This is done only when a marker points within text being deleted,
199 because that's the only case where an automatic marker adjustment
200 won't be inverted automatically by undoing the buffer modification. */
203 record_marker_adjustment (marker
, adjustment
)
207 if (EQ (current_buffer
->undo_list
, Qt
))
210 /* Allocate a cons cell to be the undo boundary after this command. */
211 if (NILP (pending_boundary
))
212 pending_boundary
= Fcons (Qnil
, Qnil
);
214 if (!BUFFERP (last_undo_buffer
)
215 || current_buffer
!= XBUFFER (last_undo_buffer
))
217 XSETBUFFER (last_undo_buffer
, current_buffer
);
219 current_buffer
->undo_list
220 = Fcons (Fcons (marker
, make_number (adjustment
)),
221 current_buffer
->undo_list
);
224 /* Record that a replacement is about to take place,
225 for LENGTH characters at location BEG.
226 The replacement must not change the number of characters. */
229 record_change (beg
, length
)
232 record_delete (beg
, make_buffer_string (beg
, beg
+ length
, 1));
233 record_insert (beg
, length
);
236 /* Record that an unmodified buffer is about to be changed.
237 Record the file modification date so that when undoing this entry
238 we can tell whether it is obsolete because the file was saved again. */
241 record_first_change ()
243 Lisp_Object high
, low
;
244 struct buffer
*base_buffer
= current_buffer
;
246 if (EQ (current_buffer
->undo_list
, Qt
))
249 if (!BUFFERP (last_undo_buffer
)
250 || current_buffer
!= XBUFFER (last_undo_buffer
))
252 XSETBUFFER (last_undo_buffer
, current_buffer
);
254 if (base_buffer
->base_buffer
)
255 base_buffer
= base_buffer
->base_buffer
;
257 XSETFASTINT (high
, (base_buffer
->modtime
>> 16) & 0xffff);
258 XSETFASTINT (low
, base_buffer
->modtime
& 0xffff);
259 current_buffer
->undo_list
= Fcons (Fcons (Qt
, Fcons (high
, low
)), current_buffer
->undo_list
);
262 /* Record a change in property PROP (whose old value was VAL)
263 for LENGTH characters starting at position BEG in BUFFER. */
266 record_property_change (beg
, length
, prop
, value
, buffer
)
268 Lisp_Object prop
, value
, buffer
;
270 Lisp_Object lbeg
, lend
, entry
;
271 struct buffer
*obuf
= current_buffer
;
274 if (EQ (XBUFFER (buffer
)->undo_list
, Qt
))
277 /* Allocate a cons cell to be the undo boundary after this command. */
278 if (NILP (pending_boundary
))
279 pending_boundary
= Fcons (Qnil
, Qnil
);
281 if (!EQ (buffer
, last_undo_buffer
))
283 last_undo_buffer
= buffer
;
285 /* Switch temporarily to the buffer that was changed. */
286 current_buffer
= XBUFFER (buffer
);
291 if (MODIFF
<= SAVE_MODIFF
)
292 record_first_change ();
295 XSETINT (lend
, beg
+ length
);
296 entry
= Fcons (Qnil
, Fcons (prop
, Fcons (value
, Fcons (lbeg
, lend
))));
297 current_buffer
->undo_list
= Fcons (entry
, current_buffer
->undo_list
);
299 current_buffer
= obuf
;
302 DEFUN ("undo-boundary", Fundo_boundary
, Sundo_boundary
, 0, 0, 0,
303 doc
: /* Mark a boundary between units of undo.
304 An undo command will stop at this point,
305 but another undo command will undo to the previous boundary. */)
309 if (EQ (current_buffer
->undo_list
, Qt
))
311 tem
= Fcar (current_buffer
->undo_list
);
314 /* One way or another, cons nil onto the front of the undo list. */
315 if (!NILP (pending_boundary
))
317 /* If we have preallocated the cons cell to use here,
319 XSETCDR (pending_boundary
, current_buffer
->undo_list
);
320 current_buffer
->undo_list
= pending_boundary
;
321 pending_boundary
= Qnil
;
324 current_buffer
->undo_list
= Fcons (Qnil
, current_buffer
->undo_list
);
329 /* At garbage collection time, make an undo list shorter at the end,
330 returning the truncated list. How this is done depends on the
331 variables undo-limit, undo-strong-limit and undo-outer-limit.
332 In some cases this works by calling undo-outer-limit-function. */
335 truncate_undo_list (b
)
339 Lisp_Object prev
, next
, last_boundary
;
342 /* Make sure that calling undo-outer-limit-function
343 won't cause another GC. */
344 int count
= inhibit_garbage_collection ();
346 /* Make the buffer current to get its local values of variables such
347 as undo_limit. Also so that Vundo_outer_limit_function can
348 tell which buffer to operate on. */
349 record_unwind_protect (set_buffer_if_live
, Fcurrent_buffer ());
350 set_buffer_internal (b
);
356 last_boundary
= Qnil
;
358 /* If the first element is an undo boundary, skip past it. */
359 if (CONSP (next
) && NILP (XCAR (next
)))
361 /* Add in the space occupied by this element and its chain link. */
362 size_so_far
+= sizeof (struct Lisp_Cons
);
364 /* Advance to next element. */
369 /* Always preserve at least the most recent undo record
370 unless it is really horribly big.
372 Skip, skip, skip the undo, skip, skip, skip the undo,
373 Skip, skip, skip the undo, skip to the undo bound'ry. */
375 while (CONSP (next
) && ! NILP (XCAR (next
)))
380 /* Add in the space occupied by this element and its chain link. */
381 size_so_far
+= sizeof (struct Lisp_Cons
);
384 size_so_far
+= sizeof (struct Lisp_Cons
);
385 if (STRINGP (XCAR (elt
)))
386 size_so_far
+= (sizeof (struct Lisp_String
) - 1
387 + SCHARS (XCAR (elt
)));
390 /* Advance to next element. */
395 /* If by the first boundary we have already passed undo_outer_limit,
396 we're heading for memory full, so offer to clear out the list. */
397 if (INTEGERP (Vundo_outer_limit
)
398 && size_so_far
> XINT (Vundo_outer_limit
)
399 && !NILP (Vundo_outer_limit_function
))
401 Lisp_Object temp
= last_undo_buffer
, tem
;
403 /* Normally the function this calls is undo-outer-limit-truncate. */
404 tem
= call1 (Vundo_outer_limit_function
, make_number (size_so_far
));
407 /* The function is responsible for making
408 any desired changes in buffer-undo-list. */
409 unbind_to (count
, Qnil
);
412 /* That function probably used the minibuffer, and if so, that
413 changed last_undo_buffer. Change it back so that we don't
414 force next change to make an undo boundary here. */
415 last_undo_buffer
= temp
;
419 last_boundary
= prev
;
421 /* Keep additional undo data, if it fits in the limits. */
427 /* When we get to a boundary, decide whether to truncate
428 either before or after it. The lower threshold, undo_limit,
429 tells us to truncate after it. If its size pushes past
430 the higher threshold undo_strong_limit, we truncate before it. */
433 if (size_so_far
> undo_strong_limit
)
435 last_boundary
= prev
;
436 if (size_so_far
> undo_limit
)
440 /* Add in the space occupied by this element and its chain link. */
441 size_so_far
+= sizeof (struct Lisp_Cons
);
444 size_so_far
+= sizeof (struct Lisp_Cons
);
445 if (STRINGP (XCAR (elt
)))
446 size_so_far
+= (sizeof (struct Lisp_String
) - 1
447 + SCHARS (XCAR (elt
)));
450 /* Advance to next element. */
455 /* If we scanned the whole list, it is short enough; don't change it. */
458 /* Truncate at the boundary where we decided to truncate. */
459 else if (!NILP (last_boundary
))
460 XSETCDR (last_boundary
, Qnil
);
461 /* There's nothing we decided to keep, so clear it out. */
465 unbind_to (count
, Qnil
);
468 DEFUN ("primitive-undo", Fprimitive_undo
, Sprimitive_undo
, 2, 2, 0,
469 doc
: /* Undo N records from the front of the list LIST.
470 Return what remains of the list. */)
474 struct gcpro gcpro1
, gcpro2
;
476 int count
= SPECPDL_INDEX ();
481 #if 0 /* This is a good feature, but would make undo-start
482 unable to do what is expected. */
485 /* If the head of the list is a boundary, it is the boundary
486 preceding this command. Get rid of it and don't count it. */
496 /* I don't think we need to gcpro oldlist, as we use it only
497 to check for EQ. ++kfs */
499 /* In a writable buffer, enable undoing read-only text that is so
500 because of text properties. */
501 if (NILP (current_buffer
->read_only
))
502 specbind (Qinhibit_read_only
, Qt
);
504 /* Don't let `intangible' properties interfere with undo. */
505 specbind (Qinhibit_point_motion_hooks
, Qt
);
507 oldlist
= current_buffer
->undo_list
;
515 /* Exit inner loop at undo boundary. */
518 /* Handle an integer by setting point to that value. */
520 SET_PT (clip_to_bounds (BEGV
, XINT (next
), ZV
));
521 else if (CONSP (next
))
523 Lisp_Object car
, cdr
;
529 /* Element (t high . low) records previous modtime. */
530 Lisp_Object high
, low
;
532 struct buffer
*base_buffer
= current_buffer
;
536 mod_time
= (XFASTINT (high
) << 16) + XFASTINT (low
);
538 if (current_buffer
->base_buffer
)
539 base_buffer
= current_buffer
->base_buffer
;
541 /* If this records an obsolete save
542 (not matching the actual disk file)
543 then don't mark unmodified. */
544 if (mod_time
!= base_buffer
->modtime
)
546 #ifdef CLASH_DETECTION
548 #endif /* CLASH_DETECTION */
549 Fset_buffer_modified_p (Qnil
);
551 else if (EQ (car
, Qnil
))
553 /* Element (nil PROP VAL BEG . END) is property change. */
554 Lisp_Object beg
, end
, prop
, val
;
563 if (XINT (beg
) < BEGV
|| XINT (end
) > ZV
)
564 error ("Changes to be undone are outside visible portion of buffer");
565 Fput_text_property (beg
, end
, prop
, val
, Qnil
);
567 else if (INTEGERP (car
) && INTEGERP (cdr
))
569 /* Element (BEG . END) means range was inserted. */
571 if (XINT (car
) < BEGV
573 error ("Changes to be undone are outside visible portion of buffer");
574 /* Set point first thing, so that undoing this undo
575 does not send point back to where it is now. */
577 Fdelete_region (car
, cdr
);
579 else if (EQ (car
, Qapply
))
581 /* Element (apply FUN . ARGS) means call FUN to undo. */
582 struct buffer
*save_buffer
= current_buffer
;
588 /* Long format: (apply DELTA START END FUN . ARGS). */
589 Lisp_Object delta
= car
;
590 Lisp_Object start
= Fcar (cdr
);
591 Lisp_Object end
= Fcar (Fcdr (cdr
));
592 Lisp_Object start_mark
= Fcopy_marker (start
, Qnil
);
593 Lisp_Object end_mark
= Fcopy_marker (end
, Qt
);
595 cdr
= Fcdr (Fcdr (cdr
));
596 apply1 (Fcar (cdr
), Fcdr (cdr
));
598 /* Check that the function did what the entry said it
600 if (!EQ (start
, Fmarker_position (start_mark
))
601 || (XINT (delta
) + XINT (end
)
602 != marker_position (end_mark
)))
603 error ("Changes to be undone by function different than announced");
604 Fset_marker (start_mark
, Qnil
, Qnil
);
605 Fset_marker (end_mark
, Qnil
, Qnil
);
610 if (save_buffer
!= current_buffer
)
611 error ("Undo function switched buffer");
614 else if (STRINGP (car
) && INTEGERP (cdr
))
616 /* Element (STRING . POS) means STRING was deleted. */
618 int pos
= XINT (cdr
);
623 if (-pos
< BEGV
|| -pos
> ZV
)
624 error ("Changes to be undone are outside visible portion of buffer");
626 Finsert (1, &membuf
);
630 if (pos
< BEGV
|| pos
> ZV
)
631 error ("Changes to be undone are outside visible portion of buffer");
634 /* Now that we record marker adjustments
635 (caused by deletion) for undo,
636 we should always insert after markers,
637 so that undoing the marker adjustments
638 put the markers back in the right place. */
639 Finsert (1, &membuf
);
643 else if (MARKERP (car
) && INTEGERP (cdr
))
645 /* (MARKER . INTEGER) means a marker MARKER
646 was adjusted by INTEGER. */
647 if (XMARKER (car
)->buffer
)
649 make_number (marker_position (car
) - XINT (cdr
)),
650 Fmarker_buffer (car
));
658 /* Make sure an apply entry produces at least one undo entry,
659 so the test in `undo' for continuing an undo series
662 && EQ (oldlist
, current_buffer
->undo_list
))
663 current_buffer
->undo_list
664 = Fcons (list3 (Qapply
, Qcdr
, Qnil
), current_buffer
->undo_list
);
667 return unbind_to (count
, list
);
673 Qinhibit_read_only
= intern ("inhibit-read-only");
674 staticpro (&Qinhibit_read_only
);
676 Qapply
= intern ("apply");
679 pending_boundary
= Qnil
;
680 staticpro (&pending_boundary
);
682 defsubr (&Sprimitive_undo
);
683 defsubr (&Sundo_boundary
);
685 DEFVAR_INT ("undo-limit", &undo_limit
,
686 doc
: /* Keep no more undo information once it exceeds this size.
687 This limit is applied when garbage collection happens.
688 When a previous command increases the total undo list size past this
689 value, the earlier commands that came before it are forgotten.
691 The size is counted as the number of bytes occupied,
692 which includes both saved text and other data. */);
695 DEFVAR_INT ("undo-strong-limit", &undo_strong_limit
,
696 doc
: /* Don't keep more than this much size of undo information.
697 This limit is applied when garbage collection happens.
698 When a previous command increases the total undo list size past this
699 value, that command and the earlier commands that came before it are forgotten.
700 However, the most recent buffer-modifying command's undo info
701 is never discarded for this reason.
703 The size is counted as the number of bytes occupied,
704 which includes both saved text and other data. */);
705 undo_strong_limit
= 30000;
707 DEFVAR_LISP ("undo-outer-limit", &Vundo_outer_limit
,
708 doc
: /* Outer limit on size of undo information for one command.
709 At garbage collection time, if the current command has produced
710 more than this much undo information, it discards the info and displays
711 a warning. This is a last-ditch limit to prevent memory overflow.
713 The size is counted as the number of bytes occupied, which includes
714 both saved text and other data. A value of nil means no limit. In
715 this case, accumulating one huge undo entry could make Emacs crash as
716 a result of memory overflow.
718 In fact, this calls the function which is the value of
719 `undo-outer-limit-function' with one argument, the size.
720 The text above describes the behavior of the function
721 that variable usually specifies. */);
722 Vundo_outer_limit
= make_number (3000000);
724 DEFVAR_LISP ("undo-outer-limit-function", &Vundo_outer_limit_function
,
725 doc
: /* Function to call when an undo list exceeds `undo-outer-limit'.
726 This function is called with one argument, the current undo list size
727 for the most recent command (since the last undo boundary).
728 If the function returns t, that means truncation has been fully handled.
729 If it returns nil, the other forms of truncation are done.
731 Garbage collection is inhibited around the call to this function,
732 so it must make sure not to do a lot of consing. */);
733 Vundo_outer_limit_function
= Qnil
;
735 DEFVAR_BOOL ("undo-inhibit-record-point", &undo_inhibit_record_point
,
736 doc
: /* Non-nil means do not record `point' in `buffer-undo-list'. */);
737 undo_inhibit_record_point
= 0;
740 /* arch-tag: d546ee01-4aed-4ffb-bb8b-eefaae50d38a
741 (do not change this comment) */