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