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