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