* xdisp.c (init_iterator): Use XINT, not XFASTINT; it might be < 0.
[emacs.git] / src / insdel.c
blobbc95e3ad9e86628a83fe02b632a57b32920f730f
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985-1986, 1993-1995, 1997-2011
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
22 #include <setjmp.h>
24 #include <intprops.h>
26 #include "lisp.h"
27 #include "intervals.h"
28 #include "buffer.h"
29 #include "character.h"
30 #include "window.h"
31 #include "blockinput.h"
32 #include "region-cache.h"
34 #ifndef NULL
35 #define NULL 0
36 #endif
38 static void insert_from_string_1 (Lisp_Object string,
39 EMACS_INT pos, EMACS_INT pos_byte,
40 EMACS_INT nchars, EMACS_INT nbytes,
41 int inherit, int before_markers);
42 static void insert_from_buffer_1 (struct buffer *buf,
43 EMACS_INT from, EMACS_INT nchars,
44 int inherit);
45 static void gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap);
46 static void gap_right (EMACS_INT charpos, EMACS_INT bytepos);
47 static void adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
48 EMACS_INT to, EMACS_INT to_byte,
49 int before_markers);
50 static void adjust_markers_for_replace (EMACS_INT, EMACS_INT, EMACS_INT,
51 EMACS_INT, EMACS_INT, EMACS_INT);
52 static void adjust_point (EMACS_INT nchars, EMACS_INT nbytes);
54 static Lisp_Object Fcombine_after_change_execute (void);
56 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
57 describing changes which happened while combine_after_change_calls
58 was nonzero. We use this to decide how to call them
59 once the deferral ends.
61 In each element.
62 BEG-UNCHANGED is the number of chars before the changed range.
63 END-UNCHANGED is the number of chars after the changed range,
64 and CHANGE-AMOUNT is the number of characters inserted by the change
65 (negative for a deletion). */
66 static Lisp_Object combine_after_change_list;
68 /* Buffer which combine_after_change_list is about. */
69 static Lisp_Object combine_after_change_buffer;
71 Lisp_Object Qinhibit_modification_hooks;
73 static void signal_before_change (EMACS_INT, EMACS_INT, EMACS_INT *);
75 #define CHECK_MARKERS() \
76 do \
77 { \
78 if (check_markers_debug_flag) \
79 check_markers (); \
80 } \
81 while (0)
83 static void
84 check_markers (void)
86 register struct Lisp_Marker *tail;
87 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
89 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
91 if (tail->buffer->text != current_buffer->text)
92 abort ();
93 if (tail->charpos > Z)
94 abort ();
95 if (tail->bytepos > Z_BYTE)
96 abort ();
97 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
98 abort ();
102 /* Move gap to position CHARPOS.
103 Note that this can quit! */
105 void
106 move_gap (EMACS_INT charpos)
108 move_gap_both (charpos, charpos_to_bytepos (charpos));
111 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
112 Note that this can quit! */
114 void
115 move_gap_both (EMACS_INT charpos, EMACS_INT bytepos)
117 if (bytepos < GPT_BYTE)
118 gap_left (charpos, bytepos, 0);
119 else if (bytepos > GPT_BYTE)
120 gap_right (charpos, bytepos);
123 /* Move the gap to a position less than the current GPT.
124 BYTEPOS describes the new position as a byte position,
125 and CHARPOS is the corresponding char position.
126 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
128 static void
129 gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap)
131 register unsigned char *to, *from;
132 register EMACS_INT i;
133 EMACS_INT new_s1;
135 if (!newgap)
136 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
138 i = GPT_BYTE;
139 to = GAP_END_ADDR;
140 from = GPT_ADDR;
141 new_s1 = GPT_BYTE;
143 /* Now copy the characters. To move the gap down,
144 copy characters up. */
146 while (1)
148 /* I gets number of characters left to copy. */
149 i = new_s1 - bytepos;
150 if (i == 0)
151 break;
152 /* If a quit is requested, stop copying now.
153 Change BYTEPOS to be where we have actually moved the gap to. */
154 if (QUITP)
156 bytepos = new_s1;
157 charpos = BYTE_TO_CHAR (bytepos);
158 break;
160 /* Move at most 32000 chars before checking again for a quit. */
161 if (i > 32000)
162 i = 32000;
163 new_s1 -= i;
164 from -= i, to -= i;
165 memmove (to, from, i);
168 /* Adjust buffer data structure, to put the gap at BYTEPOS.
169 BYTEPOS is where the loop above stopped, which may be what
170 was specified or may be where a quit was detected. */
171 GPT_BYTE = bytepos;
172 GPT = charpos;
173 if (bytepos < charpos)
174 abort ();
175 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
176 QUIT;
179 /* Move the gap to a position greater than the current GPT.
180 BYTEPOS describes the new position as a byte position,
181 and CHARPOS is the corresponding char position. */
183 static void
184 gap_right (EMACS_INT charpos, EMACS_INT bytepos)
186 register unsigned char *to, *from;
187 register EMACS_INT i;
188 EMACS_INT new_s1;
190 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
192 i = GPT_BYTE;
193 from = GAP_END_ADDR;
194 to = GPT_ADDR;
195 new_s1 = GPT_BYTE;
197 /* Now copy the characters. To move the gap up,
198 copy characters down. */
200 while (1)
202 /* I gets number of characters left to copy. */
203 i = bytepos - new_s1;
204 if (i == 0)
205 break;
206 /* If a quit is requested, stop copying now.
207 Change BYTEPOS to be where we have actually moved the gap to. */
208 if (QUITP)
210 bytepos = new_s1;
211 charpos = BYTE_TO_CHAR (bytepos);
212 break;
214 /* Move at most 32000 chars before checking again for a quit. */
215 if (i > 32000)
216 i = 32000;
217 new_s1 += i;
218 memmove (to, from, i);
219 from += i, to += i;
222 GPT = charpos;
223 GPT_BYTE = bytepos;
224 if (bytepos < charpos)
225 abort ();
226 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
227 QUIT;
230 /* Adjust all markers for a deletion
231 whose range in bytes is FROM_BYTE to TO_BYTE.
232 The range in charpos is FROM to TO.
234 This function assumes that the gap is adjacent to
235 or inside of the range being deleted. */
237 void
238 adjust_markers_for_delete (EMACS_INT from, EMACS_INT from_byte,
239 EMACS_INT to, EMACS_INT to_byte)
241 Lisp_Object marker;
242 register struct Lisp_Marker *m;
243 register EMACS_INT charpos;
245 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
247 charpos = m->charpos;
249 if (charpos > Z)
250 abort ();
252 /* If the marker is after the deletion,
253 relocate by number of chars / bytes deleted. */
254 if (charpos > to)
256 m->charpos -= to - from;
257 m->bytepos -= to_byte - from_byte;
259 /* Here's the case where a marker is inside text being deleted. */
260 else if (charpos > from)
262 if (! m->insertion_type)
263 { /* Normal markers will end up at the beginning of the
264 re-inserted text after undoing a deletion, and must be
265 adjusted to move them to the correct place. */
266 XSETMISC (marker, m);
267 record_marker_adjustment (marker, from - charpos);
269 else if (charpos < to)
270 { /* Before-insertion markers will automatically move forward
271 upon re-inserting the deleted text, so we have to arrange
272 for them to move backward to the correct position. */
273 XSETMISC (marker, m);
274 record_marker_adjustment (marker, to - charpos);
276 m->charpos = from;
277 m->bytepos = from_byte;
279 /* Here's the case where a before-insertion marker is immediately
280 before the deleted region. */
281 else if (charpos == from && m->insertion_type)
283 /* Undoing the change uses normal insertion, which will
284 incorrectly make MARKER move forward, so we arrange for it
285 to then move backward to the correct place at the beginning
286 of the deleted region. */
287 XSETMISC (marker, m);
288 record_marker_adjustment (marker, to - from);
294 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
295 to TO / TO_BYTE. We have to relocate the charpos of every marker
296 that points after the insertion (but not their bytepos).
298 When a marker points at the insertion point,
299 we advance it if either its insertion-type is t
300 or BEFORE_MARKERS is true. */
302 static void
303 adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
304 EMACS_INT to, EMACS_INT to_byte, int before_markers)
306 struct Lisp_Marker *m;
307 int adjusted = 0;
308 EMACS_INT nchars = to - from;
309 EMACS_INT nbytes = to_byte - from_byte;
311 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
313 eassert (m->bytepos >= m->charpos
314 && m->bytepos - m->charpos <= Z_BYTE - Z);
316 if (m->bytepos == from_byte)
318 if (m->insertion_type || before_markers)
320 m->bytepos = to_byte;
321 m->charpos = to;
322 if (m->insertion_type)
323 adjusted = 1;
326 else if (m->bytepos > from_byte)
328 m->bytepos += nbytes;
329 m->charpos += nchars;
333 /* Adjusting only markers whose insertion-type is t may result in
334 - disordered start and end in overlays, and
335 - disordered overlays in the slot `overlays_before' of current_buffer. */
336 if (adjusted)
338 fix_start_end_in_overlays(from, to);
339 fix_overlays_before (current_buffer, from, to);
343 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
345 This is used only when the value of point changes due to an insert
346 or delete; it does not represent a conceptual change in point as a
347 marker. In particular, point is not crossing any interval
348 boundaries, so there's no need to use the usual SET_PT macro. In
349 fact it would be incorrect to do so, because either the old or the
350 new value of point is out of sync with the current set of
351 intervals. */
353 static void
354 adjust_point (EMACS_INT nchars, EMACS_INT nbytes)
356 SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes);
357 /* In a single-byte buffer, the two positions must be equal. */
358 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
361 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
362 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
363 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
364 an insertion. */
366 static void
367 adjust_markers_for_replace (EMACS_INT from, EMACS_INT from_byte,
368 EMACS_INT old_chars, EMACS_INT old_bytes,
369 EMACS_INT new_chars, EMACS_INT new_bytes)
371 register struct Lisp_Marker *m;
372 EMACS_INT prev_to_byte = from_byte + old_bytes;
373 EMACS_INT diff_chars = new_chars - old_chars;
374 EMACS_INT diff_bytes = new_bytes - old_bytes;
376 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
378 if (m->bytepos >= prev_to_byte)
380 m->charpos += diff_chars;
381 m->bytepos += diff_bytes;
383 else if (m->bytepos > from_byte)
385 m->charpos = from;
386 m->bytepos = from_byte;
390 CHECK_MARKERS ();
394 void
395 buffer_overflow (void)
397 error ("Maximum buffer size exceeded");
400 /* Make the gap NBYTES_ADDED bytes longer. */
402 static void
403 make_gap_larger (EMACS_INT nbytes_added)
405 Lisp_Object tem;
406 EMACS_INT real_gap_loc;
407 EMACS_INT real_gap_loc_byte;
408 EMACS_INT old_gap_size;
409 EMACS_INT current_size = Z_BYTE - BEG_BYTE + GAP_SIZE;
410 enum { enough_for_a_while = 2000 };
412 if (BUF_BYTES_MAX - current_size < nbytes_added)
413 buffer_overflow ();
415 /* If we have to get more space, get enough to last a while;
416 but do not exceed the maximum buffer size. */
417 nbytes_added = min (nbytes_added + enough_for_a_while,
418 BUF_BYTES_MAX - current_size);
420 enlarge_buffer_text (current_buffer, nbytes_added);
422 /* Prevent quitting in move_gap. */
423 tem = Vinhibit_quit;
424 Vinhibit_quit = Qt;
426 real_gap_loc = GPT;
427 real_gap_loc_byte = GPT_BYTE;
428 old_gap_size = GAP_SIZE;
430 /* Call the newly allocated space a gap at the end of the whole space. */
431 GPT = Z + GAP_SIZE;
432 GPT_BYTE = Z_BYTE + GAP_SIZE;
433 GAP_SIZE = nbytes_added;
435 /* Move the new gap down to be consecutive with the end of the old one.
436 This adjusts the markers properly too. */
437 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
439 /* Now combine the two into one large gap. */
440 GAP_SIZE += old_gap_size;
441 GPT = real_gap_loc;
442 GPT_BYTE = real_gap_loc_byte;
444 /* Put an anchor. */
445 *(Z_ADDR) = 0;
447 Vinhibit_quit = tem;
450 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
452 /* Make the gap NBYTES_REMOVED bytes shorter. */
454 static void
455 make_gap_smaller (EMACS_INT nbytes_removed)
457 Lisp_Object tem;
458 EMACS_INT real_gap_loc;
459 EMACS_INT real_gap_loc_byte;
460 EMACS_INT real_Z;
461 EMACS_INT real_Z_byte;
462 EMACS_INT real_beg_unchanged;
463 EMACS_INT new_gap_size;
465 /* Make sure the gap is at least 20 bytes. */
466 if (GAP_SIZE - nbytes_removed < 20)
467 nbytes_removed = GAP_SIZE - 20;
469 /* Prevent quitting in move_gap. */
470 tem = Vinhibit_quit;
471 Vinhibit_quit = Qt;
473 real_gap_loc = GPT;
474 real_gap_loc_byte = GPT_BYTE;
475 new_gap_size = GAP_SIZE - nbytes_removed;
476 real_Z = Z;
477 real_Z_byte = Z_BYTE;
478 real_beg_unchanged = BEG_UNCHANGED;
480 /* Pretend that the last unwanted part of the gap is the entire gap,
481 and that the first desired part of the gap is part of the buffer
482 text. */
483 memset (GPT_ADDR, 0, new_gap_size);
484 GPT += new_gap_size;
485 GPT_BYTE += new_gap_size;
486 Z += new_gap_size;
487 Z_BYTE += new_gap_size;
488 GAP_SIZE = nbytes_removed;
490 /* Move the unwanted pretend gap to the end of the buffer. This
491 adjusts the markers properly too. */
492 gap_right (Z, Z_BYTE);
494 enlarge_buffer_text (current_buffer, -nbytes_removed);
496 /* Now restore the desired gap. */
497 GAP_SIZE = new_gap_size;
498 GPT = real_gap_loc;
499 GPT_BYTE = real_gap_loc_byte;
500 Z = real_Z;
501 Z_BYTE = real_Z_byte;
502 BEG_UNCHANGED = real_beg_unchanged;
504 /* Put an anchor. */
505 *(Z_ADDR) = 0;
507 Vinhibit_quit = tem;
510 #endif /* USE_MMAP_FOR_BUFFERS || REL_ALLOC || DOUG_LEA_MALLOC */
512 void
513 make_gap (EMACS_INT nbytes_added)
515 if (nbytes_added >= 0)
516 make_gap_larger (nbytes_added);
517 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
518 else
519 make_gap_smaller (-nbytes_added);
520 #endif
523 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
524 FROM_MULTIBYTE says whether the incoming text is multibyte.
525 TO_MULTIBYTE says whether to store the text as multibyte.
526 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
528 Return the number of bytes stored at TO_ADDR. */
530 EMACS_INT
531 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
532 EMACS_INT nbytes, int from_multibyte, int to_multibyte)
534 if (from_multibyte == to_multibyte)
536 memcpy (to_addr, from_addr, nbytes);
537 return nbytes;
539 else if (from_multibyte)
541 EMACS_INT nchars = 0;
542 EMACS_INT bytes_left = nbytes;
544 while (bytes_left > 0)
546 int thislen, c;
547 c = STRING_CHAR_AND_LENGTH (from_addr, thislen);
548 if (! ASCII_CHAR_P (c))
549 c &= 0xFF;
550 *to_addr++ = c;
551 from_addr += thislen;
552 bytes_left -= thislen;
553 nchars++;
555 return nchars;
557 else
559 unsigned char *initial_to_addr = to_addr;
561 /* Convert single-byte to multibyte. */
562 while (nbytes > 0)
564 int c = *from_addr++;
566 if (!ASCII_CHAR_P (c))
568 c = BYTE8_TO_CHAR (c);
569 to_addr += CHAR_STRING (c, to_addr);
570 nbytes--;
572 else
573 /* Special case for speed. */
574 *to_addr++ = c, nbytes--;
576 return to_addr - initial_to_addr;
580 /* Insert a string of specified length before point.
581 This function judges multibyteness based on
582 enable_multibyte_characters in the current buffer;
583 it never converts between single-byte and multibyte.
585 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
586 prepare_to_modify_buffer could relocate the text. */
588 void
589 insert (const char *string, EMACS_INT nbytes)
591 if (nbytes > 0)
593 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
594 insert_1_both (string, len, nbytes, 0, 1, 0);
595 opoint = PT - len;
596 signal_after_change (opoint, 0, len);
597 update_compositions (opoint, PT, CHECK_BORDER);
601 /* Likewise, but inherit text properties from neighboring characters. */
603 void
604 insert_and_inherit (const char *string, EMACS_INT nbytes)
606 if (nbytes > 0)
608 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
609 insert_1_both (string, len, nbytes, 1, 1, 0);
610 opoint = PT - len;
611 signal_after_change (opoint, 0, len);
612 update_compositions (opoint, PT, CHECK_BORDER);
616 /* Insert the character C before point. Do not inherit text properties. */
618 void
619 insert_char (int c)
621 unsigned char str[MAX_MULTIBYTE_LENGTH];
622 int len;
624 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
625 len = CHAR_STRING (c, str);
626 else
628 len = 1;
629 str[0] = c;
632 insert ((char *) str, len);
635 /* Insert the null-terminated string S before point. */
637 void
638 insert_string (const char *s)
640 insert (s, strlen (s));
643 /* Like `insert' except that all markers pointing at the place where
644 the insertion happens are adjusted to point after it.
645 Don't use this function to insert part of a Lisp string,
646 since gc could happen and relocate it. */
648 void
649 insert_before_markers (const char *string, EMACS_INT nbytes)
651 if (nbytes > 0)
653 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
654 insert_1_both (string, len, nbytes, 0, 1, 1);
655 opoint = PT - len;
656 signal_after_change (opoint, 0, len);
657 update_compositions (opoint, PT, CHECK_BORDER);
661 /* Likewise, but inherit text properties from neighboring characters. */
663 void
664 insert_before_markers_and_inherit (const char *string,
665 EMACS_INT nbytes)
667 if (nbytes > 0)
669 EMACS_INT len = chars_in_text ((unsigned char *) string, nbytes), opoint;
670 insert_1_both (string, len, nbytes, 1, 1, 1);
671 opoint = PT - len;
672 signal_after_change (opoint, 0, len);
673 update_compositions (opoint, PT, CHECK_BORDER);
677 /* Subroutine used by the insert functions above. */
679 void
680 insert_1 (const char *string, EMACS_INT nbytes,
681 int inherit, int prepare, int before_markers)
683 insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
684 nbytes, inherit, prepare, before_markers);
688 #ifdef BYTE_COMBINING_DEBUG
690 /* See if the bytes before POS/POS_BYTE combine with bytes
691 at the start of STRING to form a single character.
692 If so, return the number of bytes at the start of STRING
693 which combine in this way. Otherwise, return 0. */
696 count_combining_before (const unsigned char *string, EMACS_INT length,
697 EMACS_INT pos, EMACS_INT pos_byte)
699 int len, combining_bytes;
700 const unsigned char *p;
702 if (NILP (current_buffer->enable_multibyte_characters))
703 return 0;
705 /* At first, we can exclude the following cases:
706 (1) STRING[0] can't be a following byte of multibyte sequence.
707 (2) POS is the start of the current buffer.
708 (3) A character before POS is not a multibyte character. */
709 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
710 return 0;
711 if (pos_byte == BEG_BYTE) /* case (2) */
712 return 0;
713 len = 1;
714 p = BYTE_POS_ADDR (pos_byte - 1);
715 while (! CHAR_HEAD_P (*p)) p--, len++;
716 if (! LEADING_CODE_P (*p)) /* case (3) */
717 return 0;
719 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
720 if (combining_bytes <= 0)
721 /* The character preceding POS is, complete and no room for
722 combining bytes (combining_bytes == 0), or an independent 8-bit
723 character (combining_bytes < 0). */
724 return 0;
726 /* We have a combination situation. Count the bytes at STRING that
727 may combine. */
728 p = string + 1;
729 while (!CHAR_HEAD_P (*p) && p < string + length)
730 p++;
732 return (combining_bytes < p - string ? combining_bytes : p - string);
735 /* See if the bytes after POS/POS_BYTE combine with bytes
736 at the end of STRING to form a single character.
737 If so, return the number of bytes after POS/POS_BYTE
738 which combine in this way. Otherwise, return 0. */
741 count_combining_after (const unsigned char *string,
742 EMACS_INT length, EMACS_INT pos, EMACS_INT pos_byte)
744 EMACS_INT opos_byte = pos_byte;
745 EMACS_INT i;
746 EMACS_INT bytes;
747 unsigned char *bufp;
749 if (NILP (current_buffer->enable_multibyte_characters))
750 return 0;
752 /* At first, we can exclude the following cases:
753 (1) The last byte of STRING is an ASCII.
754 (2) POS is the last of the current buffer.
755 (3) A character at POS can't be a following byte of multibyte
756 character. */
757 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
758 return 0;
759 if (pos_byte == Z_BYTE) /* case (2) */
760 return 0;
761 bufp = BYTE_POS_ADDR (pos_byte);
762 if (CHAR_HEAD_P (*bufp)) /* case (3) */
763 return 0;
765 i = length - 1;
766 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
768 i--;
770 if (i < 0)
772 /* All characters in STRING are not character head. We must
773 check also preceding bytes at POS. We are sure that the gap
774 is at POS. */
775 unsigned char *p = BEG_ADDR;
776 i = pos_byte - 2;
777 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
778 i--;
779 if (i < 0 || !LEADING_CODE_P (p[i]))
780 return 0;
782 bytes = BYTES_BY_CHAR_HEAD (p[i]);
783 return (bytes <= pos_byte - 1 - i + length
785 : bytes - (pos_byte - 1 - i + length));
787 if (!LEADING_CODE_P (string[i]))
788 return 0;
790 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
791 bufp++, pos_byte++;
792 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
794 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
797 #endif
800 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
801 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
802 are the same as in insert_1. */
804 void
805 insert_1_both (const char *string,
806 EMACS_INT nchars, EMACS_INT nbytes,
807 int inherit, int prepare, int before_markers)
809 if (nchars == 0)
810 return;
812 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
813 nchars = nbytes;
815 if (prepare)
816 /* Do this before moving and increasing the gap,
817 because the before-change hooks might move the gap
818 or make it smaller. */
819 prepare_to_modify_buffer (PT, PT, NULL);
821 if (PT != GPT)
822 move_gap_both (PT, PT_BYTE);
823 if (GAP_SIZE < nbytes)
824 make_gap (nbytes - GAP_SIZE);
826 #ifdef BYTE_COMBINING_DEBUG
827 if (count_combining_before (string, nbytes, PT, PT_BYTE)
828 || count_combining_after (string, nbytes, PT, PT_BYTE))
829 abort ();
830 #endif
832 /* Record deletion of the surrounding text that combines with
833 the insertion. This, together with recording the insertion,
834 will add up to the right stuff in the undo list. */
835 record_insert (PT, nchars);
836 MODIFF++;
837 CHARS_MODIFF = MODIFF;
839 memcpy (GPT_ADDR, string, nbytes);
841 GAP_SIZE -= nbytes;
842 GPT += nchars;
843 ZV += nchars;
844 Z += nchars;
845 GPT_BYTE += nbytes;
846 ZV_BYTE += nbytes;
847 Z_BYTE += nbytes;
848 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
850 if (GPT_BYTE < GPT)
851 abort ();
853 /* The insert may have been in the unchanged region, so check again. */
854 if (Z - GPT < END_UNCHANGED)
855 END_UNCHANGED = Z - GPT;
857 adjust_overlays_for_insert (PT, nchars);
858 adjust_markers_for_insert (PT, PT_BYTE,
859 PT + nchars, PT_BYTE + nbytes,
860 before_markers);
862 if (BUF_INTERVALS (current_buffer) != 0)
863 offset_intervals (current_buffer, PT, nchars);
865 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
866 set_text_properties (make_number (PT), make_number (PT + nchars),
867 Qnil, Qnil, Qnil);
869 adjust_point (nchars, nbytes);
871 CHECK_MARKERS ();
874 /* Insert the part of the text of STRING, a Lisp object assumed to be
875 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
876 starting at position POS / POS_BYTE. If the text of STRING has properties,
877 copy them into the buffer.
879 It does not work to use `insert' for this, because a GC could happen
880 before we copy the stuff into the buffer, and relocate the string
881 without insert noticing. */
883 void
884 insert_from_string (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
885 EMACS_INT length, EMACS_INT length_byte, int inherit)
887 EMACS_INT opoint = PT;
889 if (SCHARS (string) == 0)
890 return;
892 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
893 inherit, 0);
894 signal_after_change (opoint, 0, PT - opoint);
895 update_compositions (opoint, PT, CHECK_BORDER);
898 /* Like `insert_from_string' except that all markers pointing
899 at the place where the insertion happens are adjusted to point after it. */
901 void
902 insert_from_string_before_markers (Lisp_Object string,
903 EMACS_INT pos, EMACS_INT pos_byte,
904 EMACS_INT length, EMACS_INT length_byte,
905 int inherit)
907 EMACS_INT opoint = PT;
909 if (SCHARS (string) == 0)
910 return;
912 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
913 inherit, 1);
914 signal_after_change (opoint, 0, PT - opoint);
915 update_compositions (opoint, PT, CHECK_BORDER);
918 /* Subroutine of the insertion functions above. */
920 static void
921 insert_from_string_1 (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
922 EMACS_INT nchars, EMACS_INT nbytes,
923 int inherit, int before_markers)
925 struct gcpro gcpro1;
926 EMACS_INT outgoing_nbytes = nbytes;
927 INTERVAL intervals;
929 /* Make OUTGOING_NBYTES describe the text
930 as it will be inserted in this buffer. */
932 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
933 outgoing_nbytes = nchars;
934 else if (! STRING_MULTIBYTE (string))
935 outgoing_nbytes
936 = count_size_as_multibyte (SDATA (string) + pos_byte,
937 nbytes);
939 GCPRO1 (string);
940 /* Do this before moving and increasing the gap,
941 because the before-change hooks might move the gap
942 or make it smaller. */
943 prepare_to_modify_buffer (PT, PT, NULL);
945 if (PT != GPT)
946 move_gap_both (PT, PT_BYTE);
947 if (GAP_SIZE < outgoing_nbytes)
948 make_gap (outgoing_nbytes - GAP_SIZE);
949 UNGCPRO;
951 /* Copy the string text into the buffer, perhaps converting
952 between single-byte and multibyte. */
953 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
954 STRING_MULTIBYTE (string),
955 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
957 #ifdef BYTE_COMBINING_DEBUG
958 /* We have copied text into the gap, but we have not altered
959 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
960 to these functions and get the same results as we would
961 have got earlier on. Meanwhile, PT_ADDR does point to
962 the text that has been stored by copy_text. */
963 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
964 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
965 abort ();
966 #endif
968 record_insert (PT, nchars);
969 MODIFF++;
970 CHARS_MODIFF = MODIFF;
972 GAP_SIZE -= outgoing_nbytes;
973 GPT += nchars;
974 ZV += nchars;
975 Z += nchars;
976 GPT_BYTE += outgoing_nbytes;
977 ZV_BYTE += outgoing_nbytes;
978 Z_BYTE += outgoing_nbytes;
979 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
981 if (GPT_BYTE < GPT)
982 abort ();
984 /* The insert may have been in the unchanged region, so check again. */
985 if (Z - GPT < END_UNCHANGED)
986 END_UNCHANGED = Z - GPT;
988 adjust_overlays_for_insert (PT, nchars);
989 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
990 PT_BYTE + outgoing_nbytes,
991 before_markers);
993 offset_intervals (current_buffer, PT, nchars);
995 intervals = STRING_INTERVALS (string);
996 /* Get the intervals for the part of the string we are inserting. */
997 if (nbytes < SBYTES (string))
998 intervals = copy_intervals (intervals, pos, nchars);
1000 /* Insert those intervals. */
1001 graft_intervals_into_buffer (intervals, PT, nchars,
1002 current_buffer, inherit);
1004 adjust_point (nchars, outgoing_nbytes);
1006 CHECK_MARKERS ();
1009 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1010 starting at GPT_ADDR. */
1012 void
1013 insert_from_gap (EMACS_INT nchars, EMACS_INT nbytes)
1015 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1016 nchars = nbytes;
1018 record_insert (GPT, nchars);
1019 MODIFF++;
1021 GAP_SIZE -= nbytes;
1022 GPT += nchars;
1023 ZV += nchars;
1024 Z += nchars;
1025 GPT_BYTE += nbytes;
1026 ZV_BYTE += nbytes;
1027 Z_BYTE += nbytes;
1028 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1030 if (GPT_BYTE < GPT)
1031 abort ();
1033 adjust_overlays_for_insert (GPT - nchars, nchars);
1034 adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
1035 GPT, GPT_BYTE, 0);
1037 if (BUF_INTERVALS (current_buffer) != 0)
1039 offset_intervals (current_buffer, GPT - nchars, nchars);
1040 graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
1041 current_buffer, 0);
1044 if (GPT - nchars < PT)
1045 adjust_point (nchars, nbytes);
1047 CHECK_MARKERS ();
1050 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1051 current buffer. If the text in BUF has properties, they are absorbed
1052 into the current buffer.
1054 It does not work to use `insert' for this, because a malloc could happen
1055 and relocate BUF's text before the copy happens. */
1057 void
1058 insert_from_buffer (struct buffer *buf,
1059 EMACS_INT charpos, EMACS_INT nchars, int inherit)
1061 EMACS_INT opoint = PT;
1063 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1064 signal_after_change (opoint, 0, PT - opoint);
1065 update_compositions (opoint, PT, CHECK_BORDER);
1068 static void
1069 insert_from_buffer_1 (struct buffer *buf,
1070 EMACS_INT from, EMACS_INT nchars, int inherit)
1072 EMACS_INT chunk, chunk_expanded;
1073 EMACS_INT from_byte = buf_charpos_to_bytepos (buf, from);
1074 EMACS_INT to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1075 EMACS_INT incoming_nbytes = to_byte - from_byte;
1076 EMACS_INT outgoing_nbytes = incoming_nbytes;
1077 INTERVAL intervals;
1079 /* Make OUTGOING_NBYTES describe the text
1080 as it will be inserted in this buffer. */
1082 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1083 outgoing_nbytes = nchars;
1084 else if (NILP (BVAR (buf, enable_multibyte_characters)))
1086 EMACS_INT outgoing_before_gap = 0;
1087 EMACS_INT outgoing_after_gap = 0;
1089 if (from < BUF_GPT (buf))
1091 chunk = BUF_GPT_BYTE (buf) - from_byte;
1092 if (chunk > incoming_nbytes)
1093 chunk = incoming_nbytes;
1094 outgoing_before_gap
1095 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1096 chunk);
1098 else
1099 chunk = 0;
1101 if (chunk < incoming_nbytes)
1102 outgoing_after_gap
1103 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1104 from_byte + chunk),
1105 incoming_nbytes - chunk);
1107 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1110 /* Do this before moving and increasing the gap,
1111 because the before-change hooks might move the gap
1112 or make it smaller. */
1113 prepare_to_modify_buffer (PT, PT, NULL);
1115 if (PT != GPT)
1116 move_gap_both (PT, PT_BYTE);
1117 if (GAP_SIZE < outgoing_nbytes)
1118 make_gap (outgoing_nbytes - GAP_SIZE);
1120 if (from < BUF_GPT (buf))
1122 chunk = BUF_GPT_BYTE (buf) - from_byte;
1123 if (chunk > incoming_nbytes)
1124 chunk = incoming_nbytes;
1125 /* Record number of output bytes, so we know where
1126 to put the output from the second copy_text. */
1127 chunk_expanded
1128 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1129 GPT_ADDR, chunk,
1130 ! NILP (BVAR (buf, enable_multibyte_characters)),
1131 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1133 else
1134 chunk_expanded = chunk = 0;
1136 if (chunk < incoming_nbytes)
1137 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1138 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1139 ! NILP (BVAR (buf, enable_multibyte_characters)),
1140 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1142 #ifdef BYTE_COMBINING_DEBUG
1143 /* We have copied text into the gap, but we have not altered
1144 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1145 to these functions and get the same results as we would
1146 have got earlier on. Meanwhile, GPT_ADDR does point to
1147 the text that has been stored by copy_text. */
1148 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1149 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1150 abort ();
1151 #endif
1153 record_insert (PT, nchars);
1154 MODIFF++;
1155 CHARS_MODIFF = MODIFF;
1157 GAP_SIZE -= outgoing_nbytes;
1158 GPT += nchars;
1159 ZV += nchars;
1160 Z += nchars;
1161 GPT_BYTE += outgoing_nbytes;
1162 ZV_BYTE += outgoing_nbytes;
1163 Z_BYTE += outgoing_nbytes;
1164 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1166 if (GPT_BYTE < GPT)
1167 abort ();
1169 /* The insert may have been in the unchanged region, so check again. */
1170 if (Z - GPT < END_UNCHANGED)
1171 END_UNCHANGED = Z - GPT;
1173 adjust_overlays_for_insert (PT, nchars);
1174 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1175 PT_BYTE + outgoing_nbytes,
1178 if (BUF_INTERVALS (current_buffer) != 0)
1179 offset_intervals (current_buffer, PT, nchars);
1181 /* Get the intervals for the part of the string we are inserting. */
1182 intervals = BUF_INTERVALS (buf);
1183 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1185 if (buf == current_buffer && PT <= from)
1186 from += nchars;
1187 intervals = copy_intervals (intervals, from, nchars);
1190 /* Insert those intervals. */
1191 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1193 adjust_point (nchars, outgoing_nbytes);
1196 /* Record undo information and adjust markers and position keepers for
1197 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1198 chars (LEN_BYTE bytes) which resides in the gap just after
1199 GPT_ADDR.
1201 PREV_TEXT nil means the new text was just inserted. */
1203 static void
1204 adjust_after_replace (EMACS_INT from, EMACS_INT from_byte,
1205 Lisp_Object prev_text, EMACS_INT len, EMACS_INT len_byte)
1207 EMACS_INT nchars_del = 0, nbytes_del = 0;
1209 #ifdef BYTE_COMBINING_DEBUG
1210 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1211 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1212 abort ();
1213 #endif
1215 if (STRINGP (prev_text))
1217 nchars_del = SCHARS (prev_text);
1218 nbytes_del = SBYTES (prev_text);
1221 /* Update various buffer positions for the new text. */
1222 GAP_SIZE -= len_byte;
1223 ZV += len; Z+= len;
1224 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1225 GPT += len; GPT_BYTE += len_byte;
1226 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1228 if (nchars_del > 0)
1229 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1230 len, len_byte);
1231 else
1232 adjust_markers_for_insert (from, from_byte,
1233 from + len, from_byte + len_byte, 0);
1235 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1237 if (nchars_del > 0)
1238 record_delete (from, prev_text);
1239 record_insert (from, len);
1242 if (len > nchars_del)
1243 adjust_overlays_for_insert (from, len - nchars_del);
1244 else if (len < nchars_del)
1245 adjust_overlays_for_delete (from, nchars_del - len);
1246 if (BUF_INTERVALS (current_buffer) != 0)
1248 offset_intervals (current_buffer, from, len - nchars_del);
1251 if (from < PT)
1252 adjust_point (len - nchars_del, len_byte - nbytes_del);
1254 /* As byte combining will decrease Z, we must check this again. */
1255 if (Z - GPT < END_UNCHANGED)
1256 END_UNCHANGED = Z - GPT;
1258 CHECK_MARKERS ();
1260 if (len == 0)
1261 evaporate_overlays (from);
1262 MODIFF++;
1263 CHARS_MODIFF = MODIFF;
1266 /* Record undo information, adjust markers and position keepers for an
1267 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1268 text already exists in the current buffer but character length (TO
1269 - FROM) may be incorrect, the correct length is NEWLEN. */
1271 void
1272 adjust_after_insert (EMACS_INT from, EMACS_INT from_byte,
1273 EMACS_INT to, EMACS_INT to_byte, EMACS_INT newlen)
1275 EMACS_INT len = to - from, len_byte = to_byte - from_byte;
1277 if (GPT != to)
1278 move_gap_both (to, to_byte);
1279 GAP_SIZE += len_byte;
1280 GPT -= len; GPT_BYTE -= len_byte;
1281 ZV -= len; ZV_BYTE -= len_byte;
1282 Z -= len; Z_BYTE -= len_byte;
1283 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1286 /* Replace the text from character positions FROM to TO with NEW,
1287 If PREPARE is nonzero, call prepare_to_modify_buffer.
1288 If INHERIT, the newly inserted text should inherit text properties
1289 from the surrounding non-deleted text. */
1291 /* Note that this does not yet handle markers quite right.
1292 Also it needs to record a single undo-entry that does a replacement
1293 rather than a separate delete and insert.
1294 That way, undo will also handle markers properly.
1296 But if MARKERS is 0, don't relocate markers. */
1298 void
1299 replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
1300 int prepare, int inherit, int markers)
1302 EMACS_INT inschars = SCHARS (new);
1303 EMACS_INT insbytes = SBYTES (new);
1304 EMACS_INT from_byte, to_byte;
1305 EMACS_INT nbytes_del, nchars_del;
1306 struct gcpro gcpro1;
1307 INTERVAL intervals;
1308 EMACS_INT outgoing_insbytes = insbytes;
1309 Lisp_Object deletion;
1311 CHECK_MARKERS ();
1313 GCPRO1 (new);
1314 deletion = Qnil;
1316 if (prepare)
1318 EMACS_INT range_length = to - from;
1319 prepare_to_modify_buffer (from, to, &from);
1320 to = from + range_length;
1323 UNGCPRO;
1325 /* Make args be valid */
1326 if (from < BEGV)
1327 from = BEGV;
1328 if (to > ZV)
1329 to = ZV;
1331 from_byte = CHAR_TO_BYTE (from);
1332 to_byte = CHAR_TO_BYTE (to);
1334 nchars_del = to - from;
1335 nbytes_del = to_byte - from_byte;
1337 if (nbytes_del <= 0 && insbytes == 0)
1338 return;
1340 /* Make OUTGOING_INSBYTES describe the text
1341 as it will be inserted in this buffer. */
1343 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1344 outgoing_insbytes = inschars;
1345 else if (! STRING_MULTIBYTE (new))
1346 outgoing_insbytes
1347 = count_size_as_multibyte (SDATA (new), insbytes);
1349 GCPRO1 (new);
1351 /* Make sure the gap is somewhere in or next to what we are deleting. */
1352 if (from > GPT)
1353 gap_right (from, from_byte);
1354 if (to < GPT)
1355 gap_left (to, to_byte, 0);
1357 /* Even if we don't record for undo, we must keep the original text
1358 because we may have to recover it because of inappropriate byte
1359 combining. */
1360 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1361 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1363 GAP_SIZE += nbytes_del;
1364 ZV -= nchars_del;
1365 Z -= nchars_del;
1366 ZV_BYTE -= nbytes_del;
1367 Z_BYTE -= nbytes_del;
1368 GPT = from;
1369 GPT_BYTE = from_byte;
1370 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1372 if (GPT_BYTE < GPT)
1373 abort ();
1375 if (GPT - BEG < BEG_UNCHANGED)
1376 BEG_UNCHANGED = GPT - BEG;
1377 if (Z - GPT < END_UNCHANGED)
1378 END_UNCHANGED = Z - GPT;
1380 if (GAP_SIZE < outgoing_insbytes)
1381 make_gap (outgoing_insbytes - GAP_SIZE);
1383 /* Copy the string text into the buffer, perhaps converting
1384 between single-byte and multibyte. */
1385 copy_text (SDATA (new), GPT_ADDR, insbytes,
1386 STRING_MULTIBYTE (new),
1387 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1389 #ifdef BYTE_COMBINING_DEBUG
1390 /* We have copied text into the gap, but we have not marked
1391 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1392 here, for both the previous text and the following text.
1393 Meanwhile, GPT_ADDR does point to
1394 the text that has been stored by copy_text. */
1395 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1396 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1397 abort ();
1398 #endif
1400 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1402 /* Record the insertion first, so that when we undo,
1403 the deletion will be undone first. Thus, undo
1404 will insert before deleting, and thus will keep
1405 the markers before and after this text separate. */
1406 record_insert (from + SCHARS (deletion), inschars);
1407 record_delete (from, deletion);
1410 GAP_SIZE -= outgoing_insbytes;
1411 GPT += inschars;
1412 ZV += inschars;
1413 Z += inschars;
1414 GPT_BYTE += outgoing_insbytes;
1415 ZV_BYTE += outgoing_insbytes;
1416 Z_BYTE += outgoing_insbytes;
1417 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1419 if (GPT_BYTE < GPT)
1420 abort ();
1422 /* Adjust the overlay center as needed. This must be done after
1423 adjusting the markers that bound the overlays. */
1424 adjust_overlays_for_delete (from, nchars_del);
1425 adjust_overlays_for_insert (from, inschars);
1427 /* Adjust markers for the deletion and the insertion. */
1428 if (markers)
1429 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1430 inschars, outgoing_insbytes);
1432 offset_intervals (current_buffer, from, inschars - nchars_del);
1434 /* Get the intervals for the part of the string we are inserting--
1435 not including the combined-before bytes. */
1436 intervals = STRING_INTERVALS (new);
1437 /* Insert those intervals. */
1438 graft_intervals_into_buffer (intervals, from, inschars,
1439 current_buffer, inherit);
1441 /* Relocate point as if it were a marker. */
1442 if (from < PT)
1443 adjust_point ((from + inschars - (PT < to ? PT : to)),
1444 (from_byte + outgoing_insbytes
1445 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1447 if (outgoing_insbytes == 0)
1448 evaporate_overlays (from);
1450 CHECK_MARKERS ();
1452 MODIFF++;
1453 CHARS_MODIFF = MODIFF;
1454 UNGCPRO;
1456 signal_after_change (from, nchars_del, GPT - from);
1457 update_compositions (from, GPT, CHECK_BORDER);
1460 /* Replace the text from character positions FROM to TO with
1461 the text in INS of length INSCHARS.
1462 Keep the text properties that applied to the old characters
1463 (extending them to all the new chars if there are more new chars).
1465 Note that this does not yet handle markers quite right.
1467 If MARKERS is nonzero, relocate markers.
1469 Unlike most functions at this level, never call
1470 prepare_to_modify_buffer and never call signal_after_change. */
1472 void
1473 replace_range_2 (EMACS_INT from, EMACS_INT from_byte,
1474 EMACS_INT to, EMACS_INT to_byte,
1475 const char *ins, EMACS_INT inschars, EMACS_INT insbytes,
1476 int markers)
1478 EMACS_INT nbytes_del, nchars_del;
1480 CHECK_MARKERS ();
1482 nchars_del = to - from;
1483 nbytes_del = to_byte - from_byte;
1485 if (nbytes_del <= 0 && insbytes == 0)
1486 return;
1488 /* Make sure the gap is somewhere in or next to what we are deleting. */
1489 if (from > GPT)
1490 gap_right (from, from_byte);
1491 if (to < GPT)
1492 gap_left (to, to_byte, 0);
1494 GAP_SIZE += nbytes_del;
1495 ZV -= nchars_del;
1496 Z -= nchars_del;
1497 ZV_BYTE -= nbytes_del;
1498 Z_BYTE -= nbytes_del;
1499 GPT = from;
1500 GPT_BYTE = from_byte;
1501 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1503 if (GPT_BYTE < GPT)
1504 abort ();
1506 if (GPT - BEG < BEG_UNCHANGED)
1507 BEG_UNCHANGED = GPT - BEG;
1508 if (Z - GPT < END_UNCHANGED)
1509 END_UNCHANGED = Z - GPT;
1511 if (GAP_SIZE < insbytes)
1512 make_gap (insbytes - GAP_SIZE);
1514 /* Copy the replacement text into the buffer. */
1515 memcpy (GPT_ADDR, ins, insbytes);
1517 #ifdef BYTE_COMBINING_DEBUG
1518 /* We have copied text into the gap, but we have not marked
1519 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1520 here, for both the previous text and the following text.
1521 Meanwhile, GPT_ADDR does point to
1522 the text that has been stored by copy_text. */
1523 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1524 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1525 abort ();
1526 #endif
1528 GAP_SIZE -= insbytes;
1529 GPT += inschars;
1530 ZV += inschars;
1531 Z += inschars;
1532 GPT_BYTE += insbytes;
1533 ZV_BYTE += insbytes;
1534 Z_BYTE += insbytes;
1535 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1537 if (GPT_BYTE < GPT)
1538 abort ();
1540 /* Adjust the overlay center as needed. This must be done after
1541 adjusting the markers that bound the overlays. */
1542 if (nchars_del != inschars)
1544 adjust_overlays_for_insert (from, inschars);
1545 adjust_overlays_for_delete (from + inschars, nchars_del);
1548 /* Adjust markers for the deletion and the insertion. */
1549 if (markers
1550 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1551 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1552 inschars, insbytes);
1554 offset_intervals (current_buffer, from, inschars - nchars_del);
1556 /* Relocate point as if it were a marker. */
1557 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1559 if (PT < to)
1560 /* PT was within the deleted text. Move it to FROM. */
1561 adjust_point (from - PT, from_byte - PT_BYTE);
1562 else
1563 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1566 if (insbytes == 0)
1567 evaporate_overlays (from);
1569 CHECK_MARKERS ();
1571 MODIFF++;
1572 CHARS_MODIFF = MODIFF;
1575 /* Delete characters in current buffer
1576 from FROM up to (but not including) TO.
1577 If TO comes before FROM, we delete nothing. */
1579 void
1580 del_range (EMACS_INT from, EMACS_INT to)
1582 del_range_1 (from, to, 1, 0);
1585 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1586 RET_STRING says to return the deleted text. */
1588 Lisp_Object
1589 del_range_1 (EMACS_INT from, EMACS_INT to, int prepare, int ret_string)
1591 EMACS_INT from_byte, to_byte;
1592 Lisp_Object deletion;
1593 struct gcpro gcpro1;
1595 /* Make args be valid */
1596 if (from < BEGV)
1597 from = BEGV;
1598 if (to > ZV)
1599 to = ZV;
1601 if (to <= from)
1602 return Qnil;
1604 if (prepare)
1606 EMACS_INT range_length = to - from;
1607 prepare_to_modify_buffer (from, to, &from);
1608 to = min (ZV, from + range_length);
1611 from_byte = CHAR_TO_BYTE (from);
1612 to_byte = CHAR_TO_BYTE (to);
1614 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1615 GCPRO1(deletion);
1616 signal_after_change (from, to - from, 0);
1617 update_compositions (from, from, CHECK_HEAD);
1618 UNGCPRO;
1619 return deletion;
1622 /* Like del_range_1 but args are byte positions, not char positions. */
1624 void
1625 del_range_byte (EMACS_INT from_byte, EMACS_INT to_byte, int prepare)
1627 EMACS_INT from, to;
1629 /* Make args be valid */
1630 if (from_byte < BEGV_BYTE)
1631 from_byte = BEGV_BYTE;
1632 if (to_byte > ZV_BYTE)
1633 to_byte = ZV_BYTE;
1635 if (to_byte <= from_byte)
1636 return;
1638 from = BYTE_TO_CHAR (from_byte);
1639 to = BYTE_TO_CHAR (to_byte);
1641 if (prepare)
1643 EMACS_INT old_from = from, old_to = Z - to;
1644 EMACS_INT range_length = to - from;
1645 prepare_to_modify_buffer (from, to, &from);
1646 to = from + range_length;
1648 if (old_from != from)
1649 from_byte = CHAR_TO_BYTE (from);
1650 if (to > ZV)
1652 to = ZV;
1653 to_byte = ZV_BYTE;
1655 else if (old_to == Z - to)
1656 to_byte = CHAR_TO_BYTE (to);
1659 del_range_2 (from, from_byte, to, to_byte, 0);
1660 signal_after_change (from, to - from, 0);
1661 update_compositions (from, from, CHECK_HEAD);
1664 /* Like del_range_1, but positions are specified both as charpos
1665 and bytepos. */
1667 void
1668 del_range_both (EMACS_INT from, EMACS_INT from_byte,
1669 EMACS_INT to, EMACS_INT to_byte, int prepare)
1671 /* Make args be valid */
1672 if (from_byte < BEGV_BYTE)
1673 from_byte = BEGV_BYTE;
1674 if (to_byte > ZV_BYTE)
1675 to_byte = ZV_BYTE;
1677 if (to_byte <= from_byte)
1678 return;
1680 if (from < BEGV)
1681 from = BEGV;
1682 if (to > ZV)
1683 to = ZV;
1685 if (prepare)
1687 EMACS_INT old_from = from, old_to = Z - to;
1688 EMACS_INT range_length = to - from;
1689 prepare_to_modify_buffer (from, to, &from);
1690 to = from + range_length;
1692 if (old_from != from)
1693 from_byte = CHAR_TO_BYTE (from);
1694 if (to > ZV)
1696 to = ZV;
1697 to_byte = ZV_BYTE;
1699 else if (old_to == Z - to)
1700 to_byte = CHAR_TO_BYTE (to);
1703 del_range_2 (from, from_byte, to, to_byte, 0);
1704 signal_after_change (from, to - from, 0);
1705 update_compositions (from, from, CHECK_HEAD);
1708 /* Delete a range of text, specified both as character positions
1709 and byte positions. FROM and TO are character positions,
1710 while FROM_BYTE and TO_BYTE are byte positions.
1711 If RET_STRING is true, the deleted area is returned as a string. */
1713 Lisp_Object
1714 del_range_2 (EMACS_INT from, EMACS_INT from_byte,
1715 EMACS_INT to, EMACS_INT to_byte, int ret_string)
1717 register EMACS_INT nbytes_del, nchars_del;
1718 Lisp_Object deletion;
1720 CHECK_MARKERS ();
1722 nchars_del = to - from;
1723 nbytes_del = to_byte - from_byte;
1725 /* Make sure the gap is somewhere in or next to what we are deleting. */
1726 if (from > GPT)
1727 gap_right (from, from_byte);
1728 if (to < GPT)
1729 gap_left (to, to_byte, 0);
1731 #ifdef BYTE_COMBINING_DEBUG
1732 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1733 Z_BYTE - to_byte, from, from_byte))
1734 abort ();
1735 #endif
1737 if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
1738 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1739 else
1740 deletion = Qnil;
1742 /* Relocate all markers pointing into the new, larger gap
1743 to point at the end of the text before the gap.
1744 Do this before recording the deletion,
1745 so that undo handles this after reinserting the text. */
1746 adjust_markers_for_delete (from, from_byte, to, to_byte);
1748 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1749 record_delete (from, deletion);
1750 MODIFF++;
1751 CHARS_MODIFF = MODIFF;
1753 /* Relocate point as if it were a marker. */
1754 if (from < PT)
1755 adjust_point (from - (PT < to ? PT : to),
1756 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1758 offset_intervals (current_buffer, from, - nchars_del);
1760 /* Adjust the overlay center as needed. This must be done after
1761 adjusting the markers that bound the overlays. */
1762 adjust_overlays_for_delete (from, nchars_del);
1764 GAP_SIZE += nbytes_del;
1765 ZV_BYTE -= nbytes_del;
1766 Z_BYTE -= nbytes_del;
1767 ZV -= nchars_del;
1768 Z -= nchars_del;
1769 GPT = from;
1770 GPT_BYTE = from_byte;
1771 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1772 /* Put an anchor, unless called from decode_coding_object which
1773 needs to access the previous gap contents. */
1774 *(GPT_ADDR) = 0;
1776 if (GPT_BYTE < GPT)
1777 abort ();
1779 if (GPT - BEG < BEG_UNCHANGED)
1780 BEG_UNCHANGED = GPT - BEG;
1781 if (Z - GPT < END_UNCHANGED)
1782 END_UNCHANGED = Z - GPT;
1784 CHECK_MARKERS ();
1786 evaporate_overlays (from);
1788 return deletion;
1791 /* Call this if you're about to change the region of BUFFER from
1792 character positions START to END. This checks the read-only
1793 properties of the region, calls the necessary modification hooks,
1794 and warns the next redisplay that it should pay attention to that
1795 area.
1797 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1798 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1800 void
1801 modify_region (struct buffer *buffer, EMACS_INT start, EMACS_INT end,
1802 int preserve_chars_modiff)
1804 struct buffer *old_buffer = current_buffer;
1806 if (buffer != old_buffer)
1807 set_buffer_internal (buffer);
1809 prepare_to_modify_buffer (start, end, NULL);
1811 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
1813 if (MODIFF <= SAVE_MODIFF)
1814 record_first_change ();
1815 MODIFF++;
1816 if (! preserve_chars_modiff)
1817 CHARS_MODIFF = MODIFF;
1819 BVAR (buffer, point_before_scroll) = Qnil;
1821 if (buffer != old_buffer)
1822 set_buffer_internal (old_buffer);
1825 /* Check that it is okay to modify the buffer between START and END,
1826 which are char positions.
1828 Run the before-change-function, if any. If intervals are in use,
1829 verify that the text to be modified is not read-only, and call
1830 any modification properties the text may have.
1832 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1833 by holding its value temporarily in a marker. */
1835 void
1836 prepare_to_modify_buffer (EMACS_INT start, EMACS_INT end,
1837 EMACS_INT *preserve_ptr)
1839 struct buffer *base_buffer;
1841 if (!NILP (BVAR (current_buffer, read_only)))
1842 Fbarf_if_buffer_read_only ();
1844 /* Let redisplay consider other windows than selected_window
1845 if modifying another buffer. */
1846 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
1847 ++windows_or_buffers_changed;
1849 if (BUF_INTERVALS (current_buffer) != 0)
1851 if (preserve_ptr)
1853 Lisp_Object preserve_marker;
1854 struct gcpro gcpro1;
1855 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1856 GCPRO1 (preserve_marker);
1857 verify_interval_modification (current_buffer, start, end);
1858 *preserve_ptr = marker_position (preserve_marker);
1859 unchain_marker (XMARKER (preserve_marker));
1860 UNGCPRO;
1862 else
1863 verify_interval_modification (current_buffer, start, end);
1866 /* For indirect buffers, use the base buffer to check clashes. */
1867 if (current_buffer->base_buffer != 0)
1868 base_buffer = current_buffer->base_buffer;
1869 else
1870 base_buffer = current_buffer;
1872 #ifdef CLASH_DETECTION
1873 if (!NILP (BVAR (base_buffer, file_truename))
1874 /* Make binding buffer-file-name to nil effective. */
1875 && !NILP (BVAR (base_buffer, filename))
1876 && SAVE_MODIFF >= MODIFF)
1877 lock_file (BVAR (base_buffer, file_truename));
1878 #else
1879 /* At least warn if this file has changed on disk since it was visited. */
1880 if (!NILP (BVAR (base_buffer, filename))
1881 && SAVE_MODIFF >= MODIFF
1882 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1883 && !NILP (Ffile_exists_p (BVAR (base_buffer, filename))))
1884 call1 (intern ("ask-user-about-supersession-threat"),
1885 BVAR (base_buffer,filename));
1886 #endif /* not CLASH_DETECTION */
1888 /* If `select-active-regions' is non-nil, save the region text. */
1889 if (!NILP (BVAR (current_buffer, mark_active))
1890 && !inhibit_modification_hooks
1891 && XMARKER (BVAR (current_buffer, mark))->buffer
1892 && NILP (Vsaved_region_selection)
1893 && (EQ (Vselect_active_regions, Qonly)
1894 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
1895 : (!NILP (Vselect_active_regions)
1896 && !NILP (Vtransient_mark_mode))))
1898 EMACS_INT b = XMARKER (BVAR (current_buffer, mark))->charpos;
1899 EMACS_INT e = PT;
1900 if (b < e)
1901 Vsaved_region_selection = make_buffer_string (b, e, 0);
1902 else if (b > e)
1903 Vsaved_region_selection = make_buffer_string (e, b, 0);
1906 signal_before_change (start, end, preserve_ptr);
1908 if (current_buffer->newline_cache)
1909 invalidate_region_cache (current_buffer,
1910 current_buffer->newline_cache,
1911 start - BEG, Z - end);
1912 if (current_buffer->width_run_cache)
1913 invalidate_region_cache (current_buffer,
1914 current_buffer->width_run_cache,
1915 start - BEG, Z - end);
1917 Vdeactivate_mark = Qt;
1920 /* These macros work with an argument named `preserve_ptr'
1921 and a local variable named `preserve_marker'. */
1923 #define PRESERVE_VALUE \
1924 if (preserve_ptr && NILP (preserve_marker)) \
1925 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1927 #define RESTORE_VALUE \
1928 if (! NILP (preserve_marker)) \
1930 *preserve_ptr = marker_position (preserve_marker); \
1931 unchain_marker (XMARKER (preserve_marker)); \
1934 #define PRESERVE_START_END \
1935 if (NILP (start_marker)) \
1936 start_marker = Fcopy_marker (start, Qnil); \
1937 if (NILP (end_marker)) \
1938 end_marker = Fcopy_marker (end, Qnil);
1940 #define FETCH_START \
1941 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1943 #define FETCH_END \
1944 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1946 /* Set a variable to nil if an error occurred.
1947 Don't change the variable if there was no error.
1948 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
1949 VARIABLE is the variable to maybe set to nil.
1950 NO-ERROR-FLAG is nil if there was an error,
1951 anything else meaning no error (so this function does nothing). */
1952 static Lisp_Object
1953 reset_var_on_error (Lisp_Object val)
1955 if (NILP (XCDR (val)))
1956 Fset (XCAR (val), Qnil);
1957 return Qnil;
1960 /* Signal a change to the buffer immediately before it happens.
1961 START_INT and END_INT are the bounds of the text to be changed.
1963 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1964 by holding its value temporarily in a marker. */
1966 static void
1967 signal_before_change (EMACS_INT start_int, EMACS_INT end_int,
1968 EMACS_INT *preserve_ptr)
1970 Lisp_Object start, end;
1971 Lisp_Object start_marker, end_marker;
1972 Lisp_Object preserve_marker;
1973 struct gcpro gcpro1, gcpro2, gcpro3;
1974 int count = SPECPDL_INDEX ();
1976 if (inhibit_modification_hooks)
1977 return;
1979 start = make_number (start_int);
1980 end = make_number (end_int);
1981 preserve_marker = Qnil;
1982 start_marker = Qnil;
1983 end_marker = Qnil;
1984 GCPRO3 (preserve_marker, start_marker, end_marker);
1986 specbind (Qinhibit_modification_hooks, Qt);
1988 /* If buffer is unmodified, run a special hook for that case. The
1989 check for Vfirst_change_hook is just a minor optimization. */
1990 if (SAVE_MODIFF >= MODIFF
1991 && !NILP (Vfirst_change_hook))
1993 PRESERVE_VALUE;
1994 PRESERVE_START_END;
1995 Frun_hooks (1, &Qfirst_change_hook);
1998 /* Now run the before-change-functions if any. */
1999 if (!NILP (Vbefore_change_functions))
2001 Lisp_Object args[3];
2002 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
2004 PRESERVE_VALUE;
2005 PRESERVE_START_END;
2007 /* Mark before-change-functions to be reset to nil in case of error. */
2008 record_unwind_protect (reset_var_on_error, rvoe_arg);
2010 /* Actually run the hook functions. */
2011 args[0] = Qbefore_change_functions;
2012 args[1] = FETCH_START;
2013 args[2] = FETCH_END;
2014 Frun_hook_with_args (3, args);
2016 /* There was no error: unarm the reset_on_error. */
2017 XSETCDR (rvoe_arg, Qt);
2020 if (current_buffer->overlays_before || current_buffer->overlays_after)
2022 PRESERVE_VALUE;
2023 report_overlay_modification (FETCH_START, FETCH_END, 0,
2024 FETCH_START, FETCH_END, Qnil);
2027 if (! NILP (start_marker))
2028 free_marker (start_marker);
2029 if (! NILP (end_marker))
2030 free_marker (end_marker);
2031 RESTORE_VALUE;
2032 UNGCPRO;
2034 unbind_to (count, Qnil);
2037 /* Signal a change immediately after it happens.
2038 CHARPOS is the character position of the start of the changed text.
2039 LENDEL is the number of characters of the text before the change.
2040 (Not the whole buffer; just the part that was changed.)
2041 LENINS is the number of characters in that part of the text
2042 after the change. */
2044 void
2045 signal_after_change (EMACS_INT charpos, EMACS_INT lendel, EMACS_INT lenins)
2047 int count = SPECPDL_INDEX ();
2048 if (inhibit_modification_hooks)
2049 return;
2051 /* If we are deferring calls to the after-change functions
2052 and there are no before-change functions,
2053 just record the args that we were going to use. */
2054 if (! NILP (Vcombine_after_change_calls)
2055 && NILP (Vbefore_change_functions)
2056 && !current_buffer->overlays_before
2057 && !current_buffer->overlays_after)
2059 Lisp_Object elt;
2061 if (!NILP (combine_after_change_list)
2062 && current_buffer != XBUFFER (combine_after_change_buffer))
2063 Fcombine_after_change_execute ();
2065 elt = Fcons (make_number (charpos - BEG),
2066 Fcons (make_number (Z - (charpos - lendel + lenins)),
2067 Fcons (make_number (lenins - lendel), Qnil)));
2068 combine_after_change_list
2069 = Fcons (elt, combine_after_change_list);
2070 combine_after_change_buffer = Fcurrent_buffer ();
2072 return;
2075 if (!NILP (combine_after_change_list))
2076 Fcombine_after_change_execute ();
2078 specbind (Qinhibit_modification_hooks, Qt);
2080 if (!NILP (Vafter_change_functions))
2082 Lisp_Object args[4];
2083 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2085 /* Mark after-change-functions to be reset to nil in case of error. */
2086 record_unwind_protect (reset_var_on_error, rvoe_arg);
2088 /* Actually run the hook functions. */
2089 args[0] = Qafter_change_functions;
2090 XSETFASTINT (args[1], charpos);
2091 XSETFASTINT (args[2], charpos + lenins);
2092 XSETFASTINT (args[3], lendel);
2093 Frun_hook_with_args (4, args);
2095 /* There was no error: unarm the reset_on_error. */
2096 XSETCDR (rvoe_arg, Qt);
2099 if (current_buffer->overlays_before || current_buffer->overlays_after)
2100 report_overlay_modification (make_number (charpos),
2101 make_number (charpos + lenins),
2103 make_number (charpos),
2104 make_number (charpos + lenins),
2105 make_number (lendel));
2107 /* After an insertion, call the text properties
2108 insert-behind-hooks or insert-in-front-hooks. */
2109 if (lendel == 0)
2110 report_interval_modification (make_number (charpos),
2111 make_number (charpos + lenins));
2113 unbind_to (count, Qnil);
2116 static Lisp_Object
2117 Fcombine_after_change_execute_1 (Lisp_Object val)
2119 Vcombine_after_change_calls = val;
2120 return val;
2123 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2124 Scombine_after_change_execute, 0, 0, 0,
2125 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2126 (void)
2128 int count = SPECPDL_INDEX ();
2129 EMACS_INT beg, end, change;
2130 EMACS_INT begpos, endpos;
2131 Lisp_Object tail;
2133 if (NILP (combine_after_change_list))
2134 return Qnil;
2136 /* It is rare for combine_after_change_buffer to be invalid, but
2137 possible. It can happen when combine-after-change-calls is
2138 non-nil, and insertion calls a file handler (e.g. through
2139 lock_file) which scribbles into a temp file -- cyd */
2140 if (!BUFFERP (combine_after_change_buffer)
2141 || NILP (BVAR (XBUFFER (combine_after_change_buffer), name)))
2143 combine_after_change_list = Qnil;
2144 return Qnil;
2147 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2149 Fset_buffer (combine_after_change_buffer);
2151 /* # chars unchanged at beginning of buffer. */
2152 beg = Z - BEG;
2153 /* # chars unchanged at end of buffer. */
2154 end = beg;
2155 /* Total amount of insertion (negative for deletion). */
2156 change = 0;
2158 /* Scan the various individual changes,
2159 accumulating the range info in BEG, END and CHANGE. */
2160 for (tail = combine_after_change_list; CONSP (tail);
2161 tail = XCDR (tail))
2163 Lisp_Object elt;
2164 EMACS_INT thisbeg, thisend, thischange;
2166 /* Extract the info from the next element. */
2167 elt = XCAR (tail);
2168 if (! CONSP (elt))
2169 continue;
2170 thisbeg = XINT (XCAR (elt));
2172 elt = XCDR (elt);
2173 if (! CONSP (elt))
2174 continue;
2175 thisend = XINT (XCAR (elt));
2177 elt = XCDR (elt);
2178 if (! CONSP (elt))
2179 continue;
2180 thischange = XINT (XCAR (elt));
2182 /* Merge this range into the accumulated range. */
2183 change += thischange;
2184 if (thisbeg < beg)
2185 beg = thisbeg;
2186 if (thisend < end)
2187 end = thisend;
2190 /* Get the current start and end positions of the range
2191 that was changed. */
2192 begpos = BEG + beg;
2193 endpos = Z - end;
2195 /* We are about to handle these, so discard them. */
2196 combine_after_change_list = Qnil;
2198 /* Now run the after-change functions for real.
2199 Turn off the flag that defers them. */
2200 record_unwind_protect (Fcombine_after_change_execute_1,
2201 Vcombine_after_change_calls);
2202 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2203 update_compositions (begpos, endpos, CHECK_ALL);
2205 return unbind_to (count, Qnil);
2208 void
2209 syms_of_insdel (void)
2211 staticpro (&combine_after_change_list);
2212 staticpro (&combine_after_change_buffer);
2213 combine_after_change_list = Qnil;
2214 combine_after_change_buffer = Qnil;
2216 DEFVAR_BOOL ("check-markers-debug-flag", check_markers_debug_flag,
2217 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
2218 check_markers_debug_flag = 0;
2219 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
2220 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2221 Vcombine_after_change_calls = Qnil;
2223 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
2224 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2225 This affects `before-change-functions' and `after-change-functions',
2226 as well as hooks attached to text properties and overlays. */);
2227 inhibit_modification_hooks = 0;
2228 Qinhibit_modification_hooks = intern_c_string ("inhibit-modification-hooks");
2229 staticpro (&Qinhibit_modification_hooks);
2231 defsubr (&Scombine_after_change_execute);