1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985-1986, 1993-1995, 1997-2011
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 #include "intervals.h"
26 #include "character.h"
28 #include "blockinput.h"
29 #include "region-cache.h"
35 static void insert_from_string_1 (Lisp_Object string
,
36 EMACS_INT pos
, EMACS_INT pos_byte
,
37 EMACS_INT nchars
, EMACS_INT nbytes
,
38 int inherit
, int before_markers
);
39 static void insert_from_buffer_1 (struct buffer
*buf
,
40 EMACS_INT from
, EMACS_INT nchars
,
42 static void gap_left (EMACS_INT charpos
, EMACS_INT bytepos
, int newgap
);
43 static void gap_right (EMACS_INT charpos
, EMACS_INT bytepos
);
44 static void adjust_markers_for_insert (EMACS_INT from
, EMACS_INT from_byte
,
45 EMACS_INT to
, EMACS_INT to_byte
,
47 static void adjust_markers_for_replace (EMACS_INT
, EMACS_INT
, EMACS_INT
,
48 EMACS_INT
, EMACS_INT
, EMACS_INT
);
49 static void adjust_point (EMACS_INT nchars
, EMACS_INT nbytes
);
51 INFUN (Fcombine_after_change_execute
, 0);
53 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
54 describing changes which happened while combine_after_change_calls
55 was nonzero. We use this to decide how to call them
56 once the deferral ends.
59 BEG-UNCHANGED is the number of chars before the changed range.
60 END-UNCHANGED is the number of chars after the changed range,
61 and CHANGE-AMOUNT is the number of characters inserted by the change
62 (negative for a deletion). */
63 Lisp_Object combine_after_change_list
;
65 /* Buffer which combine_after_change_list is about. */
66 Lisp_Object combine_after_change_buffer
;
68 Lisp_Object Qinhibit_modification_hooks
;
70 #define CHECK_MARKERS() \
73 if (check_markers_debug_flag) \
81 register struct Lisp_Marker
*tail
;
82 int multibyte
= ! NILP (BVAR (current_buffer
, enable_multibyte_characters
));
84 for (tail
= BUF_MARKERS (current_buffer
); tail
; tail
= tail
->next
)
86 if (tail
->buffer
->text
!= current_buffer
->text
)
88 if (tail
->charpos
> Z
)
90 if (tail
->bytepos
> Z_BYTE
)
92 if (multibyte
&& ! CHAR_HEAD_P (FETCH_BYTE (tail
->bytepos
)))
97 /* Move gap to position CHARPOS.
98 Note that this can quit! */
101 move_gap (EMACS_INT charpos
)
103 move_gap_both (charpos
, charpos_to_bytepos (charpos
));
106 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
107 Note that this can quit! */
110 move_gap_both (EMACS_INT charpos
, EMACS_INT bytepos
)
112 if (bytepos
< GPT_BYTE
)
113 gap_left (charpos
, bytepos
, 0);
114 else if (bytepos
> GPT_BYTE
)
115 gap_right (charpos
, bytepos
);
118 /* Move the gap to a position less than the current GPT.
119 BYTEPOS describes the new position as a byte position,
120 and CHARPOS is the corresponding char position.
121 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
124 gap_left (EMACS_INT charpos
, EMACS_INT bytepos
, int newgap
)
126 register unsigned char *to
, *from
;
127 register EMACS_INT i
;
131 BUF_COMPUTE_UNCHANGED (current_buffer
, charpos
, GPT
);
138 /* Now copy the characters. To move the gap down,
139 copy characters up. */
143 /* I gets number of characters left to copy. */
144 i
= new_s1
- bytepos
;
147 /* If a quit is requested, stop copying now.
148 Change BYTEPOS to be where we have actually moved the gap to. */
152 charpos
= BYTE_TO_CHAR (bytepos
);
155 /* Move at most 32000 chars before checking again for a quit. */
160 memmove (to
, from
, i
);
163 /* Adjust buffer data structure, to put the gap at BYTEPOS.
164 BYTEPOS is where the loop above stopped, which may be what
165 was specified or may be where a quit was detected. */
168 if (bytepos
< charpos
)
170 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
174 /* Move the gap to a position greater than the current GPT.
175 BYTEPOS describes the new position as a byte position,
176 and CHARPOS is the corresponding char position. */
179 gap_right (EMACS_INT charpos
, EMACS_INT bytepos
)
181 register unsigned char *to
, *from
;
182 register EMACS_INT i
;
185 BUF_COMPUTE_UNCHANGED (current_buffer
, charpos
, GPT
);
192 /* Now copy the characters. To move the gap up,
193 copy characters down. */
197 /* I gets number of characters left to copy. */
198 i
= bytepos
- new_s1
;
201 /* If a quit is requested, stop copying now.
202 Change BYTEPOS to be where we have actually moved the gap to. */
206 charpos
= BYTE_TO_CHAR (bytepos
);
209 /* Move at most 32000 chars before checking again for a quit. */
213 memmove (to
, from
, i
);
219 if (bytepos
< charpos
)
221 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
225 /* Adjust all markers for a deletion
226 whose range in bytes is FROM_BYTE to TO_BYTE.
227 The range in charpos is FROM to TO.
229 This function assumes that the gap is adjacent to
230 or inside of the range being deleted. */
233 adjust_markers_for_delete (EMACS_INT from
, EMACS_INT from_byte
,
234 EMACS_INT to
, EMACS_INT to_byte
)
237 register struct Lisp_Marker
*m
;
238 register EMACS_INT charpos
;
240 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
242 charpos
= m
->charpos
;
247 /* If the marker is after the deletion,
248 relocate by number of chars / bytes deleted. */
251 m
->charpos
-= to
- from
;
252 m
->bytepos
-= to_byte
- from_byte
;
254 /* Here's the case where a marker is inside text being deleted. */
255 else if (charpos
> from
)
257 if (! m
->insertion_type
)
258 { /* Normal markers will end up at the beginning of the
259 re-inserted text after undoing a deletion, and must be
260 adjusted to move them to the correct place. */
261 XSETMISC (marker
, m
);
262 record_marker_adjustment (marker
, from
- charpos
);
264 else if (charpos
< to
)
265 { /* Before-insertion markers will automatically move forward
266 upon re-inserting the deleted text, so we have to arrange
267 for them to move backward to the correct position. */
268 XSETMISC (marker
, m
);
269 record_marker_adjustment (marker
, to
- charpos
);
272 m
->bytepos
= from_byte
;
274 /* Here's the case where a before-insertion marker is immediately
275 before the deleted region. */
276 else if (charpos
== from
&& m
->insertion_type
)
278 /* Undoing the change uses normal insertion, which will
279 incorrectly make MARKER move forward, so we arrange for it
280 to then move backward to the correct place at the beginning
281 of the deleted region. */
282 XSETMISC (marker
, m
);
283 record_marker_adjustment (marker
, to
- from
);
289 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
290 to TO / TO_BYTE. We have to relocate the charpos of every marker
291 that points after the insertion (but not their bytepos).
293 When a marker points at the insertion point,
294 we advance it if either its insertion-type is t
295 or BEFORE_MARKERS is true. */
298 adjust_markers_for_insert (EMACS_INT from
, EMACS_INT from_byte
,
299 EMACS_INT to
, EMACS_INT to_byte
, int before_markers
)
301 struct Lisp_Marker
*m
;
303 EMACS_INT nchars
= to
- from
;
304 EMACS_INT nbytes
= to_byte
- from_byte
;
306 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
308 eassert (m
->bytepos
>= m
->charpos
309 && m
->bytepos
- m
->charpos
<= Z_BYTE
- Z
);
311 if (m
->bytepos
== from_byte
)
313 if (m
->insertion_type
|| before_markers
)
315 m
->bytepos
= to_byte
;
317 if (m
->insertion_type
)
321 else if (m
->bytepos
> from_byte
)
323 m
->bytepos
+= nbytes
;
324 m
->charpos
+= nchars
;
328 /* Adjusting only markers whose insertion-type is t may result in
329 - disordered start and end in overlays, and
330 - disordered overlays in the slot `overlays_before' of current_buffer. */
333 fix_start_end_in_overlays(from
, to
);
334 fix_overlays_before (current_buffer
, from
, to
);
338 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
340 This is used only when the value of point changes due to an insert
341 or delete; it does not represent a conceptual change in point as a
342 marker. In particular, point is not crossing any interval
343 boundaries, so there's no need to use the usual SET_PT macro. In
344 fact it would be incorrect to do so, because either the old or the
345 new value of point is out of sync with the current set of
349 adjust_point (EMACS_INT nchars
, EMACS_INT nbytes
)
351 SET_BUF_PT_BOTH (current_buffer
, PT
+ nchars
, PT_BYTE
+ nbytes
);
352 /* In a single-byte buffer, the two positions must be equal. */
353 eassert (PT_BYTE
>= PT
&& PT_BYTE
- PT
<= ZV_BYTE
- ZV
);
356 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
357 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
358 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
362 adjust_markers_for_replace (EMACS_INT from
, EMACS_INT from_byte
,
363 EMACS_INT old_chars
, EMACS_INT old_bytes
,
364 EMACS_INT new_chars
, EMACS_INT new_bytes
)
366 register struct Lisp_Marker
*m
;
367 EMACS_INT prev_to_byte
= from_byte
+ old_bytes
;
368 EMACS_INT diff_chars
= new_chars
- old_chars
;
369 EMACS_INT diff_bytes
= new_bytes
- old_bytes
;
371 for (m
= BUF_MARKERS (current_buffer
); m
; m
= m
->next
)
373 if (m
->bytepos
>= prev_to_byte
)
375 m
->charpos
+= diff_chars
;
376 m
->bytepos
+= diff_bytes
;
378 else if (m
->bytepos
> from_byte
)
381 m
->bytepos
= from_byte
;
389 /* Make the gap NBYTES_ADDED bytes longer. */
392 make_gap_larger (EMACS_INT nbytes_added
)
395 EMACS_INT real_gap_loc
;
396 EMACS_INT real_gap_loc_byte
;
397 EMACS_INT old_gap_size
;
399 /* If we have to get more space, get enough to last a while. */
400 nbytes_added
+= 2000;
402 { EMACS_INT total_size
= Z_BYTE
- BEG_BYTE
+ GAP_SIZE
+ nbytes_added
;
404 /* Don't allow a buffer size that won't fit in a Lisp integer. */
405 || total_size
!= XINT (make_number (total_size
))
406 /* Don't allow a buffer size that won't fit in an int
407 even if it will fit in a Lisp integer.
408 That won't work because so many places still use `int'. */
409 || total_size
!= (EMACS_INT
) (int) total_size
)
410 error ("Buffer exceeds maximum size");
413 enlarge_buffer_text (current_buffer
, nbytes_added
);
415 /* Prevent quitting in move_gap. */
420 real_gap_loc_byte
= GPT_BYTE
;
421 old_gap_size
= GAP_SIZE
;
423 /* Call the newly allocated space a gap at the end of the whole space. */
425 GPT_BYTE
= Z_BYTE
+ GAP_SIZE
;
426 GAP_SIZE
= nbytes_added
;
428 /* Move the new gap down to be consecutive with the end of the old one.
429 This adjusts the markers properly too. */
430 gap_left (real_gap_loc
+ old_gap_size
, real_gap_loc_byte
+ old_gap_size
, 1);
432 /* Now combine the two into one large gap. */
433 GAP_SIZE
+= old_gap_size
;
435 GPT_BYTE
= real_gap_loc_byte
;
444 /* Make the gap NBYTES_REMOVED bytes shorter. */
447 make_gap_smaller (EMACS_INT nbytes_removed
)
450 EMACS_INT real_gap_loc
;
451 EMACS_INT real_gap_loc_byte
;
453 EMACS_INT real_Z_byte
;
454 EMACS_INT real_beg_unchanged
;
455 EMACS_INT new_gap_size
;
457 /* Make sure the gap is at least 20 bytes. */
458 if (GAP_SIZE
- nbytes_removed
< 20)
459 nbytes_removed
= GAP_SIZE
- 20;
461 /* Prevent quitting in move_gap. */
466 real_gap_loc_byte
= GPT_BYTE
;
467 new_gap_size
= GAP_SIZE
- nbytes_removed
;
469 real_Z_byte
= Z_BYTE
;
470 real_beg_unchanged
= BEG_UNCHANGED
;
472 /* Pretend that the last unwanted part of the gap is the entire gap,
473 and that the first desired part of the gap is part of the buffer
475 memset (GPT_ADDR
, 0, new_gap_size
);
477 GPT_BYTE
+= new_gap_size
;
479 Z_BYTE
+= new_gap_size
;
480 GAP_SIZE
= nbytes_removed
;
482 /* Move the unwanted pretend gap to the end of the buffer. This
483 adjusts the markers properly too. */
484 gap_right (Z
, Z_BYTE
);
486 enlarge_buffer_text (current_buffer
, -nbytes_removed
);
488 /* Now restore the desired gap. */
489 GAP_SIZE
= new_gap_size
;
491 GPT_BYTE
= real_gap_loc_byte
;
493 Z_BYTE
= real_Z_byte
;
494 BEG_UNCHANGED
= real_beg_unchanged
;
503 make_gap (EMACS_INT nbytes_added
)
505 if (nbytes_added
>= 0)
506 make_gap_larger (nbytes_added
);
507 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
509 make_gap_smaller (-nbytes_added
);
513 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
514 FROM_MULTIBYTE says whether the incoming text is multibyte.
515 TO_MULTIBYTE says whether to store the text as multibyte.
516 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
518 Return the number of bytes stored at TO_ADDR. */
521 copy_text (const unsigned char *from_addr
, unsigned char *to_addr
,
522 EMACS_INT nbytes
, int from_multibyte
, int to_multibyte
)
524 if (from_multibyte
== to_multibyte
)
526 memcpy (to_addr
, from_addr
, nbytes
);
529 else if (from_multibyte
)
531 EMACS_INT nchars
= 0;
532 EMACS_INT bytes_left
= nbytes
;
534 while (bytes_left
> 0)
537 c
= STRING_CHAR_AND_LENGTH (from_addr
, thislen
);
538 if (! ASCII_CHAR_P (c
))
541 from_addr
+= thislen
;
542 bytes_left
-= thislen
;
549 unsigned char *initial_to_addr
= to_addr
;
551 /* Convert single-byte to multibyte. */
554 int c
= *from_addr
++;
556 if (!ASCII_CHAR_P (c
))
558 c
= BYTE8_TO_CHAR (c
);
559 to_addr
+= CHAR_STRING (c
, to_addr
);
563 /* Special case for speed. */
564 *to_addr
++ = c
, nbytes
--;
566 return to_addr
- initial_to_addr
;
570 /* Return the number of bytes it would take
571 to convert some single-byte text to multibyte.
572 The single-byte text consists of NBYTES bytes at PTR. */
575 count_size_as_multibyte (const unsigned char *ptr
, EMACS_INT nbytes
)
578 EMACS_INT outgoing_nbytes
= 0;
580 for (i
= 0; i
< nbytes
; i
++)
582 unsigned int c
= *ptr
++;
584 if (ASCII_CHAR_P (c
))
588 c
= BYTE8_TO_CHAR (c
);
589 outgoing_nbytes
+= CHAR_BYTES (c
);
593 return outgoing_nbytes
;
596 /* Insert a string of specified length before point.
597 This function judges multibyteness based on
598 enable_multibyte_characters in the current buffer;
599 it never converts between single-byte and multibyte.
601 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
602 prepare_to_modify_buffer could relocate the text. */
605 insert (const char *string
, EMACS_INT nbytes
)
609 EMACS_INT len
= chars_in_text ((unsigned char *) string
, nbytes
), opoint
;
610 insert_1_both (string
, len
, nbytes
, 0, 1, 0);
612 signal_after_change (opoint
, 0, len
);
613 update_compositions (opoint
, PT
, CHECK_BORDER
);
617 /* Likewise, but inherit text properties from neighboring characters. */
620 insert_and_inherit (const char *string
, EMACS_INT nbytes
)
624 EMACS_INT len
= chars_in_text ((unsigned char *) string
, nbytes
), opoint
;
625 insert_1_both (string
, len
, nbytes
, 1, 1, 0);
627 signal_after_change (opoint
, 0, len
);
628 update_compositions (opoint
, PT
, CHECK_BORDER
);
632 /* Insert the character C before point. Do not inherit text properties. */
637 unsigned char str
[MAX_MULTIBYTE_LENGTH
];
640 if (! NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
641 len
= CHAR_STRING (c
, str
);
648 insert ((char *) str
, len
);
651 /* Insert the null-terminated string S before point. */
654 insert_string (const char *s
)
656 insert (s
, strlen (s
));
659 /* Like `insert' except that all markers pointing at the place where
660 the insertion happens are adjusted to point after it.
661 Don't use this function to insert part of a Lisp string,
662 since gc could happen and relocate it. */
665 insert_before_markers (const char *string
, EMACS_INT nbytes
)
669 EMACS_INT len
= chars_in_text ((unsigned char *) string
, nbytes
), opoint
;
670 insert_1_both (string
, len
, nbytes
, 0, 1, 1);
672 signal_after_change (opoint
, 0, len
);
673 update_compositions (opoint
, PT
, CHECK_BORDER
);
677 /* Likewise, but inherit text properties from neighboring characters. */
680 insert_before_markers_and_inherit (const char *string
,
685 EMACS_INT len
= chars_in_text ((unsigned char *) string
, nbytes
), opoint
;
686 insert_1_both (string
, len
, nbytes
, 1, 1, 1);
688 signal_after_change (opoint
, 0, len
);
689 update_compositions (opoint
, PT
, CHECK_BORDER
);
693 /* Subroutine used by the insert functions above. */
696 insert_1 (const char *string
, EMACS_INT nbytes
,
697 int inherit
, int prepare
, int before_markers
)
699 insert_1_both (string
, chars_in_text ((unsigned char *) string
, nbytes
),
700 nbytes
, inherit
, prepare
, before_markers
);
704 #ifdef BYTE_COMBINING_DEBUG
706 /* See if the bytes before POS/POS_BYTE combine with bytes
707 at the start of STRING to form a single character.
708 If so, return the number of bytes at the start of STRING
709 which combine in this way. Otherwise, return 0. */
712 count_combining_before (const unsigned char *string
, EMACS_INT length
,
713 EMACS_INT pos
, EMACS_INT pos_byte
)
715 int len
, combining_bytes
;
716 const unsigned char *p
;
718 if (NILP (current_buffer
->enable_multibyte_characters
))
721 /* At first, we can exclude the following cases:
722 (1) STRING[0] can't be a following byte of multibyte sequence.
723 (2) POS is the start of the current buffer.
724 (3) A character before POS is not a multibyte character. */
725 if (length
== 0 || CHAR_HEAD_P (*string
)) /* case (1) */
727 if (pos_byte
== BEG_BYTE
) /* case (2) */
730 p
= BYTE_POS_ADDR (pos_byte
- 1);
731 while (! CHAR_HEAD_P (*p
)) p
--, len
++;
732 if (! LEADING_CODE_P (*p
)) /* case (3) */
735 combining_bytes
= BYTES_BY_CHAR_HEAD (*p
) - len
;
736 if (combining_bytes
<= 0)
737 /* The character preceding POS is, complete and no room for
738 combining bytes (combining_bytes == 0), or an independent 8-bit
739 character (combining_bytes < 0). */
742 /* We have a combination situation. Count the bytes at STRING that
745 while (!CHAR_HEAD_P (*p
) && p
< string
+ length
)
748 return (combining_bytes
< p
- string
? combining_bytes
: p
- string
);
751 /* See if the bytes after POS/POS_BYTE combine with bytes
752 at the end of STRING to form a single character.
753 If so, return the number of bytes after POS/POS_BYTE
754 which combine in this way. Otherwise, return 0. */
757 count_combining_after (const unsigned char *string
,
758 EMACS_INT length
, EMACS_INT pos
, EMACS_INT pos_byte
)
760 EMACS_INT opos_byte
= pos_byte
;
765 if (NILP (current_buffer
->enable_multibyte_characters
))
768 /* At first, we can exclude the following cases:
769 (1) The last byte of STRING is an ASCII.
770 (2) POS is the last of the current buffer.
771 (3) A character at POS can't be a following byte of multibyte
773 if (length
> 0 && ASCII_BYTE_P (string
[length
- 1])) /* case (1) */
775 if (pos_byte
== Z_BYTE
) /* case (2) */
777 bufp
= BYTE_POS_ADDR (pos_byte
);
778 if (CHAR_HEAD_P (*bufp
)) /* case (3) */
782 while (i
>= 0 && ! CHAR_HEAD_P (string
[i
]))
788 /* All characters in STRING are not character head. We must
789 check also preceding bytes at POS. We are sure that the gap
791 unsigned char *p
= BEG_ADDR
;
793 while (i
>= 0 && ! CHAR_HEAD_P (p
[i
]))
795 if (i
< 0 || !LEADING_CODE_P (p
[i
]))
798 bytes
= BYTES_BY_CHAR_HEAD (p
[i
]);
799 return (bytes
<= pos_byte
- 1 - i
+ length
801 : bytes
- (pos_byte
- 1 - i
+ length
));
803 if (!LEADING_CODE_P (string
[i
]))
806 bytes
= BYTES_BY_CHAR_HEAD (string
[i
]) - (length
- i
);
808 while (!CHAR_HEAD_P (*bufp
)) bufp
++, pos_byte
++;
810 return (bytes
<= pos_byte
- opos_byte
? bytes
: pos_byte
- opos_byte
);
816 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
817 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
818 are the same as in insert_1. */
821 insert_1_both (const char *string
,
822 EMACS_INT nchars
, EMACS_INT nbytes
,
823 int inherit
, int prepare
, int before_markers
)
828 if (NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
832 /* Do this before moving and increasing the gap,
833 because the before-change hooks might move the gap
834 or make it smaller. */
835 prepare_to_modify_buffer (PT
, PT
, NULL
);
838 move_gap_both (PT
, PT_BYTE
);
839 if (GAP_SIZE
< nbytes
)
840 make_gap (nbytes
- GAP_SIZE
);
842 #ifdef BYTE_COMBINING_DEBUG
843 if (count_combining_before (string
, nbytes
, PT
, PT_BYTE
)
844 || count_combining_after (string
, nbytes
, PT
, PT_BYTE
))
848 /* Record deletion of the surrounding text that combines with
849 the insertion. This, together with recording the insertion,
850 will add up to the right stuff in the undo list. */
851 record_insert (PT
, nchars
);
853 CHARS_MODIFF
= MODIFF
;
855 memcpy (GPT_ADDR
, string
, nbytes
);
864 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
869 /* The insert may have been in the unchanged region, so check again. */
870 if (Z
- GPT
< END_UNCHANGED
)
871 END_UNCHANGED
= Z
- GPT
;
873 adjust_overlays_for_insert (PT
, nchars
);
874 adjust_markers_for_insert (PT
, PT_BYTE
,
875 PT
+ nchars
, PT_BYTE
+ nbytes
,
878 if (BUF_INTERVALS (current_buffer
) != 0)
879 offset_intervals (current_buffer
, PT
, nchars
);
881 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
882 set_text_properties (make_number (PT
), make_number (PT
+ nchars
),
885 adjust_point (nchars
, nbytes
);
890 /* Insert the part of the text of STRING, a Lisp object assumed to be
891 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
892 starting at position POS / POS_BYTE. If the text of STRING has properties,
893 copy them into the buffer.
895 It does not work to use `insert' for this, because a GC could happen
896 before we copy the stuff into the buffer, and relocate the string
897 without insert noticing. */
900 insert_from_string (Lisp_Object string
, EMACS_INT pos
, EMACS_INT pos_byte
,
901 EMACS_INT length
, EMACS_INT length_byte
, int inherit
)
903 EMACS_INT opoint
= PT
;
905 if (SCHARS (string
) == 0)
908 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
910 signal_after_change (opoint
, 0, PT
- opoint
);
911 update_compositions (opoint
, PT
, CHECK_BORDER
);
914 /* Like `insert_from_string' except that all markers pointing
915 at the place where the insertion happens are adjusted to point after it. */
918 insert_from_string_before_markers (Lisp_Object string
,
919 EMACS_INT pos
, EMACS_INT pos_byte
,
920 EMACS_INT length
, EMACS_INT length_byte
,
923 EMACS_INT opoint
= PT
;
925 if (SCHARS (string
) == 0)
928 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
930 signal_after_change (opoint
, 0, PT
- opoint
);
931 update_compositions (opoint
, PT
, CHECK_BORDER
);
934 /* Subroutine of the insertion functions above. */
937 insert_from_string_1 (Lisp_Object string
, EMACS_INT pos
, EMACS_INT pos_byte
,
938 EMACS_INT nchars
, EMACS_INT nbytes
,
939 int inherit
, int before_markers
)
942 EMACS_INT outgoing_nbytes
= nbytes
;
945 /* Make OUTGOING_NBYTES describe the text
946 as it will be inserted in this buffer. */
948 if (NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
949 outgoing_nbytes
= nchars
;
950 else if (! STRING_MULTIBYTE (string
))
952 = count_size_as_multibyte (SDATA (string
) + pos_byte
,
956 /* Do this before moving and increasing the gap,
957 because the before-change hooks might move the gap
958 or make it smaller. */
959 prepare_to_modify_buffer (PT
, PT
, NULL
);
962 move_gap_both (PT
, PT_BYTE
);
963 if (GAP_SIZE
< outgoing_nbytes
)
964 make_gap (outgoing_nbytes
- GAP_SIZE
);
967 /* Copy the string text into the buffer, perhaps converting
968 between single-byte and multibyte. */
969 copy_text (SDATA (string
) + pos_byte
, GPT_ADDR
, nbytes
,
970 STRING_MULTIBYTE (string
),
971 ! NILP (BVAR (current_buffer
, enable_multibyte_characters
)));
973 #ifdef BYTE_COMBINING_DEBUG
974 /* We have copied text into the gap, but we have not altered
975 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
976 to these functions and get the same results as we would
977 have got earlier on. Meanwhile, PT_ADDR does point to
978 the text that has been stored by copy_text. */
979 if (count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
)
980 || count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
))
984 record_insert (PT
, nchars
);
986 CHARS_MODIFF
= MODIFF
;
988 GAP_SIZE
-= outgoing_nbytes
;
992 GPT_BYTE
+= outgoing_nbytes
;
993 ZV_BYTE
+= outgoing_nbytes
;
994 Z_BYTE
+= outgoing_nbytes
;
995 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1000 /* The insert may have been in the unchanged region, so check again. */
1001 if (Z
- GPT
< END_UNCHANGED
)
1002 END_UNCHANGED
= Z
- GPT
;
1004 adjust_overlays_for_insert (PT
, nchars
);
1005 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1006 PT_BYTE
+ outgoing_nbytes
,
1009 offset_intervals (current_buffer
, PT
, nchars
);
1011 intervals
= STRING_INTERVALS (string
);
1012 /* Get the intervals for the part of the string we are inserting. */
1013 if (nbytes
< SBYTES (string
))
1014 intervals
= copy_intervals (intervals
, pos
, nchars
);
1016 /* Insert those intervals. */
1017 graft_intervals_into_buffer (intervals
, PT
, nchars
,
1018 current_buffer
, inherit
);
1020 adjust_point (nchars
, outgoing_nbytes
);
1025 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1026 starting at GPT_ADDR. */
1029 insert_from_gap (EMACS_INT nchars
, EMACS_INT nbytes
)
1031 if (NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
1034 record_insert (GPT
, nchars
);
1044 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1049 adjust_overlays_for_insert (GPT
- nchars
, nchars
);
1050 adjust_markers_for_insert (GPT
- nchars
, GPT_BYTE
- nbytes
,
1053 if (BUF_INTERVALS (current_buffer
) != 0)
1055 offset_intervals (current_buffer
, GPT
- nchars
, nchars
);
1056 graft_intervals_into_buffer (NULL_INTERVAL
, GPT
- nchars
, nchars
,
1060 if (GPT
- nchars
< PT
)
1061 adjust_point (nchars
, nbytes
);
1066 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1067 current buffer. If the text in BUF has properties, they are absorbed
1068 into the current buffer.
1070 It does not work to use `insert' for this, because a malloc could happen
1071 and relocate BUF's text before the copy happens. */
1074 insert_from_buffer (struct buffer
*buf
,
1075 EMACS_INT charpos
, EMACS_INT nchars
, int inherit
)
1077 EMACS_INT opoint
= PT
;
1079 insert_from_buffer_1 (buf
, charpos
, nchars
, inherit
);
1080 signal_after_change (opoint
, 0, PT
- opoint
);
1081 update_compositions (opoint
, PT
, CHECK_BORDER
);
1085 insert_from_buffer_1 (struct buffer
*buf
,
1086 EMACS_INT from
, EMACS_INT nchars
, int inherit
)
1088 register Lisp_Object temp
;
1089 EMACS_INT chunk
, chunk_expanded
;
1090 EMACS_INT from_byte
= buf_charpos_to_bytepos (buf
, from
);
1091 EMACS_INT to_byte
= buf_charpos_to_bytepos (buf
, from
+ nchars
);
1092 EMACS_INT incoming_nbytes
= to_byte
- from_byte
;
1093 EMACS_INT outgoing_nbytes
= incoming_nbytes
;
1096 /* Make OUTGOING_NBYTES describe the text
1097 as it will be inserted in this buffer. */
1099 if (NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
1100 outgoing_nbytes
= nchars
;
1101 else if (NILP (BVAR (buf
, enable_multibyte_characters
)))
1103 EMACS_INT outgoing_before_gap
= 0;
1104 EMACS_INT outgoing_after_gap
= 0;
1106 if (from
< BUF_GPT (buf
))
1108 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1109 if (chunk
> incoming_nbytes
)
1110 chunk
= incoming_nbytes
;
1112 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
, from_byte
),
1118 if (chunk
< incoming_nbytes
)
1120 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
,
1122 incoming_nbytes
- chunk
);
1124 outgoing_nbytes
= outgoing_before_gap
+ outgoing_after_gap
;
1127 /* Make sure point-max won't overflow after this insertion. */
1128 XSETINT (temp
, outgoing_nbytes
+ Z
);
1129 if (outgoing_nbytes
+ Z
!= XINT (temp
))
1130 error ("Maximum buffer size exceeded");
1132 /* Do this before moving and increasing the gap,
1133 because the before-change hooks might move the gap
1134 or make it smaller. */
1135 prepare_to_modify_buffer (PT
, PT
, NULL
);
1138 move_gap_both (PT
, PT_BYTE
);
1139 if (GAP_SIZE
< outgoing_nbytes
)
1140 make_gap (outgoing_nbytes
- GAP_SIZE
);
1142 if (from
< BUF_GPT (buf
))
1144 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1145 if (chunk
> incoming_nbytes
)
1146 chunk
= incoming_nbytes
;
1147 /* Record number of output bytes, so we know where
1148 to put the output from the second copy_text. */
1150 = copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
),
1152 ! NILP (BVAR (buf
, enable_multibyte_characters
)),
1153 ! NILP (BVAR (current_buffer
, enable_multibyte_characters
)));
1156 chunk_expanded
= chunk
= 0;
1158 if (chunk
< incoming_nbytes
)
1159 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
+ chunk
),
1160 GPT_ADDR
+ chunk_expanded
, incoming_nbytes
- chunk
,
1161 ! NILP (BVAR (buf
, enable_multibyte_characters
)),
1162 ! NILP (BVAR (current_buffer
, enable_multibyte_characters
)));
1164 #ifdef BYTE_COMBINING_DEBUG
1165 /* We have copied text into the gap, but we have not altered
1166 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1167 to these functions and get the same results as we would
1168 have got earlier on. Meanwhile, GPT_ADDR does point to
1169 the text that has been stored by copy_text. */
1170 if (count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
)
1171 || count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
))
1175 record_insert (PT
, nchars
);
1177 CHARS_MODIFF
= MODIFF
;
1179 GAP_SIZE
-= outgoing_nbytes
;
1183 GPT_BYTE
+= outgoing_nbytes
;
1184 ZV_BYTE
+= outgoing_nbytes
;
1185 Z_BYTE
+= outgoing_nbytes
;
1186 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1191 /* The insert may have been in the unchanged region, so check again. */
1192 if (Z
- GPT
< END_UNCHANGED
)
1193 END_UNCHANGED
= Z
- GPT
;
1195 adjust_overlays_for_insert (PT
, nchars
);
1196 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1197 PT_BYTE
+ outgoing_nbytes
,
1200 if (BUF_INTERVALS (current_buffer
) != 0)
1201 offset_intervals (current_buffer
, PT
, nchars
);
1203 /* Get the intervals for the part of the string we are inserting. */
1204 intervals
= BUF_INTERVALS (buf
);
1205 if (nchars
< BUF_Z (buf
) - BUF_BEG (buf
))
1207 if (buf
== current_buffer
&& PT
<= from
)
1209 intervals
= copy_intervals (intervals
, from
, nchars
);
1212 /* Insert those intervals. */
1213 graft_intervals_into_buffer (intervals
, PT
, nchars
, current_buffer
, inherit
);
1215 adjust_point (nchars
, outgoing_nbytes
);
1218 /* Record undo information and adjust markers and position keepers for
1219 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1220 chars (LEN_BYTE bytes) which resides in the gap just after
1223 PREV_TEXT nil means the new text was just inserted. */
1226 adjust_after_replace (EMACS_INT from
, EMACS_INT from_byte
,
1227 Lisp_Object prev_text
, EMACS_INT len
, EMACS_INT len_byte
)
1229 EMACS_INT nchars_del
= 0, nbytes_del
= 0;
1231 #ifdef BYTE_COMBINING_DEBUG
1232 if (count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
)
1233 || count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
))
1237 if (STRINGP (prev_text
))
1239 nchars_del
= SCHARS (prev_text
);
1240 nbytes_del
= SBYTES (prev_text
);
1243 /* Update various buffer positions for the new text. */
1244 GAP_SIZE
-= len_byte
;
1246 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1247 GPT
+= len
; GPT_BYTE
+= len_byte
;
1248 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1251 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1254 adjust_markers_for_insert (from
, from_byte
,
1255 from
+ len
, from_byte
+ len_byte
, 0);
1257 if (! EQ (BVAR (current_buffer
, undo_list
), Qt
))
1260 record_delete (from
, prev_text
);
1261 record_insert (from
, len
);
1264 if (len
> nchars_del
)
1265 adjust_overlays_for_insert (from
, len
- nchars_del
);
1266 else if (len
< nchars_del
)
1267 adjust_overlays_for_delete (from
, nchars_del
- len
);
1268 if (BUF_INTERVALS (current_buffer
) != 0)
1270 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1274 adjust_point (len
- nchars_del
, len_byte
- nbytes_del
);
1276 /* As byte combining will decrease Z, we must check this again. */
1277 if (Z
- GPT
< END_UNCHANGED
)
1278 END_UNCHANGED
= Z
- GPT
;
1283 evaporate_overlays (from
);
1285 CHARS_MODIFF
= MODIFF
;
1288 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
1289 This is for use when undo is not enabled in the current buffer. */
1292 adjust_after_replace_noundo (EMACS_INT from
, EMACS_INT from_byte
,
1293 EMACS_INT nchars_del
, EMACS_INT nbytes_del
,
1294 EMACS_INT len
, EMACS_INT len_byte
)
1296 #ifdef BYTE_COMBINING_DEBUG
1297 if (count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
)
1298 || count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
))
1302 /* Update various buffer positions for the new text. */
1303 GAP_SIZE
-= len_byte
;
1305 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1306 GPT
+= len
; GPT_BYTE
+= len_byte
;
1307 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1310 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1313 adjust_markers_for_insert (from
, from_byte
,
1314 from
+ len
, from_byte
+ len_byte
, 0);
1316 if (len
> nchars_del
)
1317 adjust_overlays_for_insert (from
, len
- nchars_del
);
1318 else if (len
< nchars_del
)
1319 adjust_overlays_for_delete (from
, nchars_del
- len
);
1320 if (BUF_INTERVALS (current_buffer
) != 0)
1322 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1326 adjust_point (len
- nchars_del
, len_byte
- nbytes_del
);
1328 /* As byte combining will decrease Z, we must check this again. */
1329 if (Z
- GPT
< END_UNCHANGED
)
1330 END_UNCHANGED
= Z
- GPT
;
1335 evaporate_overlays (from
);
1337 CHARS_MODIFF
= MODIFF
;
1340 /* Record undo information, adjust markers and position keepers for an
1341 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1342 text already exists in the current buffer but character length (TO
1343 - FROM) may be incorrect, the correct length is NEWLEN. */
1346 adjust_after_insert (EMACS_INT from
, EMACS_INT from_byte
,
1347 EMACS_INT to
, EMACS_INT to_byte
, EMACS_INT newlen
)
1349 EMACS_INT len
= to
- from
, len_byte
= to_byte
- from_byte
;
1352 move_gap_both (to
, to_byte
);
1353 GAP_SIZE
+= len_byte
;
1354 GPT
-= len
; GPT_BYTE
-= len_byte
;
1355 ZV
-= len
; ZV_BYTE
-= len_byte
;
1356 Z
-= len
; Z_BYTE
-= len_byte
;
1357 adjust_after_replace (from
, from_byte
, Qnil
, newlen
, len_byte
);
1360 /* Replace the text from character positions FROM to TO with NEW,
1361 If PREPARE is nonzero, call prepare_to_modify_buffer.
1362 If INHERIT, the newly inserted text should inherit text properties
1363 from the surrounding non-deleted text. */
1365 /* Note that this does not yet handle markers quite right.
1366 Also it needs to record a single undo-entry that does a replacement
1367 rather than a separate delete and insert.
1368 That way, undo will also handle markers properly.
1370 But if MARKERS is 0, don't relocate markers. */
1373 replace_range (EMACS_INT from
, EMACS_INT to
, Lisp_Object
new,
1374 int prepare
, int inherit
, int markers
)
1376 EMACS_INT inschars
= SCHARS (new);
1377 EMACS_INT insbytes
= SBYTES (new);
1378 EMACS_INT from_byte
, to_byte
;
1379 EMACS_INT nbytes_del
, nchars_del
;
1380 register Lisp_Object temp
;
1381 struct gcpro gcpro1
;
1383 EMACS_INT outgoing_insbytes
= insbytes
;
1384 Lisp_Object deletion
;
1393 EMACS_INT range_length
= to
- from
;
1394 prepare_to_modify_buffer (from
, to
, &from
);
1395 to
= from
+ range_length
;
1400 /* Make args be valid */
1406 from_byte
= CHAR_TO_BYTE (from
);
1407 to_byte
= CHAR_TO_BYTE (to
);
1409 nchars_del
= to
- from
;
1410 nbytes_del
= to_byte
- from_byte
;
1412 if (nbytes_del
<= 0 && insbytes
== 0)
1415 /* Make OUTGOING_INSBYTES describe the text
1416 as it will be inserted in this buffer. */
1418 if (NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
1419 outgoing_insbytes
= inschars
;
1420 else if (! STRING_MULTIBYTE (new))
1422 = count_size_as_multibyte (SDATA (new), insbytes
);
1424 /* Make sure point-max won't overflow after this insertion. */
1425 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1426 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1427 error ("Maximum buffer size exceeded");
1431 /* Make sure the gap is somewhere in or next to what we are deleting. */
1433 gap_right (from
, from_byte
);
1435 gap_left (to
, to_byte
, 0);
1437 /* Even if we don't record for undo, we must keep the original text
1438 because we may have to recover it because of inappropriate byte
1440 if (! EQ (BVAR (current_buffer
, undo_list
), Qt
))
1441 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1443 GAP_SIZE
+= nbytes_del
;
1446 ZV_BYTE
-= nbytes_del
;
1447 Z_BYTE
-= nbytes_del
;
1449 GPT_BYTE
= from_byte
;
1450 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1455 if (GPT
- BEG
< BEG_UNCHANGED
)
1456 BEG_UNCHANGED
= GPT
- BEG
;
1457 if (Z
- GPT
< END_UNCHANGED
)
1458 END_UNCHANGED
= Z
- GPT
;
1460 if (GAP_SIZE
< insbytes
)
1461 make_gap (insbytes
- GAP_SIZE
);
1463 /* Copy the string text into the buffer, perhaps converting
1464 between single-byte and multibyte. */
1465 copy_text (SDATA (new), GPT_ADDR
, insbytes
,
1466 STRING_MULTIBYTE (new),
1467 ! NILP (BVAR (current_buffer
, enable_multibyte_characters
)));
1469 #ifdef BYTE_COMBINING_DEBUG
1470 /* We have copied text into the gap, but we have not marked
1471 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1472 here, for both the previous text and the following text.
1473 Meanwhile, GPT_ADDR does point to
1474 the text that has been stored by copy_text. */
1475 if (count_combining_before (GPT_ADDR
, outgoing_insbytes
, from
, from_byte
)
1476 || count_combining_after (GPT_ADDR
, outgoing_insbytes
, from
, from_byte
))
1480 if (! EQ (BVAR (current_buffer
, undo_list
), Qt
))
1482 /* Record the insertion first, so that when we undo,
1483 the deletion will be undone first. Thus, undo
1484 will insert before deleting, and thus will keep
1485 the markers before and after this text separate. */
1486 record_insert (from
+ SCHARS (deletion
), inschars
);
1487 record_delete (from
, deletion
);
1490 GAP_SIZE
-= outgoing_insbytes
;
1494 GPT_BYTE
+= outgoing_insbytes
;
1495 ZV_BYTE
+= outgoing_insbytes
;
1496 Z_BYTE
+= outgoing_insbytes
;
1497 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1502 /* Adjust the overlay center as needed. This must be done after
1503 adjusting the markers that bound the overlays. */
1504 adjust_overlays_for_delete (from
, nchars_del
);
1505 adjust_overlays_for_insert (from
, inschars
);
1507 /* Adjust markers for the deletion and the insertion. */
1509 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1510 inschars
, outgoing_insbytes
);
1512 offset_intervals (current_buffer
, from
, inschars
- nchars_del
);
1514 /* Get the intervals for the part of the string we are inserting--
1515 not including the combined-before bytes. */
1516 intervals
= STRING_INTERVALS (new);
1517 /* Insert those intervals. */
1518 graft_intervals_into_buffer (intervals
, from
, inschars
,
1519 current_buffer
, inherit
);
1521 /* Relocate point as if it were a marker. */
1523 adjust_point ((from
+ inschars
- (PT
< to
? PT
: to
)),
1524 (from_byte
+ outgoing_insbytes
1525 - (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
)));
1527 if (outgoing_insbytes
== 0)
1528 evaporate_overlays (from
);
1533 CHARS_MODIFF
= MODIFF
;
1536 signal_after_change (from
, nchars_del
, GPT
- from
);
1537 update_compositions (from
, GPT
, CHECK_BORDER
);
1540 /* Replace the text from character positions FROM to TO with
1541 the text in INS of length INSCHARS.
1542 Keep the text properties that applied to the old characters
1543 (extending them to all the new chars if there are more new chars).
1545 Note that this does not yet handle markers quite right.
1547 If MARKERS is nonzero, relocate markers.
1549 Unlike most functions at this level, never call
1550 prepare_to_modify_buffer and never call signal_after_change. */
1553 replace_range_2 (EMACS_INT from
, EMACS_INT from_byte
,
1554 EMACS_INT to
, EMACS_INT to_byte
,
1555 const char *ins
, EMACS_INT inschars
, EMACS_INT insbytes
,
1558 EMACS_INT nbytes_del
, nchars_del
;
1563 nchars_del
= to
- from
;
1564 nbytes_del
= to_byte
- from_byte
;
1566 if (nbytes_del
<= 0 && insbytes
== 0)
1569 /* Make sure point-max won't overflow after this insertion. */
1570 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1571 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1572 error ("Maximum buffer size exceeded");
1574 /* Make sure the gap is somewhere in or next to what we are deleting. */
1576 gap_right (from
, from_byte
);
1578 gap_left (to
, to_byte
, 0);
1580 GAP_SIZE
+= nbytes_del
;
1583 ZV_BYTE
-= nbytes_del
;
1584 Z_BYTE
-= nbytes_del
;
1586 GPT_BYTE
= from_byte
;
1587 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1592 if (GPT
- BEG
< BEG_UNCHANGED
)
1593 BEG_UNCHANGED
= GPT
- BEG
;
1594 if (Z
- GPT
< END_UNCHANGED
)
1595 END_UNCHANGED
= Z
- GPT
;
1597 if (GAP_SIZE
< insbytes
)
1598 make_gap (insbytes
- GAP_SIZE
);
1600 /* Copy the replacement text into the buffer. */
1601 memcpy (GPT_ADDR
, ins
, insbytes
);
1603 #ifdef BYTE_COMBINING_DEBUG
1604 /* We have copied text into the gap, but we have not marked
1605 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1606 here, for both the previous text and the following text.
1607 Meanwhile, GPT_ADDR does point to
1608 the text that has been stored by copy_text. */
1609 if (count_combining_before (GPT_ADDR
, insbytes
, from
, from_byte
)
1610 || count_combining_after (GPT_ADDR
, insbytes
, from
, from_byte
))
1614 GAP_SIZE
-= insbytes
;
1618 GPT_BYTE
+= insbytes
;
1619 ZV_BYTE
+= insbytes
;
1621 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1626 /* Adjust the overlay center as needed. This must be done after
1627 adjusting the markers that bound the overlays. */
1628 if (nchars_del
!= inschars
)
1630 adjust_overlays_for_insert (from
, inschars
);
1631 adjust_overlays_for_delete (from
+ inschars
, nchars_del
);
1634 /* Adjust markers for the deletion and the insertion. */
1636 && ! (nchars_del
== 1 && inschars
== 1 && nbytes_del
== insbytes
))
1637 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1638 inschars
, insbytes
);
1640 offset_intervals (current_buffer
, from
, inschars
- nchars_del
);
1642 /* Relocate point as if it were a marker. */
1643 if (from
< PT
&& (nchars_del
!= inschars
|| nbytes_del
!= insbytes
))
1646 /* PT was within the deleted text. Move it to FROM. */
1647 adjust_point (from
- PT
, from_byte
- PT_BYTE
);
1649 adjust_point (inschars
- nchars_del
, insbytes
- nbytes_del
);
1653 evaporate_overlays (from
);
1658 CHARS_MODIFF
= MODIFF
;
1661 /* Delete characters in current buffer
1662 from FROM up to (but not including) TO.
1663 If TO comes before FROM, we delete nothing. */
1666 del_range (EMACS_INT from
, EMACS_INT to
)
1668 del_range_1 (from
, to
, 1, 0);
1671 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1672 RET_STRING says to return the deleted text. */
1675 del_range_1 (EMACS_INT from
, EMACS_INT to
, int prepare
, int ret_string
)
1677 EMACS_INT from_byte
, to_byte
;
1678 Lisp_Object deletion
;
1679 struct gcpro gcpro1
;
1681 /* Make args be valid */
1692 EMACS_INT range_length
= to
- from
;
1693 prepare_to_modify_buffer (from
, to
, &from
);
1694 to
= min (ZV
, from
+ range_length
);
1697 from_byte
= CHAR_TO_BYTE (from
);
1698 to_byte
= CHAR_TO_BYTE (to
);
1700 deletion
= del_range_2 (from
, from_byte
, to
, to_byte
, ret_string
);
1702 signal_after_change (from
, to
- from
, 0);
1703 update_compositions (from
, from
, CHECK_HEAD
);
1708 /* Like del_range_1 but args are byte positions, not char positions. */
1711 del_range_byte (EMACS_INT from_byte
, EMACS_INT to_byte
, int prepare
)
1715 /* Make args be valid */
1716 if (from_byte
< BEGV_BYTE
)
1717 from_byte
= BEGV_BYTE
;
1718 if (to_byte
> ZV_BYTE
)
1721 if (to_byte
<= from_byte
)
1724 from
= BYTE_TO_CHAR (from_byte
);
1725 to
= BYTE_TO_CHAR (to_byte
);
1729 EMACS_INT old_from
= from
, old_to
= Z
- to
;
1730 EMACS_INT range_length
= to
- from
;
1731 prepare_to_modify_buffer (from
, to
, &from
);
1732 to
= from
+ range_length
;
1734 if (old_from
!= from
)
1735 from_byte
= CHAR_TO_BYTE (from
);
1741 else if (old_to
== Z
- to
)
1742 to_byte
= CHAR_TO_BYTE (to
);
1745 del_range_2 (from
, from_byte
, to
, to_byte
, 0);
1746 signal_after_change (from
, to
- from
, 0);
1747 update_compositions (from
, from
, CHECK_HEAD
);
1750 /* Like del_range_1, but positions are specified both as charpos
1754 del_range_both (EMACS_INT from
, EMACS_INT from_byte
,
1755 EMACS_INT to
, EMACS_INT to_byte
, int prepare
)
1757 /* Make args be valid */
1758 if (from_byte
< BEGV_BYTE
)
1759 from_byte
= BEGV_BYTE
;
1760 if (to_byte
> ZV_BYTE
)
1763 if (to_byte
<= from_byte
)
1773 EMACS_INT old_from
= from
, old_to
= Z
- to
;
1774 EMACS_INT range_length
= to
- from
;
1775 prepare_to_modify_buffer (from
, to
, &from
);
1776 to
= from
+ range_length
;
1778 if (old_from
!= from
)
1779 from_byte
= CHAR_TO_BYTE (from
);
1785 else if (old_to
== Z
- to
)
1786 to_byte
= CHAR_TO_BYTE (to
);
1789 del_range_2 (from
, from_byte
, to
, to_byte
, 0);
1790 signal_after_change (from
, to
- from
, 0);
1791 update_compositions (from
, from
, CHECK_HEAD
);
1794 /* Delete a range of text, specified both as character positions
1795 and byte positions. FROM and TO are character positions,
1796 while FROM_BYTE and TO_BYTE are byte positions.
1797 If RET_STRING is true, the deleted area is returned as a string. */
1800 del_range_2 (EMACS_INT from
, EMACS_INT from_byte
,
1801 EMACS_INT to
, EMACS_INT to_byte
, int ret_string
)
1803 register EMACS_INT nbytes_del
, nchars_del
;
1804 Lisp_Object deletion
;
1808 nchars_del
= to
- from
;
1809 nbytes_del
= to_byte
- from_byte
;
1811 /* Make sure the gap is somewhere in or next to what we are deleting. */
1813 gap_right (from
, from_byte
);
1815 gap_left (to
, to_byte
, 0);
1817 #ifdef BYTE_COMBINING_DEBUG
1818 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer
, to_byte
),
1819 Z_BYTE
- to_byte
, from
, from_byte
))
1823 if (ret_string
|| ! EQ (BVAR (current_buffer
, undo_list
), Qt
))
1824 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1828 /* Relocate all markers pointing into the new, larger gap
1829 to point at the end of the text before the gap.
1830 Do this before recording the deletion,
1831 so that undo handles this after reinserting the text. */
1832 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1834 if (! EQ (BVAR (current_buffer
, undo_list
), Qt
))
1835 record_delete (from
, deletion
);
1837 CHARS_MODIFF
= MODIFF
;
1839 /* Relocate point as if it were a marker. */
1841 adjust_point (from
- (PT
< to
? PT
: to
),
1842 from_byte
- (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
));
1844 offset_intervals (current_buffer
, from
, - nchars_del
);
1846 /* Adjust the overlay center as needed. This must be done after
1847 adjusting the markers that bound the overlays. */
1848 adjust_overlays_for_delete (from
, nchars_del
);
1850 GAP_SIZE
+= nbytes_del
;
1851 ZV_BYTE
-= nbytes_del
;
1852 Z_BYTE
-= nbytes_del
;
1856 GPT_BYTE
= from_byte
;
1857 if (GAP_SIZE
> 0 && !current_buffer
->text
->inhibit_shrinking
)
1858 /* Put an anchor, unless called from decode_coding_object which
1859 needs to access the previous gap contents. */
1865 if (GPT
- BEG
< BEG_UNCHANGED
)
1866 BEG_UNCHANGED
= GPT
- BEG
;
1867 if (Z
- GPT
< END_UNCHANGED
)
1868 END_UNCHANGED
= Z
- GPT
;
1872 evaporate_overlays (from
);
1877 /* Call this if you're about to change the region of BUFFER from
1878 character positions START to END. This checks the read-only
1879 properties of the region, calls the necessary modification hooks,
1880 and warns the next redisplay that it should pay attention to that
1883 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1884 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1887 modify_region (struct buffer
*buffer
, EMACS_INT start
, EMACS_INT end
,
1888 int preserve_chars_modiff
)
1890 struct buffer
*old_buffer
= current_buffer
;
1892 if (buffer
!= old_buffer
)
1893 set_buffer_internal (buffer
);
1895 prepare_to_modify_buffer (start
, end
, NULL
);
1897 BUF_COMPUTE_UNCHANGED (buffer
, start
- 1, end
);
1899 if (MODIFF
<= SAVE_MODIFF
)
1900 record_first_change ();
1902 if (! preserve_chars_modiff
)
1903 CHARS_MODIFF
= MODIFF
;
1905 BVAR (buffer
, point_before_scroll
) = Qnil
;
1907 if (buffer
!= old_buffer
)
1908 set_buffer_internal (old_buffer
);
1911 /* Check that it is okay to modify the buffer between START and END,
1912 which are char positions.
1914 Run the before-change-function, if any. If intervals are in use,
1915 verify that the text to be modified is not read-only, and call
1916 any modification properties the text may have.
1918 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1919 by holding its value temporarily in a marker. */
1922 prepare_to_modify_buffer (EMACS_INT start
, EMACS_INT end
,
1923 EMACS_INT
*preserve_ptr
)
1925 struct buffer
*base_buffer
;
1927 if (!NILP (BVAR (current_buffer
, read_only
)))
1928 Fbarf_if_buffer_read_only ();
1930 /* Let redisplay consider other windows than selected_window
1931 if modifying another buffer. */
1932 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
1933 ++windows_or_buffers_changed
;
1935 if (BUF_INTERVALS (current_buffer
) != 0)
1939 Lisp_Object preserve_marker
;
1940 struct gcpro gcpro1
;
1941 preserve_marker
= Fcopy_marker (make_number (*preserve_ptr
), Qnil
);
1942 GCPRO1 (preserve_marker
);
1943 verify_interval_modification (current_buffer
, start
, end
);
1944 *preserve_ptr
= marker_position (preserve_marker
);
1945 unchain_marker (XMARKER (preserve_marker
));
1949 verify_interval_modification (current_buffer
, start
, end
);
1952 /* For indirect buffers, use the base buffer to check clashes. */
1953 if (current_buffer
->base_buffer
!= 0)
1954 base_buffer
= current_buffer
->base_buffer
;
1956 base_buffer
= current_buffer
;
1958 #ifdef CLASH_DETECTION
1959 if (!NILP (BVAR (base_buffer
, file_truename
))
1960 /* Make binding buffer-file-name to nil effective. */
1961 && !NILP (BVAR (base_buffer
, filename
))
1962 && SAVE_MODIFF
>= MODIFF
)
1963 lock_file (BVAR (base_buffer
, file_truename
));
1965 /* At least warn if this file has changed on disk since it was visited. */
1966 if (!NILP (BVAR (base_buffer
, filename
))
1967 && SAVE_MODIFF
>= MODIFF
1968 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1969 && !NILP (Ffile_exists_p (BVAR (base_buffer
, filename
))))
1970 call1 (intern ("ask-user-about-supersession-threat"),
1971 BVAR (base_buffer
,filename
));
1972 #endif /* not CLASH_DETECTION */
1974 /* If `select-active-regions' is non-nil, save the region text. */
1975 if (!NILP (BVAR (current_buffer
, mark_active
))
1976 && !inhibit_modification_hooks
1977 && XMARKER (BVAR (current_buffer
, mark
))->buffer
1978 && NILP (Vsaved_region_selection
)
1979 && (EQ (Vselect_active_regions
, Qonly
)
1980 ? EQ (CAR_SAFE (Vtransient_mark_mode
), Qonly
)
1981 : (!NILP (Vselect_active_regions
)
1982 && !NILP (Vtransient_mark_mode
))))
1984 EMACS_INT b
= XMARKER (BVAR (current_buffer
, mark
))->charpos
;
1987 Vsaved_region_selection
= make_buffer_string (b
, e
, 0);
1989 Vsaved_region_selection
= make_buffer_string (e
, b
, 0);
1992 signal_before_change (start
, end
, preserve_ptr
);
1994 if (current_buffer
->newline_cache
)
1995 invalidate_region_cache (current_buffer
,
1996 current_buffer
->newline_cache
,
1997 start
- BEG
, Z
- end
);
1998 if (current_buffer
->width_run_cache
)
1999 invalidate_region_cache (current_buffer
,
2000 current_buffer
->width_run_cache
,
2001 start
- BEG
, Z
- end
);
2003 Vdeactivate_mark
= Qt
;
2006 /* These macros work with an argument named `preserve_ptr'
2007 and a local variable named `preserve_marker'. */
2009 #define PRESERVE_VALUE \
2010 if (preserve_ptr && NILP (preserve_marker)) \
2011 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2013 #define RESTORE_VALUE \
2014 if (! NILP (preserve_marker)) \
2016 *preserve_ptr = marker_position (preserve_marker); \
2017 unchain_marker (XMARKER (preserve_marker)); \
2020 #define PRESERVE_START_END \
2021 if (NILP (start_marker)) \
2022 start_marker = Fcopy_marker (start, Qnil); \
2023 if (NILP (end_marker)) \
2024 end_marker = Fcopy_marker (end, Qnil);
2026 #define FETCH_START \
2027 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2030 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2032 /* Set a variable to nil if an error occurred.
2033 Don't change the variable if there was no error.
2034 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
2035 VARIABLE is the variable to maybe set to nil.
2036 NO-ERROR-FLAG is nil if there was an error,
2037 anything else meaning no error (so this function does nothing). */
2039 reset_var_on_error (Lisp_Object val
)
2041 if (NILP (XCDR (val
)))
2042 Fset (XCAR (val
), Qnil
);
2046 /* Signal a change to the buffer immediately before it happens.
2047 START_INT and END_INT are the bounds of the text to be changed.
2049 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2050 by holding its value temporarily in a marker. */
2053 signal_before_change (EMACS_INT start_int
, EMACS_INT end_int
,
2054 EMACS_INT
*preserve_ptr
)
2056 Lisp_Object start
, end
;
2057 Lisp_Object start_marker
, end_marker
;
2058 Lisp_Object preserve_marker
;
2059 struct gcpro gcpro1
, gcpro2
, gcpro3
;
2060 int count
= SPECPDL_INDEX ();
2062 if (inhibit_modification_hooks
)
2065 start
= make_number (start_int
);
2066 end
= make_number (end_int
);
2067 preserve_marker
= Qnil
;
2068 start_marker
= Qnil
;
2070 GCPRO3 (preserve_marker
, start_marker
, end_marker
);
2072 specbind (Qinhibit_modification_hooks
, Qt
);
2074 /* If buffer is unmodified, run a special hook for that case. The
2075 check for Vfirst_change_hook is just a minor optimization. */
2076 if (SAVE_MODIFF
>= MODIFF
2077 && !NILP (Vfirst_change_hook
))
2081 Frun_hooks (1, &Qfirst_change_hook
);
2084 /* Now run the before-change-functions if any. */
2085 if (!NILP (Vbefore_change_functions
))
2087 Lisp_Object args
[3];
2088 Lisp_Object rvoe_arg
= Fcons (Qbefore_change_functions
, Qnil
);
2093 /* Mark before-change-functions to be reset to nil in case of error. */
2094 record_unwind_protect (reset_var_on_error
, rvoe_arg
);
2096 /* Actually run the hook functions. */
2097 args
[0] = Qbefore_change_functions
;
2098 args
[1] = FETCH_START
;
2099 args
[2] = FETCH_END
;
2100 Frun_hook_with_args (3, args
);
2102 /* There was no error: unarm the reset_on_error. */
2103 XSETCDR (rvoe_arg
, Qt
);
2106 if (current_buffer
->overlays_before
|| current_buffer
->overlays_after
)
2109 report_overlay_modification (FETCH_START
, FETCH_END
, 0,
2110 FETCH_START
, FETCH_END
, Qnil
);
2113 if (! NILP (start_marker
))
2114 free_marker (start_marker
);
2115 if (! NILP (end_marker
))
2116 free_marker (end_marker
);
2120 unbind_to (count
, Qnil
);
2123 /* Signal a change immediately after it happens.
2124 CHARPOS is the character position of the start of the changed text.
2125 LENDEL is the number of characters of the text before the change.
2126 (Not the whole buffer; just the part that was changed.)
2127 LENINS is the number of characters in that part of the text
2128 after the change. */
2131 signal_after_change (EMACS_INT charpos
, EMACS_INT lendel
, EMACS_INT lenins
)
2133 int count
= SPECPDL_INDEX ();
2134 if (inhibit_modification_hooks
)
2137 /* If we are deferring calls to the after-change functions
2138 and there are no before-change functions,
2139 just record the args that we were going to use. */
2140 if (! NILP (Vcombine_after_change_calls
)
2141 && NILP (Vbefore_change_functions
)
2142 && !current_buffer
->overlays_before
2143 && !current_buffer
->overlays_after
)
2147 if (!NILP (combine_after_change_list
)
2148 && current_buffer
!= XBUFFER (combine_after_change_buffer
))
2149 Fcombine_after_change_execute ();
2151 elt
= Fcons (make_number (charpos
- BEG
),
2152 Fcons (make_number (Z
- (charpos
- lendel
+ lenins
)),
2153 Fcons (make_number (lenins
- lendel
), Qnil
)));
2154 combine_after_change_list
2155 = Fcons (elt
, combine_after_change_list
);
2156 combine_after_change_buffer
= Fcurrent_buffer ();
2161 if (!NILP (combine_after_change_list
))
2162 Fcombine_after_change_execute ();
2164 specbind (Qinhibit_modification_hooks
, Qt
);
2166 if (!NILP (Vafter_change_functions
))
2168 Lisp_Object args
[4];
2169 Lisp_Object rvoe_arg
= Fcons (Qafter_change_functions
, Qnil
);
2171 /* Mark after-change-functions to be reset to nil in case of error. */
2172 record_unwind_protect (reset_var_on_error
, rvoe_arg
);
2174 /* Actually run the hook functions. */
2175 args
[0] = Qafter_change_functions
;
2176 XSETFASTINT (args
[1], charpos
);
2177 XSETFASTINT (args
[2], charpos
+ lenins
);
2178 XSETFASTINT (args
[3], lendel
);
2179 Frun_hook_with_args (4, args
);
2181 /* There was no error: unarm the reset_on_error. */
2182 XSETCDR (rvoe_arg
, Qt
);
2185 if (current_buffer
->overlays_before
|| current_buffer
->overlays_after
)
2186 report_overlay_modification (make_number (charpos
),
2187 make_number (charpos
+ lenins
),
2189 make_number (charpos
),
2190 make_number (charpos
+ lenins
),
2191 make_number (lendel
));
2193 /* After an insertion, call the text properties
2194 insert-behind-hooks or insert-in-front-hooks. */
2196 report_interval_modification (make_number (charpos
),
2197 make_number (charpos
+ lenins
));
2199 unbind_to (count
, Qnil
);
2203 Fcombine_after_change_execute_1 (Lisp_Object val
)
2205 Vcombine_after_change_calls
= val
;
2209 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute
,
2210 Scombine_after_change_execute
, 0, 0, 0,
2211 doc
: /* This function is for use internally in `combine-after-change-calls'. */)
2214 int count
= SPECPDL_INDEX ();
2215 EMACS_INT beg
, end
, change
;
2216 EMACS_INT begpos
, endpos
;
2219 if (NILP (combine_after_change_list
))
2222 /* It is rare for combine_after_change_buffer to be invalid, but
2223 possible. It can happen when combine-after-change-calls is
2224 non-nil, and insertion calls a file handler (e.g. through
2225 lock_file) which scribbles into a temp file -- cyd */
2226 if (!BUFFERP (combine_after_change_buffer
)
2227 || NILP (BVAR (XBUFFER (combine_after_change_buffer
), name
)))
2229 combine_after_change_list
= Qnil
;
2233 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
2235 Fset_buffer (combine_after_change_buffer
);
2237 /* # chars unchanged at beginning of buffer. */
2239 /* # chars unchanged at end of buffer. */
2241 /* Total amount of insertion (negative for deletion). */
2244 /* Scan the various individual changes,
2245 accumulating the range info in BEG, END and CHANGE. */
2246 for (tail
= combine_after_change_list
; CONSP (tail
);
2250 EMACS_INT thisbeg
, thisend
, thischange
;
2252 /* Extract the info from the next element. */
2256 thisbeg
= XINT (XCAR (elt
));
2261 thisend
= XINT (XCAR (elt
));
2266 thischange
= XINT (XCAR (elt
));
2268 /* Merge this range into the accumulated range. */
2269 change
+= thischange
;
2276 /* Get the current start and end positions of the range
2277 that was changed. */
2281 /* We are about to handle these, so discard them. */
2282 combine_after_change_list
= Qnil
;
2284 /* Now run the after-change functions for real.
2285 Turn off the flag that defers them. */
2286 record_unwind_protect (Fcombine_after_change_execute_1
,
2287 Vcombine_after_change_calls
);
2288 signal_after_change (begpos
, endpos
- begpos
- change
, endpos
- begpos
);
2289 update_compositions (begpos
, endpos
, CHECK_ALL
);
2291 return unbind_to (count
, Qnil
);
2295 syms_of_insdel (void)
2297 staticpro (&combine_after_change_list
);
2298 staticpro (&combine_after_change_buffer
);
2299 combine_after_change_list
= Qnil
;
2300 combine_after_change_buffer
= Qnil
;
2302 DEFVAR_BOOL ("check-markers-debug-flag", check_markers_debug_flag
,
2303 doc
: /* Non-nil means enable debugging checks for invalid marker positions. */);
2304 check_markers_debug_flag
= 0;
2305 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls
,
2306 doc
: /* Used internally by the `combine-after-change-calls' macro. */);
2307 Vcombine_after_change_calls
= Qnil
;
2309 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks
,
2310 doc
: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2311 This affects `before-change-functions' and `after-change-functions',
2312 as well as hooks attached to text properties and overlays. */);
2313 inhibit_modification_hooks
= 0;
2314 Qinhibit_modification_hooks
= intern_c_string ("inhibit-modification-hooks");
2315 staticpro (&Qinhibit_modification_hooks
);
2317 defsubr (&Scombine_after_change_execute
);