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