Workaround dumping problem on PaX-enabled Linux kernels
[emacs.git] / src / insdel.c
blob148ba221940acb018a7c3f359fd854c4454420c3
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985-1986, 1993-1995, 1997-2012
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
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.
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.
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/>. */
21 #include <config.h>
22 #include <setjmp.h>
24 #include <intprops.h>
26 #include "lisp.h"
27 #include "intervals.h"
28 #include "buffer.h"
29 #include "character.h"
30 #include "window.h"
31 #include "blockinput.h"
32 #include "region-cache.h"
34 static void insert_from_string_1 (Lisp_Object string,
35 ptrdiff_t pos, ptrdiff_t pos_byte,
36 ptrdiff_t nchars, ptrdiff_t nbytes,
37 int inherit, int before_markers);
38 static void insert_from_buffer_1 (struct buffer *buf,
39 ptrdiff_t from, ptrdiff_t nchars,
40 int inherit);
41 static void gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, int newgap);
42 static void gap_right (ptrdiff_t charpos, ptrdiff_t bytepos);
44 static Lisp_Object Fcombine_after_change_execute (void);
46 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
47 describing changes which happened while combine_after_change_calls
48 was nonzero. We use this to decide how to call them
49 once the deferral ends.
51 In each element.
52 BEG-UNCHANGED is the number of chars before the changed range.
53 END-UNCHANGED is the number of chars after the changed range,
54 and CHANGE-AMOUNT is the number of characters inserted by the change
55 (negative for a deletion). */
56 static Lisp_Object combine_after_change_list;
58 /* Buffer which combine_after_change_list is about. */
59 static Lisp_Object combine_after_change_buffer;
61 Lisp_Object Qinhibit_modification_hooks;
63 static void signal_before_change (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
65 #define CHECK_MARKERS() \
66 do \
67 { \
68 if (check_markers_debug_flag) \
69 check_markers (); \
70 } \
71 while (0)
73 static void
74 check_markers (void)
76 register struct Lisp_Marker *tail;
77 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
79 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
81 if (tail->buffer->text != current_buffer->text)
82 abort ();
83 if (tail->charpos > Z)
84 abort ();
85 if (tail->bytepos > Z_BYTE)
86 abort ();
87 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
88 abort ();
92 /* Move gap to position CHARPOS.
93 Note that this can quit! */
95 void
96 move_gap (ptrdiff_t charpos)
98 move_gap_both (charpos, charpos_to_bytepos (charpos));
101 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
102 Note that this can quit! */
104 void
105 move_gap_both (ptrdiff_t charpos, ptrdiff_t bytepos)
107 if (bytepos < GPT_BYTE)
108 gap_left (charpos, bytepos, 0);
109 else if (bytepos > GPT_BYTE)
110 gap_right (charpos, bytepos);
113 /* Move the gap to a position less than the current GPT.
114 BYTEPOS describes the new position as a byte position,
115 and CHARPOS is the corresponding char position.
116 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
118 static void
119 gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, int newgap)
121 register unsigned char *to, *from;
122 register ptrdiff_t i;
123 ptrdiff_t new_s1;
125 if (!newgap)
126 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
128 i = GPT_BYTE;
129 to = GAP_END_ADDR;
130 from = GPT_ADDR;
131 new_s1 = GPT_BYTE;
133 /* Now copy the characters. To move the gap down,
134 copy characters up. */
136 while (1)
138 /* I gets number of characters left to copy. */
139 i = new_s1 - bytepos;
140 if (i == 0)
141 break;
142 /* If a quit is requested, stop copying now.
143 Change BYTEPOS to be where we have actually moved the gap to. */
144 if (QUITP)
146 bytepos = new_s1;
147 charpos = BYTE_TO_CHAR (bytepos);
148 break;
150 /* Move at most 32000 chars before checking again for a quit. */
151 if (i > 32000)
152 i = 32000;
153 new_s1 -= i;
154 from -= i, to -= i;
155 memmove (to, from, i);
158 /* Adjust buffer data structure, to put the gap at BYTEPOS.
159 BYTEPOS is where the loop above stopped, which may be what
160 was specified or may be where a quit was detected. */
161 GPT_BYTE = bytepos;
162 GPT = charpos;
163 if (bytepos < charpos)
164 abort ();
165 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
166 QUIT;
169 /* Move the gap to a position greater than the current GPT.
170 BYTEPOS describes the new position as a byte position,
171 and CHARPOS is the corresponding char position. */
173 static void
174 gap_right (ptrdiff_t charpos, ptrdiff_t bytepos)
176 register unsigned char *to, *from;
177 register ptrdiff_t i;
178 ptrdiff_t new_s1;
180 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
182 i = GPT_BYTE;
183 from = GAP_END_ADDR;
184 to = GPT_ADDR;
185 new_s1 = GPT_BYTE;
187 /* Now copy the characters. To move the gap up,
188 copy characters down. */
190 while (1)
192 /* I gets number of characters left to copy. */
193 i = bytepos - new_s1;
194 if (i == 0)
195 break;
196 /* If a quit is requested, stop copying now.
197 Change BYTEPOS to be where we have actually moved the gap to. */
198 if (QUITP)
200 bytepos = new_s1;
201 charpos = BYTE_TO_CHAR (bytepos);
202 break;
204 /* Move at most 32000 chars before checking again for a quit. */
205 if (i > 32000)
206 i = 32000;
207 new_s1 += i;
208 memmove (to, from, i);
209 from += i, to += i;
212 GPT = charpos;
213 GPT_BYTE = bytepos;
214 if (bytepos < charpos)
215 abort ();
216 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
217 QUIT;
220 /* Adjust all markers for a deletion
221 whose range in bytes is FROM_BYTE to TO_BYTE.
222 The range in charpos is FROM to TO.
224 This function assumes that the gap is adjacent to
225 or inside of the range being deleted. */
227 void
228 adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte,
229 ptrdiff_t to, ptrdiff_t to_byte)
231 Lisp_Object marker;
232 register struct Lisp_Marker *m;
233 register ptrdiff_t charpos;
235 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
237 charpos = m->charpos;
239 if (charpos > Z)
240 abort ();
242 /* If the marker is after the deletion,
243 relocate by number of chars / bytes deleted. */
244 if (charpos > to)
246 m->charpos -= to - from;
247 m->bytepos -= to_byte - from_byte;
249 /* Here's the case where a marker is inside text being deleted. */
250 else if (charpos > from)
252 if (! m->insertion_type)
253 { /* Normal markers will end up at the beginning of the
254 re-inserted text after undoing a deletion, and must be
255 adjusted to move them to the correct place. */
256 XSETMISC (marker, m);
257 record_marker_adjustment (marker, from - charpos);
259 else if (charpos < to)
260 { /* Before-insertion markers will automatically move forward
261 upon re-inserting the deleted text, so we have to arrange
262 for them to move backward to the correct position. */
263 XSETMISC (marker, m);
264 record_marker_adjustment (marker, to - charpos);
266 m->charpos = from;
267 m->bytepos = from_byte;
269 /* Here's the case where a before-insertion marker is immediately
270 before the deleted region. */
271 else if (charpos == from && m->insertion_type)
273 /* Undoing the change uses normal insertion, which will
274 incorrectly make MARKER move forward, so we arrange for it
275 to then move backward to the correct place at the beginning
276 of the deleted region. */
277 XSETMISC (marker, m);
278 record_marker_adjustment (marker, to - from);
284 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
285 to TO / TO_BYTE. We have to relocate the charpos of every marker
286 that points after the insertion (but not their bytepos).
288 When a marker points at the insertion point,
289 we advance it if either its insertion-type is t
290 or BEFORE_MARKERS is true. */
292 static void
293 adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
294 ptrdiff_t to, ptrdiff_t to_byte, int before_markers)
296 struct Lisp_Marker *m;
297 int adjusted = 0;
298 ptrdiff_t nchars = to - from;
299 ptrdiff_t nbytes = to_byte - from_byte;
301 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
303 eassert (m->bytepos >= m->charpos
304 && m->bytepos - m->charpos <= Z_BYTE - Z);
306 if (m->bytepos == from_byte)
308 if (m->insertion_type || before_markers)
310 m->bytepos = to_byte;
311 m->charpos = to;
312 if (m->insertion_type)
313 adjusted = 1;
316 else if (m->bytepos > from_byte)
318 m->bytepos += nbytes;
319 m->charpos += nchars;
323 /* Adjusting only markers whose insertion-type is t may result in
324 - disordered start and end in overlays, and
325 - disordered overlays in the slot `overlays_before' of current_buffer. */
326 if (adjusted)
328 fix_start_end_in_overlays (from, to);
329 fix_overlays_before (current_buffer, from, to);
333 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
335 This is used only when the value of point changes due to an insert
336 or delete; it does not represent a conceptual change in point as a
337 marker. In particular, point is not crossing any interval
338 boundaries, so there's no need to use the usual SET_PT macro. In
339 fact it would be incorrect to do so, because either the old or the
340 new value of point is out of sync with the current set of
341 intervals. */
343 static void
344 adjust_point (ptrdiff_t nchars, ptrdiff_t nbytes)
346 SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes);
347 /* In a single-byte buffer, the two positions must be equal. */
348 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
351 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
352 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
353 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
354 an insertion. */
356 static void
357 adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
358 ptrdiff_t old_chars, ptrdiff_t old_bytes,
359 ptrdiff_t new_chars, ptrdiff_t new_bytes)
361 register struct Lisp_Marker *m;
362 ptrdiff_t prev_to_byte = from_byte + old_bytes;
363 ptrdiff_t diff_chars = new_chars - old_chars;
364 ptrdiff_t diff_bytes = new_bytes - old_bytes;
366 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
368 if (m->bytepos >= prev_to_byte)
370 m->charpos += diff_chars;
371 m->bytepos += diff_bytes;
373 else if (m->bytepos > from_byte)
375 m->charpos = from;
376 m->bytepos = from_byte;
380 CHECK_MARKERS ();
384 void
385 buffer_overflow (void)
387 error ("Maximum buffer size exceeded");
390 /* Make the gap NBYTES_ADDED bytes longer. */
392 static void
393 make_gap_larger (ptrdiff_t nbytes_added)
395 Lisp_Object tem;
396 ptrdiff_t real_gap_loc;
397 ptrdiff_t real_gap_loc_byte;
398 ptrdiff_t old_gap_size;
399 ptrdiff_t current_size = Z_BYTE - BEG_BYTE + GAP_SIZE;
400 enum { enough_for_a_while = 2000 };
402 if (BUF_BYTES_MAX - current_size < nbytes_added)
403 buffer_overflow ();
405 /* If we have to get more space, get enough to last a while;
406 but do not exceed the maximum buffer size. */
407 nbytes_added = min (nbytes_added + enough_for_a_while,
408 BUF_BYTES_MAX - current_size);
410 enlarge_buffer_text (current_buffer, nbytes_added);
412 /* Prevent quitting in move_gap. */
413 tem = Vinhibit_quit;
414 Vinhibit_quit = Qt;
416 real_gap_loc = GPT;
417 real_gap_loc_byte = GPT_BYTE;
418 old_gap_size = GAP_SIZE;
420 /* Call the newly allocated space a gap at the end of the whole space. */
421 GPT = Z + GAP_SIZE;
422 GPT_BYTE = Z_BYTE + GAP_SIZE;
423 GAP_SIZE = nbytes_added;
425 /* Move the new gap down to be consecutive with the end of the old one.
426 This adjusts the markers properly too. */
427 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
429 /* Now combine the two into one large gap. */
430 GAP_SIZE += old_gap_size;
431 GPT = real_gap_loc;
432 GPT_BYTE = real_gap_loc_byte;
434 /* Put an anchor. */
435 *(Z_ADDR) = 0;
437 Vinhibit_quit = tem;
440 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
442 /* Make the gap NBYTES_REMOVED bytes shorter. */
444 static void
445 make_gap_smaller (ptrdiff_t nbytes_removed)
447 Lisp_Object tem;
448 ptrdiff_t real_gap_loc;
449 ptrdiff_t real_gap_loc_byte;
450 ptrdiff_t real_Z;
451 ptrdiff_t real_Z_byte;
452 ptrdiff_t real_beg_unchanged;
453 ptrdiff_t new_gap_size;
455 /* Make sure the gap is at least 20 bytes. */
456 if (GAP_SIZE - nbytes_removed < 20)
457 nbytes_removed = GAP_SIZE - 20;
459 /* Prevent quitting in move_gap. */
460 tem = Vinhibit_quit;
461 Vinhibit_quit = Qt;
463 real_gap_loc = GPT;
464 real_gap_loc_byte = GPT_BYTE;
465 new_gap_size = GAP_SIZE - nbytes_removed;
466 real_Z = Z;
467 real_Z_byte = Z_BYTE;
468 real_beg_unchanged = BEG_UNCHANGED;
470 /* Pretend that the last unwanted part of the gap is the entire gap,
471 and that the first desired part of the gap is part of the buffer
472 text. */
473 memset (GPT_ADDR, 0, new_gap_size);
474 GPT += new_gap_size;
475 GPT_BYTE += new_gap_size;
476 Z += new_gap_size;
477 Z_BYTE += new_gap_size;
478 GAP_SIZE = nbytes_removed;
480 /* Move the unwanted pretend gap to the end of the buffer. This
481 adjusts the markers properly too. */
482 gap_right (Z, Z_BYTE);
484 enlarge_buffer_text (current_buffer, -nbytes_removed);
486 /* Now restore the desired gap. */
487 GAP_SIZE = new_gap_size;
488 GPT = real_gap_loc;
489 GPT_BYTE = real_gap_loc_byte;
490 Z = real_Z;
491 Z_BYTE = real_Z_byte;
492 BEG_UNCHANGED = real_beg_unchanged;
494 /* Put an anchor. */
495 *(Z_ADDR) = 0;
497 Vinhibit_quit = tem;
500 #endif /* USE_MMAP_FOR_BUFFERS || REL_ALLOC || DOUG_LEA_MALLOC */
502 void
503 make_gap (ptrdiff_t nbytes_added)
505 if (nbytes_added >= 0)
506 make_gap_larger (nbytes_added);
507 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
508 else
509 make_gap_smaller (-nbytes_added);
510 #endif
513 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
514 FROM_MULTIBYTE says whether the incoming text is multibyte.
515 TO_MULTIBYTE says whether to store the text as multibyte.
516 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
518 Return the number of bytes stored at TO_ADDR. */
520 ptrdiff_t
521 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
522 ptrdiff_t nbytes, int from_multibyte, int to_multibyte)
524 if (from_multibyte == to_multibyte)
526 memcpy (to_addr, from_addr, nbytes);
527 return nbytes;
529 else if (from_multibyte)
531 ptrdiff_t nchars = 0;
532 ptrdiff_t bytes_left = nbytes;
534 while (bytes_left > 0)
536 int thislen, c;
537 c = STRING_CHAR_AND_LENGTH (from_addr, thislen);
538 if (! ASCII_CHAR_P (c))
539 c &= 0xFF;
540 *to_addr++ = c;
541 from_addr += thislen;
542 bytes_left -= thislen;
543 nchars++;
545 return nchars;
547 else
549 unsigned char *initial_to_addr = to_addr;
551 /* Convert single-byte to multibyte. */
552 while (nbytes > 0)
554 int c = *from_addr++;
556 if (!ASCII_CHAR_P (c))
558 c = BYTE8_TO_CHAR (c);
559 to_addr += CHAR_STRING (c, to_addr);
560 nbytes--;
562 else
563 /* Special case for speed. */
564 *to_addr++ = c, nbytes--;
566 return to_addr - initial_to_addr;
570 /* Insert a string of specified length before point.
571 This function judges multibyteness based on
572 enable_multibyte_characters in the current buffer;
573 it never converts between single-byte and multibyte.
575 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
576 prepare_to_modify_buffer could relocate the text. */
578 void
579 insert (const char *string, ptrdiff_t nbytes)
581 if (nbytes > 0)
583 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
584 insert_1_both (string, len, nbytes, 0, 1, 0);
585 opoint = PT - len;
586 signal_after_change (opoint, 0, len);
587 update_compositions (opoint, PT, CHECK_BORDER);
591 /* Likewise, but inherit text properties from neighboring characters. */
593 void
594 insert_and_inherit (const char *string, ptrdiff_t nbytes)
596 if (nbytes > 0)
598 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
599 insert_1_both (string, len, nbytes, 1, 1, 0);
600 opoint = PT - len;
601 signal_after_change (opoint, 0, len);
602 update_compositions (opoint, PT, CHECK_BORDER);
606 /* Insert the character C before point. Do not inherit text properties. */
608 void
609 insert_char (int c)
611 unsigned char str[MAX_MULTIBYTE_LENGTH];
612 int len;
614 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
615 len = CHAR_STRING (c, str);
616 else
618 len = 1;
619 str[0] = c;
622 insert ((char *) str, len);
625 /* Insert the null-terminated string S before point. */
627 void
628 insert_string (const char *s)
630 insert (s, strlen (s));
633 /* Like `insert' except that all markers pointing at the place where
634 the insertion happens are adjusted to point after it.
635 Don't use this function to insert part of a Lisp string,
636 since gc could happen and relocate it. */
638 void
639 insert_before_markers (const char *string, ptrdiff_t nbytes)
641 if (nbytes > 0)
643 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
644 insert_1_both (string, len, nbytes, 0, 1, 1);
645 opoint = PT - len;
646 signal_after_change (opoint, 0, len);
647 update_compositions (opoint, PT, CHECK_BORDER);
651 /* Likewise, but inherit text properties from neighboring characters. */
653 void
654 insert_before_markers_and_inherit (const char *string,
655 ptrdiff_t nbytes)
657 if (nbytes > 0)
659 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
660 insert_1_both (string, len, nbytes, 1, 1, 1);
661 opoint = PT - len;
662 signal_after_change (opoint, 0, len);
663 update_compositions (opoint, PT, CHECK_BORDER);
667 /* Subroutine used by the insert functions above. */
669 void
670 insert_1 (const char *string, ptrdiff_t nbytes,
671 int inherit, int prepare, int before_markers)
673 insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
674 nbytes, inherit, prepare, before_markers);
678 #ifdef BYTE_COMBINING_DEBUG
680 /* See if the bytes before POS/POS_BYTE combine with bytes
681 at the start of STRING to form a single character.
682 If so, return the number of bytes at the start of STRING
683 which combine in this way. Otherwise, return 0. */
686 count_combining_before (const unsigned char *string, ptrdiff_t length,
687 ptrdiff_t pos, ptrdiff_t pos_byte)
689 int len, combining_bytes;
690 const unsigned char *p;
692 if (NILP (current_buffer->enable_multibyte_characters))
693 return 0;
695 /* At first, we can exclude the following cases:
696 (1) STRING[0] can't be a following byte of multibyte sequence.
697 (2) POS is the start of the current buffer.
698 (3) A character before POS is not a multibyte character. */
699 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
700 return 0;
701 if (pos_byte == BEG_BYTE) /* case (2) */
702 return 0;
703 len = 1;
704 p = BYTE_POS_ADDR (pos_byte - 1);
705 while (! CHAR_HEAD_P (*p)) p--, len++;
706 if (! LEADING_CODE_P (*p)) /* case (3) */
707 return 0;
709 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
710 if (combining_bytes <= 0)
711 /* The character preceding POS is, complete and no room for
712 combining bytes (combining_bytes == 0), or an independent 8-bit
713 character (combining_bytes < 0). */
714 return 0;
716 /* We have a combination situation. Count the bytes at STRING that
717 may combine. */
718 p = string + 1;
719 while (!CHAR_HEAD_P (*p) && p < string + length)
720 p++;
722 return (combining_bytes < p - string ? combining_bytes : p - string);
725 /* See if the bytes after POS/POS_BYTE combine with bytes
726 at the end of STRING to form a single character.
727 If so, return the number of bytes after POS/POS_BYTE
728 which combine in this way. Otherwise, return 0. */
731 count_combining_after (const unsigned char *string,
732 ptrdiff_t length, ptrdiff_t pos, ptrdiff_t pos_byte)
734 ptrdiff_t opos_byte = pos_byte;
735 ptrdiff_t i;
736 ptrdiff_t bytes;
737 unsigned char *bufp;
739 if (NILP (current_buffer->enable_multibyte_characters))
740 return 0;
742 /* At first, we can exclude the following cases:
743 (1) The last byte of STRING is an ASCII.
744 (2) POS is the last of the current buffer.
745 (3) A character at POS can't be a following byte of multibyte
746 character. */
747 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
748 return 0;
749 if (pos_byte == Z_BYTE) /* case (2) */
750 return 0;
751 bufp = BYTE_POS_ADDR (pos_byte);
752 if (CHAR_HEAD_P (*bufp)) /* case (3) */
753 return 0;
755 i = length - 1;
756 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
758 i--;
760 if (i < 0)
762 /* All characters in STRING are not character head. We must
763 check also preceding bytes at POS. We are sure that the gap
764 is at POS. */
765 unsigned char *p = BEG_ADDR;
766 i = pos_byte - 2;
767 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
768 i--;
769 if (i < 0 || !LEADING_CODE_P (p[i]))
770 return 0;
772 bytes = BYTES_BY_CHAR_HEAD (p[i]);
773 return (bytes <= pos_byte - 1 - i + length
775 : bytes - (pos_byte - 1 - i + length));
777 if (!LEADING_CODE_P (string[i]))
778 return 0;
780 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
781 bufp++, pos_byte++;
782 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
784 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
787 #endif
790 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
791 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
792 are the same as in insert_1. */
794 void
795 insert_1_both (const char *string,
796 ptrdiff_t nchars, ptrdiff_t nbytes,
797 int inherit, int prepare, int before_markers)
799 if (nchars == 0)
800 return;
802 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
803 nchars = nbytes;
805 if (prepare)
806 /* Do this before moving and increasing the gap,
807 because the before-change hooks might move the gap
808 or make it smaller. */
809 prepare_to_modify_buffer (PT, PT, NULL);
811 if (PT != GPT)
812 move_gap_both (PT, PT_BYTE);
813 if (GAP_SIZE < nbytes)
814 make_gap (nbytes - GAP_SIZE);
816 #ifdef BYTE_COMBINING_DEBUG
817 if (count_combining_before (string, nbytes, PT, PT_BYTE)
818 || count_combining_after (string, nbytes, PT, PT_BYTE))
819 abort ();
820 #endif
822 /* Record deletion of the surrounding text that combines with
823 the insertion. This, together with recording the insertion,
824 will add up to the right stuff in the undo list. */
825 record_insert (PT, nchars);
826 MODIFF++;
827 CHARS_MODIFF = MODIFF;
829 memcpy (GPT_ADDR, string, nbytes);
831 GAP_SIZE -= nbytes;
832 GPT += nchars;
833 ZV += nchars;
834 Z += nchars;
835 GPT_BYTE += nbytes;
836 ZV_BYTE += nbytes;
837 Z_BYTE += nbytes;
838 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
840 if (GPT_BYTE < GPT)
841 abort ();
843 /* The insert may have been in the unchanged region, so check again. */
844 if (Z - GPT < END_UNCHANGED)
845 END_UNCHANGED = Z - GPT;
847 adjust_overlays_for_insert (PT, nchars);
848 adjust_markers_for_insert (PT, PT_BYTE,
849 PT + nchars, PT_BYTE + nbytes,
850 before_markers);
852 if (BUF_INTERVALS (current_buffer) != 0)
853 offset_intervals (current_buffer, PT, nchars);
855 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
856 set_text_properties (make_number (PT), make_number (PT + nchars),
857 Qnil, Qnil, Qnil);
859 adjust_point (nchars, nbytes);
861 CHECK_MARKERS ();
864 /* Insert the part of the text of STRING, a Lisp object assumed to be
865 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
866 starting at position POS / POS_BYTE. If the text of STRING has properties,
867 copy them into the buffer.
869 It does not work to use `insert' for this, because a GC could happen
870 before we copy the stuff into the buffer, and relocate the string
871 without insert noticing. */
873 void
874 insert_from_string (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
875 ptrdiff_t length, ptrdiff_t length_byte, int inherit)
877 ptrdiff_t opoint = PT;
879 if (SCHARS (string) == 0)
880 return;
882 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
883 inherit, 0);
884 signal_after_change (opoint, 0, PT - opoint);
885 update_compositions (opoint, PT, CHECK_BORDER);
888 /* Like `insert_from_string' except that all markers pointing
889 at the place where the insertion happens are adjusted to point after it. */
891 void
892 insert_from_string_before_markers (Lisp_Object string,
893 ptrdiff_t pos, ptrdiff_t pos_byte,
894 ptrdiff_t length, ptrdiff_t length_byte,
895 int inherit)
897 ptrdiff_t opoint = PT;
899 if (SCHARS (string) == 0)
900 return;
902 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
903 inherit, 1);
904 signal_after_change (opoint, 0, PT - opoint);
905 update_compositions (opoint, PT, CHECK_BORDER);
908 /* Subroutine of the insertion functions above. */
910 static void
911 insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
912 ptrdiff_t nchars, ptrdiff_t nbytes,
913 int inherit, int before_markers)
915 struct gcpro gcpro1;
916 ptrdiff_t outgoing_nbytes = nbytes;
917 INTERVAL intervals;
919 /* Make OUTGOING_NBYTES describe the text
920 as it will be inserted in this buffer. */
922 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
923 outgoing_nbytes = nchars;
924 else if (! STRING_MULTIBYTE (string))
925 outgoing_nbytes
926 = count_size_as_multibyte (SDATA (string) + pos_byte,
927 nbytes);
929 GCPRO1 (string);
930 /* Do this before moving and increasing the gap,
931 because the before-change hooks might move the gap
932 or make it smaller. */
933 prepare_to_modify_buffer (PT, PT, NULL);
935 if (PT != GPT)
936 move_gap_both (PT, PT_BYTE);
937 if (GAP_SIZE < outgoing_nbytes)
938 make_gap (outgoing_nbytes - GAP_SIZE);
939 UNGCPRO;
941 /* Copy the string text into the buffer, perhaps converting
942 between single-byte and multibyte. */
943 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
944 STRING_MULTIBYTE (string),
945 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
947 #ifdef BYTE_COMBINING_DEBUG
948 /* We have copied text into the gap, but we have not altered
949 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
950 to these functions and get the same results as we would
951 have got earlier on. Meanwhile, PT_ADDR does point to
952 the text that has been stored by copy_text. */
953 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
954 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
955 abort ();
956 #endif
958 record_insert (PT, nchars);
959 MODIFF++;
960 CHARS_MODIFF = MODIFF;
962 GAP_SIZE -= outgoing_nbytes;
963 GPT += nchars;
964 ZV += nchars;
965 Z += nchars;
966 GPT_BYTE += outgoing_nbytes;
967 ZV_BYTE += outgoing_nbytes;
968 Z_BYTE += outgoing_nbytes;
969 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
971 if (GPT_BYTE < GPT)
972 abort ();
974 /* The insert may have been in the unchanged region, so check again. */
975 if (Z - GPT < END_UNCHANGED)
976 END_UNCHANGED = Z - GPT;
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);
983 offset_intervals (current_buffer, PT, nchars);
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);
990 /* Insert those intervals. */
991 graft_intervals_into_buffer (intervals, PT, nchars,
992 current_buffer, inherit);
994 adjust_point (nchars, outgoing_nbytes);
996 CHECK_MARKERS ();
999 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1000 starting at GPT_ADDR. */
1002 void
1003 insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes)
1005 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1006 nchars = nbytes;
1008 record_insert (GPT, nchars);
1009 MODIFF++;
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. */
1020 if (GPT_BYTE < GPT)
1021 abort ();
1023 adjust_overlays_for_insert (GPT - nchars, nchars);
1024 adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
1025 GPT, GPT_BYTE, 0);
1027 if (BUF_INTERVALS (current_buffer) != 0)
1029 offset_intervals (current_buffer, GPT - nchars, nchars);
1030 graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
1031 current_buffer, 0);
1034 if (GPT - nchars < PT)
1035 adjust_point (nchars, nbytes);
1037 CHECK_MARKERS ();
1040 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1041 current buffer. If the text in BUF has properties, they are absorbed
1042 into the current buffer.
1044 It does not work to use `insert' for this, because a malloc could happen
1045 and relocate BUF's text before the copy happens. */
1047 void
1048 insert_from_buffer (struct buffer *buf,
1049 ptrdiff_t charpos, ptrdiff_t nchars, int inherit)
1051 ptrdiff_t opoint = PT;
1053 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1054 signal_after_change (opoint, 0, PT - opoint);
1055 update_compositions (opoint, PT, CHECK_BORDER);
1058 static void
1059 insert_from_buffer_1 (struct buffer *buf,
1060 ptrdiff_t from, ptrdiff_t nchars, int inherit)
1062 ptrdiff_t chunk, chunk_expanded;
1063 ptrdiff_t from_byte = buf_charpos_to_bytepos (buf, from);
1064 ptrdiff_t to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1065 ptrdiff_t incoming_nbytes = to_byte - from_byte;
1066 ptrdiff_t outgoing_nbytes = incoming_nbytes;
1067 INTERVAL intervals;
1069 /* Make OUTGOING_NBYTES describe the text
1070 as it will be inserted in this buffer. */
1072 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1073 outgoing_nbytes = nchars;
1074 else if (NILP (BVAR (buf, enable_multibyte_characters)))
1076 ptrdiff_t outgoing_before_gap = 0;
1077 ptrdiff_t outgoing_after_gap = 0;
1079 if (from < BUF_GPT (buf))
1081 chunk = BUF_GPT_BYTE (buf) - from_byte;
1082 if (chunk > incoming_nbytes)
1083 chunk = incoming_nbytes;
1084 outgoing_before_gap
1085 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1086 chunk);
1088 else
1089 chunk = 0;
1091 if (chunk < incoming_nbytes)
1092 outgoing_after_gap
1093 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1094 from_byte + chunk),
1095 incoming_nbytes - chunk);
1097 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1100 /* Do this before moving and increasing the gap,
1101 because the before-change hooks might move the gap
1102 or make it smaller. */
1103 prepare_to_modify_buffer (PT, PT, NULL);
1105 if (PT != GPT)
1106 move_gap_both (PT, PT_BYTE);
1107 if (GAP_SIZE < outgoing_nbytes)
1108 make_gap (outgoing_nbytes - GAP_SIZE);
1110 if (from < BUF_GPT (buf))
1112 chunk = BUF_GPT_BYTE (buf) - from_byte;
1113 if (chunk > incoming_nbytes)
1114 chunk = incoming_nbytes;
1115 /* Record number of output bytes, so we know where
1116 to put the output from the second copy_text. */
1117 chunk_expanded
1118 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1119 GPT_ADDR, chunk,
1120 ! NILP (BVAR (buf, enable_multibyte_characters)),
1121 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1123 else
1124 chunk_expanded = chunk = 0;
1126 if (chunk < incoming_nbytes)
1127 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1128 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1129 ! NILP (BVAR (buf, enable_multibyte_characters)),
1130 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1132 #ifdef BYTE_COMBINING_DEBUG
1133 /* We have copied text into the gap, but we have not altered
1134 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1135 to these functions and get the same results as we would
1136 have got earlier on. Meanwhile, GPT_ADDR does point to
1137 the text that has been stored by copy_text. */
1138 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1139 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1140 abort ();
1141 #endif
1143 record_insert (PT, nchars);
1144 MODIFF++;
1145 CHARS_MODIFF = MODIFF;
1147 GAP_SIZE -= outgoing_nbytes;
1148 GPT += nchars;
1149 ZV += nchars;
1150 Z += nchars;
1151 GPT_BYTE += outgoing_nbytes;
1152 ZV_BYTE += outgoing_nbytes;
1153 Z_BYTE += outgoing_nbytes;
1154 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1156 if (GPT_BYTE < GPT)
1157 abort ();
1159 /* The insert may have been in the unchanged region, so check again. */
1160 if (Z - GPT < END_UNCHANGED)
1161 END_UNCHANGED = Z - GPT;
1163 adjust_overlays_for_insert (PT, nchars);
1164 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1165 PT_BYTE + outgoing_nbytes,
1168 if (BUF_INTERVALS (current_buffer) != 0)
1169 offset_intervals (current_buffer, PT, nchars);
1171 /* Get the intervals for the part of the string we are inserting. */
1172 intervals = BUF_INTERVALS (buf);
1173 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1175 if (buf == current_buffer && PT <= from)
1176 from += nchars;
1177 intervals = copy_intervals (intervals, from, nchars);
1180 /* Insert those intervals. */
1181 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1183 adjust_point (nchars, outgoing_nbytes);
1186 /* Record undo information and adjust markers and position keepers for
1187 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1188 chars (LEN_BYTE bytes) which resides in the gap just after
1189 GPT_ADDR.
1191 PREV_TEXT nil means the new text was just inserted. */
1193 static void
1194 adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1195 Lisp_Object prev_text, ptrdiff_t len, ptrdiff_t len_byte)
1197 ptrdiff_t nchars_del = 0, nbytes_del = 0;
1199 #ifdef BYTE_COMBINING_DEBUG
1200 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1201 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1202 abort ();
1203 #endif
1205 if (STRINGP (prev_text))
1207 nchars_del = SCHARS (prev_text);
1208 nbytes_del = SBYTES (prev_text);
1211 /* Update various buffer positions for the new text. */
1212 GAP_SIZE -= len_byte;
1213 ZV += len; Z+= len;
1214 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1215 GPT += len; GPT_BYTE += len_byte;
1216 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1218 if (nchars_del > 0)
1219 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1220 len, len_byte);
1221 else
1222 adjust_markers_for_insert (from, from_byte,
1223 from + len, from_byte + len_byte, 0);
1225 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1227 if (nchars_del > 0)
1228 record_delete (from, prev_text);
1229 record_insert (from, len);
1232 if (len > nchars_del)
1233 adjust_overlays_for_insert (from, len - nchars_del);
1234 else if (len < nchars_del)
1235 adjust_overlays_for_delete (from, nchars_del - len);
1236 if (BUF_INTERVALS (current_buffer) != 0)
1238 offset_intervals (current_buffer, from, len - nchars_del);
1241 if (from < PT)
1242 adjust_point (len - nchars_del, len_byte - nbytes_del);
1244 /* As byte combining will decrease Z, we must check this again. */
1245 if (Z - GPT < END_UNCHANGED)
1246 END_UNCHANGED = Z - GPT;
1248 CHECK_MARKERS ();
1250 if (len == 0)
1251 evaporate_overlays (from);
1252 MODIFF++;
1253 CHARS_MODIFF = MODIFF;
1256 /* Record undo information, adjust markers and position keepers for an
1257 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1258 text already exists in the current buffer but character length (TO
1259 - FROM) may be incorrect, the correct length is NEWLEN. */
1261 void
1262 adjust_after_insert (ptrdiff_t from, ptrdiff_t from_byte,
1263 ptrdiff_t to, ptrdiff_t to_byte, ptrdiff_t newlen)
1265 ptrdiff_t len = to - from, len_byte = to_byte - from_byte;
1267 if (GPT != to)
1268 move_gap_both (to, to_byte);
1269 GAP_SIZE += len_byte;
1270 GPT -= len; GPT_BYTE -= len_byte;
1271 ZV -= len; ZV_BYTE -= len_byte;
1272 Z -= len; Z_BYTE -= len_byte;
1273 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1276 /* Replace the text from character positions FROM to TO with NEW,
1277 If PREPARE is nonzero, call prepare_to_modify_buffer.
1278 If INHERIT, the newly inserted text should inherit text properties
1279 from the surrounding non-deleted text. */
1281 /* Note that this does not yet handle markers quite right.
1282 Also it needs to record a single undo-entry that does a replacement
1283 rather than a separate delete and insert.
1284 That way, undo will also handle markers properly.
1286 But if MARKERS is 0, don't relocate markers. */
1288 void
1289 replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1290 int prepare, int inherit, int markers)
1292 ptrdiff_t inschars = SCHARS (new);
1293 ptrdiff_t insbytes = SBYTES (new);
1294 ptrdiff_t from_byte, to_byte;
1295 ptrdiff_t nbytes_del, nchars_del;
1296 struct gcpro gcpro1;
1297 INTERVAL intervals;
1298 ptrdiff_t outgoing_insbytes = insbytes;
1299 Lisp_Object deletion;
1301 CHECK_MARKERS ();
1303 GCPRO1 (new);
1304 deletion = Qnil;
1306 if (prepare)
1308 ptrdiff_t range_length = to - from;
1309 prepare_to_modify_buffer (from, to, &from);
1310 to = from + range_length;
1313 UNGCPRO;
1315 /* Make args be valid. */
1316 if (from < BEGV)
1317 from = BEGV;
1318 if (to > ZV)
1319 to = ZV;
1321 from_byte = CHAR_TO_BYTE (from);
1322 to_byte = CHAR_TO_BYTE (to);
1324 nchars_del = to - from;
1325 nbytes_del = to_byte - from_byte;
1327 if (nbytes_del <= 0 && insbytes == 0)
1328 return;
1330 /* Make OUTGOING_INSBYTES describe the text
1331 as it will be inserted in this buffer. */
1333 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1334 outgoing_insbytes = inschars;
1335 else if (! STRING_MULTIBYTE (new))
1336 outgoing_insbytes
1337 = count_size_as_multibyte (SDATA (new), insbytes);
1339 GCPRO1 (new);
1341 /* Make sure the gap is somewhere in or next to what we are deleting. */
1342 if (from > GPT)
1343 gap_right (from, from_byte);
1344 if (to < GPT)
1345 gap_left (to, to_byte, 0);
1347 /* Even if we don't record for undo, we must keep the original text
1348 because we may have to recover it because of inappropriate byte
1349 combining. */
1350 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1351 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1353 GAP_SIZE += nbytes_del;
1354 ZV -= nchars_del;
1355 Z -= nchars_del;
1356 ZV_BYTE -= nbytes_del;
1357 Z_BYTE -= nbytes_del;
1358 GPT = from;
1359 GPT_BYTE = from_byte;
1360 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1362 if (GPT_BYTE < GPT)
1363 abort ();
1365 if (GPT - BEG < BEG_UNCHANGED)
1366 BEG_UNCHANGED = GPT - BEG;
1367 if (Z - GPT < END_UNCHANGED)
1368 END_UNCHANGED = Z - GPT;
1370 if (GAP_SIZE < outgoing_insbytes)
1371 make_gap (outgoing_insbytes - GAP_SIZE);
1373 /* Copy the string text into the buffer, perhaps converting
1374 between single-byte and multibyte. */
1375 copy_text (SDATA (new), GPT_ADDR, insbytes,
1376 STRING_MULTIBYTE (new),
1377 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1379 #ifdef BYTE_COMBINING_DEBUG
1380 /* We have copied text into the gap, but we have not marked
1381 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1382 here, for both the previous text and the following text.
1383 Meanwhile, GPT_ADDR does point to
1384 the text that has been stored by copy_text. */
1385 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1386 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1387 abort ();
1388 #endif
1390 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1392 /* Record the insertion first, so that when we undo,
1393 the deletion will be undone first. Thus, undo
1394 will insert before deleting, and thus will keep
1395 the markers before and after this text separate. */
1396 record_insert (from + SCHARS (deletion), inschars);
1397 record_delete (from, deletion);
1400 GAP_SIZE -= outgoing_insbytes;
1401 GPT += inschars;
1402 ZV += inschars;
1403 Z += inschars;
1404 GPT_BYTE += outgoing_insbytes;
1405 ZV_BYTE += outgoing_insbytes;
1406 Z_BYTE += outgoing_insbytes;
1407 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1409 if (GPT_BYTE < GPT)
1410 abort ();
1412 /* Adjust the overlay center as needed. This must be done after
1413 adjusting the markers that bound the overlays. */
1414 adjust_overlays_for_delete (from, nchars_del);
1415 adjust_overlays_for_insert (from, inschars);
1417 /* Adjust markers for the deletion and the insertion. */
1418 if (markers)
1419 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1420 inschars, outgoing_insbytes);
1422 offset_intervals (current_buffer, from, inschars - nchars_del);
1424 /* Get the intervals for the part of the string we are inserting--
1425 not including the combined-before bytes. */
1426 intervals = STRING_INTERVALS (new);
1427 /* Insert those intervals. */
1428 graft_intervals_into_buffer (intervals, from, inschars,
1429 current_buffer, inherit);
1431 /* Relocate point as if it were a marker. */
1432 if (from < PT)
1433 adjust_point ((from + inschars - (PT < to ? PT : to)),
1434 (from_byte + outgoing_insbytes
1435 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1437 if (outgoing_insbytes == 0)
1438 evaporate_overlays (from);
1440 CHECK_MARKERS ();
1442 MODIFF++;
1443 CHARS_MODIFF = MODIFF;
1444 UNGCPRO;
1446 signal_after_change (from, nchars_del, GPT - from);
1447 update_compositions (from, GPT, CHECK_BORDER);
1450 /* Replace the text from character positions FROM to TO with
1451 the text in INS of length INSCHARS.
1452 Keep the text properties that applied to the old characters
1453 (extending them to all the new chars if there are more new chars).
1455 Note that this does not yet handle markers quite right.
1457 If MARKERS is nonzero, relocate markers.
1459 Unlike most functions at this level, never call
1460 prepare_to_modify_buffer and never call signal_after_change. */
1462 void
1463 replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1464 ptrdiff_t to, ptrdiff_t to_byte,
1465 const char *ins, ptrdiff_t inschars, ptrdiff_t insbytes,
1466 int markers)
1468 ptrdiff_t nbytes_del, nchars_del;
1470 CHECK_MARKERS ();
1472 nchars_del = to - from;
1473 nbytes_del = to_byte - from_byte;
1475 if (nbytes_del <= 0 && insbytes == 0)
1476 return;
1478 /* Make sure the gap is somewhere in or next to what we are deleting. */
1479 if (from > GPT)
1480 gap_right (from, from_byte);
1481 if (to < GPT)
1482 gap_left (to, to_byte, 0);
1484 GAP_SIZE += nbytes_del;
1485 ZV -= nchars_del;
1486 Z -= nchars_del;
1487 ZV_BYTE -= nbytes_del;
1488 Z_BYTE -= nbytes_del;
1489 GPT = from;
1490 GPT_BYTE = from_byte;
1491 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1493 if (GPT_BYTE < GPT)
1494 abort ();
1496 if (GPT - BEG < BEG_UNCHANGED)
1497 BEG_UNCHANGED = GPT - BEG;
1498 if (Z - GPT < END_UNCHANGED)
1499 END_UNCHANGED = Z - GPT;
1501 if (GAP_SIZE < insbytes)
1502 make_gap (insbytes - GAP_SIZE);
1504 /* Copy the replacement text into the buffer. */
1505 memcpy (GPT_ADDR, ins, insbytes);
1507 #ifdef BYTE_COMBINING_DEBUG
1508 /* We have copied text into the gap, but we have not marked
1509 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1510 here, for both the previous text and the following text.
1511 Meanwhile, GPT_ADDR does point to
1512 the text that has been stored by copy_text. */
1513 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1514 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1515 abort ();
1516 #endif
1518 GAP_SIZE -= insbytes;
1519 GPT += inschars;
1520 ZV += inschars;
1521 Z += inschars;
1522 GPT_BYTE += insbytes;
1523 ZV_BYTE += insbytes;
1524 Z_BYTE += insbytes;
1525 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1527 if (GPT_BYTE < GPT)
1528 abort ();
1530 /* Adjust the overlay center as needed. This must be done after
1531 adjusting the markers that bound the overlays. */
1532 if (nchars_del != inschars)
1534 adjust_overlays_for_insert (from, inschars);
1535 adjust_overlays_for_delete (from + inschars, nchars_del);
1538 /* Adjust markers for the deletion and the insertion. */
1539 if (markers
1540 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1541 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1542 inschars, insbytes);
1544 offset_intervals (current_buffer, from, inschars - nchars_del);
1546 /* Relocate point as if it were a marker. */
1547 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1549 if (PT < to)
1550 /* PT was within the deleted text. Move it to FROM. */
1551 adjust_point (from - PT, from_byte - PT_BYTE);
1552 else
1553 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1556 if (insbytes == 0)
1557 evaporate_overlays (from);
1559 CHECK_MARKERS ();
1561 MODIFF++;
1562 CHARS_MODIFF = MODIFF;
1565 /* Delete characters in current buffer
1566 from FROM up to (but not including) TO.
1567 If TO comes before FROM, we delete nothing. */
1569 void
1570 del_range (ptrdiff_t from, ptrdiff_t to)
1572 del_range_1 (from, to, 1, 0);
1575 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1576 RET_STRING says to return the deleted text. */
1578 Lisp_Object
1579 del_range_1 (ptrdiff_t from, ptrdiff_t to, int prepare, int ret_string)
1581 ptrdiff_t from_byte, to_byte;
1582 Lisp_Object deletion;
1583 struct gcpro gcpro1;
1585 /* Make args be valid */
1586 if (from < BEGV)
1587 from = BEGV;
1588 if (to > ZV)
1589 to = ZV;
1591 if (to <= from)
1592 return Qnil;
1594 if (prepare)
1596 ptrdiff_t range_length = to - from;
1597 prepare_to_modify_buffer (from, to, &from);
1598 to = min (ZV, from + range_length);
1601 from_byte = CHAR_TO_BYTE (from);
1602 to_byte = CHAR_TO_BYTE (to);
1604 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1605 GCPRO1 (deletion);
1606 signal_after_change (from, to - from, 0);
1607 update_compositions (from, from, CHECK_HEAD);
1608 UNGCPRO;
1609 return deletion;
1612 /* Like del_range_1 but args are byte positions, not char positions. */
1614 void
1615 del_range_byte (ptrdiff_t from_byte, ptrdiff_t to_byte, int prepare)
1617 ptrdiff_t from, to;
1619 /* Make args be valid */
1620 if (from_byte < BEGV_BYTE)
1621 from_byte = BEGV_BYTE;
1622 if (to_byte > ZV_BYTE)
1623 to_byte = ZV_BYTE;
1625 if (to_byte <= from_byte)
1626 return;
1628 from = BYTE_TO_CHAR (from_byte);
1629 to = BYTE_TO_CHAR (to_byte);
1631 if (prepare)
1633 ptrdiff_t old_from = from, old_to = Z - to;
1634 ptrdiff_t range_length = to - from;
1635 prepare_to_modify_buffer (from, to, &from);
1636 to = from + range_length;
1638 if (old_from != from)
1639 from_byte = CHAR_TO_BYTE (from);
1640 if (to > ZV)
1642 to = ZV;
1643 to_byte = ZV_BYTE;
1645 else if (old_to == Z - to)
1646 to_byte = CHAR_TO_BYTE (to);
1649 del_range_2 (from, from_byte, to, to_byte, 0);
1650 signal_after_change (from, to - from, 0);
1651 update_compositions (from, from, CHECK_HEAD);
1654 /* Like del_range_1, but positions are specified both as charpos
1655 and bytepos. */
1657 void
1658 del_range_both (ptrdiff_t from, ptrdiff_t from_byte,
1659 ptrdiff_t to, ptrdiff_t to_byte, int prepare)
1661 /* Make args be valid */
1662 if (from_byte < BEGV_BYTE)
1663 from_byte = BEGV_BYTE;
1664 if (to_byte > ZV_BYTE)
1665 to_byte = ZV_BYTE;
1667 if (to_byte <= from_byte)
1668 return;
1670 if (from < BEGV)
1671 from = BEGV;
1672 if (to > ZV)
1673 to = ZV;
1675 if (prepare)
1677 ptrdiff_t old_from = from, old_to = Z - to;
1678 ptrdiff_t range_length = to - from;
1679 prepare_to_modify_buffer (from, to, &from);
1680 to = from + range_length;
1682 if (old_from != from)
1683 from_byte = CHAR_TO_BYTE (from);
1684 if (to > ZV)
1686 to = ZV;
1687 to_byte = ZV_BYTE;
1689 else if (old_to == Z - to)
1690 to_byte = CHAR_TO_BYTE (to);
1693 del_range_2 (from, from_byte, to, to_byte, 0);
1694 signal_after_change (from, to - from, 0);
1695 update_compositions (from, from, CHECK_HEAD);
1698 /* Delete a range of text, specified both as character positions
1699 and byte positions. FROM and TO are character positions,
1700 while FROM_BYTE and TO_BYTE are byte positions.
1701 If RET_STRING is true, the deleted area is returned as a string. */
1703 Lisp_Object
1704 del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1705 ptrdiff_t to, ptrdiff_t to_byte, int ret_string)
1707 register ptrdiff_t nbytes_del, nchars_del;
1708 Lisp_Object deletion;
1710 CHECK_MARKERS ();
1712 nchars_del = to - from;
1713 nbytes_del = to_byte - from_byte;
1715 /* Make sure the gap is somewhere in or next to what we are deleting. */
1716 if (from > GPT)
1717 gap_right (from, from_byte);
1718 if (to < GPT)
1719 gap_left (to, to_byte, 0);
1721 #ifdef BYTE_COMBINING_DEBUG
1722 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1723 Z_BYTE - to_byte, from, from_byte))
1724 abort ();
1725 #endif
1727 if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
1728 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1729 else
1730 deletion = Qnil;
1732 /* Relocate all markers pointing into the new, larger gap
1733 to point at the end of the text before the gap.
1734 Do this before recording the deletion,
1735 so that undo handles this after reinserting the text. */
1736 adjust_markers_for_delete (from, from_byte, to, to_byte);
1738 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1739 record_delete (from, deletion);
1740 MODIFF++;
1741 CHARS_MODIFF = MODIFF;
1743 /* Relocate point as if it were a marker. */
1744 if (from < PT)
1745 adjust_point (from - (PT < to ? PT : to),
1746 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1748 offset_intervals (current_buffer, from, - nchars_del);
1750 /* Adjust the overlay center as needed. This must be done after
1751 adjusting the markers that bound the overlays. */
1752 adjust_overlays_for_delete (from, nchars_del);
1754 GAP_SIZE += nbytes_del;
1755 ZV_BYTE -= nbytes_del;
1756 Z_BYTE -= nbytes_del;
1757 ZV -= nchars_del;
1758 Z -= nchars_del;
1759 GPT = from;
1760 GPT_BYTE = from_byte;
1761 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1762 /* Put an anchor, unless called from decode_coding_object which
1763 needs to access the previous gap contents. */
1764 *(GPT_ADDR) = 0;
1766 if (GPT_BYTE < GPT)
1767 abort ();
1769 if (GPT - BEG < BEG_UNCHANGED)
1770 BEG_UNCHANGED = GPT - BEG;
1771 if (Z - GPT < END_UNCHANGED)
1772 END_UNCHANGED = Z - GPT;
1774 CHECK_MARKERS ();
1776 evaporate_overlays (from);
1778 return deletion;
1781 /* Call this if you're about to change the region of BUFFER from
1782 character positions START to END. This checks the read-only
1783 properties of the region, calls the necessary modification hooks,
1784 and warns the next redisplay that it should pay attention to that
1785 area.
1787 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1788 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1790 void
1791 modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end,
1792 int preserve_chars_modiff)
1794 struct buffer *old_buffer = current_buffer;
1796 if (buffer != old_buffer)
1797 set_buffer_internal (buffer);
1799 prepare_to_modify_buffer (start, end, NULL);
1801 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
1803 if (MODIFF <= SAVE_MODIFF)
1804 record_first_change ();
1805 MODIFF++;
1806 if (! preserve_chars_modiff)
1807 CHARS_MODIFF = MODIFF;
1809 BVAR (buffer, point_before_scroll) = Qnil;
1811 if (buffer != old_buffer)
1812 set_buffer_internal (old_buffer);
1815 /* Check that it is okay to modify the buffer between START and END,
1816 which are char positions.
1818 Run the before-change-function, if any. If intervals are in use,
1819 verify that the text to be modified is not read-only, and call
1820 any modification properties the text may have.
1822 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1823 by holding its value temporarily in a marker. */
1825 void
1826 prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
1827 ptrdiff_t *preserve_ptr)
1829 struct buffer *base_buffer;
1831 if (!NILP (BVAR (current_buffer, read_only)))
1832 Fbarf_if_buffer_read_only ();
1834 /* Let redisplay consider other windows than selected_window
1835 if modifying another buffer. */
1836 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
1837 ++windows_or_buffers_changed;
1839 if (BUF_INTERVALS (current_buffer) != 0)
1841 if (preserve_ptr)
1843 Lisp_Object preserve_marker;
1844 struct gcpro gcpro1;
1845 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1846 GCPRO1 (preserve_marker);
1847 verify_interval_modification (current_buffer, start, end);
1848 *preserve_ptr = marker_position (preserve_marker);
1849 unchain_marker (XMARKER (preserve_marker));
1850 UNGCPRO;
1852 else
1853 verify_interval_modification (current_buffer, start, end);
1856 /* For indirect buffers, use the base buffer to check clashes. */
1857 if (current_buffer->base_buffer != 0)
1858 base_buffer = current_buffer->base_buffer;
1859 else
1860 base_buffer = current_buffer;
1862 #ifdef CLASH_DETECTION
1863 if (!NILP (BVAR (base_buffer, file_truename))
1864 /* Make binding buffer-file-name to nil effective. */
1865 && !NILP (BVAR (base_buffer, filename))
1866 && SAVE_MODIFF >= MODIFF)
1867 lock_file (BVAR (base_buffer, file_truename));
1868 #else
1869 /* At least warn if this file has changed on disk since it was visited. */
1870 if (!NILP (BVAR (base_buffer, filename))
1871 && SAVE_MODIFF >= MODIFF
1872 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1873 && !NILP (Ffile_exists_p (BVAR (base_buffer, filename))))
1874 call1 (intern ("ask-user-about-supersession-threat"),
1875 BVAR (base_buffer,filename));
1876 #endif /* not CLASH_DETECTION */
1878 /* If `select-active-regions' is non-nil, save the region text. */
1879 if (!NILP (BVAR (current_buffer, mark_active))
1880 && !inhibit_modification_hooks
1881 && XMARKER (BVAR (current_buffer, mark))->buffer
1882 && NILP (Vsaved_region_selection)
1883 && (EQ (Vselect_active_regions, Qonly)
1884 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
1885 : (!NILP (Vselect_active_regions)
1886 && !NILP (Vtransient_mark_mode))))
1888 ptrdiff_t b = XMARKER (BVAR (current_buffer, mark))->charpos;
1889 ptrdiff_t e = PT;
1890 if (b < e)
1891 Vsaved_region_selection = make_buffer_string (b, e, 0);
1892 else if (b > e)
1893 Vsaved_region_selection = make_buffer_string (e, b, 0);
1896 signal_before_change (start, end, preserve_ptr);
1898 if (current_buffer->newline_cache)
1899 invalidate_region_cache (current_buffer,
1900 current_buffer->newline_cache,
1901 start - BEG, Z - end);
1902 if (current_buffer->width_run_cache)
1903 invalidate_region_cache (current_buffer,
1904 current_buffer->width_run_cache,
1905 start - BEG, Z - end);
1907 Vdeactivate_mark = Qt;
1910 /* These macros work with an argument named `preserve_ptr'
1911 and a local variable named `preserve_marker'. */
1913 #define PRESERVE_VALUE \
1914 if (preserve_ptr && NILP (preserve_marker)) \
1915 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1917 #define RESTORE_VALUE \
1918 if (! NILP (preserve_marker)) \
1920 *preserve_ptr = marker_position (preserve_marker); \
1921 unchain_marker (XMARKER (preserve_marker)); \
1924 #define PRESERVE_START_END \
1925 if (NILP (start_marker)) \
1926 start_marker = Fcopy_marker (start, Qnil); \
1927 if (NILP (end_marker)) \
1928 end_marker = Fcopy_marker (end, Qnil);
1930 #define FETCH_START \
1931 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1933 #define FETCH_END \
1934 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1936 /* Set a variable to nil if an error occurred.
1937 Don't change the variable if there was no error.
1938 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
1939 VARIABLE is the variable to maybe set to nil.
1940 NO-ERROR-FLAG is nil if there was an error,
1941 anything else meaning no error (so this function does nothing). */
1942 static Lisp_Object
1943 reset_var_on_error (Lisp_Object val)
1945 if (NILP (XCDR (val)))
1946 Fset (XCAR (val), Qnil);
1947 return Qnil;
1950 /* Signal a change to the buffer immediately before it happens.
1951 START_INT and END_INT are the bounds of the text to be changed.
1953 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1954 by holding its value temporarily in a marker. */
1956 static void
1957 signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int,
1958 ptrdiff_t *preserve_ptr)
1960 Lisp_Object start, end;
1961 Lisp_Object start_marker, end_marker;
1962 Lisp_Object preserve_marker;
1963 struct gcpro gcpro1, gcpro2, gcpro3;
1964 ptrdiff_t count = SPECPDL_INDEX ();
1966 if (inhibit_modification_hooks)
1967 return;
1969 start = make_number (start_int);
1970 end = make_number (end_int);
1971 preserve_marker = Qnil;
1972 start_marker = Qnil;
1973 end_marker = Qnil;
1974 GCPRO3 (preserve_marker, start_marker, end_marker);
1976 specbind (Qinhibit_modification_hooks, Qt);
1978 /* If buffer is unmodified, run a special hook for that case. The
1979 check for Vfirst_change_hook is just a minor optimization. */
1980 if (SAVE_MODIFF >= MODIFF
1981 && !NILP (Vfirst_change_hook))
1983 PRESERVE_VALUE;
1984 PRESERVE_START_END;
1985 Frun_hooks (1, &Qfirst_change_hook);
1988 /* Now run the before-change-functions if any. */
1989 if (!NILP (Vbefore_change_functions))
1991 Lisp_Object args[3];
1992 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
1994 PRESERVE_VALUE;
1995 PRESERVE_START_END;
1997 /* Mark before-change-functions to be reset to nil in case of error. */
1998 record_unwind_protect (reset_var_on_error, rvoe_arg);
2000 /* Actually run the hook functions. */
2001 args[0] = Qbefore_change_functions;
2002 args[1] = FETCH_START;
2003 args[2] = FETCH_END;
2004 Frun_hook_with_args (3, args);
2006 /* There was no error: unarm the reset_on_error. */
2007 XSETCDR (rvoe_arg, Qt);
2010 if (current_buffer->overlays_before || current_buffer->overlays_after)
2012 PRESERVE_VALUE;
2013 report_overlay_modification (FETCH_START, FETCH_END, 0,
2014 FETCH_START, FETCH_END, Qnil);
2017 if (! NILP (start_marker))
2018 free_marker (start_marker);
2019 if (! NILP (end_marker))
2020 free_marker (end_marker);
2021 RESTORE_VALUE;
2022 UNGCPRO;
2024 unbind_to (count, Qnil);
2027 /* Signal a change immediately after it happens.
2028 CHARPOS is the character position of the start of the changed text.
2029 LENDEL is the number of characters of the text before the change.
2030 (Not the whole buffer; just the part that was changed.)
2031 LENINS is the number of characters in that part of the text
2032 after the change. */
2034 void
2035 signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
2037 ptrdiff_t count = SPECPDL_INDEX ();
2038 if (inhibit_modification_hooks)
2039 return;
2041 /* If we are deferring calls to the after-change functions
2042 and there are no before-change functions,
2043 just record the args that we were going to use. */
2044 if (! NILP (Vcombine_after_change_calls)
2045 && NILP (Vbefore_change_functions)
2046 && !current_buffer->overlays_before
2047 && !current_buffer->overlays_after)
2049 Lisp_Object elt;
2051 if (!NILP (combine_after_change_list)
2052 && current_buffer != XBUFFER (combine_after_change_buffer))
2053 Fcombine_after_change_execute ();
2055 elt = Fcons (make_number (charpos - BEG),
2056 Fcons (make_number (Z - (charpos - lendel + lenins)),
2057 Fcons (make_number (lenins - lendel), Qnil)));
2058 combine_after_change_list
2059 = Fcons (elt, combine_after_change_list);
2060 combine_after_change_buffer = Fcurrent_buffer ();
2062 return;
2065 if (!NILP (combine_after_change_list))
2066 Fcombine_after_change_execute ();
2068 specbind (Qinhibit_modification_hooks, Qt);
2070 if (!NILP (Vafter_change_functions))
2072 Lisp_Object args[4];
2073 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2075 /* Mark after-change-functions to be reset to nil in case of error. */
2076 record_unwind_protect (reset_var_on_error, rvoe_arg);
2078 /* Actually run the hook functions. */
2079 args[0] = Qafter_change_functions;
2080 XSETFASTINT (args[1], charpos);
2081 XSETFASTINT (args[2], charpos + lenins);
2082 XSETFASTINT (args[3], lendel);
2083 Frun_hook_with_args (4, args);
2085 /* There was no error: unarm the reset_on_error. */
2086 XSETCDR (rvoe_arg, Qt);
2089 if (current_buffer->overlays_before || current_buffer->overlays_after)
2090 report_overlay_modification (make_number (charpos),
2091 make_number (charpos + lenins),
2093 make_number (charpos),
2094 make_number (charpos + lenins),
2095 make_number (lendel));
2097 /* After an insertion, call the text properties
2098 insert-behind-hooks or insert-in-front-hooks. */
2099 if (lendel == 0)
2100 report_interval_modification (make_number (charpos),
2101 make_number (charpos + lenins));
2103 unbind_to (count, Qnil);
2106 static Lisp_Object
2107 Fcombine_after_change_execute_1 (Lisp_Object val)
2109 Vcombine_after_change_calls = val;
2110 return val;
2113 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2114 Scombine_after_change_execute, 0, 0, 0,
2115 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2116 (void)
2118 ptrdiff_t count = SPECPDL_INDEX ();
2119 ptrdiff_t beg, end, change;
2120 ptrdiff_t begpos, endpos;
2121 Lisp_Object tail;
2123 if (NILP (combine_after_change_list))
2124 return Qnil;
2126 /* It is rare for combine_after_change_buffer to be invalid, but
2127 possible. It can happen when combine-after-change-calls is
2128 non-nil, and insertion calls a file handler (e.g. through
2129 lock_file) which scribbles into a temp file -- cyd */
2130 if (!BUFFERP (combine_after_change_buffer)
2131 || NILP (BVAR (XBUFFER (combine_after_change_buffer), name)))
2133 combine_after_change_list = Qnil;
2134 return Qnil;
2137 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2139 Fset_buffer (combine_after_change_buffer);
2141 /* # chars unchanged at beginning of buffer. */
2142 beg = Z - BEG;
2143 /* # chars unchanged at end of buffer. */
2144 end = beg;
2145 /* Total amount of insertion (negative for deletion). */
2146 change = 0;
2148 /* Scan the various individual changes,
2149 accumulating the range info in BEG, END and CHANGE. */
2150 for (tail = combine_after_change_list; CONSP (tail);
2151 tail = XCDR (tail))
2153 Lisp_Object elt;
2154 ptrdiff_t thisbeg, thisend, thischange;
2156 /* Extract the info from the next element. */
2157 elt = XCAR (tail);
2158 if (! CONSP (elt))
2159 continue;
2160 thisbeg = XINT (XCAR (elt));
2162 elt = XCDR (elt);
2163 if (! CONSP (elt))
2164 continue;
2165 thisend = XINT (XCAR (elt));
2167 elt = XCDR (elt);
2168 if (! CONSP (elt))
2169 continue;
2170 thischange = XINT (XCAR (elt));
2172 /* Merge this range into the accumulated range. */
2173 change += thischange;
2174 if (thisbeg < beg)
2175 beg = thisbeg;
2176 if (thisend < end)
2177 end = thisend;
2180 /* Get the current start and end positions of the range
2181 that was changed. */
2182 begpos = BEG + beg;
2183 endpos = Z - end;
2185 /* We are about to handle these, so discard them. */
2186 combine_after_change_list = Qnil;
2188 /* Now run the after-change functions for real.
2189 Turn off the flag that defers them. */
2190 record_unwind_protect (Fcombine_after_change_execute_1,
2191 Vcombine_after_change_calls);
2192 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2193 update_compositions (begpos, endpos, CHECK_ALL);
2195 return unbind_to (count, Qnil);
2198 void
2199 syms_of_insdel (void)
2201 staticpro (&combine_after_change_list);
2202 staticpro (&combine_after_change_buffer);
2203 combine_after_change_list = Qnil;
2204 combine_after_change_buffer = Qnil;
2206 DEFVAR_BOOL ("check-markers-debug-flag", check_markers_debug_flag,
2207 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
2208 check_markers_debug_flag = 0;
2209 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
2210 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2211 Vcombine_after_change_calls = Qnil;
2213 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
2214 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2215 This affects `before-change-functions' and `after-change-functions',
2216 as well as hooks attached to text properties and overlays. */);
2217 inhibit_modification_hooks = 0;
2218 DEFSYM (Qinhibit_modification_hooks, "inhibit-modification-hooks");
2220 defsubr (&Scombine_after_change_execute);