merge from upstream
[emacs.git] / src / insdel.c
blob4117b0e6b9328badc4621afa28f1a1be180fc8ac
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"
33 #include "xwidget.h"
35 #ifndef NULL
36 #define NULL 0
37 #endif
39 static void insert_from_string_1 (Lisp_Object string,
40 EMACS_INT pos, EMACS_INT pos_byte,
41 EMACS_INT nchars, EMACS_INT nbytes,
42 int inherit, int before_markers);
43 static void insert_from_buffer_1 (struct buffer *buf,
44 EMACS_INT from, EMACS_INT nchars,
45 int inherit);
46 static void gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap);
47 static void gap_right (EMACS_INT charpos, EMACS_INT bytepos);
48 static void adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
49 EMACS_INT to, EMACS_INT to_byte,
50 int before_markers);
51 static void adjust_markers_for_replace (EMACS_INT, EMACS_INT, EMACS_INT,
52 EMACS_INT, EMACS_INT, EMACS_INT);
53 static void adjust_point (EMACS_INT nchars, EMACS_INT nbytes);
55 static Lisp_Object Fcombine_after_change_execute (void);
57 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
58 describing changes which happened while combine_after_change_calls
59 was nonzero. We use this to decide how to call them
60 once the deferral ends.
62 In each element.
63 BEG-UNCHANGED is the number of chars before the changed range.
64 END-UNCHANGED is the number of chars after the changed range,
65 and CHANGE-AMOUNT is the number of characters inserted by the change
66 (negative for a deletion). */
67 static Lisp_Object combine_after_change_list;
69 /* Buffer which combine_after_change_list is about. */
70 static Lisp_Object combine_after_change_buffer;
72 Lisp_Object Qinhibit_modification_hooks;
74 static void signal_before_change (EMACS_INT, EMACS_INT, EMACS_INT *);
76 #define CHECK_MARKERS() \
77 do \
78 { \
79 if (check_markers_debug_flag) \
80 check_markers (); \
81 } \
82 while (0)
84 static void
85 check_markers (void)
87 register struct Lisp_Marker *tail;
88 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
90 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
92 if (tail->buffer->text != current_buffer->text)
93 abort ();
94 if (tail->charpos > Z)
95 abort ();
96 if (tail->bytepos > Z_BYTE)
97 abort ();
98 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
99 abort ();
103 /* Move gap to position CHARPOS.
104 Note that this can quit! */
106 void
107 move_gap (EMACS_INT charpos)
109 move_gap_both (charpos, charpos_to_bytepos (charpos));
112 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
113 Note that this can quit! */
115 void
116 move_gap_both (EMACS_INT charpos, EMACS_INT bytepos)
118 if (bytepos < GPT_BYTE)
119 gap_left (charpos, bytepos, 0);
120 else if (bytepos > GPT_BYTE)
121 gap_right (charpos, bytepos);
124 /* Move the gap to a position less than the current GPT.
125 BYTEPOS describes the new position as a byte position,
126 and CHARPOS is the corresponding char position.
127 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
129 static void
130 gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap)
132 register unsigned char *to, *from;
133 register EMACS_INT i;
134 EMACS_INT new_s1;
136 if (!newgap)
137 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
139 i = GPT_BYTE;
140 to = GAP_END_ADDR;
141 from = GPT_ADDR;
142 new_s1 = GPT_BYTE;
144 /* Now copy the characters. To move the gap down,
145 copy characters up. */
147 while (1)
149 /* I gets number of characters left to copy. */
150 i = new_s1 - bytepos;
151 if (i == 0)
152 break;
153 /* If a quit is requested, stop copying now.
154 Change BYTEPOS to be where we have actually moved the gap to. */
155 if (QUITP)
157 bytepos = new_s1;
158 charpos = BYTE_TO_CHAR (bytepos);
159 break;
161 /* Move at most 32000 chars before checking again for a quit. */
162 if (i > 32000)
163 i = 32000;
164 new_s1 -= i;
165 from -= i, to -= i;
166 memmove (to, from, i);
169 /* Adjust buffer data structure, to put the gap at BYTEPOS.
170 BYTEPOS is where the loop above stopped, which may be what
171 was specified or may be where a quit was detected. */
172 GPT_BYTE = bytepos;
173 GPT = charpos;
174 if (bytepos < charpos)
175 abort ();
176 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
177 QUIT;
180 /* Move the gap to a position greater than the current GPT.
181 BYTEPOS describes the new position as a byte position,
182 and CHARPOS is the corresponding char position. */
184 static void
185 gap_right (EMACS_INT charpos, EMACS_INT bytepos)
187 register unsigned char *to, *from;
188 register EMACS_INT i;
189 EMACS_INT new_s1;
191 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
193 i = GPT_BYTE;
194 from = GAP_END_ADDR;
195 to = GPT_ADDR;
196 new_s1 = GPT_BYTE;
198 /* Now copy the characters. To move the gap up,
199 copy characters down. */
201 while (1)
203 /* I gets number of characters left to copy. */
204 i = bytepos - new_s1;
205 if (i == 0)
206 break;
207 /* If a quit is requested, stop copying now.
208 Change BYTEPOS to be where we have actually moved the gap to. */
209 if (QUITP)
211 bytepos = new_s1;
212 charpos = BYTE_TO_CHAR (bytepos);
213 break;
215 /* Move at most 32000 chars before checking again for a quit. */
216 if (i > 32000)
217 i = 32000;
218 new_s1 += i;
219 memmove (to, from, i);
220 from += i, to += i;
223 GPT = charpos;
224 GPT_BYTE = bytepos;
225 if (bytepos < charpos)
226 abort ();
227 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
228 QUIT;
231 /* Adjust all markers for a deletion
232 whose range in bytes is FROM_BYTE to TO_BYTE.
233 The range in charpos is FROM to TO.
235 This function assumes that the gap is adjacent to
236 or inside of the range being deleted. */
238 void
239 adjust_markers_for_delete (EMACS_INT from, EMACS_INT from_byte,
240 EMACS_INT to, EMACS_INT to_byte)
242 Lisp_Object marker;
243 register struct Lisp_Marker *m;
244 register EMACS_INT charpos;
246 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
248 charpos = m->charpos;
250 if (charpos > Z)
251 abort ();
253 /* If the marker is after the deletion,
254 relocate by number of chars / bytes deleted. */
255 if (charpos > to)
257 m->charpos -= to - from;
258 m->bytepos -= to_byte - from_byte;
260 /* Here's the case where a marker is inside text being deleted. */
261 else if (charpos > from)
263 if (! m->insertion_type)
264 { /* Normal markers will end up at the beginning of the
265 re-inserted text after undoing a deletion, and must be
266 adjusted to move them to the correct place. */
267 XSETMISC (marker, m);
268 record_marker_adjustment (marker, from - charpos);
270 else if (charpos < to)
271 { /* Before-insertion markers will automatically move forward
272 upon re-inserting the deleted text, so we have to arrange
273 for them to move backward to the correct position. */
274 XSETMISC (marker, m);
275 record_marker_adjustment (marker, to - charpos);
277 m->charpos = from;
278 m->bytepos = from_byte;
280 /* Here's the case where a before-insertion marker is immediately
281 before the deleted region. */
282 else if (charpos == from && m->insertion_type)
284 /* Undoing the change uses normal insertion, which will
285 incorrectly make MARKER move forward, so we arrange for it
286 to then move backward to the correct place at the beginning
287 of the deleted region. */
288 XSETMISC (marker, m);
289 record_marker_adjustment (marker, to - from);
295 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
296 to TO / TO_BYTE. We have to relocate the charpos of every marker
297 that points after the insertion (but not their bytepos).
299 When a marker points at the insertion point,
300 we advance it if either its insertion-type is t
301 or BEFORE_MARKERS is true. */
303 static void
304 adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
305 EMACS_INT to, EMACS_INT to_byte, int before_markers)
307 struct Lisp_Marker *m;
308 int adjusted = 0;
309 EMACS_INT nchars = to - from;
310 EMACS_INT nbytes = to_byte - from_byte;
312 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
314 eassert (m->bytepos >= m->charpos
315 && m->bytepos - m->charpos <= Z_BYTE - Z);
317 if (m->bytepos == from_byte)
319 if (m->insertion_type || before_markers)
321 m->bytepos = to_byte;
322 m->charpos = to;
323 if (m->insertion_type)
324 adjusted = 1;
327 else if (m->bytepos > from_byte)
329 m->bytepos += nbytes;
330 m->charpos += nchars;
334 /* Adjusting only markers whose insertion-type is t may result in
335 - disordered start and end in overlays, and
336 - disordered overlays in the slot `overlays_before' of current_buffer. */
337 if (adjusted)
339 fix_start_end_in_overlays(from, to);
340 fix_overlays_before (current_buffer, from, to);
344 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
346 This is used only when the value of point changes due to an insert
347 or delete; it does not represent a conceptual change in point as a
348 marker. In particular, point is not crossing any interval
349 boundaries, so there's no need to use the usual SET_PT macro. In
350 fact it would be incorrect to do so, because either the old or the
351 new value of point is out of sync with the current set of
352 intervals. */
354 static void
355 adjust_point (EMACS_INT nchars, EMACS_INT nbytes)
357 SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes);
358 /* In a single-byte buffer, the two positions must be equal. */
359 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
362 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
363 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
364 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
365 an insertion. */
367 static void
368 adjust_markers_for_replace (EMACS_INT from, EMACS_INT from_byte,
369 EMACS_INT old_chars, EMACS_INT old_bytes,
370 EMACS_INT new_chars, EMACS_INT new_bytes)
372 register struct Lisp_Marker *m;
373 EMACS_INT prev_to_byte = from_byte + old_bytes;
374 EMACS_INT diff_chars = new_chars - old_chars;
375 EMACS_INT diff_bytes = new_bytes - old_bytes;
377 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
379 if (m->bytepos >= prev_to_byte)
381 m->charpos += diff_chars;
382 m->bytepos += diff_bytes;
384 else if (m->bytepos > from_byte)
386 m->charpos = from;
387 m->bytepos = from_byte;
391 CHECK_MARKERS ();
395 /* Make the gap NBYTES_ADDED bytes longer. */
397 static void
398 make_gap_larger (EMACS_INT nbytes_added)
400 Lisp_Object tem;
401 EMACS_INT real_gap_loc;
402 EMACS_INT real_gap_loc_byte;
403 EMACS_INT old_gap_size;
405 /* If we have to get more space, get enough to last a while. */
406 nbytes_added += 2000;
408 { EMACS_INT total_size = Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added;
409 if (total_size < 0
410 /* Don't allow a buffer size that won't fit in a Lisp integer. */
411 || total_size != XINT (make_number (total_size)))
412 error ("Buffer exceeds maximum size");
415 enlarge_buffer_text (current_buffer, nbytes_added);
417 /* Prevent quitting in move_gap. */
418 tem = Vinhibit_quit;
419 Vinhibit_quit = Qt;
421 real_gap_loc = GPT;
422 real_gap_loc_byte = GPT_BYTE;
423 old_gap_size = GAP_SIZE;
425 /* Call the newly allocated space a gap at the end of the whole space. */
426 GPT = Z + GAP_SIZE;
427 GPT_BYTE = Z_BYTE + GAP_SIZE;
428 GAP_SIZE = nbytes_added;
430 /* Move the new gap down to be consecutive with the end of the old one.
431 This adjusts the markers properly too. */
432 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
434 /* Now combine the two into one large gap. */
435 GAP_SIZE += old_gap_size;
436 GPT = real_gap_loc;
437 GPT_BYTE = real_gap_loc_byte;
439 /* Put an anchor. */
440 *(Z_ADDR) = 0;
442 Vinhibit_quit = tem;
445 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
447 /* Make the gap NBYTES_REMOVED bytes shorter. */
449 static void
450 make_gap_smaller (EMACS_INT nbytes_removed)
452 Lisp_Object tem;
453 EMACS_INT real_gap_loc;
454 EMACS_INT real_gap_loc_byte;
455 EMACS_INT real_Z;
456 EMACS_INT real_Z_byte;
457 EMACS_INT real_beg_unchanged;
458 EMACS_INT new_gap_size;
460 /* Make sure the gap is at least 20 bytes. */
461 if (GAP_SIZE - nbytes_removed < 20)
462 nbytes_removed = GAP_SIZE - 20;
464 /* Prevent quitting in move_gap. */
465 tem = Vinhibit_quit;
466 Vinhibit_quit = Qt;
468 real_gap_loc = GPT;
469 real_gap_loc_byte = GPT_BYTE;
470 new_gap_size = GAP_SIZE - nbytes_removed;
471 real_Z = Z;
472 real_Z_byte = Z_BYTE;
473 real_beg_unchanged = BEG_UNCHANGED;
475 /* Pretend that the last unwanted part of the gap is the entire gap,
476 and that the first desired part of the gap is part of the buffer
477 text. */
478 memset (GPT_ADDR, 0, new_gap_size);
479 GPT += new_gap_size;
480 GPT_BYTE += new_gap_size;
481 Z += new_gap_size;
482 Z_BYTE += new_gap_size;
483 GAP_SIZE = nbytes_removed;
485 /* Move the unwanted pretend gap to the end of the buffer. This
486 adjusts the markers properly too. */
487 gap_right (Z, Z_BYTE);
489 enlarge_buffer_text (current_buffer, -nbytes_removed);
491 /* Now restore the desired gap. */
492 GAP_SIZE = new_gap_size;
493 GPT = real_gap_loc;
494 GPT_BYTE = real_gap_loc_byte;
495 Z = real_Z;
496 Z_BYTE = real_Z_byte;
497 BEG_UNCHANGED = real_beg_unchanged;
499 /* Put an anchor. */
500 *(Z_ADDR) = 0;
502 Vinhibit_quit = tem;
505 #endif /* USE_MMAP_FOR_BUFFERS || REL_ALLOC || DOUG_LEA_MALLOC */
507 void
508 make_gap (EMACS_INT nbytes_added)
510 if (nbytes_added >= 0)
511 make_gap_larger (nbytes_added);
512 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
513 else
514 make_gap_smaller (-nbytes_added);
515 #endif
518 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
519 FROM_MULTIBYTE says whether the incoming text is multibyte.
520 TO_MULTIBYTE says whether to store the text as multibyte.
521 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
523 Return the number of bytes stored at TO_ADDR. */
525 EMACS_INT
526 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
527 EMACS_INT nbytes, int from_multibyte, int to_multibyte)
529 if (from_multibyte == to_multibyte)
531 memcpy (to_addr, from_addr, nbytes);
532 return nbytes;
534 else if (from_multibyte)
536 EMACS_INT nchars = 0;
537 EMACS_INT bytes_left = nbytes;
539 while (bytes_left > 0)
541 int thislen, c;
542 c = STRING_CHAR_AND_LENGTH (from_addr, thislen);
543 if (! ASCII_CHAR_P (c))
544 c &= 0xFF;
545 *to_addr++ = c;
546 from_addr += thislen;
547 bytes_left -= thislen;
548 nchars++;
550 return nchars;
552 else
554 unsigned char *initial_to_addr = to_addr;
556 /* Convert single-byte to multibyte. */
557 while (nbytes > 0)
559 int c = *from_addr++;
561 if (!ASCII_CHAR_P (c))
563 c = BYTE8_TO_CHAR (c);
564 to_addr += CHAR_STRING (c, to_addr);
565 nbytes--;
567 else
568 /* Special case for speed. */
569 *to_addr++ = c, nbytes--;
571 return to_addr - initial_to_addr;
575 /* Insert a string of specified length before point.
576 This function judges multibyteness based on
577 enable_multibyte_characters in the current buffer;
578 it never converts between single-byte and multibyte.
580 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
581 prepare_to_modify_buffer could relocate the text. */
583 void
584 insert (const char *string, EMACS_INT nbytes)
586 if (nbytes > 0)
588 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
589 insert_1_both (string, len, nbytes, 0, 1, 0);
590 opoint = PT - len;
591 signal_after_change (opoint, 0, len);
592 update_compositions (opoint, PT, CHECK_BORDER);
596 /* Likewise, but inherit text properties from neighboring characters. */
598 void
599 insert_and_inherit (const char *string, EMACS_INT nbytes)
601 if (nbytes > 0)
603 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
604 insert_1_both (string, len, nbytes, 1, 1, 0);
605 opoint = PT - len;
606 signal_after_change (opoint, 0, len);
607 update_compositions (opoint, PT, CHECK_BORDER);
611 /* Insert the character C before point. Do not inherit text properties. */
613 void
614 insert_char (int c)
616 unsigned char str[MAX_MULTIBYTE_LENGTH];
617 int len;
619 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
620 len = CHAR_STRING (c, str);
621 else
623 len = 1;
624 str[0] = c;
627 insert ((char *) str, len);
630 /* Insert the null-terminated string S before point. */
632 void
633 insert_string (const char *s)
635 insert (s, strlen (s));
638 /* Like `insert' except that all markers pointing at the place where
639 the insertion happens are adjusted to point after it.
640 Don't use this function to insert part of a Lisp string,
641 since gc could happen and relocate it. */
643 void
644 insert_before_markers (const char *string, EMACS_INT nbytes)
646 if (nbytes > 0)
648 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
649 insert_1_both (string, len, nbytes, 0, 1, 1);
650 opoint = PT - len;
651 signal_after_change (opoint, 0, len);
652 update_compositions (opoint, PT, CHECK_BORDER);
656 /* Likewise, but inherit text properties from neighboring characters. */
658 void
659 insert_before_markers_and_inherit (const char *string,
660 EMACS_INT nbytes)
662 if (nbytes > 0)
664 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
665 insert_1_both (string, len, nbytes, 1, 1, 1);
666 opoint = PT - len;
667 signal_after_change (opoint, 0, len);
668 update_compositions (opoint, PT, CHECK_BORDER);
672 /* Subroutine used by the insert functions above. */
674 void
675 insert_1 (const char *string, EMACS_INT nbytes,
676 int inherit, int prepare, int before_markers)
678 insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
679 nbytes, inherit, prepare, before_markers);
683 #ifdef BYTE_COMBINING_DEBUG
685 /* See if the bytes before POS/POS_BYTE combine with bytes
686 at the start of STRING to form a single character.
687 If so, return the number of bytes at the start of STRING
688 which combine in this way. Otherwise, return 0. */
691 count_combining_before (const unsigned char *string, EMACS_INT length,
692 EMACS_INT pos, EMACS_INT pos_byte)
694 int len, combining_bytes;
695 const unsigned char *p;
697 if (NILP (current_buffer->enable_multibyte_characters))
698 return 0;
700 /* At first, we can exclude the following cases:
701 (1) STRING[0] can't be a following byte of multibyte sequence.
702 (2) POS is the start of the current buffer.
703 (3) A character before POS is not a multibyte character. */
704 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
705 return 0;
706 if (pos_byte == BEG_BYTE) /* case (2) */
707 return 0;
708 len = 1;
709 p = BYTE_POS_ADDR (pos_byte - 1);
710 while (! CHAR_HEAD_P (*p)) p--, len++;
711 if (! LEADING_CODE_P (*p)) /* case (3) */
712 return 0;
714 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
715 if (combining_bytes <= 0)
716 /* The character preceding POS is, complete and no room for
717 combining bytes (combining_bytes == 0), or an independent 8-bit
718 character (combining_bytes < 0). */
719 return 0;
721 /* We have a combination situation. Count the bytes at STRING that
722 may combine. */
723 p = string + 1;
724 while (!CHAR_HEAD_P (*p) && p < string + length)
725 p++;
727 return (combining_bytes < p - string ? combining_bytes : p - string);
730 /* See if the bytes after POS/POS_BYTE combine with bytes
731 at the end of STRING to form a single character.
732 If so, return the number of bytes after POS/POS_BYTE
733 which combine in this way. Otherwise, return 0. */
736 count_combining_after (const unsigned char *string,
737 EMACS_INT length, EMACS_INT pos, EMACS_INT pos_byte)
739 EMACS_INT opos_byte = pos_byte;
740 EMACS_INT i;
741 EMACS_INT bytes;
742 unsigned char *bufp;
744 if (NILP (current_buffer->enable_multibyte_characters))
745 return 0;
747 /* At first, we can exclude the following cases:
748 (1) The last byte of STRING is an ASCII.
749 (2) POS is the last of the current buffer.
750 (3) A character at POS can't be a following byte of multibyte
751 character. */
752 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
753 return 0;
754 if (pos_byte == Z_BYTE) /* case (2) */
755 return 0;
756 bufp = BYTE_POS_ADDR (pos_byte);
757 if (CHAR_HEAD_P (*bufp)) /* case (3) */
758 return 0;
760 i = length - 1;
761 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
763 i--;
765 if (i < 0)
767 /* All characters in STRING are not character head. We must
768 check also preceding bytes at POS. We are sure that the gap
769 is at POS. */
770 unsigned char *p = BEG_ADDR;
771 i = pos_byte - 2;
772 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
773 i--;
774 if (i < 0 || !LEADING_CODE_P (p[i]))
775 return 0;
777 bytes = BYTES_BY_CHAR_HEAD (p[i]);
778 return (bytes <= pos_byte - 1 - i + length
780 : bytes - (pos_byte - 1 - i + length));
782 if (!LEADING_CODE_P (string[i]))
783 return 0;
785 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
786 bufp++, pos_byte++;
787 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
789 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
792 #endif
795 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
796 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
797 are the same as in insert_1. */
799 void
800 insert_1_both (const char *string,
801 EMACS_INT nchars, EMACS_INT nbytes,
802 int inherit, int prepare, int before_markers)
804 if (nchars == 0)
805 return;
807 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
808 nchars = nbytes;
810 if (prepare)
811 /* Do this before moving and increasing the gap,
812 because the before-change hooks might move the gap
813 or make it smaller. */
814 prepare_to_modify_buffer (PT, PT, NULL);
816 if (PT != GPT)
817 move_gap_both (PT, PT_BYTE);
818 if (GAP_SIZE < nbytes)
819 make_gap (nbytes - GAP_SIZE);
821 #ifdef BYTE_COMBINING_DEBUG
822 if (count_combining_before (string, nbytes, PT, PT_BYTE)
823 || count_combining_after (string, nbytes, PT, PT_BYTE))
824 abort ();
825 #endif
827 /* Record deletion of the surrounding text that combines with
828 the insertion. This, together with recording the insertion,
829 will add up to the right stuff in the undo list. */
830 record_insert (PT, nchars);
831 MODIFF++;
832 CHARS_MODIFF = MODIFF;
834 memcpy (GPT_ADDR, string, nbytes);
836 GAP_SIZE -= nbytes;
837 GPT += nchars;
838 ZV += nchars;
839 Z += nchars;
840 GPT_BYTE += nbytes;
841 ZV_BYTE += nbytes;
842 Z_BYTE += nbytes;
843 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
845 if (GPT_BYTE < GPT)
846 abort ();
848 /* The insert may have been in the unchanged region, so check again. */
849 if (Z - GPT < END_UNCHANGED)
850 END_UNCHANGED = Z - GPT;
852 adjust_overlays_for_insert (PT, nchars);
853 adjust_markers_for_insert (PT, PT_BYTE,
854 PT + nchars, PT_BYTE + nbytes,
855 before_markers);
857 if (BUF_INTERVALS (current_buffer) != 0)
858 offset_intervals (current_buffer, PT, nchars);
860 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
861 set_text_properties (make_number (PT), make_number (PT + nchars),
862 Qnil, Qnil, Qnil);
864 adjust_point (nchars, nbytes);
866 CHECK_MARKERS ();
869 /* Insert the part of the text of STRING, a Lisp object assumed to be
870 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
871 starting at position POS / POS_BYTE. If the text of STRING has properties,
872 copy them into the buffer.
874 It does not work to use `insert' for this, because a GC could happen
875 before we copy the stuff into the buffer, and relocate the string
876 without insert noticing. */
878 void
879 insert_from_string (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
880 EMACS_INT length, EMACS_INT length_byte, int inherit)
882 EMACS_INT opoint = PT;
884 if (SCHARS (string) == 0)
885 return;
887 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
888 inherit, 0);
889 signal_after_change (opoint, 0, PT - opoint);
890 update_compositions (opoint, PT, CHECK_BORDER);
893 /* Like `insert_from_string' except that all markers pointing
894 at the place where the insertion happens are adjusted to point after it. */
896 void
897 insert_from_string_before_markers (Lisp_Object string,
898 EMACS_INT pos, EMACS_INT pos_byte,
899 EMACS_INT length, EMACS_INT length_byte,
900 int inherit)
902 EMACS_INT opoint = PT;
904 if (SCHARS (string) == 0)
905 return;
907 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
908 inherit, 1);
909 signal_after_change (opoint, 0, PT - opoint);
910 update_compositions (opoint, PT, CHECK_BORDER);
913 /* Subroutine of the insertion functions above. */
915 static void
916 insert_from_string_1 (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
917 EMACS_INT nchars, EMACS_INT nbytes,
918 int inherit, int before_markers)
920 struct gcpro gcpro1;
921 EMACS_INT outgoing_nbytes = nbytes;
922 INTERVAL intervals;
924 /* Make OUTGOING_NBYTES describe the text
925 as it will be inserted in this buffer. */
927 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
928 outgoing_nbytes = nchars;
929 else if (! STRING_MULTIBYTE (string))
930 outgoing_nbytes
931 = count_size_as_multibyte (SDATA (string) + pos_byte,
932 nbytes);
934 GCPRO1 (string);
935 /* Do this before moving and increasing the gap,
936 because the before-change hooks might move the gap
937 or make it smaller. */
938 prepare_to_modify_buffer (PT, PT, NULL);
940 if (PT != GPT)
941 move_gap_both (PT, PT_BYTE);
942 if (GAP_SIZE < outgoing_nbytes)
943 make_gap (outgoing_nbytes - GAP_SIZE);
944 UNGCPRO;
946 /* Copy the string text into the buffer, perhaps converting
947 between single-byte and multibyte. */
948 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
949 STRING_MULTIBYTE (string),
950 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
952 #ifdef BYTE_COMBINING_DEBUG
953 /* We have copied text into the gap, but we have not altered
954 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
955 to these functions and get the same results as we would
956 have got earlier on. Meanwhile, PT_ADDR does point to
957 the text that has been stored by copy_text. */
958 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
959 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
960 abort ();
961 #endif
963 record_insert (PT, nchars);
964 MODIFF++;
965 CHARS_MODIFF = MODIFF;
967 GAP_SIZE -= outgoing_nbytes;
968 GPT += nchars;
969 ZV += nchars;
970 Z += nchars;
971 GPT_BYTE += outgoing_nbytes;
972 ZV_BYTE += outgoing_nbytes;
973 Z_BYTE += outgoing_nbytes;
974 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
976 if (GPT_BYTE < GPT)
977 abort ();
979 /* The insert may have been in the unchanged region, so check again. */
980 if (Z - GPT < END_UNCHANGED)
981 END_UNCHANGED = Z - GPT;
983 adjust_overlays_for_insert (PT, nchars);
984 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
985 PT_BYTE + outgoing_nbytes,
986 before_markers);
988 offset_intervals (current_buffer, PT, nchars);
990 intervals = STRING_INTERVALS (string);
991 /* Get the intervals for the part of the string we are inserting. */
992 if (nbytes < SBYTES (string))
993 intervals = copy_intervals (intervals, pos, nchars);
995 /* Insert those intervals. */
996 graft_intervals_into_buffer (intervals, PT, nchars,
997 current_buffer, inherit);
999 adjust_point (nchars, outgoing_nbytes);
1001 CHECK_MARKERS ();
1004 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1005 starting at GPT_ADDR. */
1007 void
1008 insert_from_gap (EMACS_INT nchars, EMACS_INT nbytes)
1010 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1011 nchars = nbytes;
1013 record_insert (GPT, nchars);
1014 MODIFF++;
1016 GAP_SIZE -= nbytes;
1017 GPT += nchars;
1018 ZV += nchars;
1019 Z += nchars;
1020 GPT_BYTE += nbytes;
1021 ZV_BYTE += nbytes;
1022 Z_BYTE += nbytes;
1023 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1025 if (GPT_BYTE < GPT)
1026 abort ();
1028 adjust_overlays_for_insert (GPT - nchars, nchars);
1029 adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
1030 GPT, GPT_BYTE, 0);
1032 if (BUF_INTERVALS (current_buffer) != 0)
1034 offset_intervals (current_buffer, GPT - nchars, nchars);
1035 graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
1036 current_buffer, 0);
1039 if (GPT - nchars < PT)
1040 adjust_point (nchars, nbytes);
1042 CHECK_MARKERS ();
1045 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1046 current buffer. If the text in BUF has properties, they are absorbed
1047 into the current buffer.
1049 It does not work to use `insert' for this, because a malloc could happen
1050 and relocate BUF's text before the copy happens. */
1052 void
1053 insert_from_buffer (struct buffer *buf,
1054 EMACS_INT charpos, EMACS_INT nchars, int inherit)
1056 EMACS_INT opoint = PT;
1058 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1059 signal_after_change (opoint, 0, PT - opoint);
1060 update_compositions (opoint, PT, CHECK_BORDER);
1063 static void
1064 insert_from_buffer_1 (struct buffer *buf,
1065 EMACS_INT from, EMACS_INT nchars, int inherit)
1067 register Lisp_Object temp;
1068 EMACS_INT chunk, chunk_expanded;
1069 EMACS_INT from_byte = buf_charpos_to_bytepos (buf, from);
1070 EMACS_INT to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1071 EMACS_INT incoming_nbytes = to_byte - from_byte;
1072 EMACS_INT outgoing_nbytes = incoming_nbytes;
1073 INTERVAL intervals;
1075 /* Make OUTGOING_NBYTES describe the text
1076 as it will be inserted in this buffer. */
1078 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1079 outgoing_nbytes = nchars;
1080 else if (NILP (BVAR (buf, enable_multibyte_characters)))
1082 EMACS_INT outgoing_before_gap = 0;
1083 EMACS_INT outgoing_after_gap = 0;
1085 if (from < BUF_GPT (buf))
1087 chunk = BUF_GPT_BYTE (buf) - from_byte;
1088 if (chunk > incoming_nbytes)
1089 chunk = incoming_nbytes;
1090 outgoing_before_gap
1091 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1092 chunk);
1094 else
1095 chunk = 0;
1097 if (chunk < incoming_nbytes)
1098 outgoing_after_gap
1099 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1100 from_byte + chunk),
1101 incoming_nbytes - chunk);
1103 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1106 /* Make sure point-max won't overflow after this insertion. */
1107 XSETINT (temp, outgoing_nbytes + Z);
1108 if (outgoing_nbytes + Z != XINT (temp))
1109 error ("Maximum buffer size exceeded");
1111 /* Do this before moving and increasing the gap,
1112 because the before-change hooks might move the gap
1113 or make it smaller. */
1114 prepare_to_modify_buffer (PT, PT, NULL);
1116 if (PT != GPT)
1117 move_gap_both (PT, PT_BYTE);
1118 if (GAP_SIZE < outgoing_nbytes)
1119 make_gap (outgoing_nbytes - GAP_SIZE);
1121 if (from < BUF_GPT (buf))
1123 chunk = BUF_GPT_BYTE (buf) - from_byte;
1124 if (chunk > incoming_nbytes)
1125 chunk = incoming_nbytes;
1126 /* Record number of output bytes, so we know where
1127 to put the output from the second copy_text. */
1128 chunk_expanded
1129 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1130 GPT_ADDR, chunk,
1131 ! NILP (BVAR (buf, enable_multibyte_characters)),
1132 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1134 else
1135 chunk_expanded = chunk = 0;
1137 if (chunk < incoming_nbytes)
1138 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1139 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1140 ! NILP (BVAR (buf, enable_multibyte_characters)),
1141 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1143 #ifdef BYTE_COMBINING_DEBUG
1144 /* We have copied text into the gap, but we have not altered
1145 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1146 to these functions and get the same results as we would
1147 have got earlier on. Meanwhile, GPT_ADDR does point to
1148 the text that has been stored by copy_text. */
1149 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1150 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1151 abort ();
1152 #endif
1154 record_insert (PT, nchars);
1155 MODIFF++;
1156 CHARS_MODIFF = MODIFF;
1158 GAP_SIZE -= outgoing_nbytes;
1159 GPT += nchars;
1160 ZV += nchars;
1161 Z += nchars;
1162 GPT_BYTE += outgoing_nbytes;
1163 ZV_BYTE += outgoing_nbytes;
1164 Z_BYTE += outgoing_nbytes;
1165 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1167 if (GPT_BYTE < GPT)
1168 abort ();
1170 /* The insert may have been in the unchanged region, so check again. */
1171 if (Z - GPT < END_UNCHANGED)
1172 END_UNCHANGED = Z - GPT;
1174 adjust_overlays_for_insert (PT, nchars);
1175 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1176 PT_BYTE + outgoing_nbytes,
1179 if (BUF_INTERVALS (current_buffer) != 0)
1180 offset_intervals (current_buffer, PT, nchars);
1182 /* Get the intervals for the part of the string we are inserting. */
1183 intervals = BUF_INTERVALS (buf);
1184 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1186 if (buf == current_buffer && PT <= from)
1187 from += nchars;
1188 intervals = copy_intervals (intervals, from, nchars);
1191 /* Insert those intervals. */
1192 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1194 adjust_point (nchars, outgoing_nbytes);
1197 /* Record undo information and adjust markers and position keepers for
1198 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1199 chars (LEN_BYTE bytes) which resides in the gap just after
1200 GPT_ADDR.
1202 PREV_TEXT nil means the new text was just inserted. */
1204 static void
1205 adjust_after_replace (EMACS_INT from, EMACS_INT from_byte,
1206 Lisp_Object prev_text, EMACS_INT len, EMACS_INT len_byte)
1208 EMACS_INT nchars_del = 0, nbytes_del = 0;
1210 #ifdef BYTE_COMBINING_DEBUG
1211 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1212 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1213 abort ();
1214 #endif
1216 if (STRINGP (prev_text))
1218 nchars_del = SCHARS (prev_text);
1219 nbytes_del = SBYTES (prev_text);
1222 /* Update various buffer positions for the new text. */
1223 GAP_SIZE -= len_byte;
1224 ZV += len; Z+= len;
1225 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1226 GPT += len; GPT_BYTE += len_byte;
1227 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1229 if (nchars_del > 0)
1230 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1231 len, len_byte);
1232 else
1233 adjust_markers_for_insert (from, from_byte,
1234 from + len, from_byte + len_byte, 0);
1236 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1238 if (nchars_del > 0)
1239 record_delete (from, prev_text);
1240 record_insert (from, len);
1243 if (len > nchars_del)
1244 adjust_overlays_for_insert (from, len - nchars_del);
1245 else if (len < nchars_del)
1246 adjust_overlays_for_delete (from, nchars_del - len);
1247 if (BUF_INTERVALS (current_buffer) != 0)
1249 offset_intervals (current_buffer, from, len - nchars_del);
1252 if (from < PT)
1253 adjust_point (len - nchars_del, len_byte - nbytes_del);
1255 /* As byte combining will decrease Z, we must check this again. */
1256 if (Z - GPT < END_UNCHANGED)
1257 END_UNCHANGED = Z - GPT;
1259 CHECK_MARKERS ();
1261 if (len == 0)
1262 evaporate_overlays (from);
1263 MODIFF++;
1264 CHARS_MODIFF = MODIFF;
1267 /* Record undo information, adjust markers and position keepers for an
1268 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1269 text already exists in the current buffer but character length (TO
1270 - FROM) may be incorrect, the correct length is NEWLEN. */
1272 void
1273 adjust_after_insert (EMACS_INT from, EMACS_INT from_byte,
1274 EMACS_INT to, EMACS_INT to_byte, EMACS_INT newlen)
1276 EMACS_INT len = to - from, len_byte = to_byte - from_byte;
1278 if (GPT != to)
1279 move_gap_both (to, to_byte);
1280 GAP_SIZE += len_byte;
1281 GPT -= len; GPT_BYTE -= len_byte;
1282 ZV -= len; ZV_BYTE -= len_byte;
1283 Z -= len; Z_BYTE -= len_byte;
1284 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1287 /* Replace the text from character positions FROM to TO with NEW,
1288 If PREPARE is nonzero, call prepare_to_modify_buffer.
1289 If INHERIT, the newly inserted text should inherit text properties
1290 from the surrounding non-deleted text. */
1292 /* Note that this does not yet handle markers quite right.
1293 Also it needs to record a single undo-entry that does a replacement
1294 rather than a separate delete and insert.
1295 That way, undo will also handle markers properly.
1297 But if MARKERS is 0, don't relocate markers. */
1299 void
1300 replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
1301 int prepare, int inherit, int markers)
1303 EMACS_INT inschars = SCHARS (new);
1304 EMACS_INT insbytes = SBYTES (new);
1305 EMACS_INT from_byte, to_byte;
1306 EMACS_INT nbytes_del, nchars_del;
1307 register Lisp_Object temp;
1308 struct gcpro gcpro1;
1309 INTERVAL intervals;
1310 EMACS_INT outgoing_insbytes = insbytes;
1311 Lisp_Object deletion;
1313 CHECK_MARKERS ();
1315 GCPRO1 (new);
1316 deletion = Qnil;
1318 if (prepare)
1320 EMACS_INT range_length = to - from;
1321 prepare_to_modify_buffer (from, to, &from);
1322 to = from + range_length;
1325 UNGCPRO;
1327 /* Make args be valid */
1328 if (from < BEGV)
1329 from = BEGV;
1330 if (to > ZV)
1331 to = ZV;
1333 from_byte = CHAR_TO_BYTE (from);
1334 to_byte = CHAR_TO_BYTE (to);
1336 nchars_del = to - from;
1337 nbytes_del = to_byte - from_byte;
1339 if (nbytes_del <= 0 && insbytes == 0)
1340 return;
1342 /* Make OUTGOING_INSBYTES describe the text
1343 as it will be inserted in this buffer. */
1345 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1346 outgoing_insbytes = inschars;
1347 else if (! STRING_MULTIBYTE (new))
1348 outgoing_insbytes
1349 = count_size_as_multibyte (SDATA (new), insbytes);
1351 /* Make sure point-max won't overflow after this insertion. */
1352 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1353 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1354 error ("Maximum buffer size exceeded");
1356 GCPRO1 (new);
1358 /* Make sure the gap is somewhere in or next to what we are deleting. */
1359 if (from > GPT)
1360 gap_right (from, from_byte);
1361 if (to < GPT)
1362 gap_left (to, to_byte, 0);
1364 /* Even if we don't record for undo, we must keep the original text
1365 because we may have to recover it because of inappropriate byte
1366 combining. */
1367 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1368 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1370 GAP_SIZE += nbytes_del;
1371 ZV -= nchars_del;
1372 Z -= nchars_del;
1373 ZV_BYTE -= nbytes_del;
1374 Z_BYTE -= nbytes_del;
1375 GPT = from;
1376 GPT_BYTE = from_byte;
1377 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1379 if (GPT_BYTE < GPT)
1380 abort ();
1382 if (GPT - BEG < BEG_UNCHANGED)
1383 BEG_UNCHANGED = GPT - BEG;
1384 if (Z - GPT < END_UNCHANGED)
1385 END_UNCHANGED = Z - GPT;
1387 if (GAP_SIZE < insbytes)
1388 make_gap (insbytes - GAP_SIZE);
1390 /* Copy the string text into the buffer, perhaps converting
1391 between single-byte and multibyte. */
1392 copy_text (SDATA (new), GPT_ADDR, insbytes,
1393 STRING_MULTIBYTE (new),
1394 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1396 #ifdef BYTE_COMBINING_DEBUG
1397 /* We have copied text into the gap, but we have not marked
1398 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1399 here, for both the previous text and the following text.
1400 Meanwhile, GPT_ADDR does point to
1401 the text that has been stored by copy_text. */
1402 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1403 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1404 abort ();
1405 #endif
1407 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1409 /* Record the insertion first, so that when we undo,
1410 the deletion will be undone first. Thus, undo
1411 will insert before deleting, and thus will keep
1412 the markers before and after this text separate. */
1413 record_insert (from + SCHARS (deletion), inschars);
1414 record_delete (from, deletion);
1417 GAP_SIZE -= outgoing_insbytes;
1418 GPT += inschars;
1419 ZV += inschars;
1420 Z += inschars;
1421 GPT_BYTE += outgoing_insbytes;
1422 ZV_BYTE += outgoing_insbytes;
1423 Z_BYTE += outgoing_insbytes;
1424 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1426 if (GPT_BYTE < GPT)
1427 abort ();
1429 /* Adjust the overlay center as needed. This must be done after
1430 adjusting the markers that bound the overlays. */
1431 adjust_overlays_for_delete (from, nchars_del);
1432 adjust_overlays_for_insert (from, inschars);
1434 /* Adjust markers for the deletion and the insertion. */
1435 if (markers)
1436 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1437 inschars, outgoing_insbytes);
1439 offset_intervals (current_buffer, from, inschars - nchars_del);
1441 /* Get the intervals for the part of the string we are inserting--
1442 not including the combined-before bytes. */
1443 intervals = STRING_INTERVALS (new);
1444 /* Insert those intervals. */
1445 graft_intervals_into_buffer (intervals, from, inschars,
1446 current_buffer, inherit);
1448 /* Relocate point as if it were a marker. */
1449 if (from < PT)
1450 adjust_point ((from + inschars - (PT < to ? PT : to)),
1451 (from_byte + outgoing_insbytes
1452 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1454 if (outgoing_insbytes == 0)
1455 evaporate_overlays (from);
1457 CHECK_MARKERS ();
1459 MODIFF++;
1460 CHARS_MODIFF = MODIFF;
1461 UNGCPRO;
1463 signal_after_change (from, nchars_del, GPT - from);
1464 update_compositions (from, GPT, CHECK_BORDER);
1467 /* Replace the text from character positions FROM to TO with
1468 the text in INS of length INSCHARS.
1469 Keep the text properties that applied to the old characters
1470 (extending them to all the new chars if there are more new chars).
1472 Note that this does not yet handle markers quite right.
1474 If MARKERS is nonzero, relocate markers.
1476 Unlike most functions at this level, never call
1477 prepare_to_modify_buffer and never call signal_after_change. */
1479 void
1480 replace_range_2 (EMACS_INT from, EMACS_INT from_byte,
1481 EMACS_INT to, EMACS_INT to_byte,
1482 const char *ins, EMACS_INT inschars, EMACS_INT insbytes,
1483 int markers)
1485 EMACS_INT nbytes_del, nchars_del;
1486 Lisp_Object temp;
1488 CHECK_MARKERS ();
1490 nchars_del = to - from;
1491 nbytes_del = to_byte - from_byte;
1493 if (nbytes_del <= 0 && insbytes == 0)
1494 return;
1496 /* Make sure point-max won't overflow after this insertion. */
1497 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1498 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1499 error ("Maximum buffer size exceeded");
1501 /* Make sure the gap is somewhere in or next to what we are deleting. */
1502 if (from > GPT)
1503 gap_right (from, from_byte);
1504 if (to < GPT)
1505 gap_left (to, to_byte, 0);
1507 GAP_SIZE += nbytes_del;
1508 ZV -= nchars_del;
1509 Z -= nchars_del;
1510 ZV_BYTE -= nbytes_del;
1511 Z_BYTE -= nbytes_del;
1512 GPT = from;
1513 GPT_BYTE = from_byte;
1514 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1516 if (GPT_BYTE < GPT)
1517 abort ();
1519 if (GPT - BEG < BEG_UNCHANGED)
1520 BEG_UNCHANGED = GPT - BEG;
1521 if (Z - GPT < END_UNCHANGED)
1522 END_UNCHANGED = Z - GPT;
1524 if (GAP_SIZE < insbytes)
1525 make_gap (insbytes - GAP_SIZE);
1527 /* Copy the replacement text into the buffer. */
1528 memcpy (GPT_ADDR, ins, insbytes);
1530 #ifdef BYTE_COMBINING_DEBUG
1531 /* We have copied text into the gap, but we have not marked
1532 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1533 here, for both the previous text and the following text.
1534 Meanwhile, GPT_ADDR does point to
1535 the text that has been stored by copy_text. */
1536 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1537 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1538 abort ();
1539 #endif
1541 GAP_SIZE -= insbytes;
1542 GPT += inschars;
1543 ZV += inschars;
1544 Z += inschars;
1545 GPT_BYTE += insbytes;
1546 ZV_BYTE += insbytes;
1547 Z_BYTE += insbytes;
1548 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1550 if (GPT_BYTE < GPT)
1551 abort ();
1553 /* Adjust the overlay center as needed. This must be done after
1554 adjusting the markers that bound the overlays. */
1555 if (nchars_del != inschars)
1557 adjust_overlays_for_insert (from, inschars);
1558 adjust_overlays_for_delete (from + inschars, nchars_del);
1561 /* Adjust markers for the deletion and the insertion. */
1562 if (markers
1563 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1564 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1565 inschars, insbytes);
1567 offset_intervals (current_buffer, from, inschars - nchars_del);
1569 /* Relocate point as if it were a marker. */
1570 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1572 if (PT < to)
1573 /* PT was within the deleted text. Move it to FROM. */
1574 adjust_point (from - PT, from_byte - PT_BYTE);
1575 else
1576 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1579 if (insbytes == 0)
1580 evaporate_overlays (from);
1582 CHECK_MARKERS ();
1584 MODIFF++;
1585 CHARS_MODIFF = MODIFF;
1588 /* Delete characters in current buffer
1589 from FROM up to (but not including) TO.
1590 If TO comes before FROM, we delete nothing. */
1592 void
1593 del_range (EMACS_INT from, EMACS_INT to)
1595 del_range_1 (from, to, 1, 0);
1598 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1599 RET_STRING says to return the deleted text. */
1601 Lisp_Object
1602 del_range_1 (EMACS_INT from, EMACS_INT to, int prepare, int ret_string)
1604 EMACS_INT from_byte, to_byte;
1605 Lisp_Object deletion;
1606 struct gcpro gcpro1;
1608 /* Make args be valid */
1609 if (from < BEGV)
1610 from = BEGV;
1611 if (to > ZV)
1612 to = ZV;
1614 if (to <= from)
1615 return Qnil;
1617 if (prepare)
1619 EMACS_INT range_length = to - from;
1620 prepare_to_modify_buffer (from, to, &from);
1621 to = min (ZV, from + range_length);
1624 from_byte = CHAR_TO_BYTE (from);
1625 to_byte = CHAR_TO_BYTE (to);
1627 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1628 GCPRO1(deletion);
1629 signal_after_change (from, to - from, 0);
1630 update_compositions (from, from, CHECK_HEAD);
1631 UNGCPRO;
1632 return deletion;
1635 /* Like del_range_1 but args are byte positions, not char positions. */
1637 void
1638 del_range_byte (EMACS_INT from_byte, EMACS_INT to_byte, int prepare)
1640 EMACS_INT from, to;
1642 /* Make args be valid */
1643 if (from_byte < BEGV_BYTE)
1644 from_byte = BEGV_BYTE;
1645 if (to_byte > ZV_BYTE)
1646 to_byte = ZV_BYTE;
1648 if (to_byte <= from_byte)
1649 return;
1651 from = BYTE_TO_CHAR (from_byte);
1652 to = BYTE_TO_CHAR (to_byte);
1654 if (prepare)
1656 EMACS_INT old_from = from, old_to = Z - to;
1657 EMACS_INT range_length = to - from;
1658 prepare_to_modify_buffer (from, to, &from);
1659 to = from + range_length;
1661 if (old_from != from)
1662 from_byte = CHAR_TO_BYTE (from);
1663 if (to > ZV)
1665 to = ZV;
1666 to_byte = ZV_BYTE;
1668 else if (old_to == Z - to)
1669 to_byte = CHAR_TO_BYTE (to);
1672 del_range_2 (from, from_byte, to, to_byte, 0);
1673 signal_after_change (from, to - from, 0);
1674 update_compositions (from, from, CHECK_HEAD);
1677 /* Like del_range_1, but positions are specified both as charpos
1678 and bytepos. */
1680 void
1681 del_range_both (EMACS_INT from, EMACS_INT from_byte,
1682 EMACS_INT to, EMACS_INT to_byte, int prepare)
1684 /* Make args be valid */
1685 if (from_byte < BEGV_BYTE)
1686 from_byte = BEGV_BYTE;
1687 if (to_byte > ZV_BYTE)
1688 to_byte = ZV_BYTE;
1690 if (to_byte <= from_byte)
1691 return;
1693 if (from < BEGV)
1694 from = BEGV;
1695 if (to > ZV)
1696 to = ZV;
1698 if (prepare)
1700 EMACS_INT old_from = from, old_to = Z - to;
1701 EMACS_INT range_length = to - from;
1702 prepare_to_modify_buffer (from, to, &from);
1703 to = from + range_length;
1705 if (old_from != from)
1706 from_byte = CHAR_TO_BYTE (from);
1707 if (to > ZV)
1709 to = ZV;
1710 to_byte = ZV_BYTE;
1712 else if (old_to == Z - to)
1713 to_byte = CHAR_TO_BYTE (to);
1716 del_range_2 (from, from_byte, to, to_byte, 0);
1717 signal_after_change (from, to - from, 0);
1718 update_compositions (from, from, CHECK_HEAD);
1721 /* Delete a range of text, specified both as character positions
1722 and byte positions. FROM and TO are character positions,
1723 while FROM_BYTE and TO_BYTE are byte positions.
1724 If RET_STRING is true, the deleted area is returned as a string. */
1726 Lisp_Object
1727 del_range_2 (EMACS_INT from, EMACS_INT from_byte,
1728 EMACS_INT to, EMACS_INT to_byte, int ret_string)
1730 register EMACS_INT nbytes_del, nchars_del;
1731 Lisp_Object deletion;
1733 CHECK_MARKERS ();
1735 nchars_del = to - from;
1736 nbytes_del = to_byte - from_byte;
1738 /* Make sure the gap is somewhere in or next to what we are deleting. */
1739 if (from > GPT)
1740 gap_right (from, from_byte);
1741 if (to < GPT)
1742 gap_left (to, to_byte, 0);
1744 #ifdef BYTE_COMBINING_DEBUG
1745 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1746 Z_BYTE - to_byte, from, from_byte))
1747 abort ();
1748 #endif
1750 if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
1751 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1752 else
1753 deletion = Qnil;
1755 /* Relocate all markers pointing into the new, larger gap
1756 to point at the end of the text before the gap.
1757 Do this before recording the deletion,
1758 so that undo handles this after reinserting the text. */
1759 adjust_markers_for_delete (from, from_byte, to, to_byte);
1761 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1762 record_delete (from, deletion);
1763 MODIFF++;
1764 CHARS_MODIFF = MODIFF;
1766 /* Relocate point as if it were a marker. */
1767 if (from < PT)
1768 adjust_point (from - (PT < to ? PT : to),
1769 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1771 offset_intervals (current_buffer, from, - nchars_del);
1773 /* Adjust the overlay center as needed. This must be done after
1774 adjusting the markers that bound the overlays. */
1775 adjust_overlays_for_delete (from, nchars_del);
1777 GAP_SIZE += nbytes_del;
1778 ZV_BYTE -= nbytes_del;
1779 Z_BYTE -= nbytes_del;
1780 ZV -= nchars_del;
1781 Z -= nchars_del;
1782 GPT = from;
1783 GPT_BYTE = from_byte;
1784 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1785 /* Put an anchor, unless called from decode_coding_object which
1786 needs to access the previous gap contents. */
1787 *(GPT_ADDR) = 0;
1789 if (GPT_BYTE < GPT)
1790 abort ();
1792 if (GPT - BEG < BEG_UNCHANGED)
1793 BEG_UNCHANGED = GPT - BEG;
1794 if (Z - GPT < END_UNCHANGED)
1795 END_UNCHANGED = Z - GPT;
1797 CHECK_MARKERS ();
1799 evaporate_overlays (from);
1801 return deletion;
1804 /* Call this if you're about to change the region of BUFFER from
1805 character positions START to END. This checks the read-only
1806 properties of the region, calls the necessary modification hooks,
1807 and warns the next redisplay that it should pay attention to that
1808 area.
1810 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1811 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1813 void
1814 modify_region (struct buffer *buffer, EMACS_INT start, EMACS_INT end,
1815 int preserve_chars_modiff)
1817 // printf("modify region\n");
1818 xwidget_modify_region();
1819 struct buffer *old_buffer = current_buffer;
1821 if (buffer != old_buffer)
1822 set_buffer_internal (buffer);
1824 prepare_to_modify_buffer (start, end, NULL);
1826 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
1828 if (MODIFF <= SAVE_MODIFF)
1829 record_first_change ();
1830 MODIFF++;
1831 if (! preserve_chars_modiff)
1832 CHARS_MODIFF = MODIFF;
1834 BVAR (buffer, point_before_scroll) = Qnil;
1836 if (buffer != old_buffer)
1837 set_buffer_internal (old_buffer);
1840 /* Check that it is okay to modify the buffer between START and END,
1841 which are char positions.
1843 Run the before-change-function, if any. If intervals are in use,
1844 verify that the text to be modified is not read-only, and call
1845 any modification properties the text may have.
1847 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1848 by holding its value temporarily in a marker. */
1850 void
1851 prepare_to_modify_buffer (EMACS_INT start, EMACS_INT end,
1852 EMACS_INT *preserve_ptr)
1854 struct buffer *base_buffer;
1856 if (!NILP (BVAR (current_buffer, read_only)))
1857 Fbarf_if_buffer_read_only ();
1859 /* Let redisplay consider other windows than selected_window
1860 if modifying another buffer. */
1861 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
1862 ++windows_or_buffers_changed;
1864 if (BUF_INTERVALS (current_buffer) != 0)
1866 if (preserve_ptr)
1868 Lisp_Object preserve_marker;
1869 struct gcpro gcpro1;
1870 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1871 GCPRO1 (preserve_marker);
1872 verify_interval_modification (current_buffer, start, end);
1873 *preserve_ptr = marker_position (preserve_marker);
1874 unchain_marker (XMARKER (preserve_marker));
1875 UNGCPRO;
1877 else
1878 verify_interval_modification (current_buffer, start, end);
1881 /* For indirect buffers, use the base buffer to check clashes. */
1882 if (current_buffer->base_buffer != 0)
1883 base_buffer = current_buffer->base_buffer;
1884 else
1885 base_buffer = current_buffer;
1887 #ifdef CLASH_DETECTION
1888 if (!NILP (BVAR (base_buffer, file_truename))
1889 /* Make binding buffer-file-name to nil effective. */
1890 && !NILP (BVAR (base_buffer, filename))
1891 && SAVE_MODIFF >= MODIFF)
1892 lock_file (BVAR (base_buffer, file_truename));
1893 #else
1894 /* At least warn if this file has changed on disk since it was visited. */
1895 if (!NILP (BVAR (base_buffer, filename))
1896 && SAVE_MODIFF >= MODIFF
1897 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1898 && !NILP (Ffile_exists_p (BVAR (base_buffer, filename))))
1899 call1 (intern ("ask-user-about-supersession-threat"),
1900 BVAR (base_buffer,filename));
1901 #endif /* not CLASH_DETECTION */
1903 /* If `select-active-regions' is non-nil, save the region text. */
1904 if (!NILP (BVAR (current_buffer, mark_active))
1905 && !inhibit_modification_hooks
1906 && XMARKER (BVAR (current_buffer, mark))->buffer
1907 && NILP (Vsaved_region_selection)
1908 && (EQ (Vselect_active_regions, Qonly)
1909 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
1910 : (!NILP (Vselect_active_regions)
1911 && !NILP (Vtransient_mark_mode))))
1913 EMACS_INT b = XMARKER (BVAR (current_buffer, mark))->charpos;
1914 EMACS_INT e = PT;
1915 if (b < e)
1916 Vsaved_region_selection = make_buffer_string (b, e, 0);
1917 else if (b > e)
1918 Vsaved_region_selection = make_buffer_string (e, b, 0);
1921 signal_before_change (start, end, preserve_ptr);
1923 if (current_buffer->newline_cache)
1924 invalidate_region_cache (current_buffer,
1925 current_buffer->newline_cache,
1926 start - BEG, Z - end);
1927 if (current_buffer->width_run_cache)
1928 invalidate_region_cache (current_buffer,
1929 current_buffer->width_run_cache,
1930 start - BEG, Z - end);
1932 Vdeactivate_mark = Qt;
1935 /* These macros work with an argument named `preserve_ptr'
1936 and a local variable named `preserve_marker'. */
1938 #define PRESERVE_VALUE \
1939 if (preserve_ptr && NILP (preserve_marker)) \
1940 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1942 #define RESTORE_VALUE \
1943 if (! NILP (preserve_marker)) \
1945 *preserve_ptr = marker_position (preserve_marker); \
1946 unchain_marker (XMARKER (preserve_marker)); \
1949 #define PRESERVE_START_END \
1950 if (NILP (start_marker)) \
1951 start_marker = Fcopy_marker (start, Qnil); \
1952 if (NILP (end_marker)) \
1953 end_marker = Fcopy_marker (end, Qnil);
1955 #define FETCH_START \
1956 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1958 #define FETCH_END \
1959 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1961 /* Set a variable to nil if an error occurred.
1962 Don't change the variable if there was no error.
1963 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
1964 VARIABLE is the variable to maybe set to nil.
1965 NO-ERROR-FLAG is nil if there was an error,
1966 anything else meaning no error (so this function does nothing). */
1967 static Lisp_Object
1968 reset_var_on_error (Lisp_Object val)
1970 if (NILP (XCDR (val)))
1971 Fset (XCAR (val), Qnil);
1972 return Qnil;
1975 /* Signal a change to the buffer immediately before it happens.
1976 START_INT and END_INT are the bounds of the text to be changed.
1978 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1979 by holding its value temporarily in a marker. */
1981 static void
1982 signal_before_change (EMACS_INT start_int, EMACS_INT end_int,
1983 EMACS_INT *preserve_ptr)
1985 Lisp_Object start, end;
1986 Lisp_Object start_marker, end_marker;
1987 Lisp_Object preserve_marker;
1988 struct gcpro gcpro1, gcpro2, gcpro3;
1989 int count = SPECPDL_INDEX ();
1991 if (inhibit_modification_hooks)
1992 return;
1994 start = make_number (start_int);
1995 end = make_number (end_int);
1996 preserve_marker = Qnil;
1997 start_marker = Qnil;
1998 end_marker = Qnil;
1999 GCPRO3 (preserve_marker, start_marker, end_marker);
2001 specbind (Qinhibit_modification_hooks, Qt);
2003 /* If buffer is unmodified, run a special hook for that case. The
2004 check for Vfirst_change_hook is just a minor optimization. */
2005 if (SAVE_MODIFF >= MODIFF
2006 && !NILP (Vfirst_change_hook))
2008 PRESERVE_VALUE;
2009 PRESERVE_START_END;
2010 Frun_hooks (1, &Qfirst_change_hook);
2013 /* Now run the before-change-functions if any. */
2014 if (!NILP (Vbefore_change_functions))
2016 Lisp_Object args[3];
2017 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
2019 PRESERVE_VALUE;
2020 PRESERVE_START_END;
2022 /* Mark before-change-functions to be reset to nil in case of error. */
2023 record_unwind_protect (reset_var_on_error, rvoe_arg);
2025 /* Actually run the hook functions. */
2026 args[0] = Qbefore_change_functions;
2027 args[1] = FETCH_START;
2028 args[2] = FETCH_END;
2029 Frun_hook_with_args (3, args);
2031 /* There was no error: unarm the reset_on_error. */
2032 XSETCDR (rvoe_arg, Qt);
2035 if (current_buffer->overlays_before || current_buffer->overlays_after)
2037 PRESERVE_VALUE;
2038 report_overlay_modification (FETCH_START, FETCH_END, 0,
2039 FETCH_START, FETCH_END, Qnil);
2042 if (! NILP (start_marker))
2043 free_marker (start_marker);
2044 if (! NILP (end_marker))
2045 free_marker (end_marker);
2046 RESTORE_VALUE;
2047 UNGCPRO;
2049 unbind_to (count, Qnil);
2052 /* Signal a change immediately after it happens.
2053 CHARPOS is the character position of the start of the changed text.
2054 LENDEL is the number of characters of the text before the change.
2055 (Not the whole buffer; just the part that was changed.)
2056 LENINS is the number of characters in that part of the text
2057 after the change. */
2059 void
2060 signal_after_change (EMACS_INT charpos, EMACS_INT lendel, EMACS_INT lenins)
2062 int count = SPECPDL_INDEX ();
2063 if (inhibit_modification_hooks)
2064 return;
2066 /* If we are deferring calls to the after-change functions
2067 and there are no before-change functions,
2068 just record the args that we were going to use. */
2069 if (! NILP (Vcombine_after_change_calls)
2070 && NILP (Vbefore_change_functions)
2071 && !current_buffer->overlays_before
2072 && !current_buffer->overlays_after)
2074 Lisp_Object elt;
2076 if (!NILP (combine_after_change_list)
2077 && current_buffer != XBUFFER (combine_after_change_buffer))
2078 Fcombine_after_change_execute ();
2080 elt = Fcons (make_number (charpos - BEG),
2081 Fcons (make_number (Z - (charpos - lendel + lenins)),
2082 Fcons (make_number (lenins - lendel), Qnil)));
2083 combine_after_change_list
2084 = Fcons (elt, combine_after_change_list);
2085 combine_after_change_buffer = Fcurrent_buffer ();
2087 return;
2090 if (!NILP (combine_after_change_list))
2091 Fcombine_after_change_execute ();
2093 specbind (Qinhibit_modification_hooks, Qt);
2095 if (!NILP (Vafter_change_functions))
2097 Lisp_Object args[4];
2098 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2100 /* Mark after-change-functions to be reset to nil in case of error. */
2101 record_unwind_protect (reset_var_on_error, rvoe_arg);
2103 /* Actually run the hook functions. */
2104 args[0] = Qafter_change_functions;
2105 XSETFASTINT (args[1], charpos);
2106 XSETFASTINT (args[2], charpos + lenins);
2107 XSETFASTINT (args[3], lendel);
2108 Frun_hook_with_args (4, args);
2110 /* There was no error: unarm the reset_on_error. */
2111 XSETCDR (rvoe_arg, Qt);
2114 if (current_buffer->overlays_before || current_buffer->overlays_after)
2115 report_overlay_modification (make_number (charpos),
2116 make_number (charpos + lenins),
2118 make_number (charpos),
2119 make_number (charpos + lenins),
2120 make_number (lendel));
2122 /* After an insertion, call the text properties
2123 insert-behind-hooks or insert-in-front-hooks. */
2124 if (lendel == 0)
2125 report_interval_modification (make_number (charpos),
2126 make_number (charpos + lenins));
2128 unbind_to (count, Qnil);
2131 static Lisp_Object
2132 Fcombine_after_change_execute_1 (Lisp_Object val)
2134 Vcombine_after_change_calls = val;
2135 return val;
2138 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2139 Scombine_after_change_execute, 0, 0, 0,
2140 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2141 (void)
2143 int count = SPECPDL_INDEX ();
2144 EMACS_INT beg, end, change;
2145 EMACS_INT begpos, endpos;
2146 Lisp_Object tail;
2148 if (NILP (combine_after_change_list))
2149 return Qnil;
2151 /* It is rare for combine_after_change_buffer to be invalid, but
2152 possible. It can happen when combine-after-change-calls is
2153 non-nil, and insertion calls a file handler (e.g. through
2154 lock_file) which scribbles into a temp file -- cyd */
2155 if (!BUFFERP (combine_after_change_buffer)
2156 || NILP (BVAR (XBUFFER (combine_after_change_buffer), name)))
2158 combine_after_change_list = Qnil;
2159 return Qnil;
2162 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2164 Fset_buffer (combine_after_change_buffer);
2166 /* # chars unchanged at beginning of buffer. */
2167 beg = Z - BEG;
2168 /* # chars unchanged at end of buffer. */
2169 end = beg;
2170 /* Total amount of insertion (negative for deletion). */
2171 change = 0;
2173 /* Scan the various individual changes,
2174 accumulating the range info in BEG, END and CHANGE. */
2175 for (tail = combine_after_change_list; CONSP (tail);
2176 tail = XCDR (tail))
2178 Lisp_Object elt;
2179 EMACS_INT thisbeg, thisend, thischange;
2181 /* Extract the info from the next element. */
2182 elt = XCAR (tail);
2183 if (! CONSP (elt))
2184 continue;
2185 thisbeg = XINT (XCAR (elt));
2187 elt = XCDR (elt);
2188 if (! CONSP (elt))
2189 continue;
2190 thisend = XINT (XCAR (elt));
2192 elt = XCDR (elt);
2193 if (! CONSP (elt))
2194 continue;
2195 thischange = XINT (XCAR (elt));
2197 /* Merge this range into the accumulated range. */
2198 change += thischange;
2199 if (thisbeg < beg)
2200 beg = thisbeg;
2201 if (thisend < end)
2202 end = thisend;
2205 /* Get the current start and end positions of the range
2206 that was changed. */
2207 begpos = BEG + beg;
2208 endpos = Z - end;
2210 /* We are about to handle these, so discard them. */
2211 combine_after_change_list = Qnil;
2213 /* Now run the after-change functions for real.
2214 Turn off the flag that defers them. */
2215 record_unwind_protect (Fcombine_after_change_execute_1,
2216 Vcombine_after_change_calls);
2217 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2218 update_compositions (begpos, endpos, CHECK_ALL);
2220 return unbind_to (count, Qnil);
2223 void
2224 syms_of_insdel (void)
2226 staticpro (&combine_after_change_list);
2227 staticpro (&combine_after_change_buffer);
2228 combine_after_change_list = Qnil;
2229 combine_after_change_buffer = Qnil;
2231 DEFVAR_BOOL ("check-markers-debug-flag", check_markers_debug_flag,
2232 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
2233 check_markers_debug_flag = 0;
2234 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
2235 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2236 Vcombine_after_change_calls = Qnil;
2238 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
2239 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2240 This affects `before-change-functions' and `after-change-functions',
2241 as well as hooks attached to text properties and overlays. */);
2242 inhibit_modification_hooks = 0;
2243 Qinhibit_modification_hooks = intern_c_string ("inhibit-modification-hooks");
2244 staticpro (&Qinhibit_modification_hooks);
2246 defsubr (&Scombine_after_change_execute);