(signal_before_change): If inhibit_modification_hooks
[bpt/emacs.git] / src / insdel.c
CommitLineData
b45433b3 1/* Buffer insertion/deletion and gap motion for GNU Emacs.
4a2f9c6a 2 Copyright (C) 1985, 86, 93, 94, 95, 97, 1998 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"
dfcf069d 29#include "region-cache.h"
b45433b3 30
d206af14
RS
31#ifndef NULL
32#define NULL 0
33#endif
34
14f6194b
RS
35#define min(x, y) ((x) < (y) ? (x) : (y))
36
2b083808 37static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int, int));
ef29f213 38static void insert_from_buffer_1 ();
3be11131
RS
39static void gap_left P_ ((int, int, int));
40static void gap_right P_ ((int, int));
41static void adjust_markers_gap_motion P_ ((int, int, int));
432f78d2 42static void adjust_markers_for_insert P_ ((int, int, int, int, int, int, int));
3be11131 43static void adjust_markers_for_delete P_ ((int, int, int, int));
7cc3983f 44static void adjust_markers_for_record_delete P_ ((int, int, int, int));
3be11131 45static void adjust_point P_ ((int, int));
395ec62e 46
fb2e7d14
RS
47Lisp_Object Fcombine_after_change_execute ();
48
49/* Non-nil means don't call the after-change-functions right away,
50 just record an element in Vcombine_after_change_calls_list. */
51Lisp_Object Vcombine_after_change_calls;
52
53/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
54 describing changes which happened while combine_after_change_calls
55 was nonzero. We use this to decide how to call them
56 once the deferral ends.
57
58 In each element.
59 BEG-UNCHANGED is the number of chars before the changed range.
60 END-UNCHANGED is the number of chars after the changed range,
61 and CHANGE-AMOUNT is the number of characters inserted by the change
62 (negative for a deletion). */
63Lisp_Object combine_after_change_list;
64
65/* Buffer which combine_after_change_list is about. */
66Lisp_Object combine_after_change_buffer;
2b083808 67\f
60ea6052
RS
68/* Check all markers in the current buffer, looking for something invalid. */
69
70static int check_markers_debug_flag;
71
72#define CHECK_MARKERS() \
73 if (check_markers_debug_flag) \
74 check_markers (); \
75 else
76
77void
78check_markers ()
79{
80 register Lisp_Object tail, prev, next;
81
82 tail = BUF_MARKERS (current_buffer);
83
84 while (XSYMBOL (tail) != XSYMBOL (Qnil))
85 {
86 if (XMARKER (tail)->buffer->text != current_buffer->text)
87 abort ();
88 if (XMARKER (tail)->charpos > Z)
89 abort ();
90 if (XMARKER (tail)->bytepos > Z_BYTE)
91 abort ();
92
93 tail = XMARKER (tail)->chain;
94 }
95}
96\f
3be11131 97/* Move gap to position CHARPOS.
b45433b3
JB
98 Note that this can quit! */
99
c660b094 100void
3be11131
RS
101move_gap (charpos)
102 int charpos;
b45433b3 103{
3be11131 104 move_gap_both (charpos, charpos_to_bytepos (charpos));
b45433b3
JB
105}
106
3be11131
RS
107/* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
108 Note that this can quit! */
109
110void
111move_gap_both (charpos, bytepos)
112 int charpos, bytepos;
113{
114 if (bytepos < GPT_BYTE)
115 gap_left (charpos, bytepos, 0);
116 else if (bytepos > GPT_BYTE)
117 gap_right (charpos, bytepos);
118}
119
120/* Move the gap to a position less than the current GPT.
121 BYTEPOS describes the new position as a byte position,
122 and CHARPOS is the corresponding char position.
b45433b3
JB
123 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
124
2bcaed71 125static void
3be11131
RS
126gap_left (charpos, bytepos, newgap)
127 register int charpos, bytepos;
b45433b3
JB
128 int newgap;
129{
130 register unsigned char *to, *from;
131 register int i;
132 int new_s1;
133
b45433b3
JB
134 if (!newgap)
135 {
894ab630
RS
136 if (unchanged_modified == MODIFF
137 && overlay_unchanged_modified == OVERLAY_MODIFF)
b45433b3 138 {
3be11131
RS
139 beg_unchanged = charpos - BEG;
140 end_unchanged = Z - charpos;
b45433b3
JB
141 }
142 else
143 {
144 if (Z - GPT < end_unchanged)
145 end_unchanged = Z - GPT;
3be11131
RS
146 if (charpos < beg_unchanged)
147 beg_unchanged = charpos - BEG;
b45433b3
JB
148 }
149 }
150
3be11131 151 i = GPT_BYTE;
b45433b3
JB
152 to = GAP_END_ADDR;
153 from = GPT_ADDR;
3be11131 154 new_s1 = GPT_BYTE;
b45433b3
JB
155
156 /* Now copy the characters. To move the gap down,
157 copy characters up. */
158
159 while (1)
160 {
161 /* I gets number of characters left to copy. */
3be11131 162 i = new_s1 - bytepos;
b45433b3
JB
163 if (i == 0)
164 break;
165 /* If a quit is requested, stop copying now.
3be11131 166 Change BYTEPOS to be where we have actually moved the gap to. */
b45433b3
JB
167 if (QUITP)
168 {
3be11131
RS
169 bytepos = new_s1;
170 charpos = BYTE_TO_CHAR (bytepos);
b45433b3
JB
171 break;
172 }
173 /* Move at most 32000 chars before checking again for a quit. */
174 if (i > 32000)
175 i = 32000;
176#ifdef GAP_USE_BCOPY
177 if (i >= 128
178 /* bcopy is safe if the two areas of memory do not overlap
179 or on systems where bcopy is always safe for moving upward. */
180 && (BCOPY_UPWARD_SAFE
181 || to - from >= 128))
182 {
183 /* If overlap is not safe, avoid it by not moving too many
184 characters at once. */
185 if (!BCOPY_UPWARD_SAFE && i > to - from)
186 i = to - from;
187 new_s1 -= i;
188 from -= i, to -= i;
189 bcopy (from, to, i);
190 }
191 else
192#endif
193 {
194 new_s1 -= i;
195 while (--i >= 0)
196 *--to = *--from;
197 }
198 }
199
3be11131
RS
200 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
201 BYTEPOS is where the loop above stopped, which may be what was specified
b45433b3 202 or may be where a quit was detected. */
3be11131
RS
203 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
204 GPT_BYTE = bytepos;
205 GPT = charpos;
206 if (bytepos < charpos)
207 abort ();
469ff680 208 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
209 QUIT;
210}
211
3be11131
RS
212/* Move the gap to a position greater than than the current GPT.
213 BYTEPOS describes the new position as a byte position,
214 and CHARPOS is the corresponding char position. */
215
2bcaed71 216static void
3be11131
RS
217gap_right (charpos, bytepos)
218 register int charpos, bytepos;
b45433b3
JB
219{
220 register unsigned char *to, *from;
221 register int i;
222 int new_s1;
223
894ab630
RS
224 if (unchanged_modified == MODIFF
225 && overlay_unchanged_modified == OVERLAY_MODIFF)
b45433b3 226 {
3be11131
RS
227 beg_unchanged = charpos - BEG;
228 end_unchanged = Z - charpos;
b45433b3
JB
229 }
230 else
231 {
3be11131
RS
232 if (Z - charpos - 1 < end_unchanged)
233 end_unchanged = Z - charpos;
b45433b3
JB
234 if (GPT - BEG < beg_unchanged)
235 beg_unchanged = GPT - BEG;
236 }
237
3be11131 238 i = GPT_BYTE;
b45433b3
JB
239 from = GAP_END_ADDR;
240 to = GPT_ADDR;
3be11131 241 new_s1 = GPT_BYTE;
b45433b3
JB
242
243 /* Now copy the characters. To move the gap up,
244 copy characters down. */
245
246 while (1)
247 {
248 /* I gets number of characters left to copy. */
3be11131 249 i = bytepos - new_s1;
b45433b3
JB
250 if (i == 0)
251 break;
252 /* If a quit is requested, stop copying now.
3be11131 253 Change BYTEPOS to be where we have actually moved the gap to. */
b45433b3
JB
254 if (QUITP)
255 {
3be11131
RS
256 bytepos = new_s1;
257 charpos = BYTE_TO_CHAR (bytepos);
b45433b3
JB
258 break;
259 }
260 /* Move at most 32000 chars before checking again for a quit. */
261 if (i > 32000)
262 i = 32000;
263#ifdef GAP_USE_BCOPY
264 if (i >= 128
265 /* bcopy is safe if the two areas of memory do not overlap
266 or on systems where bcopy is always safe for moving downward. */
267 && (BCOPY_DOWNWARD_SAFE
268 || from - to >= 128))
269 {
270 /* If overlap is not safe, avoid it by not moving too many
271 characters at once. */
272 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
273 i = from - to;
274 new_s1 += i;
275 bcopy (from, to, i);
276 from += i, to += i;
277 }
278 else
279#endif
280 {
281 new_s1 += i;
282 while (--i >= 0)
283 *to++ = *from++;
284 }
285 }
286
3be11131
RS
287 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
288 - GAP_SIZE);
289 GPT = charpos;
290 GPT_BYTE = bytepos;
291 if (bytepos < charpos)
292 abort ();
469ff680 293 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
294 QUIT;
295}
2b083808 296\f
3be11131
RS
297/* Add AMOUNT to the byte position of every marker in the current buffer
298 whose current byte position is between FROM (exclusive) and TO (inclusive).
8948d317 299
b45433b3
JB
300 Also, any markers past the outside of that interval, in the direction
301 of adjustment, are first moved back to the near end of the interval
8948d317
RS
302 and then adjusted by AMOUNT.
303
304 When the latter adjustment is done, if AMOUNT is negative,
305 we record the adjustment for undo. (This case happens only for
3be11131
RS
306 deletion.)
307
308 The markers' character positions are not altered,
309 because gap motion does not affect character positions. */
310
311int adjust_markers_test;
b45433b3 312
2bcaed71 313static void
3be11131 314adjust_markers_gap_motion (from, to, amount)
b45433b3
JB
315 register int from, to, amount;
316{
80f6e77c
RS
317 /* Now that a marker has a bytepos, not counting the gap,
318 nothing needs to be done here. */
319#if 0
b45433b3
JB
320 Lisp_Object marker;
321 register struct Lisp_Marker *m;
322 register int mpos;
323
9fbf87cd 324 marker = BUF_MARKERS (current_buffer);
b45433b3 325
d427b66a 326 while (!NILP (marker))
b45433b3
JB
327 {
328 m = XMARKER (marker);
80f6e77c 329 mpos = m->bytepos;
b45433b3
JB
330 if (amount > 0)
331 {
332 if (mpos > to && mpos < to + amount)
3be11131
RS
333 {
334 if (adjust_markers_test)
335 abort ();
336 mpos = to + amount;
337 }
b45433b3
JB
338 }
339 else
340 {
8948d317
RS
341 /* Here's the case where a marker is inside text being deleted.
342 AMOUNT can be negative for gap motion, too,
343 but then this range contains no markers. */
b45433b3 344 if (mpos > from + amount && mpos <= from)
8948d317 345 {
3be11131
RS
346 if (adjust_markers_test)
347 abort ();
348 mpos = from + amount;
8948d317 349 }
b45433b3
JB
350 }
351 if (mpos > from && mpos <= to)
352 mpos += amount;
353 m->bufpos = mpos;
354 marker = m->chain;
355 }
80f6e77c 356#endif
b45433b3 357}
2b083808 358\f
3be11131
RS
359/* Adjust all markers for a deletion
360 whose range in bytes is FROM_BYTE to TO_BYTE.
361 The range in charpos is FROM to TO.
362
363 This function assumes that the gap is adjacent to
364 or inside of the range being deleted. */
beecb55b
RS
365
366static void
3be11131
RS
367adjust_markers_for_delete (from, from_byte, to, to_byte)
368 register int from, from_byte, to, to_byte;
369{
370 Lisp_Object marker;
371 register struct Lisp_Marker *m;
372 register int charpos;
3be11131
RS
373
374 marker = BUF_MARKERS (current_buffer);
375
376 while (!NILP (marker))
377 {
378 m = XMARKER (marker);
379 charpos = m->charpos;
380
381 if (charpos > Z)
382 abort ();
383
384 /* If the marker is after the deletion,
80f6e77c 385 relocate by number of chars / bytes deleted. */
3be11131 386 if (charpos > to)
80f6e77c
RS
387 {
388 m->charpos -= to - from;
389 m->bytepos -= to_byte - from_byte;
390 }
3be11131 391
80f6e77c 392 /* Here's the case where a marker is inside text being deleted. */
3be11131
RS
393 else if (charpos > from)
394 {
395 record_marker_adjustment (marker, from - charpos);
396 m->charpos = from;
80f6e77c 397 m->bytepos = from_byte;
3be11131
RS
398 }
399
3be11131
RS
400 marker = m->chain;
401 }
402}
23b20a70
KH
403
404/* Adjust all markers for a byte combining of NBYTES at char position
405 FROM and byte position FROM_BYTE. */
406
407static void
408adjust_markers_for_combining (from, from_byte, nbytes)
409 register int from, from_byte, nbytes;
410{
411 Lisp_Object marker;
412 register struct Lisp_Marker *m;
413 register int bytepos;
414 register int to_byte = from_byte + nbytes;
415
416 marker = BUF_MARKERS (current_buffer);
417
418 while (!NILP (marker))
419 {
420 m = XMARKER (marker);
421 bytepos = m->bytepos;
422
423 if (bytepos >= to_byte)
424 {
425 record_marker_adjustment (marker, - nbytes);
426 m->charpos -= nbytes;
427 }
428 else if (bytepos > from_byte)
429 {
430 record_marker_adjustment (marker, from - m->charpos);
431 m->charpos = from;
432 m->bytepos = to_byte;
433 }
434 else if (bytepos == from_byte)
435 {
436 m->bytepos = to_byte;
437 }
438
439 marker = m->chain;
440 }
441}
2b083808 442\f
7cc3983f
RS
443/* Adjust all markers for calling record_delete for combining bytes.
444 whose range in bytes is FROM_BYTE to TO_BYTE.
445 The range in charpos is FROM to TO. */
446
447static void
448adjust_markers_for_record_delete (from, from_byte, to, to_byte)
449 register int from, from_byte, to, to_byte;
450{
451 Lisp_Object marker;
452 register struct Lisp_Marker *m;
453 register int charpos;
454
455 marker = BUF_MARKERS (current_buffer);
456
457 while (!NILP (marker))
458 {
459 m = XMARKER (marker);
460 charpos = m->charpos;
461
462 /* If the marker is after the deletion,
463 relocate by number of chars / bytes deleted. */
464 if (charpos > to)
465 ;
466 /* Here's the case where a marker is inside text being deleted. */
467 else if (charpos > from)
468 record_marker_adjustment (marker, from - charpos);
469
470 marker = m->chain;
471 }
472}
473\f
432f78d2
RS
474/* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
475 to TO / TO_BYTE. We have to relocate the charpos of every marker
476 that points after the insertion (but not their bytepos).
3be11131 477
ce97a2d7
RS
478 COMBINED_BEFORE_BYTES is the number of bytes at the start of the insertion
479 that combine into one character with the text before the insertion.
432f78d2 480 COMBINED_AFTER_BYTES is the number of bytes after the insertion
ce97a2d7 481 that combine into one character with the last inserted bytes.
3be11131
RS
482
483 When a marker points at the insertion point,
484 we advance it if either its insertion-type is t
485 or BEFORE_MARKERS is true. */
486
487static void
432f78d2
RS
488adjust_markers_for_insert (from, from_byte, to, to_byte,
489 combined_before_bytes, combined_after_bytes,
490 before_markers)
491 register int from, from_byte, to, to_byte;
492 int combined_before_bytes, combined_after_bytes, before_markers;
beecb55b
RS
493{
494 Lisp_Object marker;
469ff680 495 int adjusted = 0;
3be11131
RS
496 int nchars = to - from;
497 int nbytes = to_byte - from_byte;
beecb55b
RS
498
499 marker = BUF_MARKERS (current_buffer);
500
501 while (!NILP (marker))
502 {
503 register struct Lisp_Marker *m = XMARKER (marker);
1f90a790
RS
504
505 /* In a single-byte buffer, a marker's two positions must be equal.
506 (If this insertion is going to combine characters, Z will
507 become different from Z_BYTE, but they might be the same now.
508 If so, the two OLD positions of the marker should be equal.) */
509 if (Z == Z_BYTE)
510 {
511 if (m->charpos != m->bytepos)
512 abort ();
513 }
514
432f78d2 515 if (m->bytepos == from_byte)
469ff680 516 {
432f78d2
RS
517 if (m->insertion_type || before_markers)
518 {
519 m->bytepos += nbytes + combined_after_bytes;
520 m->charpos += nchars + !!combined_after_bytes;
521 /* Point the marker before the combined character,
522 so that undoing the insertion puts it back where it was. */
523 if (combined_after_bytes)
524 DEC_BOTH (m->charpos, m->bytepos);
525 if (m->insertion_type)
526 adjusted = 1;
527 }
528 else if (combined_before_bytes)
529 {
530 /* This marker doesn't "need relocation",
531 but don't leave it pointing in the middle of a character.
532 Point the marker after the combined character,
533 so that undoing the insertion puts it back where it was. */
ce97a2d7
RS
534
535 /* Here we depend on the fact that the gap is after
536 all of the combining bytes that we are going to skip over. */
537 DEC_BOTH (m->charpos, m->bytepos);
432f78d2
RS
538 INC_BOTH (m->charpos, m->bytepos);
539 }
469ff680 540 }
ce97a2d7
RS
541 /* If a marker was pointing into the combining bytes
542 after the insertion, don't leave it there
543 in the middle of a character. */
544 else if (combined_after_bytes && m->bytepos >= from_byte
545 && m->bytepos < from_byte + combined_after_bytes)
546 {
547 /* Put it after the combining bytes. */
548 m->bytepos = to_byte + combined_after_bytes;
549 m->charpos = to + 1;
550 /* Now move it back before the combined character,
551 so that undoing the insertion will put it where it was. */
552 DEC_BOTH (m->charpos, m->bytepos);
553 }
80f6e77c
RS
554 else if (m->bytepos > from_byte)
555 {
556 m->bytepos += nbytes;
557 m->charpos += nchars;
558 }
3be11131 559
beecb55b
RS
560 marker = m->chain;
561 }
3be11131
RS
562
563 /* Adjusting only markers whose insertion-type is t may result in
564 disordered overlays in the slot `overlays_before'. */
469ff680 565 if (adjusted)
3be11131 566 fix_overlays_before (current_buffer, from, to);
beecb55b
RS
567}
568
3be11131
RS
569/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
570
571 This is used only when the value of point changes due to an insert
572 or delete; it does not represent a conceptual change in point as a
573 marker. In particular, point is not crossing any interval
574 boundaries, so there's no need to use the usual SET_PT macro. In
575 fact it would be incorrect to do so, because either the old or the
576 new value of point is out of sync with the current set of
577 intervals. */
578
a27a38d8 579static void
3be11131
RS
580adjust_point (nchars, nbytes)
581 int nchars, nbytes;
a27a38d8 582{
3be11131
RS
583 BUF_PT (current_buffer) += nchars;
584 BUF_PT_BYTE (current_buffer) += nbytes;
585
586 /* In a single-byte buffer, the two positions must be equal. */
587 if (ZV == ZV_BYTE
588 && PT != PT_BYTE)
589 abort ();
a27a38d8 590}
b45433b3 591\f
652838b5
KH
592/* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
593 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
594 (NEW_BYTES).
595
596 See the comment of adjust_markers_for_insert for the args
597 COMBINED_BEFORE_BYTES and COMBINED_AFTER_BYTES. */
598
599static void
600adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
601 new_chars, new_bytes,
602 combined_before_bytes, combined_after_bytes)
603 int from, from_byte, old_chars, old_bytes, new_chars, new_bytes;
604 int combined_before_bytes, combined_after_bytes;
605{
606 Lisp_Object marker = BUF_MARKERS (current_buffer);
607 int prev_to_byte = from_byte + old_bytes;
608 int diff_chars = new_chars - old_chars;
609 int diff_bytes = new_bytes - old_bytes;
610
611 while (!NILP (marker))
612 {
613 register struct Lisp_Marker *m = XMARKER (marker);
614
615 if (m->bytepos >= prev_to_byte)
616 {
617 if (m->bytepos < prev_to_byte + combined_after_bytes)
618 {
619 /* Put it after the combining bytes. */
620 m->bytepos = from_byte + new_bytes;
621 m->charpos = from + new_chars;
622 }
623 else
624 {
625 m->charpos += diff_chars;
626 m->bytepos += diff_bytes;
627 }
628 if (m->charpos == from + new_chars)
629 record_marker_adjustment (marker, - old_chars);
630 }
631 else if (m->bytepos > from_byte)
632 {
633 record_marker_adjustment (marker, from - m->charpos);
634 m->charpos = from;
635 m->bytepos = from_byte;
636 }
652838b5
KH
637
638 marker = m->chain;
639 }
640}
641
642\f
3be11131 643/* Make the gap NBYTES_ADDED bytes longer. */
b45433b3 644
c660b094 645void
3be11131
RS
646make_gap (nbytes_added)
647 int nbytes_added;
b45433b3
JB
648{
649 unsigned char *result;
650 Lisp_Object tem;
651 int real_gap_loc;
3be11131 652 int real_gap_loc_byte;
b45433b3
JB
653 int old_gap_size;
654
655 /* If we have to get more space, get enough to last a while. */
3be11131 656 nbytes_added += 2000;
b45433b3 657
94056516
RS
658 /* Don't allow a buffer size that won't fit in an int
659 even if it will fit in a Lisp integer.
660 That won't work because so many places use `int'. */
661
3be11131 662 if (Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added
68be917d 663 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
14f6194b 664 error ("Buffer exceeds maximum size");
94056516 665
9ac0d9e0 666 BLOCK_INPUT;
469ff680 667 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
3be11131
RS
668 result = BUFFER_REALLOC (BEG_ADDR, (Z_BYTE - BEG_BYTE
669 + GAP_SIZE + nbytes_added + 1));
9ac0d9e0 670
b45433b3 671 if (result == 0)
270c2138
RS
672 {
673 UNBLOCK_INPUT;
674 memory_full ();
675 }
676
677 /* We can't unblock until the new address is properly stored. */
b45433b3 678 BEG_ADDR = result;
270c2138 679 UNBLOCK_INPUT;
b45433b3
JB
680
681 /* Prevent quitting in move_gap. */
682 tem = Vinhibit_quit;
683 Vinhibit_quit = Qt;
684
685 real_gap_loc = GPT;
3be11131 686 real_gap_loc_byte = GPT_BYTE;
b45433b3
JB
687 old_gap_size = GAP_SIZE;
688
689 /* Call the newly allocated space a gap at the end of the whole space. */
690 GPT = Z + GAP_SIZE;
7d92db58 691 GPT_BYTE = Z_BYTE + GAP_SIZE;
3be11131 692 GAP_SIZE = nbytes_added;
b45433b3
JB
693
694 /* Move the new gap down to be consecutive with the end of the old one.
695 This adjusts the markers properly too. */
3be11131 696 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
b45433b3
JB
697
698 /* Now combine the two into one large gap. */
699 GAP_SIZE += old_gap_size;
700 GPT = real_gap_loc;
3be11131 701 GPT_BYTE = real_gap_loc_byte;
b45433b3 702
469ff680
KH
703 /* Put an anchor. */
704 *(Z_ADDR) = 0;
705
b45433b3
JB
706 Vinhibit_quit = tem;
707}
708\f
2b083808
RS
709/* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
710 FROM_MULTIBYTE says whether the incoming text is multibyte.
711 TO_MULTIBYTE says whether to store the text as multibyte.
712 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
713
714 Return the number of bytes stored at TO_ADDR. */
715
716int
717copy_text (from_addr, to_addr, nbytes,
718 from_multibyte, to_multibyte)
719 unsigned char *from_addr;
720 unsigned char *to_addr;
721 int nbytes;
722 int from_multibyte, to_multibyte;
723{
724 if (from_multibyte == to_multibyte)
725 {
726 bcopy (from_addr, to_addr, nbytes);
727 return nbytes;
728 }
729 else if (from_multibyte)
730 {
731 int nchars = 0;
732 int bytes_left = nbytes;
f44cbcd8
KH
733 Lisp_Object tbl = Qnil, temp;
734
735 /* We set the variable tbl to the reverse table of
736 Vnonascii_translation_table in advance. */
737 if (CHAR_TABLE_P (Vnonascii_translation_table))
738 {
739 tbl = Fchar_table_extra_slot (Vnonascii_translation_table,
740 make_number (0));
741 if (!CHAR_TABLE_P (tbl))
742 tbl = Qnil;
743 }
2b083808
RS
744
745 /* Convert multibyte to single byte. */
746 while (bytes_left > 0)
747 {
f44cbcd8
KH
748 int thislen, c, c_save;
749 c = c_save = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen);
750 if (!SINGLE_BYTE_CHAR_P (c))
4ec36780 751 c = multibyte_char_to_unibyte (c, tbl);
f44cbcd8 752 *to_addr++ = c;
2b083808 753 from_addr += thislen;
7e79b8e0 754 bytes_left -= thislen;
2b083808
RS
755 nchars++;
756 }
757 return nchars;
758 }
759 else
760 {
761 unsigned char *initial_to_addr = to_addr;
762
763 /* Convert single-byte to multibyte. */
764 while (nbytes > 0)
765 {
766 int c = *from_addr++;
767 unsigned char workbuf[4], *str;
768 int len;
769
3b080018 770 if ((c >= 0240 || !NILP (Vnonascii_translation_table)) && c < 0400)
2b083808 771 {
59a52d50 772 c = unibyte_char_to_multibyte (c);
2b083808
RS
773 len = CHAR_STRING (c, workbuf, str);
774 bcopy (str, to_addr, len);
775 to_addr += len;
776 nbytes--;
777 }
778 else
779 /* Special case for speed. */
780 *to_addr++ = c, nbytes--;
781 }
782 return to_addr - initial_to_addr;
783 }
784}
785
786/* Return the number of bytes it would take
787 to convert some single-byte text to multibyte.
788 The single-byte text consists of NBYTES bytes at PTR. */
789
790int
791count_size_as_multibyte (ptr, nbytes)
792 unsigned char *ptr;
793 int nbytes;
794{
795 int i;
796 int outgoing_nbytes = 0;
797
798 for (i = 0; i < nbytes; i++)
799 {
800 unsigned int c = *ptr++;
59a52d50 801
3b080018 802 if (c < 0240 && NILP (Vnonascii_translation_table))
59a52d50
KH
803 outgoing_nbytes++;
804 else
2b083808 805 {
59a52d50 806 c = unibyte_char_to_multibyte (c);
643044eb 807 outgoing_nbytes += CHAR_BYTES (c);
2b083808 808 }
2b083808
RS
809 }
810
811 return outgoing_nbytes;
812}
813\f
b45433b3 814/* Insert a string of specified length before point.
2b083808
RS
815 This function judges multibyteness based on
816 enable_multibyte_characters in the current buffer;
817 it never converts between single-byte and multibyte.
818
ef29f213
KH
819 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
820 prepare_to_modify_buffer could relocate the text. */
b45433b3 821
c660b094 822void
3be11131 823insert (string, nbytes)
b45433b3 824 register unsigned char *string;
dfcf069d 825 register int nbytes;
b45433b3 826{
3be11131 827 if (nbytes > 0)
395ec62e 828 {
3be11131
RS
829 int opoint = PT;
830 insert_1 (string, nbytes, 0, 1, 0);
831 signal_after_change (opoint, 0, PT - opoint);
cd11ef31
RS
832 }
833}
834
2b083808
RS
835/* Likewise, but inherit text properties from neighboring characters. */
836
c660b094 837void
3be11131 838insert_and_inherit (string, nbytes)
cd11ef31 839 register unsigned char *string;
dfcf069d 840 register int nbytes;
cd11ef31 841{
3be11131 842 if (nbytes > 0)
cd11ef31 843 {
3be11131
RS
844 int opoint = PT;
845 insert_1 (string, nbytes, 1, 1, 0);
846 signal_after_change (opoint, 0, PT - opoint);
395ec62e
KH
847 }
848}
b45433b3 849
2b083808 850/* Insert the character C before point. Do not inherit text properties. */
3be11131 851
c660b094 852void
3be11131
RS
853insert_char (c)
854 int c;
855{
856 unsigned char workbuf[4], *str;
2b083808
RS
857 int len;
858
859 if (! NILP (current_buffer->enable_multibyte_characters))
860 len = CHAR_STRING (c, workbuf, str);
861 else
862 {
863 len = 1;
864 workbuf[0] = c;
865 str = workbuf;
866 }
3be11131
RS
867
868 insert (str, len);
869}
870
2b083808 871/* Insert the null-terminated string S before point. */
3be11131
RS
872
873void
874insert_string (s)
875 char *s;
876{
877 insert (s, strlen (s));
878}
879
880/* Like `insert' except that all markers pointing at the place where
881 the insertion happens are adjusted to point after it.
882 Don't use this function to insert part of a Lisp string,
883 since gc could happen and relocate it. */
884
885void
886insert_before_markers (string, nbytes)
887 unsigned char *string;
888 register int nbytes;
889{
890 if (nbytes > 0)
891 {
892 int opoint = PT;
893
894 insert_1 (string, nbytes, 0, 1, 1);
895 signal_after_change (opoint, 0, PT - opoint);
896 }
897}
898
2b083808
RS
899/* Likewise, but inherit text properties from neighboring characters. */
900
3be11131
RS
901void
902insert_before_markers_and_inherit (string, nbytes)
903 unsigned char *string;
904 register int nbytes;
905{
906 if (nbytes > 0)
907 {
908 int opoint = PT;
909
910 insert_1 (string, nbytes, 1, 1, 1);
911 signal_after_change (opoint, 0, PT - opoint);
912 }
913}
1f90a790 914
3be11131
RS
915/* Subroutine used by the insert functions above. */
916
917void
918insert_1 (string, nbytes, inherit, prepare, before_markers)
395ec62e 919 register unsigned char *string;
3be11131
RS
920 register int nbytes;
921 int inherit, prepare, before_markers;
395ec62e 922{
432f78d2
RS
923 insert_1_both (string, chars_in_text (string, nbytes), nbytes,
924 inherit, prepare, before_markers);
925}
1f90a790 926\f
432f78d2
RS
927/* See if the bytes before POS/POS_BYTE combine with bytes
928 at the start of STRING to form a single character.
ce97a2d7 929 If so, return the number of bytes at the start of STRING
432f78d2 930 which combine in this way. Otherwise, return 0. */
b45433b3 931
432f78d2
RS
932int
933count_combining_before (string, length, pos, pos_byte)
934 unsigned char *string;
935 int length;
936 int pos, pos_byte;
937{
938 int opos = pos, opos_byte = pos_byte;
939 int c;
ce97a2d7 940 unsigned char *p = string;
b45433b3 941
432f78d2
RS
942 if (NILP (current_buffer->enable_multibyte_characters))
943 return 0;
944 if (length == 0 || CHAR_HEAD_P (*string))
945 return 0;
946 if (pos == BEGV)
947 return 0;
948 c = FETCH_BYTE (pos_byte - 1);
949 if (ASCII_BYTE_P (c))
950 return 0;
951 DEC_BOTH (pos, pos_byte);
952 c = FETCH_BYTE (pos_byte);
953 if (! BASE_LEADING_CODE_P (c))
954 return 0;
ce97a2d7
RS
955
956 /* We have a combination situation.
957 Count the bytes at STRING that will combine. */
958 while (!CHAR_HEAD_P (*p) && p < string + length)
959 p++;
960
961 return p - string;
432f78d2 962}
b45433b3 963
432f78d2
RS
964/* See if the bytes after POS/POS_BYTE combine with bytes
965 at the end of STRING to form a single character.
966 If so, return the number of bytes after POS/POS_BYTE
967 which combine in this way. Otherwise, return 0. */
679194a6 968
432f78d2
RS
969int
970count_combining_after (string, length, pos, pos_byte)
971 unsigned char *string;
972 int length;
973 int pos, pos_byte;
974{
975 int opos = pos, opos_byte = pos_byte;
976 int i;
977 int c;
3be11131 978
432f78d2
RS
979 if (NILP (current_buffer->enable_multibyte_characters))
980 return 0;
981 if (length == 0 || ASCII_BYTE_P (string[length - 1]))
982 return 0;
983 i = length - 1;
b57a7b0b 984 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
432f78d2
RS
985 {
986 i--;
987 }
b57a7b0b
KH
988 if (i < 0)
989 {
990 /* All characters in `string' are not character head.
991 We must check also preceding bytes at POS.
992 We are sure that the gap is at POS. */
993 string = BEG_ADDR;
994 i = pos_byte - 2;
995 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
996 i--;
997 if (i < 0 || !BASE_LEADING_CODE_P (string[i]))
998 return 0;
999 }
1000 else if (!BASE_LEADING_CODE_P (string[i]))
432f78d2
RS
1001 return 0;
1002
1003 if (pos == ZV)
1004 return 0;
1005 c = FETCH_BYTE (pos_byte);
1006 if (CHAR_HEAD_P (c))
1007 return 0;
1008 while (pos_byte < ZV_BYTE)
1009 {
1010 c = FETCH_BYTE (pos_byte);
1011 if (CHAR_HEAD_P (c))
1012 break;
1013 pos_byte++;
1014 }
cd11ef31 1015
432f78d2 1016 return pos_byte - opos_byte;
b45433b3 1017}
2b083808 1018
e3a87305
KH
1019/* Adjust the position TARGET/TARGET_BYTE for the combining of NBYTES
1020 following the position POS/POS_BYTE to the character preceding POS.
1021 If TARGET is after POS+NBYTES, we only have to adjust the character
1022 position TARGET, else, if TARGET is after POS, we have to adjust
1023 both the character position TARGET and the byte position
1024 TARGET_BYTE, else we don't have to do any adjustment. */
1025
1026#define ADJUST_CHAR_POS(target, target_byte) \
1027 do { \
1028 if (target > pos + nbytes) \
1029 target -= nbytes; \
1030 else if (target >= pos) \
1031 { \
1032 target = pos; \
1033 target_byte = pos_byte + nbytes; \
1034 } \
1035 } while (0)
1036
1f90a790
RS
1037/* Combine NBYTES stray trailing-codes, which were formerly separate
1038 characters, with the preceding character. These bytes
1039 are located after position POS / POS_BYTE, and the preceding character
1040 is located just before that position. */
1041
1042static void
1043combine_bytes (pos, pos_byte, nbytes)
1044 int pos, pos_byte, nbytes;
1045{
1046 /* Adjust all markers. */
23b20a70 1047 adjust_markers_for_combining (pos, pos_byte, nbytes);
1f90a790
RS
1048
1049 adjust_overlays_for_delete (pos, nbytes);
1050
e3a87305
KH
1051 ADJUST_CHAR_POS (BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
1052 ADJUST_CHAR_POS (GPT, GPT_BYTE);
1053 ADJUST_CHAR_POS (Z, Z_BYTE);
1054 ADJUST_CHAR_POS (ZV, ZV_BYTE);
1f90a790
RS
1055
1056 if (BUF_INTERVALS (current_buffer) != 0)
1057 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
1058 offset_intervals (current_buffer, pos, - nbytes);
60ea6052
RS
1059
1060 CHECK_MARKERS ();
1f90a790
RS
1061}
1062\f
2b083808
RS
1063/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1064 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
1065 are the same as in insert_1. */
1066
1067void
1068insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
1069 register unsigned char *string;
1070 register int nchars, nbytes;
1071 int inherit, prepare, before_markers;
1072{
0aa8c4b2 1073 register Lisp_Object temp;
432f78d2 1074 int combined_before_bytes, combined_after_bytes;
2b083808 1075
57404188
KH
1076 if (NILP (current_buffer->enable_multibyte_characters))
1077 nchars = nbytes;
1078
35d63725
RS
1079 if (prepare)
1080 /* Do this before moving and increasing the gap,
1081 because the before-change hooks might move the gap
1082 or make it smaller. */
1083 prepare_to_modify_buffer (PT, PT, NULL);
1084
2b083808
RS
1085 if (PT != GPT)
1086 move_gap_both (PT, PT_BYTE);
1087 if (GAP_SIZE < nbytes)
1088 make_gap (nbytes - GAP_SIZE);
1089
1f90a790
RS
1090 combined_before_bytes
1091 = count_combining_before (string, nbytes, PT, PT_BYTE);
1092 combined_after_bytes
1093 = count_combining_after (string, nbytes, PT, PT_BYTE);
432f78d2
RS
1094
1095 /* Record deletion of the surrounding text that combines with
1096 the insertion. This, together with recording the insertion,
1097 will add up to the right stuff in the undo list.
1098
1099 But there is no need to actually delete the combining bytes
1100 from the buffer and reinsert them. */
1101
1102 if (combined_after_bytes)
7cc3983f 1103 {
0aa8c4b2
RS
1104 Lisp_Object deletion;
1105 deletion = Qnil;
1106
1107 if (! EQ (current_buffer->undo_list, Qt))
1108 deletion = make_buffer_string_both (PT, PT_BYTE,
1109 PT + combined_after_bytes,
1110 PT_BYTE + combined_after_bytes, 1);
628cea90 1111
7cc3983f
RS
1112 adjust_markers_for_record_delete (PT, PT_BYTE,
1113 PT + combined_after_bytes,
1114 PT_BYTE + combined_after_bytes);
0aa8c4b2
RS
1115 if (! EQ (current_buffer->undo_list, Qt))
1116 record_delete (PT, deletion);
7cc3983f 1117 }
432f78d2
RS
1118
1119 if (combined_before_bytes)
7cc3983f 1120 {
0aa8c4b2
RS
1121 Lisp_Object deletion;
1122 deletion = Qnil;
1123
1124 if (! EQ (current_buffer->undo_list, Qt))
1125 deletion = make_buffer_string_both (PT - 1, CHAR_TO_BYTE (PT - 1),
1126 PT, PT_BYTE, 1);
7cc3983f
RS
1127 adjust_markers_for_record_delete (PT - 1, CHAR_TO_BYTE (PT - 1),
1128 PT, PT_BYTE);
0aa8c4b2
RS
1129 if (! EQ (current_buffer->undo_list, Qt))
1130 record_delete (PT - 1, deletion);
7cc3983f 1131 }
432f78d2 1132
e0c0ed58
RS
1133 record_insert (PT - !!combined_before_bytes,
1134 nchars - combined_before_bytes + !!combined_before_bytes);
2b083808
RS
1135 MODIFF++;
1136
1137 bcopy (string, GPT_ADDR, nbytes);
1138
2b083808 1139 GAP_SIZE -= nbytes;
ce97a2d7
RS
1140 /* When we have combining at the end of the insertion,
1141 this is the character position before the combined character. */
1f90a790
RS
1142 GPT += nchars;
1143 ZV += nchars;
1144 Z += nchars;
2b083808
RS
1145 GPT_BYTE += nbytes;
1146 ZV_BYTE += nbytes;
1147 Z_BYTE += nbytes;
1148 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1f90a790
RS
1149
1150 if (combined_after_bytes)
1151 move_gap_both (GPT + combined_after_bytes,
1152 GPT_BYTE + combined_after_bytes);
1153
1154 if (GPT_BYTE < GPT)
1155 abort ();
1156
1157 adjust_overlays_for_insert (PT, nchars);
432f78d2 1158 adjust_markers_for_insert (PT, PT_BYTE,
1f90a790 1159 PT + nchars, PT_BYTE + nbytes,
432f78d2 1160 combined_before_bytes, combined_after_bytes,
2b083808 1161 before_markers);
ce97a2d7 1162
ce97a2d7 1163#ifdef USE_TEXT_PROPERTIES
1f90a790
RS
1164 if (BUF_INTERVALS (current_buffer) != 0)
1165 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
1166 offset_intervals (current_buffer, PT, nchars);
1167
ce97a2d7 1168 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
1f90a790 1169 Fset_text_properties (make_number (PT), make_number (PT + nchars),
ce97a2d7
RS
1170 Qnil, Qnil);
1171#endif
1172
1f90a790
RS
1173 {
1174 int pos = PT, pos_byte = PT_BYTE;
432f78d2 1175
1f90a790
RS
1176 adjust_point (nchars + combined_after_bytes,
1177 nbytes + combined_after_bytes);
2b083808 1178
1f90a790
RS
1179 if (combined_after_bytes)
1180 combine_bytes (pos + nchars, pos_byte + nbytes, combined_after_bytes);
1181
1182 if (combined_before_bytes)
1183 combine_bytes (pos, pos_byte, combined_before_bytes);
1184 }
2b083808 1185}
3be11131 1186\f
679194a6 1187/* Insert the part of the text of STRING, a Lisp object assumed to be
2b083808
RS
1188 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
1189 starting at position POS / POS_BYTE. If the text of STRING has properties,
1190 copy them into the buffer.
679194a6
JA
1191
1192 It does not work to use `insert' for this, because a GC could happen
7e1ea612
JB
1193 before we bcopy the stuff into the buffer, and relocate the string
1194 without insert noticing. */
679194a6 1195
c660b094 1196void
2b083808 1197insert_from_string (string, pos, pos_byte, length, length_byte, inherit)
b45433b3 1198 Lisp_Object string;
2b083808 1199 register int pos, pos_byte, length, length_byte;
9391e591 1200 int inherit;
395ec62e 1201{
62b82678
RS
1202 int opoint = PT;
1203 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
1204 inherit, 0);
1205 signal_after_change (opoint, 0, PT - opoint);
395ec62e
KH
1206}
1207
2b083808
RS
1208/* Like `insert_from_string' except that all markers pointing
1209 at the place where the insertion happens are adjusted to point after it. */
3be11131
RS
1210
1211void
2b083808
RS
1212insert_from_string_before_markers (string, pos, pos_byte,
1213 length, length_byte, inherit)
395ec62e 1214 Lisp_Object string;
2b083808 1215 register int pos, pos_byte, length, length_byte;
395ec62e 1216 int inherit;
3be11131 1217{
62b82678
RS
1218 int opoint = PT;
1219 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
1220 inherit, 1);
1221 signal_after_change (opoint, 0, PT - opoint);
3be11131
RS
1222}
1223
1224/* Subroutine of the insertion functions above. */
1225
1226static void
2b083808
RS
1227insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
1228 inherit, before_markers)
3be11131 1229 Lisp_Object string;
2b083808 1230 register int pos, pos_byte, nchars, nbytes;
3be11131 1231 int inherit, before_markers;
b45433b3
JB
1232{
1233 register Lisp_Object temp;
1234 struct gcpro gcpro1;
2b083808 1235 int outgoing_nbytes = nbytes;
432f78d2
RS
1236 int combined_before_bytes, combined_after_bytes;
1237 int adjusted_nchars;
ce97a2d7 1238 INTERVAL intervals;
2b083808
RS
1239
1240 /* Make OUTGOING_NBYTES describe the text
1241 as it will be inserted in this buffer. */
1242
1243 if (NILP (current_buffer->enable_multibyte_characters))
1244 outgoing_nbytes = nchars;
2a1d8be0 1245 else if (! STRING_MULTIBYTE (string))
2b083808
RS
1246 outgoing_nbytes
1247 = count_size_as_multibyte (&XSTRING (string)->data[pos_byte],
1248 nbytes);
b45433b3 1249
b45433b3 1250 GCPRO1 (string);
35d63725
RS
1251 /* Do this before moving and increasing the gap,
1252 because the before-change hooks might move the gap
1253 or make it smaller. */
d206af14 1254 prepare_to_modify_buffer (PT, PT, NULL);
b45433b3 1255
2bcaed71 1256 if (PT != GPT)
3be11131
RS
1257 move_gap_both (PT, PT_BYTE);
1258 if (GAP_SIZE < nbytes)
2b083808 1259 make_gap (outgoing_nbytes - GAP_SIZE);
b45433b3
JB
1260 UNGCPRO;
1261
2b083808
RS
1262 /* Copy the string text into the buffer, perhaps converting
1263 between single-byte and multibyte. */
1264 copy_text (XSTRING (string)->data + pos_byte, GPT_ADDR, nbytes,
2a1d8be0 1265 STRING_MULTIBYTE (string),
2b083808 1266 ! NILP (current_buffer->enable_multibyte_characters));
b45433b3 1267
432f78d2
RS
1268 /* We have copied text into the gap, but we have not altered
1269 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1270 to these functions and get the same results as we would
1271 have got earlier on. Meanwhile, PT_ADDR does point to
1272 the text that has been stored by copy_text. */
1273
1274 combined_before_bytes
1f90a790 1275 = count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE);
432f78d2 1276 combined_after_bytes
1f90a790 1277 = count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE);
432f78d2
RS
1278
1279 /* Record deletion of the surrounding text that combines with
1280 the insertion. This, together with recording the insertion,
1281 will add up to the right stuff in the undo list.
1282
1283 But there is no need to actually delete the combining bytes
1284 from the buffer and reinsert them. */
1285
1286 if (combined_after_bytes)
7cc3983f 1287 {
0aa8c4b2
RS
1288 Lisp_Object deletion;
1289 deletion = Qnil;
1290
1291 if (! EQ (current_buffer->undo_list, Qt))
1292 deletion = make_buffer_string_both (PT, PT_BYTE,
1293 PT + combined_after_bytes,
1294 PT_BYTE + combined_after_bytes, 1);
628cea90 1295
7cc3983f
RS
1296 adjust_markers_for_record_delete (PT, PT_BYTE,
1297 PT + combined_after_bytes,
1298 PT_BYTE + combined_after_bytes);
0aa8c4b2
RS
1299 if (! EQ (current_buffer->undo_list, Qt))
1300 record_delete (PT, deletion);
7cc3983f 1301 }
432f78d2
RS
1302
1303 if (combined_before_bytes)
7cc3983f 1304 {
0aa8c4b2
RS
1305 Lisp_Object deletion;
1306 deletion = Qnil;
1307
1308 if (! EQ (current_buffer->undo_list, Qt))
1309 deletion = make_buffer_string_both (PT - 1, CHAR_TO_BYTE (PT - 1),
1310 PT, PT_BYTE, 1);
7cc3983f
RS
1311 adjust_markers_for_record_delete (PT - 1, CHAR_TO_BYTE (PT - 1),
1312 PT, PT_BYTE);
0aa8c4b2
RS
1313 if (! EQ (current_buffer->undo_list, Qt))
1314 record_delete (PT - 1, deletion);
7cc3983f 1315 }
432f78d2 1316
e0c0ed58
RS
1317 record_insert (PT - !!combined_before_bytes,
1318 nchars - combined_before_bytes + !!combined_before_bytes);
432f78d2
RS
1319 MODIFF++;
1320
7792090e 1321 GAP_SIZE -= outgoing_nbytes;
1f90a790
RS
1322 GPT += nchars;
1323 ZV += nchars;
1324 Z += nchars;
2b083808
RS
1325 GPT_BYTE += outgoing_nbytes;
1326 ZV_BYTE += outgoing_nbytes;
1327 Z_BYTE += outgoing_nbytes;
469ff680 1328 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
3be11131 1329
432f78d2 1330 if (combined_after_bytes)
1f90a790
RS
1331 move_gap_both (GPT + combined_after_bytes,
1332 GPT_BYTE + combined_after_bytes);
432f78d2 1333
3be11131
RS
1334 if (GPT_BYTE < GPT)
1335 abort ();
679194a6 1336
1f90a790
RS
1337 adjust_overlays_for_insert (PT, nchars);
1338 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1339 PT_BYTE + outgoing_nbytes,
1340 combined_before_bytes, combined_after_bytes,
1341 before_markers);
ce97a2d7 1342
1f90a790
RS
1343 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1344 offset_intervals (current_buffer, PT, nchars);
1345
1346 intervals = XSTRING (string)->intervals;
ce97a2d7
RS
1347 /* Get the intervals for the part of the string we are inserting--
1348 not including the combined-before bytes. */
fc932ac6 1349 if (nbytes < STRING_BYTES (XSTRING (string)))
1f90a790 1350 intervals = copy_intervals (intervals, pos, nchars);
ce97a2d7
RS
1351
1352 /* Insert those intervals. */
1f90a790 1353 graft_intervals_into_buffer (intervals, PT, nchars,
9391e591 1354 current_buffer, inherit);
ce97a2d7 1355
1f90a790
RS
1356 {
1357 int pos = PT, pos_byte = PT_BYTE;
1358
1359 adjust_point (nchars + combined_after_bytes,
1360 outgoing_nbytes + combined_after_bytes);
1361
1362 if (combined_after_bytes)
1363 combine_bytes (pos + nchars, pos_byte + outgoing_nbytes,
1364 combined_after_bytes);
1365
1366 if (combined_before_bytes)
1367 combine_bytes (pos, pos_byte, combined_before_bytes);
1368 }
b45433b3 1369}
3be11131
RS
1370\f
1371/* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
ef29f213
KH
1372 current buffer. If the text in BUF has properties, they are absorbed
1373 into the current buffer.
1374
1375 It does not work to use `insert' for this, because a malloc could happen
1376 and relocate BUF's text before the bcopy happens. */
1377
1378void
3be11131 1379insert_from_buffer (buf, charpos, nchars, inherit)
ef29f213 1380 struct buffer *buf;
3be11131 1381 int charpos, nchars;
ef29f213
KH
1382 int inherit;
1383{
62b82678 1384 int opoint = PT;
3be11131 1385
62b82678
RS
1386 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1387 signal_after_change (opoint, 0, PT - opoint);
ef29f213
KH
1388}
1389
1390static void
3be11131 1391insert_from_buffer_1 (buf, from, nchars, inherit)
ef29f213 1392 struct buffer *buf;
3be11131 1393 int from, nchars;
ef29f213
KH
1394 int inherit;
1395{
0aa8c4b2 1396 register Lisp_Object temp;
ef29f213 1397 int chunk;
3be11131
RS
1398 int from_byte = buf_charpos_to_bytepos (buf, from);
1399 int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
2b083808
RS
1400 int incoming_nbytes = to_byte - from_byte;
1401 int outgoing_nbytes = incoming_nbytes;
432f78d2
RS
1402 int combined_before_bytes, combined_after_bytes;
1403 int adjusted_nchars;
ce97a2d7 1404 INTERVAL intervals;
2b083808
RS
1405
1406 /* Make OUTGOING_NBYTES describe the text
1407 as it will be inserted in this buffer. */
1408
1409 if (NILP (current_buffer->enable_multibyte_characters))
1410 outgoing_nbytes = nchars;
1411 else if (NILP (buf->enable_multibyte_characters))
1412 outgoing_nbytes
1413 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1414 incoming_nbytes);
ef29f213
KH
1415
1416 /* Make sure point-max won't overflow after this insertion. */
2b083808
RS
1417 XSETINT (temp, outgoing_nbytes + Z);
1418 if (outgoing_nbytes + Z != XINT (temp))
3be11131 1419 error ("Maximum buffer size exceeded");
ef29f213 1420
35d63725
RS
1421 /* Do this before moving and increasing the gap,
1422 because the before-change hooks might move the gap
1423 or make it smaller. */
d206af14 1424 prepare_to_modify_buffer (PT, PT, NULL);
ef29f213
KH
1425
1426 if (PT != GPT)
3be11131 1427 move_gap_both (PT, PT_BYTE);
2b083808
RS
1428 if (GAP_SIZE < outgoing_nbytes)
1429 make_gap (outgoing_nbytes - GAP_SIZE);
ef29f213 1430
3be11131 1431 if (from < BUF_GPT (buf))
ef29f213 1432 {
3be11131 1433 chunk = BUF_GPT_BYTE (buf) - from_byte;
2b083808
RS
1434 if (chunk > incoming_nbytes)
1435 chunk = incoming_nbytes;
1436 copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1437 GPT_ADDR, chunk,
1438 ! NILP (buf->enable_multibyte_characters),
1439 ! NILP (current_buffer->enable_multibyte_characters));
ef29f213
KH
1440 }
1441 else
1442 chunk = 0;
2b083808
RS
1443 if (chunk < incoming_nbytes)
1444 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1445 GPT_ADDR + chunk, incoming_nbytes - chunk,
1446 ! NILP (buf->enable_multibyte_characters),
1447 ! NILP (current_buffer->enable_multibyte_characters));
ef29f213 1448
432f78d2
RS
1449 /* We have copied text into the gap, but we have not altered
1450 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1451 to these functions and get the same results as we would
1f90a790 1452 have got earlier on. Meanwhile, GPT_ADDR does point to
432f78d2
RS
1453 the text that has been stored by copy_text. */
1454 combined_before_bytes
1f90a790 1455 = count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE);
432f78d2 1456 combined_after_bytes
1f90a790 1457 = count_combining_after (GPT_ADDR, outgoing_nbytes,
432f78d2
RS
1458 PT, PT_BYTE);
1459
432f78d2
RS
1460 /* Record deletion of the surrounding text that combines with
1461 the insertion. This, together with recording the insertion,
1462 will add up to the right stuff in the undo list.
1463
1464 But there is no need to actually delete the combining bytes
1465 from the buffer and reinsert them. */
1466
1467 if (combined_after_bytes)
7cc3983f 1468 {
0aa8c4b2
RS
1469 Lisp_Object deletion;
1470 deletion = Qnil;
1471
1472 if (! EQ (current_buffer->undo_list, Qt))
1473 deletion = make_buffer_string_both (PT, PT_BYTE,
1474 PT + combined_after_bytes,
1475 PT_BYTE + combined_after_bytes, 1);
628cea90 1476
7cc3983f
RS
1477 adjust_markers_for_record_delete (PT, PT_BYTE,
1478 PT + combined_after_bytes,
1479 PT_BYTE + combined_after_bytes);
0aa8c4b2
RS
1480 if (! EQ (current_buffer->undo_list, Qt))
1481 record_delete (PT, deletion);
7cc3983f 1482 }
432f78d2
RS
1483
1484 if (combined_before_bytes)
7cc3983f 1485 {
0aa8c4b2
RS
1486 Lisp_Object deletion;
1487 deletion = Qnil;
1488
1489 if (! EQ (current_buffer->undo_list, Qt))
1490 deletion = make_buffer_string_both (PT - 1, CHAR_TO_BYTE (PT - 1),
1491 PT, PT_BYTE, 1);
7cc3983f
RS
1492 adjust_markers_for_record_delete (PT - 1, CHAR_TO_BYTE (PT - 1),
1493 PT, PT_BYTE);
0aa8c4b2
RS
1494 if (! EQ (current_buffer->undo_list, Qt))
1495 record_delete (PT - 1, deletion);
7cc3983f 1496 }
432f78d2 1497
e0c0ed58
RS
1498 record_insert (PT - !!combined_before_bytes,
1499 nchars - combined_before_bytes + !!combined_before_bytes);
432f78d2
RS
1500 MODIFF++;
1501
2b083808 1502 GAP_SIZE -= outgoing_nbytes;
1f90a790
RS
1503 GPT += nchars;
1504 ZV += nchars;
1505 Z += nchars;
2b083808
RS
1506 GPT_BYTE += outgoing_nbytes;
1507 ZV_BYTE += outgoing_nbytes;
1508 Z_BYTE += outgoing_nbytes;
469ff680 1509 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1f90a790
RS
1510
1511 if (combined_after_bytes)
1512 move_gap_both (GPT + combined_after_bytes,
1513 GPT_BYTE + combined_after_bytes);
1514
1515 if (GPT_BYTE < GPT)
1516 abort ();
1517
1518 adjust_overlays_for_insert (PT, nchars);
1519 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
432f78d2
RS
1520 PT_BYTE + outgoing_nbytes,
1521 combined_before_bytes, combined_after_bytes, 0);
ce97a2d7 1522
1f90a790
RS
1523#ifdef USE_TEXT_PROPERTIES
1524 if (BUF_INTERVALS (current_buffer) != 0)
1525 offset_intervals (current_buffer, PT, nchars);
1526#endif
ce97a2d7
RS
1527
1528 /* Get the intervals for the part of the string we are inserting--
1529 not including the combined-before bytes. */
1530 intervals = BUF_INTERVALS (buf);
1f90a790
RS
1531 if (outgoing_nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf))
1532 intervals = copy_intervals (intervals, from, nchars);
ce97a2d7
RS
1533
1534 /* Insert those intervals. */
1f90a790 1535 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
ce97a2d7 1536
1f90a790
RS
1537 {
1538 int pos = PT, pos_byte = PT_BYTE;
ce97a2d7 1539
1f90a790
RS
1540 adjust_point (nchars + combined_after_bytes,
1541 outgoing_nbytes + combined_after_bytes);
432f78d2 1542
1f90a790
RS
1543 if (combined_after_bytes)
1544 combine_bytes (pos + nchars, pos_byte + outgoing_nbytes,
1545 combined_after_bytes);
3be11131 1546
1f90a790
RS
1547 if (combined_before_bytes)
1548 combine_bytes (pos, pos_byte, combined_before_bytes);
1549 }
b45433b3
JB
1550}
1551\f
2d9eea44 1552/* This function should be called after moving gap to FROM and before
59a52d50
KH
1553 altering text between FROM and TO. This adjusts various position
1554 keepers and markers as if the text is deleted. Don't forget to
1555 call adjust_after_replace after you actually alter the text. */
2d9eea44 1556
1e9c7b7d
KH
1557void
1558adjust_before_replace (from, from_byte, to, to_byte)
1559 int from, from_byte, to, to_byte;
1560{
628cea90 1561 Lisp_Object deletion;
0aa8c4b2
RS
1562
1563 if (! EQ (current_buffer->undo_list, Qt))
1564 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
628cea90 1565
60ea6052
RS
1566 CHECK_MARKERS ();
1567
1e9c7b7d 1568 adjust_markers_for_delete (from, from_byte, to, to_byte);
0aa8c4b2
RS
1569
1570 if (! EQ (current_buffer->undo_list, Qt))
1571 record_delete (from, deletion);
1572
61415a25 1573 adjust_overlays_for_delete (from, to - from);
1e9c7b7d
KH
1574}
1575
652838b5
KH
1576/* Record undo information and adjust markers and position keepers for
1577 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1578 chars (LEN_BYTE bytes) which resides in the gap just after
1579 GPT_ADDR.
1580
1581 PREV_TEXT nil means the new text was just inserted. */
2d9eea44 1582
1e9c7b7d 1583void
652838b5
KH
1584adjust_after_replace (from, from_byte, prev_text, len, len_byte)
1585 int from, from_byte, len, len_byte;
1586 Lisp_Object prev_text;
1e9c7b7d 1587{
61415a25
KH
1588 int combined_before_bytes
1589 = count_combining_before (GPT_ADDR, len_byte, from, from_byte);
1590 int combined_after_bytes
1591 = count_combining_after (GPT_ADDR, len_byte, from, from_byte);
652838b5 1592 int nchars_del = 0, nbytes_del = 0;
61415a25
KH
1593
1594 if (combined_after_bytes)
7cc3983f 1595 {
0aa8c4b2
RS
1596 Lisp_Object deletion;
1597 deletion = Qnil;
1598
1599 if (! EQ (current_buffer->undo_list, Qt))
1600 deletion = make_buffer_string_both (from, from_byte,
1601 from + combined_after_bytes,
1602 from_byte + combined_after_bytes,
1603 1);
628cea90 1604
7cc3983f
RS
1605 adjust_markers_for_record_delete (from, from_byte,
1606 from + combined_after_bytes,
1607 from_byte + combined_after_bytes);
0aa8c4b2
RS
1608
1609 if (! EQ (current_buffer->undo_list, Qt))
23b20a70 1610 record_delete (from + len, deletion);
7cc3983f 1611 }
61415a25
KH
1612
1613 if (combined_before_bytes)
7cc3983f 1614 {
0aa8c4b2
RS
1615 Lisp_Object deletion;
1616 deletion = Qnil;
1617
1618 if (! EQ (current_buffer->undo_list, Qt))
1619 deletion = make_buffer_string_both (from - 1, CHAR_TO_BYTE (from - 1),
1620 from, from_byte, 1);
7cc3983f
RS
1621 adjust_markers_for_record_delete (from - 1, CHAR_TO_BYTE (from - 1),
1622 from, from_byte);
0aa8c4b2
RS
1623 if (! EQ (current_buffer->undo_list, Qt))
1624 record_delete (from - 1, deletion);
7cc3983f 1625 }
61415a25
KH
1626
1627 /* Update various buffer positions for the new text. */
1628 GAP_SIZE -= len_byte;
1629 ZV += len; Z+= len;
1630 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1631 GPT += len; GPT_BYTE += len_byte;
1632 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1633
1634 if (combined_after_bytes)
1635 move_gap_both (GPT + combined_after_bytes,
1636 GPT_BYTE + combined_after_bytes);
1637
652838b5
KH
1638 if (STRINGP (prev_text))
1639 {
1640 nchars_del = XSTRING (prev_text)->size;
1641 nbytes_del = STRING_BYTES (XSTRING (prev_text));
1642 }
1643 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1644 len, len_byte,
1645 combined_before_bytes, combined_after_bytes);
1646 if (STRINGP (prev_text))
4a7cf15f 1647 record_delete (from - !!combined_before_bytes, prev_text);
e0c0ed58
RS
1648 record_insert (from - !!combined_before_bytes,
1649 len - combined_before_bytes + !!combined_before_bytes);
652838b5
KH
1650
1651 if (len > nchars_del)
1652 adjust_overlays_for_insert (from, len - nchars_del);
1653 else if (len < nchars_del)
1654 adjust_overlays_for_delete (from, nchars_del - len);
61415a25
KH
1655#ifdef USE_TEXT_PROPERTIES
1656 if (BUF_INTERVALS (current_buffer) != 0)
4a7cf15f
KH
1657 {
1658 offset_intervals (current_buffer, from, len - nchars_del);
4a7cf15f 1659 }
61415a25
KH
1660#endif
1661
1662 {
1663 int pos = PT, pos_byte = PT_BYTE;
1664
1665 if (from < PT)
8bedbe9d 1666 adjust_point (len - nchars_del, len_byte - nbytes_del);
61415a25
KH
1667
1668 if (combined_after_bytes)
8bedbe9d
KH
1669 {
1670 if (combined_before_bytes)
1671 combined_before_bytes += combined_after_bytes;
1672 else
1673 combine_bytes (from + len, from_byte + len_byte,
1674 combined_after_bytes);
1675 }
61415a25
KH
1676
1677 if (combined_before_bytes)
1678 combine_bytes (from, from_byte, combined_before_bytes);
1679 }
1680
60ea6052
RS
1681 CHECK_MARKERS ();
1682
1e9c7b7d
KH
1683 if (len == 0)
1684 evaporate_overlays (from);
1685 MODIFF++;
1e9c7b7d
KH
1686}
1687
652838b5
KH
1688/* Record undo information, adjust markers and position keepers for an
1689 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1690 text already exists in the current buffer but character length (TO
1691 - FROM) may be incorrect, the correct length is NEWLEN. */
1692
1693void
1694adjust_after_insert (from, from_byte, to, to_byte, newlen)
1695 int from, from_byte, to, to_byte, newlen;
1696{
1697 int len = to - from, len_byte = to_byte - from_byte;
1698
1699 if (GPT != to)
1700 move_gap_both (to, to_byte);
1701 GAP_SIZE += len_byte;
1702 GPT -= len; GPT_BYTE -= len_byte;
1703 ZV -= len; ZV_BYTE -= len_byte;
1704 Z -= len; Z_BYTE -= len_byte;
1705 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1706}
1707
3be11131 1708/* Replace the text from character positions FROM to TO with NEW,
c5ca4d3a
RS
1709 If PREPARE is nonzero, call prepare_to_modify_buffer.
1710 If INHERIT, the newly inserted text should inherit text properties
1711 from the surrounding non-deleted text. */
1712
1713/* Note that this does not yet handle markers quite right.
1714 Also it needs to record a single undo-entry that does a replacement
1715 rather than a separate delete and insert.
60aa777a
RS
1716 That way, undo will also handle markers properly.
1717
1718 But if MARKERS is 0, don't relocate markers. */
c5ca4d3a
RS
1719
1720void
60aa777a 1721replace_range (from, to, new, prepare, inherit, markers)
c5ca4d3a 1722 Lisp_Object new;
60aa777a 1723 int from, to, prepare, inherit, markers;
c5ca4d3a 1724{
2b083808 1725 int inschars = XSTRING (new)->size;
fc932ac6 1726 int insbytes = STRING_BYTES (XSTRING (new));
3be11131
RS
1727 int from_byte, to_byte;
1728 int nbytes_del, nchars_del;
c5ca4d3a
RS
1729 register Lisp_Object temp;
1730 struct gcpro gcpro1;
432f78d2
RS
1731 int combined_before_bytes, combined_after_bytes;
1732 int adjusted_inschars;
ce97a2d7 1733 INTERVAL intervals;
1f90a790 1734 int outgoing_insbytes = insbytes;
23b20a70 1735 Lisp_Object deletion;
c5ca4d3a 1736
60ea6052
RS
1737 CHECK_MARKERS ();
1738
c5ca4d3a
RS
1739 GCPRO1 (new);
1740
1741 if (prepare)
1742 {
1743 int range_length = to - from;
1744 prepare_to_modify_buffer (from, to, &from);
1745 to = from + range_length;
1746 }
1747
3be11131
RS
1748 UNGCPRO;
1749
c5ca4d3a
RS
1750 /* Make args be valid */
1751 if (from < BEGV)
1752 from = BEGV;
1753 if (to > ZV)
1754 to = ZV;
1755
3be11131
RS
1756 from_byte = CHAR_TO_BYTE (from);
1757 to_byte = CHAR_TO_BYTE (to);
c5ca4d3a 1758
3be11131
RS
1759 nchars_del = to - from;
1760 nbytes_del = to_byte - from_byte;
1761
1762 if (nbytes_del <= 0 && insbytes == 0)
1763 return;
c5ca4d3a 1764
1f90a790
RS
1765 /* Make OUTGOING_INSBYTES describe the text
1766 as it will be inserted in this buffer. */
1767
1768 if (NILP (current_buffer->enable_multibyte_characters))
1769 outgoing_insbytes = inschars;
2a1d8be0 1770 else if (! STRING_MULTIBYTE (new))
1f90a790
RS
1771 outgoing_insbytes
1772 = count_size_as_multibyte (XSTRING (new)->data, insbytes);
1773
c5ca4d3a 1774 /* Make sure point-max won't overflow after this insertion. */
3be11131
RS
1775 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1776 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1777 error ("Maximum buffer size exceeded");
c5ca4d3a 1778
c5ca4d3a
RS
1779 GCPRO1 (new);
1780
1781 /* Make sure the gap is somewhere in or next to what we are deleting. */
1782 if (from > GPT)
3be11131 1783 gap_right (from, from_byte);
c5ca4d3a 1784 if (to < GPT)
3be11131 1785 gap_left (to, to_byte, 0);
c5ca4d3a 1786
23b20a70 1787 deletion = Qnil;
628cea90 1788
23b20a70
KH
1789 if (! EQ (current_buffer->undo_list, Qt))
1790 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
c5ca4d3a 1791
23b20a70
KH
1792 if (markers)
1793 /* Relocate all markers pointing into the new, larger gap
1794 to point at the end of the text before the gap.
1795 Do this before recording the deletion,
1796 so that undo handles this after reinserting the text. */
1797 adjust_markers_for_delete (from, from_byte, to, to_byte);
c5ca4d3a 1798
3be11131
RS
1799 GAP_SIZE += nbytes_del;
1800 ZV -= nchars_del;
1801 Z -= nchars_del;
1802 ZV_BYTE -= nbytes_del;
1803 Z_BYTE -= nbytes_del;
c5ca4d3a 1804 GPT = from;
3be11131 1805 GPT_BYTE = from_byte;
c5ca4d3a
RS
1806 *(GPT_ADDR) = 0; /* Put an anchor. */
1807
3be11131
RS
1808 if (GPT_BYTE < GPT)
1809 abort ();
1810
c5ca4d3a
RS
1811 if (GPT - BEG < beg_unchanged)
1812 beg_unchanged = GPT - BEG;
1813 if (Z - GPT < end_unchanged)
1814 end_unchanged = Z - GPT;
1815
3be11131
RS
1816 if (GAP_SIZE < insbytes)
1817 make_gap (insbytes - GAP_SIZE);
c5ca4d3a 1818
1f90a790
RS
1819 /* Copy the string text into the buffer, perhaps converting
1820 between single-byte and multibyte. */
1821 copy_text (XSTRING (new)->data, GPT_ADDR, insbytes,
2a1d8be0 1822 STRING_MULTIBYTE (new),
1f90a790
RS
1823 ! NILP (current_buffer->enable_multibyte_characters));
1824
255c7dae
RS
1825 /* We have copied text into the gap, but we have not marked
1826 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1827 here, for both the previous text and the following text.
1828 Meanwhile, GPT_ADDR does point to
432f78d2
RS
1829 the text that has been stored by copy_text. */
1830
1831 combined_before_bytes
255c7dae 1832 = count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte);
432f78d2 1833 combined_after_bytes
255c7dae 1834 = count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte);
432f78d2
RS
1835
1836 /* Record deletion of the surrounding text that combines with
1837 the insertion. This, together with recording the insertion,
1838 will add up to the right stuff in the undo list.
1839
1840 But there is no need to actually delete the combining bytes
1841 from the buffer and reinsert them. */
1842
1843 if (combined_after_bytes)
7cc3983f 1844 {
0aa8c4b2
RS
1845 Lisp_Object deletion;
1846 deletion = Qnil;
1847
1848 if (! EQ (current_buffer->undo_list, Qt))
255c7dae
RS
1849 deletion = make_buffer_string_both (from, from_byte,
1850 from + combined_after_bytes,
1851 from_byte + combined_after_bytes, 1);
628cea90 1852
255c7dae
RS
1853 adjust_markers_for_record_delete (from, from_byte,
1854 from + combined_after_bytes,
1855 from_byte + combined_after_bytes);
0aa8c4b2 1856 if (! EQ (current_buffer->undo_list, Qt))
23b20a70 1857 record_delete (from + inschars, deletion);
7cc3983f 1858 }
432f78d2
RS
1859
1860 if (combined_before_bytes)
7cc3983f 1861 {
0aa8c4b2
RS
1862 Lisp_Object deletion;
1863 deletion = Qnil;
1864
1865 if (! EQ (current_buffer->undo_list, Qt))
255c7dae
RS
1866 deletion = make_buffer_string_both (from - 1, CHAR_TO_BYTE (from - 1),
1867 from, from_byte, 1);
1868 adjust_markers_for_record_delete (from - 1, CHAR_TO_BYTE (from - 1),
1869 from, from_byte);
0aa8c4b2 1870 if (! EQ (current_buffer->undo_list, Qt))
255c7dae 1871 record_delete (from - 1, deletion);
7cc3983f 1872 }
432f78d2 1873
23b20a70
KH
1874 if (! EQ (current_buffer->undo_list, Qt))
1875 {
1876 record_delete (from - !!combined_before_bytes, deletion);
1877 record_insert (from - !!combined_before_bytes,
1878 (inschars - combined_before_bytes
1879 + !!combined_before_bytes));
1880 }
c5ca4d3a 1881
1f90a790
RS
1882 GAP_SIZE -= outgoing_insbytes;
1883 GPT += inschars;
1884 ZV += inschars;
1885 Z += inschars;
1886 GPT_BYTE += outgoing_insbytes;
1887 ZV_BYTE += outgoing_insbytes;
1888 Z_BYTE += outgoing_insbytes;
c5ca4d3a
RS
1889 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1890
1f90a790
RS
1891 if (combined_after_bytes)
1892 move_gap_both (GPT + combined_after_bytes,
1893 GPT_BYTE + combined_after_bytes);
1894
3be11131
RS
1895 if (GPT_BYTE < GPT)
1896 abort ();
1897
c5ca4d3a
RS
1898 /* Adjust the overlay center as needed. This must be done after
1899 adjusting the markers that bound the overlays. */
3be11131 1900 adjust_overlays_for_delete (from, nchars_del);
1f90a790 1901 adjust_overlays_for_insert (from, inschars);
60aa777a 1902 if (markers)
2db5082f
RS
1903 adjust_markers_for_insert (from, from_byte,
1904 from + inschars, from_byte + outgoing_insbytes,
1905 combined_before_bytes, combined_after_bytes, 0);
c5ca4d3a 1906
1f90a790 1907#ifdef USE_TEXT_PROPERTIES
255c7dae 1908 offset_intervals (current_buffer, from, inschars - nchars_del);
ce97a2d7
RS
1909
1910 /* Get the intervals for the part of the string we are inserting--
1911 not including the combined-before bytes. */
1912 intervals = XSTRING (new)->intervals;
ce97a2d7 1913 /* Insert those intervals. */
1f90a790 1914 graft_intervals_into_buffer (intervals, from, inschars,
ce97a2d7 1915 current_buffer, inherit);
1f90a790 1916#endif
c5ca4d3a 1917
1f90a790
RS
1918 /* Relocate point as if it were a marker. */
1919 if (from < PT)
8bedbe9d 1920 adjust_point ((from + inschars - (PT < to ? PT : to)),
1f90a790 1921 (from_byte + outgoing_insbytes
8bedbe9d 1922 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
c5ca4d3a 1923
93b882e8 1924 if (combined_after_bytes)
8bedbe9d
KH
1925 {
1926 if (combined_before_bytes)
1927 combined_before_bytes += combined_after_bytes;
1928 else
1929 combine_bytes (from + inschars, from_byte + outgoing_insbytes,
1930 combined_after_bytes);
1931 }
1f90a790
RS
1932 if (combined_before_bytes)
1933 combine_bytes (from, from_byte, combined_before_bytes);
1934
1935 if (outgoing_insbytes == 0)
1936 evaporate_overlays (from);
93b882e8 1937
60ea6052
RS
1938 CHECK_MARKERS ();
1939
c5ca4d3a
RS
1940 MODIFF++;
1941 UNGCPRO;
1942
255c7dae 1943 signal_after_change (from, nchars_del, GPT - from);
c5ca4d3a
RS
1944}
1945\f
b45433b3 1946/* Delete characters in current buffer
3be11131
RS
1947 from FROM up to (but not including) TO.
1948 If TO comes before FROM, we delete nothing. */
b45433b3 1949
c660b094 1950void
b45433b3
JB
1951del_range (from, to)
1952 register int from, to;
47c64747 1953{
c660b094 1954 del_range_1 (from, to, 1);
47c64747
RS
1955}
1956
1957/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
1958
c660b094 1959void
47c64747 1960del_range_1 (from, to, prepare)
d206af14 1961 int from, to, prepare;
b45433b3 1962{
3be11131
RS
1963 int from_byte, to_byte;
1964
1965 /* Make args be valid */
1966 if (from < BEGV)
1967 from = BEGV;
1968 if (to > ZV)
1969 to = ZV;
1970
1971 if (to <= from)
1972 return;
1973
1974 if (prepare)
1975 {
1976 int range_length = to - from;
1977 prepare_to_modify_buffer (from, to, &from);
1978 to = from + range_length;
1979 }
1980
1981 from_byte = CHAR_TO_BYTE (from);
1982 to_byte = CHAR_TO_BYTE (to);
1983
a66afea0 1984 del_range_2 (from, from_byte, to, to_byte);
3be11131
RS
1985}
1986
1987/* Like del_range_1 but args are byte positions, not char positions. */
1988
1989void
1990del_range_byte (from_byte, to_byte, prepare)
1991 int from_byte, to_byte, prepare;
1992{
1993 int from, to;
1994
1995 /* Make args be valid */
1996 if (from_byte < BEGV_BYTE)
1997 from_byte = BEGV_BYTE;
1998 if (to_byte > ZV_BYTE)
1999 to_byte = ZV_BYTE;
2000
2001 if (to_byte <= from_byte)
2002 return;
2003
2004 from = BYTE_TO_CHAR (from_byte);
2005 to = BYTE_TO_CHAR (to_byte);
b45433b3 2006
d206af14
RS
2007 if (prepare)
2008 {
3be11131 2009 int old_from = from, old_to = Z - to;
d206af14
RS
2010 int range_length = to - from;
2011 prepare_to_modify_buffer (from, to, &from);
2012 to = from + range_length;
3be11131
RS
2013
2014 if (old_from != from)
2015 from_byte = CHAR_TO_BYTE (from);
2016 if (old_to == Z - to)
2017 to_byte = CHAR_TO_BYTE (to);
d206af14
RS
2018 }
2019
a66afea0 2020 del_range_2 (from, from_byte, to, to_byte);
3be11131
RS
2021}
2022
2023/* Like del_range_1, but positions are specified both as charpos
2024 and bytepos. */
2025
2026void
353800c7
KH
2027del_range_both (from, from_byte, to, to_byte, prepare)
2028 int from, from_byte, to, to_byte, prepare;
3be11131 2029{
b45433b3 2030 /* Make args be valid */
3be11131
RS
2031 if (from_byte < BEGV_BYTE)
2032 from_byte = BEGV_BYTE;
2033 if (to_byte > ZV_BYTE)
2034 to_byte = ZV_BYTE;
2035
2036 if (to_byte <= from_byte)
2037 return;
2038
b45433b3
JB
2039 if (from < BEGV)
2040 from = BEGV;
2041 if (to > ZV)
2042 to = ZV;
2043
3be11131
RS
2044 if (prepare)
2045 {
2046 int old_from = from, old_to = Z - to;
2047 int range_length = to - from;
2048 prepare_to_modify_buffer (from, to, &from);
2049 to = from + range_length;
2050
2051 if (old_from != from)
2052 from_byte = CHAR_TO_BYTE (from);
2053 if (old_to == Z - to)
2054 to_byte = CHAR_TO_BYTE (to);
2055 }
2056
a66afea0 2057 del_range_2 (from, from_byte, to, to_byte);
3be11131
RS
2058}
2059
2060/* Delete a range of text, specified both as character positions
2061 and byte positions. FROM and TO are character positions,
2062 while FROM_BYTE and TO_BYTE are byte positions. */
2063
2064void
a66afea0
KH
2065del_range_2 (from, from_byte, to, to_byte)
2066 int from, from_byte, to, to_byte;
3be11131
RS
2067{
2068 register int nbytes_del, nchars_del;
1f90a790 2069 int combined_after_bytes;
628cea90
RS
2070 Lisp_Object deletion;
2071 int from_byte_1;
3be11131 2072
60ea6052
RS
2073 CHECK_MARKERS ();
2074
3be11131
RS
2075 nchars_del = to - from;
2076 nbytes_del = to_byte - from_byte;
b45433b3
JB
2077
2078 /* Make sure the gap is somewhere in or next to what we are deleting. */
2079 if (from > GPT)
3be11131 2080 gap_right (from, from_byte);
b45433b3 2081 if (to < GPT)
3be11131 2082 gap_left (to, to_byte, 0);
b45433b3 2083
e0c0ed58 2084 combined_after_bytes
e3a87305
KH
2085 = count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
2086 ZV_BYTE - to_byte, from, from_byte);
628cea90
RS
2087 if (combined_after_bytes)
2088 {
2089 from_byte_1 = from_byte;
2090 DEC_POS (from_byte_1);
2091 }
2092 else
2093 from_byte_1 = from_byte;
2094
0aa8c4b2
RS
2095 if (! EQ (current_buffer->undo_list, Qt))
2096 deletion
2097 = make_buffer_string_both (from - !!combined_after_bytes,
2098 from_byte_1,
2099 to + combined_after_bytes,
2100 to_byte + combined_after_bytes, 1);
242beafe
KH
2101 if (combined_after_bytes)
2102 /* COMBINED_AFTER_BYTES nonzero means that the above code moved
2103 the gap. We must move the gap again to a proper place. */
2104 move_gap_both (from, from_byte);
e0c0ed58 2105
8948d317
RS
2106 /* Relocate all markers pointing into the new, larger gap
2107 to point at the end of the text before the gap.
3be11131
RS
2108 Do this before recording the deletion,
2109 so that undo handles this after reinserting the text. */
2110 adjust_markers_for_delete (from, from_byte, to, to_byte);
7cc3983f
RS
2111 if (combined_after_bytes)
2112 {
7cc3983f
RS
2113 /* Adjust markers for the phony deletion
2114 that we are about to call record_undo for. */
2115
2116 /* Here we delete the markers that formerly
2117 pointed at TO ... TO + COMBINED_AFTER_BYTES.
2118 But because of the call to adjust_markers_for_delete, above,
2119 they now point at FROM ... FROM + COMBINED_AFTER_BYTES. */
2120 adjust_markers_for_record_delete (from, from_byte,
2121 from + combined_after_bytes,
2122 from_byte + combined_after_bytes);
2123
2124 adjust_markers_for_record_delete (from - 1, from_byte_1,
2125 from, from_byte);
2126 }
0aa8c4b2
RS
2127 if (! EQ (current_buffer->undo_list, Qt))
2128 record_delete (from - !!combined_after_bytes, deletion);
be09561e
RS
2129 MODIFF++;
2130
b45433b3 2131 /* Relocate point as if it were a marker. */
2bcaed71 2132 if (from < PT)
3be11131
RS
2133 adjust_point (from - (PT < to ? PT : to),
2134 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
b45433b3 2135
16032db6 2136 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3be11131 2137 offset_intervals (current_buffer, from, - nchars_del);
16032db6 2138
adde4858 2139 /* Adjust the overlay center as needed. This must be done after
a7f38d28 2140 adjusting the markers that bound the overlays. */
e3a87305 2141 adjust_overlays_for_delete (from, nchars_del);
adde4858 2142
3be11131
RS
2143 GAP_SIZE += nbytes_del;
2144 ZV_BYTE -= nbytes_del;
2145 Z_BYTE -= nbytes_del;
2146 ZV -= nchars_del;
2147 Z -= nchars_del;
b45433b3 2148 GPT = from;
3be11131 2149 GPT_BYTE = from_byte;
b45433b3 2150
e0c0ed58
RS
2151 if (combined_after_bytes)
2152 move_gap_both (GPT + combined_after_bytes,
2153 GPT_BYTE + combined_after_bytes);
2154
e3a87305
KH
2155 *(GPT_ADDR) = 0; /* Put an anchor. */
2156
3be11131
RS
2157 if (GPT_BYTE < GPT)
2158 abort ();
2159
b45433b3
JB
2160 if (GPT - BEG < beg_unchanged)
2161 beg_unchanged = GPT - BEG;
2162 if (Z - GPT < end_unchanged)
2163 end_unchanged = Z - GPT;
2164
1f90a790 2165 if (combined_after_bytes)
7cc3983f
RS
2166 {
2167 combine_bytes (from, from_byte, combined_after_bytes);
1f90a790 2168
7cc3983f
RS
2169 record_insert (GPT - 1, 1);
2170 }
1f90a790 2171
60ea6052
RS
2172 CHECK_MARKERS ();
2173
d386034e 2174 evaporate_overlays (from);
3be11131 2175 signal_after_change (from, nchars_del, 0);
b45433b3
JB
2176}
2177\f
3be11131
RS
2178/* Call this if you're about to change the region of BUFFER from
2179 character positions START to END. This checks the read-only
2180 properties of the region, calls the necessary modification hooks,
2181 and warns the next redisplay that it should pay attention to that
2182 area. */
2183
c660b094 2184void
04a759c8
JB
2185modify_region (buffer, start, end)
2186 struct buffer *buffer;
b45433b3
JB
2187 int start, end;
2188{
04a759c8
JB
2189 struct buffer *old_buffer = current_buffer;
2190
2191 if (buffer != old_buffer)
2192 set_buffer_internal (buffer);
2193
d206af14 2194 prepare_to_modify_buffer (start, end, NULL);
b45433b3 2195
894ab630
RS
2196 if (start - 1 < beg_unchanged
2197 || (unchanged_modified == MODIFF
2198 && overlay_unchanged_modified == OVERLAY_MODIFF))
b45433b3
JB
2199 beg_unchanged = start - 1;
2200 if (Z - end < end_unchanged
894ab630
RS
2201 || (unchanged_modified == MODIFF
2202 && overlay_unchanged_modified == OVERLAY_MODIFF))
b45433b3 2203 end_unchanged = Z - end;
83010cd6 2204
9fbf87cd 2205 if (MODIFF <= SAVE_MODIFF)
83010cd6 2206 record_first_change ();
b45433b3 2207 MODIFF++;
04a759c8 2208
069cdc4f
RS
2209 buffer->point_before_scroll = Qnil;
2210
04a759c8
JB
2211 if (buffer != old_buffer)
2212 set_buffer_internal (old_buffer);
b45433b3 2213}
d206af14 2214\f
3be11131
RS
2215/* Check that it is okay to modify the buffer between START and END,
2216 which are char positions.
2217
679194a6
JA
2218 Run the before-change-function, if any. If intervals are in use,
2219 verify that the text to be modified is not read-only, and call
d206af14
RS
2220 any modification properties the text may have.
2221
2222 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2223 by holding its value temporarily in a marker. */
b45433b3 2224
c660b094 2225void
d206af14 2226prepare_to_modify_buffer (start, end, preserve_ptr)
fb4ee5cd 2227 int start, end;
d206af14 2228 int *preserve_ptr;
b45433b3 2229{
d427b66a 2230 if (!NILP (current_buffer->read_only))
b45433b3
JB
2231 Fbarf_if_buffer_read_only ();
2232
679194a6 2233 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd 2234 if (BUF_INTERVALS (current_buffer) != 0)
d206af14
RS
2235 {
2236 if (preserve_ptr)
2237 {
2238 Lisp_Object preserve_marker;
2239 struct gcpro gcpro1;
2240 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
2241 GCPRO1 (preserve_marker);
2242 verify_interval_modification (current_buffer, start, end);
2243 *preserve_ptr = marker_position (preserve_marker);
2244 unchain_marker (preserve_marker);
2245 UNGCPRO;
2246 }
2247 else
2248 verify_interval_modification (current_buffer, start, end);
2249 }
b45433b3
JB
2250
2251#ifdef CLASH_DETECTION
f173b650 2252 if (!NILP (current_buffer->file_truename)
ab6c5c0c
RS
2253 /* Make binding buffer-file-name to nil effective. */
2254 && !NILP (current_buffer->filename)
9fbf87cd 2255 && SAVE_MODIFF >= MODIFF)
f173b650 2256 lock_file (current_buffer->file_truename);
b45433b3
JB
2257#else
2258 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 2259 if (!NILP (current_buffer->filename)
9fbf87cd 2260 && SAVE_MODIFF >= MODIFF
d427b66a
JB
2261 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
2262 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
2263 call1 (intern ("ask-user-about-supersession-threat"),
2264 current_buffer->filename);
2265#endif /* not CLASH_DETECTION */
2266
d206af14 2267 signal_before_change (start, end, preserve_ptr);
2f545eea 2268
56e1065e
JB
2269 if (current_buffer->newline_cache)
2270 invalidate_region_cache (current_buffer,
2271 current_buffer->newline_cache,
2272 start - BEG, Z - end);
2273 if (current_buffer->width_run_cache)
2274 invalidate_region_cache (current_buffer,
2275 current_buffer->width_run_cache,
2276 start - BEG, Z - end);
2277
2f545eea 2278 Vdeactivate_mark = Qt;
b45433b3
JB
2279}
2280\f
d206af14
RS
2281/* These macros work with an argument named `preserve_ptr'
2282 and a local variable named `preserve_marker'. */
2283
2284#define PRESERVE_VALUE \
2285 if (preserve_ptr && NILP (preserve_marker)) \
2286 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2287
2288#define RESTORE_VALUE \
2289 if (! NILP (preserve_marker)) \
2290 { \
2291 *preserve_ptr = marker_position (preserve_marker); \
2292 unchain_marker (preserve_marker); \
2293 }
2294
b86e0aaf
RS
2295#define PRESERVE_START_END \
2296 if (NILP (start_marker)) \
2297 start_marker = Fcopy_marker (start, Qnil); \
2298 if (NILP (end_marker)) \
2299 end_marker = Fcopy_marker (end, Qnil);
2300
2301#define FETCH_START \
2302 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2303
2304#define FETCH_END \
2305 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2306
eb8c3be9 2307/* Signal a change to the buffer immediately before it happens.
d206af14
RS
2308 START_INT and END_INT are the bounds of the text to be changed.
2309
2310 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2311 by holding its value temporarily in a marker. */
b45433b3 2312
c660b094 2313void
d206af14 2314signal_before_change (start_int, end_int, preserve_ptr)
6022d493 2315 int start_int, end_int;
d206af14 2316 int *preserve_ptr;
b45433b3 2317{
fb4ee5cd 2318 Lisp_Object start, end;
b86e0aaf 2319 Lisp_Object start_marker, end_marker;
d206af14 2320 Lisp_Object preserve_marker;
b86e0aaf 2321 struct gcpro gcpro1, gcpro2, gcpro3;
fb4ee5cd 2322
fd16a4c6
KH
2323 if (inhibit_modification_hooks)
2324 return;
2325
fb4ee5cd
RS
2326 start = make_number (start_int);
2327 end = make_number (end_int);
d206af14 2328 preserve_marker = Qnil;
b86e0aaf
RS
2329 start_marker = Qnil;
2330 end_marker = Qnil;
2331 GCPRO3 (preserve_marker, start_marker, end_marker);
fb4ee5cd 2332
b45433b3 2333 /* If buffer is unmodified, run a special hook for that case. */
9fbf87cd 2334 if (SAVE_MODIFF >= MODIFF
dbc4e1c1
JB
2335 && !NILP (Vfirst_change_hook)
2336 && !NILP (Vrun_hooks))
d206af14
RS
2337 {
2338 PRESERVE_VALUE;
b86e0aaf 2339 PRESERVE_START_END;
d206af14
RS
2340 call1 (Vrun_hooks, Qfirst_change_hook);
2341 }
dbc4e1c1 2342
3d1e2d9c
RS
2343 /* Run the before-change-function if any.
2344 We don't bother "binding" this variable to nil
2345 because it is obsolete anyway and new code should not use it. */
d427b66a 2346 if (!NILP (Vbefore_change_function))
d206af14
RS
2347 {
2348 PRESERVE_VALUE;
b86e0aaf
RS
2349 PRESERVE_START_END;
2350 call2 (Vbefore_change_function, FETCH_START, FETCH_END);
d206af14 2351 }
e45fb8bf 2352
3d1e2d9c 2353 /* Now run the before-change-functions if any. */
e45fb8bf
RS
2354 if (!NILP (Vbefore_change_functions))
2355 {
3d1e2d9c
RS
2356 Lisp_Object args[3];
2357 Lisp_Object before_change_functions;
2358 Lisp_Object after_change_functions;
2359 struct gcpro gcpro1, gcpro2;
2360
d206af14 2361 PRESERVE_VALUE;
b86e0aaf 2362 PRESERVE_START_END;
d206af14 2363
3d1e2d9c
RS
2364 /* "Bind" before-change-functions and after-change-functions
2365 to nil--but in a way that errors don't know about.
2366 That way, if there's an error in them, they will stay nil. */
2367 before_change_functions = Vbefore_change_functions;
2368 after_change_functions = Vafter_change_functions;
c82c1da0
KH
2369 Vbefore_change_functions = Qnil;
2370 Vafter_change_functions = Qnil;
3d1e2d9c
RS
2371 GCPRO2 (before_change_functions, after_change_functions);
2372
2373 /* Actually run the hook functions. */
2374 args[0] = Qbefore_change_functions;
b86e0aaf
RS
2375 args[1] = FETCH_START;
2376 args[2] = FETCH_END;
3d1e2d9c
RS
2377 run_hook_list_with_args (before_change_functions, 3, args);
2378
2379 /* "Unbind" the variables we "bound" to nil. */
2380 Vbefore_change_functions = before_change_functions;
2381 Vafter_change_functions = after_change_functions;
2382 UNGCPRO;
e45fb8bf 2383 }
d07c0804
RS
2384
2385 if (!NILP (current_buffer->overlays_before)
2386 || !NILP (current_buffer->overlays_after))
d206af14
RS
2387 {
2388 PRESERVE_VALUE;
b86e0aaf
RS
2389 report_overlay_modification (FETCH_START, FETCH_END, 0,
2390 FETCH_START, FETCH_END, Qnil);
d206af14
RS
2391 }
2392
b86e0aaf
RS
2393 if (! NILP (start_marker))
2394 free_marker (start_marker);
2395 if (! NILP (end_marker))
2396 free_marker (end_marker);
d206af14
RS
2397 RESTORE_VALUE;
2398 UNGCPRO;
b45433b3
JB
2399}
2400
eb8c3be9 2401/* Signal a change immediately after it happens.
3be11131 2402 CHARPOS is the character position of the start of the changed text.
b45433b3
JB
2403 LENDEL is the number of characters of the text before the change.
2404 (Not the whole buffer; just the part that was changed.)
8b09e5d0
RS
2405 LENINS is the number of characters in that part of the text
2406 after the change. */
b45433b3 2407
c660b094 2408void
3be11131
RS
2409signal_after_change (charpos, lendel, lenins)
2410 int charpos, lendel, lenins;
b45433b3 2411{
fd16a4c6
KH
2412 if (inhibit_modification_hooks)
2413 return;
2414
fb2e7d14
RS
2415 /* If we are deferring calls to the after-change functions
2416 and there are no before-change functions,
2417 just record the args that we were going to use. */
2418 if (! NILP (Vcombine_after_change_calls)
2419 && NILP (Vbefore_change_function) && NILP (Vbefore_change_functions)
2420 && NILP (current_buffer->overlays_before)
2421 && NILP (current_buffer->overlays_after))
2422 {
2423 Lisp_Object elt;
2424
2425 if (!NILP (combine_after_change_list)
2426 && current_buffer != XBUFFER (combine_after_change_buffer))
2427 Fcombine_after_change_execute ();
2428
3be11131
RS
2429 elt = Fcons (make_number (charpos - BEG),
2430 Fcons (make_number (Z - (charpos - lendel + lenins)),
fb2e7d14
RS
2431 Fcons (make_number (lenins - lendel), Qnil)));
2432 combine_after_change_list
2433 = Fcons (elt, combine_after_change_list);
2434 combine_after_change_buffer = Fcurrent_buffer ();
2435
2436 return;
2437 }
2438
2439 if (!NILP (combine_after_change_list))
2440 Fcombine_after_change_execute ();
2441
3d1e2d9c
RS
2442 /* Run the after-change-function if any.
2443 We don't bother "binding" this variable to nil
2444 because it is obsolete anyway and new code should not use it. */
d427b66a 2445 if (!NILP (Vafter_change_function))
3d1e2d9c 2446 call3 (Vafter_change_function,
3be11131 2447 make_number (charpos), make_number (charpos + lenins),
3d1e2d9c 2448 make_number (lendel));
b45433b3 2449
e45fb8bf
RS
2450 if (!NILP (Vafter_change_functions))
2451 {
3d1e2d9c
RS
2452 Lisp_Object args[4];
2453 Lisp_Object before_change_functions;
2454 Lisp_Object after_change_functions;
2455 struct gcpro gcpro1, gcpro2;
2456
2457 /* "Bind" before-change-functions and after-change-functions
2458 to nil--but in a way that errors don't know about.
2459 That way, if there's an error in them, they will stay nil. */
2460 before_change_functions = Vbefore_change_functions;
2461 after_change_functions = Vafter_change_functions;
c82c1da0
KH
2462 Vbefore_change_functions = Qnil;
2463 Vafter_change_functions = Qnil;
3d1e2d9c
RS
2464 GCPRO2 (before_change_functions, after_change_functions);
2465
2466 /* Actually run the hook functions. */
2467 args[0] = Qafter_change_functions;
3be11131
RS
2468 XSETFASTINT (args[1], charpos);
2469 XSETFASTINT (args[2], charpos + lenins);
3d1e2d9c
RS
2470 XSETFASTINT (args[3], lendel);
2471 run_hook_list_with_args (after_change_functions,
2472 4, args);
2473
2474 /* "Unbind" the variables we "bound" to nil. */
2475 Vbefore_change_functions = before_change_functions;
2476 Vafter_change_functions = after_change_functions;
2477 UNGCPRO;
e45fb8bf 2478 }
d07c0804
RS
2479
2480 if (!NILP (current_buffer->overlays_before)
2481 || !NILP (current_buffer->overlays_after))
3be11131
RS
2482 report_overlay_modification (make_number (charpos),
2483 make_number (charpos + lenins),
d07c0804 2484 1,
3be11131
RS
2485 make_number (charpos),
2486 make_number (charpos + lenins),
d07c0804 2487 make_number (lendel));
c5ca0786
RS
2488
2489 /* After an insertion, call the text properties
2490 insert-behind-hooks or insert-in-front-hooks. */
2491 if (lendel == 0)
d6b81c0f
AS
2492 report_interval_modification (make_number (charpos),
2493 make_number (charpos + lenins));
b45433b3 2494}
fb2e7d14
RS
2495
2496Lisp_Object
2497Fcombine_after_change_execute_1 (val)
2498 Lisp_Object val;
2499{
2500 Vcombine_after_change_calls = val;
2501 return val;
2502}
2503
2504DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2505 Scombine_after_change_execute, 0, 0, 0,
2506 "This function is for use internally in `combine-after-change-calls'.")
2507 ()
2508{
2509 register Lisp_Object val;
2510 int count = specpdl_ptr - specpdl;
2511 int beg, end, change;
2512 int begpos, endpos;
2513 Lisp_Object tail;
2514
2515 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2516
2517 Fset_buffer (combine_after_change_buffer);
2518
2519 /* # chars unchanged at beginning of buffer. */
2520 beg = Z - BEG;
2521 /* # chars unchanged at end of buffer. */
2522 end = beg;
2523 /* Total amount of insertion (negative for deletion). */
2524 change = 0;
2525
2526 /* Scan the various individual changes,
2527 accumulating the range info in BEG, END and CHANGE. */
2528 for (tail = combine_after_change_list; CONSP (tail);
2529 tail = XCONS (tail)->cdr)
2530 {
e688a080
KH
2531 Lisp_Object elt;
2532 int thisbeg, thisend, thischange;
fb2e7d14
RS
2533
2534 /* Extract the info from the next element. */
2535 elt = XCONS (tail)->car;
2536 if (! CONSP (elt))
2537 continue;
2538 thisbeg = XINT (XCONS (elt)->car);
2539
2540 elt = XCONS (elt)->cdr;
2541 if (! CONSP (elt))
2542 continue;
2543 thisend = XINT (XCONS (elt)->car);
2544
2545 elt = XCONS (elt)->cdr;
2546 if (! CONSP (elt))
2547 continue;
2548 thischange = XINT (XCONS (elt)->car);
2549
2550 /* Merge this range into the accumulated range. */
2551 change += thischange;
2552 if (thisbeg < beg)
2553 beg = thisbeg;
2554 if (thisend < end)
2555 end = thisend;
2556 }
2557
2558 /* Get the current start and end positions of the range
2559 that was changed. */
2560 begpos = BEG + beg;
2561 endpos = Z - end;
2562
2563 /* We are about to handle these, so discard them. */
2564 combine_after_change_list = Qnil;
2565
2566 /* Now run the after-change functions for real.
2567 Turn off the flag that defers them. */
2568 record_unwind_protect (Fcombine_after_change_execute_1,
2569 Vcombine_after_change_calls);
2570 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2571
2572 return unbind_to (count, val);
2573}
2574\f
dfcf069d 2575void
fb2e7d14
RS
2576syms_of_insdel ()
2577{
2578 staticpro (&combine_after_change_list);
2579 combine_after_change_list = Qnil;
2580
60ea6052
RS
2581 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag,
2582 "Non-nil means enable debugging checks for invalid marker positions.");
2583 check_markers_debug_flag = 0;
fb2e7d14 2584 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
60ea6052 2585 "Used internally by the `combine-after-change-calls' macro.");
fb2e7d14
RS
2586 Vcombine_after_change_calls = Qnil;
2587
2588 defsubr (&Scombine_after_change_execute);
2589}