(insert_from_buffer_1): Don't use min.
[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 = BUF_GPT (buf) - pos;
489 if (chunk > length)
490 chunk = length;
491 bcopy (BUF_CHAR_ADDRESS (buf, pos), GPT_ADDR, chunk);
492 }
493 else
494 chunk = 0;
495 if (chunk < length)
496 bcopy (BUF_CHAR_ADDRESS (buf, pos + chunk),
497 GPT_ADDR + chunk, length - chunk);
498
499 #ifdef USE_TEXT_PROPERTIES
500 if (current_buffer->intervals != 0)
501 offset_intervals (current_buffer, PT, length);
502 #endif
503
504 GAP_SIZE -= length;
505 GPT += length;
506 ZV += length;
507 Z += length;
508 adjust_point (length);
509
510 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
511 graft_intervals_into_buffer (copy_intervals (buf->intervals, pos, length),
512 PT - length, length, current_buffer, inherit);
513 }
514
515 /* Insert the character C before point */
516
517 void
518 insert_char (c)
519 unsigned char c;
520 {
521 insert (&c, 1);
522 }
523
524 /* Insert the null-terminated string S before point */
525
526 void
527 insert_string (s)
528 char *s;
529 {
530 insert (s, strlen (s));
531 }
532
533 /* Like `insert' except that all markers pointing at the place where
534 the insertion happens are adjusted to point after it.
535 Don't use this function to insert part of a Lisp string,
536 since gc could happen and relocate it. */
537
538 insert_before_markers (string, length)
539 unsigned char *string;
540 register int length;
541 {
542 if (length > 0)
543 {
544 register int opoint = PT;
545 insert_1 (string, length, 0);
546 adjust_markers (opoint - 1, opoint, length);
547 signal_after_change (PT-length, 0, length);
548 }
549 }
550
551 insert_before_markers_and_inherit (string, length)
552 unsigned char *string;
553 register int length;
554 {
555 if (length > 0)
556 {
557 register int opoint = PT;
558 insert_1 (string, length, 1);
559 adjust_markers (opoint - 1, opoint, length);
560 signal_after_change (PT-length, 0, length);
561 }
562 }
563
564 /* Insert part of a Lisp string, relocating markers after. */
565
566 insert_from_string_before_markers (string, pos, length, inherit)
567 Lisp_Object string;
568 register int pos, length;
569 int inherit;
570 {
571 if (length > 0)
572 {
573 register int opoint = PT;
574 insert_from_string_1 (string, pos, length, inherit);
575 adjust_markers (opoint - 1, opoint, length);
576 signal_after_change (PT-length, 0, length);
577 }
578 }
579 \f
580 /* Delete characters in current buffer
581 from FROM up to (but not including) TO. */
582
583 del_range (from, to)
584 register int from, to;
585 {
586 return del_range_1 (from, to, 1);
587 }
588
589 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
590
591 del_range_1 (from, to, prepare)
592 register int from, to, prepare;
593 {
594 register int numdel;
595
596 /* Make args be valid */
597 if (from < BEGV)
598 from = BEGV;
599 if (to > ZV)
600 to = ZV;
601
602 if ((numdel = to - from) <= 0)
603 return;
604
605 /* Make sure the gap is somewhere in or next to what we are deleting. */
606 if (from > GPT)
607 gap_right (from);
608 if (to < GPT)
609 gap_left (to, 0);
610
611 if (prepare)
612 prepare_to_modify_buffer (from, to);
613
614 record_delete (from, numdel);
615 MODIFF++;
616
617 /* Relocate point as if it were a marker. */
618 if (from < PT)
619 adjust_point (from - (PT < to ? PT : to));
620
621 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
622 offset_intervals (current_buffer, from, - numdel);
623
624 /* Relocate all markers pointing into the new, larger gap
625 to point at the end of the text before the gap. */
626 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
627
628 GAP_SIZE += numdel;
629 ZV -= numdel;
630 Z -= numdel;
631 GPT = from;
632
633 if (GPT - BEG < beg_unchanged)
634 beg_unchanged = GPT - BEG;
635 if (Z - GPT < end_unchanged)
636 end_unchanged = Z - GPT;
637
638 evaporate_overlays (from);
639 signal_after_change (from, numdel, 0);
640 }
641 \f
642 /* Call this if you're about to change the region of BUFFER from START
643 to END. This checks the read-only properties of the region, calls
644 the necessary modification hooks, and warns the next redisplay that
645 it should pay attention to that area. */
646 modify_region (buffer, start, end)
647 struct buffer *buffer;
648 int start, end;
649 {
650 struct buffer *old_buffer = current_buffer;
651
652 if (buffer != old_buffer)
653 set_buffer_internal (buffer);
654
655 prepare_to_modify_buffer (start, end);
656
657 if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
658 beg_unchanged = start - 1;
659 if (Z - end < end_unchanged
660 || unchanged_modified == MODIFF)
661 end_unchanged = Z - end;
662
663 if (MODIFF <= current_buffer->save_modified)
664 record_first_change ();
665 MODIFF++;
666
667 if (buffer != old_buffer)
668 set_buffer_internal (old_buffer);
669 }
670
671 /* Check that it is okay to modify the buffer between START and END.
672 Run the before-change-function, if any. If intervals are in use,
673 verify that the text to be modified is not read-only, and call
674 any modification properties the text may have. */
675
676 prepare_to_modify_buffer (start, end)
677 Lisp_Object start, end;
678 {
679 if (!NILP (current_buffer->read_only))
680 Fbarf_if_buffer_read_only ();
681
682 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
683 if (current_buffer->intervals != 0)
684 verify_interval_modification (current_buffer, start, end);
685
686 if (!NILP (current_buffer->overlays_before)
687 || !NILP (current_buffer->overlays_after))
688 verify_overlay_modification (start, end);
689
690 #ifdef CLASH_DETECTION
691 if (!NILP (current_buffer->filename)
692 && current_buffer->save_modified >= MODIFF)
693 lock_file (current_buffer->filename);
694 #else
695 /* At least warn if this file has changed on disk since it was visited. */
696 if (!NILP (current_buffer->filename)
697 && current_buffer->save_modified >= MODIFF
698 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
699 && !NILP (Ffile_exists_p (current_buffer->filename)))
700 call1 (intern ("ask-user-about-supersession-threat"),
701 current_buffer->filename);
702 #endif /* not CLASH_DETECTION */
703
704 signal_before_change (start, end);
705
706 if (current_buffer->newline_cache)
707 invalidate_region_cache (current_buffer,
708 current_buffer->newline_cache,
709 start - BEG, Z - end);
710 if (current_buffer->width_run_cache)
711 invalidate_region_cache (current_buffer,
712 current_buffer->width_run_cache,
713 start - BEG, Z - end);
714
715 Vdeactivate_mark = Qt;
716 }
717 \f
718 static Lisp_Object
719 before_change_function_restore (value)
720 Lisp_Object value;
721 {
722 Vbefore_change_function = value;
723 }
724
725 static Lisp_Object
726 after_change_function_restore (value)
727 Lisp_Object value;
728 {
729 Vafter_change_function = value;
730 }
731
732 static Lisp_Object
733 before_change_functions_restore (value)
734 Lisp_Object value;
735 {
736 Vbefore_change_functions = value;
737 }
738
739 static Lisp_Object
740 after_change_functions_restore (value)
741 Lisp_Object value;
742 {
743 Vafter_change_functions = value;
744 }
745
746 /* Signal a change to the buffer immediately before it happens.
747 START and END are the bounds of the text to be changed,
748 as Lisp objects. */
749
750 signal_before_change (start, end)
751 Lisp_Object start, end;
752 {
753 /* If buffer is unmodified, run a special hook for that case. */
754 if (current_buffer->save_modified >= MODIFF
755 && !NILP (Vfirst_change_hook)
756 && !NILP (Vrun_hooks))
757 call1 (Vrun_hooks, Qfirst_change_hook);
758
759 /* Now in any case run the before-change-function if any. */
760 if (!NILP (Vbefore_change_function))
761 {
762 int count = specpdl_ptr - specpdl;
763 Lisp_Object function;
764
765 function = Vbefore_change_function;
766
767 record_unwind_protect (after_change_function_restore,
768 Vafter_change_function);
769 record_unwind_protect (before_change_function_restore,
770 Vbefore_change_function);
771 record_unwind_protect (after_change_functions_restore,
772 Vafter_change_functions);
773 record_unwind_protect (before_change_functions_restore,
774 Vbefore_change_functions);
775 Vafter_change_function = Qnil;
776 Vbefore_change_function = Qnil;
777 Vafter_change_functions = Qnil;
778 Vbefore_change_functions = Qnil;
779
780 call2 (function, start, end);
781 unbind_to (count, Qnil);
782 }
783
784 /* Now in any case run the before-change-function if any. */
785 if (!NILP (Vbefore_change_functions))
786 {
787 int count = specpdl_ptr - specpdl;
788 Lisp_Object functions;
789
790 functions = Vbefore_change_functions;
791
792 record_unwind_protect (after_change_function_restore,
793 Vafter_change_function);
794 record_unwind_protect (before_change_function_restore,
795 Vbefore_change_function);
796 record_unwind_protect (after_change_functions_restore,
797 Vafter_change_functions);
798 record_unwind_protect (before_change_functions_restore,
799 Vbefore_change_functions);
800 Vafter_change_function = Qnil;
801 Vbefore_change_function = Qnil;
802 Vafter_change_functions = Qnil;
803 Vbefore_change_functions = Qnil;
804
805 while (CONSP (functions))
806 {
807 call2 (XCONS (functions)->car, start, end);
808 functions = XCONS (functions)->cdr;
809 }
810 unbind_to (count, Qnil);
811 }
812 }
813
814 /* Signal a change immediately after it happens.
815 POS is the address of the start of the changed text.
816 LENDEL is the number of characters of the text before the change.
817 (Not the whole buffer; just the part that was changed.)
818 LENINS is the number of characters in the changed text. */
819
820 signal_after_change (pos, lendel, lenins)
821 int pos, lendel, lenins;
822 {
823 if (!NILP (Vafter_change_function))
824 {
825 int count = specpdl_ptr - specpdl;
826 Lisp_Object function;
827 function = Vafter_change_function;
828
829 record_unwind_protect (after_change_function_restore,
830 Vafter_change_function);
831 record_unwind_protect (before_change_function_restore,
832 Vbefore_change_function);
833 record_unwind_protect (after_change_functions_restore,
834 Vafter_change_functions);
835 record_unwind_protect (before_change_functions_restore,
836 Vbefore_change_functions);
837 Vafter_change_function = Qnil;
838 Vbefore_change_function = Qnil;
839 Vafter_change_functions = Qnil;
840 Vbefore_change_functions = Qnil;
841
842 call3 (function, make_number (pos), make_number (pos + lenins),
843 make_number (lendel));
844 unbind_to (count, Qnil);
845 }
846 if (!NILP (Vafter_change_functions))
847 {
848 int count = specpdl_ptr - specpdl;
849 Lisp_Object functions;
850 functions = Vafter_change_functions;
851
852 record_unwind_protect (after_change_function_restore,
853 Vafter_change_function);
854 record_unwind_protect (before_change_function_restore,
855 Vbefore_change_function);
856 record_unwind_protect (after_change_functions_restore,
857 Vafter_change_functions);
858 record_unwind_protect (before_change_functions_restore,
859 Vbefore_change_functions);
860 Vafter_change_function = Qnil;
861 Vbefore_change_function = Qnil;
862 Vafter_change_functions = Qnil;
863 Vbefore_change_functions = Qnil;
864
865 while (CONSP (functions))
866 {
867 call3 (XCONS (functions)->car,
868 make_number (pos), make_number (pos + lenins),
869 make_number (lendel));
870 functions = XCONS (functions)->cdr;
871 }
872 unbind_to (count, Qnil);
873 }
874 }