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