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