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