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