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