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