(insert_from_buffer, insert_from_buffer_1): New functions.
[bpt/emacs.git] / src / insdel.c
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 #include <config.h>
22 #include "lisp.h"
23 #include "intervals.h"
24 #include "buffer.h"
25 #include "window.h"
26 #include "blockinput.h"
27
28 static void insert_1 ();
29 static void insert_from_string_1 ();
30 static void insert_from_buffer_1 ();
31 static void gap_left ();
32 static void gap_right ();
33 static void adjust_markers ();
34 static void adjust_point ();
35
36 /* Move gap to position `pos'.
37 Note that this can quit! */
38
39 move_gap (pos)
40 int pos;
41 {
42 if (pos < GPT)
43 gap_left (pos, 0);
44 else if (pos > GPT)
45 gap_right (pos);
46 }
47
48 /* Move the gap to POS, which is less than the current GPT.
49 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
50
51 static void
52 gap_left (pos, newgap)
53 register int pos;
54 int newgap;
55 {
56 register unsigned char *to, *from;
57 register int i;
58 int new_s1;
59
60 pos--;
61
62 if (!newgap)
63 {
64 if (unchanged_modified == MODIFF)
65 {
66 beg_unchanged = pos;
67 end_unchanged = Z - pos - 1;
68 }
69 else
70 {
71 if (Z - GPT < end_unchanged)
72 end_unchanged = Z - GPT;
73 if (pos < beg_unchanged)
74 beg_unchanged = pos;
75 }
76 }
77
78 i = GPT;
79 to = GAP_END_ADDR;
80 from = GPT_ADDR;
81 new_s1 = GPT - BEG;
82
83 /* Now copy the characters. To move the gap down,
84 copy characters up. */
85
86 while (1)
87 {
88 /* I gets number of characters left to copy. */
89 i = new_s1 - pos;
90 if (i == 0)
91 break;
92 /* If a quit is requested, stop copying now.
93 Change POS to be where we have actually moved the gap to. */
94 if (QUITP)
95 {
96 pos = new_s1;
97 break;
98 }
99 /* Move at most 32000 chars before checking again for a quit. */
100 if (i > 32000)
101 i = 32000;
102 #ifdef GAP_USE_BCOPY
103 if (i >= 128
104 /* bcopy is safe if the two areas of memory do not overlap
105 or on systems where bcopy is always safe for moving upward. */
106 && (BCOPY_UPWARD_SAFE
107 || to - from >= 128))
108 {
109 /* If overlap is not safe, avoid it by not moving too many
110 characters at once. */
111 if (!BCOPY_UPWARD_SAFE && i > to - from)
112 i = to - from;
113 new_s1 -= i;
114 from -= i, to -= i;
115 bcopy (from, to, i);
116 }
117 else
118 #endif
119 {
120 new_s1 -= i;
121 while (--i >= 0)
122 *--to = *--from;
123 }
124 }
125
126 /* Adjust markers, and buffer data structure, to put the gap at POS.
127 POS is where the loop above stopped, which may be what was specified
128 or may be where a quit was detected. */
129 adjust_markers (pos + 1, GPT, GAP_SIZE);
130 GPT = pos + 1;
131 QUIT;
132 }
133
134 static void
135 gap_right (pos)
136 register int pos;
137 {
138 register unsigned char *to, *from;
139 register int i;
140 int new_s1;
141
142 pos--;
143
144 if (unchanged_modified == MODIFF)
145 {
146 beg_unchanged = pos;
147 end_unchanged = Z - pos - 1;
148 }
149 else
150 {
151 if (Z - pos - 1 < end_unchanged)
152 end_unchanged = Z - pos - 1;
153 if (GPT - BEG < beg_unchanged)
154 beg_unchanged = GPT - BEG;
155 }
156
157 i = GPT;
158 from = GAP_END_ADDR;
159 to = GPT_ADDR;
160 new_s1 = GPT - 1;
161
162 /* Now copy the characters. To move the gap up,
163 copy characters down. */
164
165 while (1)
166 {
167 /* I gets number of characters left to copy. */
168 i = pos - new_s1;
169 if (i == 0)
170 break;
171 /* If a quit is requested, stop copying now.
172 Change POS to be where we have actually moved the gap to. */
173 if (QUITP)
174 {
175 pos = new_s1;
176 break;
177 }
178 /* Move at most 32000 chars before checking again for a quit. */
179 if (i > 32000)
180 i = 32000;
181 #ifdef GAP_USE_BCOPY
182 if (i >= 128
183 /* bcopy is safe if the two areas of memory do not overlap
184 or on systems where bcopy is always safe for moving downward. */
185 && (BCOPY_DOWNWARD_SAFE
186 || from - to >= 128))
187 {
188 /* If overlap is not safe, avoid it by not moving too many
189 characters at once. */
190 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
191 i = from - to;
192 new_s1 += i;
193 bcopy (from, to, i);
194 from += i, to += i;
195 }
196 else
197 #endif
198 {
199 new_s1 += i;
200 while (--i >= 0)
201 *to++ = *from++;
202 }
203 }
204
205 adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
206 GPT = pos + 1;
207 QUIT;
208 }
209
210 /* Add `amount' to the position of every marker in the current buffer
211 whose current position is between `from' (exclusive) and `to' (inclusive).
212 Also, any markers past the outside of that interval, in the direction
213 of adjustment, are first moved back to the near end of the interval
214 and then adjusted by `amount'. */
215
216 static void
217 adjust_markers (from, to, amount)
218 register int from, to, amount;
219 {
220 Lisp_Object marker;
221 register struct Lisp_Marker *m;
222 register int mpos;
223
224 marker = current_buffer->markers;
225
226 while (!NILP (marker))
227 {
228 m = XMARKER (marker);
229 mpos = m->bufpos;
230 if (amount > 0)
231 {
232 if (mpos > to && mpos < to + amount)
233 mpos = to + amount;
234 }
235 else
236 {
237 if (mpos > from + amount && mpos <= from)
238 mpos = from + amount;
239 }
240 if (mpos > from && mpos <= to)
241 mpos += amount;
242 m->bufpos = mpos;
243 marker = m->chain;
244 }
245 }
246
247 /* Add the specified amount to point. This is used only when the value
248 of point changes due to an insert or delete; it does not represent
249 a conceptual change in point as a marker. In particular, point is
250 not crossing any interval boundaries, so there's no need to use the
251 usual SET_PT macro. In fact it would be incorrect to do so, because
252 either the old or the new value of point is out of synch with the
253 current set of intervals. */
254 static void
255 adjust_point (amount)
256 {
257 current_buffer->text.pt += amount;
258 }
259 \f
260 /* Make the gap INCREMENT characters longer. */
261
262 make_gap (increment)
263 int increment;
264 {
265 unsigned char *result;
266 Lisp_Object tem;
267 int real_gap_loc;
268 int old_gap_size;
269
270 /* If we have to get more space, get enough to last a while. */
271 increment += 2000;
272
273 BLOCK_INPUT;
274 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
275
276 if (result == 0)
277 {
278 UNBLOCK_INPUT;
279 memory_full ();
280 }
281
282 /* We can't unblock until the new address is properly stored. */
283 BEG_ADDR = result;
284 UNBLOCK_INPUT;
285
286 /* Prevent quitting in move_gap. */
287 tem = Vinhibit_quit;
288 Vinhibit_quit = Qt;
289
290 real_gap_loc = GPT;
291 old_gap_size = GAP_SIZE;
292
293 /* Call the newly allocated space a gap at the end of the whole space. */
294 GPT = Z + GAP_SIZE;
295 GAP_SIZE = increment;
296
297 /* Move the new gap down to be consecutive with the end of the old one.
298 This adjusts the markers properly too. */
299 gap_left (real_gap_loc + old_gap_size, 1);
300
301 /* Now combine the two into one large gap. */
302 GAP_SIZE += old_gap_size;
303 GPT = real_gap_loc;
304
305 Vinhibit_quit = tem;
306 }
307 \f
308 /* Insert a string of specified length before point.
309 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
310 prepare_to_modify_buffer could relocate the text. */
311
312 insert (string, length)
313 register unsigned char *string;
314 register length;
315 {
316 if (length > 0)
317 {
318 insert_1 (string, length, 0);
319 signal_after_change (PT-length, 0, length);
320 }
321 }
322
323 insert_and_inherit (string, length)
324 register unsigned char *string;
325 register length;
326 {
327 if (length > 0)
328 {
329 insert_1 (string, length, 1);
330 signal_after_change (PT-length, 0, length);
331 }
332 }
333
334 static void
335 insert_1 (string, length, inherit)
336 register unsigned char *string;
337 register length;
338 int inherit;
339 {
340 register Lisp_Object temp;
341
342 /* Make sure point-max won't overflow after this insertion. */
343 XSETINT (temp, length + Z);
344 if (length + Z != XINT (temp))
345 error ("maximum buffer size exceeded");
346
347 prepare_to_modify_buffer (PT, PT);
348
349 if (PT != GPT)
350 move_gap (PT);
351 if (GAP_SIZE < length)
352 make_gap (length - GAP_SIZE);
353
354 record_insert (PT, length);
355 MODIFF++;
356
357 bcopy (string, GPT_ADDR, length);
358
359 #ifdef USE_TEXT_PROPERTIES
360 if (current_buffer->intervals != 0)
361 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
362 offset_intervals (current_buffer, PT, length);
363 #endif
364
365 GAP_SIZE -= length;
366 GPT += length;
367 ZV += length;
368 Z += length;
369 adjust_point (length);
370
371 #ifdef USE_TEXT_PROPERTIES
372 if (!inherit && current_buffer->intervals != 0)
373 Fset_text_properties (make_number (PT - length), make_number (PT),
374 Qnil, Qnil);
375 #endif
376 }
377
378 /* Insert the part of the text of STRING, a Lisp object assumed to be
379 of type string, consisting of the LENGTH characters starting at
380 position POS. If the text of STRING has properties, they are absorbed
381 into the buffer.
382
383 It does not work to use `insert' for this, because a GC could happen
384 before we bcopy the stuff into the buffer, and relocate the string
385 without insert noticing. */
386
387 insert_from_string (string, pos, length, inherit)
388 Lisp_Object string;
389 register int pos, length;
390 int inherit;
391 {
392 if (length > 0)
393 {
394 insert_from_string_1 (string, pos, length, inherit);
395 signal_after_change (PT-length, 0, length);
396 }
397 }
398
399 static void
400 insert_from_string_1 (string, pos, length, inherit)
401 Lisp_Object string;
402 register int pos, length;
403 int inherit;
404 {
405 register Lisp_Object temp;
406 struct gcpro gcpro1;
407
408 /* Make sure point-max won't overflow after this insertion. */
409 XSETINT (temp, length + Z);
410 if (length + Z != XINT (temp))
411 error ("maximum buffer size exceeded");
412
413 GCPRO1 (string);
414 prepare_to_modify_buffer (PT, PT);
415
416 if (PT != GPT)
417 move_gap (PT);
418 if (GAP_SIZE < length)
419 make_gap (length - GAP_SIZE);
420
421 record_insert (PT, length);
422 MODIFF++;
423 UNGCPRO;
424
425 bcopy (XSTRING (string)->data, GPT_ADDR, length);
426
427 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
428 offset_intervals (current_buffer, PT, length);
429
430 GAP_SIZE -= length;
431 GPT += length;
432 ZV += length;
433 Z += length;
434
435 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
436 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
437 current_buffer, inherit);
438
439 adjust_point (length);
440 }
441
442 /* Insert text from BUF, starting at POS and having length LENGTH, into the
443 current buffer. If the text in BUF has properties, they are absorbed
444 into the current buffer.
445
446 It does not work to use `insert' for this, because a malloc could happen
447 and relocate BUF's text before the bcopy happens. */
448
449 void
450 insert_from_buffer (buf, pos, length, inherit)
451 struct buffer *buf;
452 int pos, length;
453 int inherit;
454 {
455 if (length > 0)
456 {
457 insert_from_buffer_1 (buf, pos, length, inherit);
458 signal_after_change (PT-length, 0, length);
459 }
460 }
461
462 static void
463 insert_from_buffer_1 (buf, pos, length, inherit)
464 struct buffer *buf;
465 int pos, length;
466 int inherit;
467 {
468 register Lisp_Object temp;
469 int chunk;
470
471 /* Make sure point-max won't overflow after this insertion. */
472 XSETINT (temp, length + Z);
473 if (length + Z != XINT (temp))
474 error ("maximum buffer size exceeded");
475
476 prepare_to_modify_buffer (PT, PT);
477
478 if (PT != GPT)
479 move_gap (PT);
480 if (GAP_SIZE < length)
481 make_gap (length - GAP_SIZE);
482
483 record_insert (PT, length);
484 MODIFF++;
485
486 if (pos < BUF_GPT (buf))
487 {
488 chunk = min (length, BUF_GPT (buf) - pos);
489 bcopy (BUF_CHAR_ADDRESS (buf, pos), GPT_ADDR, chunk);
490 }
491 else
492 chunk = 0;
493 if (chunk < length)
494 bcopy (BUF_CHAR_ADDRESS (buf, pos + chunk),
495 GPT_ADDR + chunk, length - chunk);
496
497 #ifdef USE_TEXT_PROPERTIES
498 if (current_buffer->intervals != 0)
499 offset_intervals (current_buffer, PT, length);
500 #endif
501
502 GAP_SIZE -= length;
503 GPT += length;
504 ZV += length;
505 Z += length;
506 adjust_point (length);
507
508 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
509 graft_intervals_into_buffer (copy_intervals (buf->intervals, pos, length),
510 PT - length, length, current_buffer, inherit);
511 }
512
513 /* Insert the character C before point */
514
515 void
516 insert_char (c)
517 unsigned char c;
518 {
519 insert (&c, 1);
520 }
521
522 /* Insert the null-terminated string S before point */
523
524 void
525 insert_string (s)
526 char *s;
527 {
528 insert (s, strlen (s));
529 }
530
531 /* Like `insert' except that all markers pointing at the place where
532 the insertion happens are adjusted to point after it.
533 Don't use this function to insert part of a Lisp string,
534 since gc could happen and relocate it. */
535
536 insert_before_markers (string, length)
537 unsigned char *string;
538 register int length;
539 {
540 if (length > 0)
541 {
542 register int opoint = PT;
543 insert_1 (string, length, 0);
544 adjust_markers (opoint - 1, opoint, length);
545 signal_after_change (PT-length, 0, length);
546 }
547 }
548
549 insert_before_markers_and_inherit (string, length)
550 unsigned char *string;
551 register int length;
552 {
553 if (length > 0)
554 {
555 register int opoint = PT;
556 insert_1 (string, length, 1);
557 adjust_markers (opoint - 1, opoint, length);
558 signal_after_change (PT-length, 0, length);
559 }
560 }
561
562 /* Insert part of a Lisp string, relocating markers after. */
563
564 insert_from_string_before_markers (string, pos, length, inherit)
565 Lisp_Object string;
566 register int pos, length;
567 int inherit;
568 {
569 if (length > 0)
570 {
571 register int opoint = PT;
572 insert_from_string_1 (string, pos, length, inherit);
573 adjust_markers (opoint - 1, opoint, length);
574 signal_after_change (PT-length, 0, length);
575 }
576 }
577 \f
578 /* Delete characters in current buffer
579 from FROM up to (but not including) TO. */
580
581 del_range (from, to)
582 register int from, to;
583 {
584 return del_range_1 (from, to, 1);
585 }
586
587 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
588
589 del_range_1 (from, to, prepare)
590 register int from, to, prepare;
591 {
592 register int numdel;
593
594 /* Make args be valid */
595 if (from < BEGV)
596 from = BEGV;
597 if (to > ZV)
598 to = ZV;
599
600 if ((numdel = to - from) <= 0)
601 return;
602
603 /* Make sure the gap is somewhere in or next to what we are deleting. */
604 if (from > GPT)
605 gap_right (from);
606 if (to < GPT)
607 gap_left (to, 0);
608
609 if (prepare)
610 prepare_to_modify_buffer (from, to);
611
612 record_delete (from, numdel);
613 MODIFF++;
614
615 /* Relocate point as if it were a marker. */
616 if (from < PT)
617 adjust_point (from - (PT < to ? PT : to));
618
619 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
620 offset_intervals (current_buffer, from, - numdel);
621
622 /* Relocate all markers pointing into the new, larger gap
623 to point at the end of the text before the gap. */
624 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
625
626 GAP_SIZE += numdel;
627 ZV -= numdel;
628 Z -= numdel;
629 GPT = from;
630
631 if (GPT - BEG < beg_unchanged)
632 beg_unchanged = GPT - BEG;
633 if (Z - GPT < end_unchanged)
634 end_unchanged = Z - GPT;
635
636 evaporate_overlays (from);
637 signal_after_change (from, numdel, 0);
638 }
639 \f
640 /* Call this if you're about to change the region of BUFFER from START
641 to END. This checks the read-only properties of the region, calls
642 the necessary modification hooks, and warns the next redisplay that
643 it should pay attention to that area. */
644 modify_region (buffer, start, end)
645 struct buffer *buffer;
646 int start, end;
647 {
648 struct buffer *old_buffer = current_buffer;
649
650 if (buffer != old_buffer)
651 set_buffer_internal (buffer);
652
653 prepare_to_modify_buffer (start, end);
654
655 if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
656 beg_unchanged = start - 1;
657 if (Z - end < end_unchanged
658 || unchanged_modified == MODIFF)
659 end_unchanged = Z - end;
660
661 if (MODIFF <= current_buffer->save_modified)
662 record_first_change ();
663 MODIFF++;
664
665 if (buffer != old_buffer)
666 set_buffer_internal (old_buffer);
667 }
668
669 /* Check that it is okay to modify the buffer between START and END.
670 Run the before-change-function, if any. If intervals are in use,
671 verify that the text to be modified is not read-only, and call
672 any modification properties the text may have. */
673
674 prepare_to_modify_buffer (start, end)
675 Lisp_Object start, end;
676 {
677 if (!NILP (current_buffer->read_only))
678 Fbarf_if_buffer_read_only ();
679
680 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
681 if (current_buffer->intervals != 0)
682 verify_interval_modification (current_buffer, start, end);
683
684 if (!NILP (current_buffer->overlays_before)
685 || !NILP (current_buffer->overlays_after))
686 verify_overlay_modification (start, end);
687
688 #ifdef CLASH_DETECTION
689 if (!NILP (current_buffer->filename)
690 && current_buffer->save_modified >= MODIFF)
691 lock_file (current_buffer->filename);
692 #else
693 /* At least warn if this file has changed on disk since it was visited. */
694 if (!NILP (current_buffer->filename)
695 && current_buffer->save_modified >= MODIFF
696 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
697 && !NILP (Ffile_exists_p (current_buffer->filename)))
698 call1 (intern ("ask-user-about-supersession-threat"),
699 current_buffer->filename);
700 #endif /* not CLASH_DETECTION */
701
702 signal_before_change (start, end);
703
704 if (current_buffer->newline_cache)
705 invalidate_region_cache (current_buffer,
706 current_buffer->newline_cache,
707 start - BEG, Z - end);
708 if (current_buffer->width_run_cache)
709 invalidate_region_cache (current_buffer,
710 current_buffer->width_run_cache,
711 start - BEG, Z - end);
712
713 Vdeactivate_mark = Qt;
714 }
715 \f
716 static Lisp_Object
717 before_change_function_restore (value)
718 Lisp_Object value;
719 {
720 Vbefore_change_function = value;
721 }
722
723 static Lisp_Object
724 after_change_function_restore (value)
725 Lisp_Object value;
726 {
727 Vafter_change_function = value;
728 }
729
730 static Lisp_Object
731 before_change_functions_restore (value)
732 Lisp_Object value;
733 {
734 Vbefore_change_functions = value;
735 }
736
737 static Lisp_Object
738 after_change_functions_restore (value)
739 Lisp_Object value;
740 {
741 Vafter_change_functions = value;
742 }
743
744 /* Signal a change to the buffer immediately before it happens.
745 START and END are the bounds of the text to be changed,
746 as Lisp objects. */
747
748 signal_before_change (start, end)
749 Lisp_Object start, end;
750 {
751 /* If buffer is unmodified, run a special hook for that case. */
752 if (current_buffer->save_modified >= MODIFF
753 && !NILP (Vfirst_change_hook)
754 && !NILP (Vrun_hooks))
755 call1 (Vrun_hooks, Qfirst_change_hook);
756
757 /* Now in any case run the before-change-function if any. */
758 if (!NILP (Vbefore_change_function))
759 {
760 int count = specpdl_ptr - specpdl;
761 Lisp_Object function;
762
763 function = Vbefore_change_function;
764
765 record_unwind_protect (after_change_function_restore,
766 Vafter_change_function);
767 record_unwind_protect (before_change_function_restore,
768 Vbefore_change_function);
769 record_unwind_protect (after_change_functions_restore,
770 Vafter_change_functions);
771 record_unwind_protect (before_change_functions_restore,
772 Vbefore_change_functions);
773 Vafter_change_function = Qnil;
774 Vbefore_change_function = Qnil;
775 Vafter_change_functions = Qnil;
776 Vbefore_change_functions = Qnil;
777
778 call2 (function, start, end);
779 unbind_to (count, Qnil);
780 }
781
782 /* Now in any case run the before-change-function if any. */
783 if (!NILP (Vbefore_change_functions))
784 {
785 int count = specpdl_ptr - specpdl;
786 Lisp_Object functions;
787
788 functions = Vbefore_change_functions;
789
790 record_unwind_protect (after_change_function_restore,
791 Vafter_change_function);
792 record_unwind_protect (before_change_function_restore,
793 Vbefore_change_function);
794 record_unwind_protect (after_change_functions_restore,
795 Vafter_change_functions);
796 record_unwind_protect (before_change_functions_restore,
797 Vbefore_change_functions);
798 Vafter_change_function = Qnil;
799 Vbefore_change_function = Qnil;
800 Vafter_change_functions = Qnil;
801 Vbefore_change_functions = Qnil;
802
803 while (CONSP (functions))
804 {
805 call2 (XCONS (functions)->car, start, end);
806 functions = XCONS (functions)->cdr;
807 }
808 unbind_to (count, Qnil);
809 }
810 }
811
812 /* Signal a change immediately after it happens.
813 POS is the address of the start of the changed text.
814 LENDEL is the number of characters of the text before the change.
815 (Not the whole buffer; just the part that was changed.)
816 LENINS is the number of characters in the changed text. */
817
818 signal_after_change (pos, lendel, lenins)
819 int pos, lendel, lenins;
820 {
821 if (!NILP (Vafter_change_function))
822 {
823 int count = specpdl_ptr - specpdl;
824 Lisp_Object function;
825 function = Vafter_change_function;
826
827 record_unwind_protect (after_change_function_restore,
828 Vafter_change_function);
829 record_unwind_protect (before_change_function_restore,
830 Vbefore_change_function);
831 record_unwind_protect (after_change_functions_restore,
832 Vafter_change_functions);
833 record_unwind_protect (before_change_functions_restore,
834 Vbefore_change_functions);
835 Vafter_change_function = Qnil;
836 Vbefore_change_function = Qnil;
837 Vafter_change_functions = Qnil;
838 Vbefore_change_functions = Qnil;
839
840 call3 (function, make_number (pos), make_number (pos + lenins),
841 make_number (lendel));
842 unbind_to (count, Qnil);
843 }
844 if (!NILP (Vafter_change_functions))
845 {
846 int count = specpdl_ptr - specpdl;
847 Lisp_Object functions;
848 functions = Vafter_change_functions;
849
850 record_unwind_protect (after_change_function_restore,
851 Vafter_change_function);
852 record_unwind_protect (before_change_function_restore,
853 Vbefore_change_function);
854 record_unwind_protect (after_change_functions_restore,
855 Vafter_change_functions);
856 record_unwind_protect (before_change_functions_restore,
857 Vbefore_change_functions);
858 Vafter_change_function = Qnil;
859 Vbefore_change_function = Qnil;
860 Vafter_change_functions = Qnil;
861 Vbefore_change_functions = Qnil;
862
863 while (CONSP (functions))
864 {
865 call3 (XCONS (functions)->car,
866 make_number (pos), make_number (pos + lenins),
867 make_number (lendel));
868 functions = XCONS (functions)->cdr;
869 }
870 unbind_to (count, Qnil);
871 }
872 }