(kCGBitmapByteOrder32Host): New define for non-universal SDKs.
[emacs.git] / src / insdel.c
bloba22ff8b4fd637df61ca04e03d633f33f95788d92
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
24 #include <config.h>
25 #include "lisp.h"
26 #include "intervals.h"
27 #include "buffer.h"
28 #include "charset.h"
29 #include "window.h"
30 #include "blockinput.h"
31 #include "region-cache.h"
33 #ifndef NULL
34 #define NULL 0
35 #endif
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));
43 void adjust_markers_for_delete P_ ((int, int, int, int));
44 static void adjust_markers_for_replace P_ ((int, int, 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.
58 In each element.
59 BEG-UNCHANGED is the number of chars before the changed range.
60 END-UNCHANGED is the number of chars after the changed range,
61 and CHANGE-AMOUNT is the number of characters inserted by the change
62 (negative for a deletion). */
63 Lisp_Object combine_after_change_list;
65 /* Buffer which combine_after_change_list is about. */
66 Lisp_Object combine_after_change_buffer;
68 Lisp_Object Qinhibit_modification_hooks;
71 /* Check all markers in the current buffer, looking for something invalid. */
73 static int check_markers_debug_flag;
75 #define CHECK_MARKERS() \
76 if (check_markers_debug_flag) \
77 check_markers (); \
78 else
80 void
81 check_markers ()
83 register struct Lisp_Marker *tail;
84 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
86 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
88 if (tail->buffer->text != current_buffer->text)
89 abort ();
90 if (tail->charpos > Z)
91 abort ();
92 if (tail->bytepos > Z_BYTE)
93 abort ();
94 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
95 abort ();
99 /* Move gap to position CHARPOS.
100 Note that this can quit! */
102 void
103 move_gap (charpos)
104 int charpos;
106 move_gap_both (charpos, charpos_to_bytepos (charpos));
109 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
110 Note that this can quit! */
112 void
113 move_gap_both (charpos, bytepos)
114 int charpos, bytepos;
116 if (bytepos < GPT_BYTE)
117 gap_left (charpos, bytepos, 0);
118 else if (bytepos > GPT_BYTE)
119 gap_right (charpos, bytepos);
122 /* Move the gap to a position less than the current GPT.
123 BYTEPOS describes the new position as a byte position,
124 and CHARPOS is the corresponding char position.
125 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
127 static void
128 gap_left (charpos, bytepos, newgap)
129 register int charpos, bytepos;
130 int newgap;
132 register unsigned char *to, *from;
133 register int i;
134 int new_s1;
136 if (!newgap)
137 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
139 i = GPT_BYTE;
140 to = GAP_END_ADDR;
141 from = GPT_ADDR;
142 new_s1 = GPT_BYTE;
144 /* Now copy the characters. To move the gap down,
145 copy characters up. */
147 while (1)
149 /* I gets number of characters left to copy. */
150 i = new_s1 - bytepos;
151 if (i == 0)
152 break;
153 /* If a quit is requested, stop copying now.
154 Change BYTEPOS to be where we have actually moved the gap to. */
155 if (QUITP)
157 bytepos = new_s1;
158 charpos = BYTE_TO_CHAR (bytepos);
159 break;
161 /* Move at most 32000 chars before checking again for a quit. */
162 if (i > 32000)
163 i = 32000;
164 #ifdef GAP_USE_BCOPY
165 if (i >= 128
166 /* bcopy is safe if the two areas of memory do not overlap
167 or on systems where bcopy is always safe for moving upward. */
168 && (BCOPY_UPWARD_SAFE
169 || to - from >= 128))
171 /* If overlap is not safe, avoid it by not moving too many
172 characters at once. */
173 if (!BCOPY_UPWARD_SAFE && i > to - from)
174 i = to - from;
175 new_s1 -= i;
176 from -= i, to -= i;
177 bcopy (from, to, i);
179 else
180 #endif
182 new_s1 -= i;
183 while (--i >= 0)
184 *--to = *--from;
188 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
189 BYTEPOS is where the loop above stopped, which may be what was specified
190 or may be where a quit was detected. */
191 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
192 GPT_BYTE = bytepos;
193 GPT = charpos;
194 if (bytepos < charpos)
195 abort ();
196 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
197 QUIT;
200 /* Move the gap to a position greater than than the current GPT.
201 BYTEPOS describes the new position as a byte position,
202 and CHARPOS is the corresponding char position. */
204 static void
205 gap_right (charpos, bytepos)
206 register int charpos, bytepos;
208 register unsigned char *to, *from;
209 register int i;
210 int new_s1;
212 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
214 i = GPT_BYTE;
215 from = GAP_END_ADDR;
216 to = GPT_ADDR;
217 new_s1 = GPT_BYTE;
219 /* Now copy the characters. To move the gap up,
220 copy characters down. */
222 while (1)
224 /* I gets number of characters left to copy. */
225 i = bytepos - new_s1;
226 if (i == 0)
227 break;
228 /* If a quit is requested, stop copying now.
229 Change BYTEPOS to be where we have actually moved the gap to. */
230 if (QUITP)
232 bytepos = new_s1;
233 charpos = BYTE_TO_CHAR (bytepos);
234 break;
236 /* Move at most 32000 chars before checking again for a quit. */
237 if (i > 32000)
238 i = 32000;
239 #ifdef GAP_USE_BCOPY
240 if (i >= 128
241 /* bcopy is safe if the two areas of memory do not overlap
242 or on systems where bcopy is always safe for moving downward. */
243 && (BCOPY_DOWNWARD_SAFE
244 || from - to >= 128))
246 /* If overlap is not safe, avoid it by not moving too many
247 characters at once. */
248 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
249 i = from - to;
250 new_s1 += i;
251 bcopy (from, to, i);
252 from += i, to += i;
254 else
255 #endif
257 new_s1 += i;
258 while (--i >= 0)
259 *to++ = *from++;
263 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
264 - GAP_SIZE);
265 GPT = charpos;
266 GPT_BYTE = bytepos;
267 if (bytepos < charpos)
268 abort ();
269 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
270 QUIT;
273 /* Add AMOUNT to the byte position of every marker in the current buffer
274 whose current byte position is between FROM (exclusive) and TO (inclusive).
276 Also, any markers past the outside of that interval, in the direction
277 of adjustment, are first moved back to the near end of the interval
278 and then adjusted by AMOUNT.
280 When the latter adjustment is done, if AMOUNT is negative,
281 we record the adjustment for undo. (This case happens only for
282 deletion.)
284 The markers' character positions are not altered,
285 because gap motion does not affect character positions. */
287 int adjust_markers_test;
289 static void
290 adjust_markers_gap_motion (from, to, amount)
291 register int from, to, amount;
293 /* Now that a marker has a bytepos, not counting the gap,
294 nothing needs to be done here. */
295 #if 0
296 Lisp_Object marker;
297 register struct Lisp_Marker *m;
298 register int mpos;
300 marker = BUF_MARKERS (current_buffer);
302 while (!NILP (marker))
304 m = XMARKER (marker);
305 mpos = m->bytepos;
306 if (amount > 0)
308 if (mpos > to && mpos < to + amount)
310 if (adjust_markers_test)
311 abort ();
312 mpos = to + amount;
315 else
317 /* Here's the case where a marker is inside text being deleted.
318 AMOUNT can be negative for gap motion, too,
319 but then this range contains no markers. */
320 if (mpos > from + amount && mpos <= from)
322 if (adjust_markers_test)
323 abort ();
324 mpos = from + amount;
327 if (mpos > from && mpos <= to)
328 mpos += amount;
329 m->bufpos = mpos;
330 marker = m->chain;
332 #endif
335 /* Adjust all markers for a deletion
336 whose range in bytes is FROM_BYTE to TO_BYTE.
337 The range in charpos is FROM to TO.
339 This function assumes that the gap is adjacent to
340 or inside of the range being deleted. */
342 void
343 adjust_markers_for_delete (from, from_byte, to, to_byte)
344 register int from, from_byte, to, to_byte;
346 Lisp_Object marker;
347 register struct Lisp_Marker *m;
348 register int charpos;
350 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
352 charpos = m->charpos;
354 if (charpos > Z)
355 abort ();
357 /* If the marker is after the deletion,
358 relocate by number of chars / bytes deleted. */
359 if (charpos > to)
361 m->charpos -= to - from;
362 m->bytepos -= to_byte - from_byte;
364 /* Here's the case where a marker is inside text being deleted. */
365 else if (charpos > from)
367 if (! m->insertion_type)
368 { /* Normal markers will end up at the beginning of the
369 re-inserted text after undoing a deletion, and must be
370 adjusted to move them to the correct place. */
371 XSETMISC (marker, m);
372 record_marker_adjustment (marker, from - charpos);
374 else if (charpos < to)
375 { /* Before-insertion markers will automatically move forward
376 upon re-inserting the deleted text, so we have to arrange
377 for them to move backward to the correct position. */
378 XSETMISC (marker, m);
379 record_marker_adjustment (marker, charpos - to);
381 m->charpos = from;
382 m->bytepos = from_byte;
384 /* Here's the case where a before-insertion marker is immediately
385 before the deleted region. */
386 else if (charpos == from && m->insertion_type)
388 /* Undoing the change uses normal insertion, which will
389 incorrectly make MARKER move forward, so we arrange for it
390 to then move backward to the correct place at the beginning
391 of the deleted region. */
392 XSETMISC (marker, m);
393 record_marker_adjustment (marker, to - from);
399 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
400 to TO / TO_BYTE. We have to relocate the charpos of every marker
401 that points after the insertion (but not their bytepos).
403 When a marker points at the insertion point,
404 we advance it if either its insertion-type is t
405 or BEFORE_MARKERS is true. */
407 static void
408 adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
409 register int from, from_byte, to, to_byte;
410 int before_markers;
412 struct Lisp_Marker *m;
413 int adjusted = 0;
414 int nchars = to - from;
415 int nbytes = to_byte - from_byte;
417 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
419 /* In a single-byte buffer, a marker's two positions must be
420 equal. */
421 if (Z == Z_BYTE)
423 if (m->charpos != m->bytepos)
424 abort ();
427 if (m->bytepos == from_byte)
429 if (m->insertion_type || before_markers)
431 m->bytepos = to_byte;
432 m->charpos = to;
433 if (m->insertion_type)
434 adjusted = 1;
437 else if (m->bytepos > from_byte)
439 m->bytepos += nbytes;
440 m->charpos += nchars;
444 /* Adjusting only markers whose insertion-type is t may result in
445 - disordered start and end in overlays, and
446 - disordered overlays in the slot `overlays_before' of current_buffer. */
447 if (adjusted)
449 fix_start_end_in_overlays(from, to);
450 fix_overlays_before (current_buffer, from, to);
454 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
456 This is used only when the value of point changes due to an insert
457 or delete; it does not represent a conceptual change in point as a
458 marker. In particular, point is not crossing any interval
459 boundaries, so there's no need to use the usual SET_PT macro. In
460 fact it would be incorrect to do so, because either the old or the
461 new value of point is out of sync with the current set of
462 intervals. */
464 static void
465 adjust_point (nchars, nbytes)
466 int nchars, nbytes;
468 BUF_PT (current_buffer) += nchars;
469 BUF_PT_BYTE (current_buffer) += nbytes;
471 /* In a single-byte buffer, the two positions must be equal. */
472 if (ZV == ZV_BYTE
473 && PT != PT_BYTE)
474 abort ();
477 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
478 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
479 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
480 an insertion. */
482 static void
483 adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
484 new_chars, new_bytes)
485 int from, from_byte, old_chars, old_bytes, new_chars, new_bytes;
487 register struct Lisp_Marker *m;
488 int prev_to_byte = from_byte + old_bytes;
489 int diff_chars = new_chars - old_chars;
490 int diff_bytes = new_bytes - old_bytes;
492 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
494 if (m->bytepos >= prev_to_byte)
496 m->charpos += diff_chars;
497 m->bytepos += diff_bytes;
499 else if (m->bytepos > from_byte)
501 m->charpos = from;
502 m->bytepos = from_byte;
506 CHECK_MARKERS ();
510 /* Make the gap NBYTES_ADDED bytes longer. */
512 void
513 make_gap_larger (nbytes_added)
514 int nbytes_added;
516 Lisp_Object tem;
517 int real_gap_loc;
518 int real_gap_loc_byte;
519 int old_gap_size;
521 /* If we have to get more space, get enough to last a while. */
522 nbytes_added += 2000;
524 /* Don't allow a buffer size that won't fit in an int
525 even if it will fit in a Lisp integer.
526 That won't work because so many places use `int'.
528 Make sure we don't introduce overflows in the calculation. */
530 if (Z_BYTE - BEG_BYTE + GAP_SIZE
531 >= (((EMACS_INT) 1 << (min (VALBITS, BITS_PER_INT) - 1)) - 1
532 - nbytes_added))
533 error ("Buffer exceeds maximum size");
535 enlarge_buffer_text (current_buffer, nbytes_added);
537 /* Prevent quitting in move_gap. */
538 tem = Vinhibit_quit;
539 Vinhibit_quit = Qt;
541 real_gap_loc = GPT;
542 real_gap_loc_byte = GPT_BYTE;
543 old_gap_size = GAP_SIZE;
545 /* Call the newly allocated space a gap at the end of the whole space. */
546 GPT = Z + GAP_SIZE;
547 GPT_BYTE = Z_BYTE + GAP_SIZE;
548 GAP_SIZE = nbytes_added;
550 /* Move the new gap down to be consecutive with the end of the old one.
551 This adjusts the markers properly too. */
552 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
554 /* Now combine the two into one large gap. */
555 GAP_SIZE += old_gap_size;
556 GPT = real_gap_loc;
557 GPT_BYTE = real_gap_loc_byte;
559 /* Put an anchor. */
560 *(Z_ADDR) = 0;
562 Vinhibit_quit = tem;
566 /* Make the gap NBYTES_REMOVED bytes shorter. */
568 void
569 make_gap_smaller (nbytes_removed)
570 int nbytes_removed;
572 Lisp_Object tem;
573 int real_gap_loc;
574 int real_gap_loc_byte;
575 int real_Z;
576 int real_Z_byte;
577 int real_beg_unchanged;
578 int new_gap_size;
580 /* Make sure the gap is at least 20 bytes. */
581 if (GAP_SIZE - nbytes_removed < 20)
582 nbytes_removed = GAP_SIZE - 20;
584 /* Prevent quitting in move_gap. */
585 tem = Vinhibit_quit;
586 Vinhibit_quit = Qt;
588 real_gap_loc = GPT;
589 real_gap_loc_byte = GPT_BYTE;
590 new_gap_size = GAP_SIZE - nbytes_removed;
591 real_Z = Z;
592 real_Z_byte = Z_BYTE;
593 real_beg_unchanged = BEG_UNCHANGED;
595 /* Pretend that the last unwanted part of the gap is the entire gap,
596 and that the first desired part of the gap is part of the buffer
597 text. */
598 bzero (GPT_ADDR, new_gap_size);
599 GPT += new_gap_size;
600 GPT_BYTE += new_gap_size;
601 Z += new_gap_size;
602 Z_BYTE += new_gap_size;
603 GAP_SIZE = nbytes_removed;
605 /* Move the unwanted pretend gap to the end of the buffer. This
606 adjusts the markers properly too. */
607 gap_right (Z, Z_BYTE);
609 enlarge_buffer_text (current_buffer, -nbytes_removed);
611 /* Now restore the desired gap. */
612 GAP_SIZE = new_gap_size;
613 GPT = real_gap_loc;
614 GPT_BYTE = real_gap_loc_byte;
615 Z = real_Z;
616 Z_BYTE = real_Z_byte;
617 BEG_UNCHANGED = real_beg_unchanged;
619 /* Put an anchor. */
620 *(Z_ADDR) = 0;
622 Vinhibit_quit = tem;
625 void
626 make_gap (nbytes_added)
627 int nbytes_added;
629 if (nbytes_added >= 0)
630 make_gap_larger (nbytes_added);
631 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
632 else
633 make_gap_smaller (-nbytes_added);
634 #endif
637 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
638 FROM_MULTIBYTE says whether the incoming text is multibyte.
639 TO_MULTIBYTE says whether to store the text as multibyte.
640 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
642 Return the number of bytes stored at TO_ADDR. */
645 copy_text (from_addr, to_addr, nbytes,
646 from_multibyte, to_multibyte)
647 const unsigned char *from_addr;
648 unsigned char *to_addr;
649 int nbytes;
650 int from_multibyte, to_multibyte;
652 if (from_multibyte == to_multibyte)
654 bcopy (from_addr, to_addr, nbytes);
655 return nbytes;
657 else if (from_multibyte)
659 int nchars = 0;
660 int bytes_left = nbytes;
661 Lisp_Object tbl = Qnil;
663 /* We set the variable tbl to the reverse table of
664 Vnonascii_translation_table in advance. */
665 if (CHAR_TABLE_P (Vnonascii_translation_table))
667 tbl = Fchar_table_extra_slot (Vnonascii_translation_table,
668 make_number (0));
669 if (!CHAR_TABLE_P (tbl))
670 tbl = Qnil;
673 /* Convert multibyte to single byte. */
674 while (bytes_left > 0)
676 int thislen, c;
677 c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen);
678 if (!SINGLE_BYTE_CHAR_P (c))
679 c = multibyte_char_to_unibyte (c, tbl);
680 *to_addr++ = c;
681 from_addr += thislen;
682 bytes_left -= thislen;
683 nchars++;
685 return nchars;
687 else
689 unsigned char *initial_to_addr = to_addr;
691 /* Convert single-byte to multibyte. */
692 while (nbytes > 0)
694 int c = *from_addr++;
696 if (c >= 0200)
698 c = unibyte_char_to_multibyte (c);
699 to_addr += CHAR_STRING (c, to_addr);
700 nbytes--;
702 else
703 /* Special case for speed. */
704 *to_addr++ = c, nbytes--;
706 return to_addr - initial_to_addr;
710 /* Return the number of bytes it would take
711 to convert some single-byte text to multibyte.
712 The single-byte text consists of NBYTES bytes at PTR. */
715 count_size_as_multibyte (ptr, nbytes)
716 const unsigned char *ptr;
717 int nbytes;
719 int i;
720 int outgoing_nbytes = 0;
722 for (i = 0; i < nbytes; i++)
724 unsigned int c = *ptr++;
726 if (c < 0200)
727 outgoing_nbytes++;
728 else
730 c = unibyte_char_to_multibyte (c);
731 outgoing_nbytes += CHAR_BYTES (c);
735 return outgoing_nbytes;
738 /* Insert a string of specified length before point.
739 This function judges multibyteness based on
740 enable_multibyte_characters in the current buffer;
741 it never converts between single-byte and multibyte.
743 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
744 prepare_to_modify_buffer could relocate the text. */
746 void
747 insert (string, nbytes)
748 register const unsigned char *string;
749 register int nbytes;
751 if (nbytes > 0)
753 int len = chars_in_text (string, nbytes), opoint;
754 insert_1_both (string, len, nbytes, 0, 1, 0);
755 opoint = PT - len;
756 signal_after_change (opoint, 0, len);
757 update_compositions (opoint, PT, CHECK_BORDER);
761 /* Likewise, but inherit text properties from neighboring characters. */
763 void
764 insert_and_inherit (string, nbytes)
765 register const unsigned char *string;
766 register int nbytes;
768 if (nbytes > 0)
770 int len = chars_in_text (string, nbytes), opoint;
771 insert_1_both (string, len, nbytes, 1, 1, 0);
772 opoint = PT - len;
773 signal_after_change (opoint, 0, len);
774 update_compositions (opoint, PT, CHECK_BORDER);
778 /* Insert the character C before point. Do not inherit text properties. */
780 void
781 insert_char (c)
782 int c;
784 unsigned char str[MAX_MULTIBYTE_LENGTH];
785 int len;
787 if (! NILP (current_buffer->enable_multibyte_characters))
788 len = CHAR_STRING (c, str);
789 else
791 len = 1;
792 str[0] = c;
795 insert (str, len);
798 /* Insert the null-terminated string S before point. */
800 void
801 insert_string (s)
802 const char *s;
804 insert (s, strlen (s));
807 /* Like `insert' except that all markers pointing at the place where
808 the insertion happens are adjusted to point after it.
809 Don't use this function to insert part of a Lisp string,
810 since gc could happen and relocate it. */
812 void
813 insert_before_markers (string, nbytes)
814 const unsigned char *string;
815 register int nbytes;
817 if (nbytes > 0)
819 int len = chars_in_text (string, nbytes), opoint;
820 insert_1_both (string, len, nbytes, 0, 1, 1);
821 opoint = PT - len;
822 signal_after_change (opoint, 0, len);
823 update_compositions (opoint, PT, CHECK_BORDER);
827 /* Likewise, but inherit text properties from neighboring characters. */
829 void
830 insert_before_markers_and_inherit (string, nbytes)
831 const unsigned char *string;
832 register int nbytes;
834 if (nbytes > 0)
836 int len = chars_in_text (string, nbytes), opoint;
837 insert_1_both (string, len, nbytes, 1, 1, 1);
838 opoint = PT - len;
839 signal_after_change (opoint, 0, len);
840 update_compositions (opoint, PT, CHECK_BORDER);
844 /* Subroutine used by the insert functions above. */
846 void
847 insert_1 (string, nbytes, inherit, prepare, before_markers)
848 register const unsigned char *string;
849 register int nbytes;
850 int inherit, prepare, before_markers;
852 insert_1_both (string, chars_in_text (string, nbytes), nbytes,
853 inherit, prepare, before_markers);
857 #ifdef BYTE_COMBINING_DEBUG
859 /* See if the bytes before POS/POS_BYTE combine with bytes
860 at the start of STRING to form a single character.
861 If so, return the number of bytes at the start of STRING
862 which combine in this way. Otherwise, return 0. */
865 count_combining_before (string, length, pos, pos_byte)
866 const unsigned char *string;
867 int length;
868 int pos, pos_byte;
870 int len, combining_bytes;
871 const unsigned char *p;
873 if (NILP (current_buffer->enable_multibyte_characters))
874 return 0;
876 /* At first, we can exclude the following cases:
877 (1) STRING[0] can't be a following byte of multibyte sequence.
878 (2) POS is the start of the current buffer.
879 (3) A character before POS is not a multibyte character. */
880 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
881 return 0;
882 if (pos_byte == BEG_BYTE) /* case (2) */
883 return 0;
884 len = 1;
885 p = BYTE_POS_ADDR (pos_byte - 1);
886 while (! CHAR_HEAD_P (*p)) p--, len++;
887 if (! BASE_LEADING_CODE_P (*p)) /* case (3) */
888 return 0;
890 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
891 if (combining_bytes <= 0)
892 /* The character preceding POS is, complete and no room for
893 combining bytes (combining_bytes == 0), or an independent 8-bit
894 character (combining_bytes < 0). */
895 return 0;
897 /* We have a combination situation. Count the bytes at STRING that
898 may combine. */
899 p = string + 1;
900 while (!CHAR_HEAD_P (*p) && p < string + length)
901 p++;
903 return (combining_bytes < p - string ? combining_bytes : p - string);
906 /* See if the bytes after POS/POS_BYTE combine with bytes
907 at the end of STRING to form a single character.
908 If so, return the number of bytes after POS/POS_BYTE
909 which combine in this way. Otherwise, return 0. */
912 count_combining_after (string, length, pos, pos_byte)
913 const unsigned char *string;
914 int length;
915 int pos, pos_byte;
917 int opos_byte = pos_byte;
918 int i;
919 int bytes;
920 unsigned char *bufp;
922 if (NILP (current_buffer->enable_multibyte_characters))
923 return 0;
925 /* At first, we can exclude the following cases:
926 (1) The last byte of STRING is an ASCII.
927 (2) POS is the last of the current buffer.
928 (3) A character at POS can't be a following byte of multibyte
929 character. */
930 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
931 return 0;
932 if (pos_byte == Z_BYTE) /* case (2) */
933 return 0;
934 bufp = BYTE_POS_ADDR (pos_byte);
935 if (CHAR_HEAD_P (*bufp)) /* case (3) */
936 return 0;
938 i = length - 1;
939 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
941 i--;
943 if (i < 0)
945 /* All characters in STRING are not character head. We must
946 check also preceding bytes at POS. We are sure that the gap
947 is at POS. */
948 unsigned char *p = BEG_ADDR;
949 i = pos_byte - 2;
950 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
951 i--;
952 if (i < 0 || !BASE_LEADING_CODE_P (p[i]))
953 return 0;
955 bytes = BYTES_BY_CHAR_HEAD (p[i]);
956 return (bytes <= pos_byte - 1 - i + length
958 : bytes - (pos_byte - 1 - i + length));
960 if (!BASE_LEADING_CODE_P (string[i]))
961 return 0;
963 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
964 bufp++, pos_byte++;
965 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
967 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
970 #endif
973 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
974 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
975 are the same as in insert_1. */
977 void
978 insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
979 register const unsigned char *string;
980 register int nchars, nbytes;
981 int inherit, prepare, before_markers;
983 if (nchars == 0)
984 return;
986 if (NILP (current_buffer->enable_multibyte_characters))
987 nchars = nbytes;
989 if (prepare)
990 /* Do this before moving and increasing the gap,
991 because the before-change hooks might move the gap
992 or make it smaller. */
993 prepare_to_modify_buffer (PT, PT, NULL);
995 if (PT != GPT)
996 move_gap_both (PT, PT_BYTE);
997 if (GAP_SIZE < nbytes)
998 make_gap (nbytes - GAP_SIZE);
1000 #ifdef BYTE_COMBINING_DEBUG
1001 if (count_combining_before (string, nbytes, PT, PT_BYTE)
1002 || count_combining_after (string, nbytes, PT, PT_BYTE))
1003 abort ();
1004 #endif
1006 /* Record deletion of the surrounding text that combines with
1007 the insertion. This, together with recording the insertion,
1008 will add up to the right stuff in the undo list. */
1009 record_insert (PT, nchars);
1010 MODIFF++;
1011 CHARS_MODIFF = MODIFF;
1013 bcopy (string, GPT_ADDR, nbytes);
1015 GAP_SIZE -= nbytes;
1016 GPT += nchars;
1017 ZV += nchars;
1018 Z += nchars;
1019 GPT_BYTE += nbytes;
1020 ZV_BYTE += nbytes;
1021 Z_BYTE += nbytes;
1022 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1024 if (GPT_BYTE < GPT)
1025 abort ();
1027 /* The insert may have been in the unchanged region, so check again. */
1028 if (Z - GPT < END_UNCHANGED)
1029 END_UNCHANGED = Z - GPT;
1031 adjust_overlays_for_insert (PT, nchars);
1032 adjust_markers_for_insert (PT, PT_BYTE,
1033 PT + nchars, PT_BYTE + nbytes,
1034 before_markers);
1036 if (BUF_INTERVALS (current_buffer) != 0)
1037 offset_intervals (current_buffer, PT, nchars);
1039 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
1040 set_text_properties (make_number (PT), make_number (PT + nchars),
1041 Qnil, Qnil, Qnil);
1043 adjust_point (nchars, nbytes);
1045 CHECK_MARKERS ();
1048 /* Insert the part of the text of STRING, a Lisp object assumed to be
1049 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
1050 starting at position POS / POS_BYTE. If the text of STRING has properties,
1051 copy them into the buffer.
1053 It does not work to use `insert' for this, because a GC could happen
1054 before we bcopy the stuff into the buffer, and relocate the string
1055 without insert noticing. */
1057 void
1058 insert_from_string (string, pos, pos_byte, length, length_byte, inherit)
1059 Lisp_Object string;
1060 register int pos, pos_byte, length, length_byte;
1061 int inherit;
1063 int opoint = PT;
1065 if (SCHARS (string) == 0)
1066 return;
1068 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
1069 inherit, 0);
1070 signal_after_change (opoint, 0, PT - opoint);
1071 update_compositions (opoint, PT, CHECK_BORDER);
1074 /* Like `insert_from_string' except that all markers pointing
1075 at the place where the insertion happens are adjusted to point after it. */
1077 void
1078 insert_from_string_before_markers (string, pos, pos_byte,
1079 length, length_byte, inherit)
1080 Lisp_Object string;
1081 register int pos, pos_byte, length, length_byte;
1082 int inherit;
1084 int opoint = PT;
1086 if (SCHARS (string) == 0)
1087 return;
1089 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
1090 inherit, 1);
1091 signal_after_change (opoint, 0, PT - opoint);
1092 update_compositions (opoint, PT, CHECK_BORDER);
1095 /* Subroutine of the insertion functions above. */
1097 static void
1098 insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
1099 inherit, before_markers)
1100 Lisp_Object string;
1101 register int pos, pos_byte, nchars, nbytes;
1102 int inherit, before_markers;
1104 struct gcpro gcpro1;
1105 int outgoing_nbytes = nbytes;
1106 INTERVAL intervals;
1108 /* Make OUTGOING_NBYTES describe the text
1109 as it will be inserted in this buffer. */
1111 if (NILP (current_buffer->enable_multibyte_characters))
1112 outgoing_nbytes = nchars;
1113 else if (! STRING_MULTIBYTE (string))
1114 outgoing_nbytes
1115 = count_size_as_multibyte (SDATA (string) + pos_byte,
1116 nbytes);
1118 GCPRO1 (string);
1119 /* Do this before moving and increasing the gap,
1120 because the before-change hooks might move the gap
1121 or make it smaller. */
1122 prepare_to_modify_buffer (PT, PT, NULL);
1124 if (PT != GPT)
1125 move_gap_both (PT, PT_BYTE);
1126 if (GAP_SIZE < outgoing_nbytes)
1127 make_gap (outgoing_nbytes - GAP_SIZE);
1128 UNGCPRO;
1130 /* Copy the string text into the buffer, perhaps converting
1131 between single-byte and multibyte. */
1132 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
1133 STRING_MULTIBYTE (string),
1134 ! NILP (current_buffer->enable_multibyte_characters));
1136 #ifdef BYTE_COMBINING_DEBUG
1137 /* We have copied text into the gap, but we have not altered
1138 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1139 to these functions and get the same results as we would
1140 have got earlier on. Meanwhile, PT_ADDR does point to
1141 the text that has been stored by copy_text. */
1142 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1143 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1144 abort ();
1145 #endif
1147 record_insert (PT, nchars);
1148 MODIFF++;
1149 CHARS_MODIFF = MODIFF;
1151 GAP_SIZE -= outgoing_nbytes;
1152 GPT += nchars;
1153 ZV += nchars;
1154 Z += nchars;
1155 GPT_BYTE += outgoing_nbytes;
1156 ZV_BYTE += outgoing_nbytes;
1157 Z_BYTE += outgoing_nbytes;
1158 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1160 if (GPT_BYTE < GPT)
1161 abort ();
1163 /* The insert may have been in the unchanged region, so check again. */
1164 if (Z - GPT < END_UNCHANGED)
1165 END_UNCHANGED = Z - GPT;
1167 adjust_overlays_for_insert (PT, nchars);
1168 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1169 PT_BYTE + outgoing_nbytes,
1170 before_markers);
1172 offset_intervals (current_buffer, PT, nchars);
1174 intervals = STRING_INTERVALS (string);
1175 /* Get the intervals for the part of the string we are inserting. */
1176 if (nbytes < SBYTES (string))
1177 intervals = copy_intervals (intervals, pos, nchars);
1179 /* Insert those intervals. */
1180 graft_intervals_into_buffer (intervals, PT, nchars,
1181 current_buffer, inherit);
1183 adjust_point (nchars, outgoing_nbytes);
1186 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1187 current buffer. If the text in BUF has properties, they are absorbed
1188 into the current buffer.
1190 It does not work to use `insert' for this, because a malloc could happen
1191 and relocate BUF's text before the bcopy happens. */
1193 void
1194 insert_from_buffer (buf, charpos, nchars, inherit)
1195 struct buffer *buf;
1196 int charpos, nchars;
1197 int inherit;
1199 int opoint = PT;
1201 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1202 signal_after_change (opoint, 0, PT - opoint);
1203 update_compositions (opoint, PT, CHECK_BORDER);
1206 static void
1207 insert_from_buffer_1 (buf, from, nchars, inherit)
1208 struct buffer *buf;
1209 int from, nchars;
1210 int inherit;
1212 register Lisp_Object temp;
1213 int chunk, chunk_expanded;
1214 int from_byte = buf_charpos_to_bytepos (buf, from);
1215 int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1216 int incoming_nbytes = to_byte - from_byte;
1217 int outgoing_nbytes = incoming_nbytes;
1218 INTERVAL intervals;
1220 /* Make OUTGOING_NBYTES describe the text
1221 as it will be inserted in this buffer. */
1223 if (NILP (current_buffer->enable_multibyte_characters))
1224 outgoing_nbytes = nchars;
1225 else if (NILP (buf->enable_multibyte_characters))
1227 int outgoing_before_gap = 0;
1228 int outgoing_after_gap = 0;
1230 if (from < BUF_GPT (buf))
1232 chunk = BUF_GPT_BYTE (buf) - from_byte;
1233 if (chunk > incoming_nbytes)
1234 chunk = incoming_nbytes;
1235 outgoing_before_gap
1236 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1237 chunk);
1239 else
1240 chunk = 0;
1242 if (chunk < incoming_nbytes)
1243 outgoing_after_gap
1244 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1245 from_byte + chunk),
1246 incoming_nbytes - chunk);
1248 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1251 /* Make sure point-max won't overflow after this insertion. */
1252 XSETINT (temp, outgoing_nbytes + Z);
1253 if (outgoing_nbytes + Z != XINT (temp))
1254 error ("Maximum buffer size exceeded");
1256 /* Do this before moving and increasing the gap,
1257 because the before-change hooks might move the gap
1258 or make it smaller. */
1259 prepare_to_modify_buffer (PT, PT, NULL);
1261 if (PT != GPT)
1262 move_gap_both (PT, PT_BYTE);
1263 if (GAP_SIZE < outgoing_nbytes)
1264 make_gap (outgoing_nbytes - GAP_SIZE);
1266 if (from < BUF_GPT (buf))
1268 chunk = BUF_GPT_BYTE (buf) - from_byte;
1269 if (chunk > incoming_nbytes)
1270 chunk = incoming_nbytes;
1271 /* Record number of output bytes, so we know where
1272 to put the output from the second copy_text. */
1273 chunk_expanded
1274 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1275 GPT_ADDR, chunk,
1276 ! NILP (buf->enable_multibyte_characters),
1277 ! NILP (current_buffer->enable_multibyte_characters));
1279 else
1280 chunk_expanded = chunk = 0;
1282 if (chunk < incoming_nbytes)
1283 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1284 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1285 ! NILP (buf->enable_multibyte_characters),
1286 ! NILP (current_buffer->enable_multibyte_characters));
1288 #ifdef BYTE_COMBINING_DEBUG
1289 /* We have copied text into the gap, but we have not altered
1290 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1291 to these functions and get the same results as we would
1292 have got earlier on. Meanwhile, GPT_ADDR does point to
1293 the text that has been stored by copy_text. */
1294 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1295 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1296 abort ();
1297 #endif
1299 record_insert (PT, nchars);
1300 MODIFF++;
1301 CHARS_MODIFF = MODIFF;
1303 GAP_SIZE -= outgoing_nbytes;
1304 GPT += nchars;
1305 ZV += nchars;
1306 Z += nchars;
1307 GPT_BYTE += outgoing_nbytes;
1308 ZV_BYTE += outgoing_nbytes;
1309 Z_BYTE += outgoing_nbytes;
1310 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1312 if (GPT_BYTE < GPT)
1313 abort ();
1315 /* The insert may have been in the unchanged region, so check again. */
1316 if (Z - GPT < END_UNCHANGED)
1317 END_UNCHANGED = Z - GPT;
1319 adjust_overlays_for_insert (PT, nchars);
1320 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1321 PT_BYTE + outgoing_nbytes,
1324 if (BUF_INTERVALS (current_buffer) != 0)
1325 offset_intervals (current_buffer, PT, nchars);
1327 /* Get the intervals for the part of the string we are inserting. */
1328 intervals = BUF_INTERVALS (buf);
1329 if (outgoing_nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf))
1331 if (buf == current_buffer && PT <= from)
1332 from += nchars;
1333 intervals = copy_intervals (intervals, from, nchars);
1336 /* Insert those intervals. */
1337 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1339 adjust_point (nchars, outgoing_nbytes);
1342 /* Record undo information and adjust markers and position keepers for
1343 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1344 chars (LEN_BYTE bytes) which resides in the gap just after
1345 GPT_ADDR.
1347 PREV_TEXT nil means the new text was just inserted. */
1349 void
1350 adjust_after_replace (from, from_byte, prev_text, len, len_byte)
1351 int from, from_byte, len, len_byte;
1352 Lisp_Object prev_text;
1354 int nchars_del = 0, nbytes_del = 0;
1356 #ifdef BYTE_COMBINING_DEBUG
1357 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1358 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1359 abort ();
1360 #endif
1362 if (STRINGP (prev_text))
1364 nchars_del = SCHARS (prev_text);
1365 nbytes_del = SBYTES (prev_text);
1368 /* Update various buffer positions for the new text. */
1369 GAP_SIZE -= len_byte;
1370 ZV += len; Z+= len;
1371 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1372 GPT += len; GPT_BYTE += len_byte;
1373 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1375 if (nchars_del > 0)
1376 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1377 len, len_byte);
1378 else
1379 adjust_markers_for_insert (from, from_byte,
1380 from + len, from_byte + len_byte, 0);
1382 if (! EQ (current_buffer->undo_list, Qt))
1384 if (nchars_del > 0)
1385 record_delete (from, prev_text);
1386 record_insert (from, len);
1389 if (len > nchars_del)
1390 adjust_overlays_for_insert (from, len - nchars_del);
1391 else if (len < nchars_del)
1392 adjust_overlays_for_delete (from, nchars_del - len);
1393 if (BUF_INTERVALS (current_buffer) != 0)
1395 offset_intervals (current_buffer, from, len - nchars_del);
1398 if (from < PT)
1399 adjust_point (len - nchars_del, len_byte - nbytes_del);
1401 /* As byte combining will decrease Z, we must check this again. */
1402 if (Z - GPT < END_UNCHANGED)
1403 END_UNCHANGED = Z - GPT;
1405 CHECK_MARKERS ();
1407 if (len == 0)
1408 evaporate_overlays (from);
1409 MODIFF++;
1410 CHARS_MODIFF = MODIFF;
1413 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
1414 This is for use when undo is not enabled in the current buffer. */
1416 void
1417 adjust_after_replace_noundo (from, from_byte, nchars_del, nbytes_del, len, len_byte)
1418 int from, from_byte, nchars_del, nbytes_del, len, len_byte;
1420 #ifdef BYTE_COMBINING_DEBUG
1421 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1422 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1423 abort ();
1424 #endif
1426 /* Update various buffer positions for the new text. */
1427 GAP_SIZE -= len_byte;
1428 ZV += len; Z+= len;
1429 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1430 GPT += len; GPT_BYTE += len_byte;
1431 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1433 if (nchars_del > 0)
1434 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1435 len, len_byte);
1436 else
1437 adjust_markers_for_insert (from, from_byte,
1438 from + len, from_byte + len_byte, 0);
1440 if (len > nchars_del)
1441 adjust_overlays_for_insert (from, len - nchars_del);
1442 else if (len < nchars_del)
1443 adjust_overlays_for_delete (from, nchars_del - len);
1444 if (BUF_INTERVALS (current_buffer) != 0)
1446 offset_intervals (current_buffer, from, len - nchars_del);
1449 if (from < PT)
1450 adjust_point (len - nchars_del, len_byte - nbytes_del);
1452 /* As byte combining will decrease Z, we must check this again. */
1453 if (Z - GPT < END_UNCHANGED)
1454 END_UNCHANGED = Z - GPT;
1456 CHECK_MARKERS ();
1458 if (len == 0)
1459 evaporate_overlays (from);
1460 MODIFF++;
1461 CHARS_MODIFF = MODIFF;
1464 /* Record undo information, adjust markers and position keepers for an
1465 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1466 text already exists in the current buffer but character length (TO
1467 - FROM) may be incorrect, the correct length is NEWLEN. */
1469 void
1470 adjust_after_insert (from, from_byte, to, to_byte, newlen)
1471 int from, from_byte, to, to_byte, newlen;
1473 int len = to - from, len_byte = to_byte - from_byte;
1475 if (GPT != to)
1476 move_gap_both (to, to_byte);
1477 GAP_SIZE += len_byte;
1478 GPT -= len; GPT_BYTE -= len_byte;
1479 ZV -= len; ZV_BYTE -= len_byte;
1480 Z -= len; Z_BYTE -= len_byte;
1481 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1484 /* Replace the text from character positions FROM to TO with NEW,
1485 If PREPARE is nonzero, call prepare_to_modify_buffer.
1486 If INHERIT, the newly inserted text should inherit text properties
1487 from the surrounding non-deleted text. */
1489 /* Note that this does not yet handle markers quite right.
1490 Also it needs to record a single undo-entry that does a replacement
1491 rather than a separate delete and insert.
1492 That way, undo will also handle markers properly.
1494 But if MARKERS is 0, don't relocate markers. */
1496 void
1497 replace_range (from, to, new, prepare, inherit, markers)
1498 Lisp_Object new;
1499 int from, to, prepare, inherit, markers;
1501 int inschars = SCHARS (new);
1502 int insbytes = SBYTES (new);
1503 int from_byte, to_byte;
1504 int nbytes_del, nchars_del;
1505 register Lisp_Object temp;
1506 struct gcpro gcpro1;
1507 INTERVAL intervals;
1508 int outgoing_insbytes = insbytes;
1509 Lisp_Object deletion;
1511 CHECK_MARKERS ();
1513 GCPRO1 (new);
1514 deletion = Qnil;
1516 if (prepare)
1518 int range_length = to - from;
1519 prepare_to_modify_buffer (from, to, &from);
1520 to = from + range_length;
1523 UNGCPRO;
1525 /* Make args be valid */
1526 if (from < BEGV)
1527 from = BEGV;
1528 if (to > ZV)
1529 to = ZV;
1531 from_byte = CHAR_TO_BYTE (from);
1532 to_byte = CHAR_TO_BYTE (to);
1534 nchars_del = to - from;
1535 nbytes_del = to_byte - from_byte;
1537 if (nbytes_del <= 0 && insbytes == 0)
1538 return;
1540 /* Make OUTGOING_INSBYTES describe the text
1541 as it will be inserted in this buffer. */
1543 if (NILP (current_buffer->enable_multibyte_characters))
1544 outgoing_insbytes = inschars;
1545 else if (! STRING_MULTIBYTE (new))
1546 outgoing_insbytes
1547 = count_size_as_multibyte (SDATA (new), insbytes);
1549 /* Make sure point-max won't overflow after this insertion. */
1550 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1551 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1552 error ("Maximum buffer size exceeded");
1554 GCPRO1 (new);
1556 /* Make sure the gap is somewhere in or next to what we are deleting. */
1557 if (from > GPT)
1558 gap_right (from, from_byte);
1559 if (to < GPT)
1560 gap_left (to, to_byte, 0);
1562 /* Even if we don't record for undo, we must keep the original text
1563 because we may have to recover it because of inappropriate byte
1564 combining. */
1565 if (! EQ (current_buffer->undo_list, Qt))
1566 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1568 GAP_SIZE += nbytes_del;
1569 ZV -= nchars_del;
1570 Z -= nchars_del;
1571 ZV_BYTE -= nbytes_del;
1572 Z_BYTE -= nbytes_del;
1573 GPT = from;
1574 GPT_BYTE = from_byte;
1575 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1577 if (GPT_BYTE < GPT)
1578 abort ();
1580 if (GPT - BEG < BEG_UNCHANGED)
1581 BEG_UNCHANGED = GPT - BEG;
1582 if (Z - GPT < END_UNCHANGED)
1583 END_UNCHANGED = Z - GPT;
1585 if (GAP_SIZE < insbytes)
1586 make_gap (insbytes - GAP_SIZE);
1588 /* Copy the string text into the buffer, perhaps converting
1589 between single-byte and multibyte. */
1590 copy_text (SDATA (new), GPT_ADDR, insbytes,
1591 STRING_MULTIBYTE (new),
1592 ! NILP (current_buffer->enable_multibyte_characters));
1594 #ifdef BYTE_COMBINING_DEBUG
1595 /* We have copied text into the gap, but we have not marked
1596 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1597 here, for both the previous text and the following text.
1598 Meanwhile, GPT_ADDR does point to
1599 the text that has been stored by copy_text. */
1600 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1601 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1602 abort ();
1603 #endif
1605 if (! EQ (current_buffer->undo_list, Qt))
1607 /* Record the insertion first, so that when we undo,
1608 the deletion will be undone first. Thus, undo
1609 will insert before deleting, and thus will keep
1610 the markers before and after this text separate. */
1611 record_insert (from + SCHARS (deletion), inschars);
1612 record_delete (from, deletion);
1615 GAP_SIZE -= outgoing_insbytes;
1616 GPT += inschars;
1617 ZV += inschars;
1618 Z += inschars;
1619 GPT_BYTE += outgoing_insbytes;
1620 ZV_BYTE += outgoing_insbytes;
1621 Z_BYTE += outgoing_insbytes;
1622 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1624 if (GPT_BYTE < GPT)
1625 abort ();
1627 /* Adjust the overlay center as needed. This must be done after
1628 adjusting the markers that bound the overlays. */
1629 adjust_overlays_for_delete (from, nchars_del);
1630 adjust_overlays_for_insert (from, inschars);
1632 /* Adjust markers for the deletion and the insertion. */
1633 if (markers)
1634 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1635 inschars, outgoing_insbytes);
1637 offset_intervals (current_buffer, from, inschars - nchars_del);
1639 /* Get the intervals for the part of the string we are inserting--
1640 not including the combined-before bytes. */
1641 intervals = STRING_INTERVALS (new);
1642 /* Insert those intervals. */
1643 graft_intervals_into_buffer (intervals, from, inschars,
1644 current_buffer, inherit);
1646 /* Relocate point as if it were a marker. */
1647 if (from < PT)
1648 adjust_point ((from + inschars - (PT < to ? PT : to)),
1649 (from_byte + outgoing_insbytes
1650 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1652 if (outgoing_insbytes == 0)
1653 evaporate_overlays (from);
1655 CHECK_MARKERS ();
1657 MODIFF++;
1658 CHARS_MODIFF = MODIFF;
1659 UNGCPRO;
1661 signal_after_change (from, nchars_del, GPT - from);
1662 update_compositions (from, GPT, CHECK_BORDER);
1665 /* Replace the text from character positions FROM to TO with
1666 the text in INS of length INSCHARS.
1667 Keep the text properties that applied to the old characters
1668 (extending them to all the new chars if there are more new chars).
1670 Note that this does not yet handle markers quite right.
1672 If MARKERS is nonzero, relocate markers.
1674 Unlike most functions at this level, never call
1675 prepare_to_modify_buffer and never call signal_after_change. */
1677 void
1678 replace_range_2 (from, from_byte, to, to_byte, ins, inschars, insbytes, markers)
1679 int from, from_byte, to, to_byte;
1680 char *ins;
1681 int inschars, insbytes, markers;
1683 int nbytes_del, nchars_del;
1684 Lisp_Object temp;
1686 CHECK_MARKERS ();
1688 nchars_del = to - from;
1689 nbytes_del = to_byte - from_byte;
1691 if (nbytes_del <= 0 && insbytes == 0)
1692 return;
1694 /* Make sure point-max won't overflow after this insertion. */
1695 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1696 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1697 error ("Maximum buffer size exceeded");
1699 /* Make sure the gap is somewhere in or next to what we are deleting. */
1700 if (from > GPT)
1701 gap_right (from, from_byte);
1702 if (to < GPT)
1703 gap_left (to, to_byte, 0);
1705 GAP_SIZE += nbytes_del;
1706 ZV -= nchars_del;
1707 Z -= nchars_del;
1708 ZV_BYTE -= nbytes_del;
1709 Z_BYTE -= nbytes_del;
1710 GPT = from;
1711 GPT_BYTE = from_byte;
1712 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1714 if (GPT_BYTE < GPT)
1715 abort ();
1717 if (GPT - BEG < BEG_UNCHANGED)
1718 BEG_UNCHANGED = GPT - BEG;
1719 if (Z - GPT < END_UNCHANGED)
1720 END_UNCHANGED = Z - GPT;
1722 if (GAP_SIZE < insbytes)
1723 make_gap (insbytes - GAP_SIZE);
1725 /* Copy the replacement text into the buffer. */
1726 bcopy (ins, GPT_ADDR, insbytes);
1728 #ifdef BYTE_COMBINING_DEBUG
1729 /* We have copied text into the gap, but we have not marked
1730 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1731 here, for both the previous text and the following text.
1732 Meanwhile, GPT_ADDR does point to
1733 the text that has been stored by copy_text. */
1734 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1735 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1736 abort ();
1737 #endif
1739 GAP_SIZE -= insbytes;
1740 GPT += inschars;
1741 ZV += inschars;
1742 Z += inschars;
1743 GPT_BYTE += insbytes;
1744 ZV_BYTE += insbytes;
1745 Z_BYTE += insbytes;
1746 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1748 if (GPT_BYTE < GPT)
1749 abort ();
1751 /* Adjust the overlay center as needed. This must be done after
1752 adjusting the markers that bound the overlays. */
1753 if (nchars_del != inschars)
1755 adjust_overlays_for_insert (from, inschars);
1756 adjust_overlays_for_delete (from + inschars, nchars_del);
1759 /* Adjust markers for the deletion and the insertion. */
1760 if (markers
1761 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1762 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1763 inschars, insbytes);
1765 offset_intervals (current_buffer, from, inschars - nchars_del);
1767 /* Relocate point as if it were a marker. */
1768 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1770 if (PT < to)
1771 /* PT was within the deleted text. Move it to FROM. */
1772 adjust_point (from - PT, from_byte - PT_BYTE);
1773 else
1774 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1777 if (insbytes == 0)
1778 evaporate_overlays (from);
1780 CHECK_MARKERS ();
1782 MODIFF++;
1783 CHARS_MODIFF = MODIFF;
1786 /* Delete characters in current buffer
1787 from FROM up to (but not including) TO.
1788 If TO comes before FROM, we delete nothing. */
1790 void
1791 del_range (from, to)
1792 register int from, to;
1794 del_range_1 (from, to, 1, 0);
1797 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1798 RET_STRING says to return the deleted text. */
1800 Lisp_Object
1801 del_range_1 (from, to, prepare, ret_string)
1802 int from, to, prepare, ret_string;
1804 int from_byte, to_byte;
1805 Lisp_Object deletion;
1806 struct gcpro gcpro1;
1808 /* Make args be valid */
1809 if (from < BEGV)
1810 from = BEGV;
1811 if (to > ZV)
1812 to = ZV;
1814 if (to <= from)
1815 return Qnil;
1817 if (prepare)
1819 int range_length = to - from;
1820 prepare_to_modify_buffer (from, to, &from);
1821 to = min (ZV, from + range_length);
1824 from_byte = CHAR_TO_BYTE (from);
1825 to_byte = CHAR_TO_BYTE (to);
1827 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1828 GCPRO1(deletion);
1829 signal_after_change (from, to - from, 0);
1830 update_compositions (from, from, CHECK_HEAD);
1831 UNGCPRO;
1832 return deletion;
1835 /* Like del_range_1 but args are byte positions, not char positions. */
1837 void
1838 del_range_byte (from_byte, to_byte, prepare)
1839 int from_byte, to_byte, prepare;
1841 int from, to;
1843 /* Make args be valid */
1844 if (from_byte < BEGV_BYTE)
1845 from_byte = BEGV_BYTE;
1846 if (to_byte > ZV_BYTE)
1847 to_byte = ZV_BYTE;
1849 if (to_byte <= from_byte)
1850 return;
1852 from = BYTE_TO_CHAR (from_byte);
1853 to = BYTE_TO_CHAR (to_byte);
1855 if (prepare)
1857 int old_from = from, old_to = Z - to;
1858 int range_length = to - from;
1859 prepare_to_modify_buffer (from, to, &from);
1860 to = from + range_length;
1862 if (old_from != from)
1863 from_byte = CHAR_TO_BYTE (from);
1864 if (to > ZV)
1866 to = ZV;
1867 to_byte = ZV_BYTE;
1869 else if (old_to == Z - to)
1870 to_byte = CHAR_TO_BYTE (to);
1873 del_range_2 (from, from_byte, to, to_byte, 0);
1874 signal_after_change (from, to - from, 0);
1875 update_compositions (from, from, CHECK_HEAD);
1878 /* Like del_range_1, but positions are specified both as charpos
1879 and bytepos. */
1881 void
1882 del_range_both (from, from_byte, to, to_byte, prepare)
1883 int from, from_byte, to, to_byte, prepare;
1885 /* Make args be valid */
1886 if (from_byte < BEGV_BYTE)
1887 from_byte = BEGV_BYTE;
1888 if (to_byte > ZV_BYTE)
1889 to_byte = ZV_BYTE;
1891 if (to_byte <= from_byte)
1892 return;
1894 if (from < BEGV)
1895 from = BEGV;
1896 if (to > ZV)
1897 to = ZV;
1899 if (prepare)
1901 int old_from = from, old_to = Z - to;
1902 int range_length = to - from;
1903 prepare_to_modify_buffer (from, to, &from);
1904 to = from + range_length;
1906 if (old_from != from)
1907 from_byte = CHAR_TO_BYTE (from);
1908 if (to > ZV)
1910 to = ZV;
1911 to_byte = ZV_BYTE;
1913 else if (old_to == Z - to)
1914 to_byte = CHAR_TO_BYTE (to);
1917 del_range_2 (from, from_byte, to, to_byte, 0);
1918 signal_after_change (from, to - from, 0);
1919 update_compositions (from, from, CHECK_HEAD);
1922 /* Delete a range of text, specified both as character positions
1923 and byte positions. FROM and TO are character positions,
1924 while FROM_BYTE and TO_BYTE are byte positions.
1925 If RET_STRING is true, the deleted area is returned as a string. */
1927 Lisp_Object
1928 del_range_2 (from, from_byte, to, to_byte, ret_string)
1929 int from, from_byte, to, to_byte, ret_string;
1931 register int nbytes_del, nchars_del;
1932 Lisp_Object deletion;
1934 CHECK_MARKERS ();
1936 nchars_del = to - from;
1937 nbytes_del = to_byte - from_byte;
1939 /* Make sure the gap is somewhere in or next to what we are deleting. */
1940 if (from > GPT)
1941 gap_right (from, from_byte);
1942 if (to < GPT)
1943 gap_left (to, to_byte, 0);
1945 #ifdef BYTE_COMBINING_DEBUG
1946 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1947 Z_BYTE - to_byte, from, from_byte))
1948 abort ();
1949 #endif
1951 if (ret_string || ! EQ (current_buffer->undo_list, Qt))
1952 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1953 else
1954 deletion = Qnil;
1956 /* Relocate all markers pointing into the new, larger gap
1957 to point at the end of the text before the gap.
1958 Do this before recording the deletion,
1959 so that undo handles this after reinserting the text. */
1960 adjust_markers_for_delete (from, from_byte, to, to_byte);
1962 if (! EQ (current_buffer->undo_list, Qt))
1963 record_delete (from, deletion);
1964 MODIFF++;
1965 CHARS_MODIFF = MODIFF;
1967 /* Relocate point as if it were a marker. */
1968 if (from < PT)
1969 adjust_point (from - (PT < to ? PT : to),
1970 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1972 offset_intervals (current_buffer, from, - nchars_del);
1974 /* Adjust the overlay center as needed. This must be done after
1975 adjusting the markers that bound the overlays. */
1976 adjust_overlays_for_delete (from, nchars_del);
1978 GAP_SIZE += nbytes_del;
1979 ZV_BYTE -= nbytes_del;
1980 Z_BYTE -= nbytes_del;
1981 ZV -= nchars_del;
1982 Z -= nchars_del;
1983 GPT = from;
1984 GPT_BYTE = from_byte;
1985 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1987 if (GPT_BYTE < GPT)
1988 abort ();
1990 if (GPT - BEG < BEG_UNCHANGED)
1991 BEG_UNCHANGED = GPT - BEG;
1992 if (Z - GPT < END_UNCHANGED)
1993 END_UNCHANGED = Z - GPT;
1995 CHECK_MARKERS ();
1997 evaporate_overlays (from);
1999 return deletion;
2002 /* Call this if you're about to change the region of BUFFER from
2003 character positions START to END. This checks the read-only
2004 properties of the region, calls the necessary modification hooks,
2005 and warns the next redisplay that it should pay attention to that
2006 area.
2008 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
2009 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
2011 void
2012 modify_region (buffer, start, end, preserve_chars_modiff)
2013 struct buffer *buffer;
2014 int start, end, preserve_chars_modiff;
2016 struct buffer *old_buffer = current_buffer;
2018 if (buffer != old_buffer)
2019 set_buffer_internal (buffer);
2021 prepare_to_modify_buffer (start, end, NULL);
2023 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
2025 if (MODIFF <= SAVE_MODIFF)
2026 record_first_change ();
2027 MODIFF++;
2028 if (! preserve_chars_modiff)
2029 CHARS_MODIFF = MODIFF;
2031 buffer->point_before_scroll = Qnil;
2033 if (buffer != old_buffer)
2034 set_buffer_internal (old_buffer);
2037 /* Check that it is okay to modify the buffer between START and END,
2038 which are char positions.
2040 Run the before-change-function, if any. If intervals are in use,
2041 verify that the text to be modified is not read-only, and call
2042 any modification properties the text may have.
2044 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2045 by holding its value temporarily in a marker. */
2047 void
2048 prepare_to_modify_buffer (start, end, preserve_ptr)
2049 int start, end;
2050 int *preserve_ptr;
2052 struct buffer *base_buffer;
2054 if (!NILP (current_buffer->read_only))
2055 Fbarf_if_buffer_read_only ();
2057 /* Let redisplay consider other windows than selected_window
2058 if modifying another buffer. */
2059 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2060 ++windows_or_buffers_changed;
2062 if (BUF_INTERVALS (current_buffer) != 0)
2064 if (preserve_ptr)
2066 Lisp_Object preserve_marker;
2067 struct gcpro gcpro1;
2068 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
2069 GCPRO1 (preserve_marker);
2070 verify_interval_modification (current_buffer, start, end);
2071 *preserve_ptr = marker_position (preserve_marker);
2072 unchain_marker (XMARKER (preserve_marker));
2073 UNGCPRO;
2075 else
2076 verify_interval_modification (current_buffer, start, end);
2079 /* For indirect buffers, use the base buffer to check clashes. */
2080 if (current_buffer->base_buffer != 0)
2081 base_buffer = current_buffer->base_buffer;
2082 else
2083 base_buffer = current_buffer;
2085 #ifdef CLASH_DETECTION
2086 if (!NILP (base_buffer->file_truename)
2087 /* Make binding buffer-file-name to nil effective. */
2088 && !NILP (base_buffer->filename)
2089 && SAVE_MODIFF >= MODIFF)
2090 lock_file (base_buffer->file_truename);
2091 #else
2092 /* At least warn if this file has changed on disk since it was visited. */
2093 if (!NILP (base_buffer->filename)
2094 && SAVE_MODIFF >= MODIFF
2095 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
2096 && !NILP (Ffile_exists_p (base_buffer->filename)))
2097 call1 (intern ("ask-user-about-supersession-threat"),
2098 base_buffer->filename);
2099 #endif /* not CLASH_DETECTION */
2101 signal_before_change (start, end, preserve_ptr);
2103 if (current_buffer->newline_cache)
2104 invalidate_region_cache (current_buffer,
2105 current_buffer->newline_cache,
2106 start - BEG, Z - end);
2107 if (current_buffer->width_run_cache)
2108 invalidate_region_cache (current_buffer,
2109 current_buffer->width_run_cache,
2110 start - BEG, Z - end);
2112 Vdeactivate_mark = Qt;
2115 /* These macros work with an argument named `preserve_ptr'
2116 and a local variable named `preserve_marker'. */
2118 #define PRESERVE_VALUE \
2119 if (preserve_ptr && NILP (preserve_marker)) \
2120 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2122 #define RESTORE_VALUE \
2123 if (! NILP (preserve_marker)) \
2125 *preserve_ptr = marker_position (preserve_marker); \
2126 unchain_marker (XMARKER (preserve_marker)); \
2129 #define PRESERVE_START_END \
2130 if (NILP (start_marker)) \
2131 start_marker = Fcopy_marker (start, Qnil); \
2132 if (NILP (end_marker)) \
2133 end_marker = Fcopy_marker (end, Qnil);
2135 #define FETCH_START \
2136 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2138 #define FETCH_END \
2139 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2141 /* Set a variable to nil if an error occurred.
2142 Don't change the variable if there was no error.
2143 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
2144 VARIABLE is the variable to maybe set to nil.
2145 NO-ERROR-FLAG is nil if there was an error,
2146 anything else meaning no error (so this function does nothing). */
2147 Lisp_Object
2148 reset_var_on_error (val)
2149 Lisp_Object val;
2151 if (NILP (XCDR (val)))
2152 Fset (XCAR (val), Qnil);
2153 return Qnil;
2156 /* Signal a change to the buffer immediately before it happens.
2157 START_INT and END_INT are the bounds of the text to be changed.
2159 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2160 by holding its value temporarily in a marker. */
2162 void
2163 signal_before_change (start_int, end_int, preserve_ptr)
2164 int start_int, end_int;
2165 int *preserve_ptr;
2167 Lisp_Object start, end;
2168 Lisp_Object start_marker, end_marker;
2169 Lisp_Object preserve_marker;
2170 struct gcpro gcpro1, gcpro2, gcpro3;
2171 int count = SPECPDL_INDEX ();
2173 if (inhibit_modification_hooks)
2174 return;
2176 start = make_number (start_int);
2177 end = make_number (end_int);
2178 preserve_marker = Qnil;
2179 start_marker = Qnil;
2180 end_marker = Qnil;
2181 GCPRO3 (preserve_marker, start_marker, end_marker);
2183 specbind (Qinhibit_modification_hooks, Qt);
2185 /* If buffer is unmodified, run a special hook for that case. */
2186 if (SAVE_MODIFF >= MODIFF
2187 && !NILP (Vfirst_change_hook)
2188 && !NILP (Vrun_hooks))
2190 PRESERVE_VALUE;
2191 PRESERVE_START_END;
2192 call1 (Vrun_hooks, Qfirst_change_hook);
2195 /* Now run the before-change-functions if any. */
2196 if (!NILP (Vbefore_change_functions))
2198 Lisp_Object args[3];
2199 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
2201 PRESERVE_VALUE;
2202 PRESERVE_START_END;
2204 /* Mark before-change-functions to be reset to nil in case of error. */
2205 record_unwind_protect (reset_var_on_error, rvoe_arg);
2207 /* Actually run the hook functions. */
2208 args[0] = Qbefore_change_functions;
2209 args[1] = FETCH_START;
2210 args[2] = FETCH_END;
2211 Frun_hook_with_args (3, args);
2213 /* There was no error: unarm the reset_on_error. */
2214 XSETCDR (rvoe_arg, Qt);
2217 if (current_buffer->overlays_before || current_buffer->overlays_after)
2219 PRESERVE_VALUE;
2220 report_overlay_modification (FETCH_START, FETCH_END, 0,
2221 FETCH_START, FETCH_END, Qnil);
2224 if (! NILP (start_marker))
2225 free_marker (start_marker);
2226 if (! NILP (end_marker))
2227 free_marker (end_marker);
2228 RESTORE_VALUE;
2229 UNGCPRO;
2231 unbind_to (count, Qnil);
2234 /* Signal a change immediately after it happens.
2235 CHARPOS is the character position of the start of the changed text.
2236 LENDEL is the number of characters of the text before the change.
2237 (Not the whole buffer; just the part that was changed.)
2238 LENINS is the number of characters in that part of the text
2239 after the change. */
2241 void
2242 signal_after_change (charpos, lendel, lenins)
2243 int charpos, lendel, lenins;
2245 int count = SPECPDL_INDEX ();
2246 if (inhibit_modification_hooks)
2247 return;
2249 /* If we are deferring calls to the after-change functions
2250 and there are no before-change functions,
2251 just record the args that we were going to use. */
2252 if (! NILP (Vcombine_after_change_calls)
2253 && NILP (Vbefore_change_functions)
2254 && !current_buffer->overlays_before
2255 && !current_buffer->overlays_after)
2257 Lisp_Object elt;
2259 if (!NILP (combine_after_change_list)
2260 && current_buffer != XBUFFER (combine_after_change_buffer))
2261 Fcombine_after_change_execute ();
2263 elt = Fcons (make_number (charpos - BEG),
2264 Fcons (make_number (Z - (charpos - lendel + lenins)),
2265 Fcons (make_number (lenins - lendel), Qnil)));
2266 combine_after_change_list
2267 = Fcons (elt, combine_after_change_list);
2268 combine_after_change_buffer = Fcurrent_buffer ();
2270 return;
2273 if (!NILP (combine_after_change_list))
2274 Fcombine_after_change_execute ();
2276 specbind (Qinhibit_modification_hooks, Qt);
2278 if (!NILP (Vafter_change_functions))
2280 Lisp_Object args[4];
2281 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2283 /* Mark after-change-functions to be reset to nil in case of error. */
2284 record_unwind_protect (reset_var_on_error, rvoe_arg);
2286 /* Actually run the hook functions. */
2287 args[0] = Qafter_change_functions;
2288 XSETFASTINT (args[1], charpos);
2289 XSETFASTINT (args[2], charpos + lenins);
2290 XSETFASTINT (args[3], lendel);
2291 Frun_hook_with_args (4, args);
2293 /* There was no error: unarm the reset_on_error. */
2294 XSETCDR (rvoe_arg, Qt);
2297 if (current_buffer->overlays_before || current_buffer->overlays_after)
2298 report_overlay_modification (make_number (charpos),
2299 make_number (charpos + lenins),
2301 make_number (charpos),
2302 make_number (charpos + lenins),
2303 make_number (lendel));
2305 /* After an insertion, call the text properties
2306 insert-behind-hooks or insert-in-front-hooks. */
2307 if (lendel == 0)
2308 report_interval_modification (make_number (charpos),
2309 make_number (charpos + lenins));
2311 unbind_to (count, Qnil);
2314 Lisp_Object
2315 Fcombine_after_change_execute_1 (val)
2316 Lisp_Object val;
2318 Vcombine_after_change_calls = val;
2319 return val;
2322 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2323 Scombine_after_change_execute, 0, 0, 0,
2324 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2327 int count = SPECPDL_INDEX ();
2328 int beg, end, change;
2329 int begpos, endpos;
2330 Lisp_Object tail;
2332 if (NILP (combine_after_change_list))
2333 return Qnil;
2335 /* It is rare for combine_after_change_buffer to be invalid, but
2336 possible. It can happen when combine-after-change-calls is
2337 non-nil, and insertion calls a file handler (e.g. through
2338 lock_file) which scribbles into a temp file -- cyd */
2339 if (!BUFFERP (combine_after_change_buffer)
2340 || NILP (XBUFFER (combine_after_change_buffer)->name))
2342 combine_after_change_list = Qnil;
2343 return Qnil;
2346 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2348 Fset_buffer (combine_after_change_buffer);
2350 /* # chars unchanged at beginning of buffer. */
2351 beg = Z - BEG;
2352 /* # chars unchanged at end of buffer. */
2353 end = beg;
2354 /* Total amount of insertion (negative for deletion). */
2355 change = 0;
2357 /* Scan the various individual changes,
2358 accumulating the range info in BEG, END and CHANGE. */
2359 for (tail = combine_after_change_list; CONSP (tail);
2360 tail = XCDR (tail))
2362 Lisp_Object elt;
2363 int thisbeg, thisend, thischange;
2365 /* Extract the info from the next element. */
2366 elt = XCAR (tail);
2367 if (! CONSP (elt))
2368 continue;
2369 thisbeg = XINT (XCAR (elt));
2371 elt = XCDR (elt);
2372 if (! CONSP (elt))
2373 continue;
2374 thisend = XINT (XCAR (elt));
2376 elt = XCDR (elt);
2377 if (! CONSP (elt))
2378 continue;
2379 thischange = XINT (XCAR (elt));
2381 /* Merge this range into the accumulated range. */
2382 change += thischange;
2383 if (thisbeg < beg)
2384 beg = thisbeg;
2385 if (thisend < end)
2386 end = thisend;
2389 /* Get the current start and end positions of the range
2390 that was changed. */
2391 begpos = BEG + beg;
2392 endpos = Z - end;
2394 /* We are about to handle these, so discard them. */
2395 combine_after_change_list = Qnil;
2397 /* Now run the after-change functions for real.
2398 Turn off the flag that defers them. */
2399 record_unwind_protect (Fcombine_after_change_execute_1,
2400 Vcombine_after_change_calls);
2401 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2402 update_compositions (begpos, endpos, CHECK_ALL);
2404 return unbind_to (count, Qnil);
2407 void
2408 syms_of_insdel ()
2410 staticpro (&combine_after_change_list);
2411 staticpro (&combine_after_change_buffer);
2412 combine_after_change_list = Qnil;
2413 combine_after_change_buffer = Qnil;
2415 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag,
2416 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
2417 check_markers_debug_flag = 0;
2418 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
2419 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2420 Vcombine_after_change_calls = Qnil;
2422 DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks,
2423 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2424 This affects `before-change-functions' and `after-change-functions',
2425 as well as hooks attached to text properties and overlays. */);
2426 inhibit_modification_hooks = 0;
2427 Qinhibit_modification_hooks = intern ("inhibit-modification-hooks");
2428 staticpro (&Qinhibit_modification_hooks);
2430 defsubr (&Scombine_after_change_execute);
2433 /* arch-tag: 9b34b886-47d7-465e-a234-299af411b23d
2434 (do not change this comment) */