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 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, or (at your option)
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; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
25 #include "intervals.h"
27 #include "character.h"
29 #include "blockinput.h"
30 #include "region-cache.h"
36 static void insert_from_string_1
P_ ((Lisp_Object
, int, int, int, int, int, int));
37 static void insert_from_buffer_1 ();
38 static void gap_left
P_ ((int, int, int));
39 static void gap_right
P_ ((int, int));
40 static void adjust_markers_gap_motion
P_ ((int, int, int));
41 static void adjust_markers_for_insert
P_ ((int, int, int, int, int));
42 void adjust_markers_for_delete
P_ ((int, int, int, int));
43 static void adjust_markers_for_replace
P_ ((int, int, int, int, int, int));
44 static void adjust_point
P_ ((int, int));
46 Lisp_Object
Fcombine_after_change_execute ();
48 /* Non-nil means don't call the after-change-functions right away,
49 just record an element in Vcombine_after_change_calls_list. */
50 Lisp_Object Vcombine_after_change_calls
;
52 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
53 describing changes which happened while combine_after_change_calls
54 was nonzero. We use this to decide how to call them
55 once the deferral ends.
58 BEG-UNCHANGED is the number of chars before the changed range.
59 END-UNCHANGED is the number of chars after the changed range,
60 and CHANGE-AMOUNT is the number of characters inserted by the change
61 (negative for a deletion). */
62 Lisp_Object combine_after_change_list
;
64 /* Buffer which combine_after_change_list is about. */
65 Lisp_Object combine_after_change_buffer
;
67 Lisp_Object Qinhibit_modification_hooks
;
70 /* Check all markers in the current buffer, looking for something invalid. */
72 static int check_markers_debug_flag
;
74 #define CHECK_MARKERS() \
75 if (check_markers_debug_flag) \
82 register struct Lisp_Marker
*tail
;
83 int multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
85 for (tail
= BUF_MARKERS (current_buffer
); tail
; tail
= tail
->next
)
87 if (tail
->buffer
->text
!= current_buffer
->text
)
89 if (tail
->charpos
> Z
)
91 if (tail
->bytepos
> Z_BYTE
)
93 if (multibyte
&& ! CHAR_HEAD_P (FETCH_BYTE (tail
->bytepos
)))
98 /* Move gap to position CHARPOS.
99 Note that this can quit! */
105 move_gap_both (charpos
, charpos_to_bytepos (charpos
));
108 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
109 Note that this can quit! */
112 move_gap_both (charpos
, bytepos
)
113 int charpos
, bytepos
;
115 if (bytepos
< GPT_BYTE
)
116 gap_left (charpos
, bytepos
, 0);
117 else if (bytepos
> GPT_BYTE
)
118 gap_right (charpos
, bytepos
);
121 /* Move the gap to a position less than the current GPT.
122 BYTEPOS describes the new position as a byte position,
123 and CHARPOS is the corresponding char position.
124 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
127 gap_left (charpos
, bytepos
, newgap
)
128 register int charpos
, bytepos
;
131 register unsigned char *to
, *from
;
136 BUF_COMPUTE_UNCHANGED (current_buffer
, charpos
, GPT
);
143 /* Now copy the characters. To move the gap down,
144 copy characters up. */
148 /* I gets number of characters left to copy. */
149 i
= new_s1
- bytepos
;
152 /* If a quit is requested, stop copying now.
153 Change BYTEPOS to be where we have actually moved the gap to. */
157 charpos
= BYTE_TO_CHAR (bytepos
);
160 /* Move at most 32000 chars before checking again for a quit. */
165 /* bcopy is safe if the two areas of memory do not overlap
166 or on systems where bcopy is always safe for moving upward. */
167 && (BCOPY_UPWARD_SAFE
168 || to
- from
>= 128))
170 /* If overlap is not safe, avoid it by not moving too many
171 characters at once. */
172 if (!BCOPY_UPWARD_SAFE
&& i
> to
- from
)
187 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
188 BYTEPOS is where the loop above stopped, which may be what was specified
189 or may be where a quit was detected. */
190 adjust_markers_gap_motion (bytepos
, GPT_BYTE
, GAP_SIZE
);
193 if (bytepos
< charpos
)
195 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
199 /* Move the gap to a position greater than than the current GPT.
200 BYTEPOS describes the new position as a byte position,
201 and CHARPOS is the corresponding char position. */
204 gap_right (charpos
, bytepos
)
205 register int charpos
, bytepos
;
207 register unsigned char *to
, *from
;
211 BUF_COMPUTE_UNCHANGED (current_buffer
, charpos
, GPT
);
218 /* Now copy the characters. To move the gap up,
219 copy characters down. */
223 /* I gets number of characters left to copy. */
224 i
= bytepos
- new_s1
;
227 /* If a quit is requested, stop copying now.
228 Change BYTEPOS to be where we have actually moved the gap to. */
232 charpos
= BYTE_TO_CHAR (bytepos
);
235 /* Move at most 32000 chars before checking again for a quit. */
240 /* bcopy is safe if the two areas of memory do not overlap
241 or on systems where bcopy is always safe for moving downward. */
242 && (BCOPY_DOWNWARD_SAFE
243 || from
- to
>= 128))
245 /* If overlap is not safe, avoid it by not moving too many
246 characters at once. */
247 if (!BCOPY_DOWNWARD_SAFE
&& i
> from
- to
)
262 adjust_markers_gap_motion (GPT_BYTE
+ GAP_SIZE
, bytepos
+ GAP_SIZE
,
266 if (bytepos
< charpos
)
268 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
272 /* Add AMOUNT to the byte position of every marker in the current buffer
273 whose current byte position is between FROM (exclusive) and TO (inclusive).
275 Also, any markers past the outside of that interval, in the direction
276 of adjustment, are first moved back to the near end of the interval
277 and then adjusted by AMOUNT.
279 When the latter adjustment is done, if AMOUNT is negative,
280 we record the adjustment for undo. (This case happens only for
283 The markers' character positions are not altered,
284 because gap motion does not affect character positions. */
286 int adjust_markers_test
;
289 adjust_markers_gap_motion (from
, to
, amount
)
290 register int from
, to
, amount
;
292 /* Now that a marker has a bytepos, not counting the gap,
293 nothing needs to be done here. */
296 register struct Lisp_Marker
*m
;
299 marker
= BUF_MARKERS (current_buffer
);
301 while (!NILP (marker
))
303 m
= XMARKER (marker
);
307 if (mpos
> to
&& mpos
< to
+ amount
)
309 if (adjust_markers_test
)
316 /* Here's the case where a marker is inside text being deleted.
317 AMOUNT can be negative for gap motion, too,
318 but then this range contains no markers. */
319 if (mpos
> from
+ amount
&& mpos
<= from
)
321 if (adjust_markers_test
)
323 mpos
= from
+ amount
;
326 if (mpos
> from
&& mpos
<= to
)
334 /* Adjust all markers for a deletion
335 whose range in bytes is FROM_BYTE to TO_BYTE.
336 The range in charpos is FROM to TO.
338 This function assumes that the gap is adjacent to
339 or inside of the range being deleted. */
342 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
)
343 register int from
, from_byte
, to
, to_byte
;
346 register struct Lisp_Marker
*m
;
347 register int charpos
;
349 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
351 charpos
= m
->charpos
;
356 /* If the marker is after the deletion,
357 relocate by number of chars / bytes deleted. */
360 m
->charpos
-= to
- from
;
361 m
->bytepos
-= to_byte
- from_byte
;
363 /* Here's the case where a marker is inside text being deleted. */
364 else if (charpos
> from
)
366 if (! m
->insertion_type
)
367 { /* Normal markers will end up at the beginning of the
368 re-inserted text after undoing a deletion, and must be
369 adjusted to move them to the correct place. */
370 XSETMISC (marker
, m
);
371 record_marker_adjustment (marker
, from
- charpos
);
373 else if (charpos
< to
)
374 { /* Before-insertion markers will automatically move forward
375 upon re-inserting the deleted text, so we have to arrange
376 for them to move backward to the correct position. */
377 XSETMISC (marker
, m
);
378 record_marker_adjustment (marker
, charpos
- to
);
381 m
->bytepos
= from_byte
;
383 /* Here's the case where a before-insertion marker is immediately
384 before the deleted region. */
385 else if (charpos
== from
&& m
->insertion_type
)
387 /* Undoing the change uses normal insertion, which will
388 incorrectly make MARKER move forward, so we arrange for it
389 to then move backward to the correct place at the beginning
390 of the deleted region. */
391 XSETMISC (marker
, m
);
392 record_marker_adjustment (marker
, to
- from
);
398 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
399 to TO / TO_BYTE. We have to relocate the charpos of every marker
400 that points after the insertion (but not their bytepos).
402 When a marker points at the insertion point,
403 we advance it if either its insertion-type is t
404 or BEFORE_MARKERS is true. */
407 adjust_markers_for_insert (from
, from_byte
, to
, to_byte
, before_markers
)
408 register int from
, from_byte
, to
, to_byte
;
411 struct Lisp_Marker
*m
;
413 int nchars
= to
- from
;
414 int nbytes
= to_byte
- from_byte
;
416 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
418 eassert (m
->bytepos
>= m
->charpos
419 && m
->bytepos
- m
->charpos
<= Z_BYTE
- Z
);
421 if (m
->bytepos
== from_byte
)
423 if (m
->insertion_type
|| before_markers
)
425 m
->bytepos
= to_byte
;
427 if (m
->insertion_type
)
431 else if (m
->bytepos
> from_byte
)
433 m
->bytepos
+= nbytes
;
434 m
->charpos
+= nchars
;
438 /* Adjusting only markers whose insertion-type is t may result in
439 - disordered start and end in overlays, and
440 - disordered overlays in the slot `overlays_before' of current_buffer. */
443 fix_start_end_in_overlays(from
, to
);
444 fix_overlays_before (current_buffer
, from
, to
);
448 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
450 This is used only when the value of point changes due to an insert
451 or delete; it does not represent a conceptual change in point as a
452 marker. In particular, point is not crossing any interval
453 boundaries, so there's no need to use the usual SET_PT macro. In
454 fact it would be incorrect to do so, because either the old or the
455 new value of point is out of sync with the current set of
459 adjust_point (nchars
, nbytes
)
462 BUF_PT (current_buffer
) += nchars
;
463 BUF_PT_BYTE (current_buffer
) += nbytes
;
465 /* In a single-byte buffer, the two positions must be equal. */
466 eassert (PT_BYTE
>= PT
&& PT_BYTE
- PT
<= ZV_BYTE
- ZV
);
469 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
470 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
471 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
475 adjust_markers_for_replace (from
, from_byte
, old_chars
, old_bytes
,
476 new_chars
, new_bytes
)
477 int from
, from_byte
, old_chars
, old_bytes
, new_chars
, new_bytes
;
479 register struct Lisp_Marker
*m
;
480 int prev_to_byte
= from_byte
+ old_bytes
;
481 int diff_chars
= new_chars
- old_chars
;
482 int diff_bytes
= new_bytes
- old_bytes
;
484 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
486 if (m
->bytepos
>= prev_to_byte
)
488 m
->charpos
+= diff_chars
;
489 m
->bytepos
+= diff_bytes
;
491 else if (m
->bytepos
> from_byte
)
494 m
->bytepos
= from_byte
;
502 /* Make the gap NBYTES_ADDED bytes longer. */
505 make_gap_larger (nbytes_added
)
510 int real_gap_loc_byte
;
513 /* If we have to get more space, get enough to last a while. */
514 nbytes_added
+= 2000;
516 /* Don't allow a buffer size that won't fit in an int
517 even if it will fit in a Lisp integer.
518 That won't work because so many places use `int'.
520 Make sure we don't introduce overflows in the calculation. */
522 if (Z_BYTE
- BEG_BYTE
+ GAP_SIZE
523 >= (((EMACS_INT
) 1 << (min (VALBITS
, BITS_PER_INT
) - 1)) - 1
525 error ("Buffer exceeds maximum size");
527 enlarge_buffer_text (current_buffer
, nbytes_added
);
529 /* Prevent quitting in move_gap. */
534 real_gap_loc_byte
= GPT_BYTE
;
535 old_gap_size
= GAP_SIZE
;
537 /* Call the newly allocated space a gap at the end of the whole space. */
539 GPT_BYTE
= Z_BYTE
+ GAP_SIZE
;
540 GAP_SIZE
= nbytes_added
;
542 /* Move the new gap down to be consecutive with the end of the old one.
543 This adjusts the markers properly too. */
544 gap_left (real_gap_loc
+ old_gap_size
, real_gap_loc_byte
+ old_gap_size
, 1);
546 /* Now combine the two into one large gap. */
547 GAP_SIZE
+= old_gap_size
;
549 GPT_BYTE
= real_gap_loc_byte
;
558 /* Make the gap NBYTES_REMOVED bytes shorter. */
561 make_gap_smaller (nbytes_removed
)
566 int real_gap_loc_byte
;
569 int real_beg_unchanged
;
572 /* Make sure the gap is at least 20 bytes. */
573 if (GAP_SIZE
- nbytes_removed
< 20)
574 nbytes_removed
= GAP_SIZE
- 20;
576 /* Prevent quitting in move_gap. */
581 real_gap_loc_byte
= GPT_BYTE
;
582 new_gap_size
= GAP_SIZE
- nbytes_removed
;
584 real_Z_byte
= Z_BYTE
;
585 real_beg_unchanged
= BEG_UNCHANGED
;
587 /* Pretend that the last unwanted part of the gap is the entire gap,
588 and that the first desired part of the gap is part of the buffer
590 bzero (GPT_ADDR
, new_gap_size
);
592 GPT_BYTE
+= new_gap_size
;
594 Z_BYTE
+= new_gap_size
;
595 GAP_SIZE
= nbytes_removed
;
597 /* Move the unwanted pretend gap to the end of the buffer. This
598 adjusts the markers properly too. */
599 gap_right (Z
, Z_BYTE
);
601 enlarge_buffer_text (current_buffer
, -nbytes_removed
);
603 /* Now restore the desired gap. */
604 GAP_SIZE
= new_gap_size
;
606 GPT_BYTE
= real_gap_loc_byte
;
608 Z_BYTE
= real_Z_byte
;
609 BEG_UNCHANGED
= real_beg_unchanged
;
618 make_gap (nbytes_added
)
621 if (nbytes_added
>= 0)
622 make_gap_larger (nbytes_added
);
623 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
625 make_gap_smaller (-nbytes_added
);
629 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
630 FROM_MULTIBYTE says whether the incoming text is multibyte.
631 TO_MULTIBYTE says whether to store the text as multibyte.
632 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
634 Return the number of bytes stored at TO_ADDR. */
637 copy_text (from_addr
, to_addr
, nbytes
,
638 from_multibyte
, to_multibyte
)
639 const unsigned char *from_addr
;
640 unsigned char *to_addr
;
642 int from_multibyte
, to_multibyte
;
644 if (from_multibyte
== to_multibyte
)
646 bcopy (from_addr
, to_addr
, nbytes
);
649 else if (from_multibyte
)
652 int bytes_left
= nbytes
;
653 Lisp_Object tbl
= Qnil
;
655 while (bytes_left
> 0)
658 c
= STRING_CHAR_AND_LENGTH (from_addr
, bytes_left
, thislen
);
659 if (!ASCII_CHAR_P (c
))
660 c
= multibyte_char_to_unibyte (c
, tbl
);
662 from_addr
+= thislen
;
663 bytes_left
-= thislen
;
670 unsigned char *initial_to_addr
= to_addr
;
672 /* Convert single-byte to multibyte. */
675 int c
= *from_addr
++;
679 c
= unibyte_char_to_multibyte (c
);
680 to_addr
+= CHAR_STRING (c
, to_addr
);
684 /* Special case for speed. */
685 *to_addr
++ = c
, nbytes
--;
687 return to_addr
- initial_to_addr
;
691 /* Return the number of bytes it would take
692 to convert some single-byte text to multibyte.
693 The single-byte text consists of NBYTES bytes at PTR. */
696 count_size_as_multibyte (ptr
, nbytes
)
697 const unsigned char *ptr
;
701 int outgoing_nbytes
= 0;
703 for (i
= 0; i
< nbytes
; i
++)
705 unsigned int c
= *ptr
++;
711 c
= unibyte_char_to_multibyte (c
);
712 outgoing_nbytes
+= CHAR_BYTES (c
);
716 return outgoing_nbytes
;
719 /* Insert a string of specified length before point.
720 This function judges multibyteness based on
721 enable_multibyte_characters in the current buffer;
722 it never converts between single-byte and multibyte.
724 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
725 prepare_to_modify_buffer could relocate the text. */
728 insert (string
, nbytes
)
729 register const unsigned char *string
;
734 int len
= chars_in_text (string
, nbytes
), opoint
;
735 insert_1_both (string
, len
, nbytes
, 0, 1, 0);
737 signal_after_change (opoint
, 0, len
);
738 update_compositions (opoint
, PT
, CHECK_BORDER
);
742 /* Likewise, but inherit text properties from neighboring characters. */
745 insert_and_inherit (string
, nbytes
)
746 register const unsigned char *string
;
751 int len
= chars_in_text (string
, nbytes
), opoint
;
752 insert_1_both (string
, len
, nbytes
, 1, 1, 0);
754 signal_after_change (opoint
, 0, len
);
755 update_compositions (opoint
, PT
, CHECK_BORDER
);
759 /* Insert the character C before point. Do not inherit text properties. */
765 unsigned char str
[MAX_MULTIBYTE_LENGTH
];
768 if (! NILP (current_buffer
->enable_multibyte_characters
))
769 len
= CHAR_STRING (c
, str
);
779 /* Insert the null-terminated string S before point. */
785 insert (s
, strlen (s
));
788 /* Like `insert' except that all markers pointing at the place where
789 the insertion happens are adjusted to point after it.
790 Don't use this function to insert part of a Lisp string,
791 since gc could happen and relocate it. */
794 insert_before_markers (string
, nbytes
)
795 const unsigned char *string
;
800 int len
= chars_in_text (string
, nbytes
), opoint
;
801 insert_1_both (string
, len
, nbytes
, 0, 1, 1);
803 signal_after_change (opoint
, 0, len
);
804 update_compositions (opoint
, PT
, CHECK_BORDER
);
808 /* Likewise, but inherit text properties from neighboring characters. */
811 insert_before_markers_and_inherit (string
, nbytes
)
812 const unsigned char *string
;
817 int len
= chars_in_text (string
, nbytes
), opoint
;
818 insert_1_both (string
, len
, nbytes
, 1, 1, 1);
820 signal_after_change (opoint
, 0, len
);
821 update_compositions (opoint
, PT
, CHECK_BORDER
);
825 /* Subroutine used by the insert functions above. */
828 insert_1 (string
, nbytes
, inherit
, prepare
, before_markers
)
829 register const unsigned char *string
;
831 int inherit
, prepare
, before_markers
;
833 insert_1_both (string
, chars_in_text (string
, nbytes
), nbytes
,
834 inherit
, prepare
, before_markers
);
838 #ifdef BYTE_COMBINING_DEBUG
840 /* See if the bytes before POS/POS_BYTE combine with bytes
841 at the start of STRING to form a single character.
842 If so, return the number of bytes at the start of STRING
843 which combine in this way. Otherwise, return 0. */
846 count_combining_before (string
, length
, pos
, pos_byte
)
847 const unsigned char *string
;
851 int len
, combining_bytes
;
852 const unsigned char *p
;
854 if (NILP (current_buffer
->enable_multibyte_characters
))
857 /* At first, we can exclude the following cases:
858 (1) STRING[0] can't be a following byte of multibyte sequence.
859 (2) POS is the start of the current buffer.
860 (3) A character before POS is not a multibyte character. */
861 if (length
== 0 || CHAR_HEAD_P (*string
)) /* case (1) */
863 if (pos_byte
== BEG_BYTE
) /* case (2) */
866 p
= BYTE_POS_ADDR (pos_byte
- 1);
867 while (! CHAR_HEAD_P (*p
)) p
--, len
++;
868 if (! BASE_LEADING_CODE_P (*p
)) /* case (3) */
871 combining_bytes
= BYTES_BY_CHAR_HEAD (*p
) - len
;
872 if (combining_bytes
<= 0)
873 /* The character preceding POS is, complete and no room for
874 combining bytes (combining_bytes == 0), or an independent 8-bit
875 character (combining_bytes < 0). */
878 /* We have a combination situation. Count the bytes at STRING that
881 while (!CHAR_HEAD_P (*p
) && p
< string
+ length
)
884 return (combining_bytes
< p
- string
? combining_bytes
: p
- string
);
887 /* See if the bytes after POS/POS_BYTE combine with bytes
888 at the end of STRING to form a single character.
889 If so, return the number of bytes after POS/POS_BYTE
890 which combine in this way. Otherwise, return 0. */
893 count_combining_after (string
, length
, pos
, pos_byte
)
894 const unsigned char *string
;
898 int opos_byte
= pos_byte
;
903 if (NILP (current_buffer
->enable_multibyte_characters
))
906 /* At first, we can exclude the following cases:
907 (1) The last byte of STRING is an ASCII.
908 (2) POS is the last of the current buffer.
909 (3) A character at POS can't be a following byte of multibyte
911 if (length
> 0 && ASCII_BYTE_P (string
[length
- 1])) /* case (1) */
913 if (pos_byte
== Z_BYTE
) /* case (2) */
915 bufp
= BYTE_POS_ADDR (pos_byte
);
916 if (CHAR_HEAD_P (*bufp
)) /* case (3) */
920 while (i
>= 0 && ! CHAR_HEAD_P (string
[i
]))
926 /* All characters in STRING are not character head. We must
927 check also preceding bytes at POS. We are sure that the gap
929 unsigned char *p
= BEG_ADDR
;
931 while (i
>= 0 && ! CHAR_HEAD_P (p
[i
]))
933 if (i
< 0 || !BASE_LEADING_CODE_P (p
[i
]))
936 bytes
= BYTES_BY_CHAR_HEAD (p
[i
]);
937 return (bytes
<= pos_byte
- 1 - i
+ length
939 : bytes
- (pos_byte
- 1 - i
+ length
));
941 if (!BASE_LEADING_CODE_P (string
[i
]))
944 bytes
= BYTES_BY_CHAR_HEAD (string
[i
]) - (length
- i
);
946 while (!CHAR_HEAD_P (*bufp
)) bufp
++, pos_byte
++;
948 return (bytes
<= pos_byte
- opos_byte
? bytes
: pos_byte
- opos_byte
);
954 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
955 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
956 are the same as in insert_1. */
959 insert_1_both (string
, nchars
, nbytes
, inherit
, prepare
, before_markers
)
960 register const unsigned char *string
;
961 register int nchars
, nbytes
;
962 int inherit
, prepare
, before_markers
;
967 if (NILP (current_buffer
->enable_multibyte_characters
))
971 /* Do this before moving and increasing the gap,
972 because the before-change hooks might move the gap
973 or make it smaller. */
974 prepare_to_modify_buffer (PT
, PT
, NULL
);
977 move_gap_both (PT
, PT_BYTE
);
978 if (GAP_SIZE
< nbytes
)
979 make_gap (nbytes
- GAP_SIZE
);
981 #ifdef BYTE_COMBINING_DEBUG
982 if (count_combining_before (string
, nbytes
, PT
, PT_BYTE
)
983 || count_combining_after (string
, nbytes
, PT
, PT_BYTE
))
987 /* Record deletion of the surrounding text that combines with
988 the insertion. This, together with recording the insertion,
989 will add up to the right stuff in the undo list. */
990 record_insert (PT
, nchars
);
992 CHARS_MODIFF
= MODIFF
;
994 bcopy (string
, GPT_ADDR
, nbytes
);
1003 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1008 /* The insert may have been in the unchanged region, so check again. */
1009 if (Z
- GPT
< END_UNCHANGED
)
1010 END_UNCHANGED
= Z
- GPT
;
1012 adjust_overlays_for_insert (PT
, nchars
);
1013 adjust_markers_for_insert (PT
, PT_BYTE
,
1014 PT
+ nchars
, PT_BYTE
+ nbytes
,
1017 if (BUF_INTERVALS (current_buffer
) != 0)
1018 offset_intervals (current_buffer
, PT
, nchars
);
1020 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
1021 set_text_properties (make_number (PT
), make_number (PT
+ nchars
),
1024 adjust_point (nchars
, nbytes
);
1029 /* Insert the part of the text of STRING, a Lisp object assumed to be
1030 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
1031 starting at position POS / POS_BYTE. If the text of STRING has properties,
1032 copy them into the buffer.
1034 It does not work to use `insert' for this, because a GC could happen
1035 before we bcopy the stuff into the buffer, and relocate the string
1036 without insert noticing. */
1039 insert_from_string (string
, pos
, pos_byte
, length
, length_byte
, inherit
)
1041 register int pos
, pos_byte
, length
, length_byte
;
1046 if (SCHARS (string
) == 0)
1049 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
1051 signal_after_change (opoint
, 0, PT
- opoint
);
1052 update_compositions (opoint
, PT
, CHECK_BORDER
);
1055 /* Like `insert_from_string' except that all markers pointing
1056 at the place where the insertion happens are adjusted to point after it. */
1059 insert_from_string_before_markers (string
, pos
, pos_byte
,
1060 length
, length_byte
, inherit
)
1062 register int pos
, pos_byte
, length
, length_byte
;
1067 if (SCHARS (string
) == 0)
1070 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
1072 signal_after_change (opoint
, 0, PT
- opoint
);
1073 update_compositions (opoint
, PT
, CHECK_BORDER
);
1076 /* Subroutine of the insertion functions above. */
1079 insert_from_string_1 (string
, pos
, pos_byte
, nchars
, nbytes
,
1080 inherit
, before_markers
)
1082 register int pos
, pos_byte
, nchars
, nbytes
;
1083 int inherit
, before_markers
;
1085 struct gcpro gcpro1
;
1086 int outgoing_nbytes
= nbytes
;
1089 /* Make OUTGOING_NBYTES describe the text
1090 as it will be inserted in this buffer. */
1092 if (NILP (current_buffer
->enable_multibyte_characters
))
1093 outgoing_nbytes
= nchars
;
1094 else if (! STRING_MULTIBYTE (string
))
1096 = count_size_as_multibyte (SDATA (string
) + pos_byte
,
1100 /* Do this before moving and increasing the gap,
1101 because the before-change hooks might move the gap
1102 or make it smaller. */
1103 prepare_to_modify_buffer (PT
, PT
, NULL
);
1106 move_gap_both (PT
, PT_BYTE
);
1107 if (GAP_SIZE
< outgoing_nbytes
)
1108 make_gap (outgoing_nbytes
- GAP_SIZE
);
1111 /* Copy the string text into the buffer, perhaps converting
1112 between single-byte and multibyte. */
1113 copy_text (SDATA (string
) + pos_byte
, GPT_ADDR
, nbytes
,
1114 STRING_MULTIBYTE (string
),
1115 ! NILP (current_buffer
->enable_multibyte_characters
));
1117 #ifdef BYTE_COMBINING_DEBUG
1118 /* We have copied text into the gap, but we have not altered
1119 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1120 to these functions and get the same results as we would
1121 have got earlier on. Meanwhile, PT_ADDR does point to
1122 the text that has been stored by copy_text. */
1123 if (count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
)
1124 || count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
))
1128 record_insert (PT
, nchars
);
1130 CHARS_MODIFF
= MODIFF
;
1132 GAP_SIZE
-= outgoing_nbytes
;
1136 GPT_BYTE
+= outgoing_nbytes
;
1137 ZV_BYTE
+= outgoing_nbytes
;
1138 Z_BYTE
+= outgoing_nbytes
;
1139 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1144 /* The insert may have been in the unchanged region, so check again. */
1145 if (Z
- GPT
< END_UNCHANGED
)
1146 END_UNCHANGED
= Z
- GPT
;
1148 adjust_overlays_for_insert (PT
, nchars
);
1149 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1150 PT_BYTE
+ outgoing_nbytes
,
1153 offset_intervals (current_buffer
, PT
, nchars
);
1155 intervals
= STRING_INTERVALS (string
);
1156 /* Get the intervals for the part of the string we are inserting. */
1157 if (nbytes
< SBYTES (string
))
1158 intervals
= copy_intervals (intervals
, pos
, nchars
);
1160 /* Insert those intervals. */
1161 graft_intervals_into_buffer (intervals
, PT
, nchars
,
1162 current_buffer
, inherit
);
1164 adjust_point (nchars
, outgoing_nbytes
);
1169 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1170 starting at GPT_ADDR. */
1173 insert_from_gap (nchars
, nbytes
)
1174 register int nchars
, nbytes
;
1176 if (NILP (current_buffer
->enable_multibyte_characters
))
1179 record_insert (GPT
, nchars
);
1189 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1194 adjust_overlays_for_insert (GPT
- nchars
, nchars
);
1195 adjust_markers_for_insert (GPT
- nchars
, GPT_BYTE
- nbytes
,
1198 if (BUF_INTERVALS (current_buffer
) != 0)
1200 offset_intervals (current_buffer
, GPT
- nchars
, nchars
);
1201 graft_intervals_into_buffer (NULL_INTERVAL
, GPT
- nchars
, nchars
,
1205 if (GPT
- nchars
< PT
)
1206 adjust_point (nchars
, nbytes
);
1211 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1212 current buffer. If the text in BUF has properties, they are absorbed
1213 into the current buffer.
1215 It does not work to use `insert' for this, because a malloc could happen
1216 and relocate BUF's text before the bcopy happens. */
1219 insert_from_buffer (buf
, charpos
, nchars
, inherit
)
1221 int charpos
, nchars
;
1226 insert_from_buffer_1 (buf
, charpos
, nchars
, inherit
);
1227 signal_after_change (opoint
, 0, PT
- opoint
);
1228 update_compositions (opoint
, PT
, CHECK_BORDER
);
1232 insert_from_buffer_1 (buf
, from
, nchars
, inherit
)
1237 register Lisp_Object temp
;
1238 int chunk
, chunk_expanded
;
1239 int from_byte
= buf_charpos_to_bytepos (buf
, from
);
1240 int to_byte
= buf_charpos_to_bytepos (buf
, from
+ nchars
);
1241 int incoming_nbytes
= to_byte
- from_byte
;
1242 int outgoing_nbytes
= incoming_nbytes
;
1245 /* Make OUTGOING_NBYTES describe the text
1246 as it will be inserted in this buffer. */
1248 if (NILP (current_buffer
->enable_multibyte_characters
))
1249 outgoing_nbytes
= nchars
;
1250 else if (NILP (buf
->enable_multibyte_characters
))
1252 int outgoing_before_gap
= 0;
1253 int outgoing_after_gap
= 0;
1255 if (from
< BUF_GPT (buf
))
1257 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1258 if (chunk
> incoming_nbytes
)
1259 chunk
= incoming_nbytes
;
1261 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
, from_byte
),
1267 if (chunk
< incoming_nbytes
)
1269 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
,
1271 incoming_nbytes
- chunk
);
1273 outgoing_nbytes
= outgoing_before_gap
+ outgoing_after_gap
;
1276 /* Make sure point-max won't overflow after this insertion. */
1277 XSETINT (temp
, outgoing_nbytes
+ Z
);
1278 if (outgoing_nbytes
+ Z
!= XINT (temp
))
1279 error ("Maximum buffer size exceeded");
1281 /* Do this before moving and increasing the gap,
1282 because the before-change hooks might move the gap
1283 or make it smaller. */
1284 prepare_to_modify_buffer (PT
, PT
, NULL
);
1287 move_gap_both (PT
, PT_BYTE
);
1288 if (GAP_SIZE
< outgoing_nbytes
)
1289 make_gap (outgoing_nbytes
- GAP_SIZE
);
1291 if (from
< BUF_GPT (buf
))
1293 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1294 if (chunk
> incoming_nbytes
)
1295 chunk
= incoming_nbytes
;
1296 /* Record number of output bytes, so we know where
1297 to put the output from the second copy_text. */
1299 = copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
),
1301 ! NILP (buf
->enable_multibyte_characters
),
1302 ! NILP (current_buffer
->enable_multibyte_characters
));
1305 chunk_expanded
= chunk
= 0;
1307 if (chunk
< incoming_nbytes
)
1308 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
+ chunk
),
1309 GPT_ADDR
+ chunk_expanded
, incoming_nbytes
- chunk
,
1310 ! NILP (buf
->enable_multibyte_characters
),
1311 ! NILP (current_buffer
->enable_multibyte_characters
));
1313 #ifdef BYTE_COMBINING_DEBUG
1314 /* We have copied text into the gap, but we have not altered
1315 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1316 to these functions and get the same results as we would
1317 have got earlier on. Meanwhile, GPT_ADDR does point to
1318 the text that has been stored by copy_text. */
1319 if (count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
)
1320 || count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
))
1324 record_insert (PT
, nchars
);
1326 CHARS_MODIFF
= MODIFF
;
1328 GAP_SIZE
-= outgoing_nbytes
;
1332 GPT_BYTE
+= outgoing_nbytes
;
1333 ZV_BYTE
+= outgoing_nbytes
;
1334 Z_BYTE
+= outgoing_nbytes
;
1335 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1340 /* The insert may have been in the unchanged region, so check again. */
1341 if (Z
- GPT
< END_UNCHANGED
)
1342 END_UNCHANGED
= Z
- GPT
;
1344 adjust_overlays_for_insert (PT
, nchars
);
1345 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1346 PT_BYTE
+ outgoing_nbytes
,
1349 if (BUF_INTERVALS (current_buffer
) != 0)
1350 offset_intervals (current_buffer
, PT
, nchars
);
1352 /* Get the intervals for the part of the string we are inserting. */
1353 intervals
= BUF_INTERVALS (buf
);
1354 if (outgoing_nbytes
< BUF_Z_BYTE (buf
) - BUF_BEG_BYTE (buf
))
1356 if (buf
== current_buffer
&& PT
<= from
)
1358 intervals
= copy_intervals (intervals
, from
, nchars
);
1361 /* Insert those intervals. */
1362 graft_intervals_into_buffer (intervals
, PT
, nchars
, current_buffer
, inherit
);
1364 adjust_point (nchars
, outgoing_nbytes
);
1367 /* Record undo information and adjust markers and position keepers for
1368 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1369 chars (LEN_BYTE bytes) which resides in the gap just after
1372 PREV_TEXT nil means the new text was just inserted. */
1375 adjust_after_replace (from
, from_byte
, prev_text
, len
, len_byte
)
1376 int from
, from_byte
, len
, len_byte
;
1377 Lisp_Object prev_text
;
1379 int nchars_del
= 0, nbytes_del
= 0;
1381 #ifdef BYTE_COMBINING_DEBUG
1382 if (count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
)
1383 || count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
))
1387 if (STRINGP (prev_text
))
1389 nchars_del
= SCHARS (prev_text
);
1390 nbytes_del
= SBYTES (prev_text
);
1393 /* Update various buffer positions for the new text. */
1394 GAP_SIZE
-= len_byte
;
1396 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1397 GPT
+= len
; GPT_BYTE
+= len_byte
;
1398 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1401 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1404 adjust_markers_for_insert (from
, from_byte
,
1405 from
+ len
, from_byte
+ len_byte
, 0);
1407 if (! EQ (current_buffer
->undo_list
, Qt
))
1410 record_delete (from
, prev_text
);
1411 record_insert (from
, len
);
1414 if (len
> nchars_del
)
1415 adjust_overlays_for_insert (from
, len
- nchars_del
);
1416 else if (len
< nchars_del
)
1417 adjust_overlays_for_delete (from
, nchars_del
- len
);
1418 if (BUF_INTERVALS (current_buffer
) != 0)
1420 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1424 adjust_point (len
- nchars_del
, len_byte
- nbytes_del
);
1426 /* As byte combining will decrease Z, we must check this again. */
1427 if (Z
- GPT
< END_UNCHANGED
)
1428 END_UNCHANGED
= Z
- GPT
;
1433 evaporate_overlays (from
);
1435 CHARS_MODIFF
= MODIFF
;
1438 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
1439 This is for use when undo is not enabled in the current buffer. */
1442 adjust_after_replace_noundo (from
, from_byte
, nchars_del
, nbytes_del
, len
, len_byte
)
1443 int from
, from_byte
, nchars_del
, nbytes_del
, len
, len_byte
;
1445 #ifdef BYTE_COMBINING_DEBUG
1446 if (count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
)
1447 || count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
))
1451 /* Update various buffer positions for the new text. */
1452 GAP_SIZE
-= len_byte
;
1454 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1455 GPT
+= len
; GPT_BYTE
+= len_byte
;
1456 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1459 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1462 adjust_markers_for_insert (from
, from_byte
,
1463 from
+ len
, from_byte
+ len_byte
, 0);
1465 if (len
> nchars_del
)
1466 adjust_overlays_for_insert (from
, len
- nchars_del
);
1467 else if (len
< nchars_del
)
1468 adjust_overlays_for_delete (from
, nchars_del
- len
);
1469 if (BUF_INTERVALS (current_buffer
) != 0)
1471 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1475 adjust_point (len
- nchars_del
, len_byte
- nbytes_del
);
1477 /* As byte combining will decrease Z, we must check this again. */
1478 if (Z
- GPT
< END_UNCHANGED
)
1479 END_UNCHANGED
= Z
- GPT
;
1484 evaporate_overlays (from
);
1486 CHARS_MODIFF
= MODIFF
;
1489 /* Record undo information, adjust markers and position keepers for an
1490 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1491 text already exists in the current buffer but character length (TO
1492 - FROM) may be incorrect, the correct length is NEWLEN. */
1495 adjust_after_insert (from
, from_byte
, to
, to_byte
, newlen
)
1496 int from
, from_byte
, to
, to_byte
, newlen
;
1498 int len
= to
- from
, len_byte
= to_byte
- from_byte
;
1501 move_gap_both (to
, to_byte
);
1502 GAP_SIZE
+= len_byte
;
1503 GPT
-= len
; GPT_BYTE
-= len_byte
;
1504 ZV
-= len
; ZV_BYTE
-= len_byte
;
1505 Z
-= len
; Z_BYTE
-= len_byte
;
1506 adjust_after_replace (from
, from_byte
, Qnil
, newlen
, len_byte
);
1509 /* Replace the text from character positions FROM to TO with NEW,
1510 If PREPARE is nonzero, call prepare_to_modify_buffer.
1511 If INHERIT, the newly inserted text should inherit text properties
1512 from the surrounding non-deleted text. */
1514 /* Note that this does not yet handle markers quite right.
1515 Also it needs to record a single undo-entry that does a replacement
1516 rather than a separate delete and insert.
1517 That way, undo will also handle markers properly.
1519 But if MARKERS is 0, don't relocate markers. */
1522 replace_range (from
, to
, new, prepare
, inherit
, markers
)
1524 int from
, to
, prepare
, inherit
, markers
;
1526 int inschars
= SCHARS (new);
1527 int insbytes
= SBYTES (new);
1528 int from_byte
, to_byte
;
1529 int nbytes_del
, nchars_del
;
1530 register Lisp_Object temp
;
1531 struct gcpro gcpro1
;
1533 int outgoing_insbytes
= insbytes
;
1534 Lisp_Object deletion
;
1543 int range_length
= to
- from
;
1544 prepare_to_modify_buffer (from
, to
, &from
);
1545 to
= from
+ range_length
;
1550 /* Make args be valid */
1556 from_byte
= CHAR_TO_BYTE (from
);
1557 to_byte
= CHAR_TO_BYTE (to
);
1559 nchars_del
= to
- from
;
1560 nbytes_del
= to_byte
- from_byte
;
1562 if (nbytes_del
<= 0 && insbytes
== 0)
1565 /* Make OUTGOING_INSBYTES describe the text
1566 as it will be inserted in this buffer. */
1568 if (NILP (current_buffer
->enable_multibyte_characters
))
1569 outgoing_insbytes
= inschars
;
1570 else if (! STRING_MULTIBYTE (new))
1572 = count_size_as_multibyte (SDATA (new), insbytes
);
1574 /* Make sure point-max won't overflow after this insertion. */
1575 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1576 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1577 error ("Maximum buffer size exceeded");
1581 /* Make sure the gap is somewhere in or next to what we are deleting. */
1583 gap_right (from
, from_byte
);
1585 gap_left (to
, to_byte
, 0);
1587 /* Even if we don't record for undo, we must keep the original text
1588 because we may have to recover it because of inappropriate byte
1590 if (! EQ (current_buffer
->undo_list
, Qt
))
1591 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1593 GAP_SIZE
+= nbytes_del
;
1596 ZV_BYTE
-= nbytes_del
;
1597 Z_BYTE
-= nbytes_del
;
1599 GPT_BYTE
= from_byte
;
1600 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1605 if (GPT
- BEG
< BEG_UNCHANGED
)
1606 BEG_UNCHANGED
= GPT
- BEG
;
1607 if (Z
- GPT
< END_UNCHANGED
)
1608 END_UNCHANGED
= Z
- GPT
;
1610 if (GAP_SIZE
< insbytes
)
1611 make_gap (insbytes
- GAP_SIZE
);
1613 /* Copy the string text into the buffer, perhaps converting
1614 between single-byte and multibyte. */
1615 copy_text (SDATA (new), GPT_ADDR
, insbytes
,
1616 STRING_MULTIBYTE (new),
1617 ! NILP (current_buffer
->enable_multibyte_characters
));
1619 #ifdef BYTE_COMBINING_DEBUG
1620 /* We have copied text into the gap, but we have not marked
1621 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1622 here, for both the previous text and the following text.
1623 Meanwhile, GPT_ADDR does point to
1624 the text that has been stored by copy_text. */
1625 if (count_combining_before (GPT_ADDR
, outgoing_insbytes
, from
, from_byte
)
1626 || count_combining_after (GPT_ADDR
, outgoing_insbytes
, from
, from_byte
))
1630 if (! EQ (current_buffer
->undo_list
, Qt
))
1632 /* Record the insertion first, so that when we undo,
1633 the deletion will be undone first. Thus, undo
1634 will insert before deleting, and thus will keep
1635 the markers before and after this text separate. */
1636 record_insert (from
+ SCHARS (deletion
), inschars
);
1637 record_delete (from
, deletion
);
1640 GAP_SIZE
-= outgoing_insbytes
;
1644 GPT_BYTE
+= outgoing_insbytes
;
1645 ZV_BYTE
+= outgoing_insbytes
;
1646 Z_BYTE
+= outgoing_insbytes
;
1647 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1652 /* Adjust the overlay center as needed. This must be done after
1653 adjusting the markers that bound the overlays. */
1654 adjust_overlays_for_delete (from
, nchars_del
);
1655 adjust_overlays_for_insert (from
, inschars
);
1657 /* Adjust markers for the deletion and the insertion. */
1659 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1660 inschars
, outgoing_insbytes
);
1662 offset_intervals (current_buffer
, from
, inschars
- nchars_del
);
1664 /* Get the intervals for the part of the string we are inserting--
1665 not including the combined-before bytes. */
1666 intervals
= STRING_INTERVALS (new);
1667 /* Insert those intervals. */
1668 graft_intervals_into_buffer (intervals
, from
, inschars
,
1669 current_buffer
, inherit
);
1671 /* Relocate point as if it were a marker. */
1673 adjust_point ((from
+ inschars
- (PT
< to
? PT
: to
)),
1674 (from_byte
+ outgoing_insbytes
1675 - (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
)));
1677 if (outgoing_insbytes
== 0)
1678 evaporate_overlays (from
);
1683 CHARS_MODIFF
= MODIFF
;
1686 signal_after_change (from
, nchars_del
, GPT
- from
);
1687 update_compositions (from
, GPT
, CHECK_BORDER
);
1690 /* Replace the text from character positions FROM to TO with
1691 the text in INS of length INSCHARS.
1692 Keep the text properties that applied to the old characters
1693 (extending them to all the new chars if there are more new chars).
1695 Note that this does not yet handle markers quite right.
1697 If MARKERS is nonzero, relocate markers.
1699 Unlike most functions at this level, never call
1700 prepare_to_modify_buffer and never call signal_after_change. */
1703 replace_range_2 (from
, from_byte
, to
, to_byte
, ins
, inschars
, insbytes
, markers
)
1704 int from
, from_byte
, to
, to_byte
;
1706 int inschars
, insbytes
, markers
;
1708 int nbytes_del
, nchars_del
;
1713 nchars_del
= to
- from
;
1714 nbytes_del
= to_byte
- from_byte
;
1716 if (nbytes_del
<= 0 && insbytes
== 0)
1719 /* Make sure point-max won't overflow after this insertion. */
1720 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1721 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1722 error ("Maximum buffer size exceeded");
1724 /* Make sure the gap is somewhere in or next to what we are deleting. */
1726 gap_right (from
, from_byte
);
1728 gap_left (to
, to_byte
, 0);
1730 GAP_SIZE
+= nbytes_del
;
1733 ZV_BYTE
-= nbytes_del
;
1734 Z_BYTE
-= nbytes_del
;
1736 GPT_BYTE
= from_byte
;
1737 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1742 if (GPT
- BEG
< BEG_UNCHANGED
)
1743 BEG_UNCHANGED
= GPT
- BEG
;
1744 if (Z
- GPT
< END_UNCHANGED
)
1745 END_UNCHANGED
= Z
- GPT
;
1747 if (GAP_SIZE
< insbytes
)
1748 make_gap (insbytes
- GAP_SIZE
);
1750 /* Copy the replacement text into the buffer. */
1751 bcopy (ins
, GPT_ADDR
, insbytes
);
1753 #ifdef BYTE_COMBINING_DEBUG
1754 /* We have copied text into the gap, but we have not marked
1755 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1756 here, for both the previous text and the following text.
1757 Meanwhile, GPT_ADDR does point to
1758 the text that has been stored by copy_text. */
1759 if (count_combining_before (GPT_ADDR
, insbytes
, from
, from_byte
)
1760 || count_combining_after (GPT_ADDR
, insbytes
, from
, from_byte
))
1764 GAP_SIZE
-= insbytes
;
1768 GPT_BYTE
+= insbytes
;
1769 ZV_BYTE
+= insbytes
;
1771 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1776 /* Adjust the overlay center as needed. This must be done after
1777 adjusting the markers that bound the overlays. */
1778 if (nchars_del
!= inschars
)
1780 adjust_overlays_for_insert (from
, inschars
);
1781 adjust_overlays_for_delete (from
+ inschars
, nchars_del
);
1784 /* Adjust markers for the deletion and the insertion. */
1786 && ! (nchars_del
== 1 && inschars
== 1 && nbytes_del
== insbytes
))
1787 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1788 inschars
, insbytes
);
1790 offset_intervals (current_buffer
, from
, inschars
- nchars_del
);
1792 /* Relocate point as if it were a marker. */
1793 if (from
< PT
&& (nchars_del
!= inschars
|| nbytes_del
!= insbytes
))
1796 /* PT was within the deleted text. Move it to FROM. */
1797 adjust_point (from
- PT
, from_byte
- PT_BYTE
);
1799 adjust_point (inschars
- nchars_del
, insbytes
- nbytes_del
);
1803 evaporate_overlays (from
);
1808 CHARS_MODIFF
= MODIFF
;
1811 /* Delete characters in current buffer
1812 from FROM up to (but not including) TO.
1813 If TO comes before FROM, we delete nothing. */
1816 del_range (from
, to
)
1817 register int from
, to
;
1819 del_range_1 (from
, to
, 1, 0);
1822 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1823 RET_STRING says to return the deleted text. */
1826 del_range_1 (from
, to
, prepare
, ret_string
)
1827 int from
, to
, prepare
, ret_string
;
1829 int from_byte
, to_byte
;
1830 Lisp_Object deletion
;
1831 struct gcpro gcpro1
;
1833 /* Make args be valid */
1844 int range_length
= to
- from
;
1845 prepare_to_modify_buffer (from
, to
, &from
);
1846 to
= min (ZV
, from
+ range_length
);
1849 from_byte
= CHAR_TO_BYTE (from
);
1850 to_byte
= CHAR_TO_BYTE (to
);
1852 deletion
= del_range_2 (from
, from_byte
, to
, to_byte
, ret_string
);
1854 signal_after_change (from
, to
- from
, 0);
1855 update_compositions (from
, from
, CHECK_HEAD
);
1860 /* Like del_range_1 but args are byte positions, not char positions. */
1863 del_range_byte (from_byte
, to_byte
, prepare
)
1864 int from_byte
, to_byte
, prepare
;
1868 /* Make args be valid */
1869 if (from_byte
< BEGV_BYTE
)
1870 from_byte
= BEGV_BYTE
;
1871 if (to_byte
> ZV_BYTE
)
1874 if (to_byte
<= from_byte
)
1877 from
= BYTE_TO_CHAR (from_byte
);
1878 to
= BYTE_TO_CHAR (to_byte
);
1882 int old_from
= from
, old_to
= Z
- to
;
1883 int range_length
= to
- from
;
1884 prepare_to_modify_buffer (from
, to
, &from
);
1885 to
= from
+ range_length
;
1887 if (old_from
!= from
)
1888 from_byte
= CHAR_TO_BYTE (from
);
1894 else if (old_to
== Z
- to
)
1895 to_byte
= CHAR_TO_BYTE (to
);
1898 del_range_2 (from
, from_byte
, to
, to_byte
, 0);
1899 signal_after_change (from
, to
- from
, 0);
1900 update_compositions (from
, from
, CHECK_HEAD
);
1903 /* Like del_range_1, but positions are specified both as charpos
1907 del_range_both (from
, from_byte
, to
, to_byte
, prepare
)
1908 int from
, from_byte
, to
, to_byte
, prepare
;
1910 /* Make args be valid */
1911 if (from_byte
< BEGV_BYTE
)
1912 from_byte
= BEGV_BYTE
;
1913 if (to_byte
> ZV_BYTE
)
1916 if (to_byte
<= from_byte
)
1926 int old_from
= from
, old_to
= Z
- to
;
1927 int range_length
= to
- from
;
1928 prepare_to_modify_buffer (from
, to
, &from
);
1929 to
= from
+ range_length
;
1931 if (old_from
!= from
)
1932 from_byte
= CHAR_TO_BYTE (from
);
1938 else if (old_to
== Z
- to
)
1939 to_byte
= CHAR_TO_BYTE (to
);
1942 del_range_2 (from
, from_byte
, to
, to_byte
, 0);
1943 signal_after_change (from
, to
- from
, 0);
1944 update_compositions (from
, from
, CHECK_HEAD
);
1947 /* Delete a range of text, specified both as character positions
1948 and byte positions. FROM and TO are character positions,
1949 while FROM_BYTE and TO_BYTE are byte positions.
1950 If RET_STRING is true, the deleted area is returned as a string. */
1953 del_range_2 (from
, from_byte
, to
, to_byte
, ret_string
)
1954 int from
, from_byte
, to
, to_byte
, ret_string
;
1956 register int nbytes_del
, nchars_del
;
1957 Lisp_Object deletion
;
1961 nchars_del
= to
- from
;
1962 nbytes_del
= to_byte
- from_byte
;
1964 /* Make sure the gap is somewhere in or next to what we are deleting. */
1966 gap_right (from
, from_byte
);
1968 gap_left (to
, to_byte
, 0);
1970 #ifdef BYTE_COMBINING_DEBUG
1971 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer
, to_byte
),
1972 Z_BYTE
- to_byte
, from
, from_byte
))
1976 if (ret_string
|| ! EQ (current_buffer
->undo_list
, Qt
))
1977 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1981 /* Relocate all markers pointing into the new, larger gap
1982 to point at the end of the text before the gap.
1983 Do this before recording the deletion,
1984 so that undo handles this after reinserting the text. */
1985 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1987 if (! EQ (current_buffer
->undo_list
, Qt
))
1988 record_delete (from
, deletion
);
1990 CHARS_MODIFF
= MODIFF
;
1992 /* Relocate point as if it were a marker. */
1994 adjust_point (from
- (PT
< to
? PT
: to
),
1995 from_byte
- (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
));
1997 offset_intervals (current_buffer
, from
, - nchars_del
);
1999 /* Adjust the overlay center as needed. This must be done after
2000 adjusting the markers that bound the overlays. */
2001 adjust_overlays_for_delete (from
, nchars_del
);
2003 GAP_SIZE
+= nbytes_del
;
2004 ZV_BYTE
-= nbytes_del
;
2005 Z_BYTE
-= nbytes_del
;
2009 GPT_BYTE
= from_byte
;
2010 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
2015 if (GPT
- BEG
< BEG_UNCHANGED
)
2016 BEG_UNCHANGED
= GPT
- BEG
;
2017 if (Z
- GPT
< END_UNCHANGED
)
2018 END_UNCHANGED
= Z
- GPT
;
2022 evaporate_overlays (from
);
2027 /* Call this if you're about to change the region of BUFFER from
2028 character positions START to END. This checks the read-only
2029 properties of the region, calls the necessary modification hooks,
2030 and warns the next redisplay that it should pay attention to that
2033 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
2034 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
2037 modify_region (buffer
, start
, end
, preserve_chars_modiff
)
2038 struct buffer
*buffer
;
2039 int start
, end
, preserve_chars_modiff
;
2041 struct buffer
*old_buffer
= current_buffer
;
2043 if (buffer
!= old_buffer
)
2044 set_buffer_internal (buffer
);
2046 prepare_to_modify_buffer (start
, end
, NULL
);
2048 BUF_COMPUTE_UNCHANGED (buffer
, start
- 1, end
);
2050 if (MODIFF
<= SAVE_MODIFF
)
2051 record_first_change ();
2053 if (! preserve_chars_modiff
)
2054 CHARS_MODIFF
= MODIFF
;
2056 buffer
->point_before_scroll
= Qnil
;
2058 if (buffer
!= old_buffer
)
2059 set_buffer_internal (old_buffer
);
2062 /* Check that it is okay to modify the buffer between START and END,
2063 which are char positions.
2065 Run the before-change-function, if any. If intervals are in use,
2066 verify that the text to be modified is not read-only, and call
2067 any modification properties the text may have.
2069 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2070 by holding its value temporarily in a marker. */
2073 prepare_to_modify_buffer (start
, end
, preserve_ptr
)
2077 struct buffer
*base_buffer
;
2079 if (!NILP (current_buffer
->read_only
))
2080 Fbarf_if_buffer_read_only ();
2082 /* Let redisplay consider other windows than selected_window
2083 if modifying another buffer. */
2084 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2085 ++windows_or_buffers_changed
;
2087 if (BUF_INTERVALS (current_buffer
) != 0)
2091 Lisp_Object preserve_marker
;
2092 struct gcpro gcpro1
;
2093 preserve_marker
= Fcopy_marker (make_number (*preserve_ptr
), Qnil
);
2094 GCPRO1 (preserve_marker
);
2095 verify_interval_modification (current_buffer
, start
, end
);
2096 *preserve_ptr
= marker_position (preserve_marker
);
2097 unchain_marker (XMARKER (preserve_marker
));
2101 verify_interval_modification (current_buffer
, start
, end
);
2104 /* For indirect buffers, use the base buffer to check clashes. */
2105 if (current_buffer
->base_buffer
!= 0)
2106 base_buffer
= current_buffer
->base_buffer
;
2108 base_buffer
= current_buffer
;
2110 #ifdef CLASH_DETECTION
2111 if (!NILP (base_buffer
->file_truename
)
2112 /* Make binding buffer-file-name to nil effective. */
2113 && !NILP (base_buffer
->filename
)
2114 && SAVE_MODIFF
>= MODIFF
)
2115 lock_file (base_buffer
->file_truename
);
2117 /* At least warn if this file has changed on disk since it was visited. */
2118 if (!NILP (base_buffer
->filename
)
2119 && SAVE_MODIFF
>= MODIFF
2120 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
2121 && !NILP (Ffile_exists_p (base_buffer
->filename
)))
2122 call1 (intern ("ask-user-about-supersession-threat"),
2123 base_buffer
->filename
);
2124 #endif /* not CLASH_DETECTION */
2126 signal_before_change (start
, end
, preserve_ptr
);
2128 if (current_buffer
->newline_cache
)
2129 invalidate_region_cache (current_buffer
,
2130 current_buffer
->newline_cache
,
2131 start
- BEG
, Z
- end
);
2132 if (current_buffer
->width_run_cache
)
2133 invalidate_region_cache (current_buffer
,
2134 current_buffer
->width_run_cache
,
2135 start
- BEG
, Z
- end
);
2137 Vdeactivate_mark
= Qt
;
2140 /* These macros work with an argument named `preserve_ptr'
2141 and a local variable named `preserve_marker'. */
2143 #define PRESERVE_VALUE \
2144 if (preserve_ptr && NILP (preserve_marker)) \
2145 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2147 #define RESTORE_VALUE \
2148 if (! NILP (preserve_marker)) \
2150 *preserve_ptr = marker_position (preserve_marker); \
2151 unchain_marker (XMARKER (preserve_marker)); \
2154 #define PRESERVE_START_END \
2155 if (NILP (start_marker)) \
2156 start_marker = Fcopy_marker (start, Qnil); \
2157 if (NILP (end_marker)) \
2158 end_marker = Fcopy_marker (end, Qnil);
2160 #define FETCH_START \
2161 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2164 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2166 /* Set a variable to nil if an error occurred.
2167 Don't change the variable if there was no error.
2168 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
2169 VARIABLE is the variable to maybe set to nil.
2170 NO-ERROR-FLAG is nil if there was an error,
2171 anything else meaning no error (so this function does nothing). */
2173 reset_var_on_error (val
)
2176 if (NILP (XCDR (val
)))
2177 Fset (XCAR (val
), Qnil
);
2181 /* Signal a change to the buffer immediately before it happens.
2182 START_INT and END_INT are the bounds of the text to be changed.
2184 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2185 by holding its value temporarily in a marker. */
2188 signal_before_change (start_int
, end_int
, preserve_ptr
)
2189 int start_int
, end_int
;
2192 Lisp_Object start
, end
;
2193 Lisp_Object start_marker
, end_marker
;
2194 Lisp_Object preserve_marker
;
2195 struct gcpro gcpro1
, gcpro2
, gcpro3
;
2196 int count
= SPECPDL_INDEX ();
2198 if (inhibit_modification_hooks
)
2201 start
= make_number (start_int
);
2202 end
= make_number (end_int
);
2203 preserve_marker
= Qnil
;
2204 start_marker
= Qnil
;
2206 GCPRO3 (preserve_marker
, start_marker
, end_marker
);
2208 specbind (Qinhibit_modification_hooks
, Qt
);
2210 /* If buffer is unmodified, run a special hook for that case. */
2211 if (SAVE_MODIFF
>= MODIFF
2212 && !NILP (Vfirst_change_hook
)
2213 && !NILP (Vrun_hooks
))
2217 call1 (Vrun_hooks
, Qfirst_change_hook
);
2220 /* Now run the before-change-functions if any. */
2221 if (!NILP (Vbefore_change_functions
))
2223 Lisp_Object args
[3];
2224 Lisp_Object rvoe_arg
= Fcons (Qbefore_change_functions
, Qnil
);
2229 /* Mark before-change-functions to be reset to nil in case of error. */
2230 record_unwind_protect (reset_var_on_error
, rvoe_arg
);
2232 /* Actually run the hook functions. */
2233 args
[0] = Qbefore_change_functions
;
2234 args
[1] = FETCH_START
;
2235 args
[2] = FETCH_END
;
2236 Frun_hook_with_args (3, args
);
2238 /* There was no error: unarm the reset_on_error. */
2239 XSETCDR (rvoe_arg
, Qt
);
2242 if (current_buffer
->overlays_before
|| current_buffer
->overlays_after
)
2245 report_overlay_modification (FETCH_START
, FETCH_END
, 0,
2246 FETCH_START
, FETCH_END
, Qnil
);
2249 if (! NILP (start_marker
))
2250 free_marker (start_marker
);
2251 if (! NILP (end_marker
))
2252 free_marker (end_marker
);
2256 unbind_to (count
, Qnil
);
2259 /* Signal a change immediately after it happens.
2260 CHARPOS is the character position of the start of the changed text.
2261 LENDEL is the number of characters of the text before the change.
2262 (Not the whole buffer; just the part that was changed.)
2263 LENINS is the number of characters in that part of the text
2264 after the change. */
2267 signal_after_change (charpos
, lendel
, lenins
)
2268 int charpos
, lendel
, lenins
;
2270 int count
= SPECPDL_INDEX ();
2271 if (inhibit_modification_hooks
)
2274 /* If we are deferring calls to the after-change functions
2275 and there are no before-change functions,
2276 just record the args that we were going to use. */
2277 if (! NILP (Vcombine_after_change_calls
)
2278 && NILP (Vbefore_change_functions
)
2279 && !current_buffer
->overlays_before
2280 && !current_buffer
->overlays_after
)
2284 if (!NILP (combine_after_change_list
)
2285 && current_buffer
!= XBUFFER (combine_after_change_buffer
))
2286 Fcombine_after_change_execute ();
2288 elt
= Fcons (make_number (charpos
- BEG
),
2289 Fcons (make_number (Z
- (charpos
- lendel
+ lenins
)),
2290 Fcons (make_number (lenins
- lendel
), Qnil
)));
2291 combine_after_change_list
2292 = Fcons (elt
, combine_after_change_list
);
2293 combine_after_change_buffer
= Fcurrent_buffer ();
2298 if (!NILP (combine_after_change_list
))
2299 Fcombine_after_change_execute ();
2301 specbind (Qinhibit_modification_hooks
, Qt
);
2303 if (!NILP (Vafter_change_functions
))
2305 Lisp_Object args
[4];
2306 Lisp_Object rvoe_arg
= Fcons (Qafter_change_functions
, Qnil
);
2308 /* Mark after-change-functions to be reset to nil in case of error. */
2309 record_unwind_protect (reset_var_on_error
, rvoe_arg
);
2311 /* Actually run the hook functions. */
2312 args
[0] = Qafter_change_functions
;
2313 XSETFASTINT (args
[1], charpos
);
2314 XSETFASTINT (args
[2], charpos
+ lenins
);
2315 XSETFASTINT (args
[3], lendel
);
2316 Frun_hook_with_args (4, args
);
2318 /* There was no error: unarm the reset_on_error. */
2319 XSETCDR (rvoe_arg
, Qt
);
2322 if (current_buffer
->overlays_before
|| current_buffer
->overlays_after
)
2323 report_overlay_modification (make_number (charpos
),
2324 make_number (charpos
+ lenins
),
2326 make_number (charpos
),
2327 make_number (charpos
+ lenins
),
2328 make_number (lendel
));
2330 /* After an insertion, call the text properties
2331 insert-behind-hooks or insert-in-front-hooks. */
2333 report_interval_modification (make_number (charpos
),
2334 make_number (charpos
+ lenins
));
2336 unbind_to (count
, Qnil
);
2340 Fcombine_after_change_execute_1 (val
)
2343 Vcombine_after_change_calls
= val
;
2347 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute
,
2348 Scombine_after_change_execute
, 0, 0, 0,
2349 doc
: /* This function is for use internally in `combine-after-change-calls'. */)
2352 int count
= SPECPDL_INDEX ();
2353 int beg
, end
, change
;
2357 if (NILP (combine_after_change_list
))
2360 /* It is rare for combine_after_change_buffer to be invalid, but
2361 possible. It can happen when combine-after-change-calls is
2362 non-nil, and insertion calls a file handler (e.g. through
2363 lock_file) which scribbles into a temp file -- cyd */
2364 if (!BUFFERP (combine_after_change_buffer
)
2365 || NILP (XBUFFER (combine_after_change_buffer
)->name
))
2367 combine_after_change_list
= Qnil
;
2371 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
2373 Fset_buffer (combine_after_change_buffer
);
2375 /* # chars unchanged at beginning of buffer. */
2377 /* # chars unchanged at end of buffer. */
2379 /* Total amount of insertion (negative for deletion). */
2382 /* Scan the various individual changes,
2383 accumulating the range info in BEG, END and CHANGE. */
2384 for (tail
= combine_after_change_list
; CONSP (tail
);
2388 int thisbeg
, thisend
, thischange
;
2390 /* Extract the info from the next element. */
2394 thisbeg
= XINT (XCAR (elt
));
2399 thisend
= XINT (XCAR (elt
));
2404 thischange
= XINT (XCAR (elt
));
2406 /* Merge this range into the accumulated range. */
2407 change
+= thischange
;
2414 /* Get the current start and end positions of the range
2415 that was changed. */
2419 /* We are about to handle these, so discard them. */
2420 combine_after_change_list
= Qnil
;
2422 /* Now run the after-change functions for real.
2423 Turn off the flag that defers them. */
2424 record_unwind_protect (Fcombine_after_change_execute_1
,
2425 Vcombine_after_change_calls
);
2426 signal_after_change (begpos
, endpos
- begpos
- change
, endpos
- begpos
);
2427 update_compositions (begpos
, endpos
, CHECK_ALL
);
2429 return unbind_to (count
, Qnil
);
2435 staticpro (&combine_after_change_list
);
2436 staticpro (&combine_after_change_buffer
);
2437 combine_after_change_list
= Qnil
;
2438 combine_after_change_buffer
= Qnil
;
2440 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag
,
2441 doc
: /* Non-nil means enable debugging checks for invalid marker positions. */);
2442 check_markers_debug_flag
= 0;
2443 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls
,
2444 doc
: /* Used internally by the `combine-after-change-calls' macro. */);
2445 Vcombine_after_change_calls
= Qnil
;
2447 DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks
,
2448 doc
: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2449 This affects `before-change-functions' and `after-change-functions',
2450 as well as hooks attached to text properties and overlays. */);
2451 inhibit_modification_hooks
= 0;
2452 Qinhibit_modification_hooks
= intern ("inhibit-modification-hooks");
2453 staticpro (&Qinhibit_modification_hooks
);
2455 defsubr (&Scombine_after_change_execute
);
2458 /* arch-tag: 9b34b886-47d7-465e-a234-299af411b23d
2459 (do not change this comment) */