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