1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 86, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 #include "intervals.h"
28 #include "blockinput.h"
29 #include "region-cache.h"
35 #define min(x, y) ((x) < (y) ? (x) : (y))
37 static void insert_from_string_1
P_ ((Lisp_Object
, int, int, int, int, int, int));
38 static void insert_from_buffer_1 ();
39 static void gap_left
P_ ((int, int, int));
40 static void gap_right
P_ ((int, int));
41 static void adjust_markers_gap_motion
P_ ((int, int, int));
42 static void adjust_markers_for_insert
P_ ((int, int, int, int, int, int, int));
43 static void adjust_markers_for_delete
P_ ((int, int, int, int));
44 static void adjust_markers_for_record_delete
P_ ((int, int, int, int));
45 static void adjust_point
P_ ((int, int));
47 Lisp_Object
Fcombine_after_change_execute ();
49 /* Non-nil means don't call the after-change-functions right away,
50 just record an element in Vcombine_after_change_calls_list. */
51 Lisp_Object Vcombine_after_change_calls
;
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 /* Check all markers in the current buffer, looking for something invalid. */
70 static int check_markers_debug_flag
;
72 #define CHECK_MARKERS() \
73 if (check_markers_debug_flag) \
80 register Lisp_Object tail
, prev
, next
;
82 tail
= BUF_MARKERS (current_buffer
);
84 while (XSYMBOL (tail
) != XSYMBOL (Qnil
))
86 if (XMARKER (tail
)->buffer
->text
!= current_buffer
->text
)
88 if (XMARKER (tail
)->charpos
> Z
)
90 if (XMARKER (tail
)->bytepos
> Z_BYTE
)
93 tail
= XMARKER (tail
)->chain
;
97 /* Move gap to position CHARPOS.
98 Note that this can quit! */
104 move_gap_both (charpos
, charpos_to_bytepos (charpos
));
107 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
108 Note that this can quit! */
111 move_gap_both (charpos
, bytepos
)
112 int charpos
, bytepos
;
114 if (bytepos
< GPT_BYTE
)
115 gap_left (charpos
, bytepos
, 0);
116 else if (bytepos
> GPT_BYTE
)
117 gap_right (charpos
, bytepos
);
120 /* Move the gap to a position less than the current GPT.
121 BYTEPOS describes the new position as a byte position,
122 and CHARPOS is the corresponding char position.
123 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
126 gap_left (charpos
, bytepos
, newgap
)
127 register int charpos
, bytepos
;
130 register unsigned char *to
, *from
;
136 if (unchanged_modified
== MODIFF
137 && overlay_unchanged_modified
== OVERLAY_MODIFF
)
139 beg_unchanged
= charpos
- BEG
;
140 end_unchanged
= Z
- charpos
;
144 if (Z
- GPT
< end_unchanged
)
145 end_unchanged
= Z
- GPT
;
146 if (charpos
< beg_unchanged
)
147 beg_unchanged
= charpos
- BEG
;
156 /* Now copy the characters. To move the gap down,
157 copy characters up. */
161 /* I gets number of characters left to copy. */
162 i
= new_s1
- bytepos
;
165 /* If a quit is requested, stop copying now.
166 Change BYTEPOS to be where we have actually moved the gap to. */
170 charpos
= BYTE_TO_CHAR (bytepos
);
173 /* Move at most 32000 chars before checking again for a quit. */
178 /* bcopy is safe if the two areas of memory do not overlap
179 or on systems where bcopy is always safe for moving upward. */
180 && (BCOPY_UPWARD_SAFE
181 || to
- from
>= 128))
183 /* If overlap is not safe, avoid it by not moving too many
184 characters at once. */
185 if (!BCOPY_UPWARD_SAFE
&& i
> to
- from
)
200 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
201 BYTEPOS is where the loop above stopped, which may be what was specified
202 or may be where a quit was detected. */
203 adjust_markers_gap_motion (bytepos
, GPT_BYTE
, GAP_SIZE
);
206 if (bytepos
< charpos
)
208 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
212 /* Move the gap to a position greater than than the current GPT.
213 BYTEPOS describes the new position as a byte position,
214 and CHARPOS is the corresponding char position. */
217 gap_right (charpos
, bytepos
)
218 register int charpos
, bytepos
;
220 register unsigned char *to
, *from
;
224 if (unchanged_modified
== MODIFF
225 && overlay_unchanged_modified
== OVERLAY_MODIFF
)
227 beg_unchanged
= charpos
- BEG
;
228 end_unchanged
= Z
- charpos
;
232 if (Z
- charpos
- 1 < end_unchanged
)
233 end_unchanged
= Z
- charpos
;
234 if (GPT
- BEG
< beg_unchanged
)
235 beg_unchanged
= GPT
- BEG
;
243 /* Now copy the characters. To move the gap up,
244 copy characters down. */
248 /* I gets number of characters left to copy. */
249 i
= bytepos
- new_s1
;
252 /* If a quit is requested, stop copying now.
253 Change BYTEPOS to be where we have actually moved the gap to. */
257 charpos
= BYTE_TO_CHAR (bytepos
);
260 /* Move at most 32000 chars before checking again for a quit. */
265 /* bcopy is safe if the two areas of memory do not overlap
266 or on systems where bcopy is always safe for moving downward. */
267 && (BCOPY_DOWNWARD_SAFE
268 || from
- to
>= 128))
270 /* If overlap is not safe, avoid it by not moving too many
271 characters at once. */
272 if (!BCOPY_DOWNWARD_SAFE
&& i
> from
- to
)
287 adjust_markers_gap_motion (GPT_BYTE
+ GAP_SIZE
, bytepos
+ GAP_SIZE
,
291 if (bytepos
< charpos
)
293 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
297 /* Add AMOUNT to the byte position of every marker in the current buffer
298 whose current byte position is between FROM (exclusive) and TO (inclusive).
300 Also, any markers past the outside of that interval, in the direction
301 of adjustment, are first moved back to the near end of the interval
302 and then adjusted by AMOUNT.
304 When the latter adjustment is done, if AMOUNT is negative,
305 we record the adjustment for undo. (This case happens only for
308 The markers' character positions are not altered,
309 because gap motion does not affect character positions. */
311 int adjust_markers_test
;
314 adjust_markers_gap_motion (from
, to
, amount
)
315 register int from
, to
, amount
;
317 /* Now that a marker has a bytepos, not counting the gap,
318 nothing needs to be done here. */
321 register struct Lisp_Marker
*m
;
324 marker
= BUF_MARKERS (current_buffer
);
326 while (!NILP (marker
))
328 m
= XMARKER (marker
);
332 if (mpos
> to
&& mpos
< to
+ amount
)
334 if (adjust_markers_test
)
341 /* Here's the case where a marker is inside text being deleted.
342 AMOUNT can be negative for gap motion, too,
343 but then this range contains no markers. */
344 if (mpos
> from
+ amount
&& mpos
<= from
)
346 if (adjust_markers_test
)
348 mpos
= from
+ amount
;
351 if (mpos
> from
&& mpos
<= to
)
359 /* Adjust all markers for a deletion
360 whose range in bytes is FROM_BYTE to TO_BYTE.
361 The range in charpos is FROM to TO.
363 This function assumes that the gap is adjacent to
364 or inside of the range being deleted. */
367 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
)
368 register int from
, from_byte
, to
, to_byte
;
371 register struct Lisp_Marker
*m
;
372 register int charpos
;
374 marker
= BUF_MARKERS (current_buffer
);
376 while (!NILP (marker
))
378 m
= XMARKER (marker
);
379 charpos
= m
->charpos
;
384 /* If the marker is after the deletion,
385 relocate by number of chars / bytes deleted. */
388 m
->charpos
-= to
- from
;
389 m
->bytepos
-= to_byte
- from_byte
;
392 /* Here's the case where a marker is inside text being deleted. */
393 else if (charpos
> from
)
395 record_marker_adjustment (marker
, from
- charpos
);
397 m
->bytepos
= from_byte
;
404 /* Adjust all markers for calling record_delete for combining bytes.
405 whose range in bytes is FROM_BYTE to TO_BYTE.
406 The range in charpos is FROM to TO. */
409 adjust_markers_for_record_delete (from
, from_byte
, to
, to_byte
)
410 register int from
, from_byte
, to
, to_byte
;
413 register struct Lisp_Marker
*m
;
414 register int charpos
;
416 marker
= BUF_MARKERS (current_buffer
);
418 while (!NILP (marker
))
420 m
= XMARKER (marker
);
421 charpos
= m
->charpos
;
423 /* If the marker is after the deletion,
424 relocate by number of chars / bytes deleted. */
427 /* Here's the case where a marker is inside text being deleted. */
428 else if (charpos
> from
)
429 record_marker_adjustment (marker
, from
- charpos
);
435 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
436 to TO / TO_BYTE. We have to relocate the charpos of every marker
437 that points after the insertion (but not their bytepos).
439 COMBINED_BEFORE_BYTES is the number of bytes at the start of the insertion
440 that combine into one character with the text before the insertion.
441 COMBINED_AFTER_BYTES is the number of bytes after the insertion
442 that combine into one character with the last inserted bytes.
444 When a marker points at the insertion point,
445 we advance it if either its insertion-type is t
446 or BEFORE_MARKERS is true. */
449 adjust_markers_for_insert (from
, from_byte
, to
, to_byte
,
450 combined_before_bytes
, combined_after_bytes
,
452 register int from
, from_byte
, to
, to_byte
;
453 int combined_before_bytes
, combined_after_bytes
, before_markers
;
457 int nchars
= to
- from
;
458 int nbytes
= to_byte
- from_byte
;
460 marker
= BUF_MARKERS (current_buffer
);
462 while (!NILP (marker
))
464 register struct Lisp_Marker
*m
= XMARKER (marker
);
466 /* In a single-byte buffer, a marker's two positions must be equal.
467 (If this insertion is going to combine characters, Z will
468 become different from Z_BYTE, but they might be the same now.
469 If so, the two OLD positions of the marker should be equal.) */
472 if (m
->charpos
!= m
->bytepos
)
476 if (m
->bytepos
== from_byte
)
478 if (m
->insertion_type
|| before_markers
)
480 m
->bytepos
+= nbytes
+ combined_after_bytes
;
481 m
->charpos
+= nchars
+ !!combined_after_bytes
;
482 /* Point the marker before the combined character,
483 so that undoing the insertion puts it back where it was. */
484 if (combined_after_bytes
)
485 DEC_BOTH (m
->charpos
, m
->bytepos
);
486 if (m
->insertion_type
)
489 else if (combined_before_bytes
)
491 /* This marker doesn't "need relocation",
492 but don't leave it pointing in the middle of a character.
493 Point the marker after the combined character,
494 so that undoing the insertion puts it back where it was. */
496 /* Here we depend on the fact that the gap is after
497 all of the combining bytes that we are going to skip over. */
498 DEC_BOTH (m
->charpos
, m
->bytepos
);
499 INC_BOTH (m
->charpos
, m
->bytepos
);
502 /* If a marker was pointing into the combining bytes
503 after the insertion, don't leave it there
504 in the middle of a character. */
505 else if (combined_after_bytes
&& m
->bytepos
>= from_byte
506 && m
->bytepos
< from_byte
+ combined_after_bytes
)
508 /* Put it after the combining bytes. */
509 m
->bytepos
= to_byte
+ combined_after_bytes
;
511 /* Now move it back before the combined character,
512 so that undoing the insertion will put it where it was. */
513 DEC_BOTH (m
->charpos
, m
->bytepos
);
515 else if (m
->bytepos
> from_byte
)
517 m
->bytepos
+= nbytes
;
518 m
->charpos
+= nchars
;
524 /* Adjusting only markers whose insertion-type is t may result in
525 disordered overlays in the slot `overlays_before'. */
527 fix_overlays_before (current_buffer
, from
, to
);
530 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
532 This is used only when the value of point changes due to an insert
533 or delete; it does not represent a conceptual change in point as a
534 marker. In particular, point is not crossing any interval
535 boundaries, so there's no need to use the usual SET_PT macro. In
536 fact it would be incorrect to do so, because either the old or the
537 new value of point is out of sync with the current set of
541 adjust_point (nchars
, nbytes
)
544 BUF_PT (current_buffer
) += nchars
;
545 BUF_PT_BYTE (current_buffer
) += nbytes
;
547 /* In a single-byte buffer, the two positions must be equal. */
553 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
554 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
557 See the comment of adjust_markers_for_insert for the args
558 COMBINED_BEFORE_BYTES and COMBINED_AFTER_BYTES. */
561 adjust_markers_for_replace (from
, from_byte
, old_chars
, old_bytes
,
562 new_chars
, new_bytes
,
563 combined_before_bytes
, combined_after_bytes
)
564 int from
, from_byte
, old_chars
, old_bytes
, new_chars
, new_bytes
;
565 int combined_before_bytes
, combined_after_bytes
;
567 Lisp_Object marker
= BUF_MARKERS (current_buffer
);
568 int prev_to_byte
= from_byte
+ old_bytes
;
569 int diff_chars
= new_chars
- old_chars
;
570 int diff_bytes
= new_bytes
- old_bytes
;
572 while (!NILP (marker
))
574 register struct Lisp_Marker
*m
= XMARKER (marker
);
576 if (m
->bytepos
>= prev_to_byte
)
578 if (m
->bytepos
< prev_to_byte
+ combined_after_bytes
)
580 /* Put it after the combining bytes. */
581 m
->bytepos
= from_byte
+ new_bytes
;
582 m
->charpos
= from
+ new_chars
;
586 m
->charpos
+= diff_chars
;
587 m
->bytepos
+= diff_bytes
;
589 if (m
->charpos
== from
+ new_chars
)
590 record_marker_adjustment (marker
, - old_chars
);
592 else if (m
->bytepos
> from_byte
)
594 record_marker_adjustment (marker
, from
- m
->charpos
);
596 m
->bytepos
= from_byte
;
598 else if (m
->bytepos
== from_byte
)
600 if (combined_before_bytes
)
602 DEC_BOTH (m
->charpos
, m
->bytepos
);
603 INC_BOTH (m
->charpos
, m
->bytepos
);
612 /* Make the gap NBYTES_ADDED bytes longer. */
615 make_gap (nbytes_added
)
618 unsigned char *result
;
621 int real_gap_loc_byte
;
624 /* If we have to get more space, get enough to last a while. */
625 nbytes_added
+= 2000;
627 /* Don't allow a buffer size that won't fit in an int
628 even if it will fit in a Lisp integer.
629 That won't work because so many places use `int'. */
631 if (Z_BYTE
- BEG_BYTE
+ GAP_SIZE
+ nbytes_added
632 >= ((unsigned) 1 << (min (BITS_PER_INT
, VALBITS
) - 1)))
633 error ("Buffer exceeds maximum size");
636 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
637 result
= BUFFER_REALLOC (BEG_ADDR
, (Z_BYTE
- BEG_BYTE
638 + GAP_SIZE
+ nbytes_added
+ 1));
646 /* We can't unblock until the new address is properly stored. */
650 /* Prevent quitting in move_gap. */
655 real_gap_loc_byte
= GPT_BYTE
;
656 old_gap_size
= GAP_SIZE
;
658 /* Call the newly allocated space a gap at the end of the whole space. */
660 GPT_BYTE
= Z_BYTE
+ GAP_SIZE
;
661 GAP_SIZE
= nbytes_added
;
663 /* Move the new gap down to be consecutive with the end of the old one.
664 This adjusts the markers properly too. */
665 gap_left (real_gap_loc
+ old_gap_size
, real_gap_loc_byte
+ old_gap_size
, 1);
667 /* Now combine the two into one large gap. */
668 GAP_SIZE
+= old_gap_size
;
670 GPT_BYTE
= real_gap_loc_byte
;
678 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
679 FROM_MULTIBYTE says whether the incoming text is multibyte.
680 TO_MULTIBYTE says whether to store the text as multibyte.
681 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
683 Return the number of bytes stored at TO_ADDR. */
686 copy_text (from_addr
, to_addr
, nbytes
,
687 from_multibyte
, to_multibyte
)
688 unsigned char *from_addr
;
689 unsigned char *to_addr
;
691 int from_multibyte
, to_multibyte
;
693 if (from_multibyte
== to_multibyte
)
695 bcopy (from_addr
, to_addr
, nbytes
);
698 else if (from_multibyte
)
701 int bytes_left
= nbytes
;
702 Lisp_Object tbl
= Qnil
, temp
;
704 /* We set the variable tbl to the reverse table of
705 Vnonascii_translation_table in advance. */
706 if (CHAR_TABLE_P (Vnonascii_translation_table
))
708 tbl
= Fchar_table_extra_slot (Vnonascii_translation_table
,
710 if (!CHAR_TABLE_P (tbl
))
714 /* Convert multibyte to single byte. */
715 while (bytes_left
> 0)
717 int thislen
, c
, c_save
;
718 c
= c_save
= STRING_CHAR_AND_LENGTH (from_addr
, bytes_left
, thislen
);
719 if (!SINGLE_BYTE_CHAR_P (c
))
723 temp
= Faref (tbl
, make_number (c
));
727 else if (nonascii_insert_offset
> 0)
728 c
-= nonascii_insert_offset
;
729 if (c
< 128 || c
>= 256)
730 c
= (c_save
& 0177) + 0200;
733 from_addr
+= thislen
;
734 bytes_left
-= thislen
;
741 unsigned char *initial_to_addr
= to_addr
;
743 /* Convert single-byte to multibyte. */
746 int c
= *from_addr
++;
747 unsigned char workbuf
[4], *str
;
750 if (c
>= 0240 && c
< 0400)
752 c
= unibyte_char_to_multibyte (c
);
753 len
= CHAR_STRING (c
, workbuf
, str
);
754 bcopy (str
, to_addr
, len
);
759 /* Special case for speed. */
760 *to_addr
++ = c
, nbytes
--;
762 return to_addr
- initial_to_addr
;
766 /* Return the number of bytes it would take
767 to convert some single-byte text to multibyte.
768 The single-byte text consists of NBYTES bytes at PTR. */
771 count_size_as_multibyte (ptr
, nbytes
)
776 int outgoing_nbytes
= 0;
778 for (i
= 0; i
< nbytes
; i
++)
780 unsigned int c
= *ptr
++;
786 c
= unibyte_char_to_multibyte (c
);
787 outgoing_nbytes
+= XINT (Fchar_bytes (make_number (c
)));
791 return outgoing_nbytes
;
794 /* Insert a string of specified length before point.
795 This function judges multibyteness based on
796 enable_multibyte_characters in the current buffer;
797 it never converts between single-byte and multibyte.
799 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
800 prepare_to_modify_buffer could relocate the text. */
803 insert (string
, nbytes
)
804 register unsigned char *string
;
810 insert_1 (string
, nbytes
, 0, 1, 0);
811 signal_after_change (opoint
, 0, PT
- opoint
);
815 /* Likewise, but inherit text properties from neighboring characters. */
818 insert_and_inherit (string
, nbytes
)
819 register unsigned char *string
;
825 insert_1 (string
, nbytes
, 1, 1, 0);
826 signal_after_change (opoint
, 0, PT
- opoint
);
830 /* Insert the character C before point. Do not inherit text properties. */
836 unsigned char workbuf
[4], *str
;
839 if (! NILP (current_buffer
->enable_multibyte_characters
))
840 len
= CHAR_STRING (c
, workbuf
, str
);
851 /* Insert the null-terminated string S before point. */
857 insert (s
, strlen (s
));
860 /* Like `insert' except that all markers pointing at the place where
861 the insertion happens are adjusted to point after it.
862 Don't use this function to insert part of a Lisp string,
863 since gc could happen and relocate it. */
866 insert_before_markers (string
, nbytes
)
867 unsigned char *string
;
874 insert_1 (string
, nbytes
, 0, 1, 1);
875 signal_after_change (opoint
, 0, PT
- opoint
);
879 /* Likewise, but inherit text properties from neighboring characters. */
882 insert_before_markers_and_inherit (string
, nbytes
)
883 unsigned char *string
;
890 insert_1 (string
, nbytes
, 1, 1, 1);
891 signal_after_change (opoint
, 0, PT
- opoint
);
895 /* Subroutine used by the insert functions above. */
898 insert_1 (string
, nbytes
, inherit
, prepare
, before_markers
)
899 register unsigned char *string
;
901 int inherit
, prepare
, before_markers
;
903 insert_1_both (string
, chars_in_text (string
, nbytes
), nbytes
,
904 inherit
, prepare
, before_markers
);
907 /* See if the bytes before POS/POS_BYTE combine with bytes
908 at the start of STRING to form a single character.
909 If so, return the number of bytes at the start of STRING
910 which combine in this way. Otherwise, return 0. */
913 count_combining_before (string
, length
, pos
, pos_byte
)
914 unsigned char *string
;
918 int opos
= pos
, opos_byte
= pos_byte
;
920 unsigned char *p
= string
;
922 if (NILP (current_buffer
->enable_multibyte_characters
))
924 if (length
== 0 || CHAR_HEAD_P (*string
))
928 c
= FETCH_BYTE (pos_byte
- 1);
929 if (ASCII_BYTE_P (c
))
931 DEC_BOTH (pos
, pos_byte
);
932 c
= FETCH_BYTE (pos_byte
);
933 if (! BASE_LEADING_CODE_P (c
))
936 /* We have a combination situation.
937 Count the bytes at STRING that will combine. */
938 while (!CHAR_HEAD_P (*p
) && p
< string
+ length
)
944 /* See if the bytes after POS/POS_BYTE combine with bytes
945 at the end of STRING to form a single character.
946 If so, return the number of bytes after POS/POS_BYTE
947 which combine in this way. Otherwise, return 0. */
950 count_combining_after (string
, length
, pos
, pos_byte
)
951 unsigned char *string
;
955 int opos
= pos
, opos_byte
= pos_byte
;
959 if (NILP (current_buffer
->enable_multibyte_characters
))
961 if (length
== 0 || ASCII_BYTE_P (string
[length
- 1]))
964 while (i
> 0 && ! CHAR_HEAD_P (string
[i
]))
968 if (! BASE_LEADING_CODE_P (string
[i
]))
973 c
= FETCH_BYTE (pos_byte
);
976 while (pos_byte
< ZV_BYTE
)
978 c
= FETCH_BYTE (pos_byte
);
984 return pos_byte
- opos_byte
;
987 /* Adjust the position TARGET/TARGET_BYTE for the combining of NBYTES
988 following the position POS/POS_BYTE to the character preceding POS.
989 If TARGET is after POS+NBYTES, we only have to adjust the character
990 position TARGET, else, if TARGET is after POS, we have to adjust
991 both the character position TARGET and the byte position
992 TARGET_BYTE, else we don't have to do any adjustment. */
994 #define ADJUST_CHAR_POS(target, target_byte) \
996 if (target > pos + nbytes) \
998 else if (target >= pos) \
1001 target_byte = pos_byte + nbytes; \
1005 /* Combine NBYTES stray trailing-codes, which were formerly separate
1006 characters, with the preceding character. These bytes
1007 are located after position POS / POS_BYTE, and the preceding character
1008 is located just before that position. */
1011 combine_bytes (pos
, pos_byte
, nbytes
)
1012 int pos
, pos_byte
, nbytes
;
1014 /* Adjust all markers. */
1015 adjust_markers_for_delete (pos
, pos_byte
, pos
+ nbytes
, pos_byte
);
1017 adjust_overlays_for_delete (pos
, nbytes
);
1019 ADJUST_CHAR_POS (BUF_PT (current_buffer
), BUF_PT_BYTE (current_buffer
));
1020 ADJUST_CHAR_POS (GPT
, GPT_BYTE
);
1021 ADJUST_CHAR_POS (Z
, Z_BYTE
);
1022 ADJUST_CHAR_POS (ZV
, ZV_BYTE
);
1024 if (BUF_INTERVALS (current_buffer
) != 0)
1025 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
1026 offset_intervals (current_buffer
, pos
, - nbytes
);
1031 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1032 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
1033 are the same as in insert_1. */
1036 insert_1_both (string
, nchars
, nbytes
, inherit
, prepare
, before_markers
)
1037 register unsigned char *string
;
1038 register int nchars
, nbytes
;
1039 int inherit
, prepare
, before_markers
;
1041 register Lisp_Object temp
;
1042 int combined_before_bytes
, combined_after_bytes
;
1044 if (NILP (current_buffer
->enable_multibyte_characters
))
1048 /* Do this before moving and increasing the gap,
1049 because the before-change hooks might move the gap
1050 or make it smaller. */
1051 prepare_to_modify_buffer (PT
, PT
, NULL
);
1054 move_gap_both (PT
, PT_BYTE
);
1055 if (GAP_SIZE
< nbytes
)
1056 make_gap (nbytes
- GAP_SIZE
);
1058 combined_before_bytes
1059 = count_combining_before (string
, nbytes
, PT
, PT_BYTE
);
1060 combined_after_bytes
1061 = count_combining_after (string
, nbytes
, PT
, PT_BYTE
);
1063 /* Record deletion of the surrounding text that combines with
1064 the insertion. This, together with recording the insertion,
1065 will add up to the right stuff in the undo list.
1067 But there is no need to actually delete the combining bytes
1068 from the buffer and reinsert them. */
1070 if (combined_after_bytes
)
1072 Lisp_Object deletion
;
1075 if (! EQ (current_buffer
->undo_list
, Qt
))
1076 deletion
= make_buffer_string_both (PT
, PT_BYTE
,
1077 PT
+ combined_after_bytes
,
1078 PT_BYTE
+ combined_after_bytes
, 1);
1080 adjust_markers_for_record_delete (PT
, PT_BYTE
,
1081 PT
+ combined_after_bytes
,
1082 PT_BYTE
+ combined_after_bytes
);
1083 if (! EQ (current_buffer
->undo_list
, Qt
))
1084 record_delete (PT
, deletion
);
1087 if (combined_before_bytes
)
1089 Lisp_Object deletion
;
1092 if (! EQ (current_buffer
->undo_list
, Qt
))
1093 deletion
= make_buffer_string_both (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1095 adjust_markers_for_record_delete (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1097 if (! EQ (current_buffer
->undo_list
, Qt
))
1098 record_delete (PT
- 1, deletion
);
1101 record_insert (PT
- !!combined_before_bytes
,
1102 nchars
- combined_before_bytes
+ !!combined_before_bytes
);
1105 bcopy (string
, GPT_ADDR
, nbytes
);
1108 /* When we have combining at the end of the insertion,
1109 this is the character position before the combined character. */
1116 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1118 if (combined_after_bytes
)
1119 move_gap_both (GPT
+ combined_after_bytes
,
1120 GPT_BYTE
+ combined_after_bytes
);
1125 adjust_overlays_for_insert (PT
, nchars
);
1126 adjust_markers_for_insert (PT
, PT_BYTE
,
1127 PT
+ nchars
, PT_BYTE
+ nbytes
,
1128 combined_before_bytes
, combined_after_bytes
,
1131 #ifdef USE_TEXT_PROPERTIES
1132 if (BUF_INTERVALS (current_buffer
) != 0)
1133 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
1134 offset_intervals (current_buffer
, PT
, nchars
);
1136 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
1137 Fset_text_properties (make_number (PT
), make_number (PT
+ nchars
),
1142 int pos
= PT
, pos_byte
= PT_BYTE
;
1144 adjust_point (nchars
+ combined_after_bytes
,
1145 nbytes
+ combined_after_bytes
);
1147 if (combined_after_bytes
)
1148 combine_bytes (pos
+ nchars
, pos_byte
+ nbytes
, combined_after_bytes
);
1150 if (combined_before_bytes
)
1151 combine_bytes (pos
, pos_byte
, combined_before_bytes
);
1155 /* Insert the part of the text of STRING, a Lisp object assumed to be
1156 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
1157 starting at position POS / POS_BYTE. If the text of STRING has properties,
1158 copy them into the buffer.
1160 It does not work to use `insert' for this, because a GC could happen
1161 before we bcopy the stuff into the buffer, and relocate the string
1162 without insert noticing. */
1165 insert_from_string (string
, pos
, pos_byte
, length
, length_byte
, inherit
)
1167 register int pos
, pos_byte
, length
, length_byte
;
1171 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
1173 signal_after_change (opoint
, 0, PT
- opoint
);
1176 /* Like `insert_from_string' except that all markers pointing
1177 at the place where the insertion happens are adjusted to point after it. */
1180 insert_from_string_before_markers (string
, pos
, pos_byte
,
1181 length
, length_byte
, inherit
)
1183 register int pos
, pos_byte
, length
, length_byte
;
1187 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
1189 signal_after_change (opoint
, 0, PT
- opoint
);
1192 /* Subroutine of the insertion functions above. */
1195 insert_from_string_1 (string
, pos
, pos_byte
, nchars
, nbytes
,
1196 inherit
, before_markers
)
1198 register int pos
, pos_byte
, nchars
, nbytes
;
1199 int inherit
, before_markers
;
1201 register Lisp_Object temp
;
1202 struct gcpro gcpro1
;
1203 int outgoing_nbytes
= nbytes
;
1204 int combined_before_bytes
, combined_after_bytes
;
1205 int adjusted_nchars
;
1208 /* Make OUTGOING_NBYTES describe the text
1209 as it will be inserted in this buffer. */
1211 if (NILP (current_buffer
->enable_multibyte_characters
))
1212 outgoing_nbytes
= nchars
;
1213 else if (! STRING_MULTIBYTE (string
))
1215 = count_size_as_multibyte (&XSTRING (string
)->data
[pos_byte
],
1219 /* Do this before moving and increasing the gap,
1220 because the before-change hooks might move the gap
1221 or make it smaller. */
1222 prepare_to_modify_buffer (PT
, PT
, NULL
);
1225 move_gap_both (PT
, PT_BYTE
);
1226 if (GAP_SIZE
< nbytes
)
1227 make_gap (outgoing_nbytes
- GAP_SIZE
);
1230 /* Copy the string text into the buffer, perhaps converting
1231 between single-byte and multibyte. */
1232 copy_text (XSTRING (string
)->data
+ pos_byte
, GPT_ADDR
, nbytes
,
1233 STRING_MULTIBYTE (string
),
1234 ! NILP (current_buffer
->enable_multibyte_characters
));
1236 /* We have copied text into the gap, but we have not altered
1237 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1238 to these functions and get the same results as we would
1239 have got earlier on. Meanwhile, PT_ADDR does point to
1240 the text that has been stored by copy_text. */
1242 combined_before_bytes
1243 = count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
);
1244 combined_after_bytes
1245 = count_combining_after (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
);
1247 /* Record deletion of the surrounding text that combines with
1248 the insertion. This, together with recording the insertion,
1249 will add up to the right stuff in the undo list.
1251 But there is no need to actually delete the combining bytes
1252 from the buffer and reinsert them. */
1254 if (combined_after_bytes
)
1256 Lisp_Object deletion
;
1259 if (! EQ (current_buffer
->undo_list
, Qt
))
1260 deletion
= make_buffer_string_both (PT
, PT_BYTE
,
1261 PT
+ combined_after_bytes
,
1262 PT_BYTE
+ combined_after_bytes
, 1);
1264 adjust_markers_for_record_delete (PT
, PT_BYTE
,
1265 PT
+ combined_after_bytes
,
1266 PT_BYTE
+ combined_after_bytes
);
1267 if (! EQ (current_buffer
->undo_list
, Qt
))
1268 record_delete (PT
, deletion
);
1271 if (combined_before_bytes
)
1273 Lisp_Object deletion
;
1276 if (! EQ (current_buffer
->undo_list
, Qt
))
1277 deletion
= make_buffer_string_both (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1279 adjust_markers_for_record_delete (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1281 if (! EQ (current_buffer
->undo_list
, Qt
))
1282 record_delete (PT
- 1, deletion
);
1285 record_insert (PT
- !!combined_before_bytes
,
1286 nchars
- combined_before_bytes
+ !!combined_before_bytes
);
1289 GAP_SIZE
-= outgoing_nbytes
;
1293 GPT_BYTE
+= outgoing_nbytes
;
1294 ZV_BYTE
+= outgoing_nbytes
;
1295 Z_BYTE
+= outgoing_nbytes
;
1296 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1298 if (combined_after_bytes
)
1299 move_gap_both (GPT
+ combined_after_bytes
,
1300 GPT_BYTE
+ combined_after_bytes
);
1305 adjust_overlays_for_insert (PT
, nchars
);
1306 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1307 PT_BYTE
+ outgoing_nbytes
,
1308 combined_before_bytes
, combined_after_bytes
,
1311 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1312 offset_intervals (current_buffer
, PT
, nchars
);
1314 intervals
= XSTRING (string
)->intervals
;
1315 /* Get the intervals for the part of the string we are inserting--
1316 not including the combined-before bytes. */
1317 if (nbytes
< STRING_BYTES (XSTRING (string
)))
1318 intervals
= copy_intervals (intervals
, pos
, nchars
);
1320 /* Insert those intervals. */
1321 graft_intervals_into_buffer (intervals
, PT
, nchars
,
1322 current_buffer
, inherit
);
1325 int pos
= PT
, pos_byte
= PT_BYTE
;
1327 adjust_point (nchars
+ combined_after_bytes
,
1328 outgoing_nbytes
+ combined_after_bytes
);
1330 if (combined_after_bytes
)
1331 combine_bytes (pos
+ nchars
, pos_byte
+ outgoing_nbytes
,
1332 combined_after_bytes
);
1334 if (combined_before_bytes
)
1335 combine_bytes (pos
, pos_byte
, combined_before_bytes
);
1339 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1340 current buffer. If the text in BUF has properties, they are absorbed
1341 into the current buffer.
1343 It does not work to use `insert' for this, because a malloc could happen
1344 and relocate BUF's text before the bcopy happens. */
1347 insert_from_buffer (buf
, charpos
, nchars
, inherit
)
1349 int charpos
, nchars
;
1354 insert_from_buffer_1 (buf
, charpos
, nchars
, inherit
);
1355 signal_after_change (opoint
, 0, PT
- opoint
);
1359 insert_from_buffer_1 (buf
, from
, nchars
, inherit
)
1364 register Lisp_Object temp
;
1366 int from_byte
= buf_charpos_to_bytepos (buf
, from
);
1367 int to_byte
= buf_charpos_to_bytepos (buf
, from
+ nchars
);
1368 int incoming_nbytes
= to_byte
- from_byte
;
1369 int outgoing_nbytes
= incoming_nbytes
;
1370 int combined_before_bytes
, combined_after_bytes
;
1371 int adjusted_nchars
;
1374 /* Make OUTGOING_NBYTES describe the text
1375 as it will be inserted in this buffer. */
1377 if (NILP (current_buffer
->enable_multibyte_characters
))
1378 outgoing_nbytes
= nchars
;
1379 else if (NILP (buf
->enable_multibyte_characters
))
1381 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
, from_byte
),
1384 /* Make sure point-max won't overflow after this insertion. */
1385 XSETINT (temp
, outgoing_nbytes
+ Z
);
1386 if (outgoing_nbytes
+ Z
!= XINT (temp
))
1387 error ("Maximum buffer size exceeded");
1389 /* Do this before moving and increasing the gap,
1390 because the before-change hooks might move the gap
1391 or make it smaller. */
1392 prepare_to_modify_buffer (PT
, PT
, NULL
);
1395 move_gap_both (PT
, PT_BYTE
);
1396 if (GAP_SIZE
< outgoing_nbytes
)
1397 make_gap (outgoing_nbytes
- GAP_SIZE
);
1399 if (from
< BUF_GPT (buf
))
1401 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1402 if (chunk
> incoming_nbytes
)
1403 chunk
= incoming_nbytes
;
1404 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
),
1406 ! NILP (buf
->enable_multibyte_characters
),
1407 ! NILP (current_buffer
->enable_multibyte_characters
));
1411 if (chunk
< incoming_nbytes
)
1412 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
+ chunk
),
1413 GPT_ADDR
+ chunk
, incoming_nbytes
- chunk
,
1414 ! NILP (buf
->enable_multibyte_characters
),
1415 ! NILP (current_buffer
->enable_multibyte_characters
));
1417 /* We have copied text into the gap, but we have not altered
1418 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1419 to these functions and get the same results as we would
1420 have got earlier on. Meanwhile, GPT_ADDR does point to
1421 the text that has been stored by copy_text. */
1422 combined_before_bytes
1423 = count_combining_before (GPT_ADDR
, outgoing_nbytes
, PT
, PT_BYTE
);
1424 combined_after_bytes
1425 = count_combining_after (GPT_ADDR
, outgoing_nbytes
,
1428 /* Record deletion of the surrounding text that combines with
1429 the insertion. This, together with recording the insertion,
1430 will add up to the right stuff in the undo list.
1432 But there is no need to actually delete the combining bytes
1433 from the buffer and reinsert them. */
1435 if (combined_after_bytes
)
1437 Lisp_Object deletion
;
1440 if (! EQ (current_buffer
->undo_list
, Qt
))
1441 deletion
= make_buffer_string_both (PT
, PT_BYTE
,
1442 PT
+ combined_after_bytes
,
1443 PT_BYTE
+ combined_after_bytes
, 1);
1445 adjust_markers_for_record_delete (PT
, PT_BYTE
,
1446 PT
+ combined_after_bytes
,
1447 PT_BYTE
+ combined_after_bytes
);
1448 if (! EQ (current_buffer
->undo_list
, Qt
))
1449 record_delete (PT
, deletion
);
1452 if (combined_before_bytes
)
1454 Lisp_Object deletion
;
1457 if (! EQ (current_buffer
->undo_list
, Qt
))
1458 deletion
= make_buffer_string_both (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1460 adjust_markers_for_record_delete (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1462 if (! EQ (current_buffer
->undo_list
, Qt
))
1463 record_delete (PT
- 1, deletion
);
1466 record_insert (PT
- !!combined_before_bytes
,
1467 nchars
- combined_before_bytes
+ !!combined_before_bytes
);
1470 GAP_SIZE
-= outgoing_nbytes
;
1474 GPT_BYTE
+= outgoing_nbytes
;
1475 ZV_BYTE
+= outgoing_nbytes
;
1476 Z_BYTE
+= outgoing_nbytes
;
1477 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1479 if (combined_after_bytes
)
1480 move_gap_both (GPT
+ combined_after_bytes
,
1481 GPT_BYTE
+ combined_after_bytes
);
1486 adjust_overlays_for_insert (PT
, nchars
);
1487 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1488 PT_BYTE
+ outgoing_nbytes
,
1489 combined_before_bytes
, combined_after_bytes
, 0);
1491 #ifdef USE_TEXT_PROPERTIES
1492 if (BUF_INTERVALS (current_buffer
) != 0)
1493 offset_intervals (current_buffer
, PT
, nchars
);
1496 /* Get the intervals for the part of the string we are inserting--
1497 not including the combined-before bytes. */
1498 intervals
= BUF_INTERVALS (buf
);
1499 if (outgoing_nbytes
< BUF_Z_BYTE (buf
) - BUF_BEG_BYTE (buf
))
1500 intervals
= copy_intervals (intervals
, from
, nchars
);
1502 /* Insert those intervals. */
1503 graft_intervals_into_buffer (intervals
, PT
, nchars
, current_buffer
, inherit
);
1506 int pos
= PT
, pos_byte
= PT_BYTE
;
1508 adjust_point (nchars
+ combined_after_bytes
,
1509 outgoing_nbytes
+ combined_after_bytes
);
1511 if (combined_after_bytes
)
1512 combine_bytes (pos
+ nchars
, pos_byte
+ outgoing_nbytes
,
1513 combined_after_bytes
);
1515 if (combined_before_bytes
)
1516 combine_bytes (pos
, pos_byte
, combined_before_bytes
);
1520 /* This function should be called after moving gap to FROM and before
1521 altering text between FROM and TO. This adjusts various position
1522 keepers and markers as if the text is deleted. Don't forget to
1523 call adjust_after_replace after you actually alter the text. */
1526 adjust_before_replace (from
, from_byte
, to
, to_byte
)
1527 int from
, from_byte
, to
, to_byte
;
1529 Lisp_Object deletion
;
1531 if (! EQ (current_buffer
->undo_list
, Qt
))
1532 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1536 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1538 if (! EQ (current_buffer
->undo_list
, Qt
))
1539 record_delete (from
, deletion
);
1541 adjust_overlays_for_delete (from
, to
- from
);
1544 /* Record undo information and adjust markers and position keepers for
1545 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1546 chars (LEN_BYTE bytes) which resides in the gap just after
1549 PREV_TEXT nil means the new text was just inserted. */
1552 adjust_after_replace (from
, from_byte
, prev_text
, len
, len_byte
)
1553 int from
, from_byte
, len
, len_byte
;
1554 Lisp_Object prev_text
;
1556 int combined_before_bytes
1557 = count_combining_before (GPT_ADDR
, len_byte
, from
, from_byte
);
1558 int combined_after_bytes
1559 = count_combining_after (GPT_ADDR
, len_byte
, from
, from_byte
);
1560 int nchars_del
= 0, nbytes_del
= 0;
1562 if (combined_after_bytes
)
1564 Lisp_Object deletion
;
1567 if (! EQ (current_buffer
->undo_list
, Qt
))
1568 deletion
= make_buffer_string_both (from
, from_byte
,
1569 from
+ combined_after_bytes
,
1570 from_byte
+ combined_after_bytes
,
1573 adjust_markers_for_record_delete (from
, from_byte
,
1574 from
+ combined_after_bytes
,
1575 from_byte
+ combined_after_bytes
);
1577 if (! EQ (current_buffer
->undo_list
, Qt
))
1578 record_delete (from
, deletion
);
1581 if (combined_before_bytes
)
1583 Lisp_Object deletion
;
1586 if (! EQ (current_buffer
->undo_list
, Qt
))
1587 deletion
= make_buffer_string_both (from
- 1, CHAR_TO_BYTE (from
- 1),
1588 from
, from_byte
, 1);
1589 adjust_markers_for_record_delete (from
- 1, CHAR_TO_BYTE (from
- 1),
1591 if (! EQ (current_buffer
->undo_list
, Qt
))
1592 record_delete (from
- 1, deletion
);
1595 /* Update various buffer positions for the new text. */
1596 GAP_SIZE
-= len_byte
;
1598 ZV_BYTE
+= len_byte
; Z_BYTE
+= len_byte
;
1599 GPT
+= len
; GPT_BYTE
+= len_byte
;
1600 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1602 if (combined_after_bytes
)
1603 move_gap_both (GPT
+ combined_after_bytes
,
1604 GPT_BYTE
+ combined_after_bytes
);
1606 if (STRINGP (prev_text
))
1608 nchars_del
= XSTRING (prev_text
)->size
;
1609 nbytes_del
= STRING_BYTES (XSTRING (prev_text
));
1611 adjust_markers_for_replace (from
, from_byte
, nchars_del
, nbytes_del
,
1613 combined_before_bytes
, combined_after_bytes
);
1614 if (STRINGP (prev_text
))
1615 record_delete (from
, prev_text
);
1616 record_insert (from
- !!combined_before_bytes
,
1617 len
- combined_before_bytes
+ !!combined_before_bytes
);
1619 if (len
> nchars_del
)
1620 adjust_overlays_for_insert (from
, len
- nchars_del
);
1621 else if (len
< nchars_del
)
1622 adjust_overlays_for_delete (from
, nchars_del
- len
);
1623 #ifdef USE_TEXT_PROPERTIES
1624 if (BUF_INTERVALS (current_buffer
) != 0)
1625 offset_intervals (current_buffer
, from
, len
- nchars_del
);
1629 int pos
= PT
, pos_byte
= PT_BYTE
;
1632 adjust_point (len
- nchars_del
+ combined_after_bytes
,
1633 len_byte
- nbytes_del
+ combined_after_bytes
);
1634 else if (from
== PT
&& combined_before_bytes
)
1635 adjust_point (0, combined_before_bytes
);
1637 if (combined_after_bytes
)
1638 combine_bytes (from
+ len
, from_byte
+ len_byte
, combined_after_bytes
);
1640 if (combined_before_bytes
)
1641 combine_bytes (from
, from_byte
, combined_before_bytes
);
1647 evaporate_overlays (from
);
1651 /* Record undo information, adjust markers and position keepers for an
1652 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1653 text already exists in the current buffer but character length (TO
1654 - FROM) may be incorrect, the correct length is NEWLEN. */
1657 adjust_after_insert (from
, from_byte
, to
, to_byte
, newlen
)
1658 int from
, from_byte
, to
, to_byte
, newlen
;
1660 int len
= to
- from
, len_byte
= to_byte
- from_byte
;
1663 move_gap_both (to
, to_byte
);
1664 GAP_SIZE
+= len_byte
;
1665 GPT
-= len
; GPT_BYTE
-= len_byte
;
1666 ZV
-= len
; ZV_BYTE
-= len_byte
;
1667 Z
-= len
; Z_BYTE
-= len_byte
;
1668 adjust_after_replace (from
, from_byte
, Qnil
, newlen
, len_byte
);
1671 /* Replace the text from character positions FROM to TO with NEW,
1672 If PREPARE is nonzero, call prepare_to_modify_buffer.
1673 If INHERIT, the newly inserted text should inherit text properties
1674 from the surrounding non-deleted text. */
1676 /* Note that this does not yet handle markers quite right.
1677 Also it needs to record a single undo-entry that does a replacement
1678 rather than a separate delete and insert.
1679 That way, undo will also handle markers properly. */
1682 replace_range (from
, to
, new, prepare
, inherit
, nomarkers
)
1684 int from
, to
, prepare
, inherit
, nomarkers
;
1686 int inschars
= XSTRING (new)->size
;
1687 int insbytes
= STRING_BYTES (XSTRING (new));
1688 int from_byte
, to_byte
;
1689 int nbytes_del
, nchars_del
;
1690 register Lisp_Object temp
;
1691 struct gcpro gcpro1
;
1692 int combined_before_bytes
, combined_after_bytes
;
1693 int adjusted_inschars
;
1695 int outgoing_insbytes
= insbytes
;
1703 int range_length
= to
- from
;
1704 prepare_to_modify_buffer (from
, to
, &from
);
1705 to
= from
+ range_length
;
1710 /* Make args be valid */
1716 from_byte
= CHAR_TO_BYTE (from
);
1717 to_byte
= CHAR_TO_BYTE (to
);
1719 nchars_del
= to
- from
;
1720 nbytes_del
= to_byte
- from_byte
;
1722 if (nbytes_del
<= 0 && insbytes
== 0)
1725 /* Make OUTGOING_INSBYTES describe the text
1726 as it will be inserted in this buffer. */
1728 if (NILP (current_buffer
->enable_multibyte_characters
))
1729 outgoing_insbytes
= inschars
;
1730 else if (! STRING_MULTIBYTE (new))
1732 = count_size_as_multibyte (XSTRING (new)->data
, insbytes
);
1734 /* Make sure point-max won't overflow after this insertion. */
1735 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1736 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1737 error ("Maximum buffer size exceeded");
1741 /* Make sure the gap is somewhere in or next to what we are deleting. */
1743 gap_right (from
, from_byte
);
1745 gap_left (to
, to_byte
, 0);
1748 Lisp_Object deletion
;
1751 if (! EQ (current_buffer
->undo_list
, Qt
))
1752 deletion
= make_buffer_string_both (from
, from_byte
, to
, to_byte
, 1);
1755 /* Relocate all markers pointing into the new, larger gap
1756 to point at the end of the text before the gap.
1757 Do this before recording the deletion,
1758 so that undo handles this after reinserting the text. */
1759 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1761 if (! EQ (current_buffer
->undo_list
, Qt
))
1762 record_delete (from
, deletion
);
1765 GAP_SIZE
+= nbytes_del
;
1768 ZV_BYTE
-= nbytes_del
;
1769 Z_BYTE
-= nbytes_del
;
1771 GPT_BYTE
= from_byte
;
1772 *(GPT_ADDR
) = 0; /* Put an anchor. */
1777 if (GPT
- BEG
< beg_unchanged
)
1778 beg_unchanged
= GPT
- BEG
;
1779 if (Z
- GPT
< end_unchanged
)
1780 end_unchanged
= Z
- GPT
;
1782 if (GAP_SIZE
< insbytes
)
1783 make_gap (insbytes
- GAP_SIZE
);
1785 /* Copy the string text into the buffer, perhaps converting
1786 between single-byte and multibyte. */
1787 copy_text (XSTRING (new)->data
, GPT_ADDR
, insbytes
,
1788 STRING_MULTIBYTE (new),
1789 ! NILP (current_buffer
->enable_multibyte_characters
));
1791 /* We have copied text into the gap, but we have not altered
1792 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1793 to these functions and get the same results as we would
1794 have got earlier on. Meanwhile, GPT_ADDR does point to
1795 the text that has been stored by copy_text. */
1797 combined_before_bytes
1798 = count_combining_before (GPT_ADDR
, outgoing_insbytes
, PT
, PT_BYTE
);
1799 combined_after_bytes
1800 = count_combining_after (GPT_ADDR
, outgoing_insbytes
, PT
, PT_BYTE
);
1802 /* Record deletion of the surrounding text that combines with
1803 the insertion. This, together with recording the insertion,
1804 will add up to the right stuff in the undo list.
1806 But there is no need to actually delete the combining bytes
1807 from the buffer and reinsert them. */
1809 if (combined_after_bytes
)
1811 Lisp_Object deletion
;
1814 if (! EQ (current_buffer
->undo_list
, Qt
))
1815 deletion
= make_buffer_string_both (PT
, PT_BYTE
,
1816 PT
+ combined_after_bytes
,
1817 PT_BYTE
+ combined_after_bytes
, 1);
1819 adjust_markers_for_record_delete (PT
, PT_BYTE
,
1820 PT
+ combined_after_bytes
,
1821 PT_BYTE
+ combined_after_bytes
);
1822 if (! EQ (current_buffer
->undo_list
, Qt
))
1823 record_delete (PT
, deletion
);
1826 if (combined_before_bytes
)
1828 Lisp_Object deletion
;
1831 if (! EQ (current_buffer
->undo_list
, Qt
))
1832 deletion
= make_buffer_string_both (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1834 adjust_markers_for_record_delete (PT
- 1, CHAR_TO_BYTE (PT
- 1),
1836 if (! EQ (current_buffer
->undo_list
, Qt
))
1837 record_delete (PT
- 1, deletion
);
1840 record_insert (PT
- !!combined_before_bytes
,
1841 inschars
- combined_before_bytes
+ !!combined_before_bytes
);
1843 GAP_SIZE
-= outgoing_insbytes
;
1847 GPT_BYTE
+= outgoing_insbytes
;
1848 ZV_BYTE
+= outgoing_insbytes
;
1849 Z_BYTE
+= outgoing_insbytes
;
1850 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1852 if (combined_after_bytes
)
1853 move_gap_both (GPT
+ combined_after_bytes
,
1854 GPT_BYTE
+ combined_after_bytes
);
1859 /* Adjust the overlay center as needed. This must be done after
1860 adjusting the markers that bound the overlays. */
1861 adjust_overlays_for_delete (from
, nchars_del
);
1862 adjust_overlays_for_insert (from
, inschars
);
1864 adjust_markers_for_insert (from
, from_byte
,
1865 from
+ inschars
, from_byte
+ outgoing_insbytes
,
1866 combined_before_bytes
, combined_after_bytes
, 0);
1868 #ifdef USE_TEXT_PROPERTIES
1869 offset_intervals (current_buffer
, PT
, inschars
- nchars_del
);
1871 /* Get the intervals for the part of the string we are inserting--
1872 not including the combined-before bytes. */
1873 intervals
= XSTRING (new)->intervals
;
1874 /* Insert those intervals. */
1875 graft_intervals_into_buffer (intervals
, from
, inschars
,
1876 current_buffer
, inherit
);
1879 /* Relocate point as if it were a marker. */
1881 adjust_point ((from
+ inschars
- (PT
< to
? PT
: to
)
1882 + combined_after_bytes
),
1883 (from_byte
+ outgoing_insbytes
1884 - (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
)
1885 + combined_after_bytes
));
1887 if (combined_after_bytes
)
1888 combine_bytes (from
+ inschars
, from_byte
+ outgoing_insbytes
,
1889 combined_after_bytes
);
1891 if (combined_before_bytes
)
1892 combine_bytes (from
, from_byte
, combined_before_bytes
);
1894 if (outgoing_insbytes
== 0)
1895 evaporate_overlays (from
);
1902 signal_after_change (from
, nchars_del
, PT
- from
);
1905 /* Delete characters in current buffer
1906 from FROM up to (but not including) TO.
1907 If TO comes before FROM, we delete nothing. */
1910 del_range (from
, to
)
1911 register int from
, to
;
1913 del_range_1 (from
, to
, 1);
1916 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
1919 del_range_1 (from
, to
, prepare
)
1920 int from
, to
, prepare
;
1922 int from_byte
, to_byte
;
1924 /* Make args be valid */
1935 int range_length
= to
- from
;
1936 prepare_to_modify_buffer (from
, to
, &from
);
1937 to
= from
+ range_length
;
1940 from_byte
= CHAR_TO_BYTE (from
);
1941 to_byte
= CHAR_TO_BYTE (to
);
1943 del_range_2 (from
, from_byte
, to
, to_byte
);
1946 /* Like del_range_1 but args are byte positions, not char positions. */
1949 del_range_byte (from_byte
, to_byte
, prepare
)
1950 int from_byte
, to_byte
, prepare
;
1954 /* Make args be valid */
1955 if (from_byte
< BEGV_BYTE
)
1956 from_byte
= BEGV_BYTE
;
1957 if (to_byte
> ZV_BYTE
)
1960 if (to_byte
<= from_byte
)
1963 from
= BYTE_TO_CHAR (from_byte
);
1964 to
= BYTE_TO_CHAR (to_byte
);
1968 int old_from
= from
, old_to
= Z
- to
;
1969 int range_length
= to
- from
;
1970 prepare_to_modify_buffer (from
, to
, &from
);
1971 to
= from
+ range_length
;
1973 if (old_from
!= from
)
1974 from_byte
= CHAR_TO_BYTE (from
);
1975 if (old_to
== Z
- to
)
1976 to_byte
= CHAR_TO_BYTE (to
);
1979 del_range_2 (from
, from_byte
, to
, to_byte
);
1982 /* Like del_range_1, but positions are specified both as charpos
1986 del_range_both (from
, from_byte
, to
, to_byte
, prepare
)
1987 int from
, from_byte
, to
, to_byte
, prepare
;
1989 /* Make args be valid */
1990 if (from_byte
< BEGV_BYTE
)
1991 from_byte
= BEGV_BYTE
;
1992 if (to_byte
> ZV_BYTE
)
1995 if (to_byte
<= from_byte
)
2005 int old_from
= from
, old_to
= Z
- to
;
2006 int range_length
= to
- from
;
2007 prepare_to_modify_buffer (from
, to
, &from
);
2008 to
= from
+ range_length
;
2010 if (old_from
!= from
)
2011 from_byte
= CHAR_TO_BYTE (from
);
2012 if (old_to
== Z
- to
)
2013 to_byte
= CHAR_TO_BYTE (to
);
2016 del_range_2 (from
, from_byte
, to
, to_byte
);
2019 /* Delete a range of text, specified both as character positions
2020 and byte positions. FROM and TO are character positions,
2021 while FROM_BYTE and TO_BYTE are byte positions. */
2024 del_range_2 (from
, from_byte
, to
, to_byte
)
2025 int from
, from_byte
, to
, to_byte
;
2027 register int nbytes_del
, nchars_del
;
2028 int combined_after_bytes
;
2029 Lisp_Object deletion
;
2034 nchars_del
= to
- from
;
2035 nbytes_del
= to_byte
- from_byte
;
2037 /* Make sure the gap is somewhere in or next to what we are deleting. */
2039 gap_right (from
, from_byte
);
2041 gap_left (to
, to_byte
, 0);
2043 combined_after_bytes
2044 = count_combining_before (BUF_BYTE_ADDRESS (current_buffer
, to_byte
),
2045 ZV_BYTE
- to_byte
, from
, from_byte
);
2046 if (combined_after_bytes
)
2048 from_byte_1
= from_byte
;
2049 DEC_POS (from_byte_1
);
2052 from_byte_1
= from_byte
;
2054 if (! EQ (current_buffer
->undo_list
, Qt
))
2056 = make_buffer_string_both (from
- !!combined_after_bytes
,
2058 to
+ combined_after_bytes
,
2059 to_byte
+ combined_after_bytes
, 1);
2060 if (combined_after_bytes
)
2061 /* COMBINED_AFTER_BYTES nonzero means that the above code moved
2062 the gap. We must move the gap again to a proper place. */
2063 move_gap_both (from
, from_byte
);
2065 /* Relocate all markers pointing into the new, larger gap
2066 to point at the end of the text before the gap.
2067 Do this before recording the deletion,
2068 so that undo handles this after reinserting the text. */
2069 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
2070 if (combined_after_bytes
)
2072 /* Adjust markers for the phony deletion
2073 that we are about to call record_undo for. */
2075 /* Here we delete the markers that formerly
2076 pointed at TO ... TO + COMBINED_AFTER_BYTES.
2077 But because of the call to adjust_markers_for_delete, above,
2078 they now point at FROM ... FROM + COMBINED_AFTER_BYTES. */
2079 adjust_markers_for_record_delete (from
, from_byte
,
2080 from
+ combined_after_bytes
,
2081 from_byte
+ combined_after_bytes
);
2083 adjust_markers_for_record_delete (from
- 1, from_byte_1
,
2086 if (! EQ (current_buffer
->undo_list
, Qt
))
2087 record_delete (from
- !!combined_after_bytes
, deletion
);
2090 /* Relocate point as if it were a marker. */
2092 adjust_point (from
- (PT
< to
? PT
: to
),
2093 from_byte
- (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
));
2095 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2096 offset_intervals (current_buffer
, from
, - nchars_del
);
2098 /* Adjust the overlay center as needed. This must be done after
2099 adjusting the markers that bound the overlays. */
2100 adjust_overlays_for_delete (from
, nchars_del
);
2102 GAP_SIZE
+= nbytes_del
;
2103 ZV_BYTE
-= nbytes_del
;
2104 Z_BYTE
-= nbytes_del
;
2108 GPT_BYTE
= from_byte
;
2110 if (combined_after_bytes
)
2111 move_gap_both (GPT
+ combined_after_bytes
,
2112 GPT_BYTE
+ combined_after_bytes
);
2114 *(GPT_ADDR
) = 0; /* Put an anchor. */
2119 if (GPT
- BEG
< beg_unchanged
)
2120 beg_unchanged
= GPT
- BEG
;
2121 if (Z
- GPT
< end_unchanged
)
2122 end_unchanged
= Z
- GPT
;
2124 if (combined_after_bytes
)
2126 combine_bytes (from
, from_byte
, combined_after_bytes
);
2128 record_insert (GPT
- 1, 1);
2133 evaporate_overlays (from
);
2134 signal_after_change (from
, nchars_del
, 0);
2137 /* Call this if you're about to change the region of BUFFER from
2138 character positions START to END. This checks the read-only
2139 properties of the region, calls the necessary modification hooks,
2140 and warns the next redisplay that it should pay attention to that
2144 modify_region (buffer
, start
, end
)
2145 struct buffer
*buffer
;
2148 struct buffer
*old_buffer
= current_buffer
;
2150 if (buffer
!= old_buffer
)
2151 set_buffer_internal (buffer
);
2153 prepare_to_modify_buffer (start
, end
, NULL
);
2155 if (start
- 1 < beg_unchanged
2156 || (unchanged_modified
== MODIFF
2157 && overlay_unchanged_modified
== OVERLAY_MODIFF
))
2158 beg_unchanged
= start
- 1;
2159 if (Z
- end
< end_unchanged
2160 || (unchanged_modified
== MODIFF
2161 && overlay_unchanged_modified
== OVERLAY_MODIFF
))
2162 end_unchanged
= Z
- end
;
2164 if (MODIFF
<= SAVE_MODIFF
)
2165 record_first_change ();
2168 buffer
->point_before_scroll
= Qnil
;
2170 if (buffer
!= old_buffer
)
2171 set_buffer_internal (old_buffer
);
2174 /* Check that it is okay to modify the buffer between START and END,
2175 which are char positions.
2177 Run the before-change-function, if any. If intervals are in use,
2178 verify that the text to be modified is not read-only, and call
2179 any modification properties the text may have.
2181 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2182 by holding its value temporarily in a marker. */
2185 prepare_to_modify_buffer (start
, end
, preserve_ptr
)
2189 if (!NILP (current_buffer
->read_only
))
2190 Fbarf_if_buffer_read_only ();
2192 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2193 if (BUF_INTERVALS (current_buffer
) != 0)
2197 Lisp_Object preserve_marker
;
2198 struct gcpro gcpro1
;
2199 preserve_marker
= Fcopy_marker (make_number (*preserve_ptr
), Qnil
);
2200 GCPRO1 (preserve_marker
);
2201 verify_interval_modification (current_buffer
, start
, end
);
2202 *preserve_ptr
= marker_position (preserve_marker
);
2203 unchain_marker (preserve_marker
);
2207 verify_interval_modification (current_buffer
, start
, end
);
2210 #ifdef CLASH_DETECTION
2211 if (!NILP (current_buffer
->file_truename
)
2212 /* Make binding buffer-file-name to nil effective. */
2213 && !NILP (current_buffer
->filename
)
2214 && SAVE_MODIFF
>= MODIFF
)
2215 lock_file (current_buffer
->file_truename
);
2217 /* At least warn if this file has changed on disk since it was visited. */
2218 if (!NILP (current_buffer
->filename
)
2219 && SAVE_MODIFF
>= MODIFF
2220 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
2221 && !NILP (Ffile_exists_p (current_buffer
->filename
)))
2222 call1 (intern ("ask-user-about-supersession-threat"),
2223 current_buffer
->filename
);
2224 #endif /* not CLASH_DETECTION */
2226 signal_before_change (start
, end
, preserve_ptr
);
2228 if (current_buffer
->newline_cache
)
2229 invalidate_region_cache (current_buffer
,
2230 current_buffer
->newline_cache
,
2231 start
- BEG
, Z
- end
);
2232 if (current_buffer
->width_run_cache
)
2233 invalidate_region_cache (current_buffer
,
2234 current_buffer
->width_run_cache
,
2235 start
- BEG
, Z
- end
);
2237 Vdeactivate_mark
= Qt
;
2240 /* These macros work with an argument named `preserve_ptr'
2241 and a local variable named `preserve_marker'. */
2243 #define PRESERVE_VALUE \
2244 if (preserve_ptr && NILP (preserve_marker)) \
2245 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2247 #define RESTORE_VALUE \
2248 if (! NILP (preserve_marker)) \
2250 *preserve_ptr = marker_position (preserve_marker); \
2251 unchain_marker (preserve_marker); \
2254 #define PRESERVE_START_END \
2255 if (NILP (start_marker)) \
2256 start_marker = Fcopy_marker (start, Qnil); \
2257 if (NILP (end_marker)) \
2258 end_marker = Fcopy_marker (end, Qnil);
2260 #define FETCH_START \
2261 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2264 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2266 /* Signal a change to the buffer immediately before it happens.
2267 START_INT and END_INT are the bounds of the text to be changed.
2269 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2270 by holding its value temporarily in a marker. */
2273 signal_before_change (start_int
, end_int
, preserve_ptr
)
2274 int start_int
, end_int
;
2277 Lisp_Object start
, end
;
2278 Lisp_Object start_marker
, end_marker
;
2279 Lisp_Object preserve_marker
;
2280 struct gcpro gcpro1
, gcpro2
, gcpro3
;
2282 start
= make_number (start_int
);
2283 end
= make_number (end_int
);
2284 preserve_marker
= Qnil
;
2285 start_marker
= Qnil
;
2287 GCPRO3 (preserve_marker
, start_marker
, end_marker
);
2289 /* If buffer is unmodified, run a special hook for that case. */
2290 if (SAVE_MODIFF
>= MODIFF
2291 && !NILP (Vfirst_change_hook
)
2292 && !NILP (Vrun_hooks
))
2296 call1 (Vrun_hooks
, Qfirst_change_hook
);
2299 /* Run the before-change-function if any.
2300 We don't bother "binding" this variable to nil
2301 because it is obsolete anyway and new code should not use it. */
2302 if (!NILP (Vbefore_change_function
))
2306 call2 (Vbefore_change_function
, FETCH_START
, FETCH_END
);
2309 /* Now run the before-change-functions if any. */
2310 if (!NILP (Vbefore_change_functions
))
2312 Lisp_Object args
[3];
2313 Lisp_Object before_change_functions
;
2314 Lisp_Object after_change_functions
;
2315 struct gcpro gcpro1
, gcpro2
;
2320 /* "Bind" before-change-functions and after-change-functions
2321 to nil--but in a way that errors don't know about.
2322 That way, if there's an error in them, they will stay nil. */
2323 before_change_functions
= Vbefore_change_functions
;
2324 after_change_functions
= Vafter_change_functions
;
2325 Vbefore_change_functions
= Qnil
;
2326 Vafter_change_functions
= Qnil
;
2327 GCPRO2 (before_change_functions
, after_change_functions
);
2329 /* Actually run the hook functions. */
2330 args
[0] = Qbefore_change_functions
;
2331 args
[1] = FETCH_START
;
2332 args
[2] = FETCH_END
;
2333 run_hook_list_with_args (before_change_functions
, 3, args
);
2335 /* "Unbind" the variables we "bound" to nil. */
2336 Vbefore_change_functions
= before_change_functions
;
2337 Vafter_change_functions
= after_change_functions
;
2341 if (!NILP (current_buffer
->overlays_before
)
2342 || !NILP (current_buffer
->overlays_after
))
2345 report_overlay_modification (FETCH_START
, FETCH_END
, 0,
2346 FETCH_START
, FETCH_END
, Qnil
);
2349 if (! NILP (start_marker
))
2350 free_marker (start_marker
);
2351 if (! NILP (end_marker
))
2352 free_marker (end_marker
);
2357 /* Signal a change immediately after it happens.
2358 CHARPOS is the character position of the start of the changed text.
2359 LENDEL is the number of characters of the text before the change.
2360 (Not the whole buffer; just the part that was changed.)
2361 LENINS is the number of characters in that part of the text
2362 after the change. */
2365 signal_after_change (charpos
, lendel
, lenins
)
2366 int charpos
, lendel
, lenins
;
2368 /* If we are deferring calls to the after-change functions
2369 and there are no before-change functions,
2370 just record the args that we were going to use. */
2371 if (! NILP (Vcombine_after_change_calls
)
2372 && NILP (Vbefore_change_function
) && NILP (Vbefore_change_functions
)
2373 && NILP (current_buffer
->overlays_before
)
2374 && NILP (current_buffer
->overlays_after
))
2378 if (!NILP (combine_after_change_list
)
2379 && current_buffer
!= XBUFFER (combine_after_change_buffer
))
2380 Fcombine_after_change_execute ();
2382 elt
= Fcons (make_number (charpos
- BEG
),
2383 Fcons (make_number (Z
- (charpos
- lendel
+ lenins
)),
2384 Fcons (make_number (lenins
- lendel
), Qnil
)));
2385 combine_after_change_list
2386 = Fcons (elt
, combine_after_change_list
);
2387 combine_after_change_buffer
= Fcurrent_buffer ();
2392 if (!NILP (combine_after_change_list
))
2393 Fcombine_after_change_execute ();
2395 /* Run the after-change-function if any.
2396 We don't bother "binding" this variable to nil
2397 because it is obsolete anyway and new code should not use it. */
2398 if (!NILP (Vafter_change_function
))
2399 call3 (Vafter_change_function
,
2400 make_number (charpos
), make_number (charpos
+ lenins
),
2401 make_number (lendel
));
2403 if (!NILP (Vafter_change_functions
))
2405 Lisp_Object args
[4];
2406 Lisp_Object before_change_functions
;
2407 Lisp_Object after_change_functions
;
2408 struct gcpro gcpro1
, gcpro2
;
2410 /* "Bind" before-change-functions and after-change-functions
2411 to nil--but in a way that errors don't know about.
2412 That way, if there's an error in them, they will stay nil. */
2413 before_change_functions
= Vbefore_change_functions
;
2414 after_change_functions
= Vafter_change_functions
;
2415 Vbefore_change_functions
= Qnil
;
2416 Vafter_change_functions
= Qnil
;
2417 GCPRO2 (before_change_functions
, after_change_functions
);
2419 /* Actually run the hook functions. */
2420 args
[0] = Qafter_change_functions
;
2421 XSETFASTINT (args
[1], charpos
);
2422 XSETFASTINT (args
[2], charpos
+ lenins
);
2423 XSETFASTINT (args
[3], lendel
);
2424 run_hook_list_with_args (after_change_functions
,
2427 /* "Unbind" the variables we "bound" to nil. */
2428 Vbefore_change_functions
= before_change_functions
;
2429 Vafter_change_functions
= after_change_functions
;
2433 if (!NILP (current_buffer
->overlays_before
)
2434 || !NILP (current_buffer
->overlays_after
))
2435 report_overlay_modification (make_number (charpos
),
2436 make_number (charpos
+ lenins
),
2438 make_number (charpos
),
2439 make_number (charpos
+ lenins
),
2440 make_number (lendel
));
2442 /* After an insertion, call the text properties
2443 insert-behind-hooks or insert-in-front-hooks. */
2445 report_interval_modification (make_number (charpos
),
2446 make_number (charpos
+ lenins
));
2450 Fcombine_after_change_execute_1 (val
)
2453 Vcombine_after_change_calls
= val
;
2457 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute
,
2458 Scombine_after_change_execute
, 0, 0, 0,
2459 "This function is for use internally in `combine-after-change-calls'.")
2462 register Lisp_Object val
;
2463 int count
= specpdl_ptr
- specpdl
;
2464 int beg
, end
, change
;
2468 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
2470 Fset_buffer (combine_after_change_buffer
);
2472 /* # chars unchanged at beginning of buffer. */
2474 /* # chars unchanged at end of buffer. */
2476 /* Total amount of insertion (negative for deletion). */
2479 /* Scan the various individual changes,
2480 accumulating the range info in BEG, END and CHANGE. */
2481 for (tail
= combine_after_change_list
; CONSP (tail
);
2482 tail
= XCONS (tail
)->cdr
)
2485 int thisbeg
, thisend
, thischange
;
2487 /* Extract the info from the next element. */
2488 elt
= XCONS (tail
)->car
;
2491 thisbeg
= XINT (XCONS (elt
)->car
);
2493 elt
= XCONS (elt
)->cdr
;
2496 thisend
= XINT (XCONS (elt
)->car
);
2498 elt
= XCONS (elt
)->cdr
;
2501 thischange
= XINT (XCONS (elt
)->car
);
2503 /* Merge this range into the accumulated range. */
2504 change
+= thischange
;
2511 /* Get the current start and end positions of the range
2512 that was changed. */
2516 /* We are about to handle these, so discard them. */
2517 combine_after_change_list
= Qnil
;
2519 /* Now run the after-change functions for real.
2520 Turn off the flag that defers them. */
2521 record_unwind_protect (Fcombine_after_change_execute_1
,
2522 Vcombine_after_change_calls
);
2523 signal_after_change (begpos
, endpos
- begpos
- change
, endpos
- begpos
);
2525 return unbind_to (count
, val
);
2531 staticpro (&combine_after_change_list
);
2532 combine_after_change_list
= Qnil
;
2534 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag
,
2535 "Non-nil means enable debugging checks for invalid marker positions.");
2536 check_markers_debug_flag
= 0;
2537 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls
,
2538 "Used internally by the `combine-after-change-calls' macro.");
2539 Vcombine_after_change_calls
= Qnil
;
2541 defsubr (&Scombine_after_change_execute
);