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