Update FSF's address in the preamble.
[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 Also, any markers past the outside of that interval, in the direction
216 of adjustment, are first moved back to the near end of the interval
217 and then adjusted by `amount'. */
218
219 static void
220 adjust_markers (from, to, amount)
221 register int from, to, amount;
222 {
223 Lisp_Object marker;
224 register struct Lisp_Marker *m;
225 register int mpos;
226
227 marker = BUF_MARKERS (current_buffer);
228
229 while (!NILP (marker))
230 {
231 m = XMARKER (marker);
232 mpos = m->bufpos;
233 if (amount > 0)
234 {
235 if (mpos > to && mpos < to + amount)
236 mpos = to + amount;
237 }
238 else
239 {
240 if (mpos > from + amount && mpos <= from)
241 mpos = from + amount;
242 }
243 if (mpos > from && mpos <= to)
244 mpos += amount;
245 m->bufpos = mpos;
246 marker = m->chain;
247 }
248 }
249
250 /* Adjust markers whose insertion-type is t
251 for an insertion of AMOUNT characters at POS. */
252
253 static void
254 adjust_markers_for_insert (pos, amount)
255 register int pos, amount;
256 {
257 Lisp_Object marker;
258
259 marker = BUF_MARKERS (current_buffer);
260
261 while (!NILP (marker))
262 {
263 register struct Lisp_Marker *m = XMARKER (marker);
264 if (m->insertion_type && m->bufpos == pos)
265 m->bufpos += amount;
266 marker = m->chain;
267 }
268 }
269
270 /* Add the specified amount to point. This is used only when the value
271 of point changes due to an insert or delete; it does not represent
272 a conceptual change in point as a marker. In particular, point is
273 not crossing any interval boundaries, so there's no need to use the
274 usual SET_PT macro. In fact it would be incorrect to do so, because
275 either the old or the new value of point is out of sync with the
276 current set of intervals. */
277 static void
278 adjust_point (amount)
279 int amount;
280 {
281 BUF_PT (current_buffer) += amount;
282 }
283 \f
284 /* Make the gap INCREMENT characters longer. */
285
286 void
287 make_gap (increment)
288 int increment;
289 {
290 unsigned char *result;
291 Lisp_Object tem;
292 int real_gap_loc;
293 int old_gap_size;
294
295 /* If we have to get more space, get enough to last a while. */
296 increment += 2000;
297
298 /* Don't allow a buffer size that won't fit in an int
299 even if it will fit in a Lisp integer.
300 That won't work because so many places use `int'. */
301
302 if (Z - BEG + GAP_SIZE + increment
303 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
304 error ("Buffer exceeds maximum size");
305
306 BLOCK_INPUT;
307 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
308
309 if (result == 0)
310 {
311 UNBLOCK_INPUT;
312 memory_full ();
313 }
314
315 /* We can't unblock until the new address is properly stored. */
316 BEG_ADDR = result;
317 UNBLOCK_INPUT;
318
319 /* Prevent quitting in move_gap. */
320 tem = Vinhibit_quit;
321 Vinhibit_quit = Qt;
322
323 real_gap_loc = GPT;
324 old_gap_size = GAP_SIZE;
325
326 /* Call the newly allocated space a gap at the end of the whole space. */
327 GPT = Z + GAP_SIZE;
328 GAP_SIZE = increment;
329
330 /* Move the new gap down to be consecutive with the end of the old one.
331 This adjusts the markers properly too. */
332 gap_left (real_gap_loc + old_gap_size, 1);
333
334 /* Now combine the two into one large gap. */
335 GAP_SIZE += old_gap_size;
336 GPT = real_gap_loc;
337
338 Vinhibit_quit = tem;
339 }
340 \f
341 /* Insert a string of specified length before point.
342 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
343 prepare_to_modify_buffer could relocate the text. */
344
345 void
346 insert (string, length)
347 register unsigned char *string;
348 register length;
349 {
350 if (length > 0)
351 {
352 insert_1 (string, length, 0, 1);
353 signal_after_change (PT-length, 0, length);
354 }
355 }
356
357 void
358 insert_and_inherit (string, length)
359 register unsigned char *string;
360 register length;
361 {
362 if (length > 0)
363 {
364 insert_1 (string, length, 1, 1);
365 signal_after_change (PT-length, 0, length);
366 }
367 }
368
369 void
370 insert_1 (string, length, inherit, prepare)
371 register unsigned char *string;
372 register int length;
373 int inherit, prepare;
374 {
375 register Lisp_Object temp;
376
377 if (prepare)
378 prepare_to_modify_buffer (PT, PT);
379
380 if (PT != GPT)
381 move_gap (PT);
382 if (GAP_SIZE < length)
383 make_gap (length - GAP_SIZE);
384
385 record_insert (PT, length);
386 MODIFF++;
387
388 bcopy (string, GPT_ADDR, length);
389
390 #ifdef USE_TEXT_PROPERTIES
391 if (BUF_INTERVALS (current_buffer) != 0)
392 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
393 offset_intervals (current_buffer, PT, length);
394 #endif
395
396 GAP_SIZE -= length;
397 GPT += length;
398 ZV += length;
399 Z += length;
400 adjust_overlays_for_insert (PT, length);
401 adjust_markers_for_insert (PT, length);
402 adjust_point (length);
403
404 #ifdef USE_TEXT_PROPERTIES
405 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
406 Fset_text_properties (make_number (PT - length), make_number (PT),
407 Qnil, Qnil);
408 #endif
409 }
410
411 /* Insert the part of the text of STRING, a Lisp object assumed to be
412 of type string, consisting of the LENGTH characters starting at
413 position POS. If the text of STRING has properties, they are absorbed
414 into the buffer.
415
416 It does not work to use `insert' for this, because a GC could happen
417 before we bcopy the stuff into the buffer, and relocate the string
418 without insert noticing. */
419
420 void
421 insert_from_string (string, pos, length, inherit)
422 Lisp_Object string;
423 register int pos, length;
424 int inherit;
425 {
426 if (length > 0)
427 {
428 insert_from_string_1 (string, pos, length, inherit);
429 signal_after_change (PT-length, 0, length);
430 }
431 }
432
433 static void
434 insert_from_string_1 (string, pos, length, inherit)
435 Lisp_Object string;
436 register int pos, length;
437 int inherit;
438 {
439 register Lisp_Object temp;
440 struct gcpro gcpro1;
441
442 /* Make sure point-max won't overflow after this insertion. */
443 XSETINT (temp, length + Z);
444 if (length + Z != XINT (temp))
445 error ("maximum buffer size exceeded");
446
447 GCPRO1 (string);
448 prepare_to_modify_buffer (PT, PT);
449
450 if (PT != GPT)
451 move_gap (PT);
452 if (GAP_SIZE < length)
453 make_gap (length - GAP_SIZE);
454
455 record_insert (PT, length);
456 MODIFF++;
457 UNGCPRO;
458
459 bcopy (XSTRING (string)->data, GPT_ADDR, length);
460
461 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
462 offset_intervals (current_buffer, PT, length);
463
464 GAP_SIZE -= length;
465 GPT += length;
466 ZV += length;
467 Z += length;
468 adjust_overlays_for_insert (PT, length);
469 adjust_markers_for_insert (PT, length);
470
471 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
472 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
473 current_buffer, inherit);
474
475 adjust_point (length);
476 }
477
478 /* Insert text from BUF, starting at POS and having length LENGTH, into the
479 current buffer. If the text in BUF has properties, they are absorbed
480 into the current buffer.
481
482 It does not work to use `insert' for this, because a malloc could happen
483 and relocate BUF's text before the bcopy happens. */
484
485 void
486 insert_from_buffer (buf, pos, length, inherit)
487 struct buffer *buf;
488 int pos, length;
489 int inherit;
490 {
491 if (length > 0)
492 {
493 insert_from_buffer_1 (buf, pos, length, inherit);
494 signal_after_change (PT-length, 0, length);
495 }
496 }
497
498 static void
499 insert_from_buffer_1 (buf, pos, length, inherit)
500 struct buffer *buf;
501 int pos, length;
502 int inherit;
503 {
504 register Lisp_Object temp;
505 int chunk;
506
507 /* Make sure point-max won't overflow after this insertion. */
508 XSETINT (temp, length + Z);
509 if (length + Z != XINT (temp))
510 error ("maximum buffer size exceeded");
511
512 prepare_to_modify_buffer (PT, PT);
513
514 if (PT != GPT)
515 move_gap (PT);
516 if (GAP_SIZE < length)
517 make_gap (length - GAP_SIZE);
518
519 record_insert (PT, length);
520 MODIFF++;
521
522 if (pos < BUF_GPT (buf))
523 {
524 chunk = BUF_GPT (buf) - pos;
525 if (chunk > length)
526 chunk = length;
527 bcopy (BUF_CHAR_ADDRESS (buf, pos), GPT_ADDR, chunk);
528 }
529 else
530 chunk = 0;
531 if (chunk < length)
532 bcopy (BUF_CHAR_ADDRESS (buf, pos + chunk),
533 GPT_ADDR + chunk, length - chunk);
534
535 #ifdef USE_TEXT_PROPERTIES
536 if (BUF_INTERVALS (current_buffer) != 0)
537 offset_intervals (current_buffer, PT, length);
538 #endif
539
540 GAP_SIZE -= length;
541 GPT += length;
542 ZV += length;
543 Z += length;
544 adjust_overlays_for_insert (PT, length);
545 adjust_markers_for_insert (PT, length);
546 adjust_point (length);
547
548 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
549 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
550 pos, length),
551 PT - length, length, current_buffer, inherit);
552 }
553
554 /* Insert the character C before point */
555
556 void
557 insert_char (c)
558 unsigned char c;
559 {
560 insert (&c, 1);
561 }
562
563 /* Insert the null-terminated string S before point */
564
565 void
566 insert_string (s)
567 char *s;
568 {
569 insert (s, strlen (s));
570 }
571
572 /* Like `insert' except that all markers pointing at the place where
573 the insertion happens are adjusted to point after it.
574 Don't use this function to insert part of a Lisp string,
575 since gc could happen and relocate it. */
576
577 void
578 insert_before_markers (string, length)
579 unsigned char *string;
580 register int length;
581 {
582 if (length > 0)
583 {
584 register int opoint = PT;
585 insert_1 (string, length, 0, 1);
586 adjust_markers (opoint - 1, opoint, length);
587 signal_after_change (PT-length, 0, length);
588 }
589 }
590
591 void
592 insert_before_markers_and_inherit (string, length)
593 unsigned char *string;
594 register int length;
595 {
596 if (length > 0)
597 {
598 register int opoint = PT;
599 insert_1 (string, length, 1, 1);
600 adjust_markers (opoint - 1, opoint, length);
601 signal_after_change (PT-length, 0, length);
602 }
603 }
604
605 /* Insert part of a Lisp string, relocating markers after. */
606
607 void
608 insert_from_string_before_markers (string, pos, length, inherit)
609 Lisp_Object string;
610 register int pos, length;
611 int inherit;
612 {
613 if (length > 0)
614 {
615 register int opoint = PT;
616 insert_from_string_1 (string, pos, length, inherit);
617 adjust_markers (opoint - 1, opoint, length);
618 signal_after_change (PT-length, 0, length);
619 }
620 }
621 \f
622 /* Delete characters in current buffer
623 from FROM up to (but not including) TO. */
624
625 void
626 del_range (from, to)
627 register int from, to;
628 {
629 del_range_1 (from, to, 1);
630 }
631
632 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
633
634 void
635 del_range_1 (from, to, prepare)
636 register int from, to, prepare;
637 {
638 register int numdel;
639
640 /* Make args be valid */
641 if (from < BEGV)
642 from = BEGV;
643 if (to > ZV)
644 to = ZV;
645
646 if ((numdel = to - from) <= 0)
647 return;
648
649 /* Make sure the gap is somewhere in or next to what we are deleting. */
650 if (from > GPT)
651 gap_right (from);
652 if (to < GPT)
653 gap_left (to, 0);
654
655 if (prepare)
656 prepare_to_modify_buffer (from, to);
657
658 record_delete (from, numdel);
659 MODIFF++;
660
661 /* Relocate point as if it were a marker. */
662 if (from < PT)
663 adjust_point (from - (PT < to ? PT : to));
664
665 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
666 offset_intervals (current_buffer, from, - numdel);
667
668 /* Relocate all markers pointing into the new, larger gap
669 to point at the end of the text before the gap. */
670 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
671
672 /* Adjust the overlay center as needed. This must be done after
673 adjusting the markers that bound the overlays. */
674 adjust_overlays_for_delete (from, numdel);
675
676 GAP_SIZE += numdel;
677 ZV -= numdel;
678 Z -= numdel;
679 GPT = from;
680
681 if (GPT - BEG < beg_unchanged)
682 beg_unchanged = GPT - BEG;
683 if (Z - GPT < end_unchanged)
684 end_unchanged = Z - GPT;
685
686 evaporate_overlays (from);
687 signal_after_change (from, numdel, 0);
688 }
689 \f
690 /* Call this if you're about to change the region of BUFFER from START
691 to END. This checks the read-only properties of the region, calls
692 the necessary modification hooks, and warns the next redisplay that
693 it should pay attention to that area. */
694 void
695 modify_region (buffer, start, end)
696 struct buffer *buffer;
697 int start, end;
698 {
699 struct buffer *old_buffer = current_buffer;
700
701 if (buffer != old_buffer)
702 set_buffer_internal (buffer);
703
704 prepare_to_modify_buffer (start, end);
705
706 if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
707 beg_unchanged = start - 1;
708 if (Z - end < end_unchanged
709 || unchanged_modified == MODIFF)
710 end_unchanged = Z - end;
711
712 if (MODIFF <= SAVE_MODIFF)
713 record_first_change ();
714 MODIFF++;
715
716 buffer->point_before_scroll = Qnil;
717
718 if (buffer != old_buffer)
719 set_buffer_internal (old_buffer);
720 }
721
722 /* Check that it is okay to modify the buffer between START and END.
723 Run the before-change-function, if any. If intervals are in use,
724 verify that the text to be modified is not read-only, and call
725 any modification properties the text may have. */
726
727 void
728 prepare_to_modify_buffer (start, end)
729 Lisp_Object start, end;
730 {
731 if (!NILP (current_buffer->read_only))
732 Fbarf_if_buffer_read_only ();
733
734 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
735 if (BUF_INTERVALS (current_buffer) != 0)
736 verify_interval_modification (current_buffer, start, end);
737
738 #ifdef CLASH_DETECTION
739 if (!NILP (current_buffer->file_truename)
740 /* Make binding buffer-file-name to nil effective. */
741 && !NILP (current_buffer->filename)
742 && SAVE_MODIFF >= MODIFF)
743 lock_file (current_buffer->file_truename);
744 #else
745 /* At least warn if this file has changed on disk since it was visited. */
746 if (!NILP (current_buffer->filename)
747 && SAVE_MODIFF >= MODIFF
748 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
749 && !NILP (Ffile_exists_p (current_buffer->filename)))
750 call1 (intern ("ask-user-about-supersession-threat"),
751 current_buffer->filename);
752 #endif /* not CLASH_DETECTION */
753
754 signal_before_change (start, end);
755
756 if (current_buffer->newline_cache)
757 invalidate_region_cache (current_buffer,
758 current_buffer->newline_cache,
759 start - BEG, Z - end);
760 if (current_buffer->width_run_cache)
761 invalidate_region_cache (current_buffer,
762 current_buffer->width_run_cache,
763 start - BEG, Z - end);
764
765 Vdeactivate_mark = Qt;
766 }
767 \f
768 /* Signal a change to the buffer immediately before it happens.
769 START and END are the bounds of the text to be changed,
770 as Lisp objects. */
771
772 void
773 signal_before_change (start, end)
774 Lisp_Object start, end;
775 {
776 /* If buffer is unmodified, run a special hook for that case. */
777 if (SAVE_MODIFF >= MODIFF
778 && !NILP (Vfirst_change_hook)
779 && !NILP (Vrun_hooks))
780 call1 (Vrun_hooks, Qfirst_change_hook);
781
782 /* Run the before-change-function if any.
783 We don't bother "binding" this variable to nil
784 because it is obsolete anyway and new code should not use it. */
785 if (!NILP (Vbefore_change_function))
786 call2 (Vbefore_change_function, start, end);
787
788 /* Now run the before-change-functions if any. */
789 if (!NILP (Vbefore_change_functions))
790 {
791 Lisp_Object args[3];
792 Lisp_Object before_change_functions;
793 Lisp_Object after_change_functions;
794 struct gcpro gcpro1, gcpro2;
795
796 /* "Bind" before-change-functions and after-change-functions
797 to nil--but in a way that errors don't know about.
798 That way, if there's an error in them, they will stay nil. */
799 before_change_functions = Vbefore_change_functions;
800 after_change_functions = Vafter_change_functions;
801 Vbefore_change_functions = Qnil;
802 Vafter_change_functions = Qnil;
803 GCPRO2 (before_change_functions, after_change_functions);
804
805 /* Actually run the hook functions. */
806 args[0] = Qbefore_change_functions;
807 args[1] = start;
808 args[2] = end;
809 run_hook_list_with_args (before_change_functions, 3, args);
810
811 /* "Unbind" the variables we "bound" to nil. */
812 Vbefore_change_functions = before_change_functions;
813 Vafter_change_functions = after_change_functions;
814 UNGCPRO;
815 }
816
817 if (!NILP (current_buffer->overlays_before)
818 || !NILP (current_buffer->overlays_after))
819 report_overlay_modification (start, end, 0, start, end, Qnil);
820 }
821
822 /* Signal a change immediately after it happens.
823 POS is the address of the start of the changed text.
824 LENDEL is the number of characters of the text before the change.
825 (Not the whole buffer; just the part that was changed.)
826 LENINS is the number of characters in the changed text.
827
828 (Hence POS + LENINS - LENDEL is the position after the changed text.) */
829
830 void
831 signal_after_change (pos, lendel, lenins)
832 int pos, lendel, lenins;
833 {
834 /* Run the after-change-function if any.
835 We don't bother "binding" this variable to nil
836 because it is obsolete anyway and new code should not use it. */
837 if (!NILP (Vafter_change_function))
838 call3 (Vafter_change_function,
839 make_number (pos), make_number (pos + lenins),
840 make_number (lendel));
841
842 if (!NILP (Vafter_change_functions))
843 {
844 Lisp_Object args[4];
845 Lisp_Object before_change_functions;
846 Lisp_Object after_change_functions;
847 struct gcpro gcpro1, gcpro2;
848
849 /* "Bind" before-change-functions and after-change-functions
850 to nil--but in a way that errors don't know about.
851 That way, if there's an error in them, they will stay nil. */
852 before_change_functions = Vbefore_change_functions;
853 after_change_functions = Vafter_change_functions;
854 Vbefore_change_functions = Qnil;
855 Vafter_change_functions = Qnil;
856 GCPRO2 (before_change_functions, after_change_functions);
857
858 /* Actually run the hook functions. */
859 args[0] = Qafter_change_functions;
860 XSETFASTINT (args[1], pos);
861 XSETFASTINT (args[2], pos + lenins);
862 XSETFASTINT (args[3], lendel);
863 run_hook_list_with_args (after_change_functions,
864 4, args);
865
866 /* "Unbind" the variables we "bound" to nil. */
867 Vbefore_change_functions = before_change_functions;
868 Vafter_change_functions = after_change_functions;
869 UNGCPRO;
870 }
871
872 if (!NILP (current_buffer->overlays_before)
873 || !NILP (current_buffer->overlays_after))
874 report_overlay_modification (make_number (pos),
875 make_number (pos + lenins - lendel),
876 1,
877 make_number (pos), make_number (pos + lenins),
878 make_number (lendel));
879
880 /* After an insertion, call the text properties
881 insert-behind-hooks or insert-in-front-hooks. */
882 if (lendel == 0)
883 report_interval_modification (pos, pos + lenins);
884 }