(struct x_display_info): Struct renamed from x_screen.
[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 274
b45433b3 275 if (result == 0)
270c2138
RS
276 {
277 UNBLOCK_INPUT;
278 memory_full ();
279 }
280
281 /* We can't unblock until the new address is properly stored. */
b45433b3 282 BEG_ADDR = result;
270c2138 283 UNBLOCK_INPUT;
b45433b3
JB
284
285 /* Prevent quitting in move_gap. */
286 tem = Vinhibit_quit;
287 Vinhibit_quit = Qt;
288
289 real_gap_loc = GPT;
290 old_gap_size = GAP_SIZE;
291
292 /* Call the newly allocated space a gap at the end of the whole space. */
293 GPT = Z + GAP_SIZE;
294 GAP_SIZE = increment;
295
296 /* Move the new gap down to be consecutive with the end of the old one.
297 This adjusts the markers properly too. */
298 gap_left (real_gap_loc + old_gap_size, 1);
299
300 /* Now combine the two into one large gap. */
301 GAP_SIZE += old_gap_size;
302 GPT = real_gap_loc;
303
304 Vinhibit_quit = tem;
305}
306\f
307/* Insert a string of specified length before point.
308 DO NOT use this for the contents of a Lisp string!
309 prepare_to_modify_buffer could relocate the string. */
310
311insert (string, length)
312 register unsigned char *string;
313 register length;
314{
395ec62e
KH
315 if (length > 0)
316 {
cd11ef31
RS
317 insert_1 (string, length, 0);
318 signal_after_change (PT-length, 0, length);
319 }
320}
321
322insert_and_inherit (string, length)
323 register unsigned char *string;
324 register length;
325{
326 if (length > 0)
327 {
328 insert_1 (string, length, 1);
2bcaed71 329 signal_after_change (PT-length, 0, length);
395ec62e
KH
330 }
331}
b45433b3 332
395ec62e 333static void
cd11ef31 334insert_1 (string, length, inherit)
395ec62e
KH
335 register unsigned char *string;
336 register length;
cd11ef31 337 int inherit;
395ec62e
KH
338{
339 register Lisp_Object temp;
b45433b3
JB
340
341 /* Make sure point-max won't overflow after this insertion. */
eb7db9e6 342 XSETINT (temp, length + Z);
b45433b3
JB
343 if (length + Z != XINT (temp))
344 error ("maximum buffer size exceeded");
345
2bcaed71 346 prepare_to_modify_buffer (PT, PT);
b45433b3 347
2bcaed71
KH
348 if (PT != GPT)
349 move_gap (PT);
b45433b3
JB
350 if (GAP_SIZE < length)
351 make_gap (length - GAP_SIZE);
352
2bcaed71 353 record_insert (PT, length);
b45433b3
JB
354 MODIFF++;
355
356 bcopy (string, GPT_ADDR, length);
357
648c4c55
RS
358#ifdef USE_TEXT_PROPERTIES
359 if (current_buffer->intervals != 0)
360 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
361 offset_intervals (current_buffer, PT, length);
362#endif
679194a6 363
b45433b3
JB
364 GAP_SIZE -= length;
365 GPT += length;
366 ZV += length;
367 Z += length;
a27a38d8 368 adjust_point (length);
cd11ef31 369
648c4c55
RS
370#ifdef USE_TEXT_PROPERTIES
371 if (!inherit && current_buffer->intervals != 0)
cd11ef31
RS
372 Fset_text_properties (make_number (PT - length), make_number (PT),
373 Qnil, Qnil);
648c4c55 374#endif
b45433b3
JB
375}
376
679194a6
JA
377/* Insert the part of the text of STRING, a Lisp object assumed to be
378 of type string, consisting of the LENGTH characters starting at
379 position POS. If the text of STRING has properties, they are absorbed
380 into the buffer.
381
382 It does not work to use `insert' for this, because a GC could happen
7e1ea612
JB
383 before we bcopy the stuff into the buffer, and relocate the string
384 without insert noticing. */
679194a6 385
9391e591 386insert_from_string (string, pos, length, inherit)
b45433b3
JB
387 Lisp_Object string;
388 register int pos, length;
9391e591 389 int inherit;
395ec62e
KH
390{
391 if (length > 0)
392 {
393 insert_from_string_1 (string, pos, length, inherit);
2bcaed71 394 signal_after_change (PT-length, 0, length);
395ec62e
KH
395 }
396}
397
398static void
399insert_from_string_1 (string, pos, length, inherit)
400 Lisp_Object string;
401 register int pos, length;
402 int inherit;
b45433b3
JB
403{
404 register Lisp_Object temp;
405 struct gcpro gcpro1;
406
b45433b3 407 /* Make sure point-max won't overflow after this insertion. */
eb7db9e6 408 XSETINT (temp, length + Z);
b45433b3
JB
409 if (length + Z != XINT (temp))
410 error ("maximum buffer size exceeded");
411
412 GCPRO1 (string);
2bcaed71 413 prepare_to_modify_buffer (PT, PT);
b45433b3 414
2bcaed71
KH
415 if (PT != GPT)
416 move_gap (PT);
b45433b3
JB
417 if (GAP_SIZE < length)
418 make_gap (length - GAP_SIZE);
419
2bcaed71 420 record_insert (PT, length);
b45433b3
JB
421 MODIFF++;
422 UNGCPRO;
423
424 bcopy (XSTRING (string)->data, GPT_ADDR, length);
425
679194a6 426 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2bcaed71 427 offset_intervals (current_buffer, PT, length);
679194a6 428
b45433b3
JB
429 GAP_SIZE -= length;
430 GPT += length;
431 ZV += length;
432 Z += length;
679194a6
JA
433
434 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2bcaed71 435 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
9391e591 436 current_buffer, inherit);
679194a6 437
a27a38d8 438 adjust_point (length);
b45433b3
JB
439}
440
441/* Insert the character C before point */
442
443void
444insert_char (c)
445 unsigned char c;
446{
447 insert (&c, 1);
448}
449
450/* Insert the null-terminated string S before point */
451
452void
453insert_string (s)
454 char *s;
455{
456 insert (s, strlen (s));
457}
458
459/* Like `insert' except that all markers pointing at the place where
460 the insertion happens are adjusted to point after it.
461 Don't use this function to insert part of a Lisp string,
462 since gc could happen and relocate it. */
463
464insert_before_markers (string, length)
465 unsigned char *string;
466 register int length;
467{
395ec62e
KH
468 if (length > 0)
469 {
2bcaed71 470 register int opoint = PT;
9ab5c9ca 471 insert_1 (string, length, 0);
395ec62e 472 adjust_markers (opoint - 1, opoint, length);
2bcaed71 473 signal_after_change (PT-length, 0, length);
395ec62e 474 }
b45433b3
JB
475}
476
598fb6fe
RS
477insert_before_markers_and_inherit (string, length)
478 unsigned char *string;
479 register int length;
480{
481 if (length > 0)
482 {
483 register int opoint = PT;
484 insert_1 (string, length, 1);
485 adjust_markers (opoint - 1, opoint, length);
486 signal_after_change (PT-length, 0, length);
487 }
488}
489
b45433b3
JB
490/* Insert part of a Lisp string, relocating markers after. */
491
9391e591 492insert_from_string_before_markers (string, pos, length, inherit)
b45433b3
JB
493 Lisp_Object string;
494 register int pos, length;
9391e591 495 int inherit;
b45433b3 496{
395ec62e
KH
497 if (length > 0)
498 {
2bcaed71 499 register int opoint = PT;
395ec62e
KH
500 insert_from_string_1 (string, pos, length, inherit);
501 adjust_markers (opoint - 1, opoint, length);
2bcaed71 502 signal_after_change (PT-length, 0, length);
395ec62e 503 }
b45433b3
JB
504}
505\f
506/* Delete characters in current buffer
507 from FROM up to (but not including) TO. */
508
509del_range (from, to)
510 register int from, to;
47c64747
RS
511{
512 return del_range_1 (from, to, 1);
513}
514
515/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
516
517del_range_1 (from, to, prepare)
518 register int from, to, prepare;
b45433b3
JB
519{
520 register int numdel;
521
522 /* Make args be valid */
523 if (from < BEGV)
524 from = BEGV;
525 if (to > ZV)
526 to = ZV;
527
528 if ((numdel = to - from) <= 0)
529 return;
530
531 /* Make sure the gap is somewhere in or next to what we are deleting. */
532 if (from > GPT)
533 gap_right (from);
534 if (to < GPT)
535 gap_left (to, 0);
536
47c64747
RS
537 if (prepare)
538 prepare_to_modify_buffer (from, to);
b45433b3 539
be09561e
RS
540 record_delete (from, numdel);
541 MODIFF++;
542
b45433b3 543 /* Relocate point as if it were a marker. */
2bcaed71 544 if (from < PT)
a27a38d8 545 adjust_point (from - (PT < to ? PT : to));
b45433b3 546
16032db6 547 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
83010cd6 548 offset_intervals (current_buffer, from, - numdel);
16032db6 549
b45433b3
JB
550 /* Relocate all markers pointing into the new, larger gap
551 to point at the end of the text before the gap. */
552 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
553
554 GAP_SIZE += numdel;
555 ZV -= numdel;
556 Z -= numdel;
557 GPT = from;
558
559 if (GPT - BEG < beg_unchanged)
560 beg_unchanged = GPT - BEG;
561 if (Z - GPT < end_unchanged)
562 end_unchanged = Z - GPT;
563
d386034e 564 evaporate_overlays (from);
b45433b3
JB
565 signal_after_change (from, numdel, 0);
566}
567\f
04a759c8
JB
568/* Call this if you're about to change the region of BUFFER from START
569 to END. This checks the read-only properties of the region, calls
570 the necessary modification hooks, and warns the next redisplay that
571 it should pay attention to that area. */
572modify_region (buffer, start, end)
573 struct buffer *buffer;
b45433b3
JB
574 int start, end;
575{
04a759c8
JB
576 struct buffer *old_buffer = current_buffer;
577
578 if (buffer != old_buffer)
579 set_buffer_internal (buffer);
580
b45433b3
JB
581 prepare_to_modify_buffer (start, end);
582
583 if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
584 beg_unchanged = start - 1;
585 if (Z - end < end_unchanged
586 || unchanged_modified == MODIFF)
587 end_unchanged = Z - end;
83010cd6
RS
588
589 if (MODIFF <= current_buffer->save_modified)
590 record_first_change ();
b45433b3 591 MODIFF++;
04a759c8
JB
592
593 if (buffer != old_buffer)
594 set_buffer_internal (old_buffer);
b45433b3
JB
595}
596
597/* Check that it is okay to modify the buffer between START and END.
679194a6
JA
598 Run the before-change-function, if any. If intervals are in use,
599 verify that the text to be modified is not read-only, and call
600 any modification properties the text may have. */
b45433b3
JB
601
602prepare_to_modify_buffer (start, end)
603 Lisp_Object start, end;
604{
d427b66a 605 if (!NILP (current_buffer->read_only))
b45433b3
JB
606 Fbarf_if_buffer_read_only ();
607
679194a6 608 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
648c4c55
RS
609 if (current_buffer->intervals != 0)
610 verify_interval_modification (current_buffer, start, end);
b45433b3 611
648c4c55
RS
612 if (!NILP (current_buffer->overlays_before)
613 || !NILP (current_buffer->overlays_after))
614 verify_overlay_modification (start, end);
f256353c 615
b45433b3 616#ifdef CLASH_DETECTION
d427b66a 617 if (!NILP (current_buffer->filename)
b45433b3
JB
618 && current_buffer->save_modified >= MODIFF)
619 lock_file (current_buffer->filename);
620#else
621 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 622 if (!NILP (current_buffer->filename)
b45433b3 623 && current_buffer->save_modified >= MODIFF
d427b66a
JB
624 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
625 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
626 call1 (intern ("ask-user-about-supersession-threat"),
627 current_buffer->filename);
628#endif /* not CLASH_DETECTION */
629
630 signal_before_change (start, end);
2f545eea 631
56e1065e
JB
632 if (current_buffer->newline_cache)
633 invalidate_region_cache (current_buffer,
634 current_buffer->newline_cache,
635 start - BEG, Z - end);
636 if (current_buffer->width_run_cache)
637 invalidate_region_cache (current_buffer,
638 current_buffer->width_run_cache,
639 start - BEG, Z - end);
640
2f545eea 641 Vdeactivate_mark = Qt;
b45433b3
JB
642}
643\f
644static Lisp_Object
645before_change_function_restore (value)
646 Lisp_Object value;
647{
648 Vbefore_change_function = value;
649}
650
651static Lisp_Object
652after_change_function_restore (value)
653 Lisp_Object value;
654{
655 Vafter_change_function = value;
656}
657
e45fb8bf
RS
658static Lisp_Object
659before_change_functions_restore (value)
660 Lisp_Object value;
661{
662 Vbefore_change_functions = value;
663}
664
665static Lisp_Object
666after_change_functions_restore (value)
667 Lisp_Object value;
668{
669 Vafter_change_functions = value;
670}
671
eb8c3be9 672/* Signal a change to the buffer immediately before it happens.
b45433b3
JB
673 START and END are the bounds of the text to be changed,
674 as Lisp objects. */
675
676signal_before_change (start, end)
677 Lisp_Object start, end;
678{
679 /* If buffer is unmodified, run a special hook for that case. */
680 if (current_buffer->save_modified >= MODIFF
dbc4e1c1
JB
681 && !NILP (Vfirst_change_hook)
682 && !NILP (Vrun_hooks))
683 call1 (Vrun_hooks, Qfirst_change_hook);
684
b45433b3 685 /* Now in any case run the before-change-function if any. */
d427b66a 686 if (!NILP (Vbefore_change_function))
b45433b3
JB
687 {
688 int count = specpdl_ptr - specpdl;
689 Lisp_Object function;
690
691 function = Vbefore_change_function;
e45fb8bf 692
b45433b3
JB
693 record_unwind_protect (after_change_function_restore,
694 Vafter_change_function);
695 record_unwind_protect (before_change_function_restore,
696 Vbefore_change_function);
e45fb8bf
RS
697 record_unwind_protect (after_change_functions_restore,
698 Vafter_change_functions);
699 record_unwind_protect (before_change_functions_restore,
700 Vbefore_change_functions);
b45433b3
JB
701 Vafter_change_function = Qnil;
702 Vbefore_change_function = Qnil;
e45fb8bf
RS
703 Vafter_change_functions = Qnil;
704 Vbefore_change_functions = Qnil;
b45433b3
JB
705
706 call2 (function, start, end);
707 unbind_to (count, Qnil);
708 }
e45fb8bf
RS
709
710 /* Now in any case run the before-change-function if any. */
711 if (!NILP (Vbefore_change_functions))
712 {
713 int count = specpdl_ptr - specpdl;
714 Lisp_Object functions;
715
716 functions = Vbefore_change_functions;
717
718 record_unwind_protect (after_change_function_restore,
719 Vafter_change_function);
720 record_unwind_protect (before_change_function_restore,
721 Vbefore_change_function);
722 record_unwind_protect (after_change_functions_restore,
723 Vafter_change_functions);
724 record_unwind_protect (before_change_functions_restore,
725 Vbefore_change_functions);
726 Vafter_change_function = Qnil;
727 Vbefore_change_function = Qnil;
728 Vafter_change_functions = Qnil;
729 Vbefore_change_functions = Qnil;
730
731 while (CONSP (functions))
732 {
733 call2 (XCONS (functions)->car, start, end);
734 functions = XCONS (functions)->cdr;
735 }
736 unbind_to (count, Qnil);
737 }
b45433b3
JB
738}
739
eb8c3be9 740/* Signal a change immediately after it happens.
b45433b3
JB
741 POS is the address of the start of the changed text.
742 LENDEL is the number of characters of the text before the change.
743 (Not the whole buffer; just the part that was changed.)
744 LENINS is the number of characters in the changed text. */
745
746signal_after_change (pos, lendel, lenins)
747 int pos, lendel, lenins;
748{
d427b66a 749 if (!NILP (Vafter_change_function))
b45433b3
JB
750 {
751 int count = specpdl_ptr - specpdl;
752 Lisp_Object function;
753 function = Vafter_change_function;
754
755 record_unwind_protect (after_change_function_restore,
756 Vafter_change_function);
757 record_unwind_protect (before_change_function_restore,
758 Vbefore_change_function);
e45fb8bf
RS
759 record_unwind_protect (after_change_functions_restore,
760 Vafter_change_functions);
761 record_unwind_protect (before_change_functions_restore,
762 Vbefore_change_functions);
b45433b3
JB
763 Vafter_change_function = Qnil;
764 Vbefore_change_function = Qnil;
e45fb8bf
RS
765 Vafter_change_functions = Qnil;
766 Vbefore_change_functions = Qnil;
b45433b3
JB
767
768 call3 (function, make_number (pos), make_number (pos + lenins),
769 make_number (lendel));
770 unbind_to (count, Qnil);
771 }
e45fb8bf
RS
772 if (!NILP (Vafter_change_functions))
773 {
774 int count = specpdl_ptr - specpdl;
775 Lisp_Object functions;
776 functions = Vafter_change_functions;
777
778 record_unwind_protect (after_change_function_restore,
779 Vafter_change_function);
780 record_unwind_protect (before_change_function_restore,
781 Vbefore_change_function);
782 record_unwind_protect (after_change_functions_restore,
783 Vafter_change_functions);
784 record_unwind_protect (before_change_functions_restore,
785 Vbefore_change_functions);
786 Vafter_change_function = Qnil;
787 Vbefore_change_function = Qnil;
788 Vafter_change_functions = Qnil;
789 Vbefore_change_functions = Qnil;
790
791 while (CONSP (functions))
792 {
793 call3 (XCONS (functions)->car,
794 make_number (pos), make_number (pos + lenins),
795 make_number (lendel));
796 functions = XCONS (functions)->cdr;
797 }
798 unbind_to (count, Qnil);
799 }
b45433b3 800}