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