(scan_lists): Follow coding convention.
[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,
8cabe764 3 2005, 2006, 2007, 2008 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
684d6f5b 9the Free Software Foundation; either version 3, or (at your option)
3b7ad313
EN
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
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, 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"
91e25f5e 27#include "window.h"
c6953be1 28
137e23ea
RS
29/* Limits controlling how much undo information to keep. */
30
31EMACS_INT undo_limit;
32EMACS_INT undo_strong_limit;
81c1cf71
RS
33
34Lisp_Object Vundo_outer_limit;
137e23ea
RS
35
36/* Function to call when undo_outer_limit is exceeded. */
37
38Lisp_Object Vundo_outer_limit_function;
39
c6953be1
JB
40/* Last buffer for which undo information was recorded. */
41Lisp_Object last_undo_buffer;
42
f87a68b3
RS
43Lisp_Object Qinhibit_read_only;
44
49be18c9
KS
45/* Marker for function call undo list elements. */
46
47Lisp_Object Qapply;
48
c58632fc
RS
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
53 an undo-boundary. */
54Lisp_Object pending_boundary;
55
8abe0f97
MR
56/* Nonzero means do not record point in record_point. */
57
58int undo_inhibit_record_point;
59
6396140a 60/* Record point as it was at beginning of this command (if necessary)
8abe0f97 61 and prepare the undo info for recording a change.
6396140a
SM
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. */
c6953be1 64
6396140a
SM
65static void
66record_point (pt)
f45bedd4 67 int pt;
c6953be1 68{
6396140a 69 int at_boundary;
bdbe6f28 70
8abe0f97
MR
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
75 event. */
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
8801a864
KR
83 if (!BUFFERP (last_undo_buffer)
84 || current_buffer != XBUFFER (last_undo_buffer))
c6953be1 85 Fundo_boundary ();
552bdbcf 86 XSETBUFFER (last_undo_buffer, current_buffer);
c6953be1 87
6396140a
SM
88 if (CONSP (current_buffer->undo_list))
89 {
90 /* Set AT_BOUNDARY to 1 only when we have nothing other than
91 marker adjustment before undo boundary. */
92
93 Lisp_Object tail = current_buffer->undo_list, elt;
94
95 while (1)
96 {
97 if (NILP (tail))
98 elt = Qnil;
99 else
100 elt = XCAR (tail);
101 if (NILP (elt) || ! (CONSP (elt) && MARKERP (XCAR (elt))))
102 break;
103 tail = XCDR (tail);
104 }
105 at_boundary = NILP (elt);
106 }
107 else
108 at_boundary = 1;
109
ad9cdce4 110 if (MODIFF <= SAVE_MODIFF)
c6953be1
JB
111 record_first_change ();
112
177c0ea7 113 /* If we are just after an undo boundary, and
6396140a
SM
114 point wasn't at start of deleted range, record where it was. */
115 if (at_boundary
6396140a 116 && BUFFERP (last_point_position_buffer)
91e25f5e 117 /* If we're called from batch mode, this could be nil. */
6396140a 118 && current_buffer == XBUFFER (last_point_position_buffer))
91e25f5e
RS
119 {
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);
124
125 if (last_point_position != pt)
126 current_buffer->undo_list
127 = Fcons (make_number (last_point_position), current_buffer->undo_list);
128 }
6396140a
SM
129}
130
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.) */
135
136void
137record_insert (beg, length)
138 int beg, length;
139{
140 Lisp_Object lbeg, lend;
141
142 if (EQ (current_buffer->undo_list, Qt))
143 return;
144
145 record_point (beg);
146
c6953be1
JB
147 /* If this is following another insertion and consecutive with it
148 in the buffer, combine the two. */
38c0d37c 149 if (CONSP (current_buffer->undo_list))
c6953be1
JB
150 {
151 Lisp_Object elt;
c1d497be 152 elt = XCAR (current_buffer->undo_list);
38c0d37c 153 if (CONSP (elt)
c1d497be
KR
154 && INTEGERP (XCAR (elt))
155 && INTEGERP (XCDR (elt))
156 && XINT (XCDR (elt)) == beg)
c6953be1 157 {
f3fbd155 158 XSETCDR (elt, make_number (beg + length));
c6953be1
JB
159 return;
160 }
161 }
162
53480e99
KH
163 XSETFASTINT (lbeg, beg);
164 XSETINT (lend, beg + length);
213861c7
JB
165 current_buffer->undo_list = Fcons (Fcons (lbeg, lend),
166 current_buffer->undo_list);
c6953be1
JB
167}
168
169/* Record that a deletion is about to take place,
e928d437 170 of the characters in STRING, at location BEG. */
c6953be1 171
ff1aa840 172void
e928d437
RS
173record_delete (beg, string)
174 int beg;
175 Lisp_Object string;
c6953be1 176{
e928d437 177 Lisp_Object sbeg;
c6953be1 178
bdbe6f28
RS
179 if (EQ (current_buffer->undo_list, Qt))
180 return;
181
d5db4077 182 if (PT == beg + SCHARS (string))
cbc1b668 183 {
6396140a
SM
184 XSETINT (sbeg, -beg);
185 record_point (PT);
cbc1b668
KH
186 }
187 else
6396140a
SM
188 {
189 XSETFASTINT (sbeg, beg);
190 record_point (beg);
191 }
350bce56 192
c6953be1 193 current_buffer->undo_list
e928d437 194 = Fcons (Fcons (string, sbeg), current_buffer->undo_list);
c6953be1
JB
195}
196
714bced9
RS
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. */
201
ff1aa840 202void
714bced9
RS
203record_marker_adjustment (marker, adjustment)
204 Lisp_Object marker;
205 int adjustment;
206{
207 if (EQ (current_buffer->undo_list, Qt))
208 return;
209
210 /* Allocate a cons cell to be the undo boundary after this command. */
211 if (NILP (pending_boundary))
212 pending_boundary = Fcons (Qnil, Qnil);
213
177c0ea7 214 if (!BUFFERP (last_undo_buffer)
2f33f38a 215 || current_buffer != XBUFFER (last_undo_buffer))
714bced9
RS
216 Fundo_boundary ();
217 XSETBUFFER (last_undo_buffer, current_buffer);
218
219 current_buffer->undo_list
220 = Fcons (Fcons (marker, make_number (adjustment)),
221 current_buffer->undo_list);
222}
223
c6953be1
JB
224/* Record that a replacement is about to take place,
225 for LENGTH characters at location BEG.
e928d437 226 The replacement must not change the number of characters. */
c6953be1 227
ff1aa840 228void
c6953be1
JB
229record_change (beg, length)
230 int beg, length;
231{
e928d437 232 record_delete (beg, make_buffer_string (beg, beg + length, 1));
c6953be1
JB
233 record_insert (beg, length);
234}
235\f
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. */
239
90dd3e4f 240void
c6953be1
JB
241record_first_change ()
242{
243 Lisp_Object high, low;
ad9cdce4 244 struct buffer *base_buffer = current_buffer;
0736cafe
RS
245
246 if (EQ (current_buffer->undo_list, Qt))
247 return;
248
2f33f38a
GM
249 if (!BUFFERP (last_undo_buffer)
250 || current_buffer != XBUFFER (last_undo_buffer))
0736cafe 251 Fundo_boundary ();
552bdbcf 252 XSETBUFFER (last_undo_buffer, current_buffer);
0736cafe 253
ad9cdce4
RS
254 if (base_buffer->base_buffer)
255 base_buffer = base_buffer->base_buffer;
256
257 XSETFASTINT (high, (base_buffer->modtime >> 16) & 0xffff);
258 XSETFASTINT (low, base_buffer->modtime & 0xffff);
c6953be1
JB
259 current_buffer->undo_list = Fcons (Fcons (Qt, Fcons (high, low)), current_buffer->undo_list);
260}
261
da9319d5
RS
262/* Record a change in property PROP (whose old value was VAL)
263 for LENGTH characters starting at position BEG in BUFFER. */
264
90dd3e4f 265void
da9319d5
RS
266record_property_change (beg, length, prop, value, buffer)
267 int beg, length;
268 Lisp_Object prop, value, buffer;
269{
270 Lisp_Object lbeg, lend, entry;
271 struct buffer *obuf = current_buffer;
272 int boundary = 0;
273
0736cafe 274 if (EQ (XBUFFER (buffer)->undo_list, Qt))
bdbe6f28
RS
275 return;
276
c58632fc
RS
277 /* Allocate a cons cell to be the undo boundary after this command. */
278 if (NILP (pending_boundary))
279 pending_boundary = Fcons (Qnil, Qnil);
280
da9319d5
RS
281 if (!EQ (buffer, last_undo_buffer))
282 boundary = 1;
283 last_undo_buffer = buffer;
284
da9319d5
RS
285 /* Switch temporarily to the buffer that was changed. */
286 current_buffer = XBUFFER (buffer);
287
288 if (boundary)
289 Fundo_boundary ();
290
ad9cdce4 291 if (MODIFF <= SAVE_MODIFF)
da9319d5
RS
292 record_first_change ();
293
552bdbcf
KH
294 XSETINT (lbeg, beg);
295 XSETINT (lend, beg + length);
da9319d5
RS
296 entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend))));
297 current_buffer->undo_list = Fcons (entry, current_buffer->undo_list);
298
299 current_buffer = obuf;
300}
301
c6953be1 302DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0,
8c1a1077
PJ
303 doc: /* Mark a boundary between units of undo.
304An undo command will stop at this point,
305but another undo command will undo to the previous boundary. */)
306 ()
c6953be1
JB
307{
308 Lisp_Object tem;
309 if (EQ (current_buffer->undo_list, Qt))
310 return Qnil;
311 tem = Fcar (current_buffer->undo_list);
265a9e55 312 if (!NILP (tem))
c58632fc
RS
313 {
314 /* One way or another, cons nil onto the front of the undo list. */
315 if (!NILP (pending_boundary))
316 {
317 /* If we have preallocated the cons cell to use here,
318 use that one. */
f3fbd155 319 XSETCDR (pending_boundary, current_buffer->undo_list);
c58632fc
RS
320 current_buffer->undo_list = pending_boundary;
321 pending_boundary = Qnil;
322 }
323 else
324 current_buffer->undo_list = Fcons (Qnil, current_buffer->undo_list);
325 }
c6953be1
JB
326 return Qnil;
327}
328
329/* At garbage collection time, make an undo list shorter at the end,
137e23ea
RS
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. */
333
334void
335truncate_undo_list (b)
336 struct buffer *b;
c6953be1 337{
137e23ea 338 Lisp_Object list;
c6953be1
JB
339 Lisp_Object prev, next, last_boundary;
340 int size_so_far = 0;
341
137e23ea
RS
342 /* Make sure that calling undo-outer-limit-function
343 won't cause another GC. */
344 int count = inhibit_garbage_collection ();
345
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);
351
352 list = b->undo_list;
353
c6953be1
JB
354 prev = Qnil;
355 next = list;
356 last_boundary = Qnil;
357
137e23ea 358 /* If the first element is an undo boundary, skip past it. */
c1d497be 359 if (CONSP (next) && NILP (XCAR (next)))
c6953be1
JB
360 {
361 /* Add in the space occupied by this element and its chain link. */
362 size_so_far += sizeof (struct Lisp_Cons);
363
364 /* Advance to next element. */
365 prev = next;
c1d497be 366 next = XCDR (next);
c6953be1 367 }
e3d5ca1e 368
137e23ea
RS
369 /* Always preserve at least the most recent undo record
370 unless it is really horribly big.
371
372 Skip, skip, skip the undo, skip, skip, skip the undo,
373 Skip, skip, skip the undo, skip to the undo bound'ry. */
374
c1d497be 375 while (CONSP (next) && ! NILP (XCAR (next)))
c6953be1
JB
376 {
377 Lisp_Object elt;
c1d497be 378 elt = XCAR (next);
c6953be1
JB
379
380 /* Add in the space occupied by this element and its chain link. */
381 size_so_far += sizeof (struct Lisp_Cons);
38c0d37c 382 if (CONSP (elt))
c6953be1
JB
383 {
384 size_so_far += sizeof (struct Lisp_Cons);
c1d497be 385 if (STRINGP (XCAR (elt)))
c6953be1 386 size_so_far += (sizeof (struct Lisp_String) - 1
d5db4077 387 + SCHARS (XCAR (elt)));
c6953be1
JB
388 }
389
390 /* Advance to next element. */
391 prev = next;
c1d497be 392 next = XCDR (next);
c6953be1 393 }
e3d5ca1e 394
137e23ea
RS
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. */
81c1cf71
RS
397 if (INTEGERP (Vundo_outer_limit)
398 && size_so_far > XINT (Vundo_outer_limit)
137e23ea
RS
399 && !NILP (Vundo_outer_limit_function))
400 {
88fde92a 401 Lisp_Object temp = last_undo_buffer, tem;
137e23ea
RS
402
403 /* Normally the function this calls is undo-outer-limit-truncate. */
88fde92a
KR
404 tem = call1 (Vundo_outer_limit_function, make_number (size_so_far));
405 if (! NILP (tem))
137e23ea
RS
406 {
407 /* The function is responsible for making
408 any desired changes in buffer-undo-list. */
409 unbind_to (count, Qnil);
410 return;
411 }
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;
416 }
417
38c0d37c 418 if (CONSP (next))
c6953be1
JB
419 last_boundary = prev;
420
137e23ea 421 /* Keep additional undo data, if it fits in the limits. */
38c0d37c 422 while (CONSP (next))
c6953be1
JB
423 {
424 Lisp_Object elt;
c1d497be 425 elt = XCAR (next);
c6953be1
JB
426
427 /* When we get to a boundary, decide whether to truncate
137e23ea 428 either before or after it. The lower threshold, undo_limit,
c6953be1 429 tells us to truncate after it. If its size pushes past
137e23ea 430 the higher threshold undo_strong_limit, we truncate before it. */
265a9e55 431 if (NILP (elt))
c6953be1 432 {
137e23ea 433 if (size_so_far > undo_strong_limit)
c6953be1
JB
434 break;
435 last_boundary = prev;
137e23ea 436 if (size_so_far > undo_limit)
c6953be1
JB
437 break;
438 }
439
440 /* Add in the space occupied by this element and its chain link. */
441 size_so_far += sizeof (struct Lisp_Cons);
38c0d37c 442 if (CONSP (elt))
c6953be1
JB
443 {
444 size_so_far += sizeof (struct Lisp_Cons);
c1d497be 445 if (STRINGP (XCAR (elt)))
c6953be1 446 size_so_far += (sizeof (struct Lisp_String) - 1
d5db4077 447 + SCHARS (XCAR (elt)));
c6953be1
JB
448 }
449
450 /* Advance to next element. */
451 prev = next;
c1d497be 452 next = XCDR (next);
c6953be1
JB
453 }
454
455 /* If we scanned the whole list, it is short enough; don't change it. */
265a9e55 456 if (NILP (next))
137e23ea 457 ;
c6953be1 458 /* Truncate at the boundary where we decided to truncate. */
137e23ea
RS
459 else if (!NILP (last_boundary))
460 XSETCDR (last_boundary, Qnil);
461 /* There's nothing we decided to keep, so clear it out. */
c6953be1 462 else
137e23ea
RS
463 b->undo_list = Qnil;
464
465 unbind_to (count, Qnil);
c6953be1
JB
466}
467\f
468DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
8c1a1077
PJ
469 doc: /* Undo N records from the front of the list LIST.
470Return what remains of the list. */)
471 (n, list)
063fb61f 472 Lisp_Object n, list;
c6953be1 473{
de65837b
KH
474 struct gcpro gcpro1, gcpro2;
475 Lisp_Object next;
331379bf 476 int count = SPECPDL_INDEX ();
de65837b 477 register int arg;
4ac03187
KS
478 Lisp_Object oldlist;
479 int did_apply = 0;
177c0ea7 480
c6953be1
JB
481#if 0 /* This is a good feature, but would make undo-start
482 unable to do what is expected. */
483 Lisp_Object tem;
484
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. */
487 tem = Fcar (list);
265a9e55 488 if (NILP (tem))
c6953be1
JB
489 list = Fcdr (list);
490#endif
491
b7826503 492 CHECK_NUMBER (n);
de65837b
KH
493 arg = XINT (n);
494 next = Qnil;
495 GCPRO2 (next, list);
4ac03187
KS
496 /* I don't think we need to gcpro oldlist, as we use it only
497 to check for EQ. ++kfs */
de65837b 498
38d56be3
GM
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))
f87a68b3
RS
502 specbind (Qinhibit_read_only, Qt);
503
8c757fd7
GM
504 /* Don't let `intangible' properties interfere with undo. */
505 specbind (Qinhibit_point_motion_hooks, Qt);
506
4ac03187
KS
507 oldlist = current_buffer->undo_list;
508
c6953be1
JB
509 while (arg > 0)
510 {
c3b09bbf 511 while (CONSP (list))
c6953be1 512 {
c3b09bbf
SM
513 next = XCAR (list);
514 list = XCDR (list);
350bce56 515 /* Exit inner loop at undo boundary. */
265a9e55 516 if (NILP (next))
c6953be1 517 break;
350bce56 518 /* Handle an integer by setting point to that value. */
38c0d37c 519 if (INTEGERP (next))
350bce56 520 SET_PT (clip_to_bounds (BEGV, XINT (next), ZV));
38c0d37c 521 else if (CONSP (next))
c6953be1 522 {
350bce56
RS
523 Lisp_Object car, cdr;
524
c3b09bbf
SM
525 car = XCAR (next);
526 cdr = XCDR (next);
350bce56 527 if (EQ (car, Qt))
c6953be1 528 {
350bce56
RS
529 /* Element (t high . low) records previous modtime. */
530 Lisp_Object high, low;
531 int mod_time;
ad9cdce4 532 struct buffer *base_buffer = current_buffer;
350bce56
RS
533
534 high = Fcar (cdr);
535 low = Fcdr (cdr);
d8552b2f 536 mod_time = (XFASTINT (high) << 16) + XFASTINT (low);
ad9cdce4
RS
537
538 if (current_buffer->base_buffer)
539 base_buffer = current_buffer->base_buffer;
540
350bce56
RS
541 /* If this records an obsolete save
542 (not matching the actual disk file)
543 then don't mark unmodified. */
ad9cdce4 544 if (mod_time != base_buffer->modtime)
103dcb38 545 continue;
e6dd6080 546#ifdef CLASH_DETECTION
350bce56 547 Funlock_buffer ();
e6dd6080 548#endif /* CLASH_DETECTION */
350bce56 549 Fset_buffer_modified_p (Qnil);
c6953be1 550 }
d8552b2f 551 else if (EQ (car, Qnil))
da9319d5 552 {
6887bce5 553 /* Element (nil PROP VAL BEG . END) is property change. */
da9319d5
RS
554 Lisp_Object beg, end, prop, val;
555
556 prop = Fcar (cdr);
557 cdr = Fcdr (cdr);
558 val = Fcar (cdr);
559 cdr = Fcdr (cdr);
560 beg = Fcar (cdr);
561 end = Fcdr (cdr);
562
9e568684
CY
563 if (XINT (beg) < BEGV || XINT (end) > ZV)
564 error ("Changes to be undone are outside visible portion of buffer");
da9319d5
RS
565 Fput_text_property (beg, end, prop, val, Qnil);
566 }
38c0d37c 567 else if (INTEGERP (car) && INTEGERP (cdr))
c6953be1 568 {
350bce56 569 /* Element (BEG . END) means range was inserted. */
350bce56
RS
570
571 if (XINT (car) < BEGV
572 || XINT (cdr) > ZV)
c6953be1 573 error ("Changes to be undone are outside visible portion of buffer");
f28f04cc
RS
574 /* Set point first thing, so that undoing this undo
575 does not send point back to where it is now. */
350bce56 576 Fgoto_char (car);
f28f04cc 577 Fdelete_region (car, cdr);
350bce56 578 }
49be18c9 579 else if (EQ (car, Qapply))
6887bce5 580 {
3419757d 581 /* Element (apply FUN . ARGS) means call FUN to undo. */
a7a39468
KS
582 struct buffer *save_buffer = current_buffer;
583
49be18c9 584 car = Fcar (cdr);
3419757d 585 cdr = Fcdr (cdr);
49be18c9
KS
586 if (INTEGERP (car))
587 {
3419757d
SM
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);
594
595 cdr = Fcdr (Fcdr (cdr));
596 apply1 (Fcar (cdr), Fcdr (cdr));
597
598 /* Check that the function did what the entry said it
599 would do. */
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);
49be18c9 606 }
3419757d
SM
607 else
608 apply1 (car, cdr);
a7a39468
KS
609
610 if (save_buffer != current_buffer)
611 error ("Undo function switched buffer");
4ac03187 612 did_apply = 1;
6887bce5 613 }
38c0d37c 614 else if (STRINGP (car) && INTEGERP (cdr))
350bce56
RS
615 {
616 /* Element (STRING . POS) means STRING was deleted. */
617 Lisp_Object membuf;
618 int pos = XINT (cdr);
619
620 membuf = car;
621 if (pos < 0)
622 {
623 if (-pos < BEGV || -pos > ZV)
624 error ("Changes to be undone are outside visible portion of buffer");
625 SET_PT (-pos);
626 Finsert (1, &membuf);
627 }
628 else
629 {
630 if (pos < BEGV || pos > ZV)
631 error ("Changes to be undone are outside visible portion of buffer");
632 SET_PT (pos);
633
b2adc409
RS
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);
350bce56
RS
640 SET_PT (pos);
641 }
c6953be1 642 }
714bced9
RS
643 else if (MARKERP (car) && INTEGERP (cdr))
644 {
645 /* (MARKER . INTEGER) means a marker MARKER
646 was adjusted by INTEGER. */
647 if (XMARKER (car)->buffer)
648 Fset_marker (car,
649 make_number (marker_position (car) - XINT (cdr)),
650 Fmarker_buffer (car));
651 }
c6953be1
JB
652 }
653 }
654 arg--;
655 }
656
4ac03187
KS
657
658 /* Make sure an apply entry produces at least one undo entry,
659 so the test in `undo' for continuing an undo series
660 will work right. */
661 if (did_apply
662 && EQ (oldlist, current_buffer->undo_list))
663 current_buffer->undo_list
664 = Fcons (list3 (Qapply, Qcdr, Qnil), current_buffer->undo_list);
665
de65837b 666 UNGCPRO;
f87a68b3 667 return unbind_to (count, list);
c6953be1 668}
6887bce5 669\f
dfcf069d 670void
c6953be1
JB
671syms_of_undo ()
672{
f87a68b3
RS
673 Qinhibit_read_only = intern ("inhibit-read-only");
674 staticpro (&Qinhibit_read_only);
675
49be18c9
KS
676 Qapply = intern ("apply");
677 staticpro (&Qapply);
678
c58632fc
RS
679 pending_boundary = Qnil;
680 staticpro (&pending_boundary);
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. */);
693 undo_limit = 20000;
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. */);
705 undo_strong_limit = 30000;
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. */);
6de38aa3 722 Vundo_outer_limit = make_number (3000000);
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) */