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