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