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