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