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