(detect_coding_iso2022): Do not exclude posibility of
[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 25#include "buffer.h"
469ff680 26#include "charset.h"
b45433b3 27#include "window.h"
d014bf88 28#include "blockinput.h"
b45433b3 29
d206af14
RS
30#ifndef NULL
31#define NULL 0
32#endif
33
14f6194b
RS
34#define min(x, y) ((x) < (y) ? (x) : (y))
35
395ec62e 36static void insert_from_string_1 ();
ef29f213 37static void insert_from_buffer_1 ();
2bcaed71
KH
38static void gap_left ();
39static void gap_right ();
40static void adjust_markers ();
a27a38d8 41static void adjust_point ();
395ec62e 42
fb2e7d14
RS
43Lisp_Object Fcombine_after_change_execute ();
44
45/* Non-nil means don't call the after-change-functions right away,
46 just record an element in Vcombine_after_change_calls_list. */
47Lisp_Object Vcombine_after_change_calls;
48
49/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
50 describing changes which happened while combine_after_change_calls
51 was nonzero. We use this to decide how to call them
52 once the deferral ends.
53
54 In each element.
55 BEG-UNCHANGED is the number of chars before the changed range.
56 END-UNCHANGED is the number of chars after the changed range,
57 and CHANGE-AMOUNT is the number of characters inserted by the change
58 (negative for a deletion). */
59Lisp_Object combine_after_change_list;
60
61/* Buffer which combine_after_change_list is about. */
62Lisp_Object combine_after_change_buffer;
63
b45433b3
JB
64/* Move gap to position `pos'.
65 Note that this can quit! */
66
c660b094 67void
b45433b3
JB
68move_gap (pos)
69 int pos;
70{
71 if (pos < GPT)
72 gap_left (pos, 0);
73 else if (pos > GPT)
74 gap_right (pos);
75}
76
77/* Move the gap to POS, which is less than the current GPT.
78 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
79
2bcaed71 80static void
b45433b3
JB
81gap_left (pos, newgap)
82 register int pos;
83 int newgap;
84{
85 register unsigned char *to, *from;
86 register int i;
87 int new_s1;
88
89 pos--;
90
91 if (!newgap)
92 {
894ab630
RS
93 if (unchanged_modified == MODIFF
94 && overlay_unchanged_modified == OVERLAY_MODIFF)
b45433b3
JB
95 {
96 beg_unchanged = pos;
97 end_unchanged = Z - pos - 1;
98 }
99 else
100 {
101 if (Z - GPT < end_unchanged)
102 end_unchanged = Z - GPT;
103 if (pos < beg_unchanged)
104 beg_unchanged = pos;
105 }
106 }
107
108 i = GPT;
109 to = GAP_END_ADDR;
110 from = GPT_ADDR;
111 new_s1 = GPT - BEG;
112
113 /* Now copy the characters. To move the gap down,
114 copy characters up. */
115
116 while (1)
117 {
118 /* I gets number of characters left to copy. */
119 i = new_s1 - pos;
120 if (i == 0)
121 break;
122 /* If a quit is requested, stop copying now.
123 Change POS to be where we have actually moved the gap to. */
124 if (QUITP)
125 {
126 pos = new_s1;
127 break;
128 }
129 /* Move at most 32000 chars before checking again for a quit. */
130 if (i > 32000)
131 i = 32000;
132#ifdef GAP_USE_BCOPY
133 if (i >= 128
134 /* bcopy is safe if the two areas of memory do not overlap
135 or on systems where bcopy is always safe for moving upward. */
136 && (BCOPY_UPWARD_SAFE
137 || to - from >= 128))
138 {
139 /* If overlap is not safe, avoid it by not moving too many
140 characters at once. */
141 if (!BCOPY_UPWARD_SAFE && i > to - from)
142 i = to - from;
143 new_s1 -= i;
144 from -= i, to -= i;
145 bcopy (from, to, i);
146 }
147 else
148#endif
149 {
150 new_s1 -= i;
151 while (--i >= 0)
152 *--to = *--from;
153 }
154 }
155
156 /* Adjust markers, and buffer data structure, to put the gap at POS.
157 POS is where the loop above stopped, which may be what was specified
158 or may be where a quit was detected. */
159 adjust_markers (pos + 1, GPT, GAP_SIZE);
160 GPT = pos + 1;
469ff680 161 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
162 QUIT;
163}
164
2bcaed71 165static void
b45433b3
JB
166gap_right (pos)
167 register int pos;
168{
169 register unsigned char *to, *from;
170 register int i;
171 int new_s1;
172
173 pos--;
174
894ab630
RS
175 if (unchanged_modified == MODIFF
176 && overlay_unchanged_modified == OVERLAY_MODIFF)
177
b45433b3
JB
178 {
179 beg_unchanged = pos;
180 end_unchanged = Z - pos - 1;
181 }
182 else
183 {
184 if (Z - pos - 1 < end_unchanged)
185 end_unchanged = Z - pos - 1;
186 if (GPT - BEG < beg_unchanged)
187 beg_unchanged = GPT - BEG;
188 }
189
190 i = GPT;
191 from = GAP_END_ADDR;
192 to = GPT_ADDR;
193 new_s1 = GPT - 1;
194
195 /* Now copy the characters. To move the gap up,
196 copy characters down. */
197
198 while (1)
199 {
200 /* I gets number of characters left to copy. */
201 i = pos - new_s1;
202 if (i == 0)
203 break;
204 /* If a quit is requested, stop copying now.
205 Change POS to be where we have actually moved the gap to. */
206 if (QUITP)
207 {
208 pos = new_s1;
209 break;
210 }
211 /* Move at most 32000 chars before checking again for a quit. */
212 if (i > 32000)
213 i = 32000;
214#ifdef GAP_USE_BCOPY
215 if (i >= 128
216 /* bcopy is safe if the two areas of memory do not overlap
217 or on systems where bcopy is always safe for moving downward. */
218 && (BCOPY_DOWNWARD_SAFE
219 || from - to >= 128))
220 {
221 /* If overlap is not safe, avoid it by not moving too many
222 characters at once. */
223 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
224 i = from - to;
225 new_s1 += i;
226 bcopy (from, to, i);
227 from += i, to += i;
228 }
229 else
230#endif
231 {
232 new_s1 += i;
233 while (--i >= 0)
234 *to++ = *from++;
235 }
236 }
237
238 adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
239 GPT = pos + 1;
469ff680 240 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
241 QUIT;
242}
243
8948d317
RS
244/* Add AMOUNT to the position of every marker in the current buffer
245 whose current position is between FROM (exclusive) and TO (inclusive).
246
b45433b3
JB
247 Also, any markers past the outside of that interval, in the direction
248 of adjustment, are first moved back to the near end of the interval
8948d317
RS
249 and then adjusted by AMOUNT.
250
251 When the latter adjustment is done, if AMOUNT is negative,
252 we record the adjustment for undo. (This case happens only for
253 deletion.) */
b45433b3 254
2bcaed71 255static void
b45433b3
JB
256adjust_markers (from, to, amount)
257 register int from, to, amount;
258{
259 Lisp_Object marker;
260 register struct Lisp_Marker *m;
261 register int mpos;
262
9fbf87cd 263 marker = BUF_MARKERS (current_buffer);
b45433b3 264
d427b66a 265 while (!NILP (marker))
b45433b3
JB
266 {
267 m = XMARKER (marker);
268 mpos = m->bufpos;
269 if (amount > 0)
270 {
271 if (mpos > to && mpos < to + amount)
272 mpos = to + amount;
273 }
274 else
275 {
8948d317
RS
276 /* Here's the case where a marker is inside text being deleted.
277 AMOUNT can be negative for gap motion, too,
278 but then this range contains no markers. */
b45433b3 279 if (mpos > from + amount && mpos <= from)
8948d317 280 {
9856e218
RS
281 int before = mpos;
282 int after = from + amount;
283
284 mpos = after;
285
286 /* Compute the before and after positions
287 as buffer positions. */
288 if (before > GPT + GAP_SIZE)
289 before -= GAP_SIZE;
290 else if (before > GPT)
291 before = GPT;
292
293 if (after > GPT + GAP_SIZE)
294 after -= GAP_SIZE;
295 else if (after > GPT)
296 after = GPT;
297
298 record_marker_adjustment (marker, after - before);
8948d317 299 }
b45433b3
JB
300 }
301 if (mpos > from && mpos <= to)
302 mpos += amount;
303 m->bufpos = mpos;
304 marker = m->chain;
305 }
306}
a27a38d8 307
beecb55b
RS
308/* Adjust markers whose insertion-type is t
309 for an insertion of AMOUNT characters at POS. */
310
311static void
312adjust_markers_for_insert (pos, amount)
313 register int pos, amount;
314{
315 Lisp_Object marker;
469ff680 316 int adjusted = 0;
beecb55b
RS
317
318 marker = BUF_MARKERS (current_buffer);
319
320 while (!NILP (marker))
321 {
322 register struct Lisp_Marker *m = XMARKER (marker);
323 if (m->insertion_type && m->bufpos == pos)
469ff680
KH
324 {
325 m->bufpos += amount;
326 adjusted = 1;
327 }
beecb55b
RS
328 marker = m->chain;
329 }
469ff680
KH
330 if (adjusted)
331 /* Adjusting only markers whose insertion-type is t may result in
332 disordered overlays in the slot `overlays_before'. */
333 fix_overlays_before (current_buffer, pos, pos + amount);
beecb55b
RS
334}
335
a27a38d8
KH
336/* Add the specified amount to point. This is used only when the value
337 of point changes due to an insert or delete; it does not represent
338 a conceptual change in point as a marker. In particular, point is
339 not crossing any interval boundaries, so there's no need to use the
340 usual SET_PT macro. In fact it would be incorrect to do so, because
8e6208c5 341 either the old or the new value of point is out of sync with the
a27a38d8
KH
342 current set of intervals. */
343static void
344adjust_point (amount)
29eb72ac 345 int amount;
a27a38d8 346{
9fbf87cd 347 BUF_PT (current_buffer) += amount;
a27a38d8 348}
b45433b3
JB
349\f
350/* Make the gap INCREMENT characters longer. */
351
c660b094 352void
b45433b3
JB
353make_gap (increment)
354 int increment;
355{
356 unsigned char *result;
357 Lisp_Object tem;
358 int real_gap_loc;
359 int old_gap_size;
360
361 /* If we have to get more space, get enough to last a while. */
362 increment += 2000;
363
94056516
RS
364 /* Don't allow a buffer size that won't fit in an int
365 even if it will fit in a Lisp integer.
366 That won't work because so many places use `int'. */
367
14f6194b 368 if (Z - BEG + GAP_SIZE + increment
68be917d 369 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
14f6194b 370 error ("Buffer exceeds maximum size");
94056516 371
9ac0d9e0 372 BLOCK_INPUT;
469ff680
KH
373 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
374 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment + 1));
9ac0d9e0 375
b45433b3 376 if (result == 0)
270c2138
RS
377 {
378 UNBLOCK_INPUT;
379 memory_full ();
380 }
381
382 /* We can't unblock until the new address is properly stored. */
b45433b3 383 BEG_ADDR = result;
270c2138 384 UNBLOCK_INPUT;
b45433b3
JB
385
386 /* Prevent quitting in move_gap. */
387 tem = Vinhibit_quit;
388 Vinhibit_quit = Qt;
389
390 real_gap_loc = GPT;
391 old_gap_size = GAP_SIZE;
392
393 /* Call the newly allocated space a gap at the end of the whole space. */
394 GPT = Z + GAP_SIZE;
395 GAP_SIZE = increment;
396
397 /* Move the new gap down to be consecutive with the end of the old one.
398 This adjusts the markers properly too. */
399 gap_left (real_gap_loc + old_gap_size, 1);
400
401 /* Now combine the two into one large gap. */
402 GAP_SIZE += old_gap_size;
403 GPT = real_gap_loc;
404
469ff680
KH
405 /* Put an anchor. */
406 *(Z_ADDR) = 0;
407
b45433b3
JB
408 Vinhibit_quit = tem;
409}
410\f
411/* Insert a string of specified length before point.
ef29f213
KH
412 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
413 prepare_to_modify_buffer could relocate the text. */
b45433b3 414
c660b094 415void
b45433b3
JB
416insert (string, length)
417 register unsigned char *string;
418 register length;
419{
395ec62e
KH
420 if (length > 0)
421 {
c660b094 422 insert_1 (string, length, 0, 1);
cd11ef31
RS
423 signal_after_change (PT-length, 0, length);
424 }
425}
426
c660b094 427void
cd11ef31
RS
428insert_and_inherit (string, length)
429 register unsigned char *string;
430 register length;
431{
432 if (length > 0)
433 {
c660b094 434 insert_1 (string, length, 1, 1);
2bcaed71 435 signal_after_change (PT-length, 0, length);
395ec62e
KH
436 }
437}
b45433b3 438
c660b094
KH
439void
440insert_1 (string, length, inherit, prepare)
395ec62e 441 register unsigned char *string;
c660b094
KH
442 register int length;
443 int inherit, prepare;
395ec62e
KH
444{
445 register Lisp_Object temp;
b45433b3 446
c660b094 447 if (prepare)
d206af14 448 prepare_to_modify_buffer (PT, PT, NULL);
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
458 bcopy (string, GPT_ADDR, length);
459
648c4c55 460#ifdef USE_TEXT_PROPERTIES
9fbf87cd 461 if (BUF_INTERVALS (current_buffer) != 0)
648c4c55
RS
462 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
463 offset_intervals (current_buffer, PT, length);
464#endif
679194a6 465
b45433b3
JB
466 GAP_SIZE -= length;
467 GPT += length;
468 ZV += length;
469 Z += length;
469ff680 470 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
adde4858 471 adjust_overlays_for_insert (PT, length);
beecb55b 472 adjust_markers_for_insert (PT, length);
a27a38d8 473 adjust_point (length);
cd11ef31 474
648c4c55 475#ifdef USE_TEXT_PROPERTIES
9fbf87cd 476 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
cd11ef31
RS
477 Fset_text_properties (make_number (PT - length), make_number (PT),
478 Qnil, Qnil);
648c4c55 479#endif
b45433b3
JB
480}
481
679194a6
JA
482/* Insert the part of the text of STRING, a Lisp object assumed to be
483 of type string, consisting of the LENGTH characters starting at
484 position POS. If the text of STRING has properties, they are absorbed
485 into the buffer.
486
487 It does not work to use `insert' for this, because a GC could happen
7e1ea612
JB
488 before we bcopy the stuff into the buffer, and relocate the string
489 without insert noticing. */
679194a6 490
c660b094 491void
9391e591 492insert_from_string (string, pos, length, inherit)
b45433b3
JB
493 Lisp_Object string;
494 register int pos, length;
9391e591 495 int inherit;
395ec62e
KH
496{
497 if (length > 0)
498 {
499 insert_from_string_1 (string, pos, length, inherit);
2bcaed71 500 signal_after_change (PT-length, 0, length);
395ec62e
KH
501 }
502}
503
504static void
505insert_from_string_1 (string, pos, length, inherit)
506 Lisp_Object string;
507 register int pos, length;
508 int inherit;
b45433b3
JB
509{
510 register Lisp_Object temp;
511 struct gcpro gcpro1;
512
b45433b3 513 /* Make sure point-max won't overflow after this insertion. */
eb7db9e6 514 XSETINT (temp, length + Z);
b45433b3
JB
515 if (length + Z != XINT (temp))
516 error ("maximum buffer size exceeded");
517
518 GCPRO1 (string);
d206af14 519 prepare_to_modify_buffer (PT, PT, NULL);
b45433b3 520
2bcaed71
KH
521 if (PT != GPT)
522 move_gap (PT);
b45433b3
JB
523 if (GAP_SIZE < length)
524 make_gap (length - GAP_SIZE);
525
2bcaed71 526 record_insert (PT, length);
b45433b3
JB
527 MODIFF++;
528 UNGCPRO;
529
530 bcopy (XSTRING (string)->data, GPT_ADDR, length);
531
679194a6 532 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2bcaed71 533 offset_intervals (current_buffer, PT, length);
679194a6 534
b45433b3
JB
535 GAP_SIZE -= length;
536 GPT += length;
537 ZV += length;
538 Z += length;
469ff680 539 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
adde4858 540 adjust_overlays_for_insert (PT, length);
beecb55b 541 adjust_markers_for_insert (PT, length);
679194a6
JA
542
543 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2bcaed71 544 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
9391e591 545 current_buffer, inherit);
679194a6 546
a27a38d8 547 adjust_point (length);
b45433b3
JB
548}
549
ef29f213
KH
550/* Insert text from BUF, starting at POS and having length LENGTH, into the
551 current buffer. If the text in BUF has properties, they are absorbed
552 into the current buffer.
553
554 It does not work to use `insert' for this, because a malloc could happen
555 and relocate BUF's text before the bcopy happens. */
556
557void
558insert_from_buffer (buf, pos, length, inherit)
559 struct buffer *buf;
560 int pos, length;
561 int inherit;
562{
563 if (length > 0)
564 {
565 insert_from_buffer_1 (buf, pos, length, inherit);
566 signal_after_change (PT-length, 0, length);
567 }
568}
569
570static void
571insert_from_buffer_1 (buf, pos, length, inherit)
572 struct buffer *buf;
573 int pos, length;
574 int inherit;
575{
576 register Lisp_Object temp;
577 int chunk;
578
579 /* Make sure point-max won't overflow after this insertion. */
580 XSETINT (temp, length + Z);
581 if (length + Z != XINT (temp))
582 error ("maximum buffer size exceeded");
583
d206af14 584 prepare_to_modify_buffer (PT, PT, NULL);
ef29f213
KH
585
586 if (PT != GPT)
587 move_gap (PT);
588 if (GAP_SIZE < length)
589 make_gap (length - GAP_SIZE);
590
591 record_insert (PT, length);
592 MODIFF++;
593
594 if (pos < BUF_GPT (buf))
595 {
61bd0e9c
RS
596 chunk = BUF_GPT (buf) - pos;
597 if (chunk > length)
598 chunk = length;
ef29f213
KH
599 bcopy (BUF_CHAR_ADDRESS (buf, pos), GPT_ADDR, chunk);
600 }
601 else
602 chunk = 0;
603 if (chunk < length)
604 bcopy (BUF_CHAR_ADDRESS (buf, pos + chunk),
605 GPT_ADDR + chunk, length - chunk);
606
607#ifdef USE_TEXT_PROPERTIES
9fbf87cd 608 if (BUF_INTERVALS (current_buffer) != 0)
ef29f213
KH
609 offset_intervals (current_buffer, PT, length);
610#endif
611
612 GAP_SIZE -= length;
613 GPT += length;
614 ZV += length;
615 Z += length;
469ff680 616 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
adde4858 617 adjust_overlays_for_insert (PT, length);
beecb55b 618 adjust_markers_for_insert (PT, length);
ef29f213
KH
619 adjust_point (length);
620
621 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd
RS
622 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
623 pos, length),
ef29f213
KH
624 PT - length, length, current_buffer, inherit);
625}
626
b45433b3
JB
627/* Insert the character C before point */
628
629void
630insert_char (c)
469ff680 631 int c;
b45433b3 632{
469ff680
KH
633 unsigned char workbuf[4], *str;
634 int len = CHAR_STRING (c, workbuf, str);
635
636 insert (str, len);
b45433b3
JB
637}
638
639/* Insert the null-terminated string S before point */
640
641void
642insert_string (s)
643 char *s;
644{
645 insert (s, strlen (s));
646}
647
648/* Like `insert' except that all markers pointing at the place where
649 the insertion happens are adjusted to point after it.
650 Don't use this function to insert part of a Lisp string,
651 since gc could happen and relocate it. */
652
c660b094 653void
b45433b3
JB
654insert_before_markers (string, length)
655 unsigned char *string;
656 register int length;
657{
395ec62e
KH
658 if (length > 0)
659 {
2bcaed71 660 register int opoint = PT;
c660b094 661 insert_1 (string, length, 0, 1);
395ec62e 662 adjust_markers (opoint - 1, opoint, length);
2bcaed71 663 signal_after_change (PT-length, 0, length);
395ec62e 664 }
b45433b3
JB
665}
666
c660b094 667void
598fb6fe
RS
668insert_before_markers_and_inherit (string, length)
669 unsigned char *string;
670 register int length;
671{
672 if (length > 0)
673 {
674 register int opoint = PT;
c660b094 675 insert_1 (string, length, 1, 1);
598fb6fe
RS
676 adjust_markers (opoint - 1, opoint, length);
677 signal_after_change (PT-length, 0, length);
678 }
679}
680
b45433b3
JB
681/* Insert part of a Lisp string, relocating markers after. */
682
c660b094 683void
9391e591 684insert_from_string_before_markers (string, pos, length, inherit)
b45433b3
JB
685 Lisp_Object string;
686 register int pos, length;
9391e591 687 int inherit;
b45433b3 688{
395ec62e
KH
689 if (length > 0)
690 {
2bcaed71 691 register int opoint = PT;
395ec62e
KH
692 insert_from_string_1 (string, pos, length, inherit);
693 adjust_markers (opoint - 1, opoint, length);
2bcaed71 694 signal_after_change (PT-length, 0, length);
395ec62e 695 }
b45433b3
JB
696}
697\f
c5ca4d3a
RS
698/* Replace the text from FROM to TO with NEW,
699 If PREPARE is nonzero, call prepare_to_modify_buffer.
700 If INHERIT, the newly inserted text should inherit text properties
701 from the surrounding non-deleted text. */
702
703/* Note that this does not yet handle markers quite right.
704 Also it needs to record a single undo-entry that does a replacement
705 rather than a separate delete and insert.
706 That way, undo will also handle markers properly. */
707
708void
709replace_range (from, to, new, prepare, inherit)
710 Lisp_Object new;
711 int from, to, prepare, inherit;
712{
713 int numdel;
714 int inslen = XSTRING (new)->size;
715 register Lisp_Object temp;
716 struct gcpro gcpro1;
717
718 GCPRO1 (new);
719
720 if (prepare)
721 {
722 int range_length = to - from;
723 prepare_to_modify_buffer (from, to, &from);
724 to = from + range_length;
725 }
726
727 /* Make args be valid */
728 if (from < BEGV)
729 from = BEGV;
730 if (to > ZV)
731 to = ZV;
732
733 UNGCPRO;
734
735 numdel = to - from;
736
737 /* Make sure point-max won't overflow after this insertion. */
738 XSETINT (temp, Z - numdel + inslen);
739 if (Z - numdel + inslen != XINT (temp))
740 error ("maximum buffer size exceeded");
741
742 if (numdel <= 0 && inslen == 0)
743 return;
744
745 GCPRO1 (new);
746
747 /* Make sure the gap is somewhere in or next to what we are deleting. */
748 if (from > GPT)
749 gap_right (from);
750 if (to < GPT)
751 gap_left (to, 0);
752
753 /* Relocate all markers pointing into the new, larger gap
754 to point at the end of the text before the gap.
755 This has to be done before recording the deletion,
756 so undo handles this after reinserting the text. */
757 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
758
759 record_delete (from, numdel);
760
761 GAP_SIZE += numdel;
762 ZV -= numdel;
763 Z -= numdel;
764 GPT = from;
765 *(GPT_ADDR) = 0; /* Put an anchor. */
766
767 if (GPT - BEG < beg_unchanged)
768 beg_unchanged = GPT - BEG;
769 if (Z - GPT < end_unchanged)
770 end_unchanged = Z - GPT;
771
772 if (GAP_SIZE < inslen)
773 make_gap (inslen - GAP_SIZE);
774
775 record_insert (from, inslen);
776
777 bcopy (XSTRING (new)->data, GPT_ADDR, inslen);
778
779 /* Relocate point as if it were a marker. */
780 if (from < PT)
781 adjust_point (from + inslen - (PT < to ? PT : to));
782
783#ifdef USE_TEXT_PROPERTIES
784 offset_intervals (current_buffer, PT, inslen - numdel);
785#endif
786
787 GAP_SIZE -= inslen;
788 GPT += inslen;
789 ZV += inslen;
790 Z += inslen;
791 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
792
793 /* Adjust the overlay center as needed. This must be done after
794 adjusting the markers that bound the overlays. */
795 adjust_overlays_for_delete (from, numdel);
796 adjust_overlays_for_insert (from, inslen);
797 adjust_markers_for_insert (from, inslen);
798
799#ifdef USE_TEXT_PROPERTIES
800 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
801 graft_intervals_into_buffer (XSTRING (new)->intervals, from, inslen,
802 current_buffer, inherit);
803#endif
804
805 if (inslen == 0)
806 evaporate_overlays (from);
807
808 MODIFF++;
809 UNGCPRO;
810
811 signal_after_change (from, numdel, inslen);
812}
813\f
b45433b3
JB
814/* Delete characters in current buffer
815 from FROM up to (but not including) TO. */
816
c660b094 817void
b45433b3
JB
818del_range (from, to)
819 register int from, to;
47c64747 820{
c660b094 821 del_range_1 (from, to, 1);
47c64747
RS
822}
823
824/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
825
c660b094 826void
47c64747 827del_range_1 (from, to, prepare)
d206af14 828 int from, to, prepare;
b45433b3
JB
829{
830 register int numdel;
831
d206af14
RS
832 if (prepare)
833 {
834 int range_length = to - from;
835 prepare_to_modify_buffer (from, to, &from);
836 to = from + range_length;
837 }
838
b45433b3
JB
839 /* Make args be valid */
840 if (from < BEGV)
841 from = BEGV;
842 if (to > ZV)
843 to = ZV;
844
845 if ((numdel = to - from) <= 0)
846 return;
847
848 /* Make sure the gap is somewhere in or next to what we are deleting. */
849 if (from > GPT)
850 gap_right (from);
851 if (to < GPT)
852 gap_left (to, 0);
853
8948d317
RS
854 /* Relocate all markers pointing into the new, larger gap
855 to point at the end of the text before the gap.
856 This has to be done before recording the deletion,
857 so undo handles this after reinserting the text. */
858 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
859
be09561e
RS
860 record_delete (from, numdel);
861 MODIFF++;
862
b45433b3 863 /* Relocate point as if it were a marker. */
2bcaed71 864 if (from < PT)
a27a38d8 865 adjust_point (from - (PT < to ? PT : to));
b45433b3 866
16032db6 867 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
83010cd6 868 offset_intervals (current_buffer, from, - numdel);
16032db6 869
adde4858 870 /* Adjust the overlay center as needed. This must be done after
a7f38d28 871 adjusting the markers that bound the overlays. */
adde4858
KH
872 adjust_overlays_for_delete (from, numdel);
873
b45433b3
JB
874 GAP_SIZE += numdel;
875 ZV -= numdel;
876 Z -= numdel;
877 GPT = from;
469ff680 878 *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
879
880 if (GPT - BEG < beg_unchanged)
881 beg_unchanged = GPT - BEG;
882 if (Z - GPT < end_unchanged)
883 end_unchanged = Z - GPT;
884
d386034e 885 evaporate_overlays (from);
b45433b3
JB
886 signal_after_change (from, numdel, 0);
887}
888\f
04a759c8
JB
889/* Call this if you're about to change the region of BUFFER from START
890 to END. This checks the read-only properties of the region, calls
891 the necessary modification hooks, and warns the next redisplay that
892 it should pay attention to that area. */
c660b094 893void
04a759c8
JB
894modify_region (buffer, start, end)
895 struct buffer *buffer;
b45433b3
JB
896 int start, end;
897{
04a759c8
JB
898 struct buffer *old_buffer = current_buffer;
899
900 if (buffer != old_buffer)
901 set_buffer_internal (buffer);
902
d206af14 903 prepare_to_modify_buffer (start, end, NULL);
b45433b3 904
894ab630
RS
905 if (start - 1 < beg_unchanged
906 || (unchanged_modified == MODIFF
907 && overlay_unchanged_modified == OVERLAY_MODIFF))
b45433b3
JB
908 beg_unchanged = start - 1;
909 if (Z - end < end_unchanged
894ab630
RS
910 || (unchanged_modified == MODIFF
911 && overlay_unchanged_modified == OVERLAY_MODIFF))
b45433b3 912 end_unchanged = Z - end;
83010cd6 913
9fbf87cd 914 if (MODIFF <= SAVE_MODIFF)
83010cd6 915 record_first_change ();
b45433b3 916 MODIFF++;
04a759c8 917
069cdc4f
RS
918 buffer->point_before_scroll = Qnil;
919
04a759c8
JB
920 if (buffer != old_buffer)
921 set_buffer_internal (old_buffer);
b45433b3 922}
d206af14 923\f
b45433b3 924/* Check that it is okay to modify the buffer between START and END.
679194a6
JA
925 Run the before-change-function, if any. If intervals are in use,
926 verify that the text to be modified is not read-only, and call
d206af14
RS
927 any modification properties the text may have.
928
929 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
930 by holding its value temporarily in a marker. */
b45433b3 931
c660b094 932void
d206af14 933prepare_to_modify_buffer (start, end, preserve_ptr)
fb4ee5cd 934 int start, end;
d206af14 935 int *preserve_ptr;
b45433b3 936{
d427b66a 937 if (!NILP (current_buffer->read_only))
b45433b3
JB
938 Fbarf_if_buffer_read_only ();
939
679194a6 940 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd 941 if (BUF_INTERVALS (current_buffer) != 0)
d206af14
RS
942 {
943 if (preserve_ptr)
944 {
945 Lisp_Object preserve_marker;
946 struct gcpro gcpro1;
947 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
948 GCPRO1 (preserve_marker);
949 verify_interval_modification (current_buffer, start, end);
950 *preserve_ptr = marker_position (preserve_marker);
951 unchain_marker (preserve_marker);
952 UNGCPRO;
953 }
954 else
955 verify_interval_modification (current_buffer, start, end);
956 }
b45433b3
JB
957
958#ifdef CLASH_DETECTION
f173b650 959 if (!NILP (current_buffer->file_truename)
ab6c5c0c
RS
960 /* Make binding buffer-file-name to nil effective. */
961 && !NILP (current_buffer->filename)
9fbf87cd 962 && SAVE_MODIFF >= MODIFF)
f173b650 963 lock_file (current_buffer->file_truename);
b45433b3
JB
964#else
965 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 966 if (!NILP (current_buffer->filename)
9fbf87cd 967 && SAVE_MODIFF >= MODIFF
d427b66a
JB
968 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
969 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
970 call1 (intern ("ask-user-about-supersession-threat"),
971 current_buffer->filename);
972#endif /* not CLASH_DETECTION */
973
d206af14 974 signal_before_change (start, end, preserve_ptr);
2f545eea 975
56e1065e
JB
976 if (current_buffer->newline_cache)
977 invalidate_region_cache (current_buffer,
978 current_buffer->newline_cache,
979 start - BEG, Z - end);
980 if (current_buffer->width_run_cache)
981 invalidate_region_cache (current_buffer,
982 current_buffer->width_run_cache,
983 start - BEG, Z - end);
984
2f545eea 985 Vdeactivate_mark = Qt;
b45433b3
JB
986}
987\f
d206af14
RS
988/* These macros work with an argument named `preserve_ptr'
989 and a local variable named `preserve_marker'. */
990
991#define PRESERVE_VALUE \
992 if (preserve_ptr && NILP (preserve_marker)) \
993 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
994
995#define RESTORE_VALUE \
996 if (! NILP (preserve_marker)) \
997 { \
998 *preserve_ptr = marker_position (preserve_marker); \
999 unchain_marker (preserve_marker); \
1000 }
1001
eb8c3be9 1002/* Signal a change to the buffer immediately before it happens.
d206af14
RS
1003 START_INT and END_INT are the bounds of the text to be changed.
1004
1005 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1006 by holding its value temporarily in a marker. */
b45433b3 1007
c660b094 1008void
d206af14 1009signal_before_change (start_int, end_int, preserve_ptr)
6022d493 1010 int start_int, end_int;
d206af14 1011 int *preserve_ptr;
b45433b3 1012{
fb4ee5cd 1013 Lisp_Object start, end;
d206af14
RS
1014 Lisp_Object preserve_marker;
1015 struct gcpro gcpro1;
fb4ee5cd
RS
1016
1017 start = make_number (start_int);
1018 end = make_number (end_int);
d206af14
RS
1019 preserve_marker = Qnil;
1020 GCPRO1 (preserve_marker);
fb4ee5cd 1021
b45433b3 1022 /* If buffer is unmodified, run a special hook for that case. */
9fbf87cd 1023 if (SAVE_MODIFF >= MODIFF
dbc4e1c1
JB
1024 && !NILP (Vfirst_change_hook)
1025 && !NILP (Vrun_hooks))
d206af14
RS
1026 {
1027 PRESERVE_VALUE;
1028 call1 (Vrun_hooks, Qfirst_change_hook);
1029 }
dbc4e1c1 1030
3d1e2d9c
RS
1031 /* Run the before-change-function if any.
1032 We don't bother "binding" this variable to nil
1033 because it is obsolete anyway and new code should not use it. */
d427b66a 1034 if (!NILP (Vbefore_change_function))
d206af14
RS
1035 {
1036 PRESERVE_VALUE;
1037 call2 (Vbefore_change_function, start, end);
1038 }
e45fb8bf 1039
3d1e2d9c 1040 /* Now run the before-change-functions if any. */
e45fb8bf
RS
1041 if (!NILP (Vbefore_change_functions))
1042 {
3d1e2d9c
RS
1043 Lisp_Object args[3];
1044 Lisp_Object before_change_functions;
1045 Lisp_Object after_change_functions;
1046 struct gcpro gcpro1, gcpro2;
1047
d206af14
RS
1048 PRESERVE_VALUE;
1049
3d1e2d9c
RS
1050 /* "Bind" before-change-functions and after-change-functions
1051 to nil--but in a way that errors don't know about.
1052 That way, if there's an error in them, they will stay nil. */
1053 before_change_functions = Vbefore_change_functions;
1054 after_change_functions = Vafter_change_functions;
c82c1da0
KH
1055 Vbefore_change_functions = Qnil;
1056 Vafter_change_functions = Qnil;
3d1e2d9c
RS
1057 GCPRO2 (before_change_functions, after_change_functions);
1058
1059 /* Actually run the hook functions. */
1060 args[0] = Qbefore_change_functions;
1061 args[1] = start;
1062 args[2] = end;
1063 run_hook_list_with_args (before_change_functions, 3, args);
1064
1065 /* "Unbind" the variables we "bound" to nil. */
1066 Vbefore_change_functions = before_change_functions;
1067 Vafter_change_functions = after_change_functions;
1068 UNGCPRO;
e45fb8bf 1069 }
d07c0804
RS
1070
1071 if (!NILP (current_buffer->overlays_before)
1072 || !NILP (current_buffer->overlays_after))
d206af14
RS
1073 {
1074 PRESERVE_VALUE;
1075 report_overlay_modification (start, end, 0, start, end, Qnil);
1076 }
1077
1078 RESTORE_VALUE;
1079 UNGCPRO;
b45433b3
JB
1080}
1081
eb8c3be9 1082/* Signal a change immediately after it happens.
b45433b3
JB
1083 POS is the address of the start of the changed text.
1084 LENDEL is the number of characters of the text before the change.
1085 (Not the whole buffer; just the part that was changed.)
8b09e5d0
RS
1086 LENINS is the number of characters in that part of the text
1087 after the change. */
b45433b3 1088
c660b094 1089void
b45433b3
JB
1090signal_after_change (pos, lendel, lenins)
1091 int pos, lendel, lenins;
1092{
fb2e7d14
RS
1093 /* If we are deferring calls to the after-change functions
1094 and there are no before-change functions,
1095 just record the args that we were going to use. */
1096 if (! NILP (Vcombine_after_change_calls)
1097 && NILP (Vbefore_change_function) && NILP (Vbefore_change_functions)
1098 && NILP (current_buffer->overlays_before)
1099 && NILP (current_buffer->overlays_after))
1100 {
1101 Lisp_Object elt;
1102
1103 if (!NILP (combine_after_change_list)
1104 && current_buffer != XBUFFER (combine_after_change_buffer))
1105 Fcombine_after_change_execute ();
1106
1107 elt = Fcons (make_number (pos - BEG),
1108 Fcons (make_number (Z - (pos - lendel + lenins)),
1109 Fcons (make_number (lenins - lendel), Qnil)));
1110 combine_after_change_list
1111 = Fcons (elt, combine_after_change_list);
1112 combine_after_change_buffer = Fcurrent_buffer ();
1113
1114 return;
1115 }
1116
1117 if (!NILP (combine_after_change_list))
1118 Fcombine_after_change_execute ();
1119
3d1e2d9c
RS
1120 /* Run the after-change-function if any.
1121 We don't bother "binding" this variable to nil
1122 because it is obsolete anyway and new code should not use it. */
d427b66a 1123 if (!NILP (Vafter_change_function))
3d1e2d9c
RS
1124 call3 (Vafter_change_function,
1125 make_number (pos), make_number (pos + lenins),
1126 make_number (lendel));
b45433b3 1127
e45fb8bf
RS
1128 if (!NILP (Vafter_change_functions))
1129 {
3d1e2d9c
RS
1130 Lisp_Object args[4];
1131 Lisp_Object before_change_functions;
1132 Lisp_Object after_change_functions;
1133 struct gcpro gcpro1, gcpro2;
1134
1135 /* "Bind" before-change-functions and after-change-functions
1136 to nil--but in a way that errors don't know about.
1137 That way, if there's an error in them, they will stay nil. */
1138 before_change_functions = Vbefore_change_functions;
1139 after_change_functions = Vafter_change_functions;
c82c1da0
KH
1140 Vbefore_change_functions = Qnil;
1141 Vafter_change_functions = Qnil;
3d1e2d9c
RS
1142 GCPRO2 (before_change_functions, after_change_functions);
1143
1144 /* Actually run the hook functions. */
1145 args[0] = Qafter_change_functions;
1146 XSETFASTINT (args[1], pos);
1147 XSETFASTINT (args[2], pos + lenins);
1148 XSETFASTINT (args[3], lendel);
1149 run_hook_list_with_args (after_change_functions,
1150 4, args);
1151
1152 /* "Unbind" the variables we "bound" to nil. */
1153 Vbefore_change_functions = before_change_functions;
1154 Vafter_change_functions = after_change_functions;
1155 UNGCPRO;
e45fb8bf 1156 }
d07c0804
RS
1157
1158 if (!NILP (current_buffer->overlays_before)
1159 || !NILP (current_buffer->overlays_after))
835220e8 1160 report_overlay_modification (make_number (pos),
8b09e5d0 1161 make_number (pos + lenins),
d07c0804
RS
1162 1,
1163 make_number (pos), make_number (pos + lenins),
1164 make_number (lendel));
c5ca0786
RS
1165
1166 /* After an insertion, call the text properties
1167 insert-behind-hooks or insert-in-front-hooks. */
1168 if (lendel == 0)
1169 report_interval_modification (pos, pos + lenins);
b45433b3 1170}
fb2e7d14
RS
1171
1172Lisp_Object
1173Fcombine_after_change_execute_1 (val)
1174 Lisp_Object val;
1175{
1176 Vcombine_after_change_calls = val;
1177 return val;
1178}
1179
1180DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
1181 Scombine_after_change_execute, 0, 0, 0,
1182 "This function is for use internally in `combine-after-change-calls'.")
1183 ()
1184{
1185 register Lisp_Object val;
1186 int count = specpdl_ptr - specpdl;
1187 int beg, end, change;
1188 int begpos, endpos;
1189 Lisp_Object tail;
1190
1191 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
1192
1193 Fset_buffer (combine_after_change_buffer);
1194
1195 /* # chars unchanged at beginning of buffer. */
1196 beg = Z - BEG;
1197 /* # chars unchanged at end of buffer. */
1198 end = beg;
1199 /* Total amount of insertion (negative for deletion). */
1200 change = 0;
1201
1202 /* Scan the various individual changes,
1203 accumulating the range info in BEG, END and CHANGE. */
1204 for (tail = combine_after_change_list; CONSP (tail);
1205 tail = XCONS (tail)->cdr)
1206 {
e688a080
KH
1207 Lisp_Object elt;
1208 int thisbeg, thisend, thischange;
fb2e7d14
RS
1209
1210 /* Extract the info from the next element. */
1211 elt = XCONS (tail)->car;
1212 if (! CONSP (elt))
1213 continue;
1214 thisbeg = XINT (XCONS (elt)->car);
1215
1216 elt = XCONS (elt)->cdr;
1217 if (! CONSP (elt))
1218 continue;
1219 thisend = XINT (XCONS (elt)->car);
1220
1221 elt = XCONS (elt)->cdr;
1222 if (! CONSP (elt))
1223 continue;
1224 thischange = XINT (XCONS (elt)->car);
1225
1226 /* Merge this range into the accumulated range. */
1227 change += thischange;
1228 if (thisbeg < beg)
1229 beg = thisbeg;
1230 if (thisend < end)
1231 end = thisend;
1232 }
1233
1234 /* Get the current start and end positions of the range
1235 that was changed. */
1236 begpos = BEG + beg;
1237 endpos = Z - end;
1238
1239 /* We are about to handle these, so discard them. */
1240 combine_after_change_list = Qnil;
1241
1242 /* Now run the after-change functions for real.
1243 Turn off the flag that defers them. */
1244 record_unwind_protect (Fcombine_after_change_execute_1,
1245 Vcombine_after_change_calls);
1246 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
1247
1248 return unbind_to (count, val);
1249}
1250\f
1251syms_of_insdel ()
1252{
1253 staticpro (&combine_after_change_list);
1254 combine_after_change_list = Qnil;
1255
1256 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
1257 "Used internally by the `combine-after-change-calls' macro.");
1258 Vcombine_after_change_calls = Qnil;
1259
1260 defsubr (&Scombine_after_change_execute);
1261}