Convenient macro to check whether the buffer is live.
[bpt/emacs.git] / src / insdel.c
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985-1986, 1993-1995, 1997-2012
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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.
11
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.
16
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/>. */
19
20
21 #include <config.h>
22 #include <setjmp.h>
23
24 #include <intprops.h>
25
26 #include "lisp.h"
27 #include "intervals.h"
28 #include "character.h"
29 #include "buffer.h"
30 #include "window.h"
31 #include "blockinput.h"
32 #include "region-cache.h"
33
34 static void insert_from_string_1 (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t,
35 ptrdiff_t, bool, bool);
36 static void insert_from_buffer_1 (struct buffer *, ptrdiff_t, ptrdiff_t, bool);
37 static void gap_left (ptrdiff_t, ptrdiff_t, bool);
38 static void gap_right (ptrdiff_t, ptrdiff_t);
39
40 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
41 describing changes which happened while combine_after_change_calls
42 was non-nil. We use this to decide how to call them
43 once the deferral ends.
44
45 In each element.
46 BEG-UNCHANGED is the number of chars before the changed range.
47 END-UNCHANGED is the number of chars after the changed range,
48 and CHANGE-AMOUNT is the number of characters inserted by the change
49 (negative for a deletion). */
50 static Lisp_Object combine_after_change_list;
51
52 /* Buffer which combine_after_change_list is about. */
53 static Lisp_Object combine_after_change_buffer;
54
55 Lisp_Object Qinhibit_modification_hooks;
56
57 static void signal_before_change (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
58
59 /* Also used in marker.c to enable expensive marker checks. */
60
61 #ifdef MARKER_DEBUG
62
63 static void
64 check_markers (void)
65 {
66 struct Lisp_Marker *tail;
67 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
68
69 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
70 {
71 if (tail->buffer->text != current_buffer->text)
72 emacs_abort ();
73 if (tail->charpos > Z)
74 emacs_abort ();
75 if (tail->bytepos > Z_BYTE)
76 emacs_abort ();
77 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
78 emacs_abort ();
79 }
80 }
81
82 #else /* not MARKER_DEBUG */
83
84 #define check_markers() do { } while (0)
85
86 #endif /* MARKER_DEBUG */
87
88 /* Move gap to position CHARPOS.
89 Note that this can quit! */
90
91 void
92 move_gap (ptrdiff_t charpos)
93 {
94 move_gap_both (charpos, charpos_to_bytepos (charpos));
95 }
96
97 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
98 Note that this can quit! */
99
100 void
101 move_gap_both (ptrdiff_t charpos, ptrdiff_t bytepos)
102 {
103 if (bytepos < GPT_BYTE)
104 gap_left (charpos, bytepos, 0);
105 else if (bytepos > GPT_BYTE)
106 gap_right (charpos, bytepos);
107 }
108
109 /* Move the gap to a position less than the current GPT.
110 BYTEPOS describes the new position as a byte position,
111 and CHARPOS is the corresponding char position.
112 If NEWGAP, then don't update beg_unchanged and end_unchanged. */
113
114 static void
115 gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, bool newgap)
116 {
117 unsigned char *to, *from;
118 ptrdiff_t i;
119 ptrdiff_t new_s1;
120
121 if (!newgap)
122 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
123
124 i = GPT_BYTE;
125 to = GAP_END_ADDR;
126 from = GPT_ADDR;
127 new_s1 = GPT_BYTE;
128
129 /* Now copy the characters. To move the gap down,
130 copy characters up. */
131
132 while (1)
133 {
134 /* I gets number of characters left to copy. */
135 i = new_s1 - bytepos;
136 if (i == 0)
137 break;
138 /* If a quit is requested, stop copying now.
139 Change BYTEPOS to be where we have actually moved the gap to. */
140 if (QUITP)
141 {
142 bytepos = new_s1;
143 charpos = BYTE_TO_CHAR (bytepos);
144 break;
145 }
146 /* Move at most 32000 chars before checking again for a quit. */
147 if (i > 32000)
148 i = 32000;
149 new_s1 -= i;
150 from -= i, to -= i;
151 memmove (to, from, i);
152 }
153
154 /* Adjust buffer data structure, to put the gap at BYTEPOS.
155 BYTEPOS is where the loop above stopped, which may be what
156 was specified or may be where a quit was detected. */
157 GPT_BYTE = bytepos;
158 GPT = charpos;
159 eassert (charpos <= bytepos);
160 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
161 QUIT;
162 }
163
164 /* Move the gap to a position greater than the current GPT.
165 BYTEPOS describes the new position as a byte position,
166 and CHARPOS is the corresponding char position. */
167
168 static void
169 gap_right (ptrdiff_t charpos, ptrdiff_t bytepos)
170 {
171 register unsigned char *to, *from;
172 register ptrdiff_t i;
173 ptrdiff_t new_s1;
174
175 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
176
177 i = GPT_BYTE;
178 from = GAP_END_ADDR;
179 to = GPT_ADDR;
180 new_s1 = GPT_BYTE;
181
182 /* Now copy the characters. To move the gap up,
183 copy characters down. */
184
185 while (1)
186 {
187 /* I gets number of characters left to copy. */
188 i = bytepos - new_s1;
189 if (i == 0)
190 break;
191 /* If a quit is requested, stop copying now.
192 Change BYTEPOS to be where we have actually moved the gap to. */
193 if (QUITP)
194 {
195 bytepos = new_s1;
196 charpos = BYTE_TO_CHAR (bytepos);
197 break;
198 }
199 /* Move at most 32000 chars before checking again for a quit. */
200 if (i > 32000)
201 i = 32000;
202 new_s1 += i;
203 memmove (to, from, i);
204 from += i, to += i;
205 }
206
207 GPT = charpos;
208 GPT_BYTE = bytepos;
209 eassert (charpos <= bytepos);
210 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
211 QUIT;
212 }
213 \f
214 /* Adjust all markers for a deletion
215 whose range in bytes is FROM_BYTE to TO_BYTE.
216 The range in charpos is FROM to TO.
217
218 This function assumes that the gap is adjacent to
219 or inside of the range being deleted. */
220
221 void
222 adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte,
223 ptrdiff_t to, ptrdiff_t to_byte)
224 {
225 Lisp_Object marker;
226 register struct Lisp_Marker *m;
227 register ptrdiff_t charpos;
228
229 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
230 {
231 charpos = m->charpos;
232 eassert (charpos <= Z);
233
234 /* If the marker is after the deletion,
235 relocate by number of chars / bytes deleted. */
236 if (charpos > to)
237 {
238 m->charpos -= to - from;
239 m->bytepos -= to_byte - from_byte;
240 }
241 /* Here's the case where a marker is inside text being deleted. */
242 else if (charpos > from)
243 {
244 if (! m->insertion_type)
245 { /* Normal markers will end up at the beginning of the
246 re-inserted text after undoing a deletion, and must be
247 adjusted to move them to the correct place. */
248 XSETMISC (marker, m);
249 record_marker_adjustment (marker, from - charpos);
250 }
251 else if (charpos < to)
252 { /* Before-insertion markers will automatically move forward
253 upon re-inserting the deleted text, so we have to arrange
254 for them to move backward to the correct position. */
255 XSETMISC (marker, m);
256 record_marker_adjustment (marker, to - charpos);
257 }
258 m->charpos = from;
259 m->bytepos = from_byte;
260 }
261 /* Here's the case where a before-insertion marker is immediately
262 before the deleted region. */
263 else if (charpos == from && m->insertion_type)
264 {
265 /* Undoing the change uses normal insertion, which will
266 incorrectly make MARKER move forward, so we arrange for it
267 to then move backward to the correct place at the beginning
268 of the deleted region. */
269 XSETMISC (marker, m);
270 record_marker_adjustment (marker, to - from);
271 }
272 }
273 }
274
275 \f
276 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
277 to TO / TO_BYTE. We have to relocate the charpos of every marker
278 that points after the insertion (but not their bytepos).
279
280 When a marker points at the insertion point,
281 we advance it if either its insertion-type is t
282 or BEFORE_MARKERS is true. */
283
284 static void
285 adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
286 ptrdiff_t to, ptrdiff_t to_byte, bool before_markers)
287 {
288 struct Lisp_Marker *m;
289 bool adjusted = 0;
290 ptrdiff_t nchars = to - from;
291 ptrdiff_t nbytes = to_byte - from_byte;
292
293 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
294 {
295 eassert (m->bytepos >= m->charpos
296 && m->bytepos - m->charpos <= Z_BYTE - Z);
297
298 if (m->bytepos == from_byte)
299 {
300 if (m->insertion_type || before_markers)
301 {
302 m->bytepos = to_byte;
303 m->charpos = to;
304 if (m->insertion_type)
305 adjusted = 1;
306 }
307 }
308 else if (m->bytepos > from_byte)
309 {
310 m->bytepos += nbytes;
311 m->charpos += nchars;
312 }
313 }
314
315 /* Adjusting only markers whose insertion-type is t may result in
316 - disordered start and end in overlays, and
317 - disordered overlays in the slot `overlays_before' of current_buffer. */
318 if (adjusted)
319 {
320 fix_start_end_in_overlays (from, to);
321 fix_overlays_before (current_buffer, from, to);
322 }
323 }
324
325 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
326
327 This is used only when the value of point changes due to an insert
328 or delete; it does not represent a conceptual change in point as a
329 marker. In particular, point is not crossing any interval
330 boundaries, so there's no need to use the usual SET_PT macro. In
331 fact it would be incorrect to do so, because either the old or the
332 new value of point is out of sync with the current set of
333 intervals. */
334
335 static void
336 adjust_point (ptrdiff_t nchars, ptrdiff_t nbytes)
337 {
338 SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes);
339 /* In a single-byte buffer, the two positions must be equal. */
340 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
341 }
342 \f
343 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
344 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
345 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
346 an insertion. */
347
348 static void
349 adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
350 ptrdiff_t old_chars, ptrdiff_t old_bytes,
351 ptrdiff_t new_chars, ptrdiff_t new_bytes)
352 {
353 register struct Lisp_Marker *m;
354 ptrdiff_t prev_to_byte = from_byte + old_bytes;
355 ptrdiff_t diff_chars = new_chars - old_chars;
356 ptrdiff_t diff_bytes = new_bytes - old_bytes;
357
358 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
359 {
360 if (m->bytepos >= prev_to_byte)
361 {
362 m->charpos += diff_chars;
363 m->bytepos += diff_bytes;
364 }
365 else if (m->bytepos > from_byte)
366 {
367 m->charpos = from;
368 m->bytepos = from_byte;
369 }
370 }
371
372 check_markers ();
373 }
374
375 \f
376 void
377 buffer_overflow (void)
378 {
379 error ("Maximum buffer size exceeded");
380 }
381
382 /* Make the gap NBYTES_ADDED bytes longer. */
383
384 static void
385 make_gap_larger (ptrdiff_t nbytes_added)
386 {
387 Lisp_Object tem;
388 ptrdiff_t real_gap_loc;
389 ptrdiff_t real_gap_loc_byte;
390 ptrdiff_t old_gap_size;
391 ptrdiff_t current_size = Z_BYTE - BEG_BYTE + GAP_SIZE;
392 enum { enough_for_a_while = 2000 };
393
394 if (BUF_BYTES_MAX - current_size < nbytes_added)
395 buffer_overflow ();
396
397 /* If we have to get more space, get enough to last a while;
398 but do not exceed the maximum buffer size. */
399 nbytes_added = min (nbytes_added + enough_for_a_while,
400 BUF_BYTES_MAX - current_size);
401
402 enlarge_buffer_text (current_buffer, nbytes_added);
403
404 /* Prevent quitting in move_gap. */
405 tem = Vinhibit_quit;
406 Vinhibit_quit = Qt;
407
408 real_gap_loc = GPT;
409 real_gap_loc_byte = GPT_BYTE;
410 old_gap_size = GAP_SIZE;
411
412 /* Call the newly allocated space a gap at the end of the whole space. */
413 GPT = Z + GAP_SIZE;
414 GPT_BYTE = Z_BYTE + GAP_SIZE;
415 GAP_SIZE = nbytes_added;
416
417 /* Move the new gap down to be consecutive with the end of the old one.
418 This adjusts the markers properly too. */
419 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
420
421 /* Now combine the two into one large gap. */
422 GAP_SIZE += old_gap_size;
423 GPT = real_gap_loc;
424 GPT_BYTE = real_gap_loc_byte;
425
426 /* Put an anchor. */
427 *(Z_ADDR) = 0;
428
429 Vinhibit_quit = tem;
430 }
431
432 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
433
434 /* Make the gap NBYTES_REMOVED bytes shorter. */
435
436 static void
437 make_gap_smaller (ptrdiff_t nbytes_removed)
438 {
439 Lisp_Object tem;
440 ptrdiff_t real_gap_loc;
441 ptrdiff_t real_gap_loc_byte;
442 ptrdiff_t real_Z;
443 ptrdiff_t real_Z_byte;
444 ptrdiff_t real_beg_unchanged;
445 ptrdiff_t new_gap_size;
446
447 /* Make sure the gap is at least 20 bytes. */
448 if (GAP_SIZE - nbytes_removed < 20)
449 nbytes_removed = GAP_SIZE - 20;
450
451 /* Prevent quitting in move_gap. */
452 tem = Vinhibit_quit;
453 Vinhibit_quit = Qt;
454
455 real_gap_loc = GPT;
456 real_gap_loc_byte = GPT_BYTE;
457 new_gap_size = GAP_SIZE - nbytes_removed;
458 real_Z = Z;
459 real_Z_byte = Z_BYTE;
460 real_beg_unchanged = BEG_UNCHANGED;
461
462 /* Pretend that the last unwanted part of the gap is the entire gap,
463 and that the first desired part of the gap is part of the buffer
464 text. */
465 memset (GPT_ADDR, 0, new_gap_size);
466 GPT += new_gap_size;
467 GPT_BYTE += new_gap_size;
468 Z += new_gap_size;
469 Z_BYTE += new_gap_size;
470 GAP_SIZE = nbytes_removed;
471
472 /* Move the unwanted pretend gap to the end of the buffer. This
473 adjusts the markers properly too. */
474 gap_right (Z, Z_BYTE);
475
476 enlarge_buffer_text (current_buffer, -nbytes_removed);
477
478 /* Now restore the desired gap. */
479 GAP_SIZE = new_gap_size;
480 GPT = real_gap_loc;
481 GPT_BYTE = real_gap_loc_byte;
482 Z = real_Z;
483 Z_BYTE = real_Z_byte;
484 BEG_UNCHANGED = real_beg_unchanged;
485
486 /* Put an anchor. */
487 *(Z_ADDR) = 0;
488
489 Vinhibit_quit = tem;
490 }
491
492 #endif /* USE_MMAP_FOR_BUFFERS || REL_ALLOC || DOUG_LEA_MALLOC */
493
494 void
495 make_gap (ptrdiff_t nbytes_added)
496 {
497 if (nbytes_added >= 0)
498 make_gap_larger (nbytes_added);
499 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
500 else
501 make_gap_smaller (-nbytes_added);
502 #endif
503 }
504 \f
505 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
506 FROM_MULTIBYTE says whether the incoming text is multibyte.
507 TO_MULTIBYTE says whether to store the text as multibyte.
508 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
509
510 Return the number of bytes stored at TO_ADDR. */
511
512 ptrdiff_t
513 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
514 ptrdiff_t nbytes, bool from_multibyte, bool to_multibyte)
515 {
516 if (from_multibyte == to_multibyte)
517 {
518 memcpy (to_addr, from_addr, nbytes);
519 return nbytes;
520 }
521 else if (from_multibyte)
522 {
523 ptrdiff_t nchars = 0;
524 ptrdiff_t bytes_left = nbytes;
525
526 while (bytes_left > 0)
527 {
528 int thislen, c;
529 c = STRING_CHAR_AND_LENGTH (from_addr, thislen);
530 if (! ASCII_CHAR_P (c))
531 c &= 0xFF;
532 *to_addr++ = c;
533 from_addr += thislen;
534 bytes_left -= thislen;
535 nchars++;
536 }
537 return nchars;
538 }
539 else
540 {
541 unsigned char *initial_to_addr = to_addr;
542
543 /* Convert single-byte to multibyte. */
544 while (nbytes > 0)
545 {
546 int c = *from_addr++;
547
548 if (!ASCII_CHAR_P (c))
549 {
550 c = BYTE8_TO_CHAR (c);
551 to_addr += CHAR_STRING (c, to_addr);
552 nbytes--;
553 }
554 else
555 /* Special case for speed. */
556 *to_addr++ = c, nbytes--;
557 }
558 return to_addr - initial_to_addr;
559 }
560 }
561 \f
562 /* Insert a string of specified length before point.
563 This function judges multibyteness based on
564 enable_multibyte_characters in the current buffer;
565 it never converts between single-byte and multibyte.
566
567 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
568 prepare_to_modify_buffer could relocate the text. */
569
570 void
571 insert (const char *string, ptrdiff_t nbytes)
572 {
573 if (nbytes > 0)
574 {
575 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
576 insert_1_both (string, len, nbytes, 0, 1, 0);
577 opoint = PT - len;
578 signal_after_change (opoint, 0, len);
579 update_compositions (opoint, PT, CHECK_BORDER);
580 }
581 }
582
583 /* Likewise, but inherit text properties from neighboring characters. */
584
585 void
586 insert_and_inherit (const char *string, ptrdiff_t nbytes)
587 {
588 if (nbytes > 0)
589 {
590 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
591 insert_1_both (string, len, nbytes, 1, 1, 0);
592 opoint = PT - len;
593 signal_after_change (opoint, 0, len);
594 update_compositions (opoint, PT, CHECK_BORDER);
595 }
596 }
597
598 /* Insert the character C before point. Do not inherit text properties. */
599
600 void
601 insert_char (int c)
602 {
603 unsigned char str[MAX_MULTIBYTE_LENGTH];
604 int len;
605
606 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
607 len = CHAR_STRING (c, str);
608 else
609 {
610 len = 1;
611 str[0] = c;
612 }
613
614 insert ((char *) str, len);
615 }
616
617 /* Insert the null-terminated string S before point. */
618
619 void
620 insert_string (const char *s)
621 {
622 insert (s, strlen (s));
623 }
624
625 /* Like `insert' except that all markers pointing at the place where
626 the insertion happens are adjusted to point after it.
627 Don't use this function to insert part of a Lisp string,
628 since gc could happen and relocate it. */
629
630 void
631 insert_before_markers (const char *string, ptrdiff_t nbytes)
632 {
633 if (nbytes > 0)
634 {
635 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
636 insert_1_both (string, len, nbytes, 0, 1, 1);
637 opoint = PT - len;
638 signal_after_change (opoint, 0, len);
639 update_compositions (opoint, PT, CHECK_BORDER);
640 }
641 }
642
643 /* Likewise, but inherit text properties from neighboring characters. */
644
645 void
646 insert_before_markers_and_inherit (const char *string,
647 ptrdiff_t nbytes)
648 {
649 if (nbytes > 0)
650 {
651 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
652 insert_1_both (string, len, nbytes, 1, 1, 1);
653 opoint = PT - len;
654 signal_after_change (opoint, 0, len);
655 update_compositions (opoint, PT, CHECK_BORDER);
656 }
657 }
658
659 /* Subroutine used by the insert functions above. */
660
661 void
662 insert_1 (const char *string, ptrdiff_t nbytes,
663 bool inherit, bool prepare, bool before_markers)
664 {
665 insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
666 nbytes, inherit, prepare, before_markers);
667 }
668
669 \f
670 #ifdef BYTE_COMBINING_DEBUG
671
672 /* See if the bytes before POS/POS_BYTE combine with bytes
673 at the start of STRING to form a single character.
674 If so, return the number of bytes at the start of STRING
675 which combine in this way. Otherwise, return 0. */
676
677 int
678 count_combining_before (const unsigned char *string, ptrdiff_t length,
679 ptrdiff_t pos, ptrdiff_t pos_byte)
680 {
681 int len, combining_bytes;
682 const unsigned char *p;
683
684 if (NILP (current_buffer->enable_multibyte_characters))
685 return 0;
686
687 /* At first, we can exclude the following cases:
688 (1) STRING[0] can't be a following byte of multibyte sequence.
689 (2) POS is the start of the current buffer.
690 (3) A character before POS is not a multibyte character. */
691 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
692 return 0;
693 if (pos_byte == BEG_BYTE) /* case (2) */
694 return 0;
695 len = 1;
696 p = BYTE_POS_ADDR (pos_byte - 1);
697 while (! CHAR_HEAD_P (*p)) p--, len++;
698 if (! LEADING_CODE_P (*p)) /* case (3) */
699 return 0;
700
701 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
702 if (combining_bytes <= 0)
703 /* The character preceding POS is, complete and no room for
704 combining bytes (combining_bytes == 0), or an independent 8-bit
705 character (combining_bytes < 0). */
706 return 0;
707
708 /* We have a combination situation. Count the bytes at STRING that
709 may combine. */
710 p = string + 1;
711 while (!CHAR_HEAD_P (*p) && p < string + length)
712 p++;
713
714 return (combining_bytes < p - string ? combining_bytes : p - string);
715 }
716
717 /* See if the bytes after POS/POS_BYTE combine with bytes
718 at the end of STRING to form a single character.
719 If so, return the number of bytes after POS/POS_BYTE
720 which combine in this way. Otherwise, return 0. */
721
722 int
723 count_combining_after (const unsigned char *string,
724 ptrdiff_t length, ptrdiff_t pos, ptrdiff_t pos_byte)
725 {
726 ptrdiff_t opos_byte = pos_byte;
727 ptrdiff_t i;
728 ptrdiff_t bytes;
729 unsigned char *bufp;
730
731 if (NILP (current_buffer->enable_multibyte_characters))
732 return 0;
733
734 /* At first, we can exclude the following cases:
735 (1) The last byte of STRING is an ASCII.
736 (2) POS is the last of the current buffer.
737 (3) A character at POS can't be a following byte of multibyte
738 character. */
739 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
740 return 0;
741 if (pos_byte == Z_BYTE) /* case (2) */
742 return 0;
743 bufp = BYTE_POS_ADDR (pos_byte);
744 if (CHAR_HEAD_P (*bufp)) /* case (3) */
745 return 0;
746
747 i = length - 1;
748 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
749 {
750 i--;
751 }
752 if (i < 0)
753 {
754 /* All characters in STRING are not character head. We must
755 check also preceding bytes at POS. We are sure that the gap
756 is at POS. */
757 unsigned char *p = BEG_ADDR;
758 i = pos_byte - 2;
759 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
760 i--;
761 if (i < 0 || !LEADING_CODE_P (p[i]))
762 return 0;
763
764 bytes = BYTES_BY_CHAR_HEAD (p[i]);
765 return (bytes <= pos_byte - 1 - i + length
766 ? 0
767 : bytes - (pos_byte - 1 - i + length));
768 }
769 if (!LEADING_CODE_P (string[i]))
770 return 0;
771
772 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
773 bufp++, pos_byte++;
774 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
775
776 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
777 }
778
779 #endif
780
781 \f
782 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
783 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
784 are the same as in insert_1. */
785
786 void
787 insert_1_both (const char *string,
788 ptrdiff_t nchars, ptrdiff_t nbytes,
789 bool inherit, bool prepare, bool before_markers)
790 {
791 if (nchars == 0)
792 return;
793
794 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
795 nchars = nbytes;
796
797 if (prepare)
798 /* Do this before moving and increasing the gap,
799 because the before-change hooks might move the gap
800 or make it smaller. */
801 prepare_to_modify_buffer (PT, PT, NULL);
802
803 if (PT != GPT)
804 move_gap_both (PT, PT_BYTE);
805 if (GAP_SIZE < nbytes)
806 make_gap (nbytes - GAP_SIZE);
807
808 #ifdef BYTE_COMBINING_DEBUG
809 if (count_combining_before (string, nbytes, PT, PT_BYTE)
810 || count_combining_after (string, nbytes, PT, PT_BYTE))
811 emacs_abort ();
812 #endif
813
814 /* Record deletion of the surrounding text that combines with
815 the insertion. This, together with recording the insertion,
816 will add up to the right stuff in the undo list. */
817 record_insert (PT, nchars);
818 MODIFF++;
819 CHARS_MODIFF = MODIFF;
820
821 memcpy (GPT_ADDR, string, nbytes);
822
823 GAP_SIZE -= nbytes;
824 GPT += nchars;
825 ZV += nchars;
826 Z += nchars;
827 GPT_BYTE += nbytes;
828 ZV_BYTE += nbytes;
829 Z_BYTE += nbytes;
830 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
831
832 eassert (GPT <= GPT_BYTE);
833
834 /* The insert may have been in the unchanged region, so check again. */
835 if (Z - GPT < END_UNCHANGED)
836 END_UNCHANGED = Z - GPT;
837
838 adjust_overlays_for_insert (PT, nchars);
839 adjust_markers_for_insert (PT, PT_BYTE,
840 PT + nchars, PT_BYTE + nbytes,
841 before_markers);
842
843 if (buffer_intervals (current_buffer))
844 offset_intervals (current_buffer, PT, nchars);
845
846 if (!inherit && buffer_intervals (current_buffer))
847 set_text_properties (make_number (PT), make_number (PT + nchars),
848 Qnil, Qnil, Qnil);
849
850 adjust_point (nchars, nbytes);
851
852 check_markers ();
853 }
854 \f
855 /* Insert the part of the text of STRING, a Lisp object assumed to be
856 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
857 starting at position POS / POS_BYTE. If the text of STRING has properties,
858 copy them into the buffer.
859
860 It does not work to use `insert' for this, because a GC could happen
861 before we copy the stuff into the buffer, and relocate the string
862 without insert noticing. */
863
864 void
865 insert_from_string (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
866 ptrdiff_t length, ptrdiff_t length_byte, bool inherit)
867 {
868 ptrdiff_t opoint = PT;
869
870 if (SCHARS (string) == 0)
871 return;
872
873 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
874 inherit, 0);
875 signal_after_change (opoint, 0, PT - opoint);
876 update_compositions (opoint, PT, CHECK_BORDER);
877 }
878
879 /* Like `insert_from_string' except that all markers pointing
880 at the place where the insertion happens are adjusted to point after it. */
881
882 void
883 insert_from_string_before_markers (Lisp_Object string,
884 ptrdiff_t pos, ptrdiff_t pos_byte,
885 ptrdiff_t length, ptrdiff_t length_byte,
886 bool inherit)
887 {
888 ptrdiff_t opoint = PT;
889
890 if (SCHARS (string) == 0)
891 return;
892
893 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
894 inherit, 1);
895 signal_after_change (opoint, 0, PT - opoint);
896 update_compositions (opoint, PT, CHECK_BORDER);
897 }
898
899 /* Subroutine of the insertion functions above. */
900
901 static void
902 insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
903 ptrdiff_t nchars, ptrdiff_t nbytes,
904 bool inherit, bool before_markers)
905 {
906 struct gcpro gcpro1;
907 ptrdiff_t outgoing_nbytes = nbytes;
908 INTERVAL intervals;
909
910 /* Make OUTGOING_NBYTES describe the text
911 as it will be inserted in this buffer. */
912
913 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
914 outgoing_nbytes = nchars;
915 else if (! STRING_MULTIBYTE (string))
916 outgoing_nbytes
917 = count_size_as_multibyte (SDATA (string) + pos_byte,
918 nbytes);
919
920 GCPRO1 (string);
921 /* Do this before moving and increasing the gap,
922 because the before-change hooks might move the gap
923 or make it smaller. */
924 prepare_to_modify_buffer (PT, PT, NULL);
925
926 if (PT != GPT)
927 move_gap_both (PT, PT_BYTE);
928 if (GAP_SIZE < outgoing_nbytes)
929 make_gap (outgoing_nbytes - GAP_SIZE);
930 UNGCPRO;
931
932 /* Copy the string text into the buffer, perhaps converting
933 between single-byte and multibyte. */
934 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
935 STRING_MULTIBYTE (string),
936 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
937
938 #ifdef BYTE_COMBINING_DEBUG
939 /* We have copied text into the gap, but we have not altered
940 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
941 to these functions and get the same results as we would
942 have got earlier on. Meanwhile, PT_ADDR does point to
943 the text that has been stored by copy_text. */
944 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
945 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
946 emacs_abort ();
947 #endif
948
949 record_insert (PT, nchars);
950 MODIFF++;
951 CHARS_MODIFF = MODIFF;
952
953 GAP_SIZE -= outgoing_nbytes;
954 GPT += nchars;
955 ZV += nchars;
956 Z += nchars;
957 GPT_BYTE += outgoing_nbytes;
958 ZV_BYTE += outgoing_nbytes;
959 Z_BYTE += outgoing_nbytes;
960 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
961
962 eassert (GPT <= GPT_BYTE);
963
964 /* The insert may have been in the unchanged region, so check again. */
965 if (Z - GPT < END_UNCHANGED)
966 END_UNCHANGED = Z - GPT;
967
968 adjust_overlays_for_insert (PT, nchars);
969 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
970 PT_BYTE + outgoing_nbytes,
971 before_markers);
972
973 offset_intervals (current_buffer, PT, nchars);
974
975 intervals = string_intervals (string);
976 /* Get the intervals for the part of the string we are inserting. */
977 if (nbytes < SBYTES (string))
978 intervals = copy_intervals (intervals, pos, nchars);
979
980 /* Insert those intervals. */
981 graft_intervals_into_buffer (intervals, PT, nchars,
982 current_buffer, inherit);
983
984 adjust_point (nchars, outgoing_nbytes);
985
986 check_markers ();
987 }
988 \f
989 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
990 starting at GPT_ADDR. */
991
992 void
993 insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes)
994 {
995 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
996 nchars = nbytes;
997
998 record_insert (GPT, nchars);
999 MODIFF++;
1000
1001 GAP_SIZE -= nbytes;
1002 GPT += nchars;
1003 ZV += nchars;
1004 Z += nchars;
1005 GPT_BYTE += nbytes;
1006 ZV_BYTE += nbytes;
1007 Z_BYTE += nbytes;
1008 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1009
1010 eassert (GPT <= GPT_BYTE);
1011
1012 adjust_overlays_for_insert (GPT - nchars, nchars);
1013 adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes,
1014 GPT, GPT_BYTE, 0);
1015
1016 if (buffer_intervals (current_buffer))
1017 {
1018 offset_intervals (current_buffer, GPT - nchars, nchars);
1019 graft_intervals_into_buffer (NULL, GPT - nchars, nchars,
1020 current_buffer, 0);
1021 }
1022
1023 if (GPT - nchars < PT)
1024 adjust_point (nchars, nbytes);
1025
1026 check_markers ();
1027 }
1028 \f
1029 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
1030 current buffer. If the text in BUF has properties, they are absorbed
1031 into the current buffer.
1032
1033 It does not work to use `insert' for this, because a malloc could happen
1034 and relocate BUF's text before the copy happens. */
1035
1036 void
1037 insert_from_buffer (struct buffer *buf,
1038 ptrdiff_t charpos, ptrdiff_t nchars, bool inherit)
1039 {
1040 ptrdiff_t opoint = PT;
1041
1042 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1043 signal_after_change (opoint, 0, PT - opoint);
1044 update_compositions (opoint, PT, CHECK_BORDER);
1045 }
1046
1047 static void
1048 insert_from_buffer_1 (struct buffer *buf,
1049 ptrdiff_t from, ptrdiff_t nchars, bool inherit)
1050 {
1051 ptrdiff_t chunk, chunk_expanded;
1052 ptrdiff_t from_byte = buf_charpos_to_bytepos (buf, from);
1053 ptrdiff_t to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1054 ptrdiff_t incoming_nbytes = to_byte - from_byte;
1055 ptrdiff_t outgoing_nbytes = incoming_nbytes;
1056 INTERVAL intervals;
1057
1058 /* Make OUTGOING_NBYTES describe the text
1059 as it will be inserted in this buffer. */
1060
1061 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1062 outgoing_nbytes = nchars;
1063 else if (NILP (BVAR (buf, enable_multibyte_characters)))
1064 {
1065 ptrdiff_t outgoing_before_gap = 0;
1066 ptrdiff_t outgoing_after_gap = 0;
1067
1068 if (from < BUF_GPT (buf))
1069 {
1070 chunk = BUF_GPT_BYTE (buf) - from_byte;
1071 if (chunk > incoming_nbytes)
1072 chunk = incoming_nbytes;
1073 outgoing_before_gap
1074 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1075 chunk);
1076 }
1077 else
1078 chunk = 0;
1079
1080 if (chunk < incoming_nbytes)
1081 outgoing_after_gap
1082 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1083 from_byte + chunk),
1084 incoming_nbytes - chunk);
1085
1086 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1087 }
1088
1089 /* Do this before moving and increasing the gap,
1090 because the before-change hooks might move the gap
1091 or make it smaller. */
1092 prepare_to_modify_buffer (PT, PT, NULL);
1093
1094 if (PT != GPT)
1095 move_gap_both (PT, PT_BYTE);
1096 if (GAP_SIZE < outgoing_nbytes)
1097 make_gap (outgoing_nbytes - GAP_SIZE);
1098
1099 if (from < BUF_GPT (buf))
1100 {
1101 chunk = BUF_GPT_BYTE (buf) - from_byte;
1102 if (chunk > incoming_nbytes)
1103 chunk = incoming_nbytes;
1104 /* Record number of output bytes, so we know where
1105 to put the output from the second copy_text. */
1106 chunk_expanded
1107 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1108 GPT_ADDR, chunk,
1109 ! NILP (BVAR (buf, enable_multibyte_characters)),
1110 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1111 }
1112 else
1113 chunk_expanded = chunk = 0;
1114
1115 if (chunk < incoming_nbytes)
1116 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1117 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1118 ! NILP (BVAR (buf, enable_multibyte_characters)),
1119 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1120
1121 #ifdef BYTE_COMBINING_DEBUG
1122 /* We have copied text into the gap, but we have not altered
1123 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1124 to these functions and get the same results as we would
1125 have got earlier on. Meanwhile, GPT_ADDR does point to
1126 the text that has been stored by copy_text. */
1127 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1128 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1129 emacs_abort ();
1130 #endif
1131
1132 record_insert (PT, nchars);
1133 MODIFF++;
1134 CHARS_MODIFF = MODIFF;
1135
1136 GAP_SIZE -= outgoing_nbytes;
1137 GPT += nchars;
1138 ZV += nchars;
1139 Z += nchars;
1140 GPT_BYTE += outgoing_nbytes;
1141 ZV_BYTE += outgoing_nbytes;
1142 Z_BYTE += outgoing_nbytes;
1143 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1144
1145 eassert (GPT <= GPT_BYTE);
1146
1147 /* The insert may have been in the unchanged region, so check again. */
1148 if (Z - GPT < END_UNCHANGED)
1149 END_UNCHANGED = Z - GPT;
1150
1151 adjust_overlays_for_insert (PT, nchars);
1152 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1153 PT_BYTE + outgoing_nbytes,
1154 0);
1155
1156 if (buffer_intervals (current_buffer))
1157 offset_intervals (current_buffer, PT, nchars);
1158
1159 /* Get the intervals for the part of the string we are inserting. */
1160 intervals = buffer_intervals (buf);
1161 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1162 {
1163 if (buf == current_buffer && PT <= from)
1164 from += nchars;
1165 intervals = copy_intervals (intervals, from, nchars);
1166 }
1167
1168 /* Insert those intervals. */
1169 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1170
1171 adjust_point (nchars, outgoing_nbytes);
1172 }
1173 \f
1174 /* Record undo information and adjust markers and position keepers for
1175 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1176 chars (LEN_BYTE bytes) which resides in the gap just after
1177 GPT_ADDR.
1178
1179 PREV_TEXT nil means the new text was just inserted. */
1180
1181 static void
1182 adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1183 Lisp_Object prev_text, ptrdiff_t len, ptrdiff_t len_byte)
1184 {
1185 ptrdiff_t nchars_del = 0, nbytes_del = 0;
1186
1187 #ifdef BYTE_COMBINING_DEBUG
1188 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1189 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1190 emacs_abort ();
1191 #endif
1192
1193 if (STRINGP (prev_text))
1194 {
1195 nchars_del = SCHARS (prev_text);
1196 nbytes_del = SBYTES (prev_text);
1197 }
1198
1199 /* Update various buffer positions for the new text. */
1200 GAP_SIZE -= len_byte;
1201 ZV += len; Z+= len;
1202 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1203 GPT += len; GPT_BYTE += len_byte;
1204 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1205
1206 if (nchars_del > 0)
1207 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1208 len, len_byte);
1209 else
1210 adjust_markers_for_insert (from, from_byte,
1211 from + len, from_byte + len_byte, 0);
1212
1213 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1214 {
1215 if (nchars_del > 0)
1216 record_delete (from, prev_text);
1217 record_insert (from, len);
1218 }
1219
1220 if (len > nchars_del)
1221 adjust_overlays_for_insert (from, len - nchars_del);
1222 else if (len < nchars_del)
1223 adjust_overlays_for_delete (from, nchars_del - len);
1224
1225 if (buffer_intervals (current_buffer))
1226 offset_intervals (current_buffer, from, len - nchars_del);
1227
1228 if (from < PT)
1229 adjust_point (len - nchars_del, len_byte - nbytes_del);
1230
1231 /* As byte combining will decrease Z, we must check this again. */
1232 if (Z - GPT < END_UNCHANGED)
1233 END_UNCHANGED = Z - GPT;
1234
1235 check_markers ();
1236
1237 if (len == 0)
1238 evaporate_overlays (from);
1239 MODIFF++;
1240 CHARS_MODIFF = MODIFF;
1241 }
1242
1243 /* Record undo information, adjust markers and position keepers for an
1244 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1245 text already exists in the current buffer but character length (TO
1246 - FROM) may be incorrect, the correct length is NEWLEN. */
1247
1248 void
1249 adjust_after_insert (ptrdiff_t from, ptrdiff_t from_byte,
1250 ptrdiff_t to, ptrdiff_t to_byte, ptrdiff_t newlen)
1251 {
1252 ptrdiff_t len = to - from, len_byte = to_byte - from_byte;
1253
1254 if (GPT != to)
1255 move_gap_both (to, to_byte);
1256 GAP_SIZE += len_byte;
1257 GPT -= len; GPT_BYTE -= len_byte;
1258 ZV -= len; ZV_BYTE -= len_byte;
1259 Z -= len; Z_BYTE -= len_byte;
1260 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1261 }
1262 \f
1263 /* Replace the text from character positions FROM to TO with NEW,
1264 If PREPARE, call prepare_to_modify_buffer.
1265 If INHERIT, the newly inserted text should inherit text properties
1266 from the surrounding non-deleted text. */
1267
1268 /* Note that this does not yet handle markers quite right.
1269 Also it needs to record a single undo-entry that does a replacement
1270 rather than a separate delete and insert.
1271 That way, undo will also handle markers properly.
1272
1273 But if MARKERS is 0, don't relocate markers. */
1274
1275 void
1276 replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1277 bool prepare, bool inherit, bool markers)
1278 {
1279 ptrdiff_t inschars = SCHARS (new);
1280 ptrdiff_t insbytes = SBYTES (new);
1281 ptrdiff_t from_byte, to_byte;
1282 ptrdiff_t nbytes_del, nchars_del;
1283 struct gcpro gcpro1;
1284 INTERVAL intervals;
1285 ptrdiff_t outgoing_insbytes = insbytes;
1286 Lisp_Object deletion;
1287
1288 check_markers ();
1289
1290 GCPRO1 (new);
1291 deletion = Qnil;
1292
1293 if (prepare)
1294 {
1295 ptrdiff_t range_length = to - from;
1296 prepare_to_modify_buffer (from, to, &from);
1297 to = from + range_length;
1298 }
1299
1300 UNGCPRO;
1301
1302 /* Make args be valid. */
1303 if (from < BEGV)
1304 from = BEGV;
1305 if (to > ZV)
1306 to = ZV;
1307
1308 from_byte = CHAR_TO_BYTE (from);
1309 to_byte = CHAR_TO_BYTE (to);
1310
1311 nchars_del = to - from;
1312 nbytes_del = to_byte - from_byte;
1313
1314 if (nbytes_del <= 0 && insbytes == 0)
1315 return;
1316
1317 /* Make OUTGOING_INSBYTES describe the text
1318 as it will be inserted in this buffer. */
1319
1320 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1321 outgoing_insbytes = inschars;
1322 else if (! STRING_MULTIBYTE (new))
1323 outgoing_insbytes
1324 = count_size_as_multibyte (SDATA (new), insbytes);
1325
1326 GCPRO1 (new);
1327
1328 /* Make sure the gap is somewhere in or next to what we are deleting. */
1329 if (from > GPT)
1330 gap_right (from, from_byte);
1331 if (to < GPT)
1332 gap_left (to, to_byte, 0);
1333
1334 /* Even if we don't record for undo, we must keep the original text
1335 because we may have to recover it because of inappropriate byte
1336 combining. */
1337 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1338 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1339
1340 GAP_SIZE += nbytes_del;
1341 ZV -= nchars_del;
1342 Z -= nchars_del;
1343 ZV_BYTE -= nbytes_del;
1344 Z_BYTE -= nbytes_del;
1345 GPT = from;
1346 GPT_BYTE = from_byte;
1347 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1348
1349 eassert (GPT <= GPT_BYTE);
1350
1351 if (GPT - BEG < BEG_UNCHANGED)
1352 BEG_UNCHANGED = GPT - BEG;
1353 if (Z - GPT < END_UNCHANGED)
1354 END_UNCHANGED = Z - GPT;
1355
1356 if (GAP_SIZE < outgoing_insbytes)
1357 make_gap (outgoing_insbytes - GAP_SIZE);
1358
1359 /* Copy the string text into the buffer, perhaps converting
1360 between single-byte and multibyte. */
1361 copy_text (SDATA (new), GPT_ADDR, insbytes,
1362 STRING_MULTIBYTE (new),
1363 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1364
1365 #ifdef BYTE_COMBINING_DEBUG
1366 /* We have copied text into the gap, but we have not marked
1367 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1368 here, for both the previous text and the following text.
1369 Meanwhile, GPT_ADDR does point to
1370 the text that has been stored by copy_text. */
1371 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1372 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1373 emacs_abort ();
1374 #endif
1375
1376 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1377 {
1378 /* Record the insertion first, so that when we undo,
1379 the deletion will be undone first. Thus, undo
1380 will insert before deleting, and thus will keep
1381 the markers before and after this text separate. */
1382 record_insert (from + SCHARS (deletion), inschars);
1383 record_delete (from, deletion);
1384 }
1385
1386 GAP_SIZE -= outgoing_insbytes;
1387 GPT += inschars;
1388 ZV += inschars;
1389 Z += inschars;
1390 GPT_BYTE += outgoing_insbytes;
1391 ZV_BYTE += outgoing_insbytes;
1392 Z_BYTE += outgoing_insbytes;
1393 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1394
1395 eassert (GPT <= GPT_BYTE);
1396
1397 /* Adjust the overlay center as needed. This must be done after
1398 adjusting the markers that bound the overlays. */
1399 adjust_overlays_for_delete (from, nchars_del);
1400 adjust_overlays_for_insert (from, inschars);
1401
1402 /* Adjust markers for the deletion and the insertion. */
1403 if (markers)
1404 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1405 inschars, outgoing_insbytes);
1406
1407 offset_intervals (current_buffer, from, inschars - nchars_del);
1408
1409 /* Get the intervals for the part of the string we are inserting--
1410 not including the combined-before bytes. */
1411 intervals = string_intervals (new);
1412 /* Insert those intervals. */
1413 graft_intervals_into_buffer (intervals, from, inschars,
1414 current_buffer, inherit);
1415
1416 /* Relocate point as if it were a marker. */
1417 if (from < PT)
1418 adjust_point ((from + inschars - (PT < to ? PT : to)),
1419 (from_byte + outgoing_insbytes
1420 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1421
1422 if (outgoing_insbytes == 0)
1423 evaporate_overlays (from);
1424
1425 check_markers ();
1426
1427 MODIFF++;
1428 CHARS_MODIFF = MODIFF;
1429 UNGCPRO;
1430
1431 signal_after_change (from, nchars_del, GPT - from);
1432 update_compositions (from, GPT, CHECK_BORDER);
1433 }
1434 \f
1435 /* Replace the text from character positions FROM to TO with
1436 the text in INS of length INSCHARS.
1437 Keep the text properties that applied to the old characters
1438 (extending them to all the new chars if there are more new chars).
1439
1440 Note that this does not yet handle markers quite right.
1441
1442 If MARKERS, relocate markers.
1443
1444 Unlike most functions at this level, never call
1445 prepare_to_modify_buffer and never call signal_after_change. */
1446
1447 void
1448 replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1449 ptrdiff_t to, ptrdiff_t to_byte,
1450 const char *ins, ptrdiff_t inschars, ptrdiff_t insbytes,
1451 bool markers)
1452 {
1453 ptrdiff_t nbytes_del, nchars_del;
1454
1455 check_markers ();
1456
1457 nchars_del = to - from;
1458 nbytes_del = to_byte - from_byte;
1459
1460 if (nbytes_del <= 0 && insbytes == 0)
1461 return;
1462
1463 /* Make sure the gap is somewhere in or next to what we are deleting. */
1464 if (from > GPT)
1465 gap_right (from, from_byte);
1466 if (to < GPT)
1467 gap_left (to, to_byte, 0);
1468
1469 GAP_SIZE += nbytes_del;
1470 ZV -= nchars_del;
1471 Z -= nchars_del;
1472 ZV_BYTE -= nbytes_del;
1473 Z_BYTE -= nbytes_del;
1474 GPT = from;
1475 GPT_BYTE = from_byte;
1476 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1477
1478 eassert (GPT <= GPT_BYTE);
1479
1480 if (GPT - BEG < BEG_UNCHANGED)
1481 BEG_UNCHANGED = GPT - BEG;
1482 if (Z - GPT < END_UNCHANGED)
1483 END_UNCHANGED = Z - GPT;
1484
1485 if (GAP_SIZE < insbytes)
1486 make_gap (insbytes - GAP_SIZE);
1487
1488 /* Copy the replacement text into the buffer. */
1489 memcpy (GPT_ADDR, ins, insbytes);
1490
1491 #ifdef BYTE_COMBINING_DEBUG
1492 /* We have copied text into the gap, but we have not marked
1493 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1494 here, for both the previous text and the following text.
1495 Meanwhile, GPT_ADDR does point to
1496 the text that has been stored by copy_text. */
1497 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1498 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1499 emacs_abort ();
1500 #endif
1501
1502 GAP_SIZE -= insbytes;
1503 GPT += inschars;
1504 ZV += inschars;
1505 Z += inschars;
1506 GPT_BYTE += insbytes;
1507 ZV_BYTE += insbytes;
1508 Z_BYTE += insbytes;
1509 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1510
1511 eassert (GPT <= GPT_BYTE);
1512
1513 /* Adjust the overlay center as needed. This must be done after
1514 adjusting the markers that bound the overlays. */
1515 if (nchars_del != inschars)
1516 {
1517 adjust_overlays_for_insert (from, inschars);
1518 adjust_overlays_for_delete (from + inschars, nchars_del);
1519 }
1520
1521 /* Adjust markers for the deletion and the insertion. */
1522 if (markers
1523 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1524 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1525 inschars, insbytes);
1526
1527 offset_intervals (current_buffer, from, inschars - nchars_del);
1528
1529 /* Relocate point as if it were a marker. */
1530 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1531 {
1532 if (PT < to)
1533 /* PT was within the deleted text. Move it to FROM. */
1534 adjust_point (from - PT, from_byte - PT_BYTE);
1535 else
1536 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1537 }
1538
1539 if (insbytes == 0)
1540 evaporate_overlays (from);
1541
1542 check_markers ();
1543
1544 MODIFF++;
1545 CHARS_MODIFF = MODIFF;
1546 }
1547 \f
1548 /* Delete characters in current buffer
1549 from FROM up to (but not including) TO.
1550 If TO comes before FROM, we delete nothing. */
1551
1552 void
1553 del_range (ptrdiff_t from, ptrdiff_t to)
1554 {
1555 del_range_1 (from, to, 1, 0);
1556 }
1557
1558 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1559 RET_STRING says to return the deleted text. */
1560
1561 Lisp_Object
1562 del_range_1 (ptrdiff_t from, ptrdiff_t to, bool prepare, bool ret_string)
1563 {
1564 ptrdiff_t from_byte, to_byte;
1565 Lisp_Object deletion;
1566 struct gcpro gcpro1;
1567
1568 /* Make args be valid */
1569 if (from < BEGV)
1570 from = BEGV;
1571 if (to > ZV)
1572 to = ZV;
1573
1574 if (to <= from)
1575 return Qnil;
1576
1577 if (prepare)
1578 {
1579 ptrdiff_t range_length = to - from;
1580 prepare_to_modify_buffer (from, to, &from);
1581 to = min (ZV, from + range_length);
1582 }
1583
1584 from_byte = CHAR_TO_BYTE (from);
1585 to_byte = CHAR_TO_BYTE (to);
1586
1587 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1588 GCPRO1 (deletion);
1589 signal_after_change (from, to - from, 0);
1590 update_compositions (from, from, CHECK_HEAD);
1591 UNGCPRO;
1592 return deletion;
1593 }
1594
1595 /* Like del_range_1 but args are byte positions, not char positions. */
1596
1597 void
1598 del_range_byte (ptrdiff_t from_byte, ptrdiff_t to_byte, bool prepare)
1599 {
1600 ptrdiff_t from, to;
1601
1602 /* Make args be valid */
1603 if (from_byte < BEGV_BYTE)
1604 from_byte = BEGV_BYTE;
1605 if (to_byte > ZV_BYTE)
1606 to_byte = ZV_BYTE;
1607
1608 if (to_byte <= from_byte)
1609 return;
1610
1611 from = BYTE_TO_CHAR (from_byte);
1612 to = BYTE_TO_CHAR (to_byte);
1613
1614 if (prepare)
1615 {
1616 ptrdiff_t old_from = from, old_to = Z - to;
1617 ptrdiff_t range_length = to - from;
1618 prepare_to_modify_buffer (from, to, &from);
1619 to = from + range_length;
1620
1621 if (old_from != from)
1622 from_byte = CHAR_TO_BYTE (from);
1623 if (to > ZV)
1624 {
1625 to = ZV;
1626 to_byte = ZV_BYTE;
1627 }
1628 else if (old_to == Z - to)
1629 to_byte = CHAR_TO_BYTE (to);
1630 }
1631
1632 del_range_2 (from, from_byte, to, to_byte, 0);
1633 signal_after_change (from, to - from, 0);
1634 update_compositions (from, from, CHECK_HEAD);
1635 }
1636
1637 /* Like del_range_1, but positions are specified both as charpos
1638 and bytepos. */
1639
1640 void
1641 del_range_both (ptrdiff_t from, ptrdiff_t from_byte,
1642 ptrdiff_t to, ptrdiff_t to_byte, bool prepare)
1643 {
1644 /* Make args be valid */
1645 if (from_byte < BEGV_BYTE)
1646 from_byte = BEGV_BYTE;
1647 if (to_byte > ZV_BYTE)
1648 to_byte = ZV_BYTE;
1649
1650 if (to_byte <= from_byte)
1651 return;
1652
1653 if (from < BEGV)
1654 from = BEGV;
1655 if (to > ZV)
1656 to = ZV;
1657
1658 if (prepare)
1659 {
1660 ptrdiff_t old_from = from, old_to = Z - to;
1661 ptrdiff_t range_length = to - from;
1662 prepare_to_modify_buffer (from, to, &from);
1663 to = from + range_length;
1664
1665 if (old_from != from)
1666 from_byte = CHAR_TO_BYTE (from);
1667 if (to > ZV)
1668 {
1669 to = ZV;
1670 to_byte = ZV_BYTE;
1671 }
1672 else if (old_to == Z - to)
1673 to_byte = CHAR_TO_BYTE (to);
1674 }
1675
1676 del_range_2 (from, from_byte, to, to_byte, 0);
1677 signal_after_change (from, to - from, 0);
1678 update_compositions (from, from, CHECK_HEAD);
1679 }
1680
1681 /* Delete a range of text, specified both as character positions
1682 and byte positions. FROM and TO are character positions,
1683 while FROM_BYTE and TO_BYTE are byte positions.
1684 If RET_STRING, the deleted area is returned as a string. */
1685
1686 Lisp_Object
1687 del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1688 ptrdiff_t to, ptrdiff_t to_byte, bool ret_string)
1689 {
1690 ptrdiff_t nbytes_del, nchars_del;
1691 Lisp_Object deletion;
1692
1693 check_markers ();
1694
1695 nchars_del = to - from;
1696 nbytes_del = to_byte - from_byte;
1697
1698 /* Make sure the gap is somewhere in or next to what we are deleting. */
1699 if (from > GPT)
1700 gap_right (from, from_byte);
1701 if (to < GPT)
1702 gap_left (to, to_byte, 0);
1703
1704 #ifdef BYTE_COMBINING_DEBUG
1705 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1706 Z_BYTE - to_byte, from, from_byte))
1707 emacs_abort ();
1708 #endif
1709
1710 if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
1711 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1712 else
1713 deletion = Qnil;
1714
1715 /* Relocate all markers pointing into the new, larger gap
1716 to point at the end of the text before the gap.
1717 Do this before recording the deletion,
1718 so that undo handles this after reinserting the text. */
1719 adjust_markers_for_delete (from, from_byte, to, to_byte);
1720
1721 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1722 record_delete (from, deletion);
1723 MODIFF++;
1724 CHARS_MODIFF = MODIFF;
1725
1726 /* Relocate point as if it were a marker. */
1727 if (from < PT)
1728 adjust_point (from - (PT < to ? PT : to),
1729 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1730
1731 offset_intervals (current_buffer, from, - nchars_del);
1732
1733 /* Adjust the overlay center as needed. This must be done after
1734 adjusting the markers that bound the overlays. */
1735 adjust_overlays_for_delete (from, nchars_del);
1736
1737 GAP_SIZE += nbytes_del;
1738 ZV_BYTE -= nbytes_del;
1739 Z_BYTE -= nbytes_del;
1740 ZV -= nchars_del;
1741 Z -= nchars_del;
1742 GPT = from;
1743 GPT_BYTE = from_byte;
1744 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1745 /* Put an anchor, unless called from decode_coding_object which
1746 needs to access the previous gap contents. */
1747 *(GPT_ADDR) = 0;
1748
1749 eassert (GPT <= GPT_BYTE);
1750
1751 if (GPT - BEG < BEG_UNCHANGED)
1752 BEG_UNCHANGED = GPT - BEG;
1753 if (Z - GPT < END_UNCHANGED)
1754 END_UNCHANGED = Z - GPT;
1755
1756 check_markers ();
1757
1758 evaporate_overlays (from);
1759
1760 return deletion;
1761 }
1762 \f
1763 /* Call this if you're about to change the region of BUFFER from
1764 character positions START to END. This checks the read-only
1765 properties of the region, calls the necessary modification hooks,
1766 and warns the next redisplay that it should pay attention to that
1767 area.
1768
1769 If PRESERVE_CHARS_MODIFF, do not update CHARS_MODIFF.
1770 Otherwise set CHARS_MODIFF to the new value of MODIFF. */
1771
1772 void
1773 modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end,
1774 bool preserve_chars_modiff)
1775 {
1776 struct buffer *old_buffer = current_buffer;
1777
1778 set_buffer_internal (buffer);
1779
1780 prepare_to_modify_buffer (start, end, NULL);
1781
1782 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
1783
1784 if (MODIFF <= SAVE_MODIFF)
1785 record_first_change ();
1786 MODIFF++;
1787 if (! preserve_chars_modiff)
1788 CHARS_MODIFF = MODIFF;
1789
1790 bset_point_before_scroll (buffer, Qnil);
1791
1792 set_buffer_internal (old_buffer);
1793 }
1794 \f
1795 /* Check that it is okay to modify the buffer between START and END,
1796 which are char positions.
1797
1798 Run the before-change-function, if any. If intervals are in use,
1799 verify that the text to be modified is not read-only, and call
1800 any modification properties the text may have.
1801
1802 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1803 by holding its value temporarily in a marker. */
1804
1805 void
1806 prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
1807 ptrdiff_t *preserve_ptr)
1808 {
1809 struct buffer *base_buffer;
1810
1811 if (!NILP (BVAR (current_buffer, read_only)))
1812 Fbarf_if_buffer_read_only ();
1813
1814 /* Let redisplay consider other windows than selected_window
1815 if modifying another buffer. */
1816 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
1817 ++windows_or_buffers_changed;
1818
1819 if (buffer_intervals (current_buffer))
1820 {
1821 if (preserve_ptr)
1822 {
1823 Lisp_Object preserve_marker;
1824 struct gcpro gcpro1;
1825 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1826 GCPRO1 (preserve_marker);
1827 verify_interval_modification (current_buffer, start, end);
1828 *preserve_ptr = marker_position (preserve_marker);
1829 unchain_marker (XMARKER (preserve_marker));
1830 UNGCPRO;
1831 }
1832 else
1833 verify_interval_modification (current_buffer, start, end);
1834 }
1835
1836 /* For indirect buffers, use the base buffer to check clashes. */
1837 if (current_buffer->base_buffer != 0)
1838 base_buffer = current_buffer->base_buffer;
1839 else
1840 base_buffer = current_buffer;
1841
1842 #ifdef CLASH_DETECTION
1843 if (!NILP (BVAR (base_buffer, file_truename))
1844 /* Make binding buffer-file-name to nil effective. */
1845 && !NILP (BVAR (base_buffer, filename))
1846 && SAVE_MODIFF >= MODIFF)
1847 lock_file (BVAR (base_buffer, file_truename));
1848 #else
1849 /* At least warn if this file has changed on disk since it was visited. */
1850 if (!NILP (BVAR (base_buffer, filename))
1851 && SAVE_MODIFF >= MODIFF
1852 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1853 && !NILP (Ffile_exists_p (BVAR (base_buffer, filename))))
1854 call1 (intern ("ask-user-about-supersession-threat"),
1855 BVAR (base_buffer,filename));
1856 #endif /* not CLASH_DETECTION */
1857
1858 /* If `select-active-regions' is non-nil, save the region text. */
1859 if (!NILP (BVAR (current_buffer, mark_active))
1860 && !inhibit_modification_hooks
1861 && XMARKER (BVAR (current_buffer, mark))->buffer
1862 && NILP (Vsaved_region_selection)
1863 && (EQ (Vselect_active_regions, Qonly)
1864 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
1865 : (!NILP (Vselect_active_regions)
1866 && !NILP (Vtransient_mark_mode))))
1867 {
1868 ptrdiff_t b = XMARKER (BVAR (current_buffer, mark))->charpos;
1869 ptrdiff_t e = PT;
1870 if (b < e)
1871 Vsaved_region_selection = make_buffer_string (b, e, 0);
1872 else if (b > e)
1873 Vsaved_region_selection = make_buffer_string (e, b, 0);
1874 }
1875
1876 signal_before_change (start, end, preserve_ptr);
1877
1878 if (current_buffer->newline_cache)
1879 invalidate_region_cache (current_buffer,
1880 current_buffer->newline_cache,
1881 start - BEG, Z - end);
1882 if (current_buffer->width_run_cache)
1883 invalidate_region_cache (current_buffer,
1884 current_buffer->width_run_cache,
1885 start - BEG, Z - end);
1886
1887 Vdeactivate_mark = Qt;
1888 }
1889 \f
1890 /* These macros work with an argument named `preserve_ptr'
1891 and a local variable named `preserve_marker'. */
1892
1893 #define PRESERVE_VALUE \
1894 if (preserve_ptr && NILP (preserve_marker)) \
1895 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1896
1897 #define RESTORE_VALUE \
1898 if (! NILP (preserve_marker)) \
1899 { \
1900 *preserve_ptr = marker_position (preserve_marker); \
1901 unchain_marker (XMARKER (preserve_marker)); \
1902 }
1903
1904 #define PRESERVE_START_END \
1905 if (NILP (start_marker)) \
1906 start_marker = Fcopy_marker (start, Qnil); \
1907 if (NILP (end_marker)) \
1908 end_marker = Fcopy_marker (end, Qnil);
1909
1910 #define FETCH_START \
1911 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1912
1913 #define FETCH_END \
1914 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1915
1916 /* Set a variable to nil if an error occurred.
1917 Don't change the variable if there was no error.
1918 VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG).
1919 VARIABLE is the variable to maybe set to nil.
1920 NO-ERROR-FLAG is nil if there was an error,
1921 anything else meaning no error (so this function does nothing). */
1922 static Lisp_Object
1923 reset_var_on_error (Lisp_Object val)
1924 {
1925 if (NILP (XCDR (val)))
1926 Fset (XCAR (val), Qnil);
1927 return Qnil;
1928 }
1929
1930 /* Signal a change to the buffer immediately before it happens.
1931 START_INT and END_INT are the bounds of the text to be changed.
1932
1933 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1934 by holding its value temporarily in a marker. */
1935
1936 static void
1937 signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int,
1938 ptrdiff_t *preserve_ptr)
1939 {
1940 Lisp_Object start, end;
1941 Lisp_Object start_marker, end_marker;
1942 Lisp_Object preserve_marker;
1943 struct gcpro gcpro1, gcpro2, gcpro3;
1944 ptrdiff_t count = SPECPDL_INDEX ();
1945
1946 if (inhibit_modification_hooks)
1947 return;
1948
1949 start = make_number (start_int);
1950 end = make_number (end_int);
1951 preserve_marker = Qnil;
1952 start_marker = Qnil;
1953 end_marker = Qnil;
1954 GCPRO3 (preserve_marker, start_marker, end_marker);
1955
1956 specbind (Qinhibit_modification_hooks, Qt);
1957
1958 /* If buffer is unmodified, run a special hook for that case. The
1959 check for Vfirst_change_hook is just a minor optimization. */
1960 if (SAVE_MODIFF >= MODIFF
1961 && !NILP (Vfirst_change_hook))
1962 {
1963 PRESERVE_VALUE;
1964 PRESERVE_START_END;
1965 Frun_hooks (1, &Qfirst_change_hook);
1966 }
1967
1968 /* Now run the before-change-functions if any. */
1969 if (!NILP (Vbefore_change_functions))
1970 {
1971 Lisp_Object args[3];
1972 Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil);
1973
1974 PRESERVE_VALUE;
1975 PRESERVE_START_END;
1976
1977 /* Mark before-change-functions to be reset to nil in case of error. */
1978 record_unwind_protect (reset_var_on_error, rvoe_arg);
1979
1980 /* Actually run the hook functions. */
1981 args[0] = Qbefore_change_functions;
1982 args[1] = FETCH_START;
1983 args[2] = FETCH_END;
1984 Frun_hook_with_args (3, args);
1985
1986 /* There was no error: unarm the reset_on_error. */
1987 XSETCDR (rvoe_arg, Qt);
1988 }
1989
1990 if (buffer_has_overlays ())
1991 {
1992 PRESERVE_VALUE;
1993 report_overlay_modification (FETCH_START, FETCH_END, 0,
1994 FETCH_START, FETCH_END, Qnil);
1995 }
1996
1997 if (! NILP (start_marker))
1998 free_marker (start_marker);
1999 if (! NILP (end_marker))
2000 free_marker (end_marker);
2001 RESTORE_VALUE;
2002 UNGCPRO;
2003
2004 unbind_to (count, Qnil);
2005 }
2006
2007 /* Signal a change immediately after it happens.
2008 CHARPOS is the character position of the start of the changed text.
2009 LENDEL is the number of characters of the text before the change.
2010 (Not the whole buffer; just the part that was changed.)
2011 LENINS is the number of characters in that part of the text
2012 after the change. */
2013
2014 void
2015 signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
2016 {
2017 ptrdiff_t count = SPECPDL_INDEX ();
2018 if (inhibit_modification_hooks)
2019 return;
2020
2021 /* If we are deferring calls to the after-change functions
2022 and there are no before-change functions,
2023 just record the args that we were going to use. */
2024 if (! NILP (Vcombine_after_change_calls)
2025 && NILP (Vbefore_change_functions)
2026 && !buffer_has_overlays ())
2027 {
2028 Lisp_Object elt;
2029
2030 if (!NILP (combine_after_change_list)
2031 && current_buffer != XBUFFER (combine_after_change_buffer))
2032 Fcombine_after_change_execute ();
2033
2034 elt = Fcons (make_number (charpos - BEG),
2035 Fcons (make_number (Z - (charpos - lendel + lenins)),
2036 Fcons (make_number (lenins - lendel), Qnil)));
2037 combine_after_change_list
2038 = Fcons (elt, combine_after_change_list);
2039 combine_after_change_buffer = Fcurrent_buffer ();
2040
2041 return;
2042 }
2043
2044 if (!NILP (combine_after_change_list))
2045 Fcombine_after_change_execute ();
2046
2047 specbind (Qinhibit_modification_hooks, Qt);
2048
2049 if (!NILP (Vafter_change_functions))
2050 {
2051 Lisp_Object args[4];
2052 Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil);
2053
2054 /* Mark after-change-functions to be reset to nil in case of error. */
2055 record_unwind_protect (reset_var_on_error, rvoe_arg);
2056
2057 /* Actually run the hook functions. */
2058 args[0] = Qafter_change_functions;
2059 XSETFASTINT (args[1], charpos);
2060 XSETFASTINT (args[2], charpos + lenins);
2061 XSETFASTINT (args[3], lendel);
2062 Frun_hook_with_args (4, args);
2063
2064 /* There was no error: unarm the reset_on_error. */
2065 XSETCDR (rvoe_arg, Qt);
2066 }
2067
2068 if (buffer_has_overlays ())
2069 report_overlay_modification (make_number (charpos),
2070 make_number (charpos + lenins),
2071 1,
2072 make_number (charpos),
2073 make_number (charpos + lenins),
2074 make_number (lendel));
2075
2076 /* After an insertion, call the text properties
2077 insert-behind-hooks or insert-in-front-hooks. */
2078 if (lendel == 0)
2079 report_interval_modification (make_number (charpos),
2080 make_number (charpos + lenins));
2081
2082 unbind_to (count, Qnil);
2083 }
2084
2085 static Lisp_Object
2086 Fcombine_after_change_execute_1 (Lisp_Object val)
2087 {
2088 Vcombine_after_change_calls = val;
2089 return val;
2090 }
2091
2092 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2093 Scombine_after_change_execute, 0, 0, 0,
2094 doc: /* This function is for use internally in `combine-after-change-calls'. */)
2095 (void)
2096 {
2097 ptrdiff_t count = SPECPDL_INDEX ();
2098 ptrdiff_t beg, end, change;
2099 ptrdiff_t begpos, endpos;
2100 Lisp_Object tail;
2101
2102 if (NILP (combine_after_change_list))
2103 return Qnil;
2104
2105 /* It is rare for combine_after_change_buffer to be invalid, but
2106 possible. It can happen when combine-after-change-calls is
2107 non-nil, and insertion calls a file handler (e.g. through
2108 lock_file) which scribbles into a temp file -- cyd */
2109 if (!BUFFERP (combine_after_change_buffer)
2110 || !BUFFER_LIVE_P (XBUFFER (combine_after_change_buffer)))
2111 {
2112 combine_after_change_list = Qnil;
2113 return Qnil;
2114 }
2115
2116 record_unwind_current_buffer ();
2117
2118 Fset_buffer (combine_after_change_buffer);
2119
2120 /* # chars unchanged at beginning of buffer. */
2121 beg = Z - BEG;
2122 /* # chars unchanged at end of buffer. */
2123 end = beg;
2124 /* Total amount of insertion (negative for deletion). */
2125 change = 0;
2126
2127 /* Scan the various individual changes,
2128 accumulating the range info in BEG, END and CHANGE. */
2129 for (tail = combine_after_change_list; CONSP (tail);
2130 tail = XCDR (tail))
2131 {
2132 Lisp_Object elt;
2133 ptrdiff_t thisbeg, thisend, thischange;
2134
2135 /* Extract the info from the next element. */
2136 elt = XCAR (tail);
2137 if (! CONSP (elt))
2138 continue;
2139 thisbeg = XINT (XCAR (elt));
2140
2141 elt = XCDR (elt);
2142 if (! CONSP (elt))
2143 continue;
2144 thisend = XINT (XCAR (elt));
2145
2146 elt = XCDR (elt);
2147 if (! CONSP (elt))
2148 continue;
2149 thischange = XINT (XCAR (elt));
2150
2151 /* Merge this range into the accumulated range. */
2152 change += thischange;
2153 if (thisbeg < beg)
2154 beg = thisbeg;
2155 if (thisend < end)
2156 end = thisend;
2157 }
2158
2159 /* Get the current start and end positions of the range
2160 that was changed. */
2161 begpos = BEG + beg;
2162 endpos = Z - end;
2163
2164 /* We are about to handle these, so discard them. */
2165 combine_after_change_list = Qnil;
2166
2167 /* Now run the after-change functions for real.
2168 Turn off the flag that defers them. */
2169 record_unwind_protect (Fcombine_after_change_execute_1,
2170 Vcombine_after_change_calls);
2171 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2172 update_compositions (begpos, endpos, CHECK_ALL);
2173
2174 return unbind_to (count, Qnil);
2175 }
2176 \f
2177 void
2178 syms_of_insdel (void)
2179 {
2180 staticpro (&combine_after_change_list);
2181 staticpro (&combine_after_change_buffer);
2182 combine_after_change_list = Qnil;
2183 combine_after_change_buffer = Qnil;
2184
2185 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
2186 doc: /* Used internally by the `combine-after-change-calls' macro. */);
2187 Vcombine_after_change_calls = Qnil;
2188
2189 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
2190 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
2191 This affects `before-change-functions' and `after-change-functions',
2192 as well as hooks attached to text properties and overlays. */);
2193 inhibit_modification_hooks = 0;
2194 DEFSYM (Qinhibit_modification_hooks, "inhibit-modification-hooks");
2195
2196 defsubr (&Scombine_after_change_execute);
2197 }