1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 1986, 1993, 1994, 1995 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"
30 #define min(x, y) ((x) < (y) ? (x) : (y))
32 static void insert_from_string_1 ();
33 static void insert_from_buffer_1 ();
34 static void gap_left ();
35 static void gap_right ();
36 static void adjust_markers ();
37 static void adjust_point ();
39 Lisp_Object
Fcombine_after_change_execute ();
41 /* Non-nil means don't call the after-change-functions right away,
42 just record an element in Vcombine_after_change_calls_list. */
43 Lisp_Object Vcombine_after_change_calls
;
45 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
46 describing changes which happened while combine_after_change_calls
47 was nonzero. We use this to decide how to call them
48 once the deferral ends.
51 BEG-UNCHANGED is the number of chars before the changed range.
52 END-UNCHANGED is the number of chars after the changed range,
53 and CHANGE-AMOUNT is the number of characters inserted by the change
54 (negative for a deletion). */
55 Lisp_Object combine_after_change_list
;
57 /* Buffer which combine_after_change_list is about. */
58 Lisp_Object combine_after_change_buffer
;
60 /* Move gap to position `pos'.
61 Note that this can quit! */
73 /* Move the gap to POS, which is less than the current GPT.
74 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
77 gap_left (pos
, newgap
)
81 register unsigned char *to
, *from
;
89 if (unchanged_modified
== MODIFF
90 && overlay_unchanged_modified
== OVERLAY_MODIFF
)
93 end_unchanged
= Z
- pos
- 1;
97 if (Z
- GPT
< end_unchanged
)
98 end_unchanged
= Z
- GPT
;
99 if (pos
< beg_unchanged
)
109 /* Now copy the characters. To move the gap down,
110 copy characters up. */
114 /* I gets number of characters left to copy. */
118 /* If a quit is requested, stop copying now.
119 Change POS to be where we have actually moved the gap to. */
125 /* Move at most 32000 chars before checking again for a quit. */
130 /* bcopy is safe if the two areas of memory do not overlap
131 or on systems where bcopy is always safe for moving upward. */
132 && (BCOPY_UPWARD_SAFE
133 || to
- from
>= 128))
135 /* If overlap is not safe, avoid it by not moving too many
136 characters at once. */
137 if (!BCOPY_UPWARD_SAFE
&& i
> to
- from
)
152 /* Adjust markers, and buffer data structure, to put the gap at POS.
153 POS is where the loop above stopped, which may be what was specified
154 or may be where a quit was detected. */
155 adjust_markers (pos
+ 1, GPT
, GAP_SIZE
);
157 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
165 register unsigned char *to
, *from
;
171 if (unchanged_modified
== MODIFF
172 && overlay_unchanged_modified
== OVERLAY_MODIFF
)
176 end_unchanged
= Z
- pos
- 1;
180 if (Z
- pos
- 1 < end_unchanged
)
181 end_unchanged
= Z
- pos
- 1;
182 if (GPT
- BEG
< beg_unchanged
)
183 beg_unchanged
= GPT
- BEG
;
191 /* Now copy the characters. To move the gap up,
192 copy characters down. */
196 /* I gets number of characters left to copy. */
200 /* If a quit is requested, stop copying now.
201 Change POS to be where we have actually moved the gap to. */
207 /* Move at most 32000 chars before checking again for a quit. */
212 /* bcopy is safe if the two areas of memory do not overlap
213 or on systems where bcopy is always safe for moving downward. */
214 && (BCOPY_DOWNWARD_SAFE
215 || from
- to
>= 128))
217 /* If overlap is not safe, avoid it by not moving too many
218 characters at once. */
219 if (!BCOPY_DOWNWARD_SAFE
&& i
> from
- to
)
234 adjust_markers (GPT
+ GAP_SIZE
, pos
+ 1 + GAP_SIZE
, - GAP_SIZE
);
236 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
240 /* Add AMOUNT to the position of every marker in the current buffer
241 whose current position is between FROM (exclusive) and TO (inclusive).
243 Also, any markers past the outside of that interval, in the direction
244 of adjustment, are first moved back to the near end of the interval
245 and then adjusted by AMOUNT.
247 When the latter adjustment is done, if AMOUNT is negative,
248 we record the adjustment for undo. (This case happens only for
252 adjust_markers (from
, to
, amount
)
253 register int from
, to
, amount
;
256 register struct Lisp_Marker
*m
;
259 marker
= BUF_MARKERS (current_buffer
);
261 while (!NILP (marker
))
263 m
= XMARKER (marker
);
267 if (mpos
> to
&& mpos
< to
+ amount
)
272 /* Here's the case where a marker is inside text being deleted.
273 AMOUNT can be negative for gap motion, too,
274 but then this range contains no markers. */
275 if (mpos
> from
+ amount
&& mpos
<= from
)
277 record_marker_adjustment (marker
, from
+ amount
- mpos
);
278 mpos
= from
+ amount
;
281 if (mpos
> from
&& mpos
<= to
)
288 /* Adjust markers whose insertion-type is t
289 for an insertion of AMOUNT characters at POS. */
292 adjust_markers_for_insert (pos
, amount
)
293 register int pos
, amount
;
298 marker
= BUF_MARKERS (current_buffer
);
300 while (!NILP (marker
))
302 register struct Lisp_Marker
*m
= XMARKER (marker
);
303 if (m
->insertion_type
&& m
->bufpos
== pos
)
311 /* Adjusting only markers whose insertion-type is t may result in
312 disordered overlays in the slot `overlays_before'. */
313 fix_overlays_before (current_buffer
, pos
, pos
+ amount
);
316 /* Add the specified amount to point. This is used only when the value
317 of point changes due to an insert or delete; it does not represent
318 a conceptual change in point as a marker. In particular, point is
319 not crossing any interval boundaries, so there's no need to use the
320 usual SET_PT macro. In fact it would be incorrect to do so, because
321 either the old or the new value of point is out of sync with the
322 current set of intervals. */
324 adjust_point (amount
)
327 BUF_PT (current_buffer
) += amount
;
330 /* Make the gap INCREMENT characters longer. */
336 unsigned char *result
;
341 /* If we have to get more space, get enough to last a while. */
344 /* Don't allow a buffer size that won't fit in an int
345 even if it will fit in a Lisp integer.
346 That won't work because so many places use `int'. */
348 if (Z
- BEG
+ GAP_SIZE
+ increment
349 >= ((unsigned) 1 << (min (BITS_PER_INT
, VALBITS
) - 1)))
350 error ("Buffer exceeds maximum size");
353 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
354 result
= BUFFER_REALLOC (BEG_ADDR
, (Z
- BEG
+ GAP_SIZE
+ increment
+ 1));
362 /* We can't unblock until the new address is properly stored. */
366 /* Prevent quitting in move_gap. */
371 old_gap_size
= GAP_SIZE
;
373 /* Call the newly allocated space a gap at the end of the whole space. */
375 GAP_SIZE
= increment
;
377 /* Move the new gap down to be consecutive with the end of the old one.
378 This adjusts the markers properly too. */
379 gap_left (real_gap_loc
+ old_gap_size
, 1);
381 /* Now combine the two into one large gap. */
382 GAP_SIZE
+= old_gap_size
;
391 /* Insert a string of specified length before point.
392 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
393 prepare_to_modify_buffer could relocate the text. */
396 insert (string
, length
)
397 register unsigned char *string
;
402 insert_1 (string
, length
, 0, 1);
403 signal_after_change (PT
-length
, 0, length
);
408 insert_and_inherit (string
, length
)
409 register unsigned char *string
;
414 insert_1 (string
, length
, 1, 1);
415 signal_after_change (PT
-length
, 0, length
);
420 insert_1 (string
, length
, inherit
, prepare
)
421 register unsigned char *string
;
423 int inherit
, prepare
;
425 register Lisp_Object temp
;
428 prepare_to_modify_buffer (PT
, PT
);
432 if (GAP_SIZE
< length
)
433 make_gap (length
- GAP_SIZE
);
435 record_insert (PT
, length
);
438 bcopy (string
, GPT_ADDR
, length
);
440 #ifdef USE_TEXT_PROPERTIES
441 if (BUF_INTERVALS (current_buffer
) != 0)
442 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
443 offset_intervals (current_buffer
, PT
, length
);
450 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
451 adjust_overlays_for_insert (PT
, length
);
452 adjust_markers_for_insert (PT
, length
);
453 adjust_point (length
);
455 #ifdef USE_TEXT_PROPERTIES
456 if (!inherit
&& BUF_INTERVALS (current_buffer
) != 0)
457 Fset_text_properties (make_number (PT
- length
), make_number (PT
),
462 /* Insert the part of the text of STRING, a Lisp object assumed to be
463 of type string, consisting of the LENGTH characters starting at
464 position POS. If the text of STRING has properties, they are absorbed
467 It does not work to use `insert' for this, because a GC could happen
468 before we bcopy the stuff into the buffer, and relocate the string
469 without insert noticing. */
472 insert_from_string (string
, pos
, length
, inherit
)
474 register int pos
, length
;
479 insert_from_string_1 (string
, pos
, length
, inherit
);
480 signal_after_change (PT
-length
, 0, length
);
485 insert_from_string_1 (string
, pos
, length
, inherit
)
487 register int pos
, length
;
490 register Lisp_Object temp
;
493 /* Make sure point-max won't overflow after this insertion. */
494 XSETINT (temp
, length
+ Z
);
495 if (length
+ Z
!= XINT (temp
))
496 error ("maximum buffer size exceeded");
499 prepare_to_modify_buffer (PT
, PT
);
503 if (GAP_SIZE
< length
)
504 make_gap (length
- GAP_SIZE
);
506 record_insert (PT
, length
);
510 bcopy (XSTRING (string
)->data
, GPT_ADDR
, length
);
512 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
513 offset_intervals (current_buffer
, PT
, length
);
519 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
520 adjust_overlays_for_insert (PT
, length
);
521 adjust_markers_for_insert (PT
, length
);
523 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
524 graft_intervals_into_buffer (XSTRING (string
)->intervals
, PT
, length
,
525 current_buffer
, inherit
);
527 adjust_point (length
);
530 /* Insert text from BUF, starting at POS and having length LENGTH, into the
531 current buffer. If the text in BUF has properties, they are absorbed
532 into the current buffer.
534 It does not work to use `insert' for this, because a malloc could happen
535 and relocate BUF's text before the bcopy happens. */
538 insert_from_buffer (buf
, pos
, length
, inherit
)
545 insert_from_buffer_1 (buf
, pos
, length
, inherit
);
546 signal_after_change (PT
-length
, 0, length
);
551 insert_from_buffer_1 (buf
, pos
, length
, inherit
)
556 register Lisp_Object temp
;
559 /* Make sure point-max won't overflow after this insertion. */
560 XSETINT (temp
, length
+ Z
);
561 if (length
+ Z
!= XINT (temp
))
562 error ("maximum buffer size exceeded");
564 prepare_to_modify_buffer (PT
, PT
);
568 if (GAP_SIZE
< length
)
569 make_gap (length
- GAP_SIZE
);
571 record_insert (PT
, length
);
574 if (pos
< BUF_GPT (buf
))
576 chunk
= BUF_GPT (buf
) - pos
;
579 bcopy (BUF_CHAR_ADDRESS (buf
, pos
), GPT_ADDR
, chunk
);
584 bcopy (BUF_CHAR_ADDRESS (buf
, pos
+ chunk
),
585 GPT_ADDR
+ chunk
, length
- chunk
);
587 #ifdef USE_TEXT_PROPERTIES
588 if (BUF_INTERVALS (current_buffer
) != 0)
589 offset_intervals (current_buffer
, PT
, length
);
596 if (GAP_SIZE
> 0) *(GPT_ADDR
) = 0; /* Put an anchor. */
597 adjust_overlays_for_insert (PT
, length
);
598 adjust_markers_for_insert (PT
, length
);
599 adjust_point (length
);
601 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
602 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf
),
604 PT
- length
, length
, current_buffer
, inherit
);
607 /* Insert the character C before point */
613 unsigned char workbuf
[4], *str
;
614 int len
= CHAR_STRING (c
, workbuf
, str
);
619 /* Insert the null-terminated string S before point */
625 insert (s
, strlen (s
));
628 /* Like `insert' except that all markers pointing at the place where
629 the insertion happens are adjusted to point after it.
630 Don't use this function to insert part of a Lisp string,
631 since gc could happen and relocate it. */
634 insert_before_markers (string
, length
)
635 unsigned char *string
;
640 register int opoint
= PT
;
641 insert_1 (string
, length
, 0, 1);
642 adjust_markers (opoint
- 1, opoint
, length
);
643 signal_after_change (PT
-length
, 0, length
);
648 insert_before_markers_and_inherit (string
, length
)
649 unsigned char *string
;
654 register int opoint
= PT
;
655 insert_1 (string
, length
, 1, 1);
656 adjust_markers (opoint
- 1, opoint
, length
);
657 signal_after_change (PT
-length
, 0, length
);
661 /* Insert part of a Lisp string, relocating markers after. */
664 insert_from_string_before_markers (string
, pos
, length
, inherit
)
666 register int pos
, length
;
671 register int opoint
= PT
;
672 insert_from_string_1 (string
, pos
, length
, inherit
);
673 adjust_markers (opoint
- 1, opoint
, length
);
674 signal_after_change (PT
-length
, 0, length
);
678 /* Delete characters in current buffer
679 from FROM up to (but not including) TO. */
683 register int from
, to
;
685 del_range_1 (from
, to
, 1);
688 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
691 del_range_1 (from
, to
, prepare
)
692 register int from
, to
, prepare
;
696 /* Make args be valid */
702 if ((numdel
= to
- from
) <= 0)
705 /* Make sure the gap is somewhere in or next to what we are deleting. */
712 prepare_to_modify_buffer (from
, to
);
714 /* Relocate all markers pointing into the new, larger gap
715 to point at the end of the text before the gap.
716 This has to be done before recording the deletion,
717 so undo handles this after reinserting the text. */
718 adjust_markers (to
+ GAP_SIZE
, to
+ GAP_SIZE
, - numdel
- GAP_SIZE
);
720 record_delete (from
, numdel
);
723 /* Relocate point as if it were a marker. */
725 adjust_point (from
- (PT
< to
? PT
: to
));
727 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
728 offset_intervals (current_buffer
, from
, - numdel
);
730 /* Adjust the overlay center as needed. This must be done after
731 adjusting the markers that bound the overlays. */
732 adjust_overlays_for_delete (from
, numdel
);
738 *(GPT_ADDR
) = 0; /* Put an anchor. */
740 if (GPT
- BEG
< beg_unchanged
)
741 beg_unchanged
= GPT
- BEG
;
742 if (Z
- GPT
< end_unchanged
)
743 end_unchanged
= Z
- GPT
;
745 evaporate_overlays (from
);
746 signal_after_change (from
, numdel
, 0);
749 /* Call this if you're about to change the region of BUFFER from START
750 to END. This checks the read-only properties of the region, calls
751 the necessary modification hooks, and warns the next redisplay that
752 it should pay attention to that area. */
754 modify_region (buffer
, start
, end
)
755 struct buffer
*buffer
;
758 struct buffer
*old_buffer
= current_buffer
;
760 if (buffer
!= old_buffer
)
761 set_buffer_internal (buffer
);
763 prepare_to_modify_buffer (start
, end
);
765 if (start
- 1 < beg_unchanged
766 || (unchanged_modified
== MODIFF
767 && overlay_unchanged_modified
== OVERLAY_MODIFF
))
768 beg_unchanged
= start
- 1;
769 if (Z
- end
< end_unchanged
770 || (unchanged_modified
== MODIFF
771 && overlay_unchanged_modified
== OVERLAY_MODIFF
))
772 end_unchanged
= Z
- end
;
774 if (MODIFF
<= SAVE_MODIFF
)
775 record_first_change ();
778 buffer
->point_before_scroll
= Qnil
;
780 if (buffer
!= old_buffer
)
781 set_buffer_internal (old_buffer
);
784 /* Check that it is okay to modify the buffer between START and END.
785 Run the before-change-function, if any. If intervals are in use,
786 verify that the text to be modified is not read-only, and call
787 any modification properties the text may have. */
790 prepare_to_modify_buffer (start
, end
)
793 if (!NILP (current_buffer
->read_only
))
794 Fbarf_if_buffer_read_only ();
796 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
797 if (BUF_INTERVALS (current_buffer
) != 0)
798 verify_interval_modification (current_buffer
, start
, end
);
800 #ifdef CLASH_DETECTION
801 if (!NILP (current_buffer
->file_truename
)
802 /* Make binding buffer-file-name to nil effective. */
803 && !NILP (current_buffer
->filename
)
804 && SAVE_MODIFF
>= MODIFF
)
805 lock_file (current_buffer
->file_truename
);
807 /* At least warn if this file has changed on disk since it was visited. */
808 if (!NILP (current_buffer
->filename
)
809 && SAVE_MODIFF
>= MODIFF
810 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
811 && !NILP (Ffile_exists_p (current_buffer
->filename
)))
812 call1 (intern ("ask-user-about-supersession-threat"),
813 current_buffer
->filename
);
814 #endif /* not CLASH_DETECTION */
816 signal_before_change (start
, end
);
818 if (current_buffer
->newline_cache
)
819 invalidate_region_cache (current_buffer
,
820 current_buffer
->newline_cache
,
821 start
- BEG
, Z
- end
);
822 if (current_buffer
->width_run_cache
)
823 invalidate_region_cache (current_buffer
,
824 current_buffer
->width_run_cache
,
825 start
- BEG
, Z
- end
);
827 Vdeactivate_mark
= Qt
;
830 /* Signal a change to the buffer immediately before it happens.
831 START_INT and END_INT are the bounds of the text to be changed. */
834 signal_before_change (start_int
, end_int
)
835 int start_int
, end_int
;
837 Lisp_Object start
, end
;
839 start
= make_number (start_int
);
840 end
= make_number (end_int
);
842 /* If buffer is unmodified, run a special hook for that case. */
843 if (SAVE_MODIFF
>= MODIFF
844 && !NILP (Vfirst_change_hook
)
845 && !NILP (Vrun_hooks
))
846 call1 (Vrun_hooks
, Qfirst_change_hook
);
848 /* Run the before-change-function if any.
849 We don't bother "binding" this variable to nil
850 because it is obsolete anyway and new code should not use it. */
851 if (!NILP (Vbefore_change_function
))
852 call2 (Vbefore_change_function
, start
, end
);
854 /* Now run the before-change-functions if any. */
855 if (!NILP (Vbefore_change_functions
))
858 Lisp_Object before_change_functions
;
859 Lisp_Object after_change_functions
;
860 struct gcpro gcpro1
, gcpro2
;
862 /* "Bind" before-change-functions and after-change-functions
863 to nil--but in a way that errors don't know about.
864 That way, if there's an error in them, they will stay nil. */
865 before_change_functions
= Vbefore_change_functions
;
866 after_change_functions
= Vafter_change_functions
;
867 Vbefore_change_functions
= Qnil
;
868 Vafter_change_functions
= Qnil
;
869 GCPRO2 (before_change_functions
, after_change_functions
);
871 /* Actually run the hook functions. */
872 args
[0] = Qbefore_change_functions
;
875 run_hook_list_with_args (before_change_functions
, 3, args
);
877 /* "Unbind" the variables we "bound" to nil. */
878 Vbefore_change_functions
= before_change_functions
;
879 Vafter_change_functions
= after_change_functions
;
883 if (!NILP (current_buffer
->overlays_before
)
884 || !NILP (current_buffer
->overlays_after
))
885 report_overlay_modification (start
, end
, 0, start
, end
, Qnil
);
888 /* Signal a change immediately after it happens.
889 POS is the address of the start of the changed text.
890 LENDEL is the number of characters of the text before the change.
891 (Not the whole buffer; just the part that was changed.)
892 LENINS is the number of characters in that part of the text
896 signal_after_change (pos
, lendel
, lenins
)
897 int pos
, lendel
, lenins
;
899 /* If we are deferring calls to the after-change functions
900 and there are no before-change functions,
901 just record the args that we were going to use. */
902 if (! NILP (Vcombine_after_change_calls
)
903 && NILP (Vbefore_change_function
) && NILP (Vbefore_change_functions
)
904 && NILP (current_buffer
->overlays_before
)
905 && NILP (current_buffer
->overlays_after
))
909 if (!NILP (combine_after_change_list
)
910 && current_buffer
!= XBUFFER (combine_after_change_buffer
))
911 Fcombine_after_change_execute ();
913 elt
= Fcons (make_number (pos
- BEG
),
914 Fcons (make_number (Z
- (pos
- lendel
+ lenins
)),
915 Fcons (make_number (lenins
- lendel
), Qnil
)));
916 combine_after_change_list
917 = Fcons (elt
, combine_after_change_list
);
918 combine_after_change_buffer
= Fcurrent_buffer ();
923 if (!NILP (combine_after_change_list
))
924 Fcombine_after_change_execute ();
926 /* Run the after-change-function if any.
927 We don't bother "binding" this variable to nil
928 because it is obsolete anyway and new code should not use it. */
929 if (!NILP (Vafter_change_function
))
930 call3 (Vafter_change_function
,
931 make_number (pos
), make_number (pos
+ lenins
),
932 make_number (lendel
));
934 if (!NILP (Vafter_change_functions
))
937 Lisp_Object before_change_functions
;
938 Lisp_Object after_change_functions
;
939 struct gcpro gcpro1
, gcpro2
;
941 /* "Bind" before-change-functions and after-change-functions
942 to nil--but in a way that errors don't know about.
943 That way, if there's an error in them, they will stay nil. */
944 before_change_functions
= Vbefore_change_functions
;
945 after_change_functions
= Vafter_change_functions
;
946 Vbefore_change_functions
= Qnil
;
947 Vafter_change_functions
= Qnil
;
948 GCPRO2 (before_change_functions
, after_change_functions
);
950 /* Actually run the hook functions. */
951 args
[0] = Qafter_change_functions
;
952 XSETFASTINT (args
[1], pos
);
953 XSETFASTINT (args
[2], pos
+ lenins
);
954 XSETFASTINT (args
[3], lendel
);
955 run_hook_list_with_args (after_change_functions
,
958 /* "Unbind" the variables we "bound" to nil. */
959 Vbefore_change_functions
= before_change_functions
;
960 Vafter_change_functions
= after_change_functions
;
964 if (!NILP (current_buffer
->overlays_before
)
965 || !NILP (current_buffer
->overlays_after
))
966 report_overlay_modification (make_number (pos
),
967 make_number (pos
+ lenins
),
969 make_number (pos
), make_number (pos
+ lenins
),
970 make_number (lendel
));
972 /* After an insertion, call the text properties
973 insert-behind-hooks or insert-in-front-hooks. */
975 report_interval_modification (pos
, pos
+ lenins
);
979 Fcombine_after_change_execute_1 (val
)
982 Vcombine_after_change_calls
= val
;
986 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute
,
987 Scombine_after_change_execute
, 0, 0, 0,
988 "This function is for use internally in `combine-after-change-calls'.")
991 register Lisp_Object val
;
992 int count
= specpdl_ptr
- specpdl
;
993 int beg
, end
, change
;
997 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
999 Fset_buffer (combine_after_change_buffer
);
1001 /* # chars unchanged at beginning of buffer. */
1003 /* # chars unchanged at end of buffer. */
1005 /* Total amount of insertion (negative for deletion). */
1008 /* Scan the various individual changes,
1009 accumulating the range info in BEG, END and CHANGE. */
1010 for (tail
= combine_after_change_list
; CONSP (tail
);
1011 tail
= XCONS (tail
)->cdr
)
1014 int thisbeg
, thisend
, thischange
;
1016 /* Extract the info from the next element. */
1017 elt
= XCONS (tail
)->car
;
1020 thisbeg
= XINT (XCONS (elt
)->car
);
1022 elt
= XCONS (elt
)->cdr
;
1025 thisend
= XINT (XCONS (elt
)->car
);
1027 elt
= XCONS (elt
)->cdr
;
1030 thischange
= XINT (XCONS (elt
)->car
);
1032 /* Merge this range into the accumulated range. */
1033 change
+= thischange
;
1040 /* Get the current start and end positions of the range
1041 that was changed. */
1045 /* We are about to handle these, so discard them. */
1046 combine_after_change_list
= Qnil
;
1048 /* Now run the after-change functions for real.
1049 Turn off the flag that defers them. */
1050 record_unwind_protect (Fcombine_after_change_execute_1
,
1051 Vcombine_after_change_calls
);
1052 signal_after_change (begpos
, endpos
- begpos
- change
, endpos
- begpos
);
1054 return unbind_to (count
, val
);
1059 staticpro (&combine_after_change_list
);
1060 combine_after_change_list
= Qnil
;
1062 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls
,
1063 "Used internally by the `combine-after-change-calls' macro.");
1064 Vcombine_after_change_calls
= Qnil
;
1066 defsubr (&Scombine_after_change_execute
);