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