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"
34 #define min(x, y) ((x) < (y) ? (x) : (y))
36 static void insert_from_string_1
P_ ((Lisp_Object
, int, int, int, int, int, int));
37 static void insert_from_buffer_1 ();
38 static void gap_left
P_ ((int, int, int));
39 static void gap_right
P_ ((int, int));
40 static void adjust_markers_gap_motion
P_ ((int, int, int));
41 static void adjust_markers_for_insert
P_ ((int, int, int, int, int));
42 static void adjust_markers_for_delete
P_ ((int, int, int, int));
43 static void adjust_point
P_ ((int, int));
45 Lisp_Object
Fcombine_after_change_execute ();
47 /* Non-nil means don't call the after-change-functions right away,
48 just record an element in Vcombine_after_change_calls_list. */
49 Lisp_Object Vcombine_after_change_calls
;
51 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
52 describing changes which happened while combine_after_change_calls
53 was nonzero. We use this to decide how to call them
54 once the deferral ends.
57 BEG-UNCHANGED is the number of chars before the changed range.
58 END-UNCHANGED is the number of chars after the changed range,
59 and CHANGE-AMOUNT is the number of characters inserted by the change
60 (negative for a deletion). */
61 Lisp_Object combine_after_change_list
;
63 /* Buffer which combine_after_change_list is about. */
64 Lisp_Object combine_after_change_buffer
;
66 #define DEFAULT_NONASCII_INSERT_OFFSET 0x800
68 /* Move gap to position CHARPOS.
69 Note that this can quit! */
75 move_gap_both (charpos
, charpos_to_bytepos (charpos
));
78 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
79 Note that this can quit! */
82 move_gap_both (charpos
, bytepos
)
85 if (bytepos
< GPT_BYTE
)
86 gap_left (charpos
, bytepos
, 0);
87 else if (bytepos
> GPT_BYTE
)
88 gap_right (charpos
, bytepos
);
91 /* Move the gap to a position less than the current GPT.
92 BYTEPOS describes the new position as a byte position,
93 and CHARPOS is the corresponding char position.
94 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
97 gap_left (charpos
, bytepos
, newgap
)
98 register int charpos
, bytepos
;
101 register unsigned char *to
, *from
;
107 if (unchanged_modified
== MODIFF
108 && overlay_unchanged_modified
== OVERLAY_MODIFF
)
110 beg_unchanged
= charpos
- BEG
;
111 end_unchanged
= Z
- charpos
;
115 if (Z
- GPT
< end_unchanged
)
116 end_unchanged
= Z
- GPT
;
117 if (charpos
< beg_unchanged
)
118 beg_unchanged
= charpos
- BEG
;
127 /* Now copy the characters. To move the gap down,
128 copy characters up. */
132 /* I gets number of characters left to copy. */
133 i
= new_s1
- bytepos
;
136 /* If a quit is requested, stop copying now.
137 Change BYTEPOS to be where we have actually moved the gap to. */
141 charpos
= BYTE_TO_CHAR (bytepos
);
144 /* Move at most 32000 chars before checking again for a quit. */
149 /* bcopy is safe if the two areas of memory do not overlap
150 or on systems where bcopy is always safe for moving upward. */
151 && (BCOPY_UPWARD_SAFE
152 || to
- from
>= 128))
154 /* If overlap is not safe, avoid it by not moving too many
155 characters at once. */
156 if (!BCOPY_UPWARD_SAFE
&& i
> to
- from
)
171 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
172 BYTEPOS is where the loop above stopped, which may be what was specified
173 or may be where a quit was detected. */
174 adjust_markers_gap_motion (bytepos
, GPT_BYTE
, GAP_SIZE
);
177 if (bytepos
< charpos
)
179 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
183 /* Move the gap to a position greater than than the current GPT.
184 BYTEPOS describes the new position as a byte position,
185 and CHARPOS is the corresponding char position. */
188 gap_right (charpos
, bytepos
)
189 register int charpos
, bytepos
;
191 register unsigned char *to
, *from
;
195 if (unchanged_modified
== MODIFF
196 && overlay_unchanged_modified
== OVERLAY_MODIFF
)
198 beg_unchanged
= charpos
- BEG
;
199 end_unchanged
= Z
- charpos
;
203 if (Z
- charpos
- 1 < end_unchanged
)
204 end_unchanged
= Z
- charpos
;
205 if (GPT
- BEG
< beg_unchanged
)
206 beg_unchanged
= GPT
- BEG
;
214 /* Now copy the characters. To move the gap up,
215 copy characters down. */
219 /* I gets number of characters left to copy. */
220 i
= bytepos
- new_s1
;
223 /* If a quit is requested, stop copying now.
224 Change BYTEPOS to be where we have actually moved the gap to. */
228 charpos
= BYTE_TO_CHAR (bytepos
);
231 /* Move at most 32000 chars before checking again for a quit. */
236 /* bcopy is safe if the two areas of memory do not overlap
237 or on systems where bcopy is always safe for moving downward. */
238 && (BCOPY_DOWNWARD_SAFE
239 || from
- to
>= 128))
241 /* If overlap is not safe, avoid it by not moving too many
242 characters at once. */
243 if (!BCOPY_DOWNWARD_SAFE
&& i
> from
- to
)
258 adjust_markers_gap_motion (GPT_BYTE
+ GAP_SIZE
, bytepos
+ GAP_SIZE
,
262 if (bytepos
< charpos
)
264 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
268 /* Add AMOUNT to the byte position of every marker in the current buffer
269 whose current byte position is between FROM (exclusive) and TO (inclusive).
271 Also, any markers past the outside of that interval, in the direction
272 of adjustment, are first moved back to the near end of the interval
273 and then adjusted by AMOUNT.
275 When the latter adjustment is done, if AMOUNT is negative,
276 we record the adjustment for undo. (This case happens only for
279 The markers' character positions are not altered,
280 because gap motion does not affect character positions. */
282 int adjust_markers_test
;
285 adjust_markers_gap_motion (from
, to
, amount
)
286 register int from
, to
, amount
;
288 /* Now that a marker has a bytepos, not counting the gap,
289 nothing needs to be done here. */
292 register struct Lisp_Marker
*m
;
295 marker
= BUF_MARKERS (current_buffer
);
297 while (!NILP (marker
))
299 m
= XMARKER (marker
);
303 if (mpos
> to
&& mpos
< to
+ amount
)
305 if (adjust_markers_test
)
312 /* Here's the case where a marker is inside text being deleted.
313 AMOUNT can be negative for gap motion, too,
314 but then this range contains no markers. */
315 if (mpos
> from
+ amount
&& mpos
<= from
)
317 if (adjust_markers_test
)
319 mpos
= from
+ amount
;
322 if (mpos
> from
&& mpos
<= to
)
330 /* Adjust all markers for a deletion
331 whose range in bytes is FROM_BYTE to TO_BYTE.
332 The range in charpos is FROM to TO.
334 This function assumes that the gap is adjacent to
335 or inside of the range being deleted. */
338 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
)
339 register int from
, from_byte
, to
, to_byte
;
342 register struct Lisp_Marker
*m
;
343 register int charpos
;
344 /* This is what GAP_SIZE will be when this deletion is finished. */
345 int coming_gap_size
= GAP_SIZE
+ to_byte
- from_byte
;
347 marker
= BUF_MARKERS (current_buffer
);
349 while (!NILP (marker
))
351 m
= XMARKER (marker
);
352 charpos
= m
->charpos
;
357 /* If the marker is after the deletion,
358 relocate by number of chars / bytes deleted. */
361 m
->charpos
-= to
- from
;
362 m
->bytepos
-= to_byte
- from_byte
;
365 /* Here's the case where a marker is inside text being deleted. */
366 else if (charpos
> from
)
368 record_marker_adjustment (marker
, from
- charpos
);
370 m
->bytepos
= from_byte
;
373 /* In a single-byte buffer, a marker's two positions must be equal. */
376 register int i
= m
->bytepos
;
379 /* We use FROM_BYTE here instead of GPT_BYTE
380 because FROM_BYTE is where the gap will be after the deletion. */
381 if (i
> from_byte
+ coming_gap_size
)
382 i
-= coming_gap_size
;
383 else if (i
> from_byte
)
395 /* Adjust markers for an insertion at CHARPOS / BYTEPOS
396 consisting of NCHARS chars, which are NBYTES bytes.
398 We have to relocate the charpos of every marker that points
399 after the insertion (but not their bytepos).
401 When a marker points at the insertion point,
402 we advance it if either its insertion-type is t
403 or BEFORE_MARKERS is true. */
406 adjust_markers_for_insert (from
, from_byte
, to
, to_byte
, before_markers
)
407 register int from
, from_byte
, to
, to_byte
, before_markers
;
411 int nchars
= to
- from
;
412 int nbytes
= to_byte
- from_byte
;
414 marker
= BUF_MARKERS (current_buffer
);
416 while (!NILP (marker
))
418 register struct Lisp_Marker
*m
= XMARKER (marker
);
419 if (m
->bytepos
== from_byte
420 && (m
->insertion_type
|| before_markers
))
422 m
->bytepos
+= nbytes
;
423 m
->charpos
+= nchars
;
424 if (m
->insertion_type
)
427 else if (m
->bytepos
> from_byte
)
429 m
->bytepos
+= nbytes
;
430 m
->charpos
+= nchars
;
433 /* In a single-byte buffer, a marker's two positions must be equal. */
436 register int i
= m
->bytepos
;
439 if (i
> GPT_BYTE
+ GAP_SIZE
)
441 else if (i
> GPT_BYTE
)
452 /* Adjusting only markers whose insertion-type is t may result in
453 disordered overlays in the slot `overlays_before'. */
455 fix_overlays_before (current_buffer
, from
, to
);
458 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
460 This is used only when the value of point changes due to an insert
461 or delete; it does not represent a conceptual change in point as a
462 marker. In particular, point is not crossing any interval
463 boundaries, so there's no need to use the usual SET_PT macro. In
464 fact it would be incorrect to do so, because either the old or the
465 new value of point is out of sync with the current set of
469 adjust_point (nchars
, nbytes
)
472 BUF_PT (current_buffer
) += nchars
;
473 BUF_PT_BYTE (current_buffer
) += nbytes
;
475 /* In a single-byte buffer, the two positions must be equal. */
481 /* Make the gap NBYTES_ADDED bytes longer. */
484 make_gap (nbytes_added
)
487 unsigned char *result
;
490 int real_gap_loc_byte
;
493 /* If we have to get more space, get enough to last a while. */
494 nbytes_added
+= 2000;
496 /* Don't allow a buffer size that won't fit in an int
497 even if it will fit in a Lisp integer.
498 That won't work because so many places use `int'. */
500 if (Z_BYTE
- BEG_BYTE
+ GAP_SIZE
+ nbytes_added
501 >= ((unsigned) 1 << (min (BITS_PER_INT
, VALBITS
) - 1)))
502 error ("Buffer exceeds maximum size");
505 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
506 result
= BUFFER_REALLOC (BEG_ADDR
, (Z_BYTE
- BEG_BYTE
507 + GAP_SIZE
+ nbytes_added
+ 1));
515 /* We can't unblock until the new address is properly stored. */
519 /* Prevent quitting in move_gap. */
524 real_gap_loc_byte
= GPT_BYTE
;
525 old_gap_size
= GAP_SIZE
;
527 /* Call the newly allocated space a gap at the end of the whole space. */
529 GPT_BYTE
= Z_BYTE
+ GAP_SIZE
;
530 GAP_SIZE
= nbytes_added
;
532 /* Move the new gap down to be consecutive with the end of the old one.
533 This adjusts the markers properly too. */
534 gap_left (real_gap_loc
+ old_gap_size
, real_gap_loc_byte
+ old_gap_size
, 1);
536 /* Now combine the two into one large gap. */
537 GAP_SIZE
+= old_gap_size
;
539 GPT_BYTE
= real_gap_loc_byte
;
547 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
548 FROM_MULTIBYTE says whether the incoming text is multibyte.
549 TO_MULTIBYTE says whether to store the text as multibyte.
550 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
552 Return the number of bytes stored at TO_ADDR. */
555 copy_text (from_addr
, to_addr
, nbytes
,
556 from_multibyte
, to_multibyte
)
557 unsigned char *from_addr
;
558 unsigned char *to_addr
;
560 int from_multibyte
, to_multibyte
;
562 if (from_multibyte
== to_multibyte
)
564 bcopy (from_addr
, to_addr
, nbytes
);
567 else if (from_multibyte
)
570 int bytes_left
= nbytes
;
572 /* Convert multibyte to single byte. */
573 while (bytes_left
> 0)
576 c
= STRING_CHAR_AND_LENGTH (from_addr
, bytes_left
, thislen
);
577 *to_addr
++ = SINGLE_BYTE_CHAR_P (c
) ? c
: (c
& 0177) + 0200;
578 from_addr
+= thislen
;
586 unsigned char *initial_to_addr
= to_addr
;
588 /* Convert single-byte to multibyte. */
591 int c
= *from_addr
++;
592 unsigned char workbuf
[4], *str
;
595 if (c
>= 0200 && c
< 0400)
597 if (nonascii_insert_offset
> 0)
598 c
+= nonascii_insert_offset
;
600 c
+= DEFAULT_NONASCII_INSERT_OFFSET
;
602 len
= CHAR_STRING (c
, workbuf
, str
);
603 bcopy (str
, to_addr
, len
);
608 /* Special case for speed. */
609 *to_addr
++ = c
, nbytes
--;
611 return to_addr
- initial_to_addr
;
615 /* Return the number of bytes it would take
616 to convert some single-byte text to multibyte.
617 The single-byte text consists of NBYTES bytes at PTR. */
620 count_size_as_multibyte (ptr
, nbytes
)
625 int outgoing_nbytes
= 0;
627 for (i
= 0; i
< nbytes
; i
++)
629 unsigned int c
= *ptr
++;
630 if (c
>= 0200 && c
< 0400)
632 if (nonascii_insert_offset
> 0)
633 c
+= nonascii_insert_offset
;
635 c
+= DEFAULT_NONASCII_INSERT_OFFSET
;
637 outgoing_nbytes
+= XINT (Fchar_bytes (make_number (c
)));
640 return outgoing_nbytes
;
643 /* Insert a string of specified length before point.
644 This function judges multibyteness based on
645 enable_multibyte_characters in the current buffer;
646 it never converts between single-byte and multibyte.
648 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
649 prepare_to_modify_buffer could relocate the text. */
652 insert (string
, nbytes
)
653 register unsigned char *string
;
659 insert_1 (string
, nbytes
, 0, 1, 0);
660 signal_after_change (opoint
, 0, PT
- opoint
);
664 /* Likewise, but inherit text properties from neighboring characters. */
667 insert_and_inherit (string
, nbytes
)
668 register unsigned char *string
;
674 insert_1 (string
, nbytes
, 1, 1, 0);
675 signal_after_change (opoint
, 0, PT
- opoint
);
679 /* Insert the character C before point. Do not inherit text properties. */
685 unsigned char workbuf
[4], *str
;
688 if (! NILP (current_buffer
->enable_multibyte_characters
))
689 len
= CHAR_STRING (c
, workbuf
, str
);
700 /* Insert the null-terminated string S before point. */
706 insert (s
, strlen (s
));
709 /* Like `insert' except that all markers pointing at the place where
710 the insertion happens are adjusted to point after it.
711 Don't use this function to insert part of a Lisp string,
712 since gc could happen and relocate it. */
715 insert_before_markers (string
, nbytes
)
716 unsigned char *string
;
723 insert_1 (string
, nbytes
, 0, 1, 1);
724 signal_after_change (opoint
, 0, PT
- opoint
);
728 /* Likewise, but inherit text properties from neighboring characters. */
731 insert_before_markers_and_inherit (string
, nbytes
)
732 unsigned char *string
;
739 insert_1 (string
, nbytes
, 1, 1, 1);
740 signal_after_change (opoint
, 0, PT
- opoint
);
744 /* Subroutine used by the insert functions above. */
747 insert_1 (string
, nbytes
, inherit
, prepare
, before_markers
)
748 register unsigned char *string
;
750 int inherit
, prepare
, before_markers
;
752 register Lisp_Object temp
;
753 int nchars
= chars_in_text (string
, nbytes
);
756 prepare_to_modify_buffer (PT
, PT
, NULL
);
759 move_gap_both (PT
, PT_BYTE
);
760 if (GAP_SIZE
< nbytes
)
761 make_gap (nbytes
- GAP_SIZE
);
763 record_insert (PT
, nchars
);
766 bcopy (string
, GPT_ADDR
, nbytes
);
768 #ifdef USE_TEXT_PROPERTIES
769 if (BUF_INTERVALS (current_buffer
) != 0)
770 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
771 offset_intervals (current_buffer
, PT
, nchars
);
781 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
782 adjust_overlays_for_insert (PT
, nchars
);
783 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
, PT_BYTE
+ nbytes
,
785 adjust_point (nchars
, nbytes
);
790 #ifdef USE_TEXT_PROPERTIES
791 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
792 Fset_text_properties (make_number (PT
- nchars
), make_number (PT
),
797 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
798 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
799 are the same as in insert_1. */
802 insert_1_both (string
, nchars
, nbytes
, inherit
, prepare
, before_markers
)
803 register unsigned char *string
;
804 register int nchars
, nbytes
;
805 int inherit
, prepare
, before_markers
;
807 register Lisp_Object temp
;
810 prepare_to_modify_buffer (PT
, PT
, NULL
);
813 move_gap_both (PT
, PT_BYTE
);
814 if (GAP_SIZE
< nbytes
)
815 make_gap (nbytes
- GAP_SIZE
);
817 record_insert (PT
, nchars
);
820 bcopy (string
, GPT_ADDR
, nbytes
);
822 #ifdef USE_TEXT_PROPERTIES
823 if (BUF_INTERVALS (current_buffer
) != 0)
824 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
825 offset_intervals (current_buffer
, PT
, nchars
);
835 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
836 adjust_overlays_for_insert (PT
, nchars
);
837 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
, PT_BYTE
+ nbytes
,
839 adjust_point (nchars
, nbytes
);
844 #ifdef USE_TEXT_PROPERTIES
845 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
846 Fset_text_properties (make_number (PT
- nchars
), make_number (PT
),
851 /* Insert the part of the text of STRING, a Lisp object assumed to be
852 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
853 starting at position POS / POS_BYTE. If the text of STRING has properties,
854 copy them into the buffer.
856 It does not work to use `insert' for this, because a GC could happen
857 before we bcopy the stuff into the buffer, and relocate the string
858 without insert noticing. */
861 insert_from_string (string
, pos
, pos_byte
, length
, length_byte
, inherit
)
863 register int pos
, pos_byte
, length
, length_byte
;
869 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
871 signal_after_change (opoint
, 0, PT
- opoint
);
875 /* Like `insert_from_string' except that all markers pointing
876 at the place where the insertion happens are adjusted to point after it. */
879 insert_from_string_before_markers (string
, pos
, pos_byte
,
880 length
, length_byte
, inherit
)
882 register int pos
, pos_byte
, length
, length_byte
;
888 insert_from_string_1 (string
, pos
, pos_byte
, length
, length_byte
,
890 signal_after_change (opoint
, 0, PT
- opoint
);
894 /* Subroutine of the insertion functions above. */
897 insert_from_string_1 (string
, pos
, pos_byte
, nchars
, nbytes
,
898 inherit
, before_markers
)
900 register int pos
, pos_byte
, nchars
, nbytes
;
901 int inherit
, before_markers
;
903 register Lisp_Object temp
;
905 int outgoing_nbytes
= nbytes
;
907 /* Make OUTGOING_NBYTES describe the text
908 as it will be inserted in this buffer. */
910 if (NILP (current_buffer
->enable_multibyte_characters
))
911 outgoing_nbytes
= nchars
;
912 else if (nchars
== nbytes
)
914 = count_size_as_multibyte (&XSTRING (string
)->data
[pos_byte
],
917 /* Make sure point-max won't overflow after this insertion. */
918 XSETINT (temp
, outgoing_nbytes
+ Z
);
919 if (outgoing_nbytes
+ Z
!= XINT (temp
))
920 error ("Maximum buffer size exceeded");
923 prepare_to_modify_buffer (PT
, PT
, NULL
);
926 move_gap_both (PT
, PT_BYTE
);
927 if (GAP_SIZE
< nbytes
)
928 make_gap (outgoing_nbytes
- GAP_SIZE
);
930 record_insert (PT
, nchars
);
934 /* Copy the string text into the buffer, perhaps converting
935 between single-byte and multibyte. */
936 copy_text (XSTRING (string
)->data
+ pos_byte
, GPT_ADDR
, nbytes
,
937 /* If these are equal, it is a single-byte string.
938 Its chars are either ASCII, in which case copy_text
939 won't change it, or single-byte non-ASCII chars,
940 that need to be changed. */
942 ! NILP (current_buffer
->enable_multibyte_characters
));
944 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
945 offset_intervals (current_buffer
, PT
, nchars
);
947 GAP_SIZE
-= outgoing_nbytes
;
951 GPT_BYTE
+= outgoing_nbytes
;
952 ZV_BYTE
+= outgoing_nbytes
;
953 Z_BYTE
+= outgoing_nbytes
;
954 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
955 adjust_overlays_for_insert (PT
, nchars
);
956 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
957 PT_BYTE
+ outgoing_nbytes
,
963 graft_intervals_into_buffer (XSTRING (string
)->intervals
, PT
, nchars
,
964 current_buffer
, inherit
);
966 adjust_point (nchars
, outgoing_nbytes
);
969 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
970 current buffer. If the text in BUF has properties, they are absorbed
971 into the current buffer.
973 It does not work to use `insert' for this, because a malloc could happen
974 and relocate BUF's text before the bcopy happens. */
977 insert_from_buffer (buf
, charpos
, nchars
, inherit
)
986 insert_from_buffer_1 (buf
, charpos
, nchars
, inherit
);
987 signal_after_change (opoint
, 0, PT
- opoint
);
992 insert_from_buffer_1 (buf
, from
, nchars
, inherit
)
997 register Lisp_Object temp
;
999 int from_byte
= buf_charpos_to_bytepos (buf
, from
);
1000 int to_byte
= buf_charpos_to_bytepos (buf
, from
+ nchars
);
1001 int incoming_nbytes
= to_byte
- from_byte
;
1002 int outgoing_nbytes
= incoming_nbytes
;
1004 /* Make OUTGOING_NBYTES describe the text
1005 as it will be inserted in this buffer. */
1007 if (NILP (current_buffer
->enable_multibyte_characters
))
1008 outgoing_nbytes
= nchars
;
1009 else if (NILP (buf
->enable_multibyte_characters
))
1011 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf
, from_byte
),
1014 /* Make sure point-max won't overflow after this insertion. */
1015 XSETINT (temp
, outgoing_nbytes
+ Z
);
1016 if (outgoing_nbytes
+ Z
!= XINT (temp
))
1017 error ("Maximum buffer size exceeded");
1019 prepare_to_modify_buffer (PT
, PT
, NULL
);
1022 move_gap_both (PT
, PT_BYTE
);
1023 if (GAP_SIZE
< outgoing_nbytes
)
1024 make_gap (outgoing_nbytes
- GAP_SIZE
);
1026 record_insert (PT
, nchars
);
1029 if (from
< BUF_GPT (buf
))
1031 chunk
= BUF_GPT_BYTE (buf
) - from_byte
;
1032 if (chunk
> incoming_nbytes
)
1033 chunk
= incoming_nbytes
;
1034 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
),
1036 ! NILP (buf
->enable_multibyte_characters
),
1037 ! NILP (current_buffer
->enable_multibyte_characters
));
1041 if (chunk
< incoming_nbytes
)
1042 copy_text (BUF_BYTE_ADDRESS (buf
, from_byte
+ chunk
),
1043 GPT_ADDR
+ chunk
, incoming_nbytes
- chunk
,
1044 ! NILP (buf
->enable_multibyte_characters
),
1045 ! NILP (current_buffer
->enable_multibyte_characters
));
1047 #ifdef USE_TEXT_PROPERTIES
1048 if (BUF_INTERVALS (current_buffer
) != 0)
1049 offset_intervals (current_buffer
, PT
, nchars
);
1052 GAP_SIZE
-= outgoing_nbytes
;
1056 GPT_BYTE
+= outgoing_nbytes
;
1057 ZV_BYTE
+= outgoing_nbytes
;
1058 Z_BYTE
+= outgoing_nbytes
;
1059 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1060 adjust_overlays_for_insert (PT
, nchars
);
1061 adjust_markers_for_insert (PT
, PT_BYTE
, PT
+ nchars
,
1062 PT_BYTE
+ outgoing_nbytes
, 0);
1063 adjust_point (nchars
, outgoing_nbytes
);
1068 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1069 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf
),
1071 PT
- nchars
, nchars
,
1072 current_buffer
, inherit
);
1076 adjust_before_replace (from
, from_byte
, to
, to_byte
)
1077 int from
, from_byte
, to
, to_byte
;
1079 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1080 record_delete (from
, to
- from
);
1084 adjust_after_replace (from
, from_byte
, to
, to_byte
, len
, len_byte
)
1085 int from
, from_byte
, to
, to_byte
, len
, len_byte
;
1087 record_insert (from
, len
);
1089 adjust_point (len
, len_byte
);
1090 #ifdef USE_TEXT_PROPERTIES
1091 offset_intervals (current_buffer
, PT
, len
- (to
- from
));
1093 adjust_overlays_for_delete (from
, to
- from
);
1094 adjust_overlays_for_insert (from
, len
);
1095 adjust_markers_for_insert (from
, from_byte
,
1096 from
+ len
, from_byte
+ len_byte
, 0);
1098 evaporate_overlays (from
);
1100 signal_after_change (from
, to
- from
, len
);
1103 /* Replace the text from character positions FROM to TO with NEW,
1104 If PREPARE is nonzero, call prepare_to_modify_buffer.
1105 If INHERIT, the newly inserted text should inherit text properties
1106 from the surrounding non-deleted text. */
1108 /* Note that this does not yet handle markers quite right.
1109 Also it needs to record a single undo-entry that does a replacement
1110 rather than a separate delete and insert.
1111 That way, undo will also handle markers properly. */
1114 replace_range (from
, to
, new, prepare
, inherit
)
1116 int from
, to
, prepare
, inherit
;
1118 int inschars
= XSTRING (new)->size
;
1119 int insbytes
= XSTRING (new)->size_byte
;
1120 int from_byte
, to_byte
;
1121 int nbytes_del
, nchars_del
;
1122 register Lisp_Object temp
;
1123 struct gcpro gcpro1
;
1129 int range_length
= to
- from
;
1130 prepare_to_modify_buffer (from
, to
, &from
);
1131 to
= from
+ range_length
;
1136 /* Make args be valid */
1142 from_byte
= CHAR_TO_BYTE (from
);
1143 to_byte
= CHAR_TO_BYTE (to
);
1145 nchars_del
= to
- from
;
1146 nbytes_del
= to_byte
- from_byte
;
1148 if (nbytes_del
<= 0 && insbytes
== 0)
1151 /* Make sure point-max won't overflow after this insertion. */
1152 XSETINT (temp
, Z_BYTE
- nbytes_del
+ insbytes
);
1153 if (Z_BYTE
- nbytes_del
+ insbytes
!= XINT (temp
))
1154 error ("Maximum buffer size exceeded");
1158 /* Make sure the gap is somewhere in or next to what we are deleting. */
1160 gap_right (from
, from_byte
);
1162 gap_left (to
, to_byte
, 0);
1164 /* Relocate all markers pointing into the new, larger gap
1165 to point at the end of the text before the gap.
1166 Do this before recording the deletion,
1167 so that undo handles this after reinserting the text. */
1168 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1170 record_delete (from
, nchars_del
);
1172 GAP_SIZE
+= nbytes_del
;
1175 ZV_BYTE
-= nbytes_del
;
1176 Z_BYTE
-= nbytes_del
;
1178 GPT_BYTE
= from_byte
;
1179 *(GPT_ADDR
) = 0; /* Put an anchor. */
1184 if (GPT
- BEG
< beg_unchanged
)
1185 beg_unchanged
= GPT
- BEG
;
1186 if (Z
- GPT
< end_unchanged
)
1187 end_unchanged
= Z
- GPT
;
1189 if (GAP_SIZE
< insbytes
)
1190 make_gap (insbytes
- GAP_SIZE
);
1192 record_insert (from
, inschars
);
1194 bcopy (XSTRING (new)->data
, GPT_ADDR
, insbytes
);
1196 /* Relocate point as if it were a marker. */
1198 adjust_point (from
+ inschars
- (PT
< to
? PT
: to
),
1199 (from_byte
+ insbytes
1200 - (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
)));
1202 #ifdef USE_TEXT_PROPERTIES
1203 offset_intervals (current_buffer
, PT
, inschars
- nchars_del
);
1206 GAP_SIZE
-= insbytes
;
1210 GPT_BYTE
+= insbytes
;
1211 ZV_BYTE
+= insbytes
;
1212 ZV_BYTE
+= insbytes
;
1213 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
1218 /* Adjust the overlay center as needed. This must be done after
1219 adjusting the markers that bound the overlays. */
1220 adjust_overlays_for_delete (from
, nchars_del
);
1221 adjust_overlays_for_insert (from
, inschars
);
1222 adjust_markers_for_insert (from
, from_byte
, from
+ inschars
,
1223 from_byte
+ insbytes
, 0);
1225 #ifdef USE_TEXT_PROPERTIES
1226 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1227 graft_intervals_into_buffer (XSTRING (new)->intervals
, from
,
1228 inschars
, current_buffer
, inherit
);
1232 evaporate_overlays (from
);
1237 signal_after_change (from
, nchars_del
, inschars
);
1240 /* Delete characters in current buffer
1241 from FROM up to (but not including) TO.
1242 If TO comes before FROM, we delete nothing. */
1245 del_range (from
, to
)
1246 register int from
, to
;
1248 del_range_1 (from
, to
, 1);
1251 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
1254 del_range_1 (from
, to
, prepare
)
1255 int from
, to
, prepare
;
1257 int from_byte
, to_byte
;
1259 /* Make args be valid */
1270 int range_length
= to
- from
;
1271 prepare_to_modify_buffer (from
, to
, &from
);
1272 to
= from
+ range_length
;
1275 from_byte
= CHAR_TO_BYTE (from
);
1276 to_byte
= CHAR_TO_BYTE (to
);
1278 del_range_2 (from
, to
, from_byte
, to_byte
);
1281 /* Like del_range_1 but args are byte positions, not char positions. */
1284 del_range_byte (from_byte
, to_byte
, prepare
)
1285 int from_byte
, to_byte
, prepare
;
1289 /* Make args be valid */
1290 if (from_byte
< BEGV_BYTE
)
1291 from_byte
= BEGV_BYTE
;
1292 if (to_byte
> ZV_BYTE
)
1295 if (to_byte
<= from_byte
)
1298 from
= BYTE_TO_CHAR (from_byte
);
1299 to
= BYTE_TO_CHAR (to_byte
);
1303 int old_from
= from
, old_to
= Z
- to
;
1304 int range_length
= to
- from
;
1305 prepare_to_modify_buffer (from
, to
, &from
);
1306 to
= from
+ range_length
;
1308 if (old_from
!= from
)
1309 from_byte
= CHAR_TO_BYTE (from
);
1310 if (old_to
== Z
- to
)
1311 to_byte
= CHAR_TO_BYTE (to
);
1314 del_range_2 (from
, to
, from_byte
, to_byte
);
1317 /* Like del_range_1, but positions are specified both as charpos
1321 del_range_both (from
, to
, from_byte
, to_byte
, prepare
)
1322 int from
, to
, from_byte
, to_byte
, prepare
;
1324 /* Make args be valid */
1325 if (from_byte
< BEGV_BYTE
)
1326 from_byte
= BEGV_BYTE
;
1327 if (to_byte
> ZV_BYTE
)
1330 if (to_byte
<= from_byte
)
1340 int old_from
= from
, old_to
= Z
- to
;
1341 int range_length
= to
- from
;
1342 prepare_to_modify_buffer (from
, to
, &from
);
1343 to
= from
+ range_length
;
1345 if (old_from
!= from
)
1346 from_byte
= CHAR_TO_BYTE (from
);
1347 if (old_to
== Z
- to
)
1348 to_byte
= CHAR_TO_BYTE (to
);
1351 del_range_2 (from
, to
, from_byte
, to_byte
);
1354 /* Delete a range of text, specified both as character positions
1355 and byte positions. FROM and TO are character positions,
1356 while FROM_BYTE and TO_BYTE are byte positions. */
1359 del_range_2 (from
, to
, from_byte
, to_byte
)
1360 int from
, to
, from_byte
, to_byte
;
1362 register int nbytes_del
, nchars_del
;
1364 nchars_del
= to
- from
;
1365 nbytes_del
= to_byte
- from_byte
;
1367 /* Make sure the gap is somewhere in or next to what we are deleting. */
1369 gap_right (from
, from_byte
);
1371 gap_left (to
, to_byte
, 0);
1373 /* Relocate all markers pointing into the new, larger gap
1374 to point at the end of the text before the gap.
1375 Do this before recording the deletion,
1376 so that undo handles this after reinserting the text. */
1377 adjust_markers_for_delete (from
, from_byte
, to
, to_byte
);
1379 record_delete (from
, nchars_del
);
1382 /* Relocate point as if it were a marker. */
1384 adjust_point (from
- (PT
< to
? PT
: to
),
1385 from_byte
- (PT_BYTE
< to_byte
? PT_BYTE
: to_byte
));
1387 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1388 offset_intervals (current_buffer
, from
, - nchars_del
);
1390 /* Adjust the overlay center as needed. This must be done after
1391 adjusting the markers that bound the overlays. */
1392 adjust_overlays_for_delete (from_byte
, nchars_del
);
1394 GAP_SIZE
+= nbytes_del
;
1395 ZV_BYTE
-= nbytes_del
;
1396 Z_BYTE
-= nbytes_del
;
1400 GPT_BYTE
= from_byte
;
1401 *(GPT_ADDR
) = 0; /* Put an anchor. */
1406 if (GPT
- BEG
< beg_unchanged
)
1407 beg_unchanged
= GPT
- BEG
;
1408 if (Z
- GPT
< end_unchanged
)
1409 end_unchanged
= Z
- GPT
;
1411 evaporate_overlays (from
);
1412 signal_after_change (from
, nchars_del
, 0);
1415 /* Call this if you're about to change the region of BUFFER from
1416 character positions START to END. This checks the read-only
1417 properties of the region, calls the necessary modification hooks,
1418 and warns the next redisplay that it should pay attention to that
1422 modify_region (buffer
, start
, end
)
1423 struct buffer
*buffer
;
1426 struct buffer
*old_buffer
= current_buffer
;
1428 if (buffer
!= old_buffer
)
1429 set_buffer_internal (buffer
);
1431 prepare_to_modify_buffer (start
, end
, NULL
);
1433 if (start
- 1 < beg_unchanged
1434 || (unchanged_modified
== MODIFF
1435 && overlay_unchanged_modified
== OVERLAY_MODIFF
))
1436 beg_unchanged
= start
- 1;
1437 if (Z
- end
< end_unchanged
1438 || (unchanged_modified
== MODIFF
1439 && overlay_unchanged_modified
== OVERLAY_MODIFF
))
1440 end_unchanged
= Z
- end
;
1442 if (MODIFF
<= SAVE_MODIFF
)
1443 record_first_change ();
1446 buffer
->point_before_scroll
= Qnil
;
1448 if (buffer
!= old_buffer
)
1449 set_buffer_internal (old_buffer
);
1452 /* Check that it is okay to modify the buffer between START and END,
1453 which are char positions.
1455 Run the before-change-function, if any. If intervals are in use,
1456 verify that the text to be modified is not read-only, and call
1457 any modification properties the text may have.
1459 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1460 by holding its value temporarily in a marker. */
1463 prepare_to_modify_buffer (start
, end
, preserve_ptr
)
1467 if (!NILP (current_buffer
->read_only
))
1468 Fbarf_if_buffer_read_only ();
1470 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1471 if (BUF_INTERVALS (current_buffer
) != 0)
1475 Lisp_Object preserve_marker
;
1476 struct gcpro gcpro1
;
1477 preserve_marker
= Fcopy_marker (make_number (*preserve_ptr
), Qnil
);
1478 GCPRO1 (preserve_marker
);
1479 verify_interval_modification (current_buffer
, start
, end
);
1480 *preserve_ptr
= marker_position (preserve_marker
);
1481 unchain_marker (preserve_marker
);
1485 verify_interval_modification (current_buffer
, start
, end
);
1488 #ifdef CLASH_DETECTION
1489 if (!NILP (current_buffer
->file_truename
)
1490 /* Make binding buffer-file-name to nil effective. */
1491 && !NILP (current_buffer
->filename
)
1492 && SAVE_MODIFF
>= MODIFF
)
1493 lock_file (current_buffer
->file_truename
);
1495 /* At least warn if this file has changed on disk since it was visited. */
1496 if (!NILP (current_buffer
->filename
)
1497 && SAVE_MODIFF
>= MODIFF
1498 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1499 && !NILP (Ffile_exists_p (current_buffer
->filename
)))
1500 call1 (intern ("ask-user-about-supersession-threat"),
1501 current_buffer
->filename
);
1502 #endif /* not CLASH_DETECTION */
1504 signal_before_change (start
, end
, preserve_ptr
);
1506 if (current_buffer
->newline_cache
)
1507 invalidate_region_cache (current_buffer
,
1508 current_buffer
->newline_cache
,
1509 start
- BEG
, Z
- end
);
1510 if (current_buffer
->width_run_cache
)
1511 invalidate_region_cache (current_buffer
,
1512 current_buffer
->width_run_cache
,
1513 start
- BEG
, Z
- end
);
1515 Vdeactivate_mark
= Qt
;
1518 /* These macros work with an argument named `preserve_ptr'
1519 and a local variable named `preserve_marker'. */
1521 #define PRESERVE_VALUE \
1522 if (preserve_ptr && NILP (preserve_marker)) \
1523 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1525 #define RESTORE_VALUE \
1526 if (! NILP (preserve_marker)) \
1528 *preserve_ptr = marker_position (preserve_marker); \
1529 unchain_marker (preserve_marker); \
1532 #define PRESERVE_START_END \
1533 if (NILP (start_marker)) \
1534 start_marker = Fcopy_marker (start, Qnil); \
1535 if (NILP (end_marker)) \
1536 end_marker = Fcopy_marker (end, Qnil);
1538 #define FETCH_START \
1539 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1542 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1544 /* Signal a change to the buffer immediately before it happens.
1545 START_INT and END_INT are the bounds of the text to be changed.
1547 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1548 by holding its value temporarily in a marker. */
1551 signal_before_change (start_int
, end_int
, preserve_ptr
)
1552 int start_int
, end_int
;
1555 Lisp_Object start
, end
;
1556 Lisp_Object start_marker
, end_marker
;
1557 Lisp_Object preserve_marker
;
1558 struct gcpro gcpro1
, gcpro2
, gcpro3
;
1560 start
= make_number (start_int
);
1561 end
= make_number (end_int
);
1562 preserve_marker
= Qnil
;
1563 start_marker
= Qnil
;
1565 GCPRO3 (preserve_marker
, start_marker
, end_marker
);
1567 /* If buffer is unmodified, run a special hook for that case. */
1568 if (SAVE_MODIFF
>= MODIFF
1569 && !NILP (Vfirst_change_hook
)
1570 && !NILP (Vrun_hooks
))
1574 call1 (Vrun_hooks
, Qfirst_change_hook
);
1577 /* Run the before-change-function if any.
1578 We don't bother "binding" this variable to nil
1579 because it is obsolete anyway and new code should not use it. */
1580 if (!NILP (Vbefore_change_function
))
1584 call2 (Vbefore_change_function
, FETCH_START
, FETCH_END
);
1587 /* Now run the before-change-functions if any. */
1588 if (!NILP (Vbefore_change_functions
))
1590 Lisp_Object args
[3];
1591 Lisp_Object before_change_functions
;
1592 Lisp_Object after_change_functions
;
1593 struct gcpro gcpro1
, gcpro2
;
1598 /* "Bind" before-change-functions and after-change-functions
1599 to nil--but in a way that errors don't know about.
1600 That way, if there's an error in them, they will stay nil. */
1601 before_change_functions
= Vbefore_change_functions
;
1602 after_change_functions
= Vafter_change_functions
;
1603 Vbefore_change_functions
= Qnil
;
1604 Vafter_change_functions
= Qnil
;
1605 GCPRO2 (before_change_functions
, after_change_functions
);
1607 /* Actually run the hook functions. */
1608 args
[0] = Qbefore_change_functions
;
1609 args
[1] = FETCH_START
;
1610 args
[2] = FETCH_END
;
1611 run_hook_list_with_args (before_change_functions
, 3, args
);
1613 /* "Unbind" the variables we "bound" to nil. */
1614 Vbefore_change_functions
= before_change_functions
;
1615 Vafter_change_functions
= after_change_functions
;
1619 if (!NILP (current_buffer
->overlays_before
)
1620 || !NILP (current_buffer
->overlays_after
))
1623 report_overlay_modification (FETCH_START
, FETCH_END
, 0,
1624 FETCH_START
, FETCH_END
, Qnil
);
1627 if (! NILP (start_marker
))
1628 free_marker (start_marker
);
1629 if (! NILP (end_marker
))
1630 free_marker (end_marker
);
1635 /* Signal a change immediately after it happens.
1636 CHARPOS is the character position of the start of the changed text.
1637 LENDEL is the number of characters of the text before the change.
1638 (Not the whole buffer; just the part that was changed.)
1639 LENINS is the number of characters in that part of the text
1640 after the change. */
1643 signal_after_change (charpos
, lendel
, lenins
)
1644 int charpos
, lendel
, lenins
;
1646 /* If we are deferring calls to the after-change functions
1647 and there are no before-change functions,
1648 just record the args that we were going to use. */
1649 if (! NILP (Vcombine_after_change_calls
)
1650 && NILP (Vbefore_change_function
) && NILP (Vbefore_change_functions
)
1651 && NILP (current_buffer
->overlays_before
)
1652 && NILP (current_buffer
->overlays_after
))
1656 if (!NILP (combine_after_change_list
)
1657 && current_buffer
!= XBUFFER (combine_after_change_buffer
))
1658 Fcombine_after_change_execute ();
1660 elt
= Fcons (make_number (charpos
- BEG
),
1661 Fcons (make_number (Z
- (charpos
- lendel
+ lenins
)),
1662 Fcons (make_number (lenins
- lendel
), Qnil
)));
1663 combine_after_change_list
1664 = Fcons (elt
, combine_after_change_list
);
1665 combine_after_change_buffer
= Fcurrent_buffer ();
1670 if (!NILP (combine_after_change_list
))
1671 Fcombine_after_change_execute ();
1673 /* Run the after-change-function if any.
1674 We don't bother "binding" this variable to nil
1675 because it is obsolete anyway and new code should not use it. */
1676 if (!NILP (Vafter_change_function
))
1677 call3 (Vafter_change_function
,
1678 make_number (charpos
), make_number (charpos
+ lenins
),
1679 make_number (lendel
));
1681 if (!NILP (Vafter_change_functions
))
1683 Lisp_Object args
[4];
1684 Lisp_Object before_change_functions
;
1685 Lisp_Object after_change_functions
;
1686 struct gcpro gcpro1
, gcpro2
;
1688 /* "Bind" before-change-functions and after-change-functions
1689 to nil--but in a way that errors don't know about.
1690 That way, if there's an error in them, they will stay nil. */
1691 before_change_functions
= Vbefore_change_functions
;
1692 after_change_functions
= Vafter_change_functions
;
1693 Vbefore_change_functions
= Qnil
;
1694 Vafter_change_functions
= Qnil
;
1695 GCPRO2 (before_change_functions
, after_change_functions
);
1697 /* Actually run the hook functions. */
1698 args
[0] = Qafter_change_functions
;
1699 XSETFASTINT (args
[1], charpos
);
1700 XSETFASTINT (args
[2], charpos
+ lenins
);
1701 XSETFASTINT (args
[3], lendel
);
1702 run_hook_list_with_args (after_change_functions
,
1705 /* "Unbind" the variables we "bound" to nil. */
1706 Vbefore_change_functions
= before_change_functions
;
1707 Vafter_change_functions
= after_change_functions
;
1711 if (!NILP (current_buffer
->overlays_before
)
1712 || !NILP (current_buffer
->overlays_after
))
1713 report_overlay_modification (make_number (charpos
),
1714 make_number (charpos
+ lenins
),
1716 make_number (charpos
),
1717 make_number (charpos
+ lenins
),
1718 make_number (lendel
));
1720 /* After an insertion, call the text properties
1721 insert-behind-hooks or insert-in-front-hooks. */
1723 report_interval_modification (charpos
, charpos
+ lenins
);
1727 Fcombine_after_change_execute_1 (val
)
1730 Vcombine_after_change_calls
= val
;
1734 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute
,
1735 Scombine_after_change_execute
, 0, 0, 0,
1736 "This function is for use internally in `combine-after-change-calls'.")
1739 register Lisp_Object val
;
1740 int count
= specpdl_ptr
- specpdl
;
1741 int beg
, end
, change
;
1745 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
1747 Fset_buffer (combine_after_change_buffer
);
1749 /* # chars unchanged at beginning of buffer. */
1751 /* # chars unchanged at end of buffer. */
1753 /* Total amount of insertion (negative for deletion). */
1756 /* Scan the various individual changes,
1757 accumulating the range info in BEG, END and CHANGE. */
1758 for (tail
= combine_after_change_list
; CONSP (tail
);
1759 tail
= XCONS (tail
)->cdr
)
1762 int thisbeg
, thisend
, thischange
;
1764 /* Extract the info from the next element. */
1765 elt
= XCONS (tail
)->car
;
1768 thisbeg
= XINT (XCONS (elt
)->car
);
1770 elt
= XCONS (elt
)->cdr
;
1773 thisend
= XINT (XCONS (elt
)->car
);
1775 elt
= XCONS (elt
)->cdr
;
1778 thischange
= XINT (XCONS (elt
)->car
);
1780 /* Merge this range into the accumulated range. */
1781 change
+= thischange
;
1788 /* Get the current start and end positions of the range
1789 that was changed. */
1793 /* We are about to handle these, so discard them. */
1794 combine_after_change_list
= Qnil
;
1796 /* Now run the after-change functions for real.
1797 Turn off the flag that defers them. */
1798 record_unwind_protect (Fcombine_after_change_execute_1
,
1799 Vcombine_after_change_calls
);
1800 signal_after_change (begpos
, endpos
- begpos
- change
, endpos
- begpos
);
1802 return unbind_to (count
, val
);
1807 staticpro (&combine_after_change_list
);
1808 combine_after_change_list
= Qnil
;
1810 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls
,
1811 "Used internally by the `combine-after-change-calls' macro.");
1812 Vcombine_after_change_calls
= Qnil
;
1814 defsubr (&Scombine_after_change_execute
);