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