1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 #include "intervals.h"
27 #include "character.h"
29 #include "blockinput.h"
30 #include "region-cache.h"
36 static void insert_from_string_1 (Lisp_Object string
,
37 EMACS_INT pos
, EMACS_INT pos_byte
,
38 EMACS_INT nchars
, EMACS_INT nbytes
,
39 int inherit
, int before_markers
);
40 static void insert_from_buffer_1 (struct buffer
*buf
,
41 EMACS_INT from
, EMACS_INT nchars
,
43 static void gap_left (EMACS_INT charpos
, EMACS_INT bytepos
, int newgap
);
44 static void gap_right (EMACS_INT charpos
, EMACS_INT bytepos
);
45 static void adjust_markers_gap_motion (EMACS_INT from
, EMACS_INT to
,
47 static void adjust_markers_for_insert (EMACS_INT from
, EMACS_INT from_byte
,
48 EMACS_INT to
, EMACS_INT to_byte
,
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 Lisp_Object
Fcombine_after_change_execute (void);
56 /* Non-nil means don't call the after-change-functions right away,
57 just record an element in combine_after_change_list. */
58 Lisp_Object Vcombine_after_change_calls
;
60 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
61 describing changes which happened while combine_after_change_calls
62 was nonzero. We use this to decide how to call them
63 once the deferral ends.
66 BEG-UNCHANGED is the number of chars before the changed range.
67 END-UNCHANGED is the number of chars after the changed range,
68 and CHANGE-AMOUNT is the number of characters inserted by the change
69 (negative for a deletion). */
70 Lisp_Object combine_after_change_list
;
72 /* Buffer which combine_after_change_list is about. */
73 Lisp_Object combine_after_change_buffer
;
75 Lisp_Object Qinhibit_modification_hooks
;
77 /* Check all markers in the current buffer, looking for something invalid. */
79 static int check_markers_debug_flag
;
81 #define CHECK_MARKERS() \
82 if (check_markers_debug_flag) \
89 register struct Lisp_Marker
*tail
;
90 int multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
92 for (tail
= BUF_MARKERS (current_buffer
); tail
; tail
= tail
->next
)
94 if (tail
->buffer
->text
!= current_buffer
->text
)
96 if (tail
->charpos
> Z
)
98 if (tail
->bytepos
> Z_BYTE
)
100 if (multibyte
&& ! CHAR_HEAD_P (FETCH_BYTE (tail
->bytepos
)))
105 /* Move gap to position CHARPOS.
106 Note that this can quit! */
109 move_gap (EMACS_INT charpos
)
111 move_gap_both (charpos
, charpos_to_bytepos (charpos
));
114 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
115 Note that this can quit! */
118 move_gap_both (EMACS_INT charpos
, EMACS_INT bytepos
)
120 if (bytepos
< GPT_BYTE
)
121 gap_left (charpos
, bytepos
, 0);
122 else if (bytepos
> GPT_BYTE
)
123 gap_right (charpos
, bytepos
);
126 /* Move the gap to a position less than the current GPT.
127 BYTEPOS describes the new position as a byte position,
128 and CHARPOS is the corresponding char position.
129 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
132 gap_left (EMACS_INT charpos
, EMACS_INT bytepos
, int newgap
)
134 register unsigned char *to
, *from
;
135 register EMACS_INT i
;
139 BUF_COMPUTE_UNCHANGED (current_buffer
, charpos
, GPT
);
146 /* Now copy the characters. To move the gap down,
147 copy characters up. */
151 /* I gets number of characters left to copy. */
152 i
= new_s1
- bytepos
;
155 /* If a quit is requested, stop copying now.
156 Change BYTEPOS to be where we have actually moved the gap to. */
160 charpos
= BYTE_TO_CHAR (bytepos
);
163 /* Move at most 32000 chars before checking again for a quit. */
168 memmove (to
, from
, i
);
171 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
172 BYTEPOS is where the loop above stopped, which may be what was specified
173 or may be where a quit was detected. */
174 adjust_markers_gap_motion (bytepos
, GPT_BYTE
, GAP_SIZE
);
177 if (bytepos
< charpos
)
179 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
183 /* Move the gap to a position greater than the current GPT.
184 BYTEPOS describes the new position as a byte position,
185 and CHARPOS is the corresponding char position. */
188 gap_right (EMACS_INT charpos
, EMACS_INT bytepos
)
190 register unsigned char *to
, *from
;
191 register EMACS_INT i
;
194 BUF_COMPUTE_UNCHANGED (current_buffer
, charpos
, GPT
);
201 /* Now copy the characters. To move the gap up,
202 copy characters down. */
206 /* I gets number of characters left to copy. */
207 i
= bytepos
- new_s1
;
210 /* If a quit is requested, stop copying now.
211 Change BYTEPOS to be where we have actually moved the gap to. */
215 charpos
= BYTE_TO_CHAR (bytepos
);
218 /* Move at most 32000 chars before checking again for a quit. */
222 memmove (to
, from
, i
);
226 adjust_markers_gap_motion (GPT_BYTE
+ GAP_SIZE
, bytepos
+ GAP_SIZE
,
230 if (bytepos
< charpos
)
232 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
236 /* Add AMOUNT to the byte position of every marker in the current buffer
237 whose current byte position is between FROM (exclusive) and TO (inclusive).
239 Also, any markers past the outside of that interval, in the direction
240 of adjustment, are first moved back to the near end of the interval
241 and then adjusted by AMOUNT.
243 When the latter adjustment is done, if AMOUNT is negative,
244 we record the adjustment for undo. (This case happens only for
247 The markers' character positions are not altered,
248 because gap motion does not affect character positions. */
250 int adjust_markers_test
;
253 adjust_markers_gap_motion (EMACS_INT from
, EMACS_INT to
, EMACS_INT amount
)
255 /* Now that a marker has a bytepos, not counting the gap,
256 nothing needs to be done here. */
259 register struct Lisp_Marker
*m
;
260 register EMACS_INT mpos
;
262 marker
= BUF_MARKERS (current_buffer
);
264 while (!NILP (marker
))
266 m
= XMARKER (marker
);
270 if (mpos
> to
&& mpos
< to
+ amount
)
272 if (adjust_markers_test
)
279 /* Here's the case where a marker is inside text being deleted.
280 AMOUNT can be negative for gap motion, too,
281 but then this range contains no markers. */
282 if (mpos
> from
+ amount
&& mpos
<= from
)
284 if (adjust_markers_test
)
286 mpos
= from
+ amount
;
289 if (mpos
> from
&& mpos
<= to
)
297 /* Adjust all markers for a deletion
298 whose range in bytes is FROM_BYTE to TO_BYTE.
299 The range in charpos is FROM to TO.
301 This function assumes that the gap is adjacent to
302 or inside of the range being deleted. */
305 adjust_markers_for_delete (EMACS_INT from
, EMACS_INT from_byte
,
306 EMACS_INT to
, EMACS_INT to_byte
)
309 register struct Lisp_Marker
*m
;
310 register EMACS_INT charpos
;
312 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
314 charpos
= m
->charpos
;
319 /* If the marker is after the deletion,
320 relocate by number of chars / bytes deleted. */
323 m
->charpos
-= to
- from
;
324 m
->bytepos
-= to_byte
- from_byte
;
326 /* Here's the case where a marker is inside text being deleted. */
327 else if (charpos
> from
)
329 if (! m
->insertion_type
)
330 { /* Normal markers will end up at the beginning of the
331 re-inserted text after undoing a deletion, and must be
332 adjusted to move them to the correct place. */
333 XSETMISC (marker
, m
);
334 record_marker_adjustment (marker
, from
- charpos
);
336 else if (charpos
< to
)
337 { /* Before-insertion markers will automatically move forward
338 upon re-inserting the deleted text, so we have to arrange
339 for them to move backward to the correct position. */
340 XSETMISC (marker
, m
);
341 record_marker_adjustment (marker
, to
- charpos
);
344 m
->bytepos
= from_byte
;
346 /* Here's the case where a before-insertion marker is immediately
347 before the deleted region. */
348 else if (charpos
== from
&& m
->insertion_type
)
350 /* Undoing the change uses normal insertion, which will
351 incorrectly make MARKER move forward, so we arrange for it
352 to then move backward to the correct place at the beginning
353 of the deleted region. */
354 XSETMISC (marker
, m
);
355 record_marker_adjustment (marker
, to
- from
);
361 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
362 to TO / TO_BYTE. We have to relocate the charpos of every marker
363 that points after the insertion (but not their bytepos).
365 When a marker points at the insertion point,
366 we advance it if either its insertion-type is t
367 or BEFORE_MARKERS is true. */
370 adjust_markers_for_insert (EMACS_INT from
, EMACS_INT from_byte
,
371 EMACS_INT to
, EMACS_INT to_byte
, int before_markers
)
373 struct Lisp_Marker
*m
;
375 EMACS_INT nchars
= to
- from
;
376 EMACS_INT nbytes
= to_byte
- from_byte
;
378 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
380 eassert (m
->bytepos
>= m
->charpos
381 && m
->bytepos
- m
->charpos
<= Z_BYTE
- Z
);
383 if (m
->bytepos
== from_byte
)
385 if (m
->insertion_type
|| before_markers
)
387 m
->bytepos
= to_byte
;
389 if (m
->insertion_type
)
393 else if (m
->bytepos
> from_byte
)
395 m
->bytepos
+= nbytes
;
396 m
->charpos
+= nchars
;
400 /* Adjusting only markers whose insertion-type is t may result in
401 - disordered start and end in overlays, and
402 - disordered overlays in the slot `overlays_before' of current_buffer. */
405 fix_start_end_in_overlays(from
, to
);
406 fix_overlays_before (current_buffer
, from
, to
);
410 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
412 This is used only when the value of point changes due to an insert
413 or delete; it does not represent a conceptual change in point as a
414 marker. In particular, point is not crossing any interval
415 boundaries, so there's no need to use the usual SET_PT macro. In
416 fact it would be incorrect to do so, because either the old or the
417 new value of point is out of sync with the current set of
421 adjust_point (EMACS_INT nchars
, EMACS_INT nbytes
)
423 BUF_PT (current_buffer
) += nchars
;
424 BUF_PT_BYTE (current_buffer
) += nbytes
;
426 /* In a single-byte buffer, the two positions must be equal. */
427 eassert (PT_BYTE
>= PT
&& PT_BYTE
- PT
<= ZV_BYTE
- ZV
);
430 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
431 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
432 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
436 adjust_markers_for_replace (EMACS_INT from
, EMACS_INT from_byte
,
437 EMACS_INT old_chars
, EMACS_INT old_bytes
,
438 EMACS_INT new_chars
, EMACS_INT new_bytes
)
440 register struct Lisp_Marker
*m
;
441 EMACS_INT prev_to_byte
= from_byte
+ old_bytes
;
442 EMACS_INT diff_chars
= new_chars
- old_chars
;
443 EMACS_INT diff_bytes
= new_bytes
- old_bytes
;
445 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
447 if (m
->bytepos
>= prev_to_byte
)
449 m
->charpos
+= diff_chars
;
450 m
->bytepos
+= diff_bytes
;
452 else if (m
->bytepos
> from_byte
)
455 m
->bytepos
= from_byte
;
463 /* Make the gap NBYTES_ADDED bytes longer. */
466 make_gap_larger (EMACS_INT nbytes_added
)
469 EMACS_INT real_gap_loc
;
470 EMACS_INT real_gap_loc_byte
;
471 EMACS_INT old_gap_size
;
473 /* If we have to get more space, get enough to last a while. */
474 nbytes_added
+= 2000;
476 { EMACS_INT total_size
= Z_BYTE
- BEG_BYTE
+ GAP_SIZE
+ nbytes_added
;
478 /* Don't allow a buffer size that won't fit in a Lisp integer. */
479 || total_size
!= XINT (make_number (total_size
))
480 /* Don't allow a buffer size that won't fit in an int
481 even if it will fit in a Lisp integer.
482 That won't work because so many places still use `int'. */
483 || total_size
!= (EMACS_INT
) (int) total_size
)
484 error ("Buffer exceeds maximum size");
487 enlarge_buffer_text (current_buffer
, nbytes_added
);
489 /* Prevent quitting in move_gap. */
494 real_gap_loc_byte
= GPT_BYTE
;
495 old_gap_size
= GAP_SIZE
;
497 /* Call the newly allocated space a gap at the end of the whole space. */
499 GPT_BYTE
= Z_BYTE
+ GAP_SIZE
;
500 GAP_SIZE
= nbytes_added
;
502 /* Move the new gap down to be consecutive with the end of the old one.
503 This adjusts the markers properly too. */
504 gap_left (real_gap_loc
+ old_gap_size
, real_gap_loc_byte
+ old_gap_size
, 1);
506 /* Now combine the two into one large gap. */
507 GAP_SIZE
+= old_gap_size
;
509 GPT_BYTE
= real_gap_loc_byte
;
518 /* Make the gap NBYTES_REMOVED bytes shorter. */
521 make_gap_smaller (EMACS_INT nbytes_removed
)
524 EMACS_INT real_gap_loc
;
525 EMACS_INT real_gap_loc_byte
;
527 EMACS_INT real_Z_byte
;
528 EMACS_INT real_beg_unchanged
;
529 EMACS_INT new_gap_size
;
531 /* Make sure the gap is at least 20 bytes. */
532 if (GAP_SIZE
- nbytes_removed
< 20)
533 nbytes_removed
= GAP_SIZE
- 20;
535 /* Prevent quitting in move_gap. */
540 real_gap_loc_byte
= GPT_BYTE
;
541 new_gap_size
= GAP_SIZE
- nbytes_removed
;
543 real_Z_byte
= Z_BYTE
;
544 real_beg_unchanged
= BEG_UNCHANGED
;
546 /* Pretend that the last unwanted part of the gap is the entire gap,
547 and that the first desired part of the gap is part of the buffer
549 memset (GPT_ADDR
, 0, new_gap_size
);
551 GPT_BYTE
+= new_gap_size
;
553 Z_BYTE
+= new_gap_size
;
554 GAP_SIZE
= nbytes_removed
;
556 /* Move the unwanted pretend gap to the end of the buffer. This
557 adjusts the markers properly too. */
558 gap_right (Z
, Z_BYTE
);
560 enlarge_buffer_text (current_buffer
, -nbytes_removed
);
562 /* Now restore the desired gap. */
563 GAP_SIZE
= new_gap_size
;
565 GPT_BYTE
= real_gap_loc_byte
;
567 Z_BYTE
= real_Z_byte
;
568 BEG_UNCHANGED
= real_beg_unchanged
;
577 make_gap (EMACS_INT nbytes_added
)
579 if (nbytes_added
>= 0)
580 make_gap_larger (nbytes_added
);
581 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
583 make_gap_smaller (-nbytes_added
);
587 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
588 FROM_MULTIBYTE says whether the incoming text is multibyte.
589 TO_MULTIBYTE says whether to store the text as multibyte.
590 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
592 Return the number of bytes stored at TO_ADDR. */
595 copy_text (const unsigned char *from_addr
, unsigned char *to_addr
,
596 EMACS_INT nbytes
, int from_multibyte
, int to_multibyte
)
598 if (from_multibyte
== to_multibyte
)
600 memcpy (to_addr
, from_addr
, nbytes
);
603 else if (from_multibyte
)
605 EMACS_INT nchars
= 0;
606 EMACS_INT bytes_left
= nbytes
;
607 Lisp_Object tbl
= Qnil
;
609 while (bytes_left
> 0)
612 c
= STRING_CHAR_AND_LENGTH (from_addr
, thislen
);
613 if (! ASCII_CHAR_P (c
))
616 from_addr
+= thislen
;
617 bytes_left
-= thislen
;
624 unsigned char *initial_to_addr
= to_addr
;
626 /* Convert single-byte to multibyte. */
629 int c
= *from_addr
++;
631 if (!ASCII_CHAR_P (c
))
633 c
= BYTE8_TO_CHAR (c
);
634 to_addr
+= CHAR_STRING (c
, to_addr
);
638 /* Special case for speed. */
639 *to_addr
++ = c
, nbytes
--;
641 return to_addr
- initial_to_addr
;
645 /* Return the number of bytes it would take
646 to convert some single-byte text to multibyte.
647 The single-byte text consists of NBYTES bytes at PTR. */
650 count_size_as_multibyte (const unsigned char *ptr
, EMACS_INT nbytes
)
653 EMACS_INT outgoing_nbytes
= 0;
655 for (i
= 0; i
< nbytes
; i
++)
657 unsigned int c
= *ptr
++;
659 if (ASCII_CHAR_P (c
))
663 c
= BYTE8_TO_CHAR (c
);
664 outgoing_nbytes
+= CHAR_BYTES (c
);
668 return outgoing_nbytes
;
671 /* Insert a string of specified length before point.
672 This function judges multibyteness based on
673 enable_multibyte_characters in the current buffer;
674 it never converts between single-byte and multibyte.
676 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
677 prepare_to_modify_buffer could relocate the text. */
680 insert (const unsigned char *string
, EMACS_INT nbytes
)
684 EMACS_INT len
= chars_in_text (string
, nbytes
), opoint
;
685 insert_1_both (string
, len
, nbytes
, 0, 1, 0);
687 signal_after_change (opoint
, 0, len
);
688 update_compositions (opoint
, PT
, CHECK_BORDER
);
692 /* Likewise, but inherit text properties from neighboring characters. */
695 insert_and_inherit (const unsigned char *string
, EMACS_INT nbytes
)
699 EMACS_INT len
= chars_in_text (string
, nbytes
), opoint
;
700 insert_1_both (string
, len
, nbytes
, 1, 1, 0);
702 signal_after_change (opoint
, 0, len
);
703 update_compositions (opoint
, PT
, CHECK_BORDER
);
707 /* Insert the character C before point. Do not inherit text properties. */
712 unsigned char str
[MAX_MULTIBYTE_LENGTH
];
715 if (! NILP (current_buffer
->enable_multibyte_characters
))
716 len
= CHAR_STRING (c
, str
);
726 /* Insert the null-terminated string S before point. */
729 insert_string (const char *s
)
731 insert (s
, strlen (s
));
734 /* Like `insert' except that all markers pointing at the place where
735 the insertion happens are adjusted to point after it.
736 Don't use this function to insert part of a Lisp string,
737 since gc could happen and relocate it. */
740 insert_before_markers (const unsigned char *string
, EMACS_INT nbytes
)
744 EMACS_INT len
= chars_in_text (string
, nbytes
), opoint
;
745 insert_1_both (string
, len
, nbytes
, 0, 1, 1);
747 signal_after_change (opoint
, 0, len
);
748 update_compositions (opoint
, PT
, CHECK_BORDER
);
752 /* Likewise, but inherit text properties from neighboring characters. */
755 insert_before_markers_and_inherit (const unsigned char *string
,
760 EMACS_INT len
= chars_in_text (string
, nbytes
), opoint
;
761 insert_1_both (string
, len
, nbytes
, 1, 1, 1);
763 signal_after_change (opoint
, 0, len
);
764 update_compositions (opoint
, PT
, CHECK_BORDER
);
768 /* Subroutine used by the insert functions above. */
771 insert_1 (const unsigned char *string
, EMACS_INT nbytes
,
772 int inherit
, int prepare
, int before_markers
)
774 insert_1_both (string
, chars_in_text (string
, nbytes
), nbytes
,
775 inherit
, prepare
, before_markers
);
779 #ifdef BYTE_COMBINING_DEBUG
781 /* See if the bytes before POS/POS_BYTE combine with bytes
782 at the start of STRING to form a single character.
783 If so, return the number of bytes at the start of STRING
784 which combine in this way. Otherwise, return 0. */
787 count_combining_before (const unsigned char *string
, EMACS_INT length
,
788 EMACS_INT pos
, EMACS_INT pos_byte
)
790 int len
, combining_bytes
;
791 const unsigned char *p
;
793 if (NILP (current_buffer
->enable_multibyte_characters
))
796 /* At first, we can exclude the following cases:
797 (1) STRING[0] can't be a following byte of multibyte sequence.
798 (2) POS is the start of the current buffer.
799 (3) A character before POS is not a multibyte character. */
800 if (length
== 0 || CHAR_HEAD_P (*string
)) /* case (1) */
802 if (pos_byte
== BEG_BYTE
) /* case (2) */
805 p
= BYTE_POS_ADDR (pos_byte
- 1);
806 while (! CHAR_HEAD_P (*p
)) p
--, len
++;
807 if (! LEADING_CODE_P (*p
)) /* case (3) */
810 combining_bytes
= BYTES_BY_CHAR_HEAD (*p
) - len
;
811 if (combining_bytes
<= 0)
812 /* The character preceding POS is, complete and no room for
813 combining bytes (combining_bytes == 0), or an independent 8-bit
814 character (combining_bytes < 0). */
817 /* We have a combination situation. Count the bytes at STRING that
820 while (!CHAR_HEAD_P (*p
) && p
< string
+ length
)
823 return (combining_bytes
< p
- string
? combining_bytes
: p
- string
);
826 /* See if the bytes after POS/POS_BYTE combine with bytes
827 at the end of STRING to form a single character.
828 If so, return the number of bytes after POS/POS_BYTE
829 which combine in this way. Otherwise, return 0. */
832 count_combining_after (const unsigned char *string
,
833 EMACS_INT length
, EMACS_INT pos
, EMACS_INT pos_byte
)
835 EMACS_INT opos_byte
= pos_byte
;
840 if (NILP (current_buffer
->enable_multibyte_characters
))
843 /* At first, we can exclude the following cases:
844 (1) The last byte of STRING is an ASCII.
845 (2) POS is the last of the current buffer.
846 (3) A character at POS can't be a following byte of multibyte
848 if (length
> 0 && ASCII_BYTE_P (string
[length
- 1])) /* case (1) */
850 if (pos_byte
== Z_BYTE
) /* case (2) */
852 bufp
= BYTE_POS_ADDR (pos_byte
);
853 if (CHAR_HEAD_P (*bufp
)) /* case (3) */
857 while (i
>= 0 && ! CHAR_HEAD_P (string
[i
]))
863 /* All characters in STRING are not character head. We must
864 check also preceding bytes at POS. We are sure that the gap
866 unsigned char *p
= BEG_ADDR
;
868 while (i
>= 0 && ! CHAR_HEAD_P (p
[i
]))
870 if (i
< 0 || !LEADING_CODE_P (p
[i
]))
873 bytes
= BYTES_BY_CHAR_HEAD (p
[i
]);
874 return (bytes
<= pos_byte
- 1 - i
+ length
876 : bytes
- (pos_byte
- 1 - i
+ length
));
878 if (!LEADING_CODE_P (string
[i
]))
881 bytes
= BYTES_BY_CHAR_HEAD (string
[i
]) - (length
- i
);
883 while (!CHAR_HEAD_P (*bufp
)) bufp
++, pos_byte
++;
885 return (bytes
<= pos_byte
- opos_byte
? bytes
: pos_byte
- opos_byte
);
891 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
892 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
893 are the same as in insert_1. */
896 insert_1_both (const unsigned char *string
,
897 EMACS_INT nchars
, EMACS_INT nbytes
,
898 int inherit
, int prepare
, int before_markers
)
903 if (NILP (current_buffer
->enable_multibyte_characters
))
907 /* Do this before moving and increasing the gap,
908 because the before-change hooks might move the gap
909 or make it smaller. */
910 prepare_to_modify_buffer (PT
, PT
, NULL
);
913 move_gap_both (PT
, PT_BYTE
);
914 if (GAP_SIZE
< nbytes
)
915 make_gap (nbytes
- GAP_SIZE
);
917 #ifdef BYTE_COMBINING_DEBUG
918 if (count_combining_before (string
, nbytes
, PT
, PT_BYTE
)
919 || count_combining_after (string
, nbytes
, PT
, PT_BYTE
))
923 /* Record deletion of the surrounding text that combines with
924 the insertion. This, together with recording the insertion,
925 will add up to the right stuff in the undo list. */
926 record_insert (PT
, nchars
);
928 CHARS_MODIFF
= MODIFF
;
930 memcpy (GPT_ADDR
, string
, nbytes
);
939 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
944 /* The insert may have been in the unchanged region, so check again. */
945 if (Z
- GPT
< END_UNCHANGED
)
946 END_UNCHANGED
= Z
- GPT
;
948 adjust_overlays_for_insert (PT
, nchars
);
949 adjust_markers_for_insert (PT
, PT_BYTE
,
950 PT
+ nchars
, PT_BYTE
+ nbytes
,
953 if (BUF_INTERVALS (current_buffer
) != 0)
954 offset_intervals (current_buffer
, PT
, nchars
);
956 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
957 set_text_properties (make_number (PT
), make_number (PT
+ nchars
),
960 adjust_point (nchars
, nbytes
);
965 /* Insert the part of the text of STRING, a Lisp object assumed to be
966 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
967 starting at position POS / POS_BYTE. If the text of STRING has properties,
968 copy them into the buffer.
970 It does not work to use `insert' for this, because a GC could happen
971 before we copy the stuff into the buffer, and relocate the string
972 without insert noticing. */
975 insert_from_string (Lisp_Object string
, EMACS_INT pos
, EMACS_INT pos_byte
,
976 EMACS_INT length
, EMACS_INT length_byte
, int inherit
)
978 EMACS_INT opoint
= PT
;
980 if (SCHARS (string
) == 0)
983 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
985 signal_after_change (opoint
, 0, PT
- opoint
);
986 update_compositions (opoint
, PT
, CHECK_BORDER
);
989 /* Like `insert_from_string' except that all markers pointing
990 at the place where the insertion happens are adjusted to point after it. */
993 insert_from_string_before_markers (Lisp_Object string
,
994 EMACS_INT pos
, EMACS_INT pos_byte
,
995 EMACS_INT length
, EMACS_INT length_byte
,
998 EMACS_INT opoint
= PT
;
1000 if (SCHARS (string
) == 0)
1003 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
1005 signal_after_change (opoint
, 0, PT
- opoint
);
1006 update_compositions (opoint
, PT
, CHECK_BORDER
);
1009 /* Subroutine of the insertion functions above. */
1012 insert_from_string_1 (Lisp_Object string
, EMACS_INT pos
, EMACS_INT pos_byte
,
1013 EMACS_INT nchars
, EMACS_INT nbytes
,
1014 int inherit
, int before_markers
)
1016 struct gcpro gcpro1
;
1017 EMACS_INT outgoing_nbytes
= nbytes
;
1020 /* Make OUTGOING_NBYTES describe the text
1021 as it will be inserted in this buffer. */
1023 if (NILP (current_buffer
->enable_multibyte_characters
))
1024 outgoing_nbytes
= nchars
;
1025 else if (! STRING_MULTIBYTE (string
))
1027 = count_size_as_multibyte (SDATA (string
) + pos_byte
,
1031 /* Do this before moving and increasing the gap,
1032 because the before-change hooks might move the gap
1033 or make it smaller. */
1034 prepare_to_modify_buffer (PT
, PT
, NULL
);
1037 move_gap_both (PT
, PT_BYTE
);
1038 if (GAP_SIZE
< outgoing_nbytes
)
1039 make_gap (outgoing_nbytes
- GAP_SIZE
);
1042 /* Copy the string text into the buffer, perhaps converting
1043 between single-byte and multibyte. */
1044 copy_text (SDATA (string
) + pos_byte
, GPT_ADDR
, nbytes
,
1045 STRING_MULTIBYTE (string
),
1046 ! NILP (current_buffer
->enable_multibyte_characters
));
1048 #ifdef BYTE_COMBINING_DEBUG
1049 /* We have copied text into the gap, but we have not altered
1050 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1051 to these functions and get the same results as we would
1052 have got earlier on. Meanwhile, PT_ADDR does point to
1053 the text that has been stored by copy_text. */
1054 if (count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
)
1055 || count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
))
1059 record_insert (PT
, nchars
);
1061 CHARS_MODIFF
= MODIFF
;
1063 GAP_SIZE
-= outgoing_nbytes
;
1067 GPT_BYTE
+= outgoing_nbytes
;
1068 ZV_BYTE
+= outgoing_nbytes
;
1069 Z_BYTE
+= outgoing_nbytes
;
1070 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1075 /* The insert may have been in the unchanged region, so check again. */
1076 if (Z
- GPT
< END_UNCHANGED
)
1077 END_UNCHANGED
= Z
- GPT
;
1079 adjust_overlays_for_insert (PT
, nchars
);
1080 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1081 PT_BYTE
+ outgoing_nbytes
,
1084 offset_intervals (current_buffer
, PT
, nchars
);
1086 intervals
= STRING_INTERVALS (string
);
1087 /* Get the intervals for the part of the string we are inserting. */
1088 if (nbytes
< SBYTES (string
))
1089 intervals
= copy_intervals (intervals
, pos
, nchars
);
1091 /* Insert those intervals. */
1092 graft_intervals_into_buffer (intervals
, PT
, nchars
,
1093 current_buffer
, inherit
);
1095 adjust_point (nchars
, outgoing_nbytes
);
1100 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1101 starting at GPT_ADDR. */
1104 insert_from_gap (EMACS_INT nchars
, EMACS_INT nbytes
)
1106 if (NILP (current_buffer
->enable_multibyte_characters
))
1109 record_insert (GPT
, nchars
);
1119 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1124 adjust_overlays_for_insert (GPT
- nchars
, nchars
);
1125 adjust_markers_for_insert (GPT
- nchars
, GPT_BYTE
- nbytes
,
1128 if (BUF_INTERVALS (current_buffer
) != 0)
1130 offset_intervals (current_buffer
, GPT
- nchars
, nchars
);
1131 graft_intervals_into_buffer (NULL_INTERVAL
, GPT
- nchars
, nchars
,
1135 if (GPT
- nchars
< PT
)
1136 adjust_point (nchars
, nbytes
);
1141 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1142 current buffer. If the text in BUF has properties, they are absorbed
1143 into the current buffer.
1145 It does not work to use `insert' for this, because a malloc could happen
1146 and relocate BUF's text before the copy happens. */
1149 insert_from_buffer (struct buffer
*buf
,
1150 EMACS_INT charpos
, EMACS_INT nchars
, int inherit
)
1152 EMACS_INT opoint
= PT
;
1154 insert_from_buffer_1 (buf
, charpos
, nchars
, inherit
);
1155 signal_after_change (opoint
, 0, PT
- opoint
);
1156 update_compositions (opoint
, PT
, CHECK_BORDER
);
1160 insert_from_buffer_1 (struct buffer
*buf
,
1161 EMACS_INT from
, EMACS_INT nchars
, int inherit
)
1163 register Lisp_Object temp
;
1164 EMACS_INT chunk
, chunk_expanded
;
1165 EMACS_INT from_byte
= buf_charpos_to_bytepos (buf
, from
);
1166 EMACS_INT to_byte
= buf_charpos_to_bytepos (buf
, from
+ nchars
);
1167 EMACS_INT incoming_nbytes
= to_byte
- from_byte
;
1168 EMACS_INT outgoing_nbytes
= incoming_nbytes
;
1171 /* Make OUTGOING_NBYTES describe the text
1172 as it will be inserted in this buffer. */
1174 if (NILP (current_buffer
->enable_multibyte_characters
))
1175 outgoing_nbytes
= nchars
;
1176 else if (NILP (buf
->enable_multibyte_characters
))
1178 EMACS_INT outgoing_before_gap
= 0;
1179 EMACS_INT outgoing_after_gap
= 0;
1181 if (from
< BUF_GPT (buf
))
1183 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1184 if (chunk
> incoming_nbytes
)
1185 chunk
= incoming_nbytes
;
1187 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
, from_byte
),
1193 if (chunk
< incoming_nbytes
)
1195 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
,
1197 incoming_nbytes
- chunk
);
1199 outgoing_nbytes
= outgoing_before_gap
+ outgoing_after_gap
;
1202 /* Make sure point-max won't overflow after this insertion. */
1203 XSETINT (temp
, outgoing_nbytes
+ Z
);
1204 if (outgoing_nbytes
+ Z
!= XINT (temp
))
1205 error ("Maximum buffer size exceeded");
1207 /* Do this before moving and increasing the gap,
1208 because the before-change hooks might move the gap
1209 or make it smaller. */
1210 prepare_to_modify_buffer (PT
, PT
, NULL
);
1213 move_gap_both (PT
, PT_BYTE
);
1214 if (GAP_SIZE
< outgoing_nbytes
)
1215 make_gap (outgoing_nbytes
- GAP_SIZE
);
1217 if (from
< BUF_GPT (buf
))
1219 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1220 if (chunk
> incoming_nbytes
)
1221 chunk
= incoming_nbytes
;
1222 /* Record number of output bytes, so we know where
1223 to put the output from the second copy_text. */
1225 = copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
),
1227 ! NILP (buf
->enable_multibyte_characters
),
1228 ! NILP (current_buffer
->enable_multibyte_characters
));
1231 chunk_expanded
= chunk
= 0;
1233 if (chunk
< incoming_nbytes
)
1234 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
+ chunk
),
1235 GPT_ADDR
+ chunk_expanded
, incoming_nbytes
- chunk
,
1236 ! NILP (buf
->enable_multibyte_characters
),
1237 ! NILP (current_buffer
->enable_multibyte_characters
));
1239 #ifdef BYTE_COMBINING_DEBUG
1240 /* We have copied text into the gap, but we have not altered
1241 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1242 to these functions and get the same results as we would
1243 have got earlier on. Meanwhile, GPT_ADDR does point to
1244 the text that has been stored by copy_text. */
1245 if (count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
)
1246 || count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
))
1250 record_insert (PT
, nchars
);
1252 CHARS_MODIFF
= MODIFF
;
1254 GAP_SIZE
-= outgoing_nbytes
;
1258 GPT_BYTE
+= outgoing_nbytes
;
1259 ZV_BYTE
+= outgoing_nbytes
;
1260 Z_BYTE
+= outgoing_nbytes
;
1261 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1266 /* The insert may have been in the unchanged region, so check again. */
1267 if (Z
- GPT
< END_UNCHANGED
)
1268 END_UNCHANGED
= Z
- GPT
;
1270 adjust_overlays_for_insert (PT
, nchars
);
1271 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1272 PT_BYTE
+ outgoing_nbytes
,
1275 if (BUF_INTERVALS (current_buffer
) != 0)
1276 offset_intervals (current_buffer
, PT
, nchars
);
1278 /* Get the intervals for the part of the string we are inserting. */
1279 intervals
= BUF_INTERVALS (buf
);
1280 if (nchars
< BUF_Z (buf
) - BUF_BEG (buf
))
1282 if (buf
== current_buffer
&& PT
<= from
)
1284 intervals
= copy_intervals (intervals
, from
, nchars
);
1287 /* Insert those intervals. */
1288 graft_intervals_into_buffer (intervals
, PT
, nchars
, current_buffer
, inherit
);
1290 adjust_point (nchars
, outgoing_nbytes
);
1293 /* Record undo information and adjust markers and position keepers for
1294 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1295 chars (LEN_BYTE bytes) which resides in the gap just after
1298 PREV_TEXT nil means the new text was just inserted. */
1301 adjust_after_replace (EMACS_INT from
, EMACS_INT from_byte
,
1302 Lisp_Object prev_text
, EMACS_INT len
, EMACS_INT len_byte
)
1304 EMACS_INT nchars_del
= 0, nbytes_del
= 0;
1306 #ifdef BYTE_COMBINING_DEBUG
1307 if (count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
)
1308 || count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
))
1312 if (STRINGP (prev_text
))
1314 nchars_del
= SCHARS (prev_text
);
1315 nbytes_del
= SBYTES (prev_text
);
1318 /* Update various buffer positions for the new text. */
1319 GAP_SIZE
-= len_byte
;
1321 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1322 GPT
+= len
; GPT_BYTE
+= len_byte
;
1323 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1326 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1329 adjust_markers_for_insert (from
, from_byte
,
1330 from
+ len
, from_byte
+ len_byte
, 0);
1332 if (! EQ (current_buffer
->undo_list
, Qt
))
1335 record_delete (from
, prev_text
);
1336 record_insert (from
, len
);
1339 if (len
> nchars_del
)
1340 adjust_overlays_for_insert (from
, len
- nchars_del
);
1341 else if (len
< nchars_del
)
1342 adjust_overlays_for_delete (from
, nchars_del
- len
);
1343 if (BUF_INTERVALS (current_buffer
) != 0)
1345 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1349 adjust_point (len
- nchars_del
, len_byte
- nbytes_del
);
1351 /* As byte combining will decrease Z, we must check this again. */
1352 if (Z
- GPT
< END_UNCHANGED
)
1353 END_UNCHANGED
= Z
- GPT
;
1358 evaporate_overlays (from
);
1360 CHARS_MODIFF
= MODIFF
;
1363 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
1364 This is for use when undo is not enabled in the current buffer. */
1367 adjust_after_replace_noundo (EMACS_INT from
, EMACS_INT from_byte
,
1368 EMACS_INT nchars_del
, EMACS_INT nbytes_del
,
1369 EMACS_INT len
, EMACS_INT len_byte
)
1371 #ifdef BYTE_COMBINING_DEBUG
1372 if (count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
)
1373 || count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
))
1377 /* Update various buffer positions for the new text. */
1378 GAP_SIZE
-= len_byte
;
1380 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1381 GPT
+= len
; GPT_BYTE
+= len_byte
;
1382 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1385 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1388 adjust_markers_for_insert (from
, from_byte
,
1389 from
+ len
, from_byte
+ len_byte
, 0);
1391 if (len
> nchars_del
)
1392 adjust_overlays_for_insert (from
, len
- nchars_del
);
1393 else if (len
< nchars_del
)
1394 adjust_overlays_for_delete (from
, nchars_del
- len
);
1395 if (BUF_INTERVALS (current_buffer
) != 0)
1397 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1401 adjust_point (len
- nchars_del
, len_byte
- nbytes_del
);
1403 /* As byte combining will decrease Z, we must check this again. */
1404 if (Z
- GPT
< END_UNCHANGED
)
1405 END_UNCHANGED
= Z
- GPT
;
1410 evaporate_overlays (from
);
1412 CHARS_MODIFF
= MODIFF
;
1415 /* Record undo information, adjust markers and position keepers for an
1416 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1417 text already exists in the current buffer but character length (TO
1418 - FROM) may be incorrect, the correct length is NEWLEN. */
1421 adjust_after_insert (EMACS_INT from
, EMACS_INT from_byte
,
1422 EMACS_INT to
, EMACS_INT to_byte
, EMACS_INT newlen
)
1424 EMACS_INT len
= to
- from
, len_byte
= to_byte
- from_byte
;
1427 move_gap_both (to
, to_byte
);
1428 GAP_SIZE
+= len_byte
;
1429 GPT
-= len
; GPT_BYTE
-= len_byte
;
1430 ZV
-= len
; ZV_BYTE
-= len_byte
;
1431 Z
-= len
; Z_BYTE
-= len_byte
;
1432 adjust_after_replace (from
, from_byte
, Qnil
, newlen
, len_byte
);
1435 /* Replace the text from character positions FROM to TO with NEW,
1436 If PREPARE is nonzero, call prepare_to_modify_buffer.
1437 If INHERIT, the newly inserted text should inherit text properties
1438 from the surrounding non-deleted text. */
1440 /* Note that this does not yet handle markers quite right.
1441 Also it needs to record a single undo-entry that does a replacement
1442 rather than a separate delete and insert.
1443 That way, undo will also handle markers properly.
1445 But if MARKERS is 0, don't relocate markers. */
1448 replace_range (EMACS_INT from
, EMACS_INT to
, Lisp_Object
new,
1449 int prepare
, int inherit
, int markers
)
1451 EMACS_INT inschars
= SCHARS (new);
1452 EMACS_INT insbytes
= SBYTES (new);
1453 EMACS_INT from_byte
, to_byte
;
1454 EMACS_INT nbytes_del
, nchars_del
;
1455 register Lisp_Object temp
;
1456 struct gcpro gcpro1
;
1458 EMACS_INT outgoing_insbytes
= insbytes
;
1459 Lisp_Object deletion
;
1468 EMACS_INT range_length
= to
- from
;
1469 prepare_to_modify_buffer (from
, to
, &from
);
1470 to
= from
+ range_length
;
1475 /* Make args be valid */
1481 from_byte
= CHAR_TO_BYTE (from
);
1482 to_byte
= CHAR_TO_BYTE (to
);
1484 nchars_del
= to
- from
;
1485 nbytes_del
= to_byte
- from_byte
;
1487 if (nbytes_del
<= 0 && insbytes
== 0)
1490 /* Make OUTGOING_INSBYTES describe the text
1491 as it will be inserted in this buffer. */
1493 if (NILP (current_buffer
->enable_multibyte_characters
))
1494 outgoing_insbytes
= inschars
;
1495 else if (! STRING_MULTIBYTE (new))
1497 = count_size_as_multibyte (SDATA (new), insbytes
);
1499 /* Make sure point-max won't overflow after this insertion. */
1500 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1501 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1502 error ("Maximum buffer size exceeded");
1506 /* Make sure the gap is somewhere in or next to what we are deleting. */
1508 gap_right (from
, from_byte
);
1510 gap_left (to
, to_byte
, 0);
1512 /* Even if we don't record for undo, we must keep the original text
1513 because we may have to recover it because of inappropriate byte
1515 if (! EQ (current_buffer
->undo_list
, Qt
))
1516 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1518 GAP_SIZE
+= nbytes_del
;
1521 ZV_BYTE
-= nbytes_del
;
1522 Z_BYTE
-= nbytes_del
;
1524 GPT_BYTE
= from_byte
;
1525 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1530 if (GPT
- BEG
< BEG_UNCHANGED
)
1531 BEG_UNCHANGED
= GPT
- BEG
;
1532 if (Z
- GPT
< END_UNCHANGED
)
1533 END_UNCHANGED
= Z
- GPT
;
1535 if (GAP_SIZE
< insbytes
)
1536 make_gap (insbytes
- GAP_SIZE
);
1538 /* Copy the string text into the buffer, perhaps converting
1539 between single-byte and multibyte. */
1540 copy_text (SDATA (new), GPT_ADDR
, insbytes
,
1541 STRING_MULTIBYTE (new),
1542 ! NILP (current_buffer
->enable_multibyte_characters
));
1544 #ifdef BYTE_COMBINING_DEBUG
1545 /* We have copied text into the gap, but we have not marked
1546 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1547 here, for both the previous text and the following text.
1548 Meanwhile, GPT_ADDR does point to
1549 the text that has been stored by copy_text. */
1550 if (count_combining_before (GPT_ADDR
, outgoing_insbytes
, from
, from_byte
)
1551 || count_combining_after (GPT_ADDR
, outgoing_insbytes
, from
, from_byte
))
1555 if (! EQ (current_buffer
->undo_list
, Qt
))
1557 /* Record the insertion first, so that when we undo,
1558 the deletion will be undone first. Thus, undo
1559 will insert before deleting, and thus will keep
1560 the markers before and after this text separate. */
1561 record_insert (from
+ SCHARS (deletion
), inschars
);
1562 record_delete (from
, deletion
);
1565 GAP_SIZE
-= outgoing_insbytes
;
1569 GPT_BYTE
+= outgoing_insbytes
;
1570 ZV_BYTE
+= outgoing_insbytes
;
1571 Z_BYTE
+= outgoing_insbytes
;
1572 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1577 /* Adjust the overlay center as needed. This must be done after
1578 adjusting the markers that bound the overlays. */
1579 adjust_overlays_for_delete (from
, nchars_del
);
1580 adjust_overlays_for_insert (from
, inschars
);
1582 /* Adjust markers for the deletion and the insertion. */
1584 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1585 inschars
, outgoing_insbytes
);
1587 offset_intervals (current_buffer
, from
, inschars
- nchars_del
);
1589 /* Get the intervals for the part of the string we are inserting--
1590 not including the combined-before bytes. */
1591 intervals
= STRING_INTERVALS (new);
1592 /* Insert those intervals. */
1593 graft_intervals_into_buffer (intervals
, from
, inschars
,
1594 current_buffer
, inherit
);
1596 /* Relocate point as if it were a marker. */
1598 adjust_point ((from
+ inschars
- (PT
< to
? PT
: to
)),
1599 (from_byte
+ outgoing_insbytes
1600 - (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
)));
1602 if (outgoing_insbytes
== 0)
1603 evaporate_overlays (from
);
1608 CHARS_MODIFF
= MODIFF
;
1611 signal_after_change (from
, nchars_del
, GPT
- from
);
1612 update_compositions (from
, GPT
, CHECK_BORDER
);
1615 /* Replace the text from character positions FROM to TO with
1616 the text in INS of length INSCHARS.
1617 Keep the text properties that applied to the old characters
1618 (extending them to all the new chars if there are more new chars).
1620 Note that this does not yet handle markers quite right.
1622 If MARKERS is nonzero, relocate markers.
1624 Unlike most functions at this level, never call
1625 prepare_to_modify_buffer and never call signal_after_change. */
1628 replace_range_2 (EMACS_INT from
, EMACS_INT from_byte
,
1629 EMACS_INT to
, EMACS_INT to_byte
,
1630 const char *ins
, EMACS_INT inschars
, EMACS_INT insbytes
,
1633 EMACS_INT nbytes_del
, nchars_del
;
1638 nchars_del
= to
- from
;
1639 nbytes_del
= to_byte
- from_byte
;
1641 if (nbytes_del
<= 0 && insbytes
== 0)
1644 /* Make sure point-max won't overflow after this insertion. */
1645 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1646 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1647 error ("Maximum buffer size exceeded");
1649 /* Make sure the gap is somewhere in or next to what we are deleting. */
1651 gap_right (from
, from_byte
);
1653 gap_left (to
, to_byte
, 0);
1655 GAP_SIZE
+= nbytes_del
;
1658 ZV_BYTE
-= nbytes_del
;
1659 Z_BYTE
-= nbytes_del
;
1661 GPT_BYTE
= from_byte
;
1662 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1667 if (GPT
- BEG
< BEG_UNCHANGED
)
1668 BEG_UNCHANGED
= GPT
- BEG
;
1669 if (Z
- GPT
< END_UNCHANGED
)
1670 END_UNCHANGED
= Z
- GPT
;
1672 if (GAP_SIZE
< insbytes
)
1673 make_gap (insbytes
- GAP_SIZE
);
1675 /* Copy the replacement text into the buffer. */
1676 memcpy (GPT_ADDR
, ins
, insbytes
);
1678 #ifdef BYTE_COMBINING_DEBUG
1679 /* We have copied text into the gap, but we have not marked
1680 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1681 here, for both the previous text and the following text.
1682 Meanwhile, GPT_ADDR does point to
1683 the text that has been stored by copy_text. */
1684 if (count_combining_before (GPT_ADDR
, insbytes
, from
, from_byte
)
1685 || count_combining_after (GPT_ADDR
, insbytes
, from
, from_byte
))
1689 GAP_SIZE
-= insbytes
;
1693 GPT_BYTE
+= insbytes
;
1694 ZV_BYTE
+= insbytes
;
1696 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1701 /* Adjust the overlay center as needed. This must be done after
1702 adjusting the markers that bound the overlays. */
1703 if (nchars_del
!= inschars
)
1705 adjust_overlays_for_insert (from
, inschars
);
1706 adjust_overlays_for_delete (from
+ inschars
, nchars_del
);
1709 /* Adjust markers for the deletion and the insertion. */
1711 && ! (nchars_del
== 1 && inschars
== 1 && nbytes_del
== insbytes
))
1712 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1713 inschars
, insbytes
);
1715 offset_intervals (current_buffer
, from
, inschars
- nchars_del
);
1717 /* Relocate point as if it were a marker. */
1718 if (from
< PT
&& (nchars_del
!= inschars
|| nbytes_del
!= insbytes
))
1721 /* PT was within the deleted text. Move it to FROM. */
1722 adjust_point (from
- PT
, from_byte
- PT_BYTE
);
1724 adjust_point (inschars
- nchars_del
, insbytes
- nbytes_del
);
1728 evaporate_overlays (from
);
1733 CHARS_MODIFF
= MODIFF
;
1736 /* Delete characters in current buffer
1737 from FROM up to (but not including) TO.
1738 If TO comes before FROM, we delete nothing. */
1741 del_range (EMACS_INT from
, EMACS_INT to
)
1743 del_range_1 (from
, to
, 1, 0);
1746 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1747 RET_STRING says to return the deleted text. */
1750 del_range_1 (EMACS_INT from
, EMACS_INT to
, int prepare
, int ret_string
)
1752 EMACS_INT from_byte
, to_byte
;
1753 Lisp_Object deletion
;
1754 struct gcpro gcpro1
;
1756 /* Make args be valid */
1767 EMACS_INT range_length
= to
- from
;
1768 prepare_to_modify_buffer (from
, to
, &from
);
1769 to
= min (ZV
, from
+ range_length
);
1772 from_byte
= CHAR_TO_BYTE (from
);
1773 to_byte
= CHAR_TO_BYTE (to
);
1775 deletion
= del_range_2 (from
, from_byte
, to
, to_byte
, ret_string
);
1777 signal_after_change (from
, to
- from
, 0);
1778 update_compositions (from
, from
, CHECK_HEAD
);
1783 /* Like del_range_1 but args are byte positions, not char positions. */
1786 del_range_byte (EMACS_INT from_byte
, EMACS_INT to_byte
, int prepare
)
1790 /* Make args be valid */
1791 if (from_byte
< BEGV_BYTE
)
1792 from_byte
= BEGV_BYTE
;
1793 if (to_byte
> ZV_BYTE
)
1796 if (to_byte
<= from_byte
)
1799 from
= BYTE_TO_CHAR (from_byte
);
1800 to
= BYTE_TO_CHAR (to_byte
);
1804 EMACS_INT old_from
= from
, old_to
= Z
- to
;
1805 EMACS_INT range_length
= to
- from
;
1806 prepare_to_modify_buffer (from
, to
, &from
);
1807 to
= from
+ range_length
;
1809 if (old_from
!= from
)
1810 from_byte
= CHAR_TO_BYTE (from
);
1816 else if (old_to
== Z
- to
)
1817 to_byte
= CHAR_TO_BYTE (to
);
1820 del_range_2 (from
, from_byte
, to
, to_byte
, 0);
1821 signal_after_change (from
, to
- from
, 0);
1822 update_compositions (from
, from
, CHECK_HEAD
);
1825 /* Like del_range_1, but positions are specified both as charpos
1829 del_range_both (EMACS_INT from
, EMACS_INT from_byte
,
1830 EMACS_INT to
, EMACS_INT to_byte
, int prepare
)
1832 /* Make args be valid */
1833 if (from_byte
< BEGV_BYTE
)
1834 from_byte
= BEGV_BYTE
;
1835 if (to_byte
> ZV_BYTE
)
1838 if (to_byte
<= from_byte
)
1848 EMACS_INT old_from
= from
, old_to
= Z
- to
;
1849 EMACS_INT range_length
= to
- from
;
1850 prepare_to_modify_buffer (from
, to
, &from
);
1851 to
= from
+ range_length
;
1853 if (old_from
!= from
)
1854 from_byte
= CHAR_TO_BYTE (from
);
1860 else if (old_to
== Z
- to
)
1861 to_byte
= CHAR_TO_BYTE (to
);
1864 del_range_2 (from
, from_byte
, to
, to_byte
, 0);
1865 signal_after_change (from
, to
- from
, 0);
1866 update_compositions (from
, from
, CHECK_HEAD
);
1869 /* Delete a range of text, specified both as character positions
1870 and byte positions. FROM and TO are character positions,
1871 while FROM_BYTE and TO_BYTE are byte positions.
1872 If RET_STRING is true, the deleted area is returned as a string. */
1875 del_range_2 (EMACS_INT from
, EMACS_INT from_byte
,
1876 EMACS_INT to
, EMACS_INT to_byte
, int ret_string
)
1878 register EMACS_INT nbytes_del
, nchars_del
;
1879 Lisp_Object deletion
;
1883 nchars_del
= to
- from
;
1884 nbytes_del
= to_byte
- from_byte
;
1886 /* Make sure the gap is somewhere in or next to what we are deleting. */
1888 gap_right (from
, from_byte
);
1890 gap_left (to
, to_byte
, 0);
1892 #ifdef BYTE_COMBINING_DEBUG
1893 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer
, to_byte
),
1894 Z_BYTE
- to_byte
, from
, from_byte
))
1898 if (ret_string
|| ! EQ (current_buffer
->undo_list
, Qt
))
1899 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1903 /* Relocate all markers pointing into the new, larger gap
1904 to point at the end of the text before the gap.
1905 Do this before recording the deletion,
1906 so that undo handles this after reinserting the text. */
1907 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1909 if (! EQ (current_buffer
->undo_list
, Qt
))
1910 record_delete (from
, deletion
);
1912 CHARS_MODIFF
= MODIFF
;
1914 /* Relocate point as if it were a marker. */
1916 adjust_point (from
- (PT
< to
? PT
: to
),
1917 from_byte
- (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
));
1919 offset_intervals (current_buffer
, from
, - nchars_del
);
1921 /* Adjust the overlay center as needed. This must be done after
1922 adjusting the markers that bound the overlays. */
1923 adjust_overlays_for_delete (from
, nchars_del
);
1925 GAP_SIZE
+= nbytes_del
;
1926 ZV_BYTE
-= nbytes_del
;
1927 Z_BYTE
-= nbytes_del
;
1931 GPT_BYTE
= from_byte
;
1932 if (GAP_SIZE
> 0 && !current_buffer
->text
->inhibit_shrinking
)
1933 /* Put an anchor, unless called from decode_coding_object which
1934 needs to access the previous gap contents. */
1940 if (GPT
- BEG
< BEG_UNCHANGED
)
1941 BEG_UNCHANGED
= GPT
- BEG
;
1942 if (Z
- GPT
< END_UNCHANGED
)
1943 END_UNCHANGED
= Z
- GPT
;
1947 evaporate_overlays (from
);
1952 /* Call this if you're about to change the region of BUFFER from
1953 character positions START to END. This checks the read-only
1954 properties of the region, calls the necessary modification hooks,
1955 and warns the next redisplay that it should pay attention to that
1958 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1959 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1962 modify_region (struct buffer
*buffer
, EMACS_INT start
, EMACS_INT end
,
1963 int preserve_chars_modiff
)
1965 struct buffer
*old_buffer
= current_buffer
;
1967 if (buffer
!= old_buffer
)
1968 set_buffer_internal (buffer
);
1970 prepare_to_modify_buffer (start
, end
, NULL
);
1972 BUF_COMPUTE_UNCHANGED (buffer
, start
- 1, end
);
1974 if (MODIFF
<= SAVE_MODIFF
)
1975 record_first_change ();
1977 if (! preserve_chars_modiff
)
1978 CHARS_MODIFF
= MODIFF
;
1980 buffer
->point_before_scroll
= Qnil
;
1982 if (buffer
!= old_buffer
)
1983 set_buffer_internal (old_buffer
);
1986 /* Check that it is okay to modify the buffer between START and END,
1987 which are char positions.
1989 Run the before-change-function, if any. If intervals are in use,
1990 verify that the text to be modified is not read-only, and call
1991 any modification properties the text may have.
1993 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1994 by holding its value temporarily in a marker. */
1997 prepare_to_modify_buffer (EMACS_INT start
, EMACS_INT end
,
1998 EMACS_INT
*preserve_ptr
)
2000 struct buffer
*base_buffer
;
2002 if (!NILP (current_buffer
->read_only
))
2003 Fbarf_if_buffer_read_only ();
2005 /* Let redisplay consider other windows than selected_window
2006 if modifying another buffer. */
2007 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2008 ++windows_or_buffers_changed
;
2010 if (BUF_INTERVALS (current_buffer
) != 0)
2014 Lisp_Object preserve_marker
;
2015 struct gcpro gcpro1
;
2016 preserve_marker
= Fcopy_marker (make_number (*preserve_ptr
), Qnil
);
2017 GCPRO1 (preserve_marker
);
2018 verify_interval_modification (current_buffer
, start
, end
);
2019 *preserve_ptr
= marker_position (preserve_marker
);
2020 unchain_marker (XMARKER (preserve_marker
));
2024 verify_interval_modification (current_buffer
, start
, end
);
2027 /* For indirect buffers, use the base buffer to check clashes. */
2028 if (current_buffer
->base_buffer
!= 0)
2029 base_buffer
= current_buffer
->base_buffer
;
2031 base_buffer
= current_buffer
;
2033 #ifdef CLASH_DETECTION
2034 if (!NILP (base_buffer
->file_truename
)
2035 /* Make binding buffer-file-name to nil effective. */
2036 && !NILP (base_buffer
->filename
)
2037 && SAVE_MODIFF
>= MODIFF
)
2038 lock_file (base_buffer
->file_truename
);
2040 /* At least warn if this file has changed on disk since it was visited. */
2041 if (!NILP (base_buffer
->filename
)
2042 && SAVE_MODIFF
>= MODIFF
2043 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
2044 && !NILP (Ffile_exists_p (base_buffer
->filename
)))
2045 call1 (intern ("ask-user-about-supersession-threat"),
2046 base_buffer
->filename
);
2047 #endif /* not CLASH_DETECTION */
2049 /* If `select-active-regions' is non-nil, save the region text. */
2050 if (!NILP (current_buffer
->mark_active
)
2051 && !inhibit_modification_hooks
2052 && XMARKER (current_buffer
->mark
)->buffer
2053 && NILP (Vsaved_region_selection
)
2054 && (EQ (Vselect_active_regions
, Qonly
)
2055 ? EQ (CAR_SAFE (Vtransient_mark_mode
), Qonly
)
2056 : (!NILP (Vselect_active_regions
)
2057 && !NILP (Vtransient_mark_mode
))))
2059 EMACS_INT b
= XMARKER (current_buffer
->mark
)->charpos
;
2062 Vsaved_region_selection
= make_buffer_string (b
, e
, 0);
2064 Vsaved_region_selection
= make_buffer_string (e
, b
, 0);
2067 signal_before_change (start
, end
, preserve_ptr
);
2069 if (current_buffer
->newline_cache
)
2070 invalidate_region_cache (current_buffer
,
2071 current_buffer
->newline_cache
,
2072 start
- BEG
, Z
- end
);
2073 if (current_buffer
->width_run_cache
)
2074 invalidate_region_cache (current_buffer
,
2075 current_buffer
->width_run_cache
,
2076 start
- BEG
, Z
- end
);
2078 Vdeactivate_mark
= Qt
;
2081 /* These macros work with an argument named `preserve_ptr'
2082 and a local variable named `preserve_marker'. */
2084 #define PRESERVE_VALUE \
2085 if (preserve_ptr && NILP (preserve_marker)) \
2086 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2088 #define RESTORE_VALUE \
2089 if (! NILP (preserve_marker)) \
2091 *preserve_ptr = marker_position (preserve_marker); \
2092 unchain_marker (XMARKER (preserve_marker)); \
2095 #define PRESERVE_START_END \
2096 if (NILP (start_marker)) \
2097 start_marker = Fcopy_marker (start, Qnil); \
2098 if (NILP (end_marker)) \
2099 end_marker = Fcopy_marker (end, Qnil);
2101 #define FETCH_START \
2102 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2105 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2107 /* Set a variable to nil if an error occurred.
2108 Don't change the variable if there was no error.
2109 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
2110 VARIABLE is the variable to maybe set to nil.
2111 NO-ERROR-FLAG is nil if there was an error,
2112 anything else meaning no error (so this function does nothing). */
2114 reset_var_on_error (Lisp_Object val
)
2116 if (NILP (XCDR (val
)))
2117 Fset (XCAR (val
), Qnil
);
2121 /* Signal a change to the buffer immediately before it happens.
2122 START_INT and END_INT are the bounds of the text to be changed.
2124 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2125 by holding its value temporarily in a marker. */
2128 signal_before_change (EMACS_INT start_int
, EMACS_INT end_int
,
2129 EMACS_INT
*preserve_ptr
)
2131 Lisp_Object start
, end
;
2132 Lisp_Object start_marker
, end_marker
;
2133 Lisp_Object preserve_marker
;
2134 struct gcpro gcpro1
, gcpro2
, gcpro3
;
2135 int count
= SPECPDL_INDEX ();
2137 if (inhibit_modification_hooks
)
2140 start
= make_number (start_int
);
2141 end
= make_number (end_int
);
2142 preserve_marker
= Qnil
;
2143 start_marker
= Qnil
;
2145 GCPRO3 (preserve_marker
, start_marker
, end_marker
);
2147 specbind (Qinhibit_modification_hooks
, Qt
);
2149 /* If buffer is unmodified, run a special hook for that case. */
2150 if (SAVE_MODIFF
>= MODIFF
2151 && !NILP (Vfirst_change_hook
)
2152 && !NILP (Vrun_hooks
))
2156 call1 (Vrun_hooks
, Qfirst_change_hook
);
2159 /* Now run the before-change-functions if any. */
2160 if (!NILP (Vbefore_change_functions
))
2162 Lisp_Object args
[3];
2163 Lisp_Object rvoe_arg
= Fcons (Qbefore_change_functions
, Qnil
);
2168 /* Mark before-change-functions to be reset to nil in case of error. */
2169 record_unwind_protect (reset_var_on_error
, rvoe_arg
);
2171 /* Actually run the hook functions. */
2172 args
[0] = Qbefore_change_functions
;
2173 args
[1] = FETCH_START
;
2174 args
[2] = FETCH_END
;
2175 Frun_hook_with_args (3, args
);
2177 /* There was no error: unarm the reset_on_error. */
2178 XSETCDR (rvoe_arg
, Qt
);
2181 if (current_buffer
->overlays_before
|| current_buffer
->overlays_after
)
2184 report_overlay_modification (FETCH_START
, FETCH_END
, 0,
2185 FETCH_START
, FETCH_END
, Qnil
);
2188 if (! NILP (start_marker
))
2189 free_marker (start_marker
);
2190 if (! NILP (end_marker
))
2191 free_marker (end_marker
);
2195 unbind_to (count
, Qnil
);
2198 /* Signal a change immediately after it happens.
2199 CHARPOS is the character position of the start of the changed text.
2200 LENDEL is the number of characters of the text before the change.
2201 (Not the whole buffer; just the part that was changed.)
2202 LENINS is the number of characters in that part of the text
2203 after the change. */
2206 signal_after_change (EMACS_INT charpos
, EMACS_INT lendel
, EMACS_INT lenins
)
2208 int count
= SPECPDL_INDEX ();
2209 if (inhibit_modification_hooks
)
2212 /* If we are deferring calls to the after-change functions
2213 and there are no before-change functions,
2214 just record the args that we were going to use. */
2215 if (! NILP (Vcombine_after_change_calls
)
2216 && NILP (Vbefore_change_functions
)
2217 && !current_buffer
->overlays_before
2218 && !current_buffer
->overlays_after
)
2222 if (!NILP (combine_after_change_list
)
2223 && current_buffer
!= XBUFFER (combine_after_change_buffer
))
2224 Fcombine_after_change_execute ();
2226 elt
= Fcons (make_number (charpos
- BEG
),
2227 Fcons (make_number (Z
- (charpos
- lendel
+ lenins
)),
2228 Fcons (make_number (lenins
- lendel
), Qnil
)));
2229 combine_after_change_list
2230 = Fcons (elt
, combine_after_change_list
);
2231 combine_after_change_buffer
= Fcurrent_buffer ();
2236 if (!NILP (combine_after_change_list
))
2237 Fcombine_after_change_execute ();
2239 specbind (Qinhibit_modification_hooks
, Qt
);
2241 if (!NILP (Vafter_change_functions
))
2243 Lisp_Object args
[4];
2244 Lisp_Object rvoe_arg
= Fcons (Qafter_change_functions
, Qnil
);
2246 /* Mark after-change-functions to be reset to nil in case of error. */
2247 record_unwind_protect (reset_var_on_error
, rvoe_arg
);
2249 /* Actually run the hook functions. */
2250 args
[0] = Qafter_change_functions
;
2251 XSETFASTINT (args
[1], charpos
);
2252 XSETFASTINT (args
[2], charpos
+ lenins
);
2253 XSETFASTINT (args
[3], lendel
);
2254 Frun_hook_with_args (4, args
);
2256 /* There was no error: unarm the reset_on_error. */
2257 XSETCDR (rvoe_arg
, Qt
);
2260 if (current_buffer
->overlays_before
|| current_buffer
->overlays_after
)
2261 report_overlay_modification (make_number (charpos
),
2262 make_number (charpos
+ lenins
),
2264 make_number (charpos
),
2265 make_number (charpos
+ lenins
),
2266 make_number (lendel
));
2268 /* After an insertion, call the text properties
2269 insert-behind-hooks or insert-in-front-hooks. */
2271 report_interval_modification (make_number (charpos
),
2272 make_number (charpos
+ lenins
));
2274 unbind_to (count
, Qnil
);
2278 Fcombine_after_change_execute_1 (Lisp_Object val
)
2280 Vcombine_after_change_calls
= val
;
2284 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute
,
2285 Scombine_after_change_execute
, 0, 0, 0,
2286 doc
: /* This function is for use internally in `combine-after-change-calls'. */)
2289 int count
= SPECPDL_INDEX ();
2290 EMACS_INT beg
, end
, change
;
2291 EMACS_INT begpos
, endpos
;
2294 if (NILP (combine_after_change_list
))
2297 /* It is rare for combine_after_change_buffer to be invalid, but
2298 possible. It can happen when combine-after-change-calls is
2299 non-nil, and insertion calls a file handler (e.g. through
2300 lock_file) which scribbles into a temp file -- cyd */
2301 if (!BUFFERP (combine_after_change_buffer
)
2302 || NILP (XBUFFER (combine_after_change_buffer
)->name
))
2304 combine_after_change_list
= Qnil
;
2308 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
2310 Fset_buffer (combine_after_change_buffer
);
2312 /* # chars unchanged at beginning of buffer. */
2314 /* # chars unchanged at end of buffer. */
2316 /* Total amount of insertion (negative for deletion). */
2319 /* Scan the various individual changes,
2320 accumulating the range info in BEG, END and CHANGE. */
2321 for (tail
= combine_after_change_list
; CONSP (tail
);
2325 EMACS_INT thisbeg
, thisend
, thischange
;
2327 /* Extract the info from the next element. */
2331 thisbeg
= XINT (XCAR (elt
));
2336 thisend
= XINT (XCAR (elt
));
2341 thischange
= XINT (XCAR (elt
));
2343 /* Merge this range into the accumulated range. */
2344 change
+= thischange
;
2351 /* Get the current start and end positions of the range
2352 that was changed. */
2356 /* We are about to handle these, so discard them. */
2357 combine_after_change_list
= Qnil
;
2359 /* Now run the after-change functions for real.
2360 Turn off the flag that defers them. */
2361 record_unwind_protect (Fcombine_after_change_execute_1
,
2362 Vcombine_after_change_calls
);
2363 signal_after_change (begpos
, endpos
- begpos
- change
, endpos
- begpos
);
2364 update_compositions (begpos
, endpos
, CHECK_ALL
);
2366 return unbind_to (count
, Qnil
);
2370 syms_of_insdel (void)
2372 staticpro (&combine_after_change_list
);
2373 staticpro (&combine_after_change_buffer
);
2374 combine_after_change_list
= Qnil
;
2375 combine_after_change_buffer
= Qnil
;
2377 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag
,
2378 doc
: /* Non-nil means enable debugging checks for invalid marker positions. */);
2379 check_markers_debug_flag
= 0;
2380 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls
,
2381 doc
: /* Used internally by the `combine-after-change-calls' macro. */);
2382 Vcombine_after_change_calls
= Qnil
;
2384 DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks
,
2385 doc
: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2386 This affects `before-change-functions' and `after-change-functions',
2387 as well as hooks attached to text properties and overlays. */);
2388 inhibit_modification_hooks
= 0;
2389 Qinhibit_modification_hooks
= intern_c_string ("inhibit-modification-hooks");
2390 staticpro (&Qinhibit_modification_hooks
);
2392 defsubr (&Scombine_after_change_execute
);