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