This source file includes following definitions.
- prepare_record
- record_point
- record_insert
- record_marker_adjustments
- record_delete
- record_change
- record_first_change
- record_property_change
- DEFUN
- truncate_undo_list
- syms_of_undo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include "lisp.h"
24 #include "buffer.h"
25 #include "keyboard.h"
26
27
28
29
30
31
32 static Lisp_Object pending_boundary;
33
34
35 static void
36 prepare_record (void)
37 {
38
39 if (NILP (pending_boundary))
40 pending_boundary = Fcons (Qnil, Qnil);
41 }
42
43
44
45
46
47 static void
48 record_point (ptrdiff_t beg)
49 {
50
51 if (undo_inhibit_record_point)
52 return;
53
54 bool at_boundary;
55
56
57
58
59
60 at_boundary = ! CONSP (BVAR (current_buffer, undo_list))
61 || NILP (XCAR (BVAR (current_buffer, undo_list)));
62
63
64 if (MODIFF <= SAVE_MODIFF)
65 record_first_change ();
66
67
68
69
70
71
72
73 if (at_boundary
74 && point_before_last_command_or_undo != beg
75 && buffer_before_last_command_or_undo == current_buffer )
76 bset_undo_list (current_buffer,
77 Fcons (make_fixnum (point_before_last_command_or_undo),
78 BVAR (current_buffer, undo_list)));
79 }
80
81
82
83
84
85
86 void
87 record_insert (ptrdiff_t beg, ptrdiff_t length)
88 {
89 Lisp_Object lbeg, lend;
90
91 if (EQ (BVAR (current_buffer, undo_list), Qt))
92 return;
93
94 prepare_record ();
95
96 record_point (beg);
97
98
99
100 if (CONSP (BVAR (current_buffer, undo_list)))
101 {
102 Lisp_Object elt;
103 elt = XCAR (BVAR (current_buffer, undo_list));
104 if (CONSP (elt)
105 && FIXNUMP (XCAR (elt))
106 && FIXNUMP (XCDR (elt))
107 && XFIXNUM (XCDR (elt)) == beg)
108 {
109 XSETCDR (elt, make_fixnum (beg + length));
110 return;
111 }
112 }
113
114 XSETFASTINT (lbeg, beg);
115 XSETINT (lend, beg + length);
116 bset_undo_list (current_buffer,
117 Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list)));
118 }
119
120
121
122
123
124
125
126 static void
127 record_marker_adjustments (ptrdiff_t from, ptrdiff_t to)
128 {
129 prepare_record ();
130
131 for (struct Lisp_Marker *m = BUF_MARKERS (current_buffer); m; m = m->next)
132 {
133 ptrdiff_t charpos = m->charpos;
134 eassert (charpos <= Z);
135
136 if (from <= charpos && charpos <= to)
137 {
138
139
140
141
142
143
144
145 ptrdiff_t adjustment = (m->insertion_type ? to : from) - charpos;
146
147 if (adjustment)
148 {
149 Lisp_Object marker = make_lisp_ptr (m, Lisp_Vectorlike);
150 bset_undo_list
151 (current_buffer,
152 Fcons (Fcons (marker, make_fixnum (adjustment)),
153 BVAR (current_buffer, undo_list)));
154 }
155 }
156 }
157 }
158
159
160
161
162 void
163 record_delete (ptrdiff_t beg, Lisp_Object string, bool record_markers)
164 {
165 Lisp_Object sbeg;
166
167 if (EQ (BVAR (current_buffer, undo_list), Qt))
168 return;
169
170 prepare_record ();
171
172 record_point (beg);
173
174 if (PT == beg + SCHARS (string))
175 {
176 XSETINT (sbeg, -beg);
177 }
178 else
179 {
180 XSETFASTINT (sbeg, beg);
181 }
182
183
184
185
186 if (record_markers)
187 record_marker_adjustments (beg, beg + SCHARS (string));
188
189 bset_undo_list
190 (current_buffer,
191 Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list)));
192 }
193
194
195
196
197
198 void
199 record_change (ptrdiff_t beg, ptrdiff_t length)
200 {
201 record_delete (beg, make_buffer_string (beg, beg + length, true), false);
202 record_insert (beg, length);
203 }
204
205
206
207
208
209 void
210 record_first_change (void)
211 {
212 struct buffer *base_buffer = current_buffer;
213
214 if (EQ (BVAR (current_buffer, undo_list), Qt))
215 return;
216
217 if (base_buffer->base_buffer)
218 base_buffer = base_buffer->base_buffer;
219
220 bset_undo_list (current_buffer,
221 Fcons (Fcons (Qt, buffer_visited_file_modtime (base_buffer)),
222 BVAR (current_buffer, undo_list)));
223 }
224
225
226
227
228 void
229 record_property_change (ptrdiff_t beg, ptrdiff_t length,
230 Lisp_Object prop, Lisp_Object value,
231 Lisp_Object buffer)
232 {
233 Lisp_Object lbeg, lend, entry;
234 struct buffer *buf = XBUFFER (buffer);
235
236 if (EQ (BVAR (buf, undo_list), Qt))
237 return;
238
239 prepare_record();
240
241 if (MODIFF <= SAVE_MODIFF)
242 record_first_change ();
243
244 XSETINT (lbeg, beg);
245 XSETINT (lend, beg + length);
246 entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend))));
247 bset_undo_list (current_buffer,
248 Fcons (entry, BVAR (current_buffer, undo_list)));
249 }
250
251 DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0,
252 doc:
253
254 )
255 (void)
256 {
257 Lisp_Object tem;
258 if (EQ (BVAR (current_buffer, undo_list), Qt))
259 return Qnil;
260 tem = Fcar (BVAR (current_buffer, undo_list));
261 if (!NILP (tem))
262 {
263
264 if (!NILP (pending_boundary))
265 {
266
267
268 XSETCDR (pending_boundary, BVAR (current_buffer, undo_list));
269 bset_undo_list (current_buffer, pending_boundary);
270 pending_boundary = Qnil;
271 }
272 else
273 bset_undo_list (current_buffer,
274 Fcons (Qnil, BVAR (current_buffer, undo_list)));
275 }
276
277 Fset (Qundo_auto__last_boundary_cause, Qexplicit);
278 point_before_last_command_or_undo = PT;
279 buffer_before_last_command_or_undo = current_buffer;
280
281 return Qnil;
282 }
283
284
285
286
287
288
289 void
290 truncate_undo_list (struct buffer *b)
291 {
292 Lisp_Object list;
293 Lisp_Object prev, next, last_boundary;
294 intmax_t size_so_far = 0;
295
296
297
298 specpdl_ref count = inhibit_garbage_collection ();
299
300
301
302
303 record_unwind_current_buffer ();
304 set_buffer_internal (b);
305
306 list = BVAR (b, undo_list);
307
308 prev = Qnil;
309 next = list;
310 last_boundary = Qnil;
311
312
313 if (CONSP (next) && NILP (XCAR (next)))
314 {
315
316 size_so_far += sizeof (struct Lisp_Cons);
317
318
319 prev = next;
320 next = XCDR (next);
321 }
322
323
324
325
326
327
328
329 while (CONSP (next) && ! NILP (XCAR (next)))
330 {
331 Lisp_Object elt;
332 elt = XCAR (next);
333
334
335 size_so_far += sizeof (struct Lisp_Cons);
336 if (CONSP (elt))
337 {
338 size_so_far += sizeof (struct Lisp_Cons);
339 if (STRINGP (XCAR (elt)))
340 size_so_far += (sizeof (struct Lisp_String) - 1
341 + SCHARS (XCAR (elt)));
342 }
343
344
345 prev = next;
346 next = XCDR (next);
347 }
348
349
350
351 intmax_t undo_outer_limit;
352 if ((INTEGERP (Vundo_outer_limit)
353 && (integer_to_intmax (Vundo_outer_limit, &undo_outer_limit)
354 ? undo_outer_limit < size_so_far
355 : NILP (Fnatnump (Vundo_outer_limit))))
356 && !NILP (Vundo_outer_limit_function))
357 {
358 Lisp_Object tem;
359
360
361 tem = call1 (Vundo_outer_limit_function, make_int (size_so_far));
362 if (! NILP (tem))
363 {
364
365
366 unbind_to (count, Qnil);
367 return;
368 }
369 }
370
371 if (CONSP (next))
372 last_boundary = prev;
373
374
375 while (CONSP (next))
376 {
377 Lisp_Object elt;
378 elt = XCAR (next);
379
380
381
382
383
384 if (NILP (elt))
385 {
386 if (size_so_far > undo_strong_limit)
387 break;
388 last_boundary = prev;
389 if (size_so_far > undo_limit)
390 break;
391 }
392
393
394 size_so_far += sizeof (struct Lisp_Cons);
395 if (CONSP (elt))
396 {
397 size_so_far += sizeof (struct Lisp_Cons);
398 if (STRINGP (XCAR (elt)))
399 size_so_far += (sizeof (struct Lisp_String) - 1
400 + SCHARS (XCAR (elt)));
401 }
402
403
404 prev = next;
405 next = XCDR (next);
406 }
407
408
409 if (NILP (next))
410 ;
411
412 else if (!NILP (last_boundary))
413 XSETCDR (last_boundary, Qnil);
414
415 else
416 bset_undo_list (b, Qnil);
417
418 unbind_to (count, Qnil);
419 }
420
421
422 void
423 syms_of_undo (void)
424 {
425 DEFSYM (Qinhibit_read_only, "inhibit-read-only");
426 DEFSYM (Qundo_auto__last_boundary_cause, "undo-auto--last-boundary-cause");
427 DEFSYM (Qexplicit, "explicit");
428
429
430 DEFSYM (Qapply, "apply");
431
432 pending_boundary = Qnil;
433 staticpro (&pending_boundary);
434
435 defsubr (&Sundo_boundary);
436
437 DEFVAR_INT ("undo-limit", undo_limit,
438 doc:
439
440
441
442
443
444 );
445 undo_limit = 160000;
446
447 DEFVAR_INT ("undo-strong-limit", undo_strong_limit,
448 doc:
449
450
451
452
453
454
455
456 );
457 undo_strong_limit = 240000;
458
459 DEFVAR_LISP ("undo-outer-limit", Vundo_outer_limit,
460 doc:
461
462
463
464
465
466
467
468
469
470
471
472
473 );
474 Vundo_outer_limit = make_fixnum (24000000);
475
476 DEFVAR_LISP ("undo-outer-limit-function", Vundo_outer_limit_function,
477 doc:
478
479
480
481
482
483
484 );
485 Vundo_outer_limit_function = Qnil;
486
487 DEFVAR_BOOL ("undo-inhibit-record-point", undo_inhibit_record_point,
488 doc: );
489 undo_inhibit_record_point = false;
490 }