Update FSF's address in the preamble.
[bpt/emacs.git] / src / insdel.c
CommitLineData
b45433b3 1/* Buffer insertion/deletion and gap motion for GNU Emacs.
f8c25f1b 2 Copyright (C) 1985, 1986, 1993, 1994, 1995 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
7c938215 8the Free Software Foundation; either version 2, or (at your option)
b45433b3
JB
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
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
b45433b3
JB
20
21
18160b98 22#include <config.h>
b45433b3 23#include "lisp.h"
679194a6 24#include "intervals.h"
b45433b3
JB
25#include "buffer.h"
26#include "window.h"
d014bf88 27#include "blockinput.h"
b45433b3 28
14f6194b
RS
29#define min(x, y) ((x) < (y) ? (x) : (y))
30
395ec62e 31static void insert_from_string_1 ();
ef29f213 32static void insert_from_buffer_1 ();
2bcaed71
KH
33static void gap_left ();
34static void gap_right ();
35static void adjust_markers ();
a27a38d8 36static void adjust_point ();
395ec62e 37
b45433b3
JB
38/* Move gap to position `pos'.
39 Note that this can quit! */
40
c660b094 41void
b45433b3
JB
42move_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
2bcaed71 54static void
b45433b3
JB
55gap_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
2bcaed71 137static void
b45433b3
JB
138gap_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
2bcaed71 219static void
b45433b3
JB
220adjust_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
9fbf87cd 227 marker = BUF_MARKERS (current_buffer);
b45433b3 228
d427b66a 229 while (!NILP (marker))
b45433b3
JB
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}
a27a38d8 249
beecb55b
RS
250/* Adjust markers whose insertion-type is t
251 for an insertion of AMOUNT characters at POS. */
252
253static void
254adjust_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
a27a38d8
KH
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
8e6208c5 275 either the old or the new value of point is out of sync with the
a27a38d8
KH
276 current set of intervals. */
277static void
278adjust_point (amount)
29eb72ac 279 int amount;
a27a38d8 280{
9fbf87cd 281 BUF_PT (current_buffer) += amount;
a27a38d8 282}
b45433b3
JB
283\f
284/* Make the gap INCREMENT characters longer. */
285
c660b094 286void
b45433b3
JB
287make_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
94056516
RS
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
14f6194b 302 if (Z - BEG + GAP_SIZE + increment
68be917d 303 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
14f6194b 304 error ("Buffer exceeds maximum size");
94056516 305
9ac0d9e0 306 BLOCK_INPUT;
b45433b3 307 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
9ac0d9e0 308
b45433b3 309 if (result == 0)
270c2138
RS
310 {
311 UNBLOCK_INPUT;
312 memory_full ();
313 }
314
315 /* We can't unblock until the new address is properly stored. */
b45433b3 316 BEG_ADDR = result;
270c2138 317 UNBLOCK_INPUT;
b45433b3
JB
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.
ef29f213
KH
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. */
b45433b3 344
c660b094 345void
b45433b3
JB
346insert (string, length)
347 register unsigned char *string;
348 register length;
349{
395ec62e
KH
350 if (length > 0)
351 {
c660b094 352 insert_1 (string, length, 0, 1);
cd11ef31
RS
353 signal_after_change (PT-length, 0, length);
354 }
355}
356
c660b094 357void
cd11ef31
RS
358insert_and_inherit (string, length)
359 register unsigned char *string;
360 register length;
361{
362 if (length > 0)
363 {
c660b094 364 insert_1 (string, length, 1, 1);
2bcaed71 365 signal_after_change (PT-length, 0, length);
395ec62e
KH
366 }
367}
b45433b3 368
c660b094
KH
369void
370insert_1 (string, length, inherit, prepare)
395ec62e 371 register unsigned char *string;
c660b094
KH
372 register int length;
373 int inherit, prepare;
395ec62e
KH
374{
375 register Lisp_Object temp;
b45433b3 376
c660b094
KH
377 if (prepare)
378 prepare_to_modify_buffer (PT, PT);
b45433b3 379
2bcaed71
KH
380 if (PT != GPT)
381 move_gap (PT);
b45433b3
JB
382 if (GAP_SIZE < length)
383 make_gap (length - GAP_SIZE);
384
2bcaed71 385 record_insert (PT, length);
b45433b3
JB
386 MODIFF++;
387
388 bcopy (string, GPT_ADDR, length);
389
648c4c55 390#ifdef USE_TEXT_PROPERTIES
9fbf87cd 391 if (BUF_INTERVALS (current_buffer) != 0)
648c4c55
RS
392 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
393 offset_intervals (current_buffer, PT, length);
394#endif
679194a6 395
b45433b3
JB
396 GAP_SIZE -= length;
397 GPT += length;
398 ZV += length;
399 Z += length;
adde4858 400 adjust_overlays_for_insert (PT, length);
beecb55b 401 adjust_markers_for_insert (PT, length);
a27a38d8 402 adjust_point (length);
cd11ef31 403
648c4c55 404#ifdef USE_TEXT_PROPERTIES
9fbf87cd 405 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
cd11ef31
RS
406 Fset_text_properties (make_number (PT - length), make_number (PT),
407 Qnil, Qnil);
648c4c55 408#endif
b45433b3
JB
409}
410
679194a6
JA
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
7e1ea612
JB
417 before we bcopy the stuff into the buffer, and relocate the string
418 without insert noticing. */
679194a6 419
c660b094 420void
9391e591 421insert_from_string (string, pos, length, inherit)
b45433b3
JB
422 Lisp_Object string;
423 register int pos, length;
9391e591 424 int inherit;
395ec62e
KH
425{
426 if (length > 0)
427 {
428 insert_from_string_1 (string, pos, length, inherit);
2bcaed71 429 signal_after_change (PT-length, 0, length);
395ec62e
KH
430 }
431}
432
433static void
434insert_from_string_1 (string, pos, length, inherit)
435 Lisp_Object string;
436 register int pos, length;
437 int inherit;
b45433b3
JB
438{
439 register Lisp_Object temp;
440 struct gcpro gcpro1;
441
b45433b3 442 /* Make sure point-max won't overflow after this insertion. */
eb7db9e6 443 XSETINT (temp, length + Z);
b45433b3
JB
444 if (length + Z != XINT (temp))
445 error ("maximum buffer size exceeded");
446
447 GCPRO1 (string);
2bcaed71 448 prepare_to_modify_buffer (PT, PT);
b45433b3 449
2bcaed71
KH
450 if (PT != GPT)
451 move_gap (PT);
b45433b3
JB
452 if (GAP_SIZE < length)
453 make_gap (length - GAP_SIZE);
454
2bcaed71 455 record_insert (PT, length);
b45433b3
JB
456 MODIFF++;
457 UNGCPRO;
458
459 bcopy (XSTRING (string)->data, GPT_ADDR, length);
460
679194a6 461 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2bcaed71 462 offset_intervals (current_buffer, PT, length);
679194a6 463
b45433b3
JB
464 GAP_SIZE -= length;
465 GPT += length;
466 ZV += length;
467 Z += length;
adde4858 468 adjust_overlays_for_insert (PT, length);
beecb55b 469 adjust_markers_for_insert (PT, length);
679194a6
JA
470
471 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2bcaed71 472 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
9391e591 473 current_buffer, inherit);
679194a6 474
a27a38d8 475 adjust_point (length);
b45433b3
JB
476}
477
ef29f213
KH
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
485void
486insert_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
498static void
499insert_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 {
61bd0e9c
RS
524 chunk = BUF_GPT (buf) - pos;
525 if (chunk > length)
526 chunk = length;
ef29f213
KH
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
9fbf87cd 536 if (BUF_INTERVALS (current_buffer) != 0)
ef29f213
KH
537 offset_intervals (current_buffer, PT, length);
538#endif
539
540 GAP_SIZE -= length;
541 GPT += length;
542 ZV += length;
543 Z += length;
adde4858 544 adjust_overlays_for_insert (PT, length);
beecb55b 545 adjust_markers_for_insert (PT, length);
ef29f213
KH
546 adjust_point (length);
547
548 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd
RS
549 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
550 pos, length),
ef29f213
KH
551 PT - length, length, current_buffer, inherit);
552}
553
b45433b3
JB
554/* Insert the character C before point */
555
556void
557insert_char (c)
558 unsigned char c;
559{
560 insert (&c, 1);
561}
562
563/* Insert the null-terminated string S before point */
564
565void
566insert_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
c660b094 577void
b45433b3
JB
578insert_before_markers (string, length)
579 unsigned char *string;
580 register int length;
581{
395ec62e
KH
582 if (length > 0)
583 {
2bcaed71 584 register int opoint = PT;
c660b094 585 insert_1 (string, length, 0, 1);
395ec62e 586 adjust_markers (opoint - 1, opoint, length);
2bcaed71 587 signal_after_change (PT-length, 0, length);
395ec62e 588 }
b45433b3
JB
589}
590
c660b094 591void
598fb6fe
RS
592insert_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;
c660b094 599 insert_1 (string, length, 1, 1);
598fb6fe
RS
600 adjust_markers (opoint - 1, opoint, length);
601 signal_after_change (PT-length, 0, length);
602 }
603}
604
b45433b3
JB
605/* Insert part of a Lisp string, relocating markers after. */
606
c660b094 607void
9391e591 608insert_from_string_before_markers (string, pos, length, inherit)
b45433b3
JB
609 Lisp_Object string;
610 register int pos, length;
9391e591 611 int inherit;
b45433b3 612{
395ec62e
KH
613 if (length > 0)
614 {
2bcaed71 615 register int opoint = PT;
395ec62e
KH
616 insert_from_string_1 (string, pos, length, inherit);
617 adjust_markers (opoint - 1, opoint, length);
2bcaed71 618 signal_after_change (PT-length, 0, length);
395ec62e 619 }
b45433b3
JB
620}
621\f
622/* Delete characters in current buffer
623 from FROM up to (but not including) TO. */
624
c660b094 625void
b45433b3
JB
626del_range (from, to)
627 register int from, to;
47c64747 628{
c660b094 629 del_range_1 (from, to, 1);
47c64747
RS
630}
631
632/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
633
c660b094 634void
47c64747
RS
635del_range_1 (from, to, prepare)
636 register int from, to, prepare;
b45433b3
JB
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
47c64747
RS
655 if (prepare)
656 prepare_to_modify_buffer (from, to);
b45433b3 657
be09561e
RS
658 record_delete (from, numdel);
659 MODIFF++;
660
b45433b3 661 /* Relocate point as if it were a marker. */
2bcaed71 662 if (from < PT)
a27a38d8 663 adjust_point (from - (PT < to ? PT : to));
b45433b3 664
16032db6 665 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
83010cd6 666 offset_intervals (current_buffer, from, - numdel);
16032db6 667
b45433b3
JB
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
adde4858 672 /* Adjust the overlay center as needed. This must be done after
a7f38d28 673 adjusting the markers that bound the overlays. */
adde4858
KH
674 adjust_overlays_for_delete (from, numdel);
675
b45433b3
JB
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
d386034e 686 evaporate_overlays (from);
b45433b3
JB
687 signal_after_change (from, numdel, 0);
688}
689\f
04a759c8
JB
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. */
c660b094 694void
04a759c8
JB
695modify_region (buffer, start, end)
696 struct buffer *buffer;
b45433b3
JB
697 int start, end;
698{
04a759c8
JB
699 struct buffer *old_buffer = current_buffer;
700
701 if (buffer != old_buffer)
702 set_buffer_internal (buffer);
703
b45433b3
JB
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;
83010cd6 711
9fbf87cd 712 if (MODIFF <= SAVE_MODIFF)
83010cd6 713 record_first_change ();
b45433b3 714 MODIFF++;
04a759c8 715
069cdc4f
RS
716 buffer->point_before_scroll = Qnil;
717
04a759c8
JB
718 if (buffer != old_buffer)
719 set_buffer_internal (old_buffer);
b45433b3
JB
720}
721
722/* Check that it is okay to modify the buffer between START and END.
679194a6
JA
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. */
b45433b3 726
c660b094 727void
b45433b3
JB
728prepare_to_modify_buffer (start, end)
729 Lisp_Object start, end;
730{
d427b66a 731 if (!NILP (current_buffer->read_only))
b45433b3
JB
732 Fbarf_if_buffer_read_only ();
733
679194a6 734 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd 735 if (BUF_INTERVALS (current_buffer) != 0)
648c4c55 736 verify_interval_modification (current_buffer, start, end);
b45433b3
JB
737
738#ifdef CLASH_DETECTION
f173b650 739 if (!NILP (current_buffer->file_truename)
ab6c5c0c
RS
740 /* Make binding buffer-file-name to nil effective. */
741 && !NILP (current_buffer->filename)
9fbf87cd 742 && SAVE_MODIFF >= MODIFF)
f173b650 743 lock_file (current_buffer->file_truename);
b45433b3
JB
744#else
745 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 746 if (!NILP (current_buffer->filename)
9fbf87cd 747 && SAVE_MODIFF >= MODIFF
d427b66a
JB
748 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
749 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
750 call1 (intern ("ask-user-about-supersession-threat"),
751 current_buffer->filename);
752#endif /* not CLASH_DETECTION */
753
754 signal_before_change (start, end);
2f545eea 755
56e1065e
JB
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
2f545eea 765 Vdeactivate_mark = Qt;
b45433b3
JB
766}
767\f
eb8c3be9 768/* Signal a change to the buffer immediately before it happens.
b45433b3
JB
769 START and END are the bounds of the text to be changed,
770 as Lisp objects. */
771
c660b094 772void
b45433b3
JB
773signal_before_change (start, end)
774 Lisp_Object start, end;
775{
776 /* If buffer is unmodified, run a special hook for that case. */
9fbf87cd 777 if (SAVE_MODIFF >= MODIFF
dbc4e1c1
JB
778 && !NILP (Vfirst_change_hook)
779 && !NILP (Vrun_hooks))
780 call1 (Vrun_hooks, Qfirst_change_hook);
781
3d1e2d9c
RS
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. */
d427b66a 785 if (!NILP (Vbefore_change_function))
3d1e2d9c 786 call2 (Vbefore_change_function, start, end);
e45fb8bf 787
3d1e2d9c 788 /* Now run the before-change-functions if any. */
e45fb8bf
RS
789 if (!NILP (Vbefore_change_functions))
790 {
3d1e2d9c
RS
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;
c82c1da0
KH
801 Vbefore_change_functions = Qnil;
802 Vafter_change_functions = Qnil;
3d1e2d9c
RS
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;
e45fb8bf 815 }
d07c0804
RS
816
817 if (!NILP (current_buffer->overlays_before)
818 || !NILP (current_buffer->overlays_after))
835220e8 819 report_overlay_modification (start, end, 0, start, end, Qnil);
b45433b3
JB
820}
821
eb8c3be9 822/* Signal a change immediately after it happens.
b45433b3
JB
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.)
d07c0804
RS
826 LENINS is the number of characters in the changed text.
827
828 (Hence POS + LENINS - LENDEL is the position after the changed text.) */
b45433b3 829
c660b094 830void
b45433b3
JB
831signal_after_change (pos, lendel, lenins)
832 int pos, lendel, lenins;
833{
3d1e2d9c
RS
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. */
d427b66a 837 if (!NILP (Vafter_change_function))
3d1e2d9c
RS
838 call3 (Vafter_change_function,
839 make_number (pos), make_number (pos + lenins),
840 make_number (lendel));
b45433b3 841
e45fb8bf
RS
842 if (!NILP (Vafter_change_functions))
843 {
3d1e2d9c
RS
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;
c82c1da0
KH
854 Vbefore_change_functions = Qnil;
855 Vafter_change_functions = Qnil;
3d1e2d9c
RS
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;
e45fb8bf 870 }
d07c0804
RS
871
872 if (!NILP (current_buffer->overlays_before)
873 || !NILP (current_buffer->overlays_after))
835220e8 874 report_overlay_modification (make_number (pos),
d07c0804
RS
875 make_number (pos + lenins - lendel),
876 1,
877 make_number (pos), make_number (pos + lenins),
878 make_number (lendel));
c5ca0786
RS
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);
b45433b3 884}