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