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