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