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