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