This source file includes following definitions.
- check_markers
- move_gap_both
- gap_left
- gap_right
- adjust_suspend_auto_hscroll
- adjust_markers_for_delete
- adjust_markers_for_insert
- adjust_point
- adjust_markers_for_replace
- count_bytes
- adjust_markers_bytepos
- buffer_overflow
- make_gap_larger
- make_gap_smaller
- make_gap
- make_gap_1
- copy_text
- insert
- insert_and_inherit
- insert_char
- insert_string
- insert_before_markers
- insert_before_markers_and_inherit
- count_combining_before
- count_combining_after
- insert_1_both
- insert_from_string
- insert_from_string_before_markers
- insert_from_string_1
- insert_from_gap_1
- insert_from_gap
- insert_from_buffer
- insert_from_buffer_1
- adjust_after_replace
- adjust_after_insert
- replace_range
- replace_range_2
- del_range
- safe_del_range_1
- safe_del_range_2
- safe_del_range
- del_range_1
- del_range_byte
- del_range_both
- del_range_2
- modify_text
- run_undoable_change
- prepare_to_modify_buffer_1
- prepare_to_modify_buffer
- invalidate_buffer_caches
- reset_var_on_error
- signal_before_change
- signal_after_change
- Fcombine_after_change_execute_1
- DEFUN
- syms_of_insdel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include <intprops.h>
24
25 #include "lisp.h"
26 #include "composite.h"
27 #include "intervals.h"
28 #include "character.h"
29 #include "buffer.h"
30 #include "window.h"
31 #include "region-cache.h"
32 #include "pdumper.h"
33
34 #ifdef HAVE_TREE_SITTER
35 #include "treesit.h"
36 #endif
37
38 static void insert_from_string_1 (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t,
39 ptrdiff_t, bool, bool);
40 static void insert_from_buffer_1 (struct buffer *, ptrdiff_t, ptrdiff_t, bool);
41 static void gap_left (ptrdiff_t, ptrdiff_t, bool);
42 static void gap_right (ptrdiff_t, ptrdiff_t);
43
44
45
46
47
48
49
50
51
52
53
54 static Lisp_Object combine_after_change_list;
55
56
57 static Lisp_Object combine_after_change_buffer;
58
59 static void signal_before_change (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
60
61
62
63 #ifdef MARKER_DEBUG
64
65 static void
66 check_markers (void)
67 {
68 struct Lisp_Marker *tail;
69 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
70
71 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
72 {
73 if (tail->buffer->text != current_buffer->text)
74 emacs_abort ();
75 if (tail->charpos > Z)
76 emacs_abort ();
77 if (tail->bytepos > Z_BYTE)
78 emacs_abort ();
79 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
80 emacs_abort ();
81 }
82 }
83
84 #else
85
86 #define check_markers() do { } while (0)
87
88 #endif
89
90
91
92
93 void
94 move_gap_both (ptrdiff_t charpos, ptrdiff_t bytepos)
95 {
96 eassert (charpos == BYTE_TO_CHAR (bytepos)
97 && bytepos == CHAR_TO_BYTE (charpos));
98 if (bytepos < GPT_BYTE)
99 gap_left (charpos, bytepos, 0);
100 else if (bytepos > GPT_BYTE)
101 gap_right (charpos, bytepos);
102 }
103
104
105
106
107
108
109 static void
110 gap_left (ptrdiff_t charpos, ptrdiff_t bytepos, bool newgap)
111 {
112 unsigned char *to, *from;
113 ptrdiff_t i;
114 ptrdiff_t new_s1;
115
116 if (!newgap)
117 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
118
119 i = GPT_BYTE;
120 to = GAP_END_ADDR;
121 from = GPT_ADDR;
122 new_s1 = GPT_BYTE;
123
124
125
126
127 while (1)
128 {
129
130 i = new_s1 - bytepos;
131 if (i == 0)
132 break;
133
134
135
136
137
138 if (QUITP)
139 {
140
141 bytepos = new_s1;
142 charpos = BYTE_TO_CHAR (bytepos);
143 break;
144 }
145
146
147
148
149
150
151 if (i > 32000)
152 i = 32000;
153 new_s1 -= i;
154 from -= i, to -= i;
155 memmove (to, from, i);
156 }
157
158
159
160
161 GPT_BYTE = bytepos;
162 GPT = charpos;
163 eassert (charpos <= bytepos);
164 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
165 maybe_quit ();
166 }
167
168
169
170
171
172 static void
173 gap_right (ptrdiff_t charpos, ptrdiff_t bytepos)
174 {
175 register unsigned char *to, *from;
176 register ptrdiff_t i;
177 ptrdiff_t new_s1;
178
179 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
180
181 i = GPT_BYTE;
182 from = GAP_END_ADDR;
183 to = GPT_ADDR;
184 new_s1 = GPT_BYTE;
185
186
187
188
189 while (1)
190 {
191
192 i = bytepos - new_s1;
193 if (i == 0)
194 break;
195
196
197
198
199
200 if (QUITP)
201 {
202
203 bytepos = new_s1;
204 charpos = BYTE_TO_CHAR (bytepos);
205 break;
206 }
207
208 if (i > 32000)
209 i = 32000;
210 new_s1 += i;
211 memmove (to, from, i);
212 from += i, to += i;
213 }
214
215 GPT = charpos;
216 GPT_BYTE = bytepos;
217 eassert (charpos <= bytepos);
218 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
219 maybe_quit ();
220 }
221
222
223
224
225 static void
226 adjust_suspend_auto_hscroll (ptrdiff_t from, ptrdiff_t to)
227 {
228 if (WINDOWP (selected_window))
229 {
230 struct window *w = XWINDOW (selected_window);
231
232 if (BUFFERP (w->contents)
233 && XBUFFER (w->contents) == current_buffer
234 && XMARKER (w->old_pointm)->charpos >= from
235 && XMARKER (w->old_pointm)->charpos <= to)
236 w->suspend_auto_hscroll = 0;
237 }
238 }
239
240
241
242
243
244
245
246
247
248 void
249 adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte,
250 ptrdiff_t to, ptrdiff_t to_byte)
251 {
252 struct Lisp_Marker *m;
253 ptrdiff_t charpos;
254
255 adjust_suspend_auto_hscroll (from, to);
256 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
257 {
258 charpos = m->charpos;
259 eassert (charpos <= Z);
260
261
262
263 if (charpos > to)
264 {
265 m->charpos -= to - from;
266 m->bytepos -= to_byte - from_byte;
267 }
268
269 else if (charpos > from)
270 {
271 m->charpos = from;
272 m->bytepos = from_byte;
273 }
274 }
275 adjust_overlays_for_delete (from, to - from);
276 }
277
278
279
280
281
282
283
284
285
286
287 static void
288 adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
289 ptrdiff_t to, ptrdiff_t to_byte, bool before_markers)
290 {
291 struct Lisp_Marker *m;
292 ptrdiff_t nchars = to - from;
293 ptrdiff_t nbytes = to_byte - from_byte;
294
295 adjust_suspend_auto_hscroll (from, to);
296 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
297 {
298 eassert (m->bytepos >= m->charpos
299 && m->bytepos - m->charpos <= Z_BYTE - Z);
300
301 if (m->bytepos == from_byte)
302 {
303 if (m->insertion_type || before_markers)
304 {
305 m->bytepos = to_byte;
306 m->charpos = to;
307 }
308 }
309 else if (m->bytepos > from_byte)
310 {
311 m->bytepos += nbytes;
312 m->charpos += nchars;
313 }
314 }
315 adjust_overlays_for_insert (from, to - from, before_markers);
316 }
317
318
319
320
321
322
323
324
325
326
327
328 static void
329 adjust_point (ptrdiff_t nchars, ptrdiff_t nbytes)
330 {
331 SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes);
332
333 eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV);
334 }
335
336
337
338
339
340
341 static void
342 adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
343 ptrdiff_t old_chars, ptrdiff_t old_bytes,
344 ptrdiff_t new_chars, ptrdiff_t new_bytes)
345 {
346 register struct Lisp_Marker *m;
347 ptrdiff_t prev_to_byte = from_byte + old_bytes;
348 ptrdiff_t diff_chars = new_chars - old_chars;
349 ptrdiff_t diff_bytes = new_bytes - old_bytes;
350
351 adjust_suspend_auto_hscroll (from, from + old_chars);
352
353
354
355
356
357 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
358 {
359 if (m->bytepos >= prev_to_byte)
360 {
361 m->charpos += diff_chars;
362 m->bytepos += diff_bytes;
363 }
364 else if (m->bytepos > from_byte)
365 {
366 m->charpos = from;
367 m->bytepos = from_byte;
368 }
369 }
370
371 check_markers ();
372
373 adjust_overlays_for_insert (from + old_chars, new_chars, true);
374 if (old_chars)
375 adjust_overlays_for_delete (from, old_chars);
376 }
377
378
379
380 static ptrdiff_t
381 count_bytes (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t endpos)
382 {
383 eassert (BEG_BYTE <= bytepos && bytepos <= Z_BYTE
384 && BEG <= endpos && endpos <= Z);
385
386 if (pos <= endpos)
387 for ( ; pos < endpos; pos++)
388 bytepos += next_char_len (bytepos);
389 else
390 for ( ; pos > endpos; pos--)
391 bytepos -= prev_char_len (bytepos);
392
393 return bytepos;
394 }
395
396
397
398
399
400
401
402
403
404
405 void
406 adjust_markers_bytepos (ptrdiff_t from, ptrdiff_t from_byte,
407 ptrdiff_t to, ptrdiff_t to_byte, int to_z)
408 {
409 register struct Lisp_Marker *m;
410 ptrdiff_t beg = from, begbyte = from_byte;
411
412 adjust_suspend_auto_hscroll (from, to);
413
414 if (Z == Z_BYTE || (!to_z && to == to_byte))
415 {
416
417
418 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
419 {
420 if (m->bytepos > from_byte
421 && (to_z || m->bytepos <= to_byte))
422 m->bytepos = m->charpos;
423 }
424 }
425 else
426 {
427 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
428 {
429
430 if (m->bytepos > from_byte
431 && (to_z || m->bytepos <= to_byte))
432 {
433 if (m->charpos < beg
434 && beg - m->charpos > m->charpos - from)
435 {
436 beg = from;
437 begbyte = from_byte;
438 }
439 m->bytepos = count_bytes (beg, begbyte, m->charpos);
440 beg = m->charpos;
441 begbyte = m->bytepos;
442 }
443 }
444 }
445
446
447 clear_charpos_cache (current_buffer);
448 }
449
450
451 void
452 buffer_overflow (void)
453 {
454 error ("Maximum buffer size exceeded");
455 }
456
457
458
459 static void
460 make_gap_larger (ptrdiff_t nbytes_added)
461 {
462 Lisp_Object tem;
463 ptrdiff_t real_gap_loc;
464 ptrdiff_t real_gap_loc_byte;
465 ptrdiff_t old_gap_size;
466 ptrdiff_t current_size = Z_BYTE - BEG_BYTE + GAP_SIZE;
467
468 if (BUF_BYTES_MAX - current_size < nbytes_added)
469 buffer_overflow ();
470
471
472
473 nbytes_added = min (nbytes_added + GAP_BYTES_DFL,
474 BUF_BYTES_MAX - current_size);
475
476 enlarge_buffer_text (current_buffer, nbytes_added);
477
478
479
480
481 tem = Vinhibit_quit;
482 Vinhibit_quit = Qt;
483
484 real_gap_loc = GPT;
485 real_gap_loc_byte = GPT_BYTE;
486 old_gap_size = GAP_SIZE;
487
488
489 GPT = Z + GAP_SIZE;
490 GPT_BYTE = Z_BYTE + GAP_SIZE;
491 GAP_SIZE = nbytes_added;
492
493
494 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
495
496
497 GAP_SIZE += old_gap_size;
498 GPT = real_gap_loc;
499 GPT_BYTE = real_gap_loc_byte;
500
501
502 *(Z_ADDR) = 0;
503
504 Vinhibit_quit = tem;
505 }
506
507 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
508
509
510
511 static void
512 make_gap_smaller (ptrdiff_t nbytes_removed)
513 {
514 Lisp_Object tem;
515 ptrdiff_t real_gap_loc;
516 ptrdiff_t real_gap_loc_byte;
517 ptrdiff_t real_Z;
518 ptrdiff_t real_Z_byte;
519 ptrdiff_t real_beg_unchanged;
520 ptrdiff_t new_gap_size;
521
522
523 if (GAP_SIZE - nbytes_removed < GAP_BYTES_MIN)
524 nbytes_removed = GAP_SIZE - GAP_BYTES_MIN;
525
526
527
528
529 tem = Vinhibit_quit;
530 Vinhibit_quit = Qt;
531
532 real_gap_loc = GPT;
533 real_gap_loc_byte = GPT_BYTE;
534 new_gap_size = GAP_SIZE - nbytes_removed;
535 real_Z = Z;
536 real_Z_byte = Z_BYTE;
537 real_beg_unchanged = BEG_UNCHANGED;
538
539
540
541
542 memset (GPT_ADDR, 0, new_gap_size);
543 GPT += new_gap_size;
544 GPT_BYTE += new_gap_size;
545 Z += new_gap_size;
546 Z_BYTE += new_gap_size;
547 GAP_SIZE = nbytes_removed;
548
549
550 gap_right (Z, Z_BYTE);
551
552 enlarge_buffer_text (current_buffer, -nbytes_removed);
553
554
555 GAP_SIZE = new_gap_size;
556 GPT = real_gap_loc;
557 GPT_BYTE = real_gap_loc_byte;
558 Z = real_Z;
559 Z_BYTE = real_Z_byte;
560 BEG_UNCHANGED = real_beg_unchanged;
561
562
563 *(Z_ADDR) = 0;
564
565 Vinhibit_quit = tem;
566 }
567
568 #endif
569
570 void
571 make_gap (ptrdiff_t nbytes_added)
572 {
573 if (nbytes_added >= 0)
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589 make_gap_larger (max (nbytes_added, (Z - BEG) / 64));
590 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
591 else
592 make_gap_smaller (-nbytes_added);
593 #endif
594 }
595
596
597
598
599 void
600 make_gap_1 (struct buffer *b, ptrdiff_t nbytes)
601 {
602 struct buffer *oldb = current_buffer;
603
604 current_buffer = b;
605 make_gap (nbytes);
606 current_buffer = oldb;
607 }
608
609
610
611
612
613
614
615
616 ptrdiff_t
617 copy_text (const unsigned char *from_addr, unsigned char *to_addr,
618 ptrdiff_t nbytes, bool from_multibyte, bool to_multibyte)
619 {
620 if (from_multibyte == to_multibyte)
621 {
622 memcpy (to_addr, from_addr, nbytes);
623 return nbytes;
624 }
625 else if (from_multibyte)
626 {
627 ptrdiff_t nchars = 0;
628 ptrdiff_t bytes_left = nbytes;
629
630 while (bytes_left > 0)
631 {
632 int thislen, c = string_char_and_length (from_addr, &thislen);
633 if (! ASCII_CHAR_P (c))
634 c &= 0xFF;
635 *to_addr++ = c;
636 from_addr += thislen;
637 bytes_left -= thislen;
638 nchars++;
639 }
640 return nchars;
641 }
642 else
643 {
644 unsigned char *initial_to_addr = to_addr;
645
646
647 while (nbytes > 0)
648 {
649 int c = *from_addr++;
650
651 if (!ASCII_CHAR_P (c))
652 {
653 c = BYTE8_TO_CHAR (c);
654 to_addr += CHAR_STRING (c, to_addr);
655 nbytes--;
656 }
657 else
658
659 *to_addr++ = c, nbytes--;
660 }
661 return to_addr - initial_to_addr;
662 }
663 }
664
665
666
667
668
669
670
671
672
673 void
674 insert (const char *string, ptrdiff_t nbytes)
675 {
676 if (nbytes > 0)
677 {
678 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
679 insert_1_both (string, len, nbytes, 0, 1, 0);
680 opoint = PT - len;
681 signal_after_change (opoint, 0, len);
682 update_compositions (opoint, PT, CHECK_BORDER);
683 }
684 }
685
686
687
688 void
689 insert_and_inherit (const char *string, ptrdiff_t nbytes)
690 {
691 if (nbytes > 0)
692 {
693 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
694 insert_1_both (string, len, nbytes, 1, 1, 0);
695 opoint = PT - len;
696 signal_after_change (opoint, 0, len);
697 update_compositions (opoint, PT, CHECK_BORDER);
698 }
699 }
700
701
702
703 void
704 insert_char (int c)
705 {
706 unsigned char str[MAX_MULTIBYTE_LENGTH];
707 int len;
708
709 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
710 len = CHAR_STRING (c, str);
711 else
712 {
713 len = 1;
714 str[0] = c;
715 }
716
717 insert ((char *) str, len);
718 }
719
720
721
722 void
723 insert_string (const char *s)
724 {
725 insert (s, strlen (s));
726 }
727
728
729
730
731
732
733 void
734 insert_before_markers (const char *string, ptrdiff_t nbytes)
735 {
736 if (nbytes > 0)
737 {
738 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
739 insert_1_both (string, len, nbytes, 0, 1, 1);
740 opoint = PT - len;
741 signal_after_change (opoint, 0, len);
742 update_compositions (opoint, PT, CHECK_BORDER);
743 }
744 }
745
746
747
748 void
749 insert_before_markers_and_inherit (const char *string,
750 ptrdiff_t nbytes)
751 {
752 if (nbytes > 0)
753 {
754 ptrdiff_t len = chars_in_text ((unsigned char *) string, nbytes), opoint;
755 insert_1_both (string, len, nbytes, 1, 1, 1);
756 opoint = PT - len;
757 signal_after_change (opoint, 0, len);
758 update_compositions (opoint, PT, CHECK_BORDER);
759 }
760 }
761
762 #ifdef BYTE_COMBINING_DEBUG
763
764
765
766
767
768
769 int
770 count_combining_before (const unsigned char *string, ptrdiff_t length,
771 ptrdiff_t pos, ptrdiff_t pos_byte)
772 {
773 int len, combining_bytes;
774 const unsigned char *p;
775
776 if (NILP (current_buffer->enable_multibyte_characters))
777 return 0;
778
779
780
781
782
783 if (length == 0 || CHAR_HEAD_P (*string))
784 return 0;
785 if (pos_byte == BEG_BYTE)
786 return 0;
787 len = 1;
788 p = BYTE_POS_ADDR (pos_byte - 1);
789 while (! CHAR_HEAD_P (*p)) p--, len++;
790 if (! LEADING_CODE_P (*p))
791 return 0;
792
793 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
794 if (combining_bytes <= 0)
795
796
797
798 return 0;
799
800
801
802 p = string + 1;
803 while (!CHAR_HEAD_P (*p) && p < string + length)
804 p++;
805
806 return (combining_bytes < p - string ? combining_bytes : p - string);
807 }
808
809
810
811
812
813
814 int
815 count_combining_after (const unsigned char *string,
816 ptrdiff_t length, ptrdiff_t pos, ptrdiff_t pos_byte)
817 {
818 ptrdiff_t opos_byte = pos_byte;
819 ptrdiff_t i;
820 ptrdiff_t bytes;
821 unsigned char *bufp;
822
823 if (NILP (current_buffer->enable_multibyte_characters))
824 return 0;
825
826
827
828
829
830
831 if (length > 0 && ASCII_CHAR_P (string[length - 1]))
832 return 0;
833 if (pos_byte == Z_BYTE)
834 return 0;
835 bufp = BYTE_POS_ADDR (pos_byte);
836 if (CHAR_HEAD_P (*bufp))
837 return 0;
838
839 i = length - 1;
840 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
841 {
842 i--;
843 }
844 if (i < 0)
845 {
846
847
848
849 unsigned char *p = BEG_ADDR;
850 i = pos_byte - 2;
851 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
852 i--;
853 if (i < 0 || !LEADING_CODE_P (p[i]))
854 return 0;
855
856 bytes = BYTES_BY_CHAR_HEAD (p[i]);
857 return (bytes <= pos_byte - 1 - i + length
858 ? 0
859 : bytes - (pos_byte - 1 - i + length));
860 }
861 if (!LEADING_CODE_P (string[i]))
862 return 0;
863
864 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
865 bufp++, pos_byte++;
866 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
867
868 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
869 }
870
871 #endif
872
873
874
875
876
877
878
879
880
881
882
883 void
884 insert_1_both (const char *string,
885 ptrdiff_t nchars, ptrdiff_t nbytes,
886 bool inherit, bool prepare, bool before_markers)
887 {
888 if (nchars == 0)
889 return;
890
891 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
892 nchars = nbytes;
893
894 if (prepare)
895
896
897
898 prepare_to_modify_buffer (PT, PT, NULL);
899
900 if (PT != GPT)
901 move_gap_both (PT, PT_BYTE);
902 if (GAP_SIZE < nbytes)
903 make_gap (nbytes - GAP_SIZE);
904
905 #ifdef BYTE_COMBINING_DEBUG
906 if (count_combining_before (string, nbytes, PT, PT_BYTE)
907 || count_combining_after (string, nbytes, PT, PT_BYTE))
908 emacs_abort ();
909 #endif
910
911
912
913
914 record_insert (PT, nchars);
915 modiff_incr (&MODIFF, nchars);
916 CHARS_MODIFF = MODIFF;
917
918 memcpy (GPT_ADDR, string, nbytes);
919
920 GAP_SIZE -= nbytes;
921 GPT += nchars;
922 ZV += nchars;
923 Z += nchars;
924 GPT_BYTE += nbytes;
925 ZV_BYTE += nbytes;
926 Z_BYTE += nbytes;
927 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
928
929 eassert (GPT <= GPT_BYTE);
930
931
932 if (Z - GPT < END_UNCHANGED)
933 END_UNCHANGED = Z - GPT;
934
935 adjust_markers_for_insert (PT, PT_BYTE,
936 PT + nchars, PT_BYTE + nbytes,
937 before_markers);
938
939 offset_intervals (current_buffer, PT, nchars);
940
941 if (!inherit && buffer_intervals (current_buffer))
942 set_text_properties (make_fixnum (PT), make_fixnum (PT + nchars),
943 Qnil, Qnil, Qnil);
944
945 #ifdef HAVE_TREE_SITTER
946 eassert (nbytes >= 0);
947 eassert (PT_BYTE >= 0);
948 treesit_record_change (PT_BYTE, PT_BYTE, PT_BYTE + nbytes);
949 #endif
950
951 adjust_point (nchars, nbytes);
952
953 check_markers ();
954 }
955
956
957
958
959
960
961
962
963
964
965 void
966 insert_from_string (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
967 ptrdiff_t length, ptrdiff_t length_byte, bool inherit)
968 {
969 ptrdiff_t opoint = PT;
970
971 if (SCHARS (string) == 0)
972 return;
973
974 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
975 inherit, 0);
976 signal_after_change (opoint, 0, PT - opoint);
977 update_compositions (opoint, PT, CHECK_BORDER);
978 }
979
980
981
982
983 void
984 insert_from_string_before_markers (Lisp_Object string,
985 ptrdiff_t pos, ptrdiff_t pos_byte,
986 ptrdiff_t length, ptrdiff_t length_byte,
987 bool inherit)
988 {
989 ptrdiff_t opoint = PT;
990
991 if (SCHARS (string) == 0)
992 return;
993
994 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
995 inherit, 1);
996 signal_after_change (opoint, 0, PT - opoint);
997 update_compositions (opoint, PT, CHECK_BORDER);
998 }
999
1000
1001
1002 static void
1003 insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1004 ptrdiff_t nchars, ptrdiff_t nbytes,
1005 bool inherit, bool before_markers)
1006 {
1007 ptrdiff_t outgoing_nbytes = nbytes;
1008 INTERVAL intervals;
1009
1010
1011
1012
1013 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1014 outgoing_nbytes = nchars;
1015 else if (! STRING_MULTIBYTE (string))
1016 outgoing_nbytes
1017 = count_size_as_multibyte (SDATA (string) + pos_byte,
1018 nbytes);
1019
1020
1021
1022
1023 prepare_to_modify_buffer (PT, PT, NULL);
1024
1025 if (PT != GPT)
1026 move_gap_both (PT, PT_BYTE);
1027 if (GAP_SIZE < outgoing_nbytes)
1028 make_gap (outgoing_nbytes - GAP_SIZE);
1029
1030
1031
1032 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
1033 STRING_MULTIBYTE (string),
1034 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1035
1036 #ifdef BYTE_COMBINING_DEBUG
1037
1038
1039
1040
1041
1042 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1043 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1044 emacs_abort ();
1045 #endif
1046
1047 record_insert (PT, nchars);
1048 modiff_incr (&MODIFF, nchars);
1049 CHARS_MODIFF = MODIFF;
1050
1051 GAP_SIZE -= outgoing_nbytes;
1052 GPT += nchars;
1053 ZV += nchars;
1054 Z += nchars;
1055 GPT_BYTE += outgoing_nbytes;
1056 ZV_BYTE += outgoing_nbytes;
1057 Z_BYTE += outgoing_nbytes;
1058 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1059
1060 eassert (GPT <= GPT_BYTE);
1061
1062
1063 if (Z - GPT < END_UNCHANGED)
1064 END_UNCHANGED = Z - GPT;
1065
1066 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1067 PT_BYTE + outgoing_nbytes,
1068 before_markers);
1069
1070 offset_intervals (current_buffer, PT, nchars);
1071
1072 intervals = string_intervals (string);
1073
1074 if (nbytes < SBYTES (string))
1075 intervals = copy_intervals (intervals, pos, nchars);
1076
1077
1078 graft_intervals_into_buffer (intervals, PT, nchars,
1079 current_buffer, inherit);
1080
1081 #ifdef HAVE_TREE_SITTER
1082 eassert (nbytes >= 0);
1083 eassert (PT_BYTE >= 0);
1084 treesit_record_change (PT_BYTE, PT_BYTE, PT_BYTE + nbytes);
1085 #endif
1086
1087 adjust_point (nchars, outgoing_nbytes);
1088
1089 check_markers ();
1090 }
1091
1092
1093
1094
1095
1096
1097
1098 void
1099 insert_from_gap_1 (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1100 {
1101 eassert (NILP (BVAR (current_buffer, enable_multibyte_characters))
1102 ? nchars == nbytes : nchars <= nbytes);
1103
1104 #ifdef HAVE_TREE_SITTER
1105 ptrdiff_t ins_bytepos = GPT_BYTE;
1106 #endif
1107
1108 GAP_SIZE -= nbytes;
1109 if (! text_at_gap_tail)
1110 {
1111 GPT += nchars;
1112 GPT_BYTE += nbytes;
1113 }
1114 ZV += nchars;
1115 Z += nchars;
1116 ZV_BYTE += nbytes;
1117 Z_BYTE += nbytes;
1118
1119
1120 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1121 eassert (GPT <= GPT_BYTE);
1122
1123 #ifdef HAVE_TREE_SITTER
1124 eassert (nbytes >= 0);
1125 eassert (ins_bytepos >= 0);
1126 treesit_record_change (ins_bytepos, ins_bytepos, ins_bytepos + nbytes);
1127 #endif
1128 }
1129
1130
1131
1132
1133
1134 void
1135 insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1136 {
1137 ptrdiff_t ins_charpos = GPT, ins_bytepos = GPT_BYTE;
1138
1139 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1140 nchars = nbytes;
1141
1142
1143
1144
1145
1146 invalidate_buffer_caches (current_buffer, GPT, GPT);
1147 record_insert (GPT, nchars);
1148 modiff_incr (&MODIFF, nchars);
1149 CHARS_MODIFF = MODIFF;
1150
1151 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail);
1152
1153 adjust_markers_for_insert (ins_charpos, ins_bytepos,
1154 ins_charpos + nchars, ins_bytepos + nbytes, false);
1155
1156 if (buffer_intervals (current_buffer))
1157 {
1158 offset_intervals (current_buffer, ins_charpos, nchars);
1159 graft_intervals_into_buffer (NULL, ins_charpos, nchars,
1160 current_buffer, 0);
1161 }
1162
1163 if (ins_charpos < PT)
1164 adjust_point (nchars, nbytes);
1165
1166 check_markers ();
1167 }
1168
1169
1170
1171
1172
1173
1174
1175
1176 void
1177 insert_from_buffer (struct buffer *buf,
1178 ptrdiff_t charpos, ptrdiff_t nchars, bool inherit)
1179 {
1180 ptrdiff_t opoint = PT;
1181
1182 #ifdef HAVE_TREE_SITTER
1183 ptrdiff_t obyte = PT_BYTE;
1184 #endif
1185
1186 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1187 signal_after_change (opoint, 0, PT - opoint);
1188 update_compositions (opoint, PT, CHECK_BORDER);
1189
1190 #ifdef HAVE_TREE_SITTER
1191 eassert (PT_BYTE >= BEG_BYTE);
1192 eassert (obyte >= BEG_BYTE);
1193 eassert (PT_BYTE >= obyte);
1194 treesit_record_change (obyte, obyte, PT_BYTE);
1195 #endif
1196 }
1197
1198
1199
1200
1201 static void
1202 insert_from_buffer_1 (struct buffer *buf,
1203 ptrdiff_t from, ptrdiff_t nchars, bool inherit)
1204 {
1205 ptrdiff_t chunk, chunk_expanded;
1206 ptrdiff_t from_byte = buf_charpos_to_bytepos (buf, from);
1207 ptrdiff_t to_byte = buf_charpos_to_bytepos (buf, from + nchars);
1208 ptrdiff_t incoming_nbytes = to_byte - from_byte;
1209 ptrdiff_t outgoing_nbytes = incoming_nbytes;
1210 INTERVAL intervals;
1211
1212 if (nchars == 0)
1213 return;
1214
1215
1216
1217
1218 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1219 outgoing_nbytes = nchars;
1220 else if (NILP (BVAR (buf, enable_multibyte_characters)))
1221 {
1222 ptrdiff_t outgoing_before_gap = 0;
1223 ptrdiff_t outgoing_after_gap = 0;
1224
1225 if (from < BUF_GPT (buf))
1226 {
1227 chunk = BUF_GPT_BYTE (buf) - from_byte;
1228 if (chunk > incoming_nbytes)
1229 chunk = incoming_nbytes;
1230 outgoing_before_gap
1231 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1232 chunk);
1233 }
1234 else
1235 chunk = 0;
1236
1237 if (chunk < incoming_nbytes)
1238 outgoing_after_gap
1239 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1240 from_byte + chunk),
1241 incoming_nbytes - chunk);
1242
1243 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1244 }
1245
1246
1247
1248
1249 prepare_to_modify_buffer (PT, PT, NULL);
1250
1251 if (PT != GPT)
1252 move_gap_both (PT, PT_BYTE);
1253 if (GAP_SIZE < outgoing_nbytes)
1254 make_gap (outgoing_nbytes - GAP_SIZE);
1255
1256 if (from < BUF_GPT (buf))
1257 {
1258 chunk = BUF_GPT_BYTE (buf) - from_byte;
1259 if (chunk > incoming_nbytes)
1260 chunk = incoming_nbytes;
1261
1262
1263 chunk_expanded
1264 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1265 GPT_ADDR, chunk,
1266 ! NILP (BVAR (buf, enable_multibyte_characters)),
1267 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1268 }
1269 else
1270 chunk_expanded = chunk = 0;
1271
1272 if (chunk < incoming_nbytes)
1273 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1274 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
1275 ! NILP (BVAR (buf, enable_multibyte_characters)),
1276 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1277
1278 #ifdef BYTE_COMBINING_DEBUG
1279
1280
1281
1282
1283
1284 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1285 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1286 emacs_abort ();
1287 #endif
1288
1289 record_insert (PT, nchars);
1290 modiff_incr (&MODIFF, nchars);
1291 CHARS_MODIFF = MODIFF;
1292
1293 GAP_SIZE -= outgoing_nbytes;
1294 GPT += nchars;
1295 ZV += nchars;
1296 Z += nchars;
1297 GPT_BYTE += outgoing_nbytes;
1298 ZV_BYTE += outgoing_nbytes;
1299 Z_BYTE += outgoing_nbytes;
1300 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1301
1302 eassert (GPT <= GPT_BYTE);
1303
1304
1305 if (Z - GPT < END_UNCHANGED)
1306 END_UNCHANGED = Z - GPT;
1307
1308 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1309 PT_BYTE + outgoing_nbytes,
1310 false);
1311
1312 offset_intervals (current_buffer, PT, nchars);
1313
1314
1315 intervals = buffer_intervals (buf);
1316 if (nchars < BUF_Z (buf) - BUF_BEG (buf))
1317 {
1318 if (buf == current_buffer && PT <= from)
1319 from += nchars;
1320 intervals = copy_intervals (intervals, from, nchars);
1321 }
1322
1323
1324 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
1325
1326 adjust_point (nchars, outgoing_nbytes);
1327 }
1328
1329
1330
1331
1332
1333
1334
1335
1336 static void
1337 adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1338 Lisp_Object prev_text, ptrdiff_t len, ptrdiff_t len_byte)
1339 {
1340 ptrdiff_t nchars_del = 0, nbytes_del = 0;
1341
1342 #ifdef BYTE_COMBINING_DEBUG
1343 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1344 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1345 emacs_abort ();
1346 #endif
1347
1348 if (STRINGP (prev_text))
1349 {
1350 nchars_del = SCHARS (prev_text);
1351 nbytes_del = SBYTES (prev_text);
1352 }
1353
1354
1355 GAP_SIZE -= len_byte;
1356 ZV += len; Z += len;
1357 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1358 GPT += len; GPT_BYTE += len_byte;
1359 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1360
1361 if (nchars_del > 0)
1362 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1363 len, len_byte);
1364 else
1365 adjust_markers_for_insert (from, from_byte,
1366 from + len, from_byte + len_byte, false);
1367
1368 if (nchars_del > 0)
1369 record_delete (from, prev_text, false);
1370 record_insert (from, len);
1371
1372 offset_intervals (current_buffer, from, len - nchars_del);
1373
1374 if (from < PT)
1375 adjust_point (len - nchars_del, len_byte - nbytes_del);
1376
1377
1378 if (Z - GPT < END_UNCHANGED)
1379 END_UNCHANGED = Z - GPT;
1380
1381 check_markers ();
1382
1383 modiff_incr (&MODIFF, nchars_del + len);
1384 CHARS_MODIFF = MODIFF;
1385 }
1386
1387
1388
1389
1390
1391
1392 void
1393 adjust_after_insert (ptrdiff_t from, ptrdiff_t from_byte,
1394 ptrdiff_t to, ptrdiff_t to_byte, ptrdiff_t newlen)
1395 {
1396 ptrdiff_t len = to - from, len_byte = to_byte - from_byte;
1397
1398 if (GPT != to)
1399 move_gap_both (to, to_byte);
1400 GAP_SIZE += len_byte;
1401 GPT -= len; GPT_BYTE -= len_byte;
1402 ZV -= len; ZV_BYTE -= len_byte;
1403 Z -= len; Z_BYTE -= len_byte;
1404 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1405 }
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421 void
1422 replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1423 bool prepare, bool inherit, bool markers,
1424 bool adjust_match_data, bool inhibit_mod_hooks)
1425 {
1426 ptrdiff_t inschars = SCHARS (new);
1427 ptrdiff_t insbytes = SBYTES (new);
1428 ptrdiff_t from_byte, to_byte;
1429 ptrdiff_t nbytes_del, nchars_del;
1430 INTERVAL intervals;
1431 ptrdiff_t outgoing_insbytes = insbytes;
1432 Lisp_Object deletion;
1433
1434 check_markers ();
1435
1436 deletion = Qnil;
1437
1438 if (prepare)
1439 {
1440 ptrdiff_t range_length = to - from;
1441 prepare_to_modify_buffer (from, to, &from);
1442 to = from + range_length;
1443 }
1444
1445
1446 if (from < BEGV)
1447 from = BEGV;
1448 if (to > ZV)
1449 to = ZV;
1450
1451 from_byte = CHAR_TO_BYTE (from);
1452 to_byte = CHAR_TO_BYTE (to);
1453
1454 nchars_del = to - from;
1455 nbytes_del = to_byte - from_byte;
1456
1457 if (nbytes_del <= 0 && insbytes == 0)
1458 return;
1459
1460
1461
1462
1463 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
1464 outgoing_insbytes = inschars;
1465 else if (! STRING_MULTIBYTE (new))
1466 outgoing_insbytes
1467 = count_size_as_multibyte (SDATA (new), insbytes);
1468
1469
1470 if (from > GPT)
1471 gap_right (from, from_byte);
1472 if (to < GPT)
1473 gap_left (to, to_byte, 0);
1474
1475
1476
1477
1478 if (! EQ (BVAR (current_buffer, undo_list), Qt))
1479 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1480
1481 GAP_SIZE += nbytes_del;
1482 ZV -= nchars_del;
1483 Z -= nchars_del;
1484 ZV_BYTE -= nbytes_del;
1485 Z_BYTE -= nbytes_del;
1486 GPT = from;
1487 GPT_BYTE = from_byte;
1488 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1489
1490 eassert (GPT <= GPT_BYTE);
1491
1492 if (GPT - BEG < BEG_UNCHANGED)
1493 BEG_UNCHANGED = GPT - BEG;
1494 if (Z - GPT < END_UNCHANGED)
1495 END_UNCHANGED = Z - GPT;
1496
1497 if (GAP_SIZE < outgoing_insbytes)
1498 make_gap (outgoing_insbytes - GAP_SIZE);
1499
1500
1501
1502 copy_text (SDATA (new), GPT_ADDR, insbytes,
1503 STRING_MULTIBYTE (new),
1504 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
1505
1506 #ifdef BYTE_COMBINING_DEBUG
1507
1508
1509
1510
1511
1512 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1513 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1514 emacs_abort ();
1515 #endif
1516
1517
1518
1519
1520
1521 if (!NILP (deletion))
1522 {
1523 record_insert (from + SCHARS (deletion), inschars);
1524 record_delete (from, deletion, false);
1525 }
1526
1527 GAP_SIZE -= outgoing_insbytes;
1528 GPT += inschars;
1529 ZV += inschars;
1530 Z += inschars;
1531 GPT_BYTE += outgoing_insbytes;
1532 ZV_BYTE += outgoing_insbytes;
1533 Z_BYTE += outgoing_insbytes;
1534 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1535
1536 eassert (GPT <= GPT_BYTE);
1537
1538
1539 if (markers)
1540 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1541 inschars, outgoing_insbytes);
1542 else
1543 {
1544
1545
1546
1547
1548
1549 adjust_markers_bytepos (from, from_byte, from + inschars,
1550 from_byte + outgoing_insbytes, true);
1551 }
1552
1553 offset_intervals (current_buffer, from, inschars - nchars_del);
1554
1555
1556
1557 intervals = string_intervals (new);
1558
1559 graft_intervals_into_buffer (intervals, from, inschars,
1560 current_buffer, inherit);
1561
1562 #ifdef HAVE_TREE_SITTER
1563 eassert (to_byte >= from_byte);
1564 eassert (outgoing_insbytes >= 0);
1565 eassert (from_byte >= 0);
1566 treesit_record_change (from_byte, to_byte, from_byte + outgoing_insbytes);
1567 #endif
1568
1569
1570 if (from < PT)
1571 adjust_point ((from + inschars - (PT < to ? PT : to)),
1572 (from_byte + outgoing_insbytes
1573 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1574
1575 check_markers ();
1576
1577 modiff_incr (&MODIFF, nchars_del + inschars);
1578 CHARS_MODIFF = MODIFF;
1579
1580 if (adjust_match_data)
1581 update_search_regs (from, to, from + SCHARS (new));
1582
1583 if (!inhibit_mod_hooks)
1584 {
1585 signal_after_change (from, nchars_del, GPT - from);
1586 update_compositions (from, GPT, CHECK_BORDER);
1587 }
1588 }
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606 void
1607 replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1608 ptrdiff_t to, ptrdiff_t to_byte,
1609 const char *ins, ptrdiff_t inschars, ptrdiff_t insbytes,
1610 bool markers)
1611 {
1612 ptrdiff_t nbytes_del, nchars_del;
1613
1614 check_markers ();
1615
1616 nchars_del = to - from;
1617 nbytes_del = to_byte - from_byte;
1618
1619 if (nbytes_del <= 0 && insbytes == 0)
1620 return;
1621
1622
1623 if (from > GPT)
1624 gap_right (from, from_byte);
1625 if (to < GPT)
1626 gap_left (to, to_byte, 0);
1627
1628 GAP_SIZE += nbytes_del;
1629 ZV -= nchars_del;
1630 Z -= nchars_del;
1631 ZV_BYTE -= nbytes_del;
1632 Z_BYTE -= nbytes_del;
1633 GPT = from;
1634 GPT_BYTE = from_byte;
1635 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1636
1637 eassert (GPT <= GPT_BYTE);
1638
1639 if (GPT - BEG < BEG_UNCHANGED)
1640 BEG_UNCHANGED = GPT - BEG;
1641 if (Z - GPT < END_UNCHANGED)
1642 END_UNCHANGED = Z - GPT;
1643
1644 if (GAP_SIZE < insbytes)
1645 make_gap (insbytes - GAP_SIZE);
1646
1647
1648 memcpy (GPT_ADDR, ins, insbytes);
1649
1650 #ifdef BYTE_COMBINING_DEBUG
1651
1652
1653
1654
1655
1656 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
1657 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
1658 emacs_abort ();
1659 #endif
1660
1661 GAP_SIZE -= insbytes;
1662 GPT += inschars;
1663 ZV += inschars;
1664 Z += inschars;
1665 GPT_BYTE += insbytes;
1666 ZV_BYTE += insbytes;
1667 Z_BYTE += insbytes;
1668 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1669
1670 eassert (GPT <= GPT_BYTE);
1671
1672
1673 if (! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
1674 {
1675 if (markers)
1676 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1677 inschars, insbytes);
1678 else
1679 {
1680
1681
1682
1683
1684
1685 adjust_markers_bytepos (from, from_byte, from + inschars,
1686 from_byte + insbytes, true);
1687 }
1688 }
1689
1690 offset_intervals (current_buffer, from, inschars - nchars_del);
1691
1692
1693 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
1694 {
1695 if (PT < to)
1696
1697 adjust_point (from - PT, from_byte - PT_BYTE);
1698 else
1699 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1700 }
1701
1702 check_markers ();
1703
1704 modiff_incr (&MODIFF, nchars_del + inschars);
1705 CHARS_MODIFF = MODIFF;
1706 }
1707
1708
1709
1710
1711
1712 void
1713 del_range (ptrdiff_t from, ptrdiff_t to)
1714 {
1715 del_range_1 (from, to, 1, 0);
1716 }
1717
1718 struct safe_del_range_context
1719 {
1720
1721 ptrdiff_t from, to;
1722 };
1723
1724 static Lisp_Object
1725 safe_del_range_1 (void *ptr)
1726 {
1727 struct safe_del_range_context *context;
1728
1729 context = ptr;
1730 del_range (context->from, context->to);
1731 return Qnil;
1732 }
1733
1734 static Lisp_Object
1735 safe_del_range_2 (enum nonlocal_exit type, Lisp_Object value)
1736 {
1737 return Qt;
1738 }
1739
1740
1741
1742
1743 int
1744 safe_del_range (ptrdiff_t from, ptrdiff_t to)
1745 {
1746 struct safe_del_range_context context;
1747
1748 context.from = from;
1749 context.to = to;
1750
1751 return !NILP (internal_catch_all (safe_del_range_1,
1752 &context,
1753 safe_del_range_2));
1754 }
1755
1756
1757
1758
1759 Lisp_Object
1760 del_range_1 (ptrdiff_t from, ptrdiff_t to, bool prepare, bool ret_string)
1761 {
1762 ptrdiff_t from_byte, to_byte;
1763 Lisp_Object deletion;
1764
1765
1766 if (from < BEGV)
1767 from = BEGV;
1768 if (to > ZV)
1769 to = ZV;
1770
1771 if (to <= from)
1772 return Qnil;
1773
1774 if (prepare)
1775 {
1776 ptrdiff_t range_length = to - from;
1777 prepare_to_modify_buffer (from, to, &from);
1778 to = min (ZV, from + range_length);
1779 }
1780
1781 from_byte = CHAR_TO_BYTE (from);
1782 to_byte = CHAR_TO_BYTE (to);
1783
1784 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1785 signal_after_change (from, to - from, 0);
1786 update_compositions (from, from, CHECK_HEAD);
1787 return deletion;
1788 }
1789
1790
1791
1792 void
1793 del_range_byte (ptrdiff_t from_byte, ptrdiff_t to_byte)
1794 {
1795 ptrdiff_t from, to;
1796
1797
1798 if (from_byte < BEGV_BYTE)
1799 from_byte = BEGV_BYTE;
1800 if (to_byte > ZV_BYTE)
1801 to_byte = ZV_BYTE;
1802
1803 if (to_byte <= from_byte)
1804 return;
1805
1806 from = BYTE_TO_CHAR (from_byte);
1807 to = BYTE_TO_CHAR (to_byte);
1808
1809 {
1810 ptrdiff_t old_from = from, old_to = Z - to;
1811 ptrdiff_t range_length = to - from;
1812 prepare_to_modify_buffer (from, to, &from);
1813 to = from + range_length;
1814
1815 if (old_from != from)
1816 from_byte = CHAR_TO_BYTE (from);
1817 if (to > ZV)
1818 {
1819 to = ZV;
1820 to_byte = ZV_BYTE;
1821 }
1822 else if (old_to == Z - to)
1823 to_byte = CHAR_TO_BYTE (to);
1824 }
1825
1826 del_range_2 (from, from_byte, to, to_byte, 0);
1827 signal_after_change (from, to - from, 0);
1828 update_compositions (from, from, CHECK_HEAD);
1829 }
1830
1831
1832
1833
1834 void
1835 del_range_both (ptrdiff_t from, ptrdiff_t from_byte,
1836 ptrdiff_t to, ptrdiff_t to_byte, bool prepare)
1837 {
1838
1839 if (from_byte < BEGV_BYTE)
1840 from_byte = BEGV_BYTE;
1841 if (to_byte > ZV_BYTE)
1842 to_byte = ZV_BYTE;
1843
1844 if (to_byte <= from_byte)
1845 return;
1846
1847 if (from < BEGV)
1848 from = BEGV;
1849 if (to > ZV)
1850 to = ZV;
1851
1852 if (prepare)
1853 {
1854 ptrdiff_t old_from = from, old_to = Z - to;
1855 ptrdiff_t range_length = to - from;
1856 prepare_to_modify_buffer (from, to, &from);
1857 to = from + range_length;
1858
1859 if (old_from != from)
1860 from_byte = CHAR_TO_BYTE (from);
1861 if (to > ZV)
1862 {
1863 to = ZV;
1864 to_byte = ZV_BYTE;
1865 }
1866 else if (old_to == Z - to)
1867 to_byte = CHAR_TO_BYTE (to);
1868 }
1869
1870 del_range_2 (from, from_byte, to, to_byte, 0);
1871 signal_after_change (from, to - from, 0);
1872 update_compositions (from, from, CHECK_HEAD);
1873 }
1874
1875
1876
1877
1878
1879
1880 Lisp_Object
1881 del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1882 ptrdiff_t to, ptrdiff_t to_byte, bool ret_string)
1883 {
1884 ptrdiff_t nbytes_del, nchars_del;
1885 Lisp_Object deletion;
1886
1887 check_markers ();
1888
1889 nchars_del = to - from;
1890 nbytes_del = to_byte - from_byte;
1891
1892
1893 if (from > GPT)
1894 gap_right (from, from_byte);
1895 if (to < GPT)
1896 gap_left (to, to_byte, 0);
1897
1898 #ifdef BYTE_COMBINING_DEBUG
1899 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1900 Z_BYTE - to_byte, from, from_byte))
1901 emacs_abort ();
1902 #endif
1903
1904 if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
1905 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
1906 else
1907 deletion = Qnil;
1908
1909
1910
1911 record_delete (from, deletion, true);
1912
1913
1914
1915 adjust_markers_for_delete (from, from_byte, to, to_byte);
1916
1917 modiff_incr (&MODIFF, nchars_del);
1918 CHARS_MODIFF = MODIFF;
1919
1920
1921 if (from < PT)
1922 adjust_point (from - (PT < to ? PT : to),
1923 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
1924
1925 offset_intervals (current_buffer, from, - nchars_del);
1926
1927 GAP_SIZE += nbytes_del;
1928 ZV_BYTE -= nbytes_del;
1929 Z_BYTE -= nbytes_del;
1930 ZV -= nchars_del;
1931 Z -= nchars_del;
1932 GPT = from;
1933 GPT_BYTE = from_byte;
1934 if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking)
1935
1936
1937 *(GPT_ADDR) = 0;
1938
1939 eassert (GPT <= GPT_BYTE);
1940
1941 if (GPT - BEG < BEG_UNCHANGED)
1942 BEG_UNCHANGED = GPT - BEG;
1943 if (Z - GPT < END_UNCHANGED)
1944 END_UNCHANGED = Z - GPT;
1945
1946 check_markers ();
1947
1948 #ifdef HAVE_TREE_SITTER
1949 eassert (from_byte <= to_byte);
1950 eassert (from_byte >= 0);
1951 treesit_record_change (from_byte, to_byte, from_byte);
1952 #endif
1953
1954 return deletion;
1955 }
1956
1957
1958
1959
1960
1961
1962
1963 void
1964 modify_text (ptrdiff_t start, ptrdiff_t end)
1965 {
1966 prepare_to_modify_buffer (start, end, NULL);
1967
1968 BUF_COMPUTE_UNCHANGED (current_buffer, start - 1, end);
1969 if (MODIFF <= SAVE_MODIFF)
1970 record_first_change ();
1971 modiff_incr (&MODIFF, end - start);
1972 CHARS_MODIFF = MODIFF;
1973
1974 bset_point_before_scroll (current_buffer, Qnil);
1975 }
1976
1977
1978
1979
1980 static void
1981 run_undoable_change (void)
1982 {
1983 if (EQ (BVAR (current_buffer, undo_list), Qt))
1984 return;
1985
1986 call0 (Qundo_auto__undoable_change);
1987 }
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004 void
2005 prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end,
2006 ptrdiff_t *preserve_ptr)
2007 {
2008 struct buffer *base_buffer;
2009 Lisp_Object temp;
2010
2011 XSETFASTINT (temp, start);
2012 if (!NILP (BVAR (current_buffer, read_only)))
2013 Fbarf_if_buffer_read_only (temp);
2014
2015
2016
2017
2018
2019 if (pdumper_object_p (BEG_ADDR))
2020 enlarge_buffer_text (current_buffer, 0);
2021 eassert (!pdumper_object_p (BEG_ADDR));
2022
2023 run_undoable_change();
2024
2025 bset_redisplay (current_buffer);
2026
2027 if (buffer_intervals (current_buffer))
2028 {
2029 if (preserve_ptr)
2030 {
2031 Lisp_Object preserve_marker;
2032 preserve_marker = Fcopy_marker (make_fixnum (*preserve_ptr), Qnil);
2033 verify_interval_modification (current_buffer, start, end);
2034 *preserve_ptr = marker_position (preserve_marker);
2035 unchain_marker (XMARKER (preserve_marker));
2036 }
2037 else
2038 verify_interval_modification (current_buffer, start, end);
2039 }
2040
2041
2042 if (current_buffer->base_buffer != 0)
2043 base_buffer = current_buffer->base_buffer;
2044 else
2045 base_buffer = current_buffer;
2046
2047 if (inhibit_modification_hooks)
2048 return;
2049
2050 if (!NILP (BVAR (base_buffer, file_truename))
2051
2052 && !NILP (BVAR (base_buffer, filename))
2053 && SAVE_MODIFF >= MODIFF)
2054 Flock_file (BVAR (base_buffer, file_truename));
2055
2056
2057
2058 if (!NILP (BVAR (current_buffer, mark_active))
2059 && XMARKER (BVAR (current_buffer, mark))->buffer
2060 && NILP (Vsaved_region_selection)
2061 && (EQ (Vselect_active_regions, Qonly)
2062 ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly)
2063 : (!NILP (Vselect_active_regions)
2064 && !NILP (Vtransient_mark_mode))))
2065 Vsaved_region_selection
2066 = call1 (Vregion_extract_function, Qnil);
2067
2068 signal_before_change (start, end, preserve_ptr);
2069 Fset (Qdeactivate_mark, Qt);
2070 }
2071
2072
2073
2074
2075 void
2076 prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
2077 ptrdiff_t *preserve_ptr)
2078 {
2079 prepare_to_modify_buffer_1 (start, end, preserve_ptr);
2080 invalidate_buffer_caches (current_buffer, start, end);
2081 }
2082
2083
2084
2085 void
2086 invalidate_buffer_caches (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
2087 {
2088
2089
2090 if (buf->base_buffer)
2091 buf = buf->base_buffer;
2092
2093
2094
2095 if (buf->bidi_paragraph_cache)
2096 {
2097 if (start > BUF_BEG (buf))
2098 {
2099
2100
2101
2102
2103
2104
2105
2106
2107 ptrdiff_t line_beg = start;
2108 ptrdiff_t start_byte = buf_charpos_to_bytepos (buf, start);
2109 int prev_char = BUF_FETCH_BYTE (buf, start_byte - 1);
2110
2111 if ((start == end) == (prev_char == '\n'))
2112 {
2113 struct buffer *old = current_buffer;
2114
2115 set_buffer_internal (buf);
2116
2117 line_beg = find_newline_no_quit (start, start_byte, -1,
2118 &start_byte);
2119 set_buffer_internal (old);
2120 }
2121 start = line_beg - (line_beg > BUF_BEG (buf));
2122 }
2123 invalidate_region_cache (buf,
2124 buf->bidi_paragraph_cache,
2125 start - BUF_BEG (buf), BUF_Z (buf) - end);
2126 }
2127 if (buf->newline_cache)
2128 invalidate_region_cache (buf,
2129 buf->newline_cache,
2130 start - BUF_BEG (buf), BUF_Z (buf) - end);
2131 if (buf->width_run_cache)
2132 invalidate_region_cache (buf,
2133 buf->width_run_cache,
2134 start - BUF_BEG (buf), BUF_Z (buf) - end);
2135 }
2136
2137
2138
2139
2140 #define PRESERVE_VALUE \
2141 if (preserve_ptr && NILP (preserve_marker)) \
2142 preserve_marker = Fcopy_marker (make_fixnum (*preserve_ptr), Qnil)
2143
2144 #define RESTORE_VALUE \
2145 if (! NILP (preserve_marker)) \
2146 { \
2147 *preserve_ptr = marker_position (preserve_marker); \
2148 unchain_marker (XMARKER (preserve_marker)); \
2149 }
2150
2151 #define PRESERVE_START_END \
2152 if (NILP (start_marker)) \
2153 start_marker = Fcopy_marker (start, Qnil); \
2154 if (NILP (end_marker)) \
2155 end_marker = Fcopy_marker (end, Qnil);
2156
2157 #define FETCH_START \
2158 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
2159
2160 #define FETCH_END \
2161 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
2162
2163
2164
2165
2166
2167
2168
2169 struct rvoe_arg
2170 {
2171 Lisp_Object *location;
2172 bool errorp;
2173 };
2174
2175 static void
2176 reset_var_on_error (void *ptr)
2177 {
2178 struct rvoe_arg *p = ptr;
2179 if (p->errorp)
2180 *p->location = Qnil;
2181 }
2182
2183
2184
2185
2186
2187
2188
2189 static void
2190 signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int,
2191 ptrdiff_t *preserve_ptr)
2192 {
2193 Lisp_Object start, end;
2194 Lisp_Object start_marker, end_marker;
2195 Lisp_Object preserve_marker;
2196 specpdl_ref count = SPECPDL_INDEX ();
2197 struct rvoe_arg rvoe_arg;
2198
2199 start = make_fixnum (start_int);
2200 end = make_fixnum (end_int);
2201 preserve_marker = Qnil;
2202 start_marker = Qnil;
2203 end_marker = Qnil;
2204
2205 specbind (Qinhibit_modification_hooks, Qt);
2206
2207
2208
2209 if (SAVE_MODIFF >= MODIFF
2210 && !NILP (Vfirst_change_hook))
2211 {
2212 PRESERVE_VALUE;
2213 PRESERVE_START_END;
2214 run_hook (Qfirst_change_hook);
2215 }
2216
2217
2218 if (!NILP (Vbefore_change_functions))
2219 {
2220 rvoe_arg.location = &Vbefore_change_functions;
2221 rvoe_arg.errorp = 1;
2222
2223 PRESERVE_VALUE;
2224 PRESERVE_START_END;
2225
2226
2227 record_unwind_protect_ptr (reset_var_on_error, &rvoe_arg);
2228
2229
2230 CALLN (Frun_hook_with_args, Qbefore_change_functions,
2231 FETCH_START, FETCH_END);
2232
2233
2234 rvoe_arg.errorp = 0;
2235 }
2236
2237 if (buffer_has_overlays ())
2238 {
2239 PRESERVE_VALUE;
2240 report_overlay_modification (FETCH_START, FETCH_END, 0,
2241 FETCH_START, FETCH_END, Qnil);
2242 }
2243
2244 if (! NILP (start_marker))
2245 detach_marker (start_marker);
2246 if (! NILP (end_marker))
2247 detach_marker (end_marker);
2248 RESTORE_VALUE;
2249
2250 unbind_to (count, Qnil);
2251 }
2252
2253
2254
2255
2256
2257
2258
2259
2260 void
2261 signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
2262 {
2263 specpdl_ref count = SPECPDL_INDEX ();
2264 struct rvoe_arg rvoe_arg;
2265 Lisp_Object tmp, save_insert_behind_hooks, save_insert_in_from_hooks;
2266
2267 if (inhibit_modification_hooks)
2268 return;
2269
2270
2271
2272
2273 if (! NILP (Vcombine_after_change_calls)
2274
2275
2276
2277 && (NILP (Vbefore_change_functions)
2278 || (CONSP (Vbefore_change_functions)
2279 && EQ (Qt, XCAR (Vbefore_change_functions))
2280 && NILP (Fdefault_value (Qbefore_change_functions))
2281 && CONSP (tmp = XCDR (Vbefore_change_functions))
2282 && NILP (XCDR (tmp))
2283 && EQ (XCAR (tmp), Qsyntax_ppss_flush_cache)))
2284 && !buffer_has_overlays ())
2285 {
2286 Lisp_Object elt;
2287
2288 if (!NILP (combine_after_change_list)
2289 && current_buffer != XBUFFER (combine_after_change_buffer))
2290 Fcombine_after_change_execute ();
2291
2292 elt = list3i (charpos - BEG, Z - (charpos - lendel + lenins),
2293 lenins - lendel);
2294 combine_after_change_list
2295 = Fcons (elt, combine_after_change_list);
2296 combine_after_change_buffer = Fcurrent_buffer ();
2297
2298 return;
2299 }
2300
2301
2302
2303
2304 save_insert_behind_hooks = interval_insert_behind_hooks;
2305 save_insert_in_from_hooks = interval_insert_in_front_hooks;
2306
2307 if (!NILP (combine_after_change_list))
2308 Fcombine_after_change_execute ();
2309
2310 specbind (Qinhibit_modification_hooks, Qt);
2311
2312 if (!NILP (Vafter_change_functions))
2313 {
2314 rvoe_arg.location = &Vafter_change_functions;
2315 rvoe_arg.errorp = 1;
2316
2317
2318 record_unwind_protect_ptr (reset_var_on_error, &rvoe_arg);
2319
2320
2321 CALLN (Frun_hook_with_args, Qafter_change_functions,
2322 make_fixnum (charpos), make_fixnum (charpos + lenins),
2323 make_fixnum (lendel));
2324
2325
2326 rvoe_arg.errorp = 0;
2327 }
2328
2329 interval_insert_behind_hooks = save_insert_behind_hooks;
2330 interval_insert_in_front_hooks = save_insert_in_from_hooks;
2331
2332 if (buffer_has_overlays ())
2333 report_overlay_modification (make_fixnum (charpos),
2334 make_fixnum (charpos + lenins),
2335 1,
2336 make_fixnum (charpos),
2337 make_fixnum (charpos + lenins),
2338 make_fixnum (lendel));
2339
2340
2341
2342 if (lendel == 0)
2343 report_interval_modification (make_fixnum (charpos),
2344 make_fixnum (charpos + lenins));
2345
2346 unbind_to (count, Qnil);
2347 }
2348
2349 static void
2350 Fcombine_after_change_execute_1 (Lisp_Object val)
2351 {
2352 Vcombine_after_change_calls = val;
2353 }
2354
2355 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2356 Scombine_after_change_execute, 0, 0, 0,
2357 doc: )
2358 (void)
2359 {
2360 specpdl_ref count = SPECPDL_INDEX ();
2361 ptrdiff_t beg, end, change;
2362 ptrdiff_t begpos, endpos;
2363 Lisp_Object tail;
2364
2365 if (NILP (combine_after_change_list))
2366 return Qnil;
2367
2368
2369
2370
2371
2372 if (!BUFFERP (combine_after_change_buffer)
2373 || !BUFFER_LIVE_P (XBUFFER (combine_after_change_buffer)))
2374 {
2375 combine_after_change_list = Qnil;
2376 return Qnil;
2377 }
2378
2379 record_unwind_current_buffer ();
2380
2381 Fset_buffer (combine_after_change_buffer);
2382
2383
2384 beg = Z - BEG;
2385
2386 end = beg;
2387
2388 change = 0;
2389
2390
2391
2392 for (tail = combine_after_change_list; CONSP (tail);
2393 tail = XCDR (tail))
2394 {
2395 Lisp_Object elt;
2396 ptrdiff_t thisbeg, thisend, thischange;
2397
2398
2399 elt = XCAR (tail);
2400 if (! CONSP (elt))
2401 continue;
2402 thisbeg = XFIXNUM (XCAR (elt));
2403
2404 elt = XCDR (elt);
2405 if (! CONSP (elt))
2406 continue;
2407 thisend = XFIXNUM (XCAR (elt));
2408
2409 elt = XCDR (elt);
2410 if (! CONSP (elt))
2411 continue;
2412 thischange = XFIXNUM (XCAR (elt));
2413
2414
2415 change += thischange;
2416 if (thisbeg < beg)
2417 beg = thisbeg;
2418 if (thisend < end)
2419 end = thisend;
2420 }
2421
2422
2423
2424 begpos = BEG + beg;
2425 endpos = Z - end;
2426
2427
2428 combine_after_change_list = Qnil;
2429
2430
2431
2432 record_unwind_protect (Fcombine_after_change_execute_1,
2433 Vcombine_after_change_calls);
2434 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
2435 update_compositions (begpos, endpos, CHECK_ALL);
2436
2437 return unbind_to (count, Qnil);
2438 }
2439
2440 void
2441 syms_of_insdel (void)
2442 {
2443 staticpro (&combine_after_change_list);
2444 staticpro (&combine_after_change_buffer);
2445 combine_after_change_list = Qnil;
2446 combine_after_change_buffer = Qnil;
2447
2448 DEFSYM (Qundo_auto__undoable_change, "undo-auto--undoable-change");
2449 DEFSYM (Qsyntax_ppss_flush_cache, "syntax-ppss-flush-cache");
2450
2451 DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls,
2452 doc: );
2453 Vcombine_after_change_calls = Qnil;
2454
2455 DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
2456 doc:
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467 );
2468 inhibit_modification_hooks = 0;
2469 DEFSYM (Qinhibit_modification_hooks, "inhibit-modification-hooks");
2470
2471 defsubr (&Scombine_after_change_execute);
2472 }