*** empty log message ***
[bpt/emacs.git] / src / undo.c
CommitLineData
c6953be1 1/* undo handling for GNU Emacs.
4ac03187
KS
2 Copyright (C) 1990, 1993, 1994, 2000, 2002, 2004, 2005
3 Free Software Foundation, Inc.
c6953be1
JB
4
5This file is part of GNU Emacs.
6
3b7ad313
EN
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
c6953be1 12GNU Emacs is distributed in the hope that it will be useful,
3b7ad313
EN
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
c6953be1
JB
21
22
18160b98 23#include <config.h>
c6953be1
JB
24#include "lisp.h"
25#include "buffer.h"
4e665715 26#include "commands.h"
c6953be1 27
137e23ea
RS
28/* Limits controlling how much undo information to keep. */
29
30EMACS_INT undo_limit;
31EMACS_INT undo_strong_limit;
81c1cf71
RS
32
33Lisp_Object Vundo_outer_limit;
137e23ea
RS
34
35/* Function to call when undo_outer_limit is exceeded. */
36
37Lisp_Object Vundo_outer_limit_function;
38
c6953be1
JB
39/* Last buffer for which undo information was recorded. */
40Lisp_Object last_undo_buffer;
41
f87a68b3
RS
42Lisp_Object Qinhibit_read_only;
43
49be18c9
KS
44/* Marker for function call undo list elements. */
45
46Lisp_Object Qapply;
47
c58632fc
RS
48/* The first time a command records something for undo.
49 it also allocates the undo-boundary object
50 which will be added to the list at the end of the command.
51 This ensures we can't run out of space while trying to make
52 an undo-boundary. */
53Lisp_Object pending_boundary;
54
6396140a
SM
55/* Record point as it was at beginning of this command (if necessary)
56 And prepare the undo info for recording a change.
57 PT is the position of point that will naturally occur as a result of the
58 undo record that will be added just after this command terminates. */
c6953be1 59
6396140a
SM
60static void
61record_point (pt)
f45bedd4 62 int pt;
c6953be1 63{
6396140a 64 int at_boundary;
bdbe6f28 65
c58632fc
RS
66 /* Allocate a cons cell to be the undo boundary after this command. */
67 if (NILP (pending_boundary))
68 pending_boundary = Fcons (Qnil, Qnil);
69
8801a864
KR
70 if (!BUFFERP (last_undo_buffer)
71 || current_buffer != XBUFFER (last_undo_buffer))
c6953be1 72 Fundo_boundary ();
552bdbcf 73 XSETBUFFER (last_undo_buffer, current_buffer);
c6953be1 74
6396140a
SM
75 if (CONSP (current_buffer->undo_list))
76 {
77 /* Set AT_BOUNDARY to 1 only when we have nothing other than
78 marker adjustment before undo boundary. */
79
80 Lisp_Object tail = current_buffer->undo_list, elt;
81
82 while (1)
83 {
84 if (NILP (tail))
85 elt = Qnil;
86 else
87 elt = XCAR (tail);
88 if (NILP (elt) || ! (CONSP (elt) && MARKERP (XCAR (elt))))
89 break;
90 tail = XCDR (tail);
91 }
92 at_boundary = NILP (elt);
93 }
94 else
95 at_boundary = 1;
96
ad9cdce4 97 if (MODIFF <= SAVE_MODIFF)
c6953be1
JB
98 record_first_change ();
99
177c0ea7 100 /* If we are just after an undo boundary, and
6396140a
SM
101 point wasn't at start of deleted range, record where it was. */
102 if (at_boundary
103 && last_point_position != pt
104 /* If we're called from batch mode, this could be nil. */
105 && BUFFERP (last_point_position_buffer)
106 && current_buffer == XBUFFER (last_point_position_buffer))
107 current_buffer->undo_list
108 = Fcons (make_number (last_point_position), current_buffer->undo_list);
109}
110
111/* Record an insertion that just happened or is about to happen,
112 for LENGTH characters at position BEG.
113 (It is possible to record an insertion before or after the fact
114 because we don't need to record the contents.) */
115
116void
117record_insert (beg, length)
118 int beg, length;
119{
120 Lisp_Object lbeg, lend;
121
122 if (EQ (current_buffer->undo_list, Qt))
123 return;
124
125 record_point (beg);
126
c6953be1
JB
127 /* If this is following another insertion and consecutive with it
128 in the buffer, combine the two. */
38c0d37c 129 if (CONSP (current_buffer->undo_list))
c6953be1
JB
130 {
131 Lisp_Object elt;
c1d497be 132 elt = XCAR (current_buffer->undo_list);
38c0d37c 133 if (CONSP (elt)
c1d497be
KR
134 && INTEGERP (XCAR (elt))
135 && INTEGERP (XCDR (elt))
136 && XINT (XCDR (elt)) == beg)
c6953be1 137 {
f3fbd155 138 XSETCDR (elt, make_number (beg + length));
c6953be1
JB
139 return;
140 }
141 }
142
53480e99
KH
143 XSETFASTINT (lbeg, beg);
144 XSETINT (lend, beg + length);
213861c7
JB
145 current_buffer->undo_list = Fcons (Fcons (lbeg, lend),
146 current_buffer->undo_list);
c6953be1
JB
147}
148
149/* Record that a deletion is about to take place,
e928d437 150 of the characters in STRING, at location BEG. */
c6953be1 151
ff1aa840 152void
e928d437
RS
153record_delete (beg, string)
154 int beg;
155 Lisp_Object string;
c6953be1 156{
e928d437 157 Lisp_Object sbeg;
c6953be1 158
bdbe6f28
RS
159 if (EQ (current_buffer->undo_list, Qt))
160 return;
161
d5db4077 162 if (PT == beg + SCHARS (string))
cbc1b668 163 {
6396140a
SM
164 XSETINT (sbeg, -beg);
165 record_point (PT);
cbc1b668
KH
166 }
167 else
6396140a
SM
168 {
169 XSETFASTINT (sbeg, beg);
170 record_point (beg);
171 }
350bce56 172
c6953be1 173 current_buffer->undo_list
e928d437 174 = Fcons (Fcons (string, sbeg), current_buffer->undo_list);
c6953be1
JB
175}
176
714bced9
RS
177/* Record the fact that MARKER is about to be adjusted by ADJUSTMENT.
178 This is done only when a marker points within text being deleted,
179 because that's the only case where an automatic marker adjustment
180 won't be inverted automatically by undoing the buffer modification. */
181
ff1aa840 182void
714bced9
RS
183record_marker_adjustment (marker, adjustment)
184 Lisp_Object marker;
185 int adjustment;
186{
187 if (EQ (current_buffer->undo_list, Qt))
188 return;
189
190 /* Allocate a cons cell to be the undo boundary after this command. */
191 if (NILP (pending_boundary))
192 pending_boundary = Fcons (Qnil, Qnil);
193
177c0ea7 194 if (!BUFFERP (last_undo_buffer)
2f33f38a 195 || current_buffer != XBUFFER (last_undo_buffer))
714bced9
RS
196 Fundo_boundary ();
197 XSETBUFFER (last_undo_buffer, current_buffer);
198
199 current_buffer->undo_list
200 = Fcons (Fcons (marker, make_number (adjustment)),
201 current_buffer->undo_list);
202}
203
c6953be1
JB
204/* Record that a replacement is about to take place,
205 for LENGTH characters at location BEG.
e928d437 206 The replacement must not change the number of characters. */
c6953be1 207
ff1aa840 208void
c6953be1
JB
209record_change (beg, length)
210 int beg, length;
211{
e928d437 212 record_delete (beg, make_buffer_string (beg, beg + length, 1));
c6953be1
JB
213 record_insert (beg, length);
214}
215\f
216/* Record that an unmodified buffer is about to be changed.
217 Record the file modification date so that when undoing this entry
218 we can tell whether it is obsolete because the file was saved again. */
219
90dd3e4f 220void
c6953be1
JB
221record_first_change ()
222{
223 Lisp_Object high, low;
ad9cdce4 224 struct buffer *base_buffer = current_buffer;
0736cafe
RS
225
226 if (EQ (current_buffer->undo_list, Qt))
227 return;
228
2f33f38a
GM
229 if (!BUFFERP (last_undo_buffer)
230 || current_buffer != XBUFFER (last_undo_buffer))
0736cafe 231 Fundo_boundary ();
552bdbcf 232 XSETBUFFER (last_undo_buffer, current_buffer);
0736cafe 233
ad9cdce4
RS
234 if (base_buffer->base_buffer)
235 base_buffer = base_buffer->base_buffer;
236
237 XSETFASTINT (high, (base_buffer->modtime >> 16) & 0xffff);
238 XSETFASTINT (low, base_buffer->modtime & 0xffff);
c6953be1
JB
239 current_buffer->undo_list = Fcons (Fcons (Qt, Fcons (high, low)), current_buffer->undo_list);
240}
241
da9319d5
RS
242/* Record a change in property PROP (whose old value was VAL)
243 for LENGTH characters starting at position BEG in BUFFER. */
244
90dd3e4f 245void
da9319d5
RS
246record_property_change (beg, length, prop, value, buffer)
247 int beg, length;
248 Lisp_Object prop, value, buffer;
249{
250 Lisp_Object lbeg, lend, entry;
251 struct buffer *obuf = current_buffer;
252 int boundary = 0;
253
0736cafe 254 if (EQ (XBUFFER (buffer)->undo_list, Qt))
bdbe6f28
RS
255 return;
256
c58632fc
RS
257 /* Allocate a cons cell to be the undo boundary after this command. */
258 if (NILP (pending_boundary))
259 pending_boundary = Fcons (Qnil, Qnil);
260
da9319d5
RS
261 if (!EQ (buffer, last_undo_buffer))
262 boundary = 1;
263 last_undo_buffer = buffer;
264
da9319d5
RS
265 /* Switch temporarily to the buffer that was changed. */
266 current_buffer = XBUFFER (buffer);
267
268 if (boundary)
269 Fundo_boundary ();
270
ad9cdce4 271 if (MODIFF <= SAVE_MODIFF)
da9319d5
RS
272 record_first_change ();
273
552bdbcf
KH
274 XSETINT (lbeg, beg);
275 XSETINT (lend, beg + length);
da9319d5
RS
276 entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend))));
277 current_buffer->undo_list = Fcons (entry, current_buffer->undo_list);
278
279 current_buffer = obuf;
280}
281
c6953be1 282DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0,
8c1a1077
PJ
283 doc: /* Mark a boundary between units of undo.
284An undo command will stop at this point,
285but another undo command will undo to the previous boundary. */)
286 ()
c6953be1
JB
287{
288 Lisp_Object tem;
289 if (EQ (current_buffer->undo_list, Qt))
290 return Qnil;
291 tem = Fcar (current_buffer->undo_list);
265a9e55 292 if (!NILP (tem))
c58632fc
RS
293 {
294 /* One way or another, cons nil onto the front of the undo list. */
295 if (!NILP (pending_boundary))
296 {
297 /* If we have preallocated the cons cell to use here,
298 use that one. */
f3fbd155 299 XSETCDR (pending_boundary, current_buffer->undo_list);
c58632fc
RS
300 current_buffer->undo_list = pending_boundary;
301 pending_boundary = Qnil;
302 }
303 else
304 current_buffer->undo_list = Fcons (Qnil, current_buffer->undo_list);
305 }
c6953be1
JB
306 return Qnil;
307}
308
309/* At garbage collection time, make an undo list shorter at the end,
137e23ea
RS
310 returning the truncated list. How this is done depends on the
311 variables undo-limit, undo-strong-limit and undo-outer-limit.
312 In some cases this works by calling undo-outer-limit-function. */
313
314void
315truncate_undo_list (b)
316 struct buffer *b;
c6953be1 317{
137e23ea 318 Lisp_Object list;
c6953be1
JB
319 Lisp_Object prev, next, last_boundary;
320 int size_so_far = 0;
321
137e23ea
RS
322 /* Make sure that calling undo-outer-limit-function
323 won't cause another GC. */
324 int count = inhibit_garbage_collection ();
325
326 /* Make the buffer current to get its local values of variables such
327 as undo_limit. Also so that Vundo_outer_limit_function can
328 tell which buffer to operate on. */
329 record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
330 set_buffer_internal (b);
331
332 list = b->undo_list;
333
c6953be1
JB
334 prev = Qnil;
335 next = list;
336 last_boundary = Qnil;
337
137e23ea 338 /* If the first element is an undo boundary, skip past it. */
c1d497be 339 if (CONSP (next) && NILP (XCAR (next)))
c6953be1
JB
340 {
341 /* Add in the space occupied by this element and its chain link. */
342 size_so_far += sizeof (struct Lisp_Cons);
343
344 /* Advance to next element. */
345 prev = next;
c1d497be 346 next = XCDR (next);
c6953be1 347 }
e3d5ca1e 348
137e23ea
RS
349 /* Always preserve at least the most recent undo record
350 unless it is really horribly big.
351
352 Skip, skip, skip the undo, skip, skip, skip the undo,
353 Skip, skip, skip the undo, skip to the undo bound'ry. */
354
c1d497be 355 while (CONSP (next) && ! NILP (XCAR (next)))
c6953be1
JB
356 {
357 Lisp_Object elt;
c1d497be 358 elt = XCAR (next);
c6953be1
JB
359
360 /* Add in the space occupied by this element and its chain link. */
361 size_so_far += sizeof (struct Lisp_Cons);
38c0d37c 362 if (CONSP (elt))
c6953be1
JB
363 {
364 size_so_far += sizeof (struct Lisp_Cons);
c1d497be 365 if (STRINGP (XCAR (elt)))
c6953be1 366 size_so_far += (sizeof (struct Lisp_String) - 1
d5db4077 367 + SCHARS (XCAR (elt)));
c6953be1
JB
368 }
369
370 /* Advance to next element. */
371 prev = next;
c1d497be 372 next = XCDR (next);
c6953be1 373 }
e3d5ca1e 374
137e23ea
RS
375 /* If by the first boundary we have already passed undo_outer_limit,
376 we're heading for memory full, so offer to clear out the list. */
81c1cf71
RS
377 if (INTEGERP (Vundo_outer_limit)
378 && size_so_far > XINT (Vundo_outer_limit)
137e23ea
RS
379 && !NILP (Vundo_outer_limit_function))
380 {
381 Lisp_Object temp = last_undo_buffer;
382
383 /* Normally the function this calls is undo-outer-limit-truncate. */
384 if (! NILP (call1 (Vundo_outer_limit_function,
385 make_number (size_so_far))))
386 {
387 /* The function is responsible for making
388 any desired changes in buffer-undo-list. */
389 unbind_to (count, Qnil);
390 return;
391 }
392 /* That function probably used the minibuffer, and if so, that
393 changed last_undo_buffer. Change it back so that we don't
394 force next change to make an undo boundary here. */
395 last_undo_buffer = temp;
396 }
397
38c0d37c 398 if (CONSP (next))
c6953be1
JB
399 last_boundary = prev;
400
137e23ea 401 /* Keep additional undo data, if it fits in the limits. */
38c0d37c 402 while (CONSP (next))
c6953be1
JB
403 {
404 Lisp_Object elt;
c1d497be 405 elt = XCAR (next);
c6953be1
JB
406
407 /* When we get to a boundary, decide whether to truncate
137e23ea 408 either before or after it. The lower threshold, undo_limit,
c6953be1 409 tells us to truncate after it. If its size pushes past
137e23ea 410 the higher threshold undo_strong_limit, we truncate before it. */
265a9e55 411 if (NILP (elt))
c6953be1 412 {
137e23ea 413 if (size_so_far > undo_strong_limit)
c6953be1
JB
414 break;
415 last_boundary = prev;
137e23ea 416 if (size_so_far > undo_limit)
c6953be1
JB
417 break;
418 }
419
420 /* Add in the space occupied by this element and its chain link. */
421 size_so_far += sizeof (struct Lisp_Cons);
38c0d37c 422 if (CONSP (elt))
c6953be1
JB
423 {
424 size_so_far += sizeof (struct Lisp_Cons);
c1d497be 425 if (STRINGP (XCAR (elt)))
c6953be1 426 size_so_far += (sizeof (struct Lisp_String) - 1
d5db4077 427 + SCHARS (XCAR (elt)));
c6953be1
JB
428 }
429
430 /* Advance to next element. */
431 prev = next;
c1d497be 432 next = XCDR (next);
c6953be1
JB
433 }
434
435 /* If we scanned the whole list, it is short enough; don't change it. */
265a9e55 436 if (NILP (next))
137e23ea 437 ;
c6953be1 438 /* Truncate at the boundary where we decided to truncate. */
137e23ea
RS
439 else if (!NILP (last_boundary))
440 XSETCDR (last_boundary, Qnil);
441 /* There's nothing we decided to keep, so clear it out. */
c6953be1 442 else
137e23ea
RS
443 b->undo_list = Qnil;
444
445 unbind_to (count, Qnil);
c6953be1
JB
446}
447\f
448DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
8c1a1077
PJ
449 doc: /* Undo N records from the front of the list LIST.
450Return what remains of the list. */)
451 (n, list)
063fb61f 452 Lisp_Object n, list;
c6953be1 453{
de65837b
KH
454 struct gcpro gcpro1, gcpro2;
455 Lisp_Object next;
331379bf 456 int count = SPECPDL_INDEX ();
de65837b 457 register int arg;
4ac03187
KS
458 Lisp_Object oldlist;
459 int did_apply = 0;
177c0ea7 460
c6953be1
JB
461#if 0 /* This is a good feature, but would make undo-start
462 unable to do what is expected. */
463 Lisp_Object tem;
464
465 /* If the head of the list is a boundary, it is the boundary
466 preceding this command. Get rid of it and don't count it. */
467 tem = Fcar (list);
265a9e55 468 if (NILP (tem))
c6953be1
JB
469 list = Fcdr (list);
470#endif
471
b7826503 472 CHECK_NUMBER (n);
de65837b
KH
473 arg = XINT (n);
474 next = Qnil;
475 GCPRO2 (next, list);
4ac03187
KS
476 /* I don't think we need to gcpro oldlist, as we use it only
477 to check for EQ. ++kfs */
de65837b 478
38d56be3
GM
479 /* In a writable buffer, enable undoing read-only text that is so
480 because of text properties. */
481 if (NILP (current_buffer->read_only))
f87a68b3
RS
482 specbind (Qinhibit_read_only, Qt);
483
8c757fd7
GM
484 /* Don't let `intangible' properties interfere with undo. */
485 specbind (Qinhibit_point_motion_hooks, Qt);
486
4ac03187
KS
487 oldlist = current_buffer->undo_list;
488
c6953be1
JB
489 while (arg > 0)
490 {
c3b09bbf 491 while (CONSP (list))
c6953be1 492 {
c3b09bbf
SM
493 next = XCAR (list);
494 list = XCDR (list);
350bce56 495 /* Exit inner loop at undo boundary. */
265a9e55 496 if (NILP (next))
c6953be1 497 break;
350bce56 498 /* Handle an integer by setting point to that value. */
38c0d37c 499 if (INTEGERP (next))
350bce56 500 SET_PT (clip_to_bounds (BEGV, XINT (next), ZV));
38c0d37c 501 else if (CONSP (next))
c6953be1 502 {
350bce56
RS
503 Lisp_Object car, cdr;
504
c3b09bbf
SM
505 car = XCAR (next);
506 cdr = XCDR (next);
350bce56 507 if (EQ (car, Qt))
c6953be1 508 {
350bce56
RS
509 /* Element (t high . low) records previous modtime. */
510 Lisp_Object high, low;
511 int mod_time;
ad9cdce4 512 struct buffer *base_buffer = current_buffer;
350bce56
RS
513
514 high = Fcar (cdr);
515 low = Fcdr (cdr);
d8552b2f 516 mod_time = (XFASTINT (high) << 16) + XFASTINT (low);
ad9cdce4
RS
517
518 if (current_buffer->base_buffer)
519 base_buffer = current_buffer->base_buffer;
520
350bce56
RS
521 /* If this records an obsolete save
522 (not matching the actual disk file)
523 then don't mark unmodified. */
ad9cdce4 524 if (mod_time != base_buffer->modtime)
103dcb38 525 continue;
e6dd6080 526#ifdef CLASH_DETECTION
350bce56 527 Funlock_buffer ();
e6dd6080 528#endif /* CLASH_DETECTION */
350bce56 529 Fset_buffer_modified_p (Qnil);
c6953be1 530 }
d8552b2f 531 else if (EQ (car, Qnil))
da9319d5 532 {
6887bce5 533 /* Element (nil PROP VAL BEG . END) is property change. */
da9319d5
RS
534 Lisp_Object beg, end, prop, val;
535
536 prop = Fcar (cdr);
537 cdr = Fcdr (cdr);
538 val = Fcar (cdr);
539 cdr = Fcdr (cdr);
540 beg = Fcar (cdr);
541 end = Fcdr (cdr);
542
543 Fput_text_property (beg, end, prop, val, Qnil);
544 }
38c0d37c 545 else if (INTEGERP (car) && INTEGERP (cdr))
c6953be1 546 {
350bce56 547 /* Element (BEG . END) means range was inserted. */
350bce56
RS
548
549 if (XINT (car) < BEGV
550 || XINT (cdr) > ZV)
c6953be1 551 error ("Changes to be undone are outside visible portion of buffer");
f28f04cc
RS
552 /* Set point first thing, so that undoing this undo
553 does not send point back to where it is now. */
350bce56 554 Fgoto_char (car);
f28f04cc 555 Fdelete_region (car, cdr);
350bce56 556 }
49be18c9 557 else if (EQ (car, Qapply))
6887bce5 558 {
3419757d 559 /* Element (apply FUN . ARGS) means call FUN to undo. */
49be18c9 560 car = Fcar (cdr);
3419757d 561 cdr = Fcdr (cdr);
49be18c9
KS
562 if (INTEGERP (car))
563 {
3419757d
SM
564 /* Long format: (apply DELTA START END FUN . ARGS). */
565 Lisp_Object delta = car;
566 Lisp_Object start = Fcar (cdr);
567 Lisp_Object end = Fcar (Fcdr (cdr));
568 Lisp_Object start_mark = Fcopy_marker (start, Qnil);
569 Lisp_Object end_mark = Fcopy_marker (end, Qt);
570
571 cdr = Fcdr (Fcdr (cdr));
572 apply1 (Fcar (cdr), Fcdr (cdr));
573
574 /* Check that the function did what the entry said it
575 would do. */
576 if (!EQ (start, Fmarker_position (start_mark))
577 || (XINT (delta) + XINT (end)
578 != marker_position (end_mark)))
579 error ("Changes to be undone by function different than announced");
580 Fset_marker (start_mark, Qnil, Qnil);
581 Fset_marker (end_mark, Qnil, Qnil);
49be18c9 582 }
3419757d
SM
583 else
584 apply1 (car, cdr);
4ac03187 585 did_apply = 1;
6887bce5 586 }
38c0d37c 587 else if (STRINGP (car) && INTEGERP (cdr))
350bce56
RS
588 {
589 /* Element (STRING . POS) means STRING was deleted. */
590 Lisp_Object membuf;
591 int pos = XINT (cdr);
592
593 membuf = car;
594 if (pos < 0)
595 {
596 if (-pos < BEGV || -pos > ZV)
597 error ("Changes to be undone are outside visible portion of buffer");
598 SET_PT (-pos);
599 Finsert (1, &membuf);
600 }
601 else
602 {
603 if (pos < BEGV || pos > ZV)
604 error ("Changes to be undone are outside visible portion of buffer");
605 SET_PT (pos);
606
b2adc409
RS
607 /* Now that we record marker adjustments
608 (caused by deletion) for undo,
609 we should always insert after markers,
610 so that undoing the marker adjustments
611 put the markers back in the right place. */
612 Finsert (1, &membuf);
350bce56
RS
613 SET_PT (pos);
614 }
c6953be1 615 }
714bced9
RS
616 else if (MARKERP (car) && INTEGERP (cdr))
617 {
618 /* (MARKER . INTEGER) means a marker MARKER
619 was adjusted by INTEGER. */
620 if (XMARKER (car)->buffer)
621 Fset_marker (car,
622 make_number (marker_position (car) - XINT (cdr)),
623 Fmarker_buffer (car));
624 }
c6953be1
JB
625 }
626 }
627 arg--;
628 }
629
4ac03187
KS
630
631 /* Make sure an apply entry produces at least one undo entry,
632 so the test in `undo' for continuing an undo series
633 will work right. */
634 if (did_apply
635 && EQ (oldlist, current_buffer->undo_list))
636 current_buffer->undo_list
637 = Fcons (list3 (Qapply, Qcdr, Qnil), current_buffer->undo_list);
638
de65837b 639 UNGCPRO;
f87a68b3 640 return unbind_to (count, list);
c6953be1 641}
6887bce5 642\f
dfcf069d 643void
c6953be1
JB
644syms_of_undo ()
645{
f87a68b3
RS
646 Qinhibit_read_only = intern ("inhibit-read-only");
647 staticpro (&Qinhibit_read_only);
648
49be18c9
KS
649 Qapply = intern ("apply");
650 staticpro (&Qapply);
651
c58632fc
RS
652 pending_boundary = Qnil;
653 staticpro (&pending_boundary);
654
c6953be1
JB
655 defsubr (&Sprimitive_undo);
656 defsubr (&Sundo_boundary);
137e23ea
RS
657
658 DEFVAR_INT ("undo-limit", &undo_limit,
659 doc: /* Keep no more undo information once it exceeds this size.
660This limit is applied when garbage collection happens.
661When a previous command increases the total undo list size past this
662value, the earlier commands that came before it are forgotten.
663
664The size is counted as the number of bytes occupied,
665which includes both saved text and other data. */);
666 undo_limit = 20000;
667
668 DEFVAR_INT ("undo-strong-limit", &undo_strong_limit,
669 doc: /* Don't keep more than this much size of undo information.
670This limit is applied when garbage collection happens.
671When a previous command increases the total undo list size past this
672value, that command and the earlier commands that came before it are forgotten.
673However, the most recent buffer-modifying command's undo info
674is never discarded for this reason.
675
676The size is counted as the number of bytes occupied,
677which includes both saved text and other data. */);
678 undo_strong_limit = 30000;
679
81c1cf71 680 DEFVAR_LISP ("undo-outer-limit", &Vundo_outer_limit,
137e23ea
RS
681 doc: /* Outer limit on size of undo information for one command.
682At garbage collection time, if the current command has produced
62d776fd
LT
683more than this much undo information, it discards the info and displays
684a warning. This is a last-ditch limit to prevent memory overflow.
137e23ea 685
62d776fd
LT
686The size is counted as the number of bytes occupied, which includes
687both saved text and other data. A value of nil means no limit. In
688this case, accumulating one huge undo entry could make Emacs crash as
689a result of memory overflow.
137e23ea
RS
690
691In fact, this calls the function which is the value of
692`undo-outer-limit-function' with one argument, the size.
693The text above describes the behavior of the function
694that variable usually specifies. */);
6de38aa3 695 Vundo_outer_limit = make_number (3000000);
137e23ea
RS
696
697 DEFVAR_LISP ("undo-outer-limit-function", &Vundo_outer_limit_function,
698 doc: /* Function to call when an undo list exceeds `undo-outer-limit'.
699This function is called with one argument, the current undo list size
700for the most recent command (since the last undo boundary).
701If the function returns t, that means truncation has been fully handled.
702If it returns nil, the other forms of truncation are done.
703
704Garbage collection is inhibited around the call to this function,
705so it must make sure not to do a lot of consing. */);
706 Vundo_outer_limit_function = Qnil;
c6953be1 707}
ab5796a9
MB
708
709/* arch-tag: d546ee01-4aed-4ffb-bb8b-eefaae50d38a
710 (do not change this comment) */