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