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