Add missing copyright years.
[emacs.git] / src / insdel.c
blob70f51646b0db1c51842caf17a96cdd41ffd0f3b2
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, 2009, 2010, 2011
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 of the License, or
11 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <setjmp.h>
24 #include "lisp.h"
25 #include "intervals.h"
26 #include "buffer.h"
27 #include "character.h"
28 #include "window.h"
29 #include "blockinput.h"
30 #include "region-cache.h"
32 #ifndef NULL
33 #define NULL 0
34 #endif
36 static void insert_from_string_1 (Lisp_Object string,
37 EMACS_INT pos, EMACS_INT pos_byte,
38 EMACS_INT nchars, EMACS_INT nbytes,
39 int inherit, int before_markers);
40 static void insert_from_buffer_1 (struct buffer *buf,
41 EMACS_INT from, EMACS_INT nchars,
42 int inherit);
43 static void gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap);
44 static void gap_right (EMACS_INT charpos, EMACS_INT bytepos);
45 static void adjust_markers_gap_motion (EMACS_INT from, EMACS_INT to,
46 EMACS_INT amount);
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 Lisp_Object Fcombine_after_change_execute (void);
56 /* Non-nil means don't call the after-change-functions right away,
57 just record an element in combine_after_change_list. */
58 Lisp_Object Vcombine_after_change_calls;
60 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
61 describing changes which happened while combine_after_change_calls
62 was nonzero. We use this to decide how to call them
63 once the deferral ends.
65 In each element.
66 BEG-UNCHANGED is the number of chars before the changed range.
67 END-UNCHANGED is the number of chars after the changed range,
68 and CHANGE-AMOUNT is the number of characters inserted by the change
69 (negative for a deletion). */
70 Lisp_Object combine_after_change_list;
72 /* Buffer which combine_after_change_list is about. */
73 Lisp_Object combine_after_change_buffer;
75 Lisp_Object Qinhibit_modification_hooks;
77 /* Check all markers in the current buffer, looking for something invalid. */
79 static int check_markers_debug_flag;
81 #define CHECK_MARKERS() \
82 if (check_markers_debug_flag) \
83 check_markers (); \
84 else
86 void
87 check_markers (void)
89 register struct Lisp_Marker *tail;
90 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
92 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
94 if (tail->buffer->text != current_buffer->text)
95 abort ();
96 if (tail->charpos > Z)
97 abort ();
98 if (tail->bytepos > Z_BYTE)
99 abort ();
100 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
101 abort ();
105 /* Move gap to position CHARPOS.
106 Note that this can quit! */
108 void
109 move_gap (EMACS_INT charpos)
111 move_gap_both (charpos, charpos_to_bytepos (charpos));
114 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
115 Note that this can quit! */
117 void
118 move_gap_both (EMACS_INT charpos, EMACS_INT bytepos)
120 if (bytepos < GPT_BYTE)
121 gap_left (charpos, bytepos, 0);
122 else if (bytepos > GPT_BYTE)
123 gap_right (charpos, bytepos);
126 /* Move the gap to a position less than the current GPT.
127 BYTEPOS describes the new position as a byte position,
128 and CHARPOS is the corresponding char position.
129 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
131 static void
132 gap_left (EMACS_INT charpos, EMACS_INT bytepos, int newgap)
134 register unsigned char *to, *from;
135 register EMACS_INT i;
136 EMACS_INT new_s1;
138 if (!newgap)
139 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
141 i = GPT_BYTE;
142 to = GAP_END_ADDR;
143 from = GPT_ADDR;
144 new_s1 = GPT_BYTE;
146 /* Now copy the characters. To move the gap down,
147 copy characters up. */
149 while (1)
151 /* I gets number of characters left to copy. */
152 i = new_s1 - bytepos;
153 if (i == 0)
154 break;
155 /* If a quit is requested, stop copying now.
156 Change BYTEPOS to be where we have actually moved the gap to. */
157 if (QUITP)
159 bytepos = new_s1;
160 charpos = BYTE_TO_CHAR (bytepos);
161 break;
163 /* Move at most 32000 chars before checking again for a quit. */
164 if (i > 32000)
165 i = 32000;
166 new_s1 -= i;
167 from -= i, to -= i;
168 memmove (to, from, i);
171 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
172 BYTEPOS is where the loop above stopped, which may be what was specified
173 or may be where a quit was detected. */
174 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
175 GPT_BYTE = bytepos;
176 GPT = charpos;
177 if (bytepos < charpos)
178 abort ();
179 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
180 QUIT;
183 /* Move the gap to a position greater than the current GPT.
184 BYTEPOS describes the new position as a byte position,
185 and CHARPOS is the corresponding char position. */
187 static void
188 gap_right (EMACS_INT charpos, EMACS_INT bytepos)
190 register unsigned char *to, *from;
191 register EMACS_INT i;
192 EMACS_INT new_s1;
194 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
196 i = GPT_BYTE;
197 from = GAP_END_ADDR;
198 to = GPT_ADDR;
199 new_s1 = GPT_BYTE;
201 /* Now copy the characters. To move the gap up,
202 copy characters down. */
204 while (1)
206 /* I gets number of characters left to copy. */
207 i = bytepos - new_s1;
208 if (i == 0)
209 break;
210 /* If a quit is requested, stop copying now.
211 Change BYTEPOS to be where we have actually moved the gap to. */
212 if (QUITP)
214 bytepos = new_s1;
215 charpos = BYTE_TO_CHAR (bytepos);
216 break;
218 /* Move at most 32000 chars before checking again for a quit. */
219 if (i > 32000)
220 i = 32000;
221 new_s1 += i;
222 memmove (to, from, i);
223 from += i, to += i;
226 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
227 - GAP_SIZE);
228 GPT = charpos;
229 GPT_BYTE = bytepos;
230 if (bytepos < charpos)
231 abort ();
232 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
233 QUIT;
236 /* Add AMOUNT to the byte position of every marker in the current buffer
237 whose current byte position is between FROM (exclusive) and TO (inclusive).
239 Also, any markers past the outside of that interval, in the direction
240 of adjustment, are first moved back to the near end of the interval
241 and then adjusted by AMOUNT.
243 When the latter adjustment is done, if AMOUNT is negative,
244 we record the adjustment for undo. (This case happens only for
245 deletion.)
247 The markers' character positions are not altered,
248 because gap motion does not affect character positions. */
250 int adjust_markers_test;
252 static void
253 adjust_markers_gap_motion (EMACS_INT from, EMACS_INT to, EMACS_INT amount)
255 /* Now that a marker has a bytepos, not counting the gap,
256 nothing needs to be done here. */
257 #if 0
258 Lisp_Object marker;
259 register struct Lisp_Marker *m;
260 register EMACS_INT mpos;
262 marker = BUF_MARKERS (current_buffer);
264 while (!NILP (marker))
266 m = XMARKER (marker);
267 mpos = m->bytepos;
268 if (amount > 0)
270 if (mpos > to && mpos < to + amount)
272 if (adjust_markers_test)
273 abort ();
274 mpos = to + amount;
277 else
279 /* Here's the case where a marker is inside text being deleted.
280 AMOUNT can be negative for gap motion, too,
281 but then this range contains no markers. */
282 if (mpos > from + amount && mpos <= from)
284 if (adjust_markers_test)
285 abort ();
286 mpos = from + amount;
289 if (mpos > from && mpos <= to)
290 mpos += amount;
291 m->bufpos = mpos;
292 marker = m->chain;
294 #endif
297 /* Adjust all markers for a deletion
298 whose range in bytes is FROM_BYTE to TO_BYTE.
299 The range in charpos is FROM to TO.
301 This function assumes that the gap is adjacent to
302 or inside of the range being deleted. */
304 void
305 adjust_markers_for_delete (EMACS_INT from, EMACS_INT from_byte,
306 EMACS_INT to, EMACS_INT to_byte)
308 Lisp_Object marker;
309 register struct Lisp_Marker *m;
310 register EMACS_INT charpos;
312 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
314 charpos = m->charpos;
316 if (charpos > Z)
317 abort ();
319 /* If the marker is after the deletion,
320 relocate by number of chars / bytes deleted. */
321 if (charpos > to)
323 m->charpos -= to - from;
324 m->bytepos -= to_byte - from_byte;
326 /* Here's the case where a marker is inside text being deleted. */
327 else if (charpos > from)
329 if (! m->insertion_type)
330 { /* Normal markers will end up at the beginning of the
331 re-inserted text after undoing a deletion, and must be
332 adjusted to move them to the correct place. */
333 XSETMISC (marker, m);
334 record_marker_adjustment (marker, from - charpos);
336 else if (charpos < to)
337 { /* Before-insertion markers will automatically move forward
338 upon re-inserting the deleted text, so we have to arrange
339 for them to move backward to the correct position. */
340 XSETMISC (marker, m);
341 record_marker_adjustment (marker, to - charpos);
343 m->charpos = from;
344 m->bytepos = from_byte;
346 /* Here's the case where a before-insertion marker is immediately
347 before the deleted region. */
348 else if (charpos == from && m->insertion_type)
350 /* Undoing the change uses normal insertion, which will
351 incorrectly make MARKER move forward, so we arrange for it
352 to then move backward to the correct place at the beginning
353 of the deleted region. */
354 XSETMISC (marker, m);
355 record_marker_adjustment (marker, to - from);
361 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
362 to TO / TO_BYTE. We have to relocate the charpos of every marker
363 that points after the insertion (but not their bytepos).
365 When a marker points at the insertion point,
366 we advance it if either its insertion-type is t
367 or BEFORE_MARKERS is true. */
369 static void
370 adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte,
371 EMACS_INT to, EMACS_INT to_byte, int before_markers)
373 struct Lisp_Marker *m;
374 int adjusted = 0;
375 EMACS_INT nchars = to - from;
376 EMACS_INT nbytes = to_byte - from_byte;
378 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
380 eassert (m->bytepos >= m->charpos
381 && m->bytepos - m->charpos <= Z_BYTE - Z);
383 if (m->bytepos == from_byte)
385 if (m->insertion_type || before_markers)
387 m->bytepos = to_byte;
388 m->charpos = to;
389 if (m->insertion_type)
390 adjusted = 1;
393 else if (m->bytepos > from_byte)
395 m->bytepos += nbytes;
396 m->charpos += nchars;
400 /* Adjusting only markers whose insertion-type is t may result in
401 - disordered start and end in overlays, and
402 - disordered overlays in the slot `overlays_before' of current_buffer. */
403 if (adjusted)
405 fix_start_end_in_overlays(from, to);
406 fix_overlays_before (current_buffer, from, to);
410 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
412 This is used only when the value of point changes due to an insert
413 or delete; it does not represent a conceptual change in point as a
414 marker. In particular, point is not crossing any interval
415 boundaries, so there's no need to use the usual SET_PT macro. In
416 fact it would be incorrect to do so, because either the old or the
417 new value of point is out of sync with the current set of
418 intervals. */
420 static void
421 adjust_point (EMACS_INT nchars, EMACS_INT nbytes)
423 BUF_PT (current_buffer) += nchars;
424 BUF_PT_BYTE (current_buffer) += nbytes;
426 /* In a single-byte buffer, the two positions must be equal. */
427 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
430 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
431 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
432 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
433 an insertion. */
435 static void
436 adjust_markers_for_replace (EMACS_INT from, EMACS_INT from_byte,
437 EMACS_INT old_chars, EMACS_INT old_bytes,
438 EMACS_INT new_chars, EMACS_INT new_bytes)
440 register struct Lisp_Marker *m;
441 EMACS_INT prev_to_byte = from_byte + old_bytes;
442 EMACS_INT diff_chars = new_chars - old_chars;
443 EMACS_INT diff_bytes = new_bytes - old_bytes;
445 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
447 if (m->bytepos >= prev_to_byte)
449 m->charpos += diff_chars;
450 m->bytepos += diff_bytes;
452 else if (m->bytepos > from_byte)
454 m->charpos = from;
455 m->bytepos = from_byte;
459 CHECK_MARKERS ();
463 /* Make the gap NBYTES_ADDED bytes longer. */
465 void
466 make_gap_larger (EMACS_INT nbytes_added)
468 Lisp_Object tem;
469 EMACS_INT real_gap_loc;
470 EMACS_INT real_gap_loc_byte;
471 EMACS_INT old_gap_size;
473 /* If we have to get more space, get enough to last a while. */
474 nbytes_added += 2000;
476 { EMACS_INT total_size = Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added;
477 if (total_size < 0
478 /* Don't allow a buffer size that won't fit in a Lisp integer. */
479 || total_size != XINT (make_number (total_size))
480 /* Don't allow a buffer size that won't fit in an int
481 even if it will fit in a Lisp integer.
482 That won't work because so many places still use `int'. */
483 || total_size != (EMACS_INT) (int) total_size)
484 error ("Buffer exceeds maximum size");
487 enlarge_buffer_text (current_buffer, nbytes_added);
489 /* Prevent quitting in move_gap. */
490 tem = Vinhibit_quit;
491 Vinhibit_quit = Qt;
493 real_gap_loc = GPT;
494 real_gap_loc_byte = GPT_BYTE;
495 old_gap_size = GAP_SIZE;
497 /* Call the newly allocated space a gap at the end of the whole space. */
498 GPT = Z + GAP_SIZE;
499 GPT_BYTE = Z_BYTE + GAP_SIZE;
500 GAP_SIZE = nbytes_added;
502 /* Move the new gap down to be consecutive with the end of the old one.
503 This adjusts the markers properly too. */
504 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
506 /* Now combine the two into one large gap. */
507 GAP_SIZE += old_gap_size;
508 GPT = real_gap_loc;
509 GPT_BYTE = real_gap_loc_byte;
511 /* Put an anchor. */
512 *(Z_ADDR) = 0;
514 Vinhibit_quit = tem;
518 /* Make the gap NBYTES_REMOVED bytes shorter. */
520 void
521 make_gap_smaller (EMACS_INT nbytes_removed)
523 Lisp_Object tem;
524 EMACS_INT real_gap_loc;
525 EMACS_INT real_gap_loc_byte;
526 EMACS_INT real_Z;
527 EMACS_INT real_Z_byte;
528 EMACS_INT real_beg_unchanged;
529 EMACS_INT new_gap_size;
531 /* Make sure the gap is at least 20 bytes. */
532 if (GAP_SIZE - nbytes_removed < 20)
533 nbytes_removed = GAP_SIZE - 20;
535 /* Prevent quitting in move_gap. */
536 tem = Vinhibit_quit;
537 Vinhibit_quit = Qt;
539 real_gap_loc = GPT;
540 real_gap_loc_byte = GPT_BYTE;
541 new_gap_size = GAP_SIZE - nbytes_removed;
542 real_Z = Z;
543 real_Z_byte = Z_BYTE;
544 real_beg_unchanged = BEG_UNCHANGED;
546 /* Pretend that the last unwanted part of the gap is the entire gap,
547 and that the first desired part of the gap is part of the buffer
548 text. */
549 memset (GPT_ADDR, 0, new_gap_size);
550 GPT += new_gap_size;
551 GPT_BYTE += new_gap_size;
552 Z += new_gap_size;
553 Z_BYTE += new_gap_size;
554 GAP_SIZE = nbytes_removed;
556 /* Move the unwanted pretend gap to the end of the buffer. This
557 adjusts the markers properly too. */
558 gap_right (Z, Z_BYTE);
560 enlarge_buffer_text (current_buffer, -nbytes_removed);
562 /* Now restore the desired gap. */
563 GAP_SIZE = new_gap_size;
564 GPT = real_gap_loc;
565 GPT_BYTE = real_gap_loc_byte;
566 Z = real_Z;
567 Z_BYTE = real_Z_byte;
568 BEG_UNCHANGED = real_beg_unchanged;
570 /* Put an anchor. */
571 *(Z_ADDR) = 0;
573 Vinhibit_quit = tem;
576 void
577 make_gap (EMACS_INT nbytes_added)
579 if (nbytes_added >= 0)
580 make_gap_larger (nbytes_added);
581 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
582 else
583 make_gap_smaller (-nbytes_added);
584 #endif
587 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
588 FROM_MULTIBYTE says whether the incoming text is multibyte.
589 TO_MULTIBYTE says whether to store the text as multibyte.
590 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
592 Return the number of bytes stored at TO_ADDR. */
594 EMACS_INT
595 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
596 EMACS_INT nbytes, int from_multibyte, int to_multibyte)
598 if (from_multibyte == to_multibyte)
600 memcpy (to_addr, from_addr, nbytes);
601 return nbytes;
603 else if (from_multibyte)
605 EMACS_INT nchars = 0;
606 EMACS_INT bytes_left = nbytes;
607 Lisp_Object tbl = Qnil;
609 while (bytes_left > 0)
611 int thislen, c;
612 c = STRING_CHAR_AND_LENGTH (from_addr, thislen);
613 if (! ASCII_CHAR_P (c))
614 c &= 0xFF;
615 *to_addr++ = c;
616 from_addr += thislen;
617 bytes_left -= thislen;
618 nchars++;
620 return nchars;
622 else
624 unsigned char *initial_to_addr = to_addr;
626 /* Convert single-byte to multibyte. */
627 while (nbytes > 0)
629 int c = *from_addr++;
631 if (!ASCII_CHAR_P (c))
633 c = BYTE8_TO_CHAR (c);
634 to_addr += CHAR_STRING (c, to_addr);
635 nbytes--;
637 else
638 /* Special case for speed. */
639 *to_addr++ = c, nbytes--;
641 return to_addr - initial_to_addr;
645 /* Return the number of bytes it would take
646 to convert some single-byte text to multibyte.
647 The single-byte text consists of NBYTES bytes at PTR. */
649 EMACS_INT
650 count_size_as_multibyte (const unsigned char *ptr, EMACS_INT nbytes)
652 EMACS_INT i;
653 EMACS_INT outgoing_nbytes = 0;
655 for (i = 0; i < nbytes; i++)
657 unsigned int c = *ptr++;
659 if (ASCII_CHAR_P (c))
660 outgoing_nbytes++;
661 else
663 c = BYTE8_TO_CHAR (c);
664 outgoing_nbytes += CHAR_BYTES (c);
668 return outgoing_nbytes;
671 /* Insert a string of specified length before point.
672 This function judges multibyteness based on
673 enable_multibyte_characters in the current buffer;
674 it never converts between single-byte and multibyte.
676 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
677 prepare_to_modify_buffer could relocate the text. */
679 void
680 insert (const unsigned char *string, EMACS_INT nbytes)
682 if (nbytes > 0)
684 EMACS_INT len = chars_in_text (string, nbytes), opoint;
685 insert_1_both (string, len, nbytes, 0, 1, 0);
686 opoint = PT - len;
687 signal_after_change (opoint, 0, len);
688 update_compositions (opoint, PT, CHECK_BORDER);
692 /* Likewise, but inherit text properties from neighboring characters. */
694 void
695 insert_and_inherit (const unsigned char *string, EMACS_INT nbytes)
697 if (nbytes > 0)
699 EMACS_INT len = chars_in_text (string, nbytes), opoint;
700 insert_1_both (string, len, nbytes, 1, 1, 0);
701 opoint = PT - len;
702 signal_after_change (opoint, 0, len);
703 update_compositions (opoint, PT, CHECK_BORDER);
707 /* Insert the character C before point. Do not inherit text properties. */
709 void
710 insert_char (int c)
712 unsigned char str[MAX_MULTIBYTE_LENGTH];
713 int len;
715 if (! NILP (current_buffer->enable_multibyte_characters))
716 len = CHAR_STRING (c, str);
717 else
719 len = 1;
720 str[0] = c;
723 insert (str, len);
726 /* Insert the null-terminated string S before point. */
728 void
729 insert_string (const char *s)
731 insert (s, strlen (s));
734 /* Like `insert' except that all markers pointing at the place where
735 the insertion happens are adjusted to point after it.
736 Don't use this function to insert part of a Lisp string,
737 since gc could happen and relocate it. */
739 void
740 insert_before_markers (const unsigned char *string, EMACS_INT nbytes)
742 if (nbytes > 0)
744 EMACS_INT len = chars_in_text (string, nbytes), opoint;
745 insert_1_both (string, len, nbytes, 0, 1, 1);
746 opoint = PT - len;
747 signal_after_change (opoint, 0, len);
748 update_compositions (opoint, PT, CHECK_BORDER);
752 /* Likewise, but inherit text properties from neighboring characters. */
754 void
755 insert_before_markers_and_inherit (const unsigned char *string,
756 EMACS_INT nbytes)
758 if (nbytes > 0)
760 EMACS_INT len = chars_in_text (string, nbytes), opoint;
761 insert_1_both (string, len, nbytes, 1, 1, 1);
762 opoint = PT - len;
763 signal_after_change (opoint, 0, len);
764 update_compositions (opoint, PT, CHECK_BORDER);
768 /* Subroutine used by the insert functions above. */
770 void
771 insert_1 (const unsigned char *string, EMACS_INT nbytes,
772 int inherit, int prepare, int before_markers)
774 insert_1_both (string, chars_in_text (string, nbytes), nbytes,
775 inherit, prepare, before_markers);
779 #ifdef BYTE_COMBINING_DEBUG
781 /* See if the bytes before POS/POS_BYTE combine with bytes
782 at the start of STRING to form a single character.
783 If so, return the number of bytes at the start of STRING
784 which combine in this way. Otherwise, return 0. */
787 count_combining_before (const unsigned char *string, EMACS_INT length,
788 EMACS_INT pos, EMACS_INT pos_byte)
790 int len, combining_bytes;
791 const unsigned char *p;
793 if (NILP (current_buffer->enable_multibyte_characters))
794 return 0;
796 /* At first, we can exclude the following cases:
797 (1) STRING[0] can't be a following byte of multibyte sequence.
798 (2) POS is the start of the current buffer.
799 (3) A character before POS is not a multibyte character. */
800 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
801 return 0;
802 if (pos_byte == BEG_BYTE) /* case (2) */
803 return 0;
804 len = 1;
805 p = BYTE_POS_ADDR (pos_byte - 1);
806 while (! CHAR_HEAD_P (*p)) p--, len++;
807 if (! LEADING_CODE_P (*p)) /* case (3) */
808 return 0;
810 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
811 if (combining_bytes <= 0)
812 /* The character preceding POS is, complete and no room for
813 combining bytes (combining_bytes == 0), or an independent 8-bit
814 character (combining_bytes < 0). */
815 return 0;
817 /* We have a combination situation. Count the bytes at STRING that
818 may combine. */
819 p = string + 1;
820 while (!CHAR_HEAD_P (*p) && p < string + length)
821 p++;
823 return (combining_bytes < p - string ? combining_bytes : p - string);
826 /* See if the bytes after POS/POS_BYTE combine with bytes
827 at the end of STRING to form a single character.
828 If so, return the number of bytes after POS/POS_BYTE
829 which combine in this way. Otherwise, return 0. */
832 count_combining_after (const unsigned char *string,
833 EMACS_INT length, EMACS_INT pos, EMACS_INT pos_byte)
835 EMACS_INT opos_byte = pos_byte;
836 EMACS_INT i;
837 EMACS_INT bytes;
838 unsigned char *bufp;
840 if (NILP (current_buffer->enable_multibyte_characters))
841 return 0;
843 /* At first, we can exclude the following cases:
844 (1) The last byte of STRING is an ASCII.
845 (2) POS is the last of the current buffer.
846 (3) A character at POS can't be a following byte of multibyte
847 character. */
848 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
849 return 0;
850 if (pos_byte == Z_BYTE) /* case (2) */
851 return 0;
852 bufp = BYTE_POS_ADDR (pos_byte);
853 if (CHAR_HEAD_P (*bufp)) /* case (3) */
854 return 0;
856 i = length - 1;
857 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
859 i--;
861 if (i < 0)
863 /* All characters in STRING are not character head. We must
864 check also preceding bytes at POS. We are sure that the gap
865 is at POS. */
866 unsigned char *p = BEG_ADDR;
867 i = pos_byte - 2;
868 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
869 i--;
870 if (i < 0 || !LEADING_CODE_P (p[i]))
871 return 0;
873 bytes = BYTES_BY_CHAR_HEAD (p[i]);
874 return (bytes <= pos_byte - 1 - i + length
876 : bytes - (pos_byte - 1 - i + length));
878 if (!LEADING_CODE_P (string[i]))
879 return 0;
881 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
882 bufp++, pos_byte++;
883 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
885 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
888 #endif
891 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
892 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
893 are the same as in insert_1. */
895 void
896 insert_1_both (const unsigned char *string,
897 EMACS_INT nchars, EMACS_INT nbytes,
898 int inherit, int prepare, int before_markers)
900 if (nchars == 0)
901 return;
903 if (NILP (current_buffer->enable_multibyte_characters))
904 nchars = nbytes;
906 if (prepare)
907 /* Do this before moving and increasing the gap,
908 because the before-change hooks might move the gap
909 or make it smaller. */
910 prepare_to_modify_buffer (PT, PT, NULL);
912 if (PT != GPT)
913 move_gap_both (PT, PT_BYTE);
914 if (GAP_SIZE < nbytes)
915 make_gap (nbytes - GAP_SIZE);
917 #ifdef BYTE_COMBINING_DEBUG
918 if (count_combining_before (string, nbytes, PT, PT_BYTE)
919 || count_combining_after (string, nbytes, PT, PT_BYTE))
920 abort ();
921 #endif
923 /* Record deletion of the surrounding text that combines with
924 the insertion. This, together with recording the insertion,
925 will add up to the right stuff in the undo list. */
926 record_insert (PT, nchars);
927 MODIFF++;
928 CHARS_MODIFF = MODIFF;
930 memcpy (GPT_ADDR, string, nbytes);
932 GAP_SIZE -= nbytes;
933 GPT += nchars;
934 ZV += nchars;
935 Z += nchars;
936 GPT_BYTE += nbytes;
937 ZV_BYTE += nbytes;
938 Z_BYTE += nbytes;
939 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
941 if (GPT_BYTE < GPT)
942 abort ();
944 /* The insert may have been in the unchanged region, so check again. */
945 if (Z - GPT < END_UNCHANGED)
946 END_UNCHANGED = Z - GPT;
948 adjust_overlays_for_insert (PT, nchars);
949 adjust_markers_for_insert (PT, PT_BYTE,
950 PT + nchars, PT_BYTE + nbytes,
951 before_markers);
953 if (BUF_INTERVALS (current_buffer) != 0)
954 offset_intervals (current_buffer, PT, nchars);
956 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
957 set_text_properties (make_number (PT), make_number (PT + nchars),
958 Qnil, Qnil, Qnil);
960 adjust_point (nchars, nbytes);
962 CHECK_MARKERS ();
965 /* Insert the part of the text of STRING, a Lisp object assumed to be
966 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
967 starting at position POS / POS_BYTE. If the text of STRING has properties,
968 copy them into the buffer.
970 It does not work to use `insert' for this, because a GC could happen
971 before we copy the stuff into the buffer, and relocate the string
972 without insert noticing. */
974 void
975 insert_from_string (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
976 EMACS_INT length, EMACS_INT length_byte, int inherit)
978 EMACS_INT opoint = PT;
980 if (SCHARS (string) == 0)
981 return;
983 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
984 inherit, 0);
985 signal_after_change (opoint, 0, PT - opoint);
986 update_compositions (opoint, PT, CHECK_BORDER);
989 /* Like `insert_from_string' except that all markers pointing
990 at the place where the insertion happens are adjusted to point after it. */
992 void
993 insert_from_string_before_markers (Lisp_Object string,
994 EMACS_INT pos, EMACS_INT pos_byte,
995 EMACS_INT length, EMACS_INT length_byte,
996 int inherit)
998 EMACS_INT opoint = PT;
1000 if (SCHARS (string) == 0)
1001 return;
1003 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
1004 inherit, 1);
1005 signal_after_change (opoint, 0, PT - opoint);
1006 update_compositions (opoint, PT, CHECK_BORDER);
1009 /* Subroutine of the insertion functions above. */
1011 static void
1012 insert_from_string_1 (Lisp_Object string, EMACS_INT pos, EMACS_INT pos_byte,
1013 EMACS_INT nchars, EMACS_INT nbytes,
1014 int inherit, int before_markers)
1016 struct gcpro gcpro1;
1017 EMACS_INT outgoing_nbytes = nbytes;
1018 INTERVAL intervals;
1020 /* Make OUTGOING_NBYTES describe the text
1021 as it will be inserted in this buffer. */
1023 if (NILP (current_buffer->enable_multibyte_characters))
1024 outgoing_nbytes = nchars;
1025 else if (! STRING_MULTIBYTE (string))
1026 outgoing_nbytes
1027 = count_size_as_multibyte (SDATA (string) + pos_byte,
1028 nbytes);
1030 GCPRO1 (string);
1031 /* Do this before moving and increasing the gap,
1032 because the before-change hooks might move the gap
1033 or make it smaller. */
1034 prepare_to_modify_buffer (PT, PT, NULL);
1036 if (PT != GPT)
1037 move_gap_both (PT, PT_BYTE);
1038 if (GAP_SIZE < outgoing_nbytes)
1039 make_gap (outgoing_nbytes - GAP_SIZE);
1040 UNGCPRO;
1042 /* Copy the string text into the buffer, perhaps converting
1043 between single-byte and multibyte. */
1044 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
1045 STRING_MULTIBYTE (string),
1046 ! NILP (current_buffer->enable_multibyte_characters));
1048 #ifdef BYTE_COMBINING_DEBUG
1049 /* We have copied text into the gap, but we have not altered
1050 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1051 to these functions and get the same results as we would
1052 have got earlier on. Meanwhile, PT_ADDR does point to
1053 the text that has been stored by copy_text. */
1054 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1055 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1056 abort ();
1057 #endif
1059 record_insert (PT, nchars);
1060 MODIFF++;
1061 CHARS_MODIFF = MODIFF;
1063 GAP_SIZE -= outgoing_nbytes;
1064 GPT += nchars;
1065 ZV += nchars;
1066 Z += nchars;
1067 GPT_BYTE += outgoing_nbytes;
1068 ZV_BYTE += outgoing_nbytes;
1069 Z_BYTE += outgoing_nbytes;
1070 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1072 if (GPT_BYTE < GPT)
1073 abort ();
1075 /* The insert may have been in the unchanged region, so check again. */
1076 if (Z - GPT < END_UNCHANGED)
1077 END_UNCHANGED = Z - GPT;
1079 adjust_overlays_for_insert (PT, nchars);
1080 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1081 PT_BYTE + outgoing_nbytes,
1082 before_markers);
1084 offset_intervals (current_buffer, PT, nchars);
1086 intervals = STRING_INTERVALS (string);
1087 /* Get the intervals for the part of the string we are inserting. */
1088 if (nbytes < SBYTES (string))
1089 intervals = copy_intervals (intervals, pos, nchars);
1091 /* Insert those intervals. */
1092 graft_intervals_into_buffer (intervals, PT, nchars,
1093 current_buffer, inherit);
1095 adjust_point (nchars, outgoing_nbytes);
1097 CHECK_MARKERS ();
1100 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
1101 starting at GPT_ADDR. */
1103 void
1104 insert_from_gap (EMACS_INT nchars, EMACS_INT nbytes)
1106 if (NILP (current_buffer->enable_multibyte_characters))
1107 nchars = nbytes;
1109 record_insert (GPT, nchars);
1110 MODIFF++;
1112 GAP_SIZE -= nbytes;
1113 GPT += nchars;
1114 ZV += nchars;
1115 Z += nchars;
1116 GPT_BYTE += nbytes;
1117 ZV_BYTE += nbytes;
1118 Z_BYTE += nbytes;
1119 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1121 if (GPT_BYTE < GPT)
1122 abort ();
1124 adjust_overlays_for_insert (GPT - nchars, nchars);
1125 adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
1126 GPT, GPT_BYTE, 0);
1128 if (BUF_INTERVALS (current_buffer) != 0)
1130 offset_intervals (current_buffer, GPT - nchars, nchars);
1131 graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars,
1132 current_buffer, 0);
1135 if (GPT - nchars < PT)
1136 adjust_point (nchars, nbytes);
1138 CHECK_MARKERS ();
1141 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1142 current buffer. If the text in BUF has properties, they are absorbed
1143 into the current buffer.
1145 It does not work to use `insert' for this, because a malloc could happen
1146 and relocate BUF's text before the copy happens. */
1148 void
1149 insert_from_buffer (struct buffer *buf,
1150 EMACS_INT charpos, EMACS_INT nchars, int inherit)
1152 EMACS_INT opoint = PT;
1154 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1155 signal_after_change (opoint, 0, PT - opoint);
1156 update_compositions (opoint, PT, CHECK_BORDER);
1159 static void
1160 insert_from_buffer_1 (struct buffer *buf,
1161 EMACS_INT from, EMACS_INT nchars, int inherit)
1163 register Lisp_Object temp;
1164 EMACS_INT chunk, chunk_expanded;
1165 EMACS_INT from_byte = buf_charpos_to_bytepos (buf, from);
1166 EMACS_INT to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1167 EMACS_INT incoming_nbytes = to_byte - from_byte;
1168 EMACS_INT outgoing_nbytes = incoming_nbytes;
1169 INTERVAL intervals;
1171 /* Make OUTGOING_NBYTES describe the text
1172 as it will be inserted in this buffer. */
1174 if (NILP (current_buffer->enable_multibyte_characters))
1175 outgoing_nbytes = nchars;
1176 else if (NILP (buf->enable_multibyte_characters))
1178 EMACS_INT outgoing_before_gap = 0;
1179 EMACS_INT outgoing_after_gap = 0;
1181 if (from < BUF_GPT (buf))
1183 chunk = BUF_GPT_BYTE (buf) - from_byte;
1184 if (chunk > incoming_nbytes)
1185 chunk = incoming_nbytes;
1186 outgoing_before_gap
1187 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1188 chunk);
1190 else
1191 chunk = 0;
1193 if (chunk < incoming_nbytes)
1194 outgoing_after_gap
1195 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1196 from_byte + chunk),
1197 incoming_nbytes - chunk);
1199 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1202 /* Make sure point-max won't overflow after this insertion. */
1203 XSETINT (temp, outgoing_nbytes + Z);
1204 if (outgoing_nbytes + Z != XINT (temp))
1205 error ("Maximum buffer size exceeded");
1207 /* Do this before moving and increasing the gap,
1208 because the before-change hooks might move the gap
1209 or make it smaller. */
1210 prepare_to_modify_buffer (PT, PT, NULL);
1212 if (PT != GPT)
1213 move_gap_both (PT, PT_BYTE);
1214 if (GAP_SIZE < outgoing_nbytes)
1215 make_gap (outgoing_nbytes - GAP_SIZE);
1217 if (from < BUF_GPT (buf))
1219 chunk = BUF_GPT_BYTE (buf) - from_byte;
1220 if (chunk > incoming_nbytes)
1221 chunk = incoming_nbytes;
1222 /* Record number of output bytes, so we know where
1223 to put the output from the second copy_text. */
1224 chunk_expanded
1225 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1226 GPT_ADDR, chunk,
1227 ! NILP (buf->enable_multibyte_characters),
1228 ! NILP (current_buffer->enable_multibyte_characters));
1230 else
1231 chunk_expanded = chunk = 0;
1233 if (chunk < incoming_nbytes)
1234 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1235 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1236 ! NILP (buf->enable_multibyte_characters),
1237 ! NILP (current_buffer->enable_multibyte_characters));
1239 #ifdef BYTE_COMBINING_DEBUG
1240 /* We have copied text into the gap, but we have not altered
1241 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1242 to these functions and get the same results as we would
1243 have got earlier on. Meanwhile, GPT_ADDR does point to
1244 the text that has been stored by copy_text. */
1245 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1246 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1247 abort ();
1248 #endif
1250 record_insert (PT, nchars);
1251 MODIFF++;
1252 CHARS_MODIFF = MODIFF;
1254 GAP_SIZE -= outgoing_nbytes;
1255 GPT += nchars;
1256 ZV += nchars;
1257 Z += nchars;
1258 GPT_BYTE += outgoing_nbytes;
1259 ZV_BYTE += outgoing_nbytes;
1260 Z_BYTE += outgoing_nbytes;
1261 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1263 if (GPT_BYTE < GPT)
1264 abort ();
1266 /* The insert may have been in the unchanged region, so check again. */
1267 if (Z - GPT < END_UNCHANGED)
1268 END_UNCHANGED = Z - GPT;
1270 adjust_overlays_for_insert (PT, nchars);
1271 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1272 PT_BYTE + outgoing_nbytes,
1275 if (BUF_INTERVALS (current_buffer) != 0)
1276 offset_intervals (current_buffer, PT, nchars);
1278 /* Get the intervals for the part of the string we are inserting. */
1279 intervals = BUF_INTERVALS (buf);
1280 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1282 if (buf == current_buffer && PT <= from)
1283 from += nchars;
1284 intervals = copy_intervals (intervals, from, nchars);
1287 /* Insert those intervals. */
1288 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1290 adjust_point (nchars, outgoing_nbytes);
1293 /* Record undo information and adjust markers and position keepers for
1294 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1295 chars (LEN_BYTE bytes) which resides in the gap just after
1296 GPT_ADDR.
1298 PREV_TEXT nil means the new text was just inserted. */
1300 void
1301 adjust_after_replace (EMACS_INT from, EMACS_INT from_byte,
1302 Lisp_Object prev_text, EMACS_INT len, EMACS_INT len_byte)
1304 EMACS_INT nchars_del = 0, nbytes_del = 0;
1306 #ifdef BYTE_COMBINING_DEBUG
1307 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1308 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1309 abort ();
1310 #endif
1312 if (STRINGP (prev_text))
1314 nchars_del = SCHARS (prev_text);
1315 nbytes_del = SBYTES (prev_text);
1318 /* Update various buffer positions for the new text. */
1319 GAP_SIZE -= len_byte;
1320 ZV += len; Z+= len;
1321 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1322 GPT += len; GPT_BYTE += len_byte;
1323 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1325 if (nchars_del > 0)
1326 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1327 len, len_byte);
1328 else
1329 adjust_markers_for_insert (from, from_byte,
1330 from + len, from_byte + len_byte, 0);
1332 if (! EQ (current_buffer->undo_list, Qt))
1334 if (nchars_del > 0)
1335 record_delete (from, prev_text);
1336 record_insert (from, len);
1339 if (len > nchars_del)
1340 adjust_overlays_for_insert (from, len - nchars_del);
1341 else if (len < nchars_del)
1342 adjust_overlays_for_delete (from, nchars_del - len);
1343 if (BUF_INTERVALS (current_buffer) != 0)
1345 offset_intervals (current_buffer, from, len - nchars_del);
1348 if (from < PT)
1349 adjust_point (len - nchars_del, len_byte - nbytes_del);
1351 /* As byte combining will decrease Z, we must check this again. */
1352 if (Z - GPT < END_UNCHANGED)
1353 END_UNCHANGED = Z - GPT;
1355 CHECK_MARKERS ();
1357 if (len == 0)
1358 evaporate_overlays (from);
1359 MODIFF++;
1360 CHARS_MODIFF = MODIFF;
1363 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
1364 This is for use when undo is not enabled in the current buffer. */
1366 void
1367 adjust_after_replace_noundo (EMACS_INT from, EMACS_INT from_byte,
1368 EMACS_INT nchars_del, EMACS_INT nbytes_del,
1369 EMACS_INT len, EMACS_INT len_byte)
1371 #ifdef BYTE_COMBINING_DEBUG
1372 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1373 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1374 abort ();
1375 #endif
1377 /* Update various buffer positions for the new text. */
1378 GAP_SIZE -= len_byte;
1379 ZV += len; Z+= len;
1380 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1381 GPT += len; GPT_BYTE += len_byte;
1382 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1384 if (nchars_del > 0)
1385 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1386 len, len_byte);
1387 else
1388 adjust_markers_for_insert (from, from_byte,
1389 from + len, from_byte + len_byte, 0);
1391 if (len > nchars_del)
1392 adjust_overlays_for_insert (from, len - nchars_del);
1393 else if (len < nchars_del)
1394 adjust_overlays_for_delete (from, nchars_del - len);
1395 if (BUF_INTERVALS (current_buffer) != 0)
1397 offset_intervals (current_buffer, from, len - nchars_del);
1400 if (from < PT)
1401 adjust_point (len - nchars_del, len_byte - nbytes_del);
1403 /* As byte combining will decrease Z, we must check this again. */
1404 if (Z - GPT < END_UNCHANGED)
1405 END_UNCHANGED = Z - GPT;
1407 CHECK_MARKERS ();
1409 if (len == 0)
1410 evaporate_overlays (from);
1411 MODIFF++;
1412 CHARS_MODIFF = MODIFF;
1415 /* Record undo information, adjust markers and position keepers for an
1416 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1417 text already exists in the current buffer but character length (TO
1418 - FROM) may be incorrect, the correct length is NEWLEN. */
1420 void
1421 adjust_after_insert (EMACS_INT from, EMACS_INT from_byte,
1422 EMACS_INT to, EMACS_INT to_byte, EMACS_INT newlen)
1424 EMACS_INT len = to - from, len_byte = to_byte - from_byte;
1426 if (GPT != to)
1427 move_gap_both (to, to_byte);
1428 GAP_SIZE += len_byte;
1429 GPT -= len; GPT_BYTE -= len_byte;
1430 ZV -= len; ZV_BYTE -= len_byte;
1431 Z -= len; Z_BYTE -= len_byte;
1432 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1435 /* Replace the text from character positions FROM to TO with NEW,
1436 If PREPARE is nonzero, call prepare_to_modify_buffer.
1437 If INHERIT, the newly inserted text should inherit text properties
1438 from the surrounding non-deleted text. */
1440 /* Note that this does not yet handle markers quite right.
1441 Also it needs to record a single undo-entry that does a replacement
1442 rather than a separate delete and insert.
1443 That way, undo will also handle markers properly.
1445 But if MARKERS is 0, don't relocate markers. */
1447 void
1448 replace_range (EMACS_INT from, EMACS_INT to, Lisp_Object new,
1449 int prepare, int inherit, int markers)
1451 EMACS_INT inschars = SCHARS (new);
1452 EMACS_INT insbytes = SBYTES (new);
1453 EMACS_INT from_byte, to_byte;
1454 EMACS_INT nbytes_del, nchars_del;
1455 register Lisp_Object temp;
1456 struct gcpro gcpro1;
1457 INTERVAL intervals;
1458 EMACS_INT outgoing_insbytes = insbytes;
1459 Lisp_Object deletion;
1461 CHECK_MARKERS ();
1463 GCPRO1 (new);
1464 deletion = Qnil;
1466 if (prepare)
1468 EMACS_INT range_length = to - from;
1469 prepare_to_modify_buffer (from, to, &from);
1470 to = from + range_length;
1473 UNGCPRO;
1475 /* Make args be valid */
1476 if (from < BEGV)
1477 from = BEGV;
1478 if (to > ZV)
1479 to = ZV;
1481 from_byte = CHAR_TO_BYTE (from);
1482 to_byte = CHAR_TO_BYTE (to);
1484 nchars_del = to - from;
1485 nbytes_del = to_byte - from_byte;
1487 if (nbytes_del <= 0 && insbytes == 0)
1488 return;
1490 /* Make OUTGOING_INSBYTES describe the text
1491 as it will be inserted in this buffer. */
1493 if (NILP (current_buffer->enable_multibyte_characters))
1494 outgoing_insbytes = inschars;
1495 else if (! STRING_MULTIBYTE (new))
1496 outgoing_insbytes
1497 = count_size_as_multibyte (SDATA (new), insbytes);
1499 /* Make sure point-max won't overflow after this insertion. */
1500 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1501 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1502 error ("Maximum buffer size exceeded");
1504 GCPRO1 (new);
1506 /* Make sure the gap is somewhere in or next to what we are deleting. */
1507 if (from > GPT)
1508 gap_right (from, from_byte);
1509 if (to < GPT)
1510 gap_left (to, to_byte, 0);
1512 /* Even if we don't record for undo, we must keep the original text
1513 because we may have to recover it because of inappropriate byte
1514 combining. */
1515 if (! EQ (current_buffer->undo_list, Qt))
1516 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1518 GAP_SIZE += nbytes_del;
1519 ZV -= nchars_del;
1520 Z -= nchars_del;
1521 ZV_BYTE -= nbytes_del;
1522 Z_BYTE -= nbytes_del;
1523 GPT = from;
1524 GPT_BYTE = from_byte;
1525 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1527 if (GPT_BYTE < GPT)
1528 abort ();
1530 if (GPT - BEG < BEG_UNCHANGED)
1531 BEG_UNCHANGED = GPT - BEG;
1532 if (Z - GPT < END_UNCHANGED)
1533 END_UNCHANGED = Z - GPT;
1535 if (GAP_SIZE < insbytes)
1536 make_gap (insbytes - GAP_SIZE);
1538 /* Copy the string text into the buffer, perhaps converting
1539 between single-byte and multibyte. */
1540 copy_text (SDATA (new), GPT_ADDR, insbytes,
1541 STRING_MULTIBYTE (new),
1542 ! NILP (current_buffer->enable_multibyte_characters));
1544 #ifdef BYTE_COMBINING_DEBUG
1545 /* We have copied text into the gap, but we have not marked
1546 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1547 here, for both the previous text and the following text.
1548 Meanwhile, GPT_ADDR does point to
1549 the text that has been stored by copy_text. */
1550 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1551 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1552 abort ();
1553 #endif
1555 if (! EQ (current_buffer->undo_list, Qt))
1557 /* Record the insertion first, so that when we undo,
1558 the deletion will be undone first. Thus, undo
1559 will insert before deleting, and thus will keep
1560 the markers before and after this text separate. */
1561 record_insert (from + SCHARS (deletion), inschars);
1562 record_delete (from, deletion);
1565 GAP_SIZE -= outgoing_insbytes;
1566 GPT += inschars;
1567 ZV += inschars;
1568 Z += inschars;
1569 GPT_BYTE += outgoing_insbytes;
1570 ZV_BYTE += outgoing_insbytes;
1571 Z_BYTE += outgoing_insbytes;
1572 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1574 if (GPT_BYTE < GPT)
1575 abort ();
1577 /* Adjust the overlay center as needed. This must be done after
1578 adjusting the markers that bound the overlays. */
1579 adjust_overlays_for_delete (from, nchars_del);
1580 adjust_overlays_for_insert (from, inschars);
1582 /* Adjust markers for the deletion and the insertion. */
1583 if (markers)
1584 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1585 inschars, outgoing_insbytes);
1587 offset_intervals (current_buffer, from, inschars - nchars_del);
1589 /* Get the intervals for the part of the string we are inserting--
1590 not including the combined-before bytes. */
1591 intervals = STRING_INTERVALS (new);
1592 /* Insert those intervals. */
1593 graft_intervals_into_buffer (intervals, from, inschars,
1594 current_buffer, inherit);
1596 /* Relocate point as if it were a marker. */
1597 if (from < PT)
1598 adjust_point ((from + inschars - (PT < to ? PT : to)),
1599 (from_byte + outgoing_insbytes
1600 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1602 if (outgoing_insbytes == 0)
1603 evaporate_overlays (from);
1605 CHECK_MARKERS ();
1607 MODIFF++;
1608 CHARS_MODIFF = MODIFF;
1609 UNGCPRO;
1611 signal_after_change (from, nchars_del, GPT - from);
1612 update_compositions (from, GPT, CHECK_BORDER);
1615 /* Replace the text from character positions FROM to TO with
1616 the text in INS of length INSCHARS.
1617 Keep the text properties that applied to the old characters
1618 (extending them to all the new chars if there are more new chars).
1620 Note that this does not yet handle markers quite right.
1622 If MARKERS is nonzero, relocate markers.
1624 Unlike most functions at this level, never call
1625 prepare_to_modify_buffer and never call signal_after_change. */
1627 void
1628 replace_range_2 (EMACS_INT from, EMACS_INT from_byte,
1629 EMACS_INT to, EMACS_INT to_byte,
1630 const char *ins, EMACS_INT inschars, EMACS_INT insbytes,
1631 int markers)
1633 EMACS_INT nbytes_del, nchars_del;
1634 Lisp_Object temp;
1636 CHECK_MARKERS ();
1638 nchars_del = to - from;
1639 nbytes_del = to_byte - from_byte;
1641 if (nbytes_del <= 0 && insbytes == 0)
1642 return;
1644 /* Make sure point-max won't overflow after this insertion. */
1645 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1646 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1647 error ("Maximum buffer size exceeded");
1649 /* Make sure the gap is somewhere in or next to what we are deleting. */
1650 if (from > GPT)
1651 gap_right (from, from_byte);
1652 if (to < GPT)
1653 gap_left (to, to_byte, 0);
1655 GAP_SIZE += nbytes_del;
1656 ZV -= nchars_del;
1657 Z -= nchars_del;
1658 ZV_BYTE -= nbytes_del;
1659 Z_BYTE -= nbytes_del;
1660 GPT = from;
1661 GPT_BYTE = from_byte;
1662 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1664 if (GPT_BYTE < GPT)
1665 abort ();
1667 if (GPT - BEG < BEG_UNCHANGED)
1668 BEG_UNCHANGED = GPT - BEG;
1669 if (Z - GPT < END_UNCHANGED)
1670 END_UNCHANGED = Z - GPT;
1672 if (GAP_SIZE < insbytes)
1673 make_gap (insbytes - GAP_SIZE);
1675 /* Copy the replacement text into the buffer. */
1676 memcpy (GPT_ADDR, ins, insbytes);
1678 #ifdef BYTE_COMBINING_DEBUG
1679 /* We have copied text into the gap, but we have not marked
1680 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1681 here, for both the previous text and the following text.
1682 Meanwhile, GPT_ADDR does point to
1683 the text that has been stored by copy_text. */
1684 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1685 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1686 abort ();
1687 #endif
1689 GAP_SIZE -= insbytes;
1690 GPT += inschars;
1691 ZV += inschars;
1692 Z += inschars;
1693 GPT_BYTE += insbytes;
1694 ZV_BYTE += insbytes;
1695 Z_BYTE += insbytes;
1696 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1698 if (GPT_BYTE < GPT)
1699 abort ();
1701 /* Adjust the overlay center as needed. This must be done after
1702 adjusting the markers that bound the overlays. */
1703 if (nchars_del != inschars)
1705 adjust_overlays_for_insert (from, inschars);
1706 adjust_overlays_for_delete (from + inschars, nchars_del);
1709 /* Adjust markers for the deletion and the insertion. */
1710 if (markers
1711 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1712 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1713 inschars, insbytes);
1715 offset_intervals (current_buffer, from, inschars - nchars_del);
1717 /* Relocate point as if it were a marker. */
1718 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1720 if (PT < to)
1721 /* PT was within the deleted text. Move it to FROM. */
1722 adjust_point (from - PT, from_byte - PT_BYTE);
1723 else
1724 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1727 if (insbytes == 0)
1728 evaporate_overlays (from);
1730 CHECK_MARKERS ();
1732 MODIFF++;
1733 CHARS_MODIFF = MODIFF;
1736 /* Delete characters in current buffer
1737 from FROM up to (but not including) TO.
1738 If TO comes before FROM, we delete nothing. */
1740 void
1741 del_range (EMACS_INT from, EMACS_INT to)
1743 del_range_1 (from, to, 1, 0);
1746 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1747 RET_STRING says to return the deleted text. */
1749 Lisp_Object
1750 del_range_1 (EMACS_INT from, EMACS_INT to, int prepare, int ret_string)
1752 EMACS_INT from_byte, to_byte;
1753 Lisp_Object deletion;
1754 struct gcpro gcpro1;
1756 /* Make args be valid */
1757 if (from < BEGV)
1758 from = BEGV;
1759 if (to > ZV)
1760 to = ZV;
1762 if (to <= from)
1763 return Qnil;
1765 if (prepare)
1767 EMACS_INT range_length = to - from;
1768 prepare_to_modify_buffer (from, to, &from);
1769 to = min (ZV, from + range_length);
1772 from_byte = CHAR_TO_BYTE (from);
1773 to_byte = CHAR_TO_BYTE (to);
1775 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1776 GCPRO1(deletion);
1777 signal_after_change (from, to - from, 0);
1778 update_compositions (from, from, CHECK_HEAD);
1779 UNGCPRO;
1780 return deletion;
1783 /* Like del_range_1 but args are byte positions, not char positions. */
1785 void
1786 del_range_byte (EMACS_INT from_byte, EMACS_INT to_byte, int prepare)
1788 EMACS_INT from, to;
1790 /* Make args be valid */
1791 if (from_byte < BEGV_BYTE)
1792 from_byte = BEGV_BYTE;
1793 if (to_byte > ZV_BYTE)
1794 to_byte = ZV_BYTE;
1796 if (to_byte <= from_byte)
1797 return;
1799 from = BYTE_TO_CHAR (from_byte);
1800 to = BYTE_TO_CHAR (to_byte);
1802 if (prepare)
1804 EMACS_INT old_from = from, old_to = Z - to;
1805 EMACS_INT range_length = to - from;
1806 prepare_to_modify_buffer (from, to, &from);
1807 to = from + range_length;
1809 if (old_from != from)
1810 from_byte = CHAR_TO_BYTE (from);
1811 if (to > ZV)
1813 to = ZV;
1814 to_byte = ZV_BYTE;
1816 else if (old_to == Z - to)
1817 to_byte = CHAR_TO_BYTE (to);
1820 del_range_2 (from, from_byte, to, to_byte, 0);
1821 signal_after_change (from, to - from, 0);
1822 update_compositions (from, from, CHECK_HEAD);
1825 /* Like del_range_1, but positions are specified both as charpos
1826 and bytepos. */
1828 void
1829 del_range_both (EMACS_INT from, EMACS_INT from_byte,
1830 EMACS_INT to, EMACS_INT to_byte, int prepare)
1832 /* Make args be valid */
1833 if (from_byte < BEGV_BYTE)
1834 from_byte = BEGV_BYTE;
1835 if (to_byte > ZV_BYTE)
1836 to_byte = ZV_BYTE;
1838 if (to_byte <= from_byte)
1839 return;
1841 if (from < BEGV)
1842 from = BEGV;
1843 if (to > ZV)
1844 to = ZV;
1846 if (prepare)
1848 EMACS_INT old_from = from, old_to = Z - to;
1849 EMACS_INT range_length = to - from;
1850 prepare_to_modify_buffer (from, to, &from);
1851 to = from + range_length;
1853 if (old_from != from)
1854 from_byte = CHAR_TO_BYTE (from);
1855 if (to > ZV)
1857 to = ZV;
1858 to_byte = ZV_BYTE;
1860 else if (old_to == Z - to)
1861 to_byte = CHAR_TO_BYTE (to);
1864 del_range_2 (from, from_byte, to, to_byte, 0);
1865 signal_after_change (from, to - from, 0);
1866 update_compositions (from, from, CHECK_HEAD);
1869 /* Delete a range of text, specified both as character positions
1870 and byte positions. FROM and TO are character positions,
1871 while FROM_BYTE and TO_BYTE are byte positions.
1872 If RET_STRING is true, the deleted area is returned as a string. */
1874 Lisp_Object
1875 del_range_2 (EMACS_INT from, EMACS_INT from_byte,
1876 EMACS_INT to, EMACS_INT to_byte, int ret_string)
1878 register EMACS_INT nbytes_del, nchars_del;
1879 Lisp_Object deletion;
1881 CHECK_MARKERS ();
1883 nchars_del = to - from;
1884 nbytes_del = to_byte - from_byte;
1886 /* Make sure the gap is somewhere in or next to what we are deleting. */
1887 if (from > GPT)
1888 gap_right (from, from_byte);
1889 if (to < GPT)
1890 gap_left (to, to_byte, 0);
1892 #ifdef BYTE_COMBINING_DEBUG
1893 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1894 Z_BYTE - to_byte, from, from_byte))
1895 abort ();
1896 #endif
1898 if (ret_string || ! EQ (current_buffer->undo_list, Qt))
1899 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1900 else
1901 deletion = Qnil;
1903 /* Relocate all markers pointing into the new, larger gap
1904 to point at the end of the text before the gap.
1905 Do this before recording the deletion,
1906 so that undo handles this after reinserting the text. */
1907 adjust_markers_for_delete (from, from_byte, to, to_byte);
1909 if (! EQ (current_buffer->undo_list, Qt))
1910 record_delete (from, deletion);
1911 MODIFF++;
1912 CHARS_MODIFF = MODIFF;
1914 /* Relocate point as if it were a marker. */
1915 if (from < PT)
1916 adjust_point (from - (PT < to ? PT : to),
1917 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1919 offset_intervals (current_buffer, from, - nchars_del);
1921 /* Adjust the overlay center as needed. This must be done after
1922 adjusting the markers that bound the overlays. */
1923 adjust_overlays_for_delete (from, nchars_del);
1925 GAP_SIZE += nbytes_del;
1926 ZV_BYTE -= nbytes_del;
1927 Z_BYTE -= nbytes_del;
1928 ZV -= nchars_del;
1929 Z -= nchars_del;
1930 GPT = from;
1931 GPT_BYTE = from_byte;
1932 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1933 /* Put an anchor, unless called from decode_coding_object which
1934 needs to access the previous gap contents. */
1935 *(GPT_ADDR) = 0;
1937 if (GPT_BYTE < GPT)
1938 abort ();
1940 if (GPT - BEG < BEG_UNCHANGED)
1941 BEG_UNCHANGED = GPT - BEG;
1942 if (Z - GPT < END_UNCHANGED)
1943 END_UNCHANGED = Z - GPT;
1945 CHECK_MARKERS ();
1947 evaporate_overlays (from);
1949 return deletion;
1952 /* Call this if you're about to change the region of BUFFER from
1953 character positions START to END. This checks the read-only
1954 properties of the region, calls the necessary modification hooks,
1955 and warns the next redisplay that it should pay attention to that
1956 area.
1958 If PRESERVE_CHARS_MODIFF is non-zero, do not update CHARS_MODIFF.
1959 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1961 void
1962 modify_region (struct buffer *buffer, EMACS_INT start, EMACS_INT end,
1963 int preserve_chars_modiff)
1965 struct buffer *old_buffer = current_buffer;
1967 if (buffer != old_buffer)
1968 set_buffer_internal (buffer);
1970 prepare_to_modify_buffer (start, end, NULL);
1972 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
1974 if (MODIFF <= SAVE_MODIFF)
1975 record_first_change ();
1976 MODIFF++;
1977 if (! preserve_chars_modiff)
1978 CHARS_MODIFF = MODIFF;
1980 buffer->point_before_scroll = Qnil;
1982 if (buffer != old_buffer)
1983 set_buffer_internal (old_buffer);
1986 /* Check that it is okay to modify the buffer between START and END,
1987 which are char positions.
1989 Run the before-change-function, if any. If intervals are in use,
1990 verify that the text to be modified is not read-only, and call
1991 any modification properties the text may have.
1993 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1994 by holding its value temporarily in a marker. */
1996 void
1997 prepare_to_modify_buffer (EMACS_INT start, EMACS_INT end,
1998 EMACS_INT *preserve_ptr)
2000 struct buffer *base_buffer;
2002 if (!NILP (current_buffer->read_only))
2003 Fbarf_if_buffer_read_only ();
2005 /* Let redisplay consider other windows than selected_window
2006 if modifying another buffer. */
2007 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2008 ++windows_or_buffers_changed;
2010 if (BUF_INTERVALS (current_buffer) != 0)
2012 if (preserve_ptr)
2014 Lisp_Object preserve_marker;
2015 struct gcpro gcpro1;
2016 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
2017 GCPRO1 (preserve_marker);
2018 verify_interval_modification (current_buffer, start, end);
2019 *preserve_ptr = marker_position (preserve_marker);
2020 unchain_marker (XMARKER (preserve_marker));
2021 UNGCPRO;
2023 else
2024 verify_interval_modification (current_buffer, start, end);
2027 /* For indirect buffers, use the base buffer to check clashes. */
2028 if (current_buffer->base_buffer != 0)
2029 base_buffer = current_buffer->base_buffer;
2030 else
2031 base_buffer = current_buffer;
2033 #ifdef CLASH_DETECTION
2034 if (!NILP (base_buffer->file_truename)
2035 /* Make binding buffer-file-name to nil effective. */
2036 && !NILP (base_buffer->filename)
2037 && SAVE_MODIFF >= MODIFF)
2038 lock_file (base_buffer->file_truename);
2039 #else
2040 /* At least warn if this file has changed on disk since it was visited. */
2041 if (!NILP (base_buffer->filename)
2042 && SAVE_MODIFF >= MODIFF
2043 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
2044 && !NILP (Ffile_exists_p (base_buffer->filename)))
2045 call1 (intern ("ask-user-about-supersession-threat"),
2046 base_buffer->filename);
2047 #endif /* not CLASH_DETECTION */
2049 /* If `select-active-regions' is non-nil, save the region text. */
2050 if (!NILP (current_buffer->mark_active)
2051 && !inhibit_modification_hooks
2052 && XMARKER (current_buffer->mark)->buffer
2053 && NILP (Vsaved_region_selection)
2054 && (EQ (Vselect_active_regions, Qonly)
2055 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
2056 : (!NILP (Vselect_active_regions)
2057 && !NILP (Vtransient_mark_mode))))
2059 EMACS_INT b = XMARKER (current_buffer->mark)->charpos;
2060 EMACS_INT e = PT;
2061 if (b < e)
2062 Vsaved_region_selection = make_buffer_string (b, e, 0);
2063 else if (b > e)
2064 Vsaved_region_selection = make_buffer_string (e, b, 0);
2067 signal_before_change (start, end, preserve_ptr);
2069 if (current_buffer->newline_cache)
2070 invalidate_region_cache (current_buffer,
2071 current_buffer->newline_cache,
2072 start - BEG, Z - end);
2073 if (current_buffer->width_run_cache)
2074 invalidate_region_cache (current_buffer,
2075 current_buffer->width_run_cache,
2076 start - BEG, Z - end);
2078 Vdeactivate_mark = Qt;
2081 /* These macros work with an argument named `preserve_ptr'
2082 and a local variable named `preserve_marker'. */
2084 #define PRESERVE_VALUE \
2085 if (preserve_ptr && NILP (preserve_marker)) \
2086 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
2088 #define RESTORE_VALUE \
2089 if (! NILP (preserve_marker)) \
2091 *preserve_ptr = marker_position (preserve_marker); \
2092 unchain_marker (XMARKER (preserve_marker)); \
2095 #define PRESERVE_START_END \
2096 if (NILP (start_marker)) \
2097 start_marker = Fcopy_marker (start, Qnil); \
2098 if (NILP (end_marker)) \
2099 end_marker = Fcopy_marker (end, Qnil);
2101 #define FETCH_START \
2102 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2104 #define FETCH_END \
2105 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2107 /* Set a variable to nil if an error occurred.
2108 Don't change the variable if there was no error.
2109 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
2110 VARIABLE is the variable to maybe set to nil.
2111 NO-ERROR-FLAG is nil if there was an error,
2112 anything else meaning no error (so this function does nothing). */
2113 Lisp_Object
2114 reset_var_on_error (Lisp_Object val)
2116 if (NILP (XCDR (val)))
2117 Fset (XCAR (val), Qnil);
2118 return Qnil;
2121 /* Signal a change to the buffer immediately before it happens.
2122 START_INT and END_INT are the bounds of the text to be changed.
2124 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
2125 by holding its value temporarily in a marker. */
2127 void
2128 signal_before_change (EMACS_INT start_int, EMACS_INT end_int,
2129 EMACS_INT *preserve_ptr)
2131 Lisp_Object start, end;
2132 Lisp_Object start_marker, end_marker;
2133 Lisp_Object preserve_marker;
2134 struct gcpro gcpro1, gcpro2, gcpro3;
2135 int count = SPECPDL_INDEX ();
2137 if (inhibit_modification_hooks)
2138 return;
2140 start = make_number (start_int);
2141 end = make_number (end_int);
2142 preserve_marker = Qnil;
2143 start_marker = Qnil;
2144 end_marker = Qnil;
2145 GCPRO3 (preserve_marker, start_marker, end_marker);
2147 specbind (Qinhibit_modification_hooks, Qt);
2149 /* If buffer is unmodified, run a special hook for that case. */
2150 if (SAVE_MODIFF >= MODIFF
2151 && !NILP (Vfirst_change_hook)
2152 && !NILP (Vrun_hooks))
2154 PRESERVE_VALUE;
2155 PRESERVE_START_END;
2156 call1 (Vrun_hooks, Qfirst_change_hook);
2159 /* Now run the before-change-functions if any. */
2160 if (!NILP (Vbefore_change_functions))
2162 Lisp_Object args[3];
2163 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
2165 PRESERVE_VALUE;
2166 PRESERVE_START_END;
2168 /* Mark before-change-functions to be reset to nil in case of error. */
2169 record_unwind_protect (reset_var_on_error, rvoe_arg);
2171 /* Actually run the hook functions. */
2172 args[0] = Qbefore_change_functions;
2173 args[1] = FETCH_START;
2174 args[2] = FETCH_END;
2175 Frun_hook_with_args (3, args);
2177 /* There was no error: unarm the reset_on_error. */
2178 XSETCDR (rvoe_arg, Qt);
2181 if (current_buffer->overlays_before || current_buffer->overlays_after)
2183 PRESERVE_VALUE;
2184 report_overlay_modification (FETCH_START, FETCH_END, 0,
2185 FETCH_START, FETCH_END, Qnil);
2188 if (! NILP (start_marker))
2189 free_marker (start_marker);
2190 if (! NILP (end_marker))
2191 free_marker (end_marker);
2192 RESTORE_VALUE;
2193 UNGCPRO;
2195 unbind_to (count, Qnil);
2198 /* Signal a change immediately after it happens.
2199 CHARPOS is the character position of the start of the changed text.
2200 LENDEL is the number of characters of the text before the change.
2201 (Not the whole buffer; just the part that was changed.)
2202 LENINS is the number of characters in that part of the text
2203 after the change. */
2205 void
2206 signal_after_change (EMACS_INT charpos, EMACS_INT lendel, EMACS_INT lenins)
2208 int count = SPECPDL_INDEX ();
2209 if (inhibit_modification_hooks)
2210 return;
2212 /* If we are deferring calls to the after-change functions
2213 and there are no before-change functions,
2214 just record the args that we were going to use. */
2215 if (! NILP (Vcombine_after_change_calls)
2216 && NILP (Vbefore_change_functions)
2217 && !current_buffer->overlays_before
2218 && !current_buffer->overlays_after)
2220 Lisp_Object elt;
2222 if (!NILP (combine_after_change_list)
2223 && current_buffer != XBUFFER (combine_after_change_buffer))
2224 Fcombine_after_change_execute ();
2226 elt = Fcons (make_number (charpos - BEG),
2227 Fcons (make_number (Z - (charpos - lendel + lenins)),
2228 Fcons (make_number (lenins - lendel), Qnil)));
2229 combine_after_change_list
2230 = Fcons (elt, combine_after_change_list);
2231 combine_after_change_buffer = Fcurrent_buffer ();
2233 return;
2236 if (!NILP (combine_after_change_list))
2237 Fcombine_after_change_execute ();
2239 specbind (Qinhibit_modification_hooks, Qt);
2241 if (!NILP (Vafter_change_functions))
2243 Lisp_Object args[4];
2244 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2246 /* Mark after-change-functions to be reset to nil in case of error. */
2247 record_unwind_protect (reset_var_on_error, rvoe_arg);
2249 /* Actually run the hook functions. */
2250 args[0] = Qafter_change_functions;
2251 XSETFASTINT (args[1], charpos);
2252 XSETFASTINT (args[2], charpos + lenins);
2253 XSETFASTINT (args[3], lendel);
2254 Frun_hook_with_args (4, args);
2256 /* There was no error: unarm the reset_on_error. */
2257 XSETCDR (rvoe_arg, Qt);
2260 if (current_buffer->overlays_before || current_buffer->overlays_after)
2261 report_overlay_modification (make_number (charpos),
2262 make_number (charpos + lenins),
2264 make_number (charpos),
2265 make_number (charpos + lenins),
2266 make_number (lendel));
2268 /* After an insertion, call the text properties
2269 insert-behind-hooks or insert-in-front-hooks. */
2270 if (lendel == 0)
2271 report_interval_modification (make_number (charpos),
2272 make_number (charpos + lenins));
2274 unbind_to (count, Qnil);
2277 Lisp_Object
2278 Fcombine_after_change_execute_1 (Lisp_Object val)
2280 Vcombine_after_change_calls = val;
2281 return val;
2284 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2285 Scombine_after_change_execute, 0, 0, 0,
2286 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2287 (void)
2289 int count = SPECPDL_INDEX ();
2290 EMACS_INT beg, end, change;
2291 EMACS_INT begpos, endpos;
2292 Lisp_Object tail;
2294 if (NILP (combine_after_change_list))
2295 return Qnil;
2297 /* It is rare for combine_after_change_buffer to be invalid, but
2298 possible. It can happen when combine-after-change-calls is
2299 non-nil, and insertion calls a file handler (e.g. through
2300 lock_file) which scribbles into a temp file -- cyd */
2301 if (!BUFFERP (combine_after_change_buffer)
2302 || NILP (XBUFFER (combine_after_change_buffer)->name))
2304 combine_after_change_list = Qnil;
2305 return Qnil;
2308 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2310 Fset_buffer (combine_after_change_buffer);
2312 /* # chars unchanged at beginning of buffer. */
2313 beg = Z - BEG;
2314 /* # chars unchanged at end of buffer. */
2315 end = beg;
2316 /* Total amount of insertion (negative for deletion). */
2317 change = 0;
2319 /* Scan the various individual changes,
2320 accumulating the range info in BEG, END and CHANGE. */
2321 for (tail = combine_after_change_list; CONSP (tail);
2322 tail = XCDR (tail))
2324 Lisp_Object elt;
2325 EMACS_INT thisbeg, thisend, thischange;
2327 /* Extract the info from the next element. */
2328 elt = XCAR (tail);
2329 if (! CONSP (elt))
2330 continue;
2331 thisbeg = XINT (XCAR (elt));
2333 elt = XCDR (elt);
2334 if (! CONSP (elt))
2335 continue;
2336 thisend = XINT (XCAR (elt));
2338 elt = XCDR (elt);
2339 if (! CONSP (elt))
2340 continue;
2341 thischange = XINT (XCAR (elt));
2343 /* Merge this range into the accumulated range. */
2344 change += thischange;
2345 if (thisbeg < beg)
2346 beg = thisbeg;
2347 if (thisend < end)
2348 end = thisend;
2351 /* Get the current start and end positions of the range
2352 that was changed. */
2353 begpos = BEG + beg;
2354 endpos = Z - end;
2356 /* We are about to handle these, so discard them. */
2357 combine_after_change_list = Qnil;
2359 /* Now run the after-change functions for real.
2360 Turn off the flag that defers them. */
2361 record_unwind_protect (Fcombine_after_change_execute_1,
2362 Vcombine_after_change_calls);
2363 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2364 update_compositions (begpos, endpos, CHECK_ALL);
2366 return unbind_to (count, Qnil);
2369 void
2370 syms_of_insdel (void)
2372 staticpro (&combine_after_change_list);
2373 staticpro (&combine_after_change_buffer);
2374 combine_after_change_list = Qnil;
2375 combine_after_change_buffer = Qnil;
2377 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag,
2378 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
2379 check_markers_debug_flag = 0;
2380 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
2381 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2382 Vcombine_after_change_calls = Qnil;
2384 DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks,
2385 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2386 This affects `before-change-functions' and `after-change-functions',
2387 as well as hooks attached to text properties and overlays. */);
2388 inhibit_modification_hooks = 0;
2389 Qinhibit_modification_hooks = intern_c_string ("inhibit-modification-hooks");
2390 staticpro (&Qinhibit_modification_hooks);
2392 defsubr (&Scombine_after_change_execute);