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