* insdel.c, lisp.h (buffer_overflow): New function.
[emacs.git] / src / insdel.c
blob875274df8e41000baf5746d5bb76e21119265b7d
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985-1986, 1993-1995, 1997-2011
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 #ifndef NULL
35 #define NULL 0
36 #endif
38 static void insert_from_string_1 (Lisp_Object string,
39 EMACS_INT pos, EMACS_INT pos_byte,
40 EMACS_INT nchars, EMACS_INT nbytes,
41 int inherit, int before_markers);
42 static void insert_from_buffer_1 (struct buffer *buf,
43 EMACS_INT from, EMACS_INT nchars,
44 int inherit);
45 static void gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap);
46 static void gap_right (EMACS_INT charpos, EMACS_INT bytepos);
47 static void adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
48 EMACS_INT to, EMACS_INT to_byte,
49 int before_markers);
50 static void adjust_markers_for_replace (EMACS_INT, EMACS_INT, EMACS_INT,
51 EMACS_INT, EMACS_INT, EMACS_INT);
52 static void adjust_point (EMACS_INT nchars, EMACS_INT nbytes);
54 static Lisp_Object Fcombine_after_change_execute (void);
56 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
57 describing changes which happened while combine_after_change_calls
58 was nonzero. We use this to decide how to call them
59 once the deferral ends.
61 In each element.
62 BEG-UNCHANGED is the number of chars before the changed range.
63 END-UNCHANGED is the number of chars after the changed range,
64 and CHANGE-AMOUNT is the number of characters inserted by the change
65 (negative for a deletion). */
66 static Lisp_Object combine_after_change_list;
68 /* Buffer which combine_after_change_list is about. */
69 static Lisp_Object combine_after_change_buffer;
71 Lisp_Object Qinhibit_modification_hooks;
73 static void signal_before_change (EMACS_INT, EMACS_INT, EMACS_INT *);
75 #define CHECK_MARKERS() \
76 do \
77 { \
78 if (check_markers_debug_flag) \
79 check_markers (); \
80 } \
81 while (0)
83 static void
84 check_markers (void)
86 register struct Lisp_Marker *tail;
87 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
89 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
91 if (tail->buffer->text != current_buffer->text)
92 abort ();
93 if (tail->charpos > Z)
94 abort ();
95 if (tail->bytepos > Z_BYTE)
96 abort ();
97 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
98 abort ();
102 /* Move gap to position CHARPOS.
103 Note that this can quit! */
105 void
106 move_gap (EMACS_INT charpos)
108 move_gap_both (charpos, charpos_to_bytepos (charpos));
111 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
112 Note that this can quit! */
114 void
115 move_gap_both (EMACS_INT charpos, EMACS_INT bytepos)
117 if (bytepos < GPT_BYTE)
118 gap_left (charpos, bytepos, 0);
119 else if (bytepos > GPT_BYTE)
120 gap_right (charpos, bytepos);
123 /* Move the gap to a position less than the current GPT.
124 BYTEPOS describes the new position as a byte position,
125 and CHARPOS is the corresponding char position.
126 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
128 static void
129 gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap)
131 register unsigned char *to, *from;
132 register EMACS_INT i;
133 EMACS_INT new_s1;
135 if (!newgap)
136 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
138 i = GPT_BYTE;
139 to = GAP_END_ADDR;
140 from = GPT_ADDR;
141 new_s1 = GPT_BYTE;
143 /* Now copy the characters. To move the gap down,
144 copy characters up. */
146 while (1)
148 /* I gets number of characters left to copy. */
149 i = new_s1 - bytepos;
150 if (i == 0)
151 break;
152 /* If a quit is requested, stop copying now.
153 Change BYTEPOS to be where we have actually moved the gap to. */
154 if (QUITP)
156 bytepos = new_s1;
157 charpos = BYTE_TO_CHAR (bytepos);
158 break;
160 /* Move at most 32000 chars before checking again for a quit. */
161 if (i > 32000)
162 i = 32000;
163 new_s1 -= i;
164 from -= i, to -= i;
165 memmove (to, from, i);
168 /* Adjust buffer data structure, to put the gap at BYTEPOS.
169 BYTEPOS is where the loop above stopped, which may be what
170 was specified or may be where a quit was detected. */
171 GPT_BYTE = bytepos;
172 GPT = charpos;
173 if (bytepos < charpos)
174 abort ();
175 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
176 QUIT;
179 /* Move the gap to a position greater than the current GPT.
180 BYTEPOS describes the new position as a byte position,
181 and CHARPOS is the corresponding char position. */
183 static void
184 gap_right (EMACS_INT charpos, EMACS_INT bytepos)
186 register unsigned char *to, *from;
187 register EMACS_INT i;
188 EMACS_INT new_s1;
190 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
192 i = GPT_BYTE;
193 from = GAP_END_ADDR;
194 to = GPT_ADDR;
195 new_s1 = GPT_BYTE;
197 /* Now copy the characters. To move the gap up,
198 copy characters down. */
200 while (1)
202 /* I gets number of characters left to copy. */
203 i = bytepos - new_s1;
204 if (i == 0)
205 break;
206 /* If a quit is requested, stop copying now.
207 Change BYTEPOS to be where we have actually moved the gap to. */
208 if (QUITP)
210 bytepos = new_s1;
211 charpos = BYTE_TO_CHAR (bytepos);
212 break;
214 /* Move at most 32000 chars before checking again for a quit. */
215 if (i > 32000)
216 i = 32000;
217 new_s1 += i;
218 memmove (to, from, i);
219 from += i, to += i;
222 GPT = charpos;
223 GPT_BYTE = bytepos;
224 if (bytepos < charpos)
225 abort ();
226 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
227 QUIT;
230 /* Adjust all markers for a deletion
231 whose range in bytes is FROM_BYTE to TO_BYTE.
232 The range in charpos is FROM to TO.
234 This function assumes that the gap is adjacent to
235 or inside of the range being deleted. */
237 void
238 adjust_markers_for_delete (EMACS_INT from, EMACS_INT from_byte,
239 EMACS_INT to, EMACS_INT to_byte)
241 Lisp_Object marker;
242 register struct Lisp_Marker *m;
243 register EMACS_INT charpos;
245 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
247 charpos = m->charpos;
249 if (charpos > Z)
250 abort ();
252 /* If the marker is after the deletion,
253 relocate by number of chars / bytes deleted. */
254 if (charpos > to)
256 m->charpos -= to - from;
257 m->bytepos -= to_byte - from_byte;
259 /* Here's the case where a marker is inside text being deleted. */
260 else if (charpos > from)
262 if (! m->insertion_type)
263 { /* Normal markers will end up at the beginning of the
264 re-inserted text after undoing a deletion, and must be
265 adjusted to move them to the correct place. */
266 XSETMISC (marker, m);
267 record_marker_adjustment (marker, from - charpos);
269 else if (charpos < to)
270 { /* Before-insertion markers will automatically move forward
271 upon re-inserting the deleted text, so we have to arrange
272 for them to move backward to the correct position. */
273 XSETMISC (marker, m);
274 record_marker_adjustment (marker, to - charpos);
276 m->charpos = from;
277 m->bytepos = from_byte;
279 /* Here's the case where a before-insertion marker is immediately
280 before the deleted region. */
281 else if (charpos == from && m->insertion_type)
283 /* Undoing the change uses normal insertion, which will
284 incorrectly make MARKER move forward, so we arrange for it
285 to then move backward to the correct place at the beginning
286 of the deleted region. */
287 XSETMISC (marker, m);
288 record_marker_adjustment (marker, to - from);
294 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
295 to TO / TO_BYTE. We have to relocate the charpos of every marker
296 that points after the insertion (but not their bytepos).
298 When a marker points at the insertion point,
299 we advance it if either its insertion-type is t
300 or BEFORE_MARKERS is true. */
302 static void
303 adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
304 EMACS_INT to, EMACS_INT to_byte, int before_markers)
306 struct Lisp_Marker *m;
307 int adjusted = 0;
308 EMACS_INT nchars = to - from;
309 EMACS_INT nbytes = to_byte - from_byte;
311 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
313 eassert (m->bytepos >= m->charpos
314 && m->bytepos - m->charpos <= Z_BYTE - Z);
316 if (m->bytepos == from_byte)
318 if (m->insertion_type || before_markers)
320 m->bytepos = to_byte;
321 m->charpos = to;
322 if (m->insertion_type)
323 adjusted = 1;
326 else if (m->bytepos > from_byte)
328 m->bytepos += nbytes;
329 m->charpos += nchars;
333 /* Adjusting only markers whose insertion-type is t may result in
334 - disordered start and end in overlays, and
335 - disordered overlays in the slot `overlays_before' of current_buffer. */
336 if (adjusted)
338 fix_start_end_in_overlays(from, to);
339 fix_overlays_before (current_buffer, from, to);
343 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
345 This is used only when the value of point changes due to an insert
346 or delete; it does not represent a conceptual change in point as a
347 marker. In particular, point is not crossing any interval
348 boundaries, so there's no need to use the usual SET_PT macro. In
349 fact it would be incorrect to do so, because either the old or the
350 new value of point is out of sync with the current set of
351 intervals. */
353 static void
354 adjust_point (EMACS_INT nchars, EMACS_INT nbytes)
356 SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes);
357 /* In a single-byte buffer, the two positions must be equal. */
358 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
361 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
362 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
363 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
364 an insertion. */
366 static void
367 adjust_markers_for_replace (EMACS_INT from, EMACS_INT from_byte,
368 EMACS_INT old_chars, EMACS_INT old_bytes,
369 EMACS_INT new_chars, EMACS_INT new_bytes)
371 register struct Lisp_Marker *m;
372 EMACS_INT prev_to_byte = from_byte + old_bytes;
373 EMACS_INT diff_chars = new_chars - old_chars;
374 EMACS_INT diff_bytes = new_bytes - old_bytes;
376 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
378 if (m->bytepos >= prev_to_byte)
380 m->charpos += diff_chars;
381 m->bytepos += diff_bytes;
383 else if (m->bytepos > from_byte)
385 m->charpos = from;
386 m->bytepos = from_byte;
390 CHECK_MARKERS ();
394 void
395 buffer_overflow (void)
397 error ("Maximum buffer size exceeded");
400 /* Make the gap NBYTES_ADDED bytes longer. */
402 static void
403 make_gap_larger (EMACS_INT nbytes_added)
405 Lisp_Object tem;
406 EMACS_INT real_gap_loc;
407 EMACS_INT real_gap_loc_byte;
408 EMACS_INT old_gap_size;
410 /* If we have to get more space, get enough to last a while. */
411 nbytes_added += 2000;
413 { EMACS_INT total_size = Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added;
414 if (total_size < 0
415 /* Don't allow a buffer size that won't fit in a Lisp integer. */
416 || total_size != XINT (make_number (total_size)))
417 buffer_overflow ();
420 enlarge_buffer_text (current_buffer, nbytes_added);
422 /* Prevent quitting in move_gap. */
423 tem = Vinhibit_quit;
424 Vinhibit_quit = Qt;
426 real_gap_loc = GPT;
427 real_gap_loc_byte = GPT_BYTE;
428 old_gap_size = GAP_SIZE;
430 /* Call the newly allocated space a gap at the end of the whole space. */
431 GPT = Z + GAP_SIZE;
432 GPT_BYTE = Z_BYTE + GAP_SIZE;
433 GAP_SIZE = nbytes_added;
435 /* Move the new gap down to be consecutive with the end of the old one.
436 This adjusts the markers properly too. */
437 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
439 /* Now combine the two into one large gap. */
440 GAP_SIZE += old_gap_size;
441 GPT = real_gap_loc;
442 GPT_BYTE = real_gap_loc_byte;
444 /* Put an anchor. */
445 *(Z_ADDR) = 0;
447 Vinhibit_quit = tem;
450 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
452 /* Make the gap NBYTES_REMOVED bytes shorter. */
454 static void
455 make_gap_smaller (EMACS_INT nbytes_removed)
457 Lisp_Object tem;
458 EMACS_INT real_gap_loc;
459 EMACS_INT real_gap_loc_byte;
460 EMACS_INT real_Z;
461 EMACS_INT real_Z_byte;
462 EMACS_INT real_beg_unchanged;
463 EMACS_INT new_gap_size;
465 /* Make sure the gap is at least 20 bytes. */
466 if (GAP_SIZE - nbytes_removed < 20)
467 nbytes_removed = GAP_SIZE - 20;
469 /* Prevent quitting in move_gap. */
470 tem = Vinhibit_quit;
471 Vinhibit_quit = Qt;
473 real_gap_loc = GPT;
474 real_gap_loc_byte = GPT_BYTE;
475 new_gap_size = GAP_SIZE - nbytes_removed;
476 real_Z = Z;
477 real_Z_byte = Z_BYTE;
478 real_beg_unchanged = BEG_UNCHANGED;
480 /* Pretend that the last unwanted part of the gap is the entire gap,
481 and that the first desired part of the gap is part of the buffer
482 text. */
483 memset (GPT_ADDR, 0, new_gap_size);
484 GPT += new_gap_size;
485 GPT_BYTE += new_gap_size;
486 Z += new_gap_size;
487 Z_BYTE += new_gap_size;
488 GAP_SIZE = nbytes_removed;
490 /* Move the unwanted pretend gap to the end of the buffer. This
491 adjusts the markers properly too. */
492 gap_right (Z, Z_BYTE);
494 enlarge_buffer_text (current_buffer, -nbytes_removed);
496 /* Now restore the desired gap. */
497 GAP_SIZE = new_gap_size;
498 GPT = real_gap_loc;
499 GPT_BYTE = real_gap_loc_byte;
500 Z = real_Z;
501 Z_BYTE = real_Z_byte;
502 BEG_UNCHANGED = real_beg_unchanged;
504 /* Put an anchor. */
505 *(Z_ADDR) = 0;
507 Vinhibit_quit = tem;
510 #endif /* USE_MMAP_FOR_BUFFERS || REL_ALLOC || DOUG_LEA_MALLOC */
512 void
513 make_gap (EMACS_INT nbytes_added)
515 if (nbytes_added >= 0)
516 make_gap_larger (nbytes_added);
517 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
518 else
519 make_gap_smaller (-nbytes_added);
520 #endif
523 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
524 FROM_MULTIBYTE says whether the incoming text is multibyte.
525 TO_MULTIBYTE says whether to store the text as multibyte.
526 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
528 Return the number of bytes stored at TO_ADDR. */
530 EMACS_INT
531 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
532 EMACS_INT nbytes, int from_multibyte, int to_multibyte)
534 if (from_multibyte == to_multibyte)
536 memcpy (to_addr, from_addr, nbytes);
537 return nbytes;
539 else if (from_multibyte)
541 EMACS_INT nchars = 0;
542 EMACS_INT bytes_left = nbytes;
544 while (bytes_left > 0)
546 int thislen, c;
547 c = STRING_CHAR_AND_LENGTH (from_addr, thislen);
548 if (! ASCII_CHAR_P (c))
549 c &= 0xFF;
550 *to_addr++ = c;
551 from_addr += thislen;
552 bytes_left -= thislen;
553 nchars++;
555 return nchars;
557 else
559 unsigned char *initial_to_addr = to_addr;
561 /* Convert single-byte to multibyte. */
562 while (nbytes > 0)
564 int c = *from_addr++;
566 if (!ASCII_CHAR_P (c))
568 c = BYTE8_TO_CHAR (c);
569 to_addr += CHAR_STRING (c, to_addr);
570 nbytes--;
572 else
573 /* Special case for speed. */
574 *to_addr++ = c, nbytes--;
576 return to_addr - initial_to_addr;
580 /* Insert a string of specified length before point.
581 This function judges multibyteness based on
582 enable_multibyte_characters in the current buffer;
583 it never converts between single-byte and multibyte.
585 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
586 prepare_to_modify_buffer could relocate the text. */
588 void
589 insert (const char *string, EMACS_INT nbytes)
591 if (nbytes > 0)
593 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
594 insert_1_both (string, len, nbytes, 0, 1, 0);
595 opoint = PT - len;
596 signal_after_change (opoint, 0, len);
597 update_compositions (opoint, PT, CHECK_BORDER);
601 /* Likewise, but inherit text properties from neighboring characters. */
603 void
604 insert_and_inherit (const char *string, EMACS_INT nbytes)
606 if (nbytes > 0)
608 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
609 insert_1_both (string, len, nbytes, 1, 1, 0);
610 opoint = PT - len;
611 signal_after_change (opoint, 0, len);
612 update_compositions (opoint, PT, CHECK_BORDER);
616 /* Insert the character C before point. Do not inherit text properties. */
618 void
619 insert_char (int c)
621 unsigned char str[MAX_MULTIBYTE_LENGTH];
622 int len;
624 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
625 len = CHAR_STRING (c, str);
626 else
628 len = 1;
629 str[0] = c;
632 insert ((char *) str, len);
635 /* Insert the null-terminated string S before point. */
637 void
638 insert_string (const char *s)
640 insert (s, strlen (s));
643 /* Like `insert' except that all markers pointing at the place where
644 the insertion happens are adjusted to point after it.
645 Don't use this function to insert part of a Lisp string,
646 since gc could happen and relocate it. */
648 void
649 insert_before_markers (const char *string, EMACS_INT nbytes)
651 if (nbytes > 0)
653 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
654 insert_1_both (string, len, nbytes, 0, 1, 1);
655 opoint = PT - len;
656 signal_after_change (opoint, 0, len);
657 update_compositions (opoint, PT, CHECK_BORDER);
661 /* Likewise, but inherit text properties from neighboring characters. */
663 void
664 insert_before_markers_and_inherit (const char *string,
665 EMACS_INT nbytes)
667 if (nbytes > 0)
669 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
670 insert_1_both (string, len, nbytes, 1, 1, 1);
671 opoint = PT - len;
672 signal_after_change (opoint, 0, len);
673 update_compositions (opoint, PT, CHECK_BORDER);
677 /* Subroutine used by the insert functions above. */
679 void
680 insert_1 (const char *string, EMACS_INT nbytes,
681 int inherit, int prepare, int before_markers)
683 insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
684 nbytes, inherit, prepare, before_markers);
688 #ifdef BYTE_COMBINING_DEBUG
690 /* See if the bytes before POS/POS_BYTE combine with bytes
691 at the start of STRING to form a single character.
692 If so, return the number of bytes at the start of STRING
693 which combine in this way. Otherwise, return 0. */
696 count_combining_before (const unsigned char *string, EMACS_INT length,
697 EMACS_INT pos, EMACS_INT pos_byte)
699 int len, combining_bytes;
700 const unsigned char *p;
702 if (NILP (current_buffer->enable_multibyte_characters))
703 return 0;
705 /* At first, we can exclude the following cases:
706 (1) STRING[0] can't be a following byte of multibyte sequence.
707 (2) POS is the start of the current buffer.
708 (3) A character before POS is not a multibyte character. */
709 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
710 return 0;
711 if (pos_byte == BEG_BYTE) /* case (2) */
712 return 0;
713 len = 1;
714 p = BYTE_POS_ADDR (pos_byte - 1);
715 while (! CHAR_HEAD_P (*p)) p--, len++;
716 if (! LEADING_CODE_P (*p)) /* case (3) */
717 return 0;
719 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
720 if (combining_bytes <= 0)
721 /* The character preceding POS is, complete and no room for
722 combining bytes (combining_bytes == 0), or an independent 8-bit
723 character (combining_bytes < 0). */
724 return 0;
726 /* We have a combination situation. Count the bytes at STRING that
727 may combine. */
728 p = string + 1;
729 while (!CHAR_HEAD_P (*p) && p < string + length)
730 p++;
732 return (combining_bytes < p - string ? combining_bytes : p - string);
735 /* See if the bytes after POS/POS_BYTE combine with bytes
736 at the end of STRING to form a single character.
737 If so, return the number of bytes after POS/POS_BYTE
738 which combine in this way. Otherwise, return 0. */
741 count_combining_after (const unsigned char *string,
742 EMACS_INT length, EMACS_INT pos, EMACS_INT pos_byte)
744 EMACS_INT opos_byte = pos_byte;
745 EMACS_INT i;
746 EMACS_INT bytes;
747 unsigned char *bufp;
749 if (NILP (current_buffer->enable_multibyte_characters))
750 return 0;
752 /* At first, we can exclude the following cases:
753 (1) The last byte of STRING is an ASCII.
754 (2) POS is the last of the current buffer.
755 (3) A character at POS can't be a following byte of multibyte
756 character. */
757 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
758 return 0;
759 if (pos_byte == Z_BYTE) /* case (2) */
760 return 0;
761 bufp = BYTE_POS_ADDR (pos_byte);
762 if (CHAR_HEAD_P (*bufp)) /* case (3) */
763 return 0;
765 i = length - 1;
766 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
768 i--;
770 if (i < 0)
772 /* All characters in STRING are not character head. We must
773 check also preceding bytes at POS. We are sure that the gap
774 is at POS. */
775 unsigned char *p = BEG_ADDR;
776 i = pos_byte - 2;
777 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
778 i--;
779 if (i < 0 || !LEADING_CODE_P (p[i]))
780 return 0;
782 bytes = BYTES_BY_CHAR_HEAD (p[i]);
783 return (bytes <= pos_byte - 1 - i + length
785 : bytes - (pos_byte - 1 - i + length));
787 if (!LEADING_CODE_P (string[i]))
788 return 0;
790 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
791 bufp++, pos_byte++;
792 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
794 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
797 #endif
800 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
801 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
802 are the same as in insert_1. */
804 void
805 insert_1_both (const char *string,
806 EMACS_INT nchars, EMACS_INT nbytes,
807 int inherit, int prepare, int before_markers)
809 if (nchars == 0)
810 return;
812 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
813 nchars = nbytes;
815 if (prepare)
816 /* Do this before moving and increasing the gap,
817 because the before-change hooks might move the gap
818 or make it smaller. */
819 prepare_to_modify_buffer (PT, PT, NULL);
821 if (PT != GPT)
822 move_gap_both (PT, PT_BYTE);
823 if (GAP_SIZE < nbytes)
824 make_gap (nbytes - GAP_SIZE);
826 #ifdef BYTE_COMBINING_DEBUG
827 if (count_combining_before (string, nbytes, PT, PT_BYTE)
828 || count_combining_after (string, nbytes, PT, PT_BYTE))
829 abort ();
830 #endif
832 /* Record deletion of the surrounding text that combines with
833 the insertion. This, together with recording the insertion,
834 will add up to the right stuff in the undo list. */
835 record_insert (PT, nchars);
836 MODIFF++;
837 CHARS_MODIFF = MODIFF;
839 memcpy (GPT_ADDR, string, nbytes);
841 GAP_SIZE -= nbytes;
842 GPT += nchars;
843 ZV += nchars;
844 Z += nchars;
845 GPT_BYTE += nbytes;
846 ZV_BYTE += nbytes;
847 Z_BYTE += nbytes;
848 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
850 if (GPT_BYTE < GPT)
851 abort ();
853 /* The insert may have been in the unchanged region, so check again. */
854 if (Z - GPT < END_UNCHANGED)
855 END_UNCHANGED = Z - GPT;
857 adjust_overlays_for_insert (PT, nchars);
858 adjust_markers_for_insert (PT, PT_BYTE,
859 PT + nchars, PT_BYTE + nbytes,
860 before_markers);
862 if (BUF_INTERVALS (current_buffer) != 0)
863 offset_intervals (current_buffer, PT, nchars);
865 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
866 set_text_properties (make_number (PT), make_number (PT + nchars),
867 Qnil, Qnil, Qnil);
869 adjust_point (nchars, nbytes);
871 CHECK_MARKERS ();
874 /* Insert the part of the text of STRING, a Lisp object assumed to be
875 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
876 starting at position POS / POS_BYTE. If the text of STRING has properties,
877 copy them into the buffer.
879 It does not work to use `insert' for this, because a GC could happen
880 before we copy the stuff into the buffer, and relocate the string
881 without insert noticing. */
883 void
884 insert_from_string (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
885 EMACS_INT length, EMACS_INT length_byte, int inherit)
887 EMACS_INT opoint = PT;
889 if (SCHARS (string) == 0)
890 return;
892 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
893 inherit, 0);
894 signal_after_change (opoint, 0, PT - opoint);
895 update_compositions (opoint, PT, CHECK_BORDER);
898 /* Like `insert_from_string' except that all markers pointing
899 at the place where the insertion happens are adjusted to point after it. */
901 void
902 insert_from_string_before_markers (Lisp_Object string,
903 EMACS_INT pos, EMACS_INT pos_byte,
904 EMACS_INT length, EMACS_INT length_byte,
905 int inherit)
907 EMACS_INT opoint = PT;
909 if (SCHARS (string) == 0)
910 return;
912 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
913 inherit, 1);
914 signal_after_change (opoint, 0, PT - opoint);
915 update_compositions (opoint, PT, CHECK_BORDER);
918 /* Subroutine of the insertion functions above. */
920 static void
921 insert_from_string_1 (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
922 EMACS_INT nchars, EMACS_INT nbytes,
923 int inherit, int before_markers)
925 struct gcpro gcpro1;
926 EMACS_INT outgoing_nbytes = nbytes;
927 INTERVAL intervals;
929 /* Make OUTGOING_NBYTES describe the text
930 as it will be inserted in this buffer. */
932 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
933 outgoing_nbytes = nchars;
934 else if (! STRING_MULTIBYTE (string))
935 outgoing_nbytes
936 = count_size_as_multibyte (SDATA (string) + pos_byte,
937 nbytes);
939 GCPRO1 (string);
940 /* Do this before moving and increasing the gap,
941 because the before-change hooks might move the gap
942 or make it smaller. */
943 prepare_to_modify_buffer (PT, PT, NULL);
945 if (PT != GPT)
946 move_gap_both (PT, PT_BYTE);
947 if (GAP_SIZE < outgoing_nbytes)
948 make_gap (outgoing_nbytes - GAP_SIZE);
949 UNGCPRO;
951 /* Copy the string text into the buffer, perhaps converting
952 between single-byte and multibyte. */
953 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
954 STRING_MULTIBYTE (string),
955 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
957 #ifdef BYTE_COMBINING_DEBUG
958 /* We have copied text into the gap, but we have not altered
959 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
960 to these functions and get the same results as we would
961 have got earlier on. Meanwhile, PT_ADDR does point to
962 the text that has been stored by copy_text. */
963 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
964 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
965 abort ();
966 #endif
968 record_insert (PT, nchars);
969 MODIFF++;
970 CHARS_MODIFF = MODIFF;
972 GAP_SIZE -= outgoing_nbytes;
973 GPT += nchars;
974 ZV += nchars;
975 Z += nchars;
976 GPT_BYTE += outgoing_nbytes;
977 ZV_BYTE += outgoing_nbytes;
978 Z_BYTE += outgoing_nbytes;
979 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
981 if (GPT_BYTE < GPT)
982 abort ();
984 /* The insert may have been in the unchanged region, so check again. */
985 if (Z - GPT < END_UNCHANGED)
986 END_UNCHANGED = Z - GPT;
988 adjust_overlays_for_insert (PT, nchars);
989 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
990 PT_BYTE + outgoing_nbytes,
991 before_markers);
993 offset_intervals (current_buffer, PT, nchars);
995 intervals = STRING_INTERVALS (string);
996 /* Get the intervals for the part of the string we are inserting. */
997 if (nbytes < SBYTES (string))
998 intervals = copy_intervals (intervals, pos, nchars);
1000 /* Insert those intervals. */
1001 graft_intervals_into_buffer (intervals, PT, nchars,
1002 current_buffer, inherit);
1004 adjust_point (nchars, outgoing_nbytes);
1006 CHECK_MARKERS ();
1009 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1010 starting at GPT_ADDR. */
1012 void
1013 insert_from_gap (EMACS_INT nchars, EMACS_INT nbytes)
1015 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1016 nchars = nbytes;
1018 record_insert (GPT, nchars);
1019 MODIFF++;
1021 GAP_SIZE -= nbytes;
1022 GPT += nchars;
1023 ZV += nchars;
1024 Z += nchars;
1025 GPT_BYTE += nbytes;
1026 ZV_BYTE += nbytes;
1027 Z_BYTE += nbytes;
1028 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1030 if (GPT_BYTE < GPT)
1031 abort ();
1033 adjust_overlays_for_insert (GPT - nchars, nchars);
1034 adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
1035 GPT, GPT_BYTE, 0);
1037 if (BUF_INTERVALS (current_buffer) != 0)
1039 offset_intervals (current_buffer, GPT - nchars, nchars);
1040 graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
1041 current_buffer, 0);
1044 if (GPT - nchars < PT)
1045 adjust_point (nchars, nbytes);
1047 CHECK_MARKERS ();
1050 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1051 current buffer. If the text in BUF has properties, they are absorbed
1052 into the current buffer.
1054 It does not work to use `insert' for this, because a malloc could happen
1055 and relocate BUF's text before the copy happens. */
1057 void
1058 insert_from_buffer (struct buffer *buf,
1059 EMACS_INT charpos, EMACS_INT nchars, int inherit)
1061 EMACS_INT opoint = PT;
1063 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1064 signal_after_change (opoint, 0, PT - opoint);
1065 update_compositions (opoint, PT, CHECK_BORDER);
1068 static void
1069 insert_from_buffer_1 (struct buffer *buf,
1070 EMACS_INT from, EMACS_INT nchars, int inherit)
1072 register Lisp_Object temp;
1073 EMACS_INT chunk, chunk_expanded;
1074 EMACS_INT from_byte = buf_charpos_to_bytepos (buf, from);
1075 EMACS_INT to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1076 EMACS_INT incoming_nbytes = to_byte - from_byte;
1077 EMACS_INT outgoing_nbytes = incoming_nbytes;
1078 INTERVAL intervals;
1080 /* Make OUTGOING_NBYTES describe the text
1081 as it will be inserted in this buffer. */
1083 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1084 outgoing_nbytes = nchars;
1085 else if (NILP (BVAR (buf, enable_multibyte_characters)))
1087 EMACS_INT outgoing_before_gap = 0;
1088 EMACS_INT outgoing_after_gap = 0;
1090 if (from < BUF_GPT (buf))
1092 chunk = BUF_GPT_BYTE (buf) - from_byte;
1093 if (chunk > incoming_nbytes)
1094 chunk = incoming_nbytes;
1095 outgoing_before_gap
1096 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1097 chunk);
1099 else
1100 chunk = 0;
1102 if (chunk < incoming_nbytes)
1103 outgoing_after_gap
1104 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1105 from_byte + chunk),
1106 incoming_nbytes - chunk);
1108 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1111 /* Make sure point-max won't overflow after this insertion. */
1112 XSETINT (temp, outgoing_nbytes + Z);
1113 if (outgoing_nbytes + Z != XINT (temp))
1114 buffer_overflow ();
1116 /* Do this before moving and increasing the gap,
1117 because the before-change hooks might move the gap
1118 or make it smaller. */
1119 prepare_to_modify_buffer (PT, PT, NULL);
1121 if (PT != GPT)
1122 move_gap_both (PT, PT_BYTE);
1123 if (GAP_SIZE < outgoing_nbytes)
1124 make_gap (outgoing_nbytes - GAP_SIZE);
1126 if (from < BUF_GPT (buf))
1128 chunk = BUF_GPT_BYTE (buf) - from_byte;
1129 if (chunk > incoming_nbytes)
1130 chunk = incoming_nbytes;
1131 /* Record number of output bytes, so we know where
1132 to put the output from the second copy_text. */
1133 chunk_expanded
1134 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1135 GPT_ADDR, chunk,
1136 ! NILP (BVAR (buf, enable_multibyte_characters)),
1137 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1139 else
1140 chunk_expanded = chunk = 0;
1142 if (chunk < incoming_nbytes)
1143 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1144 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1145 ! NILP (BVAR (buf, enable_multibyte_characters)),
1146 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1148 #ifdef BYTE_COMBINING_DEBUG
1149 /* We have copied text into the gap, but we have not altered
1150 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1151 to these functions and get the same results as we would
1152 have got earlier on. Meanwhile, GPT_ADDR does point to
1153 the text that has been stored by copy_text. */
1154 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1155 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1156 abort ();
1157 #endif
1159 record_insert (PT, nchars);
1160 MODIFF++;
1161 CHARS_MODIFF = MODIFF;
1163 GAP_SIZE -= outgoing_nbytes;
1164 GPT += nchars;
1165 ZV += nchars;
1166 Z += nchars;
1167 GPT_BYTE += outgoing_nbytes;
1168 ZV_BYTE += outgoing_nbytes;
1169 Z_BYTE += outgoing_nbytes;
1170 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1172 if (GPT_BYTE < GPT)
1173 abort ();
1175 /* The insert may have been in the unchanged region, so check again. */
1176 if (Z - GPT < END_UNCHANGED)
1177 END_UNCHANGED = Z - GPT;
1179 adjust_overlays_for_insert (PT, nchars);
1180 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1181 PT_BYTE + outgoing_nbytes,
1184 if (BUF_INTERVALS (current_buffer) != 0)
1185 offset_intervals (current_buffer, PT, nchars);
1187 /* Get the intervals for the part of the string we are inserting. */
1188 intervals = BUF_INTERVALS (buf);
1189 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1191 if (buf == current_buffer && PT <= from)
1192 from += nchars;
1193 intervals = copy_intervals (intervals, from, nchars);
1196 /* Insert those intervals. */
1197 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1199 adjust_point (nchars, outgoing_nbytes);
1202 /* Record undo information and adjust markers and position keepers for
1203 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1204 chars (LEN_BYTE bytes) which resides in the gap just after
1205 GPT_ADDR.
1207 PREV_TEXT nil means the new text was just inserted. */
1209 static void
1210 adjust_after_replace (EMACS_INT from, EMACS_INT from_byte,
1211 Lisp_Object prev_text, EMACS_INT len, EMACS_INT len_byte)
1213 EMACS_INT nchars_del = 0, nbytes_del = 0;
1215 #ifdef BYTE_COMBINING_DEBUG
1216 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1217 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1218 abort ();
1219 #endif
1221 if (STRINGP (prev_text))
1223 nchars_del = SCHARS (prev_text);
1224 nbytes_del = SBYTES (prev_text);
1227 /* Update various buffer positions for the new text. */
1228 GAP_SIZE -= len_byte;
1229 ZV += len; Z+= len;
1230 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1231 GPT += len; GPT_BYTE += len_byte;
1232 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1234 if (nchars_del > 0)
1235 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1236 len, len_byte);
1237 else
1238 adjust_markers_for_insert (from, from_byte,
1239 from + len, from_byte + len_byte, 0);
1241 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1243 if (nchars_del > 0)
1244 record_delete (from, prev_text);
1245 record_insert (from, len);
1248 if (len > nchars_del)
1249 adjust_overlays_for_insert (from, len - nchars_del);
1250 else if (len < nchars_del)
1251 adjust_overlays_for_delete (from, nchars_del - len);
1252 if (BUF_INTERVALS (current_buffer) != 0)
1254 offset_intervals (current_buffer, from, len - nchars_del);
1257 if (from < PT)
1258 adjust_point (len - nchars_del, len_byte - nbytes_del);
1260 /* As byte combining will decrease Z, we must check this again. */
1261 if (Z - GPT < END_UNCHANGED)
1262 END_UNCHANGED = Z - GPT;
1264 CHECK_MARKERS ();
1266 if (len == 0)
1267 evaporate_overlays (from);
1268 MODIFF++;
1269 CHARS_MODIFF = MODIFF;
1272 /* Record undo information, adjust markers and position keepers for an
1273 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1274 text already exists in the current buffer but character length (TO
1275 - FROM) may be incorrect, the correct length is NEWLEN. */
1277 void
1278 adjust_after_insert (EMACS_INT from, EMACS_INT from_byte,
1279 EMACS_INT to, EMACS_INT to_byte, EMACS_INT newlen)
1281 EMACS_INT len = to - from, len_byte = to_byte - from_byte;
1283 if (GPT != to)
1284 move_gap_both (to, to_byte);
1285 GAP_SIZE += len_byte;
1286 GPT -= len; GPT_BYTE -= len_byte;
1287 ZV -= len; ZV_BYTE -= len_byte;
1288 Z -= len; Z_BYTE -= len_byte;
1289 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1292 /* Replace the text from character positions FROM to TO with NEW,
1293 If PREPARE is nonzero, call prepare_to_modify_buffer.
1294 If INHERIT, the newly inserted text should inherit text properties
1295 from the surrounding non-deleted text. */
1297 /* Note that this does not yet handle markers quite right.
1298 Also it needs to record a single undo-entry that does a replacement
1299 rather than a separate delete and insert.
1300 That way, undo will also handle markers properly.
1302 But if MARKERS is 0, don't relocate markers. */
1304 void
1305 replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
1306 int prepare, int inherit, int markers)
1308 EMACS_INT inschars = SCHARS (new);
1309 EMACS_INT insbytes = SBYTES (new);
1310 EMACS_INT from_byte, to_byte;
1311 EMACS_INT nbytes_del, nchars_del;
1312 register Lisp_Object temp;
1313 struct gcpro gcpro1;
1314 INTERVAL intervals;
1315 EMACS_INT outgoing_insbytes = insbytes;
1316 Lisp_Object deletion;
1318 CHECK_MARKERS ();
1320 GCPRO1 (new);
1321 deletion = Qnil;
1323 if (prepare)
1325 EMACS_INT range_length = to - from;
1326 prepare_to_modify_buffer (from, to, &from);
1327 to = from + range_length;
1330 UNGCPRO;
1332 /* Make args be valid */
1333 if (from < BEGV)
1334 from = BEGV;
1335 if (to > ZV)
1336 to = ZV;
1338 from_byte = CHAR_TO_BYTE (from);
1339 to_byte = CHAR_TO_BYTE (to);
1341 nchars_del = to - from;
1342 nbytes_del = to_byte - from_byte;
1344 if (nbytes_del <= 0 && insbytes == 0)
1345 return;
1347 /* Make OUTGOING_INSBYTES describe the text
1348 as it will be inserted in this buffer. */
1350 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1351 outgoing_insbytes = inschars;
1352 else if (! STRING_MULTIBYTE (new))
1353 outgoing_insbytes
1354 = count_size_as_multibyte (SDATA (new), insbytes);
1356 /* Make sure point-max won't overflow after this insertion. */
1357 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1358 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1359 buffer_overflow ();
1361 GCPRO1 (new);
1363 /* Make sure the gap is somewhere in or next to what we are deleting. */
1364 if (from > GPT)
1365 gap_right (from, from_byte);
1366 if (to < GPT)
1367 gap_left (to, to_byte, 0);
1369 /* Even if we don't record for undo, we must keep the original text
1370 because we may have to recover it because of inappropriate byte
1371 combining. */
1372 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1373 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1375 GAP_SIZE += nbytes_del;
1376 ZV -= nchars_del;
1377 Z -= nchars_del;
1378 ZV_BYTE -= nbytes_del;
1379 Z_BYTE -= nbytes_del;
1380 GPT = from;
1381 GPT_BYTE = from_byte;
1382 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1384 if (GPT_BYTE < GPT)
1385 abort ();
1387 if (GPT - BEG < BEG_UNCHANGED)
1388 BEG_UNCHANGED = GPT - BEG;
1389 if (Z - GPT < END_UNCHANGED)
1390 END_UNCHANGED = Z - GPT;
1392 if (GAP_SIZE < insbytes)
1393 make_gap (insbytes - GAP_SIZE);
1395 /* Copy the string text into the buffer, perhaps converting
1396 between single-byte and multibyte. */
1397 copy_text (SDATA (new), GPT_ADDR, insbytes,
1398 STRING_MULTIBYTE (new),
1399 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1401 #ifdef BYTE_COMBINING_DEBUG
1402 /* We have copied text into the gap, but we have not marked
1403 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1404 here, for both the previous text and the following text.
1405 Meanwhile, GPT_ADDR does point to
1406 the text that has been stored by copy_text. */
1407 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1408 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1409 abort ();
1410 #endif
1412 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1414 /* Record the insertion first, so that when we undo,
1415 the deletion will be undone first. Thus, undo
1416 will insert before deleting, and thus will keep
1417 the markers before and after this text separate. */
1418 record_insert (from + SCHARS (deletion), inschars);
1419 record_delete (from, deletion);
1422 GAP_SIZE -= outgoing_insbytes;
1423 GPT += inschars;
1424 ZV += inschars;
1425 Z += inschars;
1426 GPT_BYTE += outgoing_insbytes;
1427 ZV_BYTE += outgoing_insbytes;
1428 Z_BYTE += outgoing_insbytes;
1429 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1431 if (GPT_BYTE < GPT)
1432 abort ();
1434 /* Adjust the overlay center as needed. This must be done after
1435 adjusting the markers that bound the overlays. */
1436 adjust_overlays_for_delete (from, nchars_del);
1437 adjust_overlays_for_insert (from, inschars);
1439 /* Adjust markers for the deletion and the insertion. */
1440 if (markers)
1441 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1442 inschars, outgoing_insbytes);
1444 offset_intervals (current_buffer, from, inschars - nchars_del);
1446 /* Get the intervals for the part of the string we are inserting--
1447 not including the combined-before bytes. */
1448 intervals = STRING_INTERVALS (new);
1449 /* Insert those intervals. */
1450 graft_intervals_into_buffer (intervals, from, inschars,
1451 current_buffer, inherit);
1453 /* Relocate point as if it were a marker. */
1454 if (from < PT)
1455 adjust_point ((from + inschars - (PT < to ? PT : to)),
1456 (from_byte + outgoing_insbytes
1457 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1459 if (outgoing_insbytes == 0)
1460 evaporate_overlays (from);
1462 CHECK_MARKERS ();
1464 MODIFF++;
1465 CHARS_MODIFF = MODIFF;
1466 UNGCPRO;
1468 signal_after_change (from, nchars_del, GPT - from);
1469 update_compositions (from, GPT, CHECK_BORDER);
1472 /* Replace the text from character positions FROM to TO with
1473 the text in INS of length INSCHARS.
1474 Keep the text properties that applied to the old characters
1475 (extending them to all the new chars if there are more new chars).
1477 Note that this does not yet handle markers quite right.
1479 If MARKERS is nonzero, relocate markers.
1481 Unlike most functions at this level, never call
1482 prepare_to_modify_buffer and never call signal_after_change. */
1484 void
1485 replace_range_2 (EMACS_INT from, EMACS_INT from_byte,
1486 EMACS_INT to, EMACS_INT to_byte,
1487 const char *ins, EMACS_INT inschars, EMACS_INT insbytes,
1488 int markers)
1490 EMACS_INT nbytes_del, nchars_del;
1491 Lisp_Object temp;
1493 CHECK_MARKERS ();
1495 nchars_del = to - from;
1496 nbytes_del = to_byte - from_byte;
1498 if (nbytes_del <= 0 && insbytes == 0)
1499 return;
1501 /* Make sure point-max won't overflow after this insertion. */
1502 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1503 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1504 buffer_overflow ();
1506 /* Make sure the gap is somewhere in or next to what we are deleting. */
1507 if (from > GPT)
1508 gap_right (from, from_byte);
1509 if (to < GPT)
1510 gap_left (to, to_byte, 0);
1512 GAP_SIZE += nbytes_del;
1513 ZV -= nchars_del;
1514 Z -= nchars_del;
1515 ZV_BYTE -= nbytes_del;
1516 Z_BYTE -= nbytes_del;
1517 GPT = from;
1518 GPT_BYTE = from_byte;
1519 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1521 if (GPT_BYTE < GPT)
1522 abort ();
1524 if (GPT - BEG < BEG_UNCHANGED)
1525 BEG_UNCHANGED = GPT - BEG;
1526 if (Z - GPT < END_UNCHANGED)
1527 END_UNCHANGED = Z - GPT;
1529 if (GAP_SIZE < insbytes)
1530 make_gap (insbytes - GAP_SIZE);
1532 /* Copy the replacement text into the buffer. */
1533 memcpy (GPT_ADDR, ins, insbytes);
1535 #ifdef BYTE_COMBINING_DEBUG
1536 /* We have copied text into the gap, but we have not marked
1537 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1538 here, for both the previous text and the following text.
1539 Meanwhile, GPT_ADDR does point to
1540 the text that has been stored by copy_text. */
1541 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1542 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1543 abort ();
1544 #endif
1546 GAP_SIZE -= insbytes;
1547 GPT += inschars;
1548 ZV += inschars;
1549 Z += inschars;
1550 GPT_BYTE += insbytes;
1551 ZV_BYTE += insbytes;
1552 Z_BYTE += insbytes;
1553 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1555 if (GPT_BYTE < GPT)
1556 abort ();
1558 /* Adjust the overlay center as needed. This must be done after
1559 adjusting the markers that bound the overlays. */
1560 if (nchars_del != inschars)
1562 adjust_overlays_for_insert (from, inschars);
1563 adjust_overlays_for_delete (from + inschars, nchars_del);
1566 /* Adjust markers for the deletion and the insertion. */
1567 if (markers
1568 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1569 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1570 inschars, insbytes);
1572 offset_intervals (current_buffer, from, inschars - nchars_del);
1574 /* Relocate point as if it were a marker. */
1575 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1577 if (PT < to)
1578 /* PT was within the deleted text. Move it to FROM. */
1579 adjust_point (from - PT, from_byte - PT_BYTE);
1580 else
1581 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1584 if (insbytes == 0)
1585 evaporate_overlays (from);
1587 CHECK_MARKERS ();
1589 MODIFF++;
1590 CHARS_MODIFF = MODIFF;
1593 /* Delete characters in current buffer
1594 from FROM up to (but not including) TO.
1595 If TO comes before FROM, we delete nothing. */
1597 void
1598 del_range (EMACS_INT from, EMACS_INT to)
1600 del_range_1 (from, to, 1, 0);
1603 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1604 RET_STRING says to return the deleted text. */
1606 Lisp_Object
1607 del_range_1 (EMACS_INT from, EMACS_INT to, int prepare, int ret_string)
1609 EMACS_INT from_byte, to_byte;
1610 Lisp_Object deletion;
1611 struct gcpro gcpro1;
1613 /* Make args be valid */
1614 if (from < BEGV)
1615 from = BEGV;
1616 if (to > ZV)
1617 to = ZV;
1619 if (to <= from)
1620 return Qnil;
1622 if (prepare)
1624 EMACS_INT range_length = to - from;
1625 prepare_to_modify_buffer (from, to, &from);
1626 to = min (ZV, from + range_length);
1629 from_byte = CHAR_TO_BYTE (from);
1630 to_byte = CHAR_TO_BYTE (to);
1632 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1633 GCPRO1(deletion);
1634 signal_after_change (from, to - from, 0);
1635 update_compositions (from, from, CHECK_HEAD);
1636 UNGCPRO;
1637 return deletion;
1640 /* Like del_range_1 but args are byte positions, not char positions. */
1642 void
1643 del_range_byte (EMACS_INT from_byte, EMACS_INT to_byte, int prepare)
1645 EMACS_INT from, to;
1647 /* Make args be valid */
1648 if (from_byte < BEGV_BYTE)
1649 from_byte = BEGV_BYTE;
1650 if (to_byte > ZV_BYTE)
1651 to_byte = ZV_BYTE;
1653 if (to_byte <= from_byte)
1654 return;
1656 from = BYTE_TO_CHAR (from_byte);
1657 to = BYTE_TO_CHAR (to_byte);
1659 if (prepare)
1661 EMACS_INT old_from = from, old_to = Z - to;
1662 EMACS_INT range_length = to - from;
1663 prepare_to_modify_buffer (from, to, &from);
1664 to = from + range_length;
1666 if (old_from != from)
1667 from_byte = CHAR_TO_BYTE (from);
1668 if (to > ZV)
1670 to = ZV;
1671 to_byte = ZV_BYTE;
1673 else if (old_to == Z - to)
1674 to_byte = CHAR_TO_BYTE (to);
1677 del_range_2 (from, from_byte, to, to_byte, 0);
1678 signal_after_change (from, to - from, 0);
1679 update_compositions (from, from, CHECK_HEAD);
1682 /* Like del_range_1, but positions are specified both as charpos
1683 and bytepos. */
1685 void
1686 del_range_both (EMACS_INT from, EMACS_INT from_byte,
1687 EMACS_INT to, EMACS_INT to_byte, int prepare)
1689 /* Make args be valid */
1690 if (from_byte < BEGV_BYTE)
1691 from_byte = BEGV_BYTE;
1692 if (to_byte > ZV_BYTE)
1693 to_byte = ZV_BYTE;
1695 if (to_byte <= from_byte)
1696 return;
1698 if (from < BEGV)
1699 from = BEGV;
1700 if (to > ZV)
1701 to = ZV;
1703 if (prepare)
1705 EMACS_INT old_from = from, old_to = Z - to;
1706 EMACS_INT range_length = to - from;
1707 prepare_to_modify_buffer (from, to, &from);
1708 to = from + range_length;
1710 if (old_from != from)
1711 from_byte = CHAR_TO_BYTE (from);
1712 if (to > ZV)
1714 to = ZV;
1715 to_byte = ZV_BYTE;
1717 else if (old_to == Z - to)
1718 to_byte = CHAR_TO_BYTE (to);
1721 del_range_2 (from, from_byte, to, to_byte, 0);
1722 signal_after_change (from, to - from, 0);
1723 update_compositions (from, from, CHECK_HEAD);
1726 /* Delete a range of text, specified both as character positions
1727 and byte positions. FROM and TO are character positions,
1728 while FROM_BYTE and TO_BYTE are byte positions.
1729 If RET_STRING is true, the deleted area is returned as a string. */
1731 Lisp_Object
1732 del_range_2 (EMACS_INT from, EMACS_INT from_byte,
1733 EMACS_INT to, EMACS_INT to_byte, int ret_string)
1735 register EMACS_INT nbytes_del, nchars_del;
1736 Lisp_Object deletion;
1738 CHECK_MARKERS ();
1740 nchars_del = to - from;
1741 nbytes_del = to_byte - from_byte;
1743 /* Make sure the gap is somewhere in or next to what we are deleting. */
1744 if (from > GPT)
1745 gap_right (from, from_byte);
1746 if (to < GPT)
1747 gap_left (to, to_byte, 0);
1749 #ifdef BYTE_COMBINING_DEBUG
1750 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1751 Z_BYTE - to_byte, from, from_byte))
1752 abort ();
1753 #endif
1755 if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
1756 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1757 else
1758 deletion = Qnil;
1760 /* Relocate all markers pointing into the new, larger gap
1761 to point at the end of the text before the gap.
1762 Do this before recording the deletion,
1763 so that undo handles this after reinserting the text. */
1764 adjust_markers_for_delete (from, from_byte, to, to_byte);
1766 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1767 record_delete (from, deletion);
1768 MODIFF++;
1769 CHARS_MODIFF = MODIFF;
1771 /* Relocate point as if it were a marker. */
1772 if (from < PT)
1773 adjust_point (from - (PT < to ? PT : to),
1774 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1776 offset_intervals (current_buffer, from, - nchars_del);
1778 /* Adjust the overlay center as needed. This must be done after
1779 adjusting the markers that bound the overlays. */
1780 adjust_overlays_for_delete (from, nchars_del);
1782 GAP_SIZE += nbytes_del;
1783 ZV_BYTE -= nbytes_del;
1784 Z_BYTE -= nbytes_del;
1785 ZV -= nchars_del;
1786 Z -= nchars_del;
1787 GPT = from;
1788 GPT_BYTE = from_byte;
1789 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1790 /* Put an anchor, unless called from decode_coding_object which
1791 needs to access the previous gap contents. */
1792 *(GPT_ADDR) = 0;
1794 if (GPT_BYTE < GPT)
1795 abort ();
1797 if (GPT - BEG < BEG_UNCHANGED)
1798 BEG_UNCHANGED = GPT - BEG;
1799 if (Z - GPT < END_UNCHANGED)
1800 END_UNCHANGED = Z - GPT;
1802 CHECK_MARKERS ();
1804 evaporate_overlays (from);
1806 return deletion;
1809 /* Call this if you're about to change the region of BUFFER from
1810 character positions START to END. This checks the read-only
1811 properties of the region, calls the necessary modification hooks,
1812 and warns the next redisplay that it should pay attention to that
1813 area.
1815 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1816 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1818 void
1819 modify_region (struct buffer *buffer, EMACS_INT start, EMACS_INT end,
1820 int preserve_chars_modiff)
1822 struct buffer *old_buffer = current_buffer;
1824 if (buffer != old_buffer)
1825 set_buffer_internal (buffer);
1827 prepare_to_modify_buffer (start, end, NULL);
1829 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
1831 if (MODIFF <= SAVE_MODIFF)
1832 record_first_change ();
1833 MODIFF++;
1834 if (! preserve_chars_modiff)
1835 CHARS_MODIFF = MODIFF;
1837 BVAR (buffer, point_before_scroll) = Qnil;
1839 if (buffer != old_buffer)
1840 set_buffer_internal (old_buffer);
1843 /* Check that it is okay to modify the buffer between START and END,
1844 which are char positions.
1846 Run the before-change-function, if any. If intervals are in use,
1847 verify that the text to be modified is not read-only, and call
1848 any modification properties the text may have.
1850 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1851 by holding its value temporarily in a marker. */
1853 void
1854 prepare_to_modify_buffer (EMACS_INT start, EMACS_INT end,
1855 EMACS_INT *preserve_ptr)
1857 struct buffer *base_buffer;
1859 if (!NILP (BVAR (current_buffer, read_only)))
1860 Fbarf_if_buffer_read_only ();
1862 /* Let redisplay consider other windows than selected_window
1863 if modifying another buffer. */
1864 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
1865 ++windows_or_buffers_changed;
1867 if (BUF_INTERVALS (current_buffer) != 0)
1869 if (preserve_ptr)
1871 Lisp_Object preserve_marker;
1872 struct gcpro gcpro1;
1873 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1874 GCPRO1 (preserve_marker);
1875 verify_interval_modification (current_buffer, start, end);
1876 *preserve_ptr = marker_position (preserve_marker);
1877 unchain_marker (XMARKER (preserve_marker));
1878 UNGCPRO;
1880 else
1881 verify_interval_modification (current_buffer, start, end);
1884 /* For indirect buffers, use the base buffer to check clashes. */
1885 if (current_buffer->base_buffer != 0)
1886 base_buffer = current_buffer->base_buffer;
1887 else
1888 base_buffer = current_buffer;
1890 #ifdef CLASH_DETECTION
1891 if (!NILP (BVAR (base_buffer, file_truename))
1892 /* Make binding buffer-file-name to nil effective. */
1893 && !NILP (BVAR (base_buffer, filename))
1894 && SAVE_MODIFF >= MODIFF)
1895 lock_file (BVAR (base_buffer, file_truename));
1896 #else
1897 /* At least warn if this file has changed on disk since it was visited. */
1898 if (!NILP (BVAR (base_buffer, filename))
1899 && SAVE_MODIFF >= MODIFF
1900 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1901 && !NILP (Ffile_exists_p (BVAR (base_buffer, filename))))
1902 call1 (intern ("ask-user-about-supersession-threat"),
1903 BVAR (base_buffer,filename));
1904 #endif /* not CLASH_DETECTION */
1906 /* If `select-active-regions' is non-nil, save the region text. */
1907 if (!NILP (BVAR (current_buffer, mark_active))
1908 && !inhibit_modification_hooks
1909 && XMARKER (BVAR (current_buffer, mark))->buffer
1910 && NILP (Vsaved_region_selection)
1911 && (EQ (Vselect_active_regions, Qonly)
1912 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
1913 : (!NILP (Vselect_active_regions)
1914 && !NILP (Vtransient_mark_mode))))
1916 EMACS_INT b = XMARKER (BVAR (current_buffer, mark))->charpos;
1917 EMACS_INT e = PT;
1918 if (b < e)
1919 Vsaved_region_selection = make_buffer_string (b, e, 0);
1920 else if (b > e)
1921 Vsaved_region_selection = make_buffer_string (e, b, 0);
1924 signal_before_change (start, end, preserve_ptr);
1926 if (current_buffer->newline_cache)
1927 invalidate_region_cache (current_buffer,
1928 current_buffer->newline_cache,
1929 start - BEG, Z - end);
1930 if (current_buffer->width_run_cache)
1931 invalidate_region_cache (current_buffer,
1932 current_buffer->width_run_cache,
1933 start - BEG, Z - end);
1935 Vdeactivate_mark = Qt;
1938 /* These macros work with an argument named `preserve_ptr'
1939 and a local variable named `preserve_marker'. */
1941 #define PRESERVE_VALUE \
1942 if (preserve_ptr && NILP (preserve_marker)) \
1943 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1945 #define RESTORE_VALUE \
1946 if (! NILP (preserve_marker)) \
1948 *preserve_ptr = marker_position (preserve_marker); \
1949 unchain_marker (XMARKER (preserve_marker)); \
1952 #define PRESERVE_START_END \
1953 if (NILP (start_marker)) \
1954 start_marker = Fcopy_marker (start, Qnil); \
1955 if (NILP (end_marker)) \
1956 end_marker = Fcopy_marker (end, Qnil);
1958 #define FETCH_START \
1959 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1961 #define FETCH_END \
1962 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1964 /* Set a variable to nil if an error occurred.
1965 Don't change the variable if there was no error.
1966 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
1967 VARIABLE is the variable to maybe set to nil.
1968 NO-ERROR-FLAG is nil if there was an error,
1969 anything else meaning no error (so this function does nothing). */
1970 static Lisp_Object
1971 reset_var_on_error (Lisp_Object val)
1973 if (NILP (XCDR (val)))
1974 Fset (XCAR (val), Qnil);
1975 return Qnil;
1978 /* Signal a change to the buffer immediately before it happens.
1979 START_INT and END_INT are the bounds of the text to be changed.
1981 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1982 by holding its value temporarily in a marker. */
1984 static void
1985 signal_before_change (EMACS_INT start_int, EMACS_INT end_int,
1986 EMACS_INT *preserve_ptr)
1988 Lisp_Object start, end;
1989 Lisp_Object start_marker, end_marker;
1990 Lisp_Object preserve_marker;
1991 struct gcpro gcpro1, gcpro2, gcpro3;
1992 int count = SPECPDL_INDEX ();
1994 if (inhibit_modification_hooks)
1995 return;
1997 start = make_number (start_int);
1998 end = make_number (end_int);
1999 preserve_marker = Qnil;
2000 start_marker = Qnil;
2001 end_marker = Qnil;
2002 GCPRO3 (preserve_marker, start_marker, end_marker);
2004 specbind (Qinhibit_modification_hooks, Qt);
2006 /* If buffer is unmodified, run a special hook for that case. The
2007 check for Vfirst_change_hook is just a minor optimization. */
2008 if (SAVE_MODIFF >= MODIFF
2009 && !NILP (Vfirst_change_hook))
2011 PRESERVE_VALUE;
2012 PRESERVE_START_END;
2013 Frun_hooks (1, &Qfirst_change_hook);
2016 /* Now run the before-change-functions if any. */
2017 if (!NILP (Vbefore_change_functions))
2019 Lisp_Object args[3];
2020 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
2022 PRESERVE_VALUE;
2023 PRESERVE_START_END;
2025 /* Mark before-change-functions to be reset to nil in case of error. */
2026 record_unwind_protect (reset_var_on_error, rvoe_arg);
2028 /* Actually run the hook functions. */
2029 args[0] = Qbefore_change_functions;
2030 args[1] = FETCH_START;
2031 args[2] = FETCH_END;
2032 Frun_hook_with_args (3, args);
2034 /* There was no error: unarm the reset_on_error. */
2035 XSETCDR (rvoe_arg, Qt);
2038 if (current_buffer->overlays_before || current_buffer->overlays_after)
2040 PRESERVE_VALUE;
2041 report_overlay_modification (FETCH_START, FETCH_END, 0,
2042 FETCH_START, FETCH_END, Qnil);
2045 if (! NILP (start_marker))
2046 free_marker (start_marker);
2047 if (! NILP (end_marker))
2048 free_marker (end_marker);
2049 RESTORE_VALUE;
2050 UNGCPRO;
2052 unbind_to (count, Qnil);
2055 /* Signal a change immediately after it happens.
2056 CHARPOS is the character position of the start of the changed text.
2057 LENDEL is the number of characters of the text before the change.
2058 (Not the whole buffer; just the part that was changed.)
2059 LENINS is the number of characters in that part of the text
2060 after the change. */
2062 void
2063 signal_after_change (EMACS_INT charpos, EMACS_INT lendel, EMACS_INT lenins)
2065 int count = SPECPDL_INDEX ();
2066 if (inhibit_modification_hooks)
2067 return;
2069 /* If we are deferring calls to the after-change functions
2070 and there are no before-change functions,
2071 just record the args that we were going to use. */
2072 if (! NILP (Vcombine_after_change_calls)
2073 && NILP (Vbefore_change_functions)
2074 && !current_buffer->overlays_before
2075 && !current_buffer->overlays_after)
2077 Lisp_Object elt;
2079 if (!NILP (combine_after_change_list)
2080 && current_buffer != XBUFFER (combine_after_change_buffer))
2081 Fcombine_after_change_execute ();
2083 elt = Fcons (make_number (charpos - BEG),
2084 Fcons (make_number (Z - (charpos - lendel + lenins)),
2085 Fcons (make_number (lenins - lendel), Qnil)));
2086 combine_after_change_list
2087 = Fcons (elt, combine_after_change_list);
2088 combine_after_change_buffer = Fcurrent_buffer ();
2090 return;
2093 if (!NILP (combine_after_change_list))
2094 Fcombine_after_change_execute ();
2096 specbind (Qinhibit_modification_hooks, Qt);
2098 if (!NILP (Vafter_change_functions))
2100 Lisp_Object args[4];
2101 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2103 /* Mark after-change-functions to be reset to nil in case of error. */
2104 record_unwind_protect (reset_var_on_error, rvoe_arg);
2106 /* Actually run the hook functions. */
2107 args[0] = Qafter_change_functions;
2108 XSETFASTINT (args[1], charpos);
2109 XSETFASTINT (args[2], charpos + lenins);
2110 XSETFASTINT (args[3], lendel);
2111 Frun_hook_with_args (4, args);
2113 /* There was no error: unarm the reset_on_error. */
2114 XSETCDR (rvoe_arg, Qt);
2117 if (current_buffer->overlays_before || current_buffer->overlays_after)
2118 report_overlay_modification (make_number (charpos),
2119 make_number (charpos + lenins),
2121 make_number (charpos),
2122 make_number (charpos + lenins),
2123 make_number (lendel));
2125 /* After an insertion, call the text properties
2126 insert-behind-hooks or insert-in-front-hooks. */
2127 if (lendel == 0)
2128 report_interval_modification (make_number (charpos),
2129 make_number (charpos + lenins));
2131 unbind_to (count, Qnil);
2134 static Lisp_Object
2135 Fcombine_after_change_execute_1 (Lisp_Object val)
2137 Vcombine_after_change_calls = val;
2138 return val;
2141 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2142 Scombine_after_change_execute, 0, 0, 0,
2143 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2144 (void)
2146 int count = SPECPDL_INDEX ();
2147 EMACS_INT beg, end, change;
2148 EMACS_INT begpos, endpos;
2149 Lisp_Object tail;
2151 if (NILP (combine_after_change_list))
2152 return Qnil;
2154 /* It is rare for combine_after_change_buffer to be invalid, but
2155 possible. It can happen when combine-after-change-calls is
2156 non-nil, and insertion calls a file handler (e.g. through
2157 lock_file) which scribbles into a temp file -- cyd */
2158 if (!BUFFERP (combine_after_change_buffer)
2159 || NILP (BVAR (XBUFFER (combine_after_change_buffer), name)))
2161 combine_after_change_list = Qnil;
2162 return Qnil;
2165 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2167 Fset_buffer (combine_after_change_buffer);
2169 /* # chars unchanged at beginning of buffer. */
2170 beg = Z - BEG;
2171 /* # chars unchanged at end of buffer. */
2172 end = beg;
2173 /* Total amount of insertion (negative for deletion). */
2174 change = 0;
2176 /* Scan the various individual changes,
2177 accumulating the range info in BEG, END and CHANGE. */
2178 for (tail = combine_after_change_list; CONSP (tail);
2179 tail = XCDR (tail))
2181 Lisp_Object elt;
2182 EMACS_INT thisbeg, thisend, thischange;
2184 /* Extract the info from the next element. */
2185 elt = XCAR (tail);
2186 if (! CONSP (elt))
2187 continue;
2188 thisbeg = XINT (XCAR (elt));
2190 elt = XCDR (elt);
2191 if (! CONSP (elt))
2192 continue;
2193 thisend = XINT (XCAR (elt));
2195 elt = XCDR (elt);
2196 if (! CONSP (elt))
2197 continue;
2198 thischange = XINT (XCAR (elt));
2200 /* Merge this range into the accumulated range. */
2201 change += thischange;
2202 if (thisbeg < beg)
2203 beg = thisbeg;
2204 if (thisend < end)
2205 end = thisend;
2208 /* Get the current start and end positions of the range
2209 that was changed. */
2210 begpos = BEG + beg;
2211 endpos = Z - end;
2213 /* We are about to handle these, so discard them. */
2214 combine_after_change_list = Qnil;
2216 /* Now run the after-change functions for real.
2217 Turn off the flag that defers them. */
2218 record_unwind_protect (Fcombine_after_change_execute_1,
2219 Vcombine_after_change_calls);
2220 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2221 update_compositions (begpos, endpos, CHECK_ALL);
2223 return unbind_to (count, Qnil);
2226 void
2227 syms_of_insdel (void)
2229 staticpro (&combine_after_change_list);
2230 staticpro (&combine_after_change_buffer);
2231 combine_after_change_list = Qnil;
2232 combine_after_change_buffer = Qnil;
2234 DEFVAR_BOOL ("check-markers-debug-flag", check_markers_debug_flag,
2235 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
2236 check_markers_debug_flag = 0;
2237 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
2238 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2239 Vcombine_after_change_calls = Qnil;
2241 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
2242 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2243 This affects `before-change-functions' and `after-change-functions',
2244 as well as hooks attached to text properties and overlays. */);
2245 inhibit_modification_hooks = 0;
2246 Qinhibit_modification_hooks = intern_c_string ("inhibit-modification-hooks");
2247 staticpro (&Qinhibit_modification_hooks);
2249 defsubr (&Scombine_after_change_execute);