(window_loop) <GET_BUFFER_WINDOW>: Prefer to return
[bpt/emacs.git] / src / insdel.c
CommitLineData
b45433b3 1/* Buffer insertion/deletion and gap motion for GNU Emacs.
00de2987 2 Copyright (C) 1985, 86,93,94,95,97,98, 1999, 2000 Free Software Foundation, Inc.
b45433b3
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
7c938215 8the Free Software Foundation; either version 2, or (at your option)
b45433b3
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
b45433b3
JB
20
21
18160b98 22#include <config.h>
b45433b3 23#include "lisp.h"
679194a6 24#include "intervals.h"
b45433b3 25#include "buffer.h"
469ff680 26#include "charset.h"
b45433b3 27#include "window.h"
d014bf88 28#include "blockinput.h"
dfcf069d 29#include "region-cache.h"
b45433b3 30
d206af14
RS
31#ifndef NULL
32#define NULL 0
33#endif
34
14f6194b 35#define min(x, y) ((x) < (y) ? (x) : (y))
2e9f55fd 36#define max(x, y) ((x) > (y) ? (x) : (y))
14f6194b 37
2b083808 38static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int, int));
ef29f213 39static void insert_from_buffer_1 ();
3be11131
RS
40static void gap_left P_ ((int, int, int));
41static void gap_right P_ ((int, int));
42static void adjust_markers_gap_motion P_ ((int, int, int));
b16afa45 43static void adjust_markers_for_insert P_ ((int, int, int, int, int));
809f3d51 44void adjust_markers_for_delete P_ ((int, int, int, int));
b16afa45 45static void adjust_markers_for_replace P_ ((int, int, int, int, int, int));
3be11131 46static void adjust_point P_ ((int, int));
395ec62e 47
fb2e7d14
RS
48Lisp_Object Fcombine_after_change_execute ();
49
50/* Non-nil means don't call the after-change-functions right away,
51 just record an element in Vcombine_after_change_calls_list. */
52Lisp_Object Vcombine_after_change_calls;
53
54/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
55 describing changes which happened while combine_after_change_calls
56 was nonzero. We use this to decide how to call them
57 once the deferral ends.
58
59 In each element.
60 BEG-UNCHANGED is the number of chars before the changed range.
61 END-UNCHANGED is the number of chars after the changed range,
62 and CHANGE-AMOUNT is the number of characters inserted by the change
63 (negative for a deletion). */
64Lisp_Object combine_after_change_list;
65
66/* Buffer which combine_after_change_list is about. */
67Lisp_Object combine_after_change_buffer;
2b083808 68\f
60ea6052
RS
69/* Check all markers in the current buffer, looking for something invalid. */
70
71static int check_markers_debug_flag;
72
73#define CHECK_MARKERS() \
74 if (check_markers_debug_flag) \
75 check_markers (); \
76 else
77
78void
79check_markers ()
80{
6021f7c5 81 register Lisp_Object tail;
9f3ede3c 82 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
60ea6052
RS
83
84 tail = BUF_MARKERS (current_buffer);
85
8801a864 86 while (! NILP (tail))
60ea6052
RS
87 {
88 if (XMARKER (tail)->buffer->text != current_buffer->text)
89 abort ();
90 if (XMARKER (tail)->charpos > Z)
91 abort ();
92 if (XMARKER (tail)->bytepos > Z_BYTE)
93 abort ();
9f3ede3c
KH
94 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (XMARKER (tail)->bytepos)))
95 abort ();
60ea6052
RS
96
97 tail = XMARKER (tail)->chain;
98 }
99}
100\f
3be11131 101/* Move gap to position CHARPOS.
b45433b3
JB
102 Note that this can quit! */
103
c660b094 104void
3be11131
RS
105move_gap (charpos)
106 int charpos;
b45433b3 107{
3be11131 108 move_gap_both (charpos, charpos_to_bytepos (charpos));
b45433b3
JB
109}
110
3be11131
RS
111/* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
112 Note that this can quit! */
113
114void
115move_gap_both (charpos, bytepos)
116 int charpos, bytepos;
117{
118 if (bytepos < GPT_BYTE)
119 gap_left (charpos, bytepos, 0);
120 else if (bytepos > GPT_BYTE)
121 gap_right (charpos, bytepos);
122}
123
124/* Move the gap to a position less than the current GPT.
125 BYTEPOS describes the new position as a byte position,
126 and CHARPOS is the corresponding char position.
b45433b3
JB
127 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
128
2bcaed71 129static void
3be11131
RS
130gap_left (charpos, bytepos, newgap)
131 register int charpos, bytepos;
b45433b3
JB
132 int newgap;
133{
134 register unsigned char *to, *from;
135 register int i;
136 int new_s1;
137
b45433b3 138 if (!newgap)
a50df55b 139 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
b45433b3 140
3be11131 141 i = GPT_BYTE;
b45433b3
JB
142 to = GAP_END_ADDR;
143 from = GPT_ADDR;
3be11131 144 new_s1 = GPT_BYTE;
b45433b3
JB
145
146 /* Now copy the characters. To move the gap down,
147 copy characters up. */
148
149 while (1)
150 {
151 /* I gets number of characters left to copy. */
3be11131 152 i = new_s1 - bytepos;
b45433b3
JB
153 if (i == 0)
154 break;
155 /* If a quit is requested, stop copying now.
3be11131 156 Change BYTEPOS to be where we have actually moved the gap to. */
b45433b3
JB
157 if (QUITP)
158 {
3be11131
RS
159 bytepos = new_s1;
160 charpos = BYTE_TO_CHAR (bytepos);
b45433b3
JB
161 break;
162 }
163 /* Move at most 32000 chars before checking again for a quit. */
164 if (i > 32000)
165 i = 32000;
166#ifdef GAP_USE_BCOPY
167 if (i >= 128
168 /* bcopy is safe if the two areas of memory do not overlap
169 or on systems where bcopy is always safe for moving upward. */
170 && (BCOPY_UPWARD_SAFE
171 || to - from >= 128))
172 {
173 /* If overlap is not safe, avoid it by not moving too many
174 characters at once. */
175 if (!BCOPY_UPWARD_SAFE && i > to - from)
176 i = to - from;
177 new_s1 -= i;
178 from -= i, to -= i;
179 bcopy (from, to, i);
180 }
181 else
182#endif
183 {
184 new_s1 -= i;
185 while (--i >= 0)
186 *--to = *--from;
187 }
188 }
189
3be11131
RS
190 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
191 BYTEPOS is where the loop above stopped, which may be what was specified
b45433b3 192 or may be where a quit was detected. */
3be11131
RS
193 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
194 GPT_BYTE = bytepos;
195 GPT = charpos;
196 if (bytepos < charpos)
197 abort ();
469ff680 198 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
199 QUIT;
200}
201
3be11131
RS
202/* Move the gap to a position greater than than the current GPT.
203 BYTEPOS describes the new position as a byte position,
204 and CHARPOS is the corresponding char position. */
205
2bcaed71 206static void
3be11131
RS
207gap_right (charpos, bytepos)
208 register int charpos, bytepos;
b45433b3
JB
209{
210 register unsigned char *to, *from;
211 register int i;
212 int new_s1;
213
a50df55b 214 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
b45433b3 215
3be11131 216 i = GPT_BYTE;
b45433b3
JB
217 from = GAP_END_ADDR;
218 to = GPT_ADDR;
3be11131 219 new_s1 = GPT_BYTE;
b45433b3
JB
220
221 /* Now copy the characters. To move the gap up,
222 copy characters down. */
223
224 while (1)
225 {
226 /* I gets number of characters left to copy. */
3be11131 227 i = bytepos - new_s1;
b45433b3
JB
228 if (i == 0)
229 break;
230 /* If a quit is requested, stop copying now.
3be11131 231 Change BYTEPOS to be where we have actually moved the gap to. */
b45433b3
JB
232 if (QUITP)
233 {
3be11131
RS
234 bytepos = new_s1;
235 charpos = BYTE_TO_CHAR (bytepos);
b45433b3
JB
236 break;
237 }
238 /* Move at most 32000 chars before checking again for a quit. */
239 if (i > 32000)
240 i = 32000;
241#ifdef GAP_USE_BCOPY
242 if (i >= 128
243 /* bcopy is safe if the two areas of memory do not overlap
244 or on systems where bcopy is always safe for moving downward. */
245 && (BCOPY_DOWNWARD_SAFE
246 || from - to >= 128))
247 {
248 /* If overlap is not safe, avoid it by not moving too many
249 characters at once. */
250 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
251 i = from - to;
252 new_s1 += i;
253 bcopy (from, to, i);
254 from += i, to += i;
255 }
256 else
257#endif
258 {
259 new_s1 += i;
260 while (--i >= 0)
261 *to++ = *from++;
262 }
263 }
264
3be11131
RS
265 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
266 - GAP_SIZE);
267 GPT = charpos;
268 GPT_BYTE = bytepos;
269 if (bytepos < charpos)
270 abort ();
469ff680 271 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
272 QUIT;
273}
2b083808 274\f
3be11131
RS
275/* Add AMOUNT to the byte position of every marker in the current buffer
276 whose current byte position is between FROM (exclusive) and TO (inclusive).
8948d317 277
b45433b3
JB
278 Also, any markers past the outside of that interval, in the direction
279 of adjustment, are first moved back to the near end of the interval
8948d317
RS
280 and then adjusted by AMOUNT.
281
282 When the latter adjustment is done, if AMOUNT is negative,
283 we record the adjustment for undo. (This case happens only for
3be11131
RS
284 deletion.)
285
286 The markers' character positions are not altered,
287 because gap motion does not affect character positions. */
288
289int adjust_markers_test;
b45433b3 290
2bcaed71 291static void
3be11131 292adjust_markers_gap_motion (from, to, amount)
b45433b3
JB
293 register int from, to, amount;
294{
80f6e77c
RS
295 /* Now that a marker has a bytepos, not counting the gap,
296 nothing needs to be done here. */
297#if 0
b45433b3
JB
298 Lisp_Object marker;
299 register struct Lisp_Marker *m;
300 register int mpos;
301
9fbf87cd 302 marker = BUF_MARKERS (current_buffer);
b45433b3 303
d427b66a 304 while (!NILP (marker))
b45433b3
JB
305 {
306 m = XMARKER (marker);
80f6e77c 307 mpos = m->bytepos;
b45433b3
JB
308 if (amount > 0)
309 {
310 if (mpos > to && mpos < to + amount)
3be11131
RS
311 {
312 if (adjust_markers_test)
313 abort ();
314 mpos = to + amount;
315 }
b45433b3
JB
316 }
317 else
318 {
8948d317
RS
319 /* Here's the case where a marker is inside text being deleted.
320 AMOUNT can be negative for gap motion, too,
321 but then this range contains no markers. */
b45433b3 322 if (mpos > from + amount && mpos <= from)
8948d317 323 {
3be11131
RS
324 if (adjust_markers_test)
325 abort ();
326 mpos = from + amount;
8948d317 327 }
b45433b3
JB
328 }
329 if (mpos > from && mpos <= to)
330 mpos += amount;
331 m->bufpos = mpos;
332 marker = m->chain;
333 }
80f6e77c 334#endif
b45433b3 335}
2b083808 336\f
3be11131
RS
337/* Adjust all markers for a deletion
338 whose range in bytes is FROM_BYTE to TO_BYTE.
339 The range in charpos is FROM to TO.
340
341 This function assumes that the gap is adjacent to
342 or inside of the range being deleted. */
beecb55b 343
809f3d51 344void
3be11131
RS
345adjust_markers_for_delete (from, from_byte, to, to_byte)
346 register int from, from_byte, to, to_byte;
347{
348 Lisp_Object marker;
349 register struct Lisp_Marker *m;
350 register int charpos;
3be11131
RS
351
352 marker = BUF_MARKERS (current_buffer);
353
354 while (!NILP (marker))
355 {
356 m = XMARKER (marker);
357 charpos = m->charpos;
358
359 if (charpos > Z)
360 abort ();
361
362 /* If the marker is after the deletion,
80f6e77c 363 relocate by number of chars / bytes deleted. */
3be11131 364 if (charpos > to)
80f6e77c
RS
365 {
366 m->charpos -= to - from;
367 m->bytepos -= to_byte - from_byte;
368 }
80f6e77c 369 /* Here's the case where a marker is inside text being deleted. */
3be11131
RS
370 else if (charpos > from)
371 {
00de2987
MB
372 if (! m->insertion_type)
373 /* Normal markers will end up at the beginning of the
374 re-inserted text after undoing a deletion, and must be
375 adjusted to move them to the correct place. */
376 record_marker_adjustment (marker, from - charpos);
377 else if (charpos < to)
378 /* Before-insertion markers will automatically move forward
379 upon re-inserting the deleted text, so we have to arrange
380 for them to move backward to the correct position. */
381 record_marker_adjustment (marker, charpos - to);
382
3be11131 383 m->charpos = from;
80f6e77c 384 m->bytepos = from_byte;
3be11131 385 }
00de2987
MB
386 /* Here's the case where a before-insertion marker is immediately
387 before the deleted region. */
388 else if (charpos == from && m->insertion_type)
389 {
390 /* Undoing the change uses normal insertion, which will
391 incorrectly make MARKER move forward, so we arrange for it
392 to then move backward to the correct place at the beginning
393 of the deleted region. */
394 record_marker_adjustment (marker, to - from);
395 }
3be11131 396
3be11131
RS
397 marker = m->chain;
398 }
399}
23b20a70 400
2b083808 401\f
432f78d2
RS
402/* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
403 to TO / TO_BYTE. We have to relocate the charpos of every marker
404 that points after the insertion (but not their bytepos).
3be11131 405
3be11131
RS
406 When a marker points at the insertion point,
407 we advance it if either its insertion-type is t
408 or BEFORE_MARKERS is true. */
409
410static void
b16afa45 411adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
432f78d2 412 register int from, from_byte, to, to_byte;
b16afa45 413 int before_markers;
beecb55b
RS
414{
415 Lisp_Object marker;
469ff680 416 int adjusted = 0;
3be11131
RS
417 int nchars = to - from;
418 int nbytes = to_byte - from_byte;
beecb55b
RS
419
420 marker = BUF_MARKERS (current_buffer);
421
422 while (!NILP (marker))
423 {
424 register struct Lisp_Marker *m = XMARKER (marker);
1f90a790 425
b16afa45
KH
426 /* In a single-byte buffer, a marker's two positions must be
427 equal. */
1f90a790
RS
428 if (Z == Z_BYTE)
429 {
430 if (m->charpos != m->bytepos)
431 abort ();
432 }
433
432f78d2 434 if (m->bytepos == from_byte)
469ff680 435 {
432f78d2
RS
436 if (m->insertion_type || before_markers)
437 {
b16afa45
KH
438 m->bytepos = to_byte;
439 m->charpos = to;
432f78d2
RS
440 if (m->insertion_type)
441 adjusted = 1;
442 }
ce97a2d7 443 }
80f6e77c
RS
444 else if (m->bytepos > from_byte)
445 {
446 m->bytepos += nbytes;
b16afa45 447 m->charpos += nchars;
80f6e77c 448 }
3be11131 449
beecb55b
RS
450 marker = m->chain;
451 }
3be11131
RS
452
453 /* Adjusting only markers whose insertion-type is t may result in
454 disordered overlays in the slot `overlays_before'. */
469ff680 455 if (adjusted)
3be11131 456 fix_overlays_before (current_buffer, from, to);
beecb55b
RS
457}
458
3be11131
RS
459/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
460
461 This is used only when the value of point changes due to an insert
462 or delete; it does not represent a conceptual change in point as a
463 marker. In particular, point is not crossing any interval
464 boundaries, so there's no need to use the usual SET_PT macro. In
465 fact it would be incorrect to do so, because either the old or the
466 new value of point is out of sync with the current set of
467 intervals. */
468
a27a38d8 469static void
3be11131
RS
470adjust_point (nchars, nbytes)
471 int nchars, nbytes;
a27a38d8 472{
3be11131
RS
473 BUF_PT (current_buffer) += nchars;
474 BUF_PT_BYTE (current_buffer) += nbytes;
475
476 /* In a single-byte buffer, the two positions must be equal. */
477 if (ZV == ZV_BYTE
478 && PT != PT_BYTE)
479 abort ();
a27a38d8 480}
b45433b3 481\f
652838b5
KH
482/* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
483 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
adee4f91
KH
484 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
485 an insertion. */
652838b5
KH
486
487static void
488adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
b16afa45 489 new_chars, new_bytes)
652838b5 490 int from, from_byte, old_chars, old_bytes, new_chars, new_bytes;
652838b5
KH
491{
492 Lisp_Object marker = BUF_MARKERS (current_buffer);
493 int prev_to_byte = from_byte + old_bytes;
b16afa45 494 int diff_chars = new_chars - old_chars;
652838b5
KH
495 int diff_bytes = new_bytes - old_bytes;
496
497 while (!NILP (marker))
498 {
499 register struct Lisp_Marker *m = XMARKER (marker);
500
adee4f91 501 if (m->bytepos >= prev_to_byte)
652838b5 502 {
adee4f91
KH
503 m->charpos += diff_chars;
504 m->bytepos += diff_bytes;
652838b5 505 }
adee4f91 506 else if (m->bytepos > from_byte)
652838b5 507 {
652838b5 508 m->charpos = from;
b16afa45 509 m->bytepos = from_byte;
652838b5 510 }
652838b5
KH
511
512 marker = m->chain;
513 }
3019692c
KH
514
515 CHECK_MARKERS ();
652838b5
KH
516}
517
518\f
3be11131 519/* Make the gap NBYTES_ADDED bytes longer. */
b45433b3 520
c660b094 521void
3be11131
RS
522make_gap (nbytes_added)
523 int nbytes_added;
b45433b3 524{
b45433b3
JB
525 Lisp_Object tem;
526 int real_gap_loc;
3be11131 527 int real_gap_loc_byte;
b45433b3
JB
528 int old_gap_size;
529
530 /* If we have to get more space, get enough to last a while. */
3be11131 531 nbytes_added += 2000;
b45433b3 532
94056516
RS
533 /* Don't allow a buffer size that won't fit in an int
534 even if it will fit in a Lisp integer.
535 That won't work because so many places use `int'. */
536
3be11131 537 if (Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added
68be917d 538 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
14f6194b 539 error ("Buffer exceeds maximum size");
94056516 540
71a7bfa7 541 enlarge_buffer_text (current_buffer, nbytes_added);
b45433b3
JB
542
543 /* Prevent quitting in move_gap. */
544 tem = Vinhibit_quit;
545 Vinhibit_quit = Qt;
546
547 real_gap_loc = GPT;
3be11131 548 real_gap_loc_byte = GPT_BYTE;
b45433b3
JB
549 old_gap_size = GAP_SIZE;
550
551 /* Call the newly allocated space a gap at the end of the whole space. */
552 GPT = Z + GAP_SIZE;
7d92db58 553 GPT_BYTE = Z_BYTE + GAP_SIZE;
3be11131 554 GAP_SIZE = nbytes_added;
b45433b3
JB
555
556 /* Move the new gap down to be consecutive with the end of the old one.
557 This adjusts the markers properly too. */
3be11131 558 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
b45433b3
JB
559
560 /* Now combine the two into one large gap. */
561 GAP_SIZE += old_gap_size;
562 GPT = real_gap_loc;
3be11131 563 GPT_BYTE = real_gap_loc_byte;
b45433b3 564
469ff680
KH
565 /* Put an anchor. */
566 *(Z_ADDR) = 0;
567
b45433b3
JB
568 Vinhibit_quit = tem;
569}
570\f
2b083808
RS
571/* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
572 FROM_MULTIBYTE says whether the incoming text is multibyte.
573 TO_MULTIBYTE says whether to store the text as multibyte.
574 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
575
576 Return the number of bytes stored at TO_ADDR. */
577
578int
579copy_text (from_addr, to_addr, nbytes,
580 from_multibyte, to_multibyte)
581 unsigned char *from_addr;
582 unsigned char *to_addr;
583 int nbytes;
584 int from_multibyte, to_multibyte;
585{
586 if (from_multibyte == to_multibyte)
587 {
588 bcopy (from_addr, to_addr, nbytes);
589 return nbytes;
590 }
591 else if (from_multibyte)
592 {
593 int nchars = 0;
594 int bytes_left = nbytes;
6021f7c5 595 Lisp_Object tbl = Qnil;
f44cbcd8
KH
596
597 /* We set the variable tbl to the reverse table of
598 Vnonascii_translation_table in advance. */
599 if (CHAR_TABLE_P (Vnonascii_translation_table))
600 {
601 tbl = Fchar_table_extra_slot (Vnonascii_translation_table,
602 make_number (0));
603 if (!CHAR_TABLE_P (tbl))
604 tbl = Qnil;
605 }
2b083808
RS
606
607 /* Convert multibyte to single byte. */
608 while (bytes_left > 0)
609 {
b16afa45
KH
610 int thislen, c;
611 c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen);
f44cbcd8 612 if (!SINGLE_BYTE_CHAR_P (c))
4ec36780 613 c = multibyte_char_to_unibyte (c, tbl);
f44cbcd8 614 *to_addr++ = c;
2b083808 615 from_addr += thislen;
7e79b8e0 616 bytes_left -= thislen;
2b083808
RS
617 nchars++;
618 }
619 return nchars;
620 }
621 else
622 {
623 unsigned char *initial_to_addr = to_addr;
624
625 /* Convert single-byte to multibyte. */
626 while (nbytes > 0)
627 {
628 int c = *from_addr++;
2b083808 629
b16afa45 630 if (c >= 0200)
2b083808 631 {
59a52d50 632 c = unibyte_char_to_multibyte (c);
0ef71121 633 to_addr += CHAR_STRING (c, to_addr);
2b083808
RS
634 nbytes--;
635 }
636 else
637 /* Special case for speed. */
638 *to_addr++ = c, nbytes--;
639 }
640 return to_addr - initial_to_addr;
641 }
642}
643
644/* Return the number of bytes it would take
645 to convert some single-byte text to multibyte.
646 The single-byte text consists of NBYTES bytes at PTR. */
647
648int
649count_size_as_multibyte (ptr, nbytes)
650 unsigned char *ptr;
651 int nbytes;
652{
653 int i;
654 int outgoing_nbytes = 0;
655
656 for (i = 0; i < nbytes; i++)
657 {
658 unsigned int c = *ptr++;
59a52d50 659
b16afa45 660 if (c < 0200)
59a52d50
KH
661 outgoing_nbytes++;
662 else
2b083808 663 {
59a52d50 664 c = unibyte_char_to_multibyte (c);
643044eb 665 outgoing_nbytes += CHAR_BYTES (c);
2b083808 666 }
2b083808
RS
667 }
668
669 return outgoing_nbytes;
670}
671\f
b45433b3 672/* Insert a string of specified length before point.
2b083808
RS
673 This function judges multibyteness based on
674 enable_multibyte_characters in the current buffer;
675 it never converts between single-byte and multibyte.
676
ef29f213
KH
677 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
678 prepare_to_modify_buffer could relocate the text. */
b45433b3 679
c660b094 680void
3be11131 681insert (string, nbytes)
b45433b3 682 register unsigned char *string;
dfcf069d 683 register int nbytes;
b45433b3 684{
3be11131 685 if (nbytes > 0)
395ec62e 686 {
3be11131
RS
687 int opoint = PT;
688 insert_1 (string, nbytes, 0, 1, 0);
689 signal_after_change (opoint, 0, PT - opoint);
0ef71121 690 update_compositions (opoint, PT, CHECK_BORDER);
cd11ef31
RS
691 }
692}
693
2b083808
RS
694/* Likewise, but inherit text properties from neighboring characters. */
695
c660b094 696void
3be11131 697insert_and_inherit (string, nbytes)
cd11ef31 698 register unsigned char *string;
dfcf069d 699 register int nbytes;
cd11ef31 700{
3be11131 701 if (nbytes > 0)
cd11ef31 702 {
3be11131
RS
703 int opoint = PT;
704 insert_1 (string, nbytes, 1, 1, 0);
705 signal_after_change (opoint, 0, PT - opoint);
0ef71121 706 update_compositions (opoint, PT, CHECK_BORDER);
395ec62e
KH
707 }
708}
b45433b3 709
2b083808 710/* Insert the character C before point. Do not inherit text properties. */
3be11131 711
c660b094 712void
3be11131
RS
713insert_char (c)
714 int c;
715{
0ef71121 716 unsigned char str[MAX_MULTIBYTE_LENGTH];
2b083808
RS
717 int len;
718
719 if (! NILP (current_buffer->enable_multibyte_characters))
0ef71121 720 len = CHAR_STRING (c, str);
2b083808
RS
721 else
722 {
723 len = 1;
0ef71121 724 str[0] = c;
2b083808 725 }
3be11131
RS
726
727 insert (str, len);
728}
729
2b083808 730/* Insert the null-terminated string S before point. */
3be11131
RS
731
732void
733insert_string (s)
734 char *s;
735{
736 insert (s, strlen (s));
737}
738
739/* Like `insert' except that all markers pointing at the place where
740 the insertion happens are adjusted to point after it.
741 Don't use this function to insert part of a Lisp string,
742 since gc could happen and relocate it. */
743
744void
745insert_before_markers (string, nbytes)
746 unsigned char *string;
747 register int nbytes;
748{
749 if (nbytes > 0)
750 {
751 int opoint = PT;
752
753 insert_1 (string, nbytes, 0, 1, 1);
754 signal_after_change (opoint, 0, PT - opoint);
0ef71121 755 update_compositions (opoint, PT, CHECK_BORDER);
3be11131
RS
756 }
757}
758
2b083808
RS
759/* Likewise, but inherit text properties from neighboring characters. */
760
3be11131
RS
761void
762insert_before_markers_and_inherit (string, nbytes)
763 unsigned char *string;
764 register int nbytes;
765{
766 if (nbytes > 0)
767 {
768 int opoint = PT;
769
770 insert_1 (string, nbytes, 1, 1, 1);
771 signal_after_change (opoint, 0, PT - opoint);
0ef71121 772 update_compositions (opoint, PT, CHECK_BORDER);
3be11131
RS
773 }
774}
1f90a790 775
3be11131
RS
776/* Subroutine used by the insert functions above. */
777
778void
779insert_1 (string, nbytes, inherit, prepare, before_markers)
395ec62e 780 register unsigned char *string;
3be11131
RS
781 register int nbytes;
782 int inherit, prepare, before_markers;
395ec62e 783{
432f78d2
RS
784 insert_1_both (string, chars_in_text (string, nbytes), nbytes,
785 inherit, prepare, before_markers);
786}
b16afa45 787
1f90a790 788\f
b16afa45
KH
789#ifdef BYTE_COMBINING_DEBUG
790
432f78d2
RS
791/* See if the bytes before POS/POS_BYTE combine with bytes
792 at the start of STRING to form a single character.
ce97a2d7 793 If so, return the number of bytes at the start of STRING
432f78d2 794 which combine in this way. Otherwise, return 0. */
b45433b3 795
432f78d2
RS
796int
797count_combining_before (string, length, pos, pos_byte)
798 unsigned char *string;
799 int length;
800 int pos, pos_byte;
801{
cae184f2
KH
802 int len, combining_bytes;
803 unsigned char *p;
b45433b3 804
432f78d2
RS
805 if (NILP (current_buffer->enable_multibyte_characters))
806 return 0;
cae184f2
KH
807
808 /* At first, we can exclude the following cases:
809 (1) STRING[0] can't be a following byte of multibyte sequence.
810 (2) POS is the start of the current buffer.
811 (3) A character before POS is not a multibyte character. */
812 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
432f78d2 813 return 0;
cae184f2 814 if (pos_byte == BEG_BYTE) /* case (2) */
432f78d2 815 return 0;
cae184f2
KH
816 len = 1;
817 p = BYTE_POS_ADDR (pos_byte - 1);
818 while (! CHAR_HEAD_P (*p)) p--, len++;
819 if (! BASE_LEADING_CODE_P (*p)) /* case (3) */
432f78d2 820 return 0;
cae184f2 821
cae184f2
KH
822 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
823 if (combining_bytes <= 0)
824 /* The character preceding POS is, complete and no room for
825 combining bytes (combining_bytes == 0), or an independent 8-bit
826 character (combining_bytes < 0). */
432f78d2 827 return 0;
ce97a2d7 828
cae184f2
KH
829 /* We have a combination situation. Count the bytes at STRING that
830 may combine. */
831 p = string + 1;
ce97a2d7
RS
832 while (!CHAR_HEAD_P (*p) && p < string + length)
833 p++;
834
cae184f2 835 return (combining_bytes < p - string ? combining_bytes : p - string);
432f78d2 836}
b45433b3 837
432f78d2
RS
838/* See if the bytes after POS/POS_BYTE combine with bytes
839 at the end of STRING to form a single character.
840 If so, return the number of bytes after POS/POS_BYTE
841 which combine in this way. Otherwise, return 0. */
679194a6 842
432f78d2
RS
843int
844count_combining_after (string, length, pos, pos_byte)
845 unsigned char *string;
846 int length;
847 int pos, pos_byte;
848{
6021f7c5 849 int opos_byte = pos_byte;
432f78d2 850 int i;
6021f7c5 851 int bytes;
cae184f2 852 unsigned char *bufp;
3be11131 853
432f78d2
RS
854 if (NILP (current_buffer->enable_multibyte_characters))
855 return 0;
cae184f2
KH
856
857 /* At first, we can exclude the following cases:
858 (1) The last byte of STRING is an ASCII.
859 (2) POS is the last of the current buffer.
860 (3) A character at POS can't be a following byte of multibyte
861 character. */
862 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
863 return 0;
864 if (pos_byte == Z_BYTE) /* case (2) */
432f78d2 865 return 0;
cae184f2
KH
866 bufp = BYTE_POS_ADDR (pos_byte);
867 if (CHAR_HEAD_P (*bufp)) /* case (3) */
868 return 0;
869
432f78d2 870 i = length - 1;
b57a7b0b 871 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
432f78d2
RS
872 {
873 i--;
874 }
b57a7b0b
KH
875 if (i < 0)
876 {
cae184f2
KH
877 /* All characters in STRING are not character head. We must
878 check also preceding bytes at POS. We are sure that the gap
879 is at POS. */
880 unsigned char *p = BEG_ADDR;
b57a7b0b 881 i = pos_byte - 2;
cae184f2 882 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
b57a7b0b 883 i--;
cae184f2 884 if (i < 0 || !BASE_LEADING_CODE_P (p[i]))
b57a7b0b 885 return 0;
0ef71121 886
cae184f2
KH
887 bytes = BYTES_BY_CHAR_HEAD (p[i]);
888 return (bytes <= pos_byte - 1 - i + length
889 ? 0
890 : bytes - (pos_byte - 1 - i + length));
b57a7b0b 891 }
cae184f2 892 if (!BASE_LEADING_CODE_P (string[i]))
432f78d2
RS
893 return 0;
894
cae184f2
KH
895 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
896 bufp++, pos_byte++;
897 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
cd11ef31 898
cae184f2 899 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
b45433b3 900}
2b083808 901
b16afa45 902#endif
9f3ede3c 903
1f90a790 904\f
2b083808
RS
905/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
906 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
907 are the same as in insert_1. */
908
909void
910insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
911 register unsigned char *string;
912 register int nchars, nbytes;
913 int inherit, prepare, before_markers;
914{
57404188
KH
915 if (NILP (current_buffer->enable_multibyte_characters))
916 nchars = nbytes;
917
35d63725
RS
918 if (prepare)
919 /* Do this before moving and increasing the gap,
920 because the before-change hooks might move the gap
921 or make it smaller. */
922 prepare_to_modify_buffer (PT, PT, NULL);
923
2b083808
RS
924 if (PT != GPT)
925 move_gap_both (PT, PT_BYTE);
926 if (GAP_SIZE < nbytes)
927 make_gap (nbytes - GAP_SIZE);
928
b16afa45
KH
929#ifdef BYTE_COMBINING_DEBUG
930 if (count_combining_before (string, nbytes, PT, PT_BYTE)
931 || count_combining_after (string, nbytes, PT, PT_BYTE))
932 abort ();
933#endif
432f78d2
RS
934
935 /* Record deletion of the surrounding text that combines with
936 the insertion. This, together with recording the insertion,
b16afa45
KH
937 will add up to the right stuff in the undo list. */
938 record_insert (PT, nchars);
2b083808
RS
939 MODIFF++;
940
941 bcopy (string, GPT_ADDR, nbytes);
942
2b083808 943 GAP_SIZE -= nbytes;
1f90a790
RS
944 GPT += nchars;
945 ZV += nchars;
946 Z += nchars;
2b083808
RS
947 GPT_BYTE += nbytes;
948 ZV_BYTE += nbytes;
949 Z_BYTE += nbytes;
950 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1f90a790 951
1f90a790
RS
952 if (GPT_BYTE < GPT)
953 abort ();
954
955 adjust_overlays_for_insert (PT, nchars);
432f78d2 956 adjust_markers_for_insert (PT, PT_BYTE,
1f90a790 957 PT + nchars, PT_BYTE + nbytes,
2b083808 958 before_markers);
ce97a2d7 959
1f90a790 960 if (BUF_INTERVALS (current_buffer) != 0)
1f90a790
RS
961 offset_intervals (current_buffer, PT, nchars);
962
ce97a2d7 963 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
f2cab2ea
GM
964 set_text_properties (make_number (PT), make_number (PT + nchars),
965 Qnil, Qnil, Qnil);
ce97a2d7 966
b16afa45 967 adjust_point (nchars, nbytes);
828f1ed3
KH
968
969 CHECK_MARKERS ();
2b083808 970}
3be11131 971\f
679194a6 972/* Insert the part of the text of STRING, a Lisp object assumed to be
2b083808
RS
973 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
974 starting at position POS / POS_BYTE. If the text of STRING has properties,
975 copy them into the buffer.
679194a6
JA
976
977 It does not work to use `insert' for this, because a GC could happen
7e1ea612
JB
978 before we bcopy the stuff into the buffer, and relocate the string
979 without insert noticing. */
679194a6 980
c660b094 981void
2b083808 982insert_from_string (string, pos, pos_byte, length, length_byte, inherit)
b45433b3 983 Lisp_Object string;
2b083808 984 register int pos, pos_byte, length, length_byte;
9391e591 985 int inherit;
395ec62e 986{
62b82678
RS
987 int opoint = PT;
988 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
989 inherit, 0);
990 signal_after_change (opoint, 0, PT - opoint);
0ef71121 991 update_compositions (opoint, PT, CHECK_BORDER);
395ec62e
KH
992}
993
2b083808
RS
994/* Like `insert_from_string' except that all markers pointing
995 at the place where the insertion happens are adjusted to point after it. */
3be11131
RS
996
997void
2b083808
RS
998insert_from_string_before_markers (string, pos, pos_byte,
999 length, length_byte, inherit)
395ec62e 1000 Lisp_Object string;
2b083808 1001 register int pos, pos_byte, length, length_byte;
395ec62e 1002 int inherit;
3be11131 1003{
62b82678
RS
1004 int opoint = PT;
1005 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
1006 inherit, 1);
1007 signal_after_change (opoint, 0, PT - opoint);
0ef71121 1008 update_compositions (opoint, PT, CHECK_BORDER);
3be11131
RS
1009}
1010
1011/* Subroutine of the insertion functions above. */
1012
1013static void
2b083808
RS
1014insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
1015 inherit, before_markers)
3be11131 1016 Lisp_Object string;
2b083808 1017 register int pos, pos_byte, nchars, nbytes;
3be11131 1018 int inherit, before_markers;
b45433b3 1019{
b45433b3 1020 struct gcpro gcpro1;
2b083808 1021 int outgoing_nbytes = nbytes;
ce97a2d7 1022 INTERVAL intervals;
2b083808
RS
1023
1024 /* Make OUTGOING_NBYTES describe the text
1025 as it will be inserted in this buffer. */
1026
1027 if (NILP (current_buffer->enable_multibyte_characters))
1028 outgoing_nbytes = nchars;
2a1d8be0 1029 else if (! STRING_MULTIBYTE (string))
2b083808
RS
1030 outgoing_nbytes
1031 = count_size_as_multibyte (&XSTRING (string)->data[pos_byte],
1032 nbytes);
b45433b3 1033
b45433b3 1034 GCPRO1 (string);
35d63725
RS
1035 /* Do this before moving and increasing the gap,
1036 because the before-change hooks might move the gap
1037 or make it smaller. */
d206af14 1038 prepare_to_modify_buffer (PT, PT, NULL);
b45433b3 1039
2bcaed71 1040 if (PT != GPT)
3be11131 1041 move_gap_both (PT, PT_BYTE);
534b9840 1042 if (GAP_SIZE < outgoing_nbytes)
2b083808 1043 make_gap (outgoing_nbytes - GAP_SIZE);
b45433b3
JB
1044 UNGCPRO;
1045
2b083808
RS
1046 /* Copy the string text into the buffer, perhaps converting
1047 between single-byte and multibyte. */
1048 copy_text (XSTRING (string)->data + pos_byte, GPT_ADDR, nbytes,
2a1d8be0 1049 STRING_MULTIBYTE (string),
2b083808 1050 ! NILP (current_buffer->enable_multibyte_characters));
b45433b3 1051
b16afa45 1052#ifdef BYTE_COMBINING_DEBUG
432f78d2
RS
1053 /* We have copied text into the gap, but we have not altered
1054 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1055 to these functions and get the same results as we would
1056 have got earlier on. Meanwhile, PT_ADDR does point to
1057 the text that has been stored by copy_text. */
b16afa45
KH
1058 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1059 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1060 abort ();
1061#endif
432f78d2 1062
b16afa45 1063 record_insert (PT, nchars);
432f78d2
RS
1064 MODIFF++;
1065
7792090e 1066 GAP_SIZE -= outgoing_nbytes;
1f90a790
RS
1067 GPT += nchars;
1068 ZV += nchars;
1069 Z += nchars;
2b083808
RS
1070 GPT_BYTE += outgoing_nbytes;
1071 ZV_BYTE += outgoing_nbytes;
1072 Z_BYTE += outgoing_nbytes;
469ff680 1073 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
3be11131
RS
1074
1075 if (GPT_BYTE < GPT)
1076 abort ();
679194a6 1077
1f90a790
RS
1078 adjust_overlays_for_insert (PT, nchars);
1079 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1080 PT_BYTE + outgoing_nbytes,
1f90a790 1081 before_markers);
ce97a2d7 1082
1f90a790
RS
1083 offset_intervals (current_buffer, PT, nchars);
1084
1085 intervals = XSTRING (string)->intervals;
b16afa45 1086 /* Get the intervals for the part of the string we are inserting. */
fc932ac6 1087 if (nbytes < STRING_BYTES (XSTRING (string)))
1f90a790 1088 intervals = copy_intervals (intervals, pos, nchars);
ce97a2d7
RS
1089
1090 /* Insert those intervals. */
1f90a790 1091 graft_intervals_into_buffer (intervals, PT, nchars,
9391e591 1092 current_buffer, inherit);
ce97a2d7 1093
b16afa45 1094 adjust_point (nchars, outgoing_nbytes);
b45433b3 1095}
3be11131
RS
1096\f
1097/* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
ef29f213
KH
1098 current buffer. If the text in BUF has properties, they are absorbed
1099 into the current buffer.
1100
1101 It does not work to use `insert' for this, because a malloc could happen
1102 and relocate BUF's text before the bcopy happens. */
1103
1104void
3be11131 1105insert_from_buffer (buf, charpos, nchars, inherit)
ef29f213 1106 struct buffer *buf;
3be11131 1107 int charpos, nchars;
ef29f213
KH
1108 int inherit;
1109{
62b82678 1110 int opoint = PT;
3be11131 1111
62b82678
RS
1112 insert_from_buffer_1 (buf, charpos, nchars, inherit);
1113 signal_after_change (opoint, 0, PT - opoint);
0ef71121 1114 update_compositions (opoint, PT, CHECK_BORDER);
ef29f213
KH
1115}
1116
1117static void
3be11131 1118insert_from_buffer_1 (buf, from, nchars, inherit)
ef29f213 1119 struct buffer *buf;
3be11131 1120 int from, nchars;
ef29f213
KH
1121 int inherit;
1122{
0aa8c4b2 1123 register Lisp_Object temp;
4468c4f1 1124 int chunk, chunk_expanded;
3be11131
RS
1125 int from_byte = buf_charpos_to_bytepos (buf, from);
1126 int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
2b083808
RS
1127 int incoming_nbytes = to_byte - from_byte;
1128 int outgoing_nbytes = incoming_nbytes;
ce97a2d7 1129 INTERVAL intervals;
2b083808
RS
1130
1131 /* Make OUTGOING_NBYTES describe the text
1132 as it will be inserted in this buffer. */
1133
1134 if (NILP (current_buffer->enable_multibyte_characters))
1135 outgoing_nbytes = nchars;
1136 else if (NILP (buf->enable_multibyte_characters))
4468c4f1
KH
1137 {
1138 int outgoing_before_gap = 0;
1139 int outgoing_after_gap = 0;
ef29f213 1140
4468c4f1
KH
1141 if (from < BUF_GPT (buf))
1142 {
1143 chunk = BUF_GPT_BYTE (buf) - from_byte;
1144 if (chunk > incoming_nbytes)
1145 chunk = incoming_nbytes;
1146 outgoing_before_gap
1147 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1148 chunk);
1149 }
1150 else
1151 chunk = 0;
1152
1153 if (chunk < incoming_nbytes)
1154 outgoing_after_gap
1155 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
1156 from_byte + chunk),
1157 incoming_nbytes - chunk);
1158
1159 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
1160 }
1161
ef29f213 1162 /* Make sure point-max won't overflow after this insertion. */
2b083808
RS
1163 XSETINT (temp, outgoing_nbytes + Z);
1164 if (outgoing_nbytes + Z != XINT (temp))
3be11131 1165 error ("Maximum buffer size exceeded");
ef29f213 1166
35d63725
RS
1167 /* Do this before moving and increasing the gap,
1168 because the before-change hooks might move the gap
1169 or make it smaller. */
d206af14 1170 prepare_to_modify_buffer (PT, PT, NULL);
ef29f213
KH
1171
1172 if (PT != GPT)
3be11131 1173 move_gap_both (PT, PT_BYTE);
2b083808
RS
1174 if (GAP_SIZE < outgoing_nbytes)
1175 make_gap (outgoing_nbytes - GAP_SIZE);
ef29f213 1176
3be11131 1177 if (from < BUF_GPT (buf))
ef29f213 1178 {
3be11131 1179 chunk = BUF_GPT_BYTE (buf) - from_byte;
2b083808
RS
1180 if (chunk > incoming_nbytes)
1181 chunk = incoming_nbytes;
4468c4f1
KH
1182 /* Record number of output bytes, so we know where
1183 to put the output from the second copy_text. */
1184 chunk_expanded
1185 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1186 GPT_ADDR, chunk,
1187 ! NILP (buf->enable_multibyte_characters),
1188 ! NILP (current_buffer->enable_multibyte_characters));
ef29f213
KH
1189 }
1190 else
4468c4f1
KH
1191 chunk_expanded = chunk = 0;
1192
2b083808
RS
1193 if (chunk < incoming_nbytes)
1194 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
4468c4f1 1195 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
2b083808
RS
1196 ! NILP (buf->enable_multibyte_characters),
1197 ! NILP (current_buffer->enable_multibyte_characters));
ef29f213 1198
b16afa45 1199#ifdef BYTE_COMBINING_DEBUG
432f78d2
RS
1200 /* We have copied text into the gap, but we have not altered
1201 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
1202 to these functions and get the same results as we would
1f90a790 1203 have got earlier on. Meanwhile, GPT_ADDR does point to
432f78d2 1204 the text that has been stored by copy_text. */
b16afa45
KH
1205 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
1206 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
1207 abort ();
1208#endif
432f78d2 1209
b16afa45 1210 record_insert (PT, nchars);
432f78d2
RS
1211 MODIFF++;
1212
2b083808 1213 GAP_SIZE -= outgoing_nbytes;
1f90a790
RS
1214 GPT += nchars;
1215 ZV += nchars;
1216 Z += nchars;
2b083808
RS
1217 GPT_BYTE += outgoing_nbytes;
1218 ZV_BYTE += outgoing_nbytes;
1219 Z_BYTE += outgoing_nbytes;
469ff680 1220 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1f90a790 1221
1f90a790
RS
1222 if (GPT_BYTE < GPT)
1223 abort ();
1224
1225 adjust_overlays_for_insert (PT, nchars);
1226 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
432f78d2 1227 PT_BYTE + outgoing_nbytes,
b16afa45 1228 0);
ce97a2d7 1229
1f90a790
RS
1230 if (BUF_INTERVALS (current_buffer) != 0)
1231 offset_intervals (current_buffer, PT, nchars);
ce97a2d7 1232
b16afa45 1233 /* Get the intervals for the part of the string we are inserting. */
ce97a2d7 1234 intervals = BUF_INTERVALS (buf);
1f90a790 1235 if (outgoing_nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf))
06d8227a
GM
1236 {
1237 if (buf == current_buffer && PT <= from)
1238 from += nchars;
1239 intervals = copy_intervals (intervals, from, nchars);
1240 }
ce97a2d7
RS
1241
1242 /* Insert those intervals. */
1f90a790 1243 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
ce97a2d7 1244
b16afa45 1245 adjust_point (nchars, outgoing_nbytes);
b45433b3
JB
1246}
1247\f
652838b5
KH
1248/* Record undo information and adjust markers and position keepers for
1249 a replacement of a text PREV_TEXT at FROM to a new text of LEN
1250 chars (LEN_BYTE bytes) which resides in the gap just after
1251 GPT_ADDR.
1252
1253 PREV_TEXT nil means the new text was just inserted. */
2d9eea44 1254
1e9c7b7d 1255void
652838b5
KH
1256adjust_after_replace (from, from_byte, prev_text, len, len_byte)
1257 int from, from_byte, len, len_byte;
1258 Lisp_Object prev_text;
1e9c7b7d 1259{
652838b5 1260 int nchars_del = 0, nbytes_del = 0;
61415a25 1261
b16afa45
KH
1262#ifdef BYTE_COMBINING_DEBUG
1263 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
1264 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
1265 abort ();
1266#endif
1267
828f1ed3
KH
1268 if (STRINGP (prev_text))
1269 {
1270 nchars_del = XSTRING (prev_text)->size;
1271 nbytes_del = STRING_BYTES (XSTRING (prev_text));
1272 }
1273
61415a25
KH
1274 /* Update various buffer positions for the new text. */
1275 GAP_SIZE -= len_byte;
1276 ZV += len; Z+= len;
1277 ZV_BYTE += len_byte; Z_BYTE += len_byte;
1278 GPT += len; GPT_BYTE += len_byte;
1279 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1280
adee4f91
KH
1281 if (nchars_del > 0)
1282 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
1283 len, len_byte);
1284 else
1285 adjust_markers_for_insert (from, from_byte,
1286 from + len, from_byte + len_byte, 0);
b16afa45 1287
828f1ed3
KH
1288 if (! EQ (current_buffer->undo_list, Qt))
1289 {
828f1ed3 1290 if (nchars_del > 0)
b16afa45
KH
1291 record_delete (from, prev_text);
1292 record_insert (from, len);
828f1ed3 1293 }
652838b5
KH
1294
1295 if (len > nchars_del)
1296 adjust_overlays_for_insert (from, len - nchars_del);
1297 else if (len < nchars_del)
1298 adjust_overlays_for_delete (from, nchars_del - len);
61415a25 1299 if (BUF_INTERVALS (current_buffer) != 0)
4a7cf15f
KH
1300 {
1301 offset_intervals (current_buffer, from, len - nchars_del);
4a7cf15f 1302 }
61415a25 1303
b16afa45
KH
1304 if (from < PT)
1305 adjust_point (len - nchars_del, len_byte - nbytes_del);
61415a25 1306
9f3ede3c 1307 /* As byte combining will decrease Z, we must check this again. */
a50df55b
GM
1308 if (Z - GPT < END_UNCHANGED)
1309 END_UNCHANGED = Z - GPT;
9f3ede3c 1310
60ea6052
RS
1311 CHECK_MARKERS ();
1312
1e9c7b7d
KH
1313 if (len == 0)
1314 evaporate_overlays (from);
1315 MODIFF++;
1e9c7b7d
KH
1316}
1317
652838b5
KH
1318/* Record undo information, adjust markers and position keepers for an
1319 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
1320 text already exists in the current buffer but character length (TO
1321 - FROM) may be incorrect, the correct length is NEWLEN. */
1322
1323void
1324adjust_after_insert (from, from_byte, to, to_byte, newlen)
1325 int from, from_byte, to, to_byte, newlen;
1326{
1327 int len = to - from, len_byte = to_byte - from_byte;
1328
1329 if (GPT != to)
1330 move_gap_both (to, to_byte);
1331 GAP_SIZE += len_byte;
1332 GPT -= len; GPT_BYTE -= len_byte;
1333 ZV -= len; ZV_BYTE -= len_byte;
1334 Z -= len; Z_BYTE -= len_byte;
1335 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
1336}
1337
3be11131 1338/* Replace the text from character positions FROM to TO with NEW,
c5ca4d3a
RS
1339 If PREPARE is nonzero, call prepare_to_modify_buffer.
1340 If INHERIT, the newly inserted text should inherit text properties
1341 from the surrounding non-deleted text. */
1342
1343/* Note that this does not yet handle markers quite right.
1344 Also it needs to record a single undo-entry that does a replacement
1345 rather than a separate delete and insert.
60aa777a
RS
1346 That way, undo will also handle markers properly.
1347
1348 But if MARKERS is 0, don't relocate markers. */
c5ca4d3a
RS
1349
1350void
60aa777a 1351replace_range (from, to, new, prepare, inherit, markers)
c5ca4d3a 1352 Lisp_Object new;
60aa777a 1353 int from, to, prepare, inherit, markers;
c5ca4d3a 1354{
2b083808 1355 int inschars = XSTRING (new)->size;
fc932ac6 1356 int insbytes = STRING_BYTES (XSTRING (new));
3be11131
RS
1357 int from_byte, to_byte;
1358 int nbytes_del, nchars_del;
c5ca4d3a
RS
1359 register Lisp_Object temp;
1360 struct gcpro gcpro1;
ce97a2d7 1361 INTERVAL intervals;
1f90a790 1362 int outgoing_insbytes = insbytes;
23b20a70 1363 Lisp_Object deletion;
c5ca4d3a 1364
60ea6052
RS
1365 CHECK_MARKERS ();
1366
c5ca4d3a 1367 GCPRO1 (new);
6bbd7a29 1368 deletion = Qnil;
c5ca4d3a
RS
1369
1370 if (prepare)
1371 {
1372 int range_length = to - from;
1373 prepare_to_modify_buffer (from, to, &from);
1374 to = from + range_length;
1375 }
1376
3be11131
RS
1377 UNGCPRO;
1378
c5ca4d3a
RS
1379 /* Make args be valid */
1380 if (from < BEGV)
1381 from = BEGV;
1382 if (to > ZV)
1383 to = ZV;
1384
3be11131
RS
1385 from_byte = CHAR_TO_BYTE (from);
1386 to_byte = CHAR_TO_BYTE (to);
c5ca4d3a 1387
3be11131
RS
1388 nchars_del = to - from;
1389 nbytes_del = to_byte - from_byte;
1390
1391 if (nbytes_del <= 0 && insbytes == 0)
1392 return;
c5ca4d3a 1393
1f90a790
RS
1394 /* Make OUTGOING_INSBYTES describe the text
1395 as it will be inserted in this buffer. */
1396
1397 if (NILP (current_buffer->enable_multibyte_characters))
1398 outgoing_insbytes = inschars;
2a1d8be0 1399 else if (! STRING_MULTIBYTE (new))
1f90a790
RS
1400 outgoing_insbytes
1401 = count_size_as_multibyte (XSTRING (new)->data, insbytes);
1402
c5ca4d3a 1403 /* Make sure point-max won't overflow after this insertion. */
3be11131
RS
1404 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1405 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1406 error ("Maximum buffer size exceeded");
c5ca4d3a 1407
c5ca4d3a
RS
1408 GCPRO1 (new);
1409
1410 /* Make sure the gap is somewhere in or next to what we are deleting. */
1411 if (from > GPT)
3be11131 1412 gap_right (from, from_byte);
c5ca4d3a 1413 if (to < GPT)
3be11131 1414 gap_left (to, to_byte, 0);
c5ca4d3a 1415
039af53a
KH
1416 /* Even if we don't record for undo, we must keep the original text
1417 because we may have to recover it because of inappropriate byte
1418 combining. */
b16afa45
KH
1419 if (! EQ (current_buffer->undo_list, Qt))
1420 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
c5ca4d3a 1421
23b20a70
KH
1422 if (markers)
1423 /* Relocate all markers pointing into the new, larger gap
1424 to point at the end of the text before the gap.
1425 Do this before recording the deletion,
1426 so that undo handles this after reinserting the text. */
1427 adjust_markers_for_delete (from, from_byte, to, to_byte);
c5ca4d3a 1428
3be11131
RS
1429 GAP_SIZE += nbytes_del;
1430 ZV -= nchars_del;
1431 Z -= nchars_del;
1432 ZV_BYTE -= nbytes_del;
1433 Z_BYTE -= nbytes_del;
c5ca4d3a 1434 GPT = from;
3be11131 1435 GPT_BYTE = from_byte;
c5ca4d3a
RS
1436 *(GPT_ADDR) = 0; /* Put an anchor. */
1437
3be11131
RS
1438 if (GPT_BYTE < GPT)
1439 abort ();
1440
a50df55b
GM
1441 if (GPT - BEG < BEG_UNCHANGED)
1442 BEG_UNCHANGED = GPT - BEG;
1443 if (Z - GPT < END_UNCHANGED)
1444 END_UNCHANGED = Z - GPT;
c5ca4d3a 1445
3be11131
RS
1446 if (GAP_SIZE < insbytes)
1447 make_gap (insbytes - GAP_SIZE);
c5ca4d3a 1448
1f90a790
RS
1449 /* Copy the string text into the buffer, perhaps converting
1450 between single-byte and multibyte. */
1451 copy_text (XSTRING (new)->data, GPT_ADDR, insbytes,
2a1d8be0 1452 STRING_MULTIBYTE (new),
1f90a790
RS
1453 ! NILP (current_buffer->enable_multibyte_characters));
1454
b16afa45 1455#ifdef BYTE_COMBINING_DEBUG
255c7dae
RS
1456 /* We have copied text into the gap, but we have not marked
1457 it as part of the buffer. So we can use the old FROM and FROM_BYTE
1458 here, for both the previous text and the following text.
1459 Meanwhile, GPT_ADDR does point to
432f78d2 1460 the text that has been stored by copy_text. */
b16afa45
KH
1461 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
1462 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
1463 abort ();
1464#endif
432f78d2 1465
23b20a70
KH
1466 if (! EQ (current_buffer->undo_list, Qt))
1467 {
b16afa45
KH
1468 record_delete (from, deletion);
1469 record_insert (from, inschars);
23b20a70 1470 }
c5ca4d3a 1471
1f90a790
RS
1472 GAP_SIZE -= outgoing_insbytes;
1473 GPT += inschars;
1474 ZV += inschars;
1475 Z += inschars;
1476 GPT_BYTE += outgoing_insbytes;
1477 ZV_BYTE += outgoing_insbytes;
1478 Z_BYTE += outgoing_insbytes;
c5ca4d3a
RS
1479 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1480
3be11131
RS
1481 if (GPT_BYTE < GPT)
1482 abort ();
1483
c5ca4d3a
RS
1484 /* Adjust the overlay center as needed. This must be done after
1485 adjusting the markers that bound the overlays. */
3be11131 1486 adjust_overlays_for_delete (from, nchars_del);
1f90a790 1487 adjust_overlays_for_insert (from, inschars);
60aa777a 1488 if (markers)
2db5082f
RS
1489 adjust_markers_for_insert (from, from_byte,
1490 from + inschars, from_byte + outgoing_insbytes,
b16afa45 1491 0);
c5ca4d3a 1492
255c7dae 1493 offset_intervals (current_buffer, from, inschars - nchars_del);
ce97a2d7
RS
1494
1495 /* Get the intervals for the part of the string we are inserting--
1496 not including the combined-before bytes. */
1497 intervals = XSTRING (new)->intervals;
ce97a2d7 1498 /* Insert those intervals. */
1f90a790 1499 graft_intervals_into_buffer (intervals, from, inschars,
ce97a2d7 1500 current_buffer, inherit);
c5ca4d3a 1501
1f90a790
RS
1502 /* Relocate point as if it were a marker. */
1503 if (from < PT)
8bedbe9d 1504 adjust_point ((from + inschars - (PT < to ? PT : to)),
1f90a790 1505 (from_byte + outgoing_insbytes
8bedbe9d 1506 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
c5ca4d3a 1507
1f90a790
RS
1508 if (outgoing_insbytes == 0)
1509 evaporate_overlays (from);
93b882e8 1510
60ea6052
RS
1511 CHECK_MARKERS ();
1512
c5ca4d3a
RS
1513 MODIFF++;
1514 UNGCPRO;
1515
255c7dae 1516 signal_after_change (from, nchars_del, GPT - from);
0ef71121 1517 update_compositions (from, GPT, CHECK_BORDER);
c5ca4d3a
RS
1518}
1519\f
b45433b3 1520/* Delete characters in current buffer
3be11131
RS
1521 from FROM up to (but not including) TO.
1522 If TO comes before FROM, we delete nothing. */
b45433b3 1523
c660b094 1524void
b45433b3
JB
1525del_range (from, to)
1526 register int from, to;
47c64747 1527{
7dae4502 1528 del_range_1 (from, to, 1, 0);
47c64747
RS
1529}
1530
7dae4502
SM
1531/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
1532 RET_STRING says to return the deleted text. */
47c64747 1533
7dae4502
SM
1534Lisp_Object
1535del_range_1 (from, to, prepare, ret_string)
1536 int from, to, prepare, ret_string;
b45433b3 1537{
3be11131 1538 int from_byte, to_byte;
7dae4502
SM
1539 Lisp_Object deletion;
1540 struct gcpro gcpro1;
3be11131
RS
1541
1542 /* Make args be valid */
1543 if (from < BEGV)
1544 from = BEGV;
1545 if (to > ZV)
1546 to = ZV;
1547
1548 if (to <= from)
7dae4502 1549 return Qnil;
3be11131
RS
1550
1551 if (prepare)
1552 {
1553 int range_length = to - from;
1554 prepare_to_modify_buffer (from, to, &from);
1555 to = from + range_length;
1556 }
1557
1558 from_byte = CHAR_TO_BYTE (from);
1559 to_byte = CHAR_TO_BYTE (to);
1560
7dae4502
SM
1561 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
1562 GCPRO1(deletion);
9c36993a 1563 signal_after_change (from, to - from, 0);
233cc02d 1564 update_compositions (from, from, CHECK_HEAD);
7dae4502
SM
1565 UNGCPRO;
1566 return deletion;
3be11131
RS
1567}
1568
1569/* Like del_range_1 but args are byte positions, not char positions. */
1570
1571void
1572del_range_byte (from_byte, to_byte, prepare)
1573 int from_byte, to_byte, prepare;
1574{
1575 int from, to;
1576
1577 /* Make args be valid */
1578 if (from_byte < BEGV_BYTE)
1579 from_byte = BEGV_BYTE;
1580 if (to_byte > ZV_BYTE)
1581 to_byte = ZV_BYTE;
1582
1583 if (to_byte <= from_byte)
1584 return;
1585
1586 from = BYTE_TO_CHAR (from_byte);
1587 to = BYTE_TO_CHAR (to_byte);
b45433b3 1588
d206af14
RS
1589 if (prepare)
1590 {
3be11131 1591 int old_from = from, old_to = Z - to;
d206af14
RS
1592 int range_length = to - from;
1593 prepare_to_modify_buffer (from, to, &from);
1594 to = from + range_length;
3be11131
RS
1595
1596 if (old_from != from)
1597 from_byte = CHAR_TO_BYTE (from);
1598 if (old_to == Z - to)
1599 to_byte = CHAR_TO_BYTE (to);
d206af14
RS
1600 }
1601
7dae4502 1602 del_range_2 (from, from_byte, to, to_byte, 0);
9c36993a 1603 signal_after_change (from, to - from, 0);
0ef71121 1604 update_compositions (from, from, CHECK_HEAD);
3be11131
RS
1605}
1606
1607/* Like del_range_1, but positions are specified both as charpos
1608 and bytepos. */
1609
1610void
353800c7
KH
1611del_range_both (from, from_byte, to, to_byte, prepare)
1612 int from, from_byte, to, to_byte, prepare;
3be11131 1613{
b45433b3 1614 /* Make args be valid */
3be11131
RS
1615 if (from_byte < BEGV_BYTE)
1616 from_byte = BEGV_BYTE;
1617 if (to_byte > ZV_BYTE)
1618 to_byte = ZV_BYTE;
1619
1620 if (to_byte <= from_byte)
1621 return;
1622
b45433b3
JB
1623 if (from < BEGV)
1624 from = BEGV;
1625 if (to > ZV)
1626 to = ZV;
1627
3be11131
RS
1628 if (prepare)
1629 {
1630 int old_from = from, old_to = Z - to;
1631 int range_length = to - from;
1632 prepare_to_modify_buffer (from, to, &from);
1633 to = from + range_length;
1634
1635 if (old_from != from)
1636 from_byte = CHAR_TO_BYTE (from);
1637 if (old_to == Z - to)
1638 to_byte = CHAR_TO_BYTE (to);
1639 }
1640
7dae4502 1641 del_range_2 (from, from_byte, to, to_byte, 0);
9c36993a 1642 signal_after_change (from, to - from, 0);
0ef71121 1643 update_compositions (from, from, CHECK_HEAD);
3be11131
RS
1644}
1645
1646/* Delete a range of text, specified both as character positions
1647 and byte positions. FROM and TO are character positions,
7dae4502
SM
1648 while FROM_BYTE and TO_BYTE are byte positions.
1649 If RET_STRING is true, the deleted area is returned as a string. */
3be11131 1650
7dae4502
SM
1651Lisp_Object
1652del_range_2 (from, from_byte, to, to_byte, ret_string)
1653 int from, from_byte, to, to_byte, ret_string;
3be11131
RS
1654{
1655 register int nbytes_del, nchars_del;
628cea90 1656 Lisp_Object deletion;
3be11131 1657
60ea6052
RS
1658 CHECK_MARKERS ();
1659
3be11131
RS
1660 nchars_del = to - from;
1661 nbytes_del = to_byte - from_byte;
b45433b3
JB
1662
1663 /* Make sure the gap is somewhere in or next to what we are deleting. */
1664 if (from > GPT)
3be11131 1665 gap_right (from, from_byte);
b45433b3 1666 if (to < GPT)
3be11131 1667 gap_left (to, to_byte, 0);
b45433b3 1668
b16afa45
KH
1669#ifdef BYTE_COMBINING_DEBUG
1670 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
1671 Z_BYTE - to_byte, from, from_byte))
1672 abort ();
1673#endif
628cea90 1674
7dae4502 1675 if (ret_string || ! EQ (current_buffer->undo_list, Qt))
b16afa45 1676 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
7dae4502
SM
1677 else
1678 deletion = Qnil;
1679
8948d317
RS
1680 /* Relocate all markers pointing into the new, larger gap
1681 to point at the end of the text before the gap.
3be11131
RS
1682 Do this before recording the deletion,
1683 so that undo handles this after reinserting the text. */
1684 adjust_markers_for_delete (from, from_byte, to, to_byte);
b16afa45 1685
0aa8c4b2 1686 if (! EQ (current_buffer->undo_list, Qt))
b16afa45 1687 record_delete (from, deletion);
be09561e
RS
1688 MODIFF++;
1689
b45433b3 1690 /* Relocate point as if it were a marker. */
2bcaed71 1691 if (from < PT)
3be11131
RS
1692 adjust_point (from - (PT < to ? PT : to),
1693 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
b45433b3 1694
3be11131 1695 offset_intervals (current_buffer, from, - nchars_del);
16032db6 1696
adde4858 1697 /* Adjust the overlay center as needed. This must be done after
a7f38d28 1698 adjusting the markers that bound the overlays. */
e3a87305 1699 adjust_overlays_for_delete (from, nchars_del);
adde4858 1700
3be11131
RS
1701 GAP_SIZE += nbytes_del;
1702 ZV_BYTE -= nbytes_del;
1703 Z_BYTE -= nbytes_del;
1704 ZV -= nchars_del;
1705 Z -= nchars_del;
b45433b3 1706 GPT = from;
3be11131 1707 GPT_BYTE = from_byte;
e3a87305
KH
1708 *(GPT_ADDR) = 0; /* Put an anchor. */
1709
3be11131
RS
1710 if (GPT_BYTE < GPT)
1711 abort ();
1712
a50df55b
GM
1713 if (GPT - BEG < BEG_UNCHANGED)
1714 BEG_UNCHANGED = GPT - BEG;
1715 if (Z - GPT < END_UNCHANGED)
1716 END_UNCHANGED = Z - GPT;
b45433b3 1717
60ea6052
RS
1718 CHECK_MARKERS ();
1719
d386034e 1720 evaporate_overlays (from);
7dae4502
SM
1721
1722 return deletion;
b45433b3
JB
1723}
1724\f
3be11131
RS
1725/* Call this if you're about to change the region of BUFFER from
1726 character positions START to END. This checks the read-only
1727 properties of the region, calls the necessary modification hooks,
1728 and warns the next redisplay that it should pay attention to that
1729 area. */
1730
c660b094 1731void
04a759c8
JB
1732modify_region (buffer, start, end)
1733 struct buffer *buffer;
b45433b3
JB
1734 int start, end;
1735{
04a759c8
JB
1736 struct buffer *old_buffer = current_buffer;
1737
1738 if (buffer != old_buffer)
1739 set_buffer_internal (buffer);
1740
d206af14 1741 prepare_to_modify_buffer (start, end, NULL);
b45433b3 1742
a50df55b 1743 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
83010cd6 1744
9fbf87cd 1745 if (MODIFF <= SAVE_MODIFF)
83010cd6 1746 record_first_change ();
b45433b3 1747 MODIFF++;
04a759c8 1748
069cdc4f
RS
1749 buffer->point_before_scroll = Qnil;
1750
04a759c8
JB
1751 if (buffer != old_buffer)
1752 set_buffer_internal (old_buffer);
b45433b3 1753}
d206af14 1754\f
3be11131
RS
1755/* Check that it is okay to modify the buffer between START and END,
1756 which are char positions.
1757
679194a6
JA
1758 Run the before-change-function, if any. If intervals are in use,
1759 verify that the text to be modified is not read-only, and call
d206af14
RS
1760 any modification properties the text may have.
1761
1762 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1763 by holding its value temporarily in a marker. */
b45433b3 1764
c660b094 1765void
d206af14 1766prepare_to_modify_buffer (start, end, preserve_ptr)
fb4ee5cd 1767 int start, end;
d206af14 1768 int *preserve_ptr;
b45433b3 1769{
d427b66a 1770 if (!NILP (current_buffer->read_only))
b45433b3
JB
1771 Fbarf_if_buffer_read_only ();
1772
2e9f55fd
GM
1773 /* Let redisplay consider other windows than selected_window
1774 if modifying another buffer. */
1775 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
1776 ++windows_or_buffers_changed;
1777
9fbf87cd 1778 if (BUF_INTERVALS (current_buffer) != 0)
d206af14
RS
1779 {
1780 if (preserve_ptr)
1781 {
1782 Lisp_Object preserve_marker;
1783 struct gcpro gcpro1;
1784 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1785 GCPRO1 (preserve_marker);
1786 verify_interval_modification (current_buffer, start, end);
1787 *preserve_ptr = marker_position (preserve_marker);
1788 unchain_marker (preserve_marker);
1789 UNGCPRO;
1790 }
1791 else
1792 verify_interval_modification (current_buffer, start, end);
1793 }
b45433b3
JB
1794
1795#ifdef CLASH_DETECTION
f173b650 1796 if (!NILP (current_buffer->file_truename)
ab6c5c0c
RS
1797 /* Make binding buffer-file-name to nil effective. */
1798 && !NILP (current_buffer->filename)
9fbf87cd 1799 && SAVE_MODIFF >= MODIFF)
f173b650 1800 lock_file (current_buffer->file_truename);
b45433b3
JB
1801#else
1802 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 1803 if (!NILP (current_buffer->filename)
9fbf87cd 1804 && SAVE_MODIFF >= MODIFF
d427b66a
JB
1805 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1806 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
1807 call1 (intern ("ask-user-about-supersession-threat"),
1808 current_buffer->filename);
1809#endif /* not CLASH_DETECTION */
1810
d206af14 1811 signal_before_change (start, end, preserve_ptr);
2f545eea 1812
56e1065e
JB
1813 if (current_buffer->newline_cache)
1814 invalidate_region_cache (current_buffer,
1815 current_buffer->newline_cache,
1816 start - BEG, Z - end);
1817 if (current_buffer->width_run_cache)
1818 invalidate_region_cache (current_buffer,
1819 current_buffer->width_run_cache,
1820 start - BEG, Z - end);
1821
2f545eea 1822 Vdeactivate_mark = Qt;
b45433b3
JB
1823}
1824\f
d206af14
RS
1825/* These macros work with an argument named `preserve_ptr'
1826 and a local variable named `preserve_marker'. */
1827
1828#define PRESERVE_VALUE \
1829 if (preserve_ptr && NILP (preserve_marker)) \
1830 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1831
1832#define RESTORE_VALUE \
1833 if (! NILP (preserve_marker)) \
1834 { \
1835 *preserve_ptr = marker_position (preserve_marker); \
1836 unchain_marker (preserve_marker); \
1837 }
1838
b86e0aaf
RS
1839#define PRESERVE_START_END \
1840 if (NILP (start_marker)) \
1841 start_marker = Fcopy_marker (start, Qnil); \
1842 if (NILP (end_marker)) \
1843 end_marker = Fcopy_marker (end, Qnil);
1844
1845#define FETCH_START \
1846 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1847
1848#define FETCH_END \
1849 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1850
eb8c3be9 1851/* Signal a change to the buffer immediately before it happens.
d206af14
RS
1852 START_INT and END_INT are the bounds of the text to be changed.
1853
1854 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1855 by holding its value temporarily in a marker. */
b45433b3 1856
c660b094 1857void
d206af14 1858signal_before_change (start_int, end_int, preserve_ptr)
6022d493 1859 int start_int, end_int;
d206af14 1860 int *preserve_ptr;
b45433b3 1861{
fb4ee5cd 1862 Lisp_Object start, end;
b86e0aaf 1863 Lisp_Object start_marker, end_marker;
d206af14 1864 Lisp_Object preserve_marker;
b86e0aaf 1865 struct gcpro gcpro1, gcpro2, gcpro3;
fb4ee5cd 1866
fd16a4c6
KH
1867 if (inhibit_modification_hooks)
1868 return;
1869
fb4ee5cd
RS
1870 start = make_number (start_int);
1871 end = make_number (end_int);
d206af14 1872 preserve_marker = Qnil;
b86e0aaf
RS
1873 start_marker = Qnil;
1874 end_marker = Qnil;
1875 GCPRO3 (preserve_marker, start_marker, end_marker);
fb4ee5cd 1876
b45433b3 1877 /* If buffer is unmodified, run a special hook for that case. */
9fbf87cd 1878 if (SAVE_MODIFF >= MODIFF
dbc4e1c1
JB
1879 && !NILP (Vfirst_change_hook)
1880 && !NILP (Vrun_hooks))
d206af14
RS
1881 {
1882 PRESERVE_VALUE;
b86e0aaf 1883 PRESERVE_START_END;
d206af14
RS
1884 call1 (Vrun_hooks, Qfirst_change_hook);
1885 }
dbc4e1c1 1886
3d1e2d9c 1887 /* Now run the before-change-functions if any. */
e45fb8bf
RS
1888 if (!NILP (Vbefore_change_functions))
1889 {
3d1e2d9c
RS
1890 Lisp_Object args[3];
1891 Lisp_Object before_change_functions;
1892 Lisp_Object after_change_functions;
1893 struct gcpro gcpro1, gcpro2;
1894
d206af14 1895 PRESERVE_VALUE;
b86e0aaf 1896 PRESERVE_START_END;
d206af14 1897
3d1e2d9c
RS
1898 /* "Bind" before-change-functions and after-change-functions
1899 to nil--but in a way that errors don't know about.
1900 That way, if there's an error in them, they will stay nil. */
1901 before_change_functions = Vbefore_change_functions;
1902 after_change_functions = Vafter_change_functions;
c82c1da0
KH
1903 Vbefore_change_functions = Qnil;
1904 Vafter_change_functions = Qnil;
3d1e2d9c
RS
1905 GCPRO2 (before_change_functions, after_change_functions);
1906
1907 /* Actually run the hook functions. */
1908 args[0] = Qbefore_change_functions;
b86e0aaf
RS
1909 args[1] = FETCH_START;
1910 args[2] = FETCH_END;
3d1e2d9c
RS
1911 run_hook_list_with_args (before_change_functions, 3, args);
1912
1913 /* "Unbind" the variables we "bound" to nil. */
1914 Vbefore_change_functions = before_change_functions;
1915 Vafter_change_functions = after_change_functions;
1916 UNGCPRO;
e45fb8bf 1917 }
d07c0804
RS
1918
1919 if (!NILP (current_buffer->overlays_before)
1920 || !NILP (current_buffer->overlays_after))
d206af14
RS
1921 {
1922 PRESERVE_VALUE;
b86e0aaf
RS
1923 report_overlay_modification (FETCH_START, FETCH_END, 0,
1924 FETCH_START, FETCH_END, Qnil);
d206af14
RS
1925 }
1926
b86e0aaf
RS
1927 if (! NILP (start_marker))
1928 free_marker (start_marker);
1929 if (! NILP (end_marker))
1930 free_marker (end_marker);
d206af14
RS
1931 RESTORE_VALUE;
1932 UNGCPRO;
b45433b3
JB
1933}
1934
eb8c3be9 1935/* Signal a change immediately after it happens.
3be11131 1936 CHARPOS is the character position of the start of the changed text.
b45433b3
JB
1937 LENDEL is the number of characters of the text before the change.
1938 (Not the whole buffer; just the part that was changed.)
8b09e5d0
RS
1939 LENINS is the number of characters in that part of the text
1940 after the change. */
b45433b3 1941
c660b094 1942void
3be11131
RS
1943signal_after_change (charpos, lendel, lenins)
1944 int charpos, lendel, lenins;
b45433b3 1945{
fd16a4c6
KH
1946 if (inhibit_modification_hooks)
1947 return;
1948
fb2e7d14
RS
1949 /* If we are deferring calls to the after-change functions
1950 and there are no before-change functions,
1951 just record the args that we were going to use. */
1952 if (! NILP (Vcombine_after_change_calls)
1675d086 1953 && NILP (Vbefore_change_functions)
fb2e7d14
RS
1954 && NILP (current_buffer->overlays_before)
1955 && NILP (current_buffer->overlays_after))
1956 {
1957 Lisp_Object elt;
1958
1959 if (!NILP (combine_after_change_list)
1960 && current_buffer != XBUFFER (combine_after_change_buffer))
1961 Fcombine_after_change_execute ();
1962
3be11131
RS
1963 elt = Fcons (make_number (charpos - BEG),
1964 Fcons (make_number (Z - (charpos - lendel + lenins)),
fb2e7d14
RS
1965 Fcons (make_number (lenins - lendel), Qnil)));
1966 combine_after_change_list
1967 = Fcons (elt, combine_after_change_list);
1968 combine_after_change_buffer = Fcurrent_buffer ();
1969
1970 return;
1971 }
1972
1973 if (!NILP (combine_after_change_list))
1974 Fcombine_after_change_execute ();
1975
e45fb8bf
RS
1976 if (!NILP (Vafter_change_functions))
1977 {
3d1e2d9c
RS
1978 Lisp_Object args[4];
1979 Lisp_Object before_change_functions;
1980 Lisp_Object after_change_functions;
1981 struct gcpro gcpro1, gcpro2;
1982
1983 /* "Bind" before-change-functions and after-change-functions
1984 to nil--but in a way that errors don't know about.
1985 That way, if there's an error in them, they will stay nil. */
1986 before_change_functions = Vbefore_change_functions;
1987 after_change_functions = Vafter_change_functions;
c82c1da0
KH
1988 Vbefore_change_functions = Qnil;
1989 Vafter_change_functions = Qnil;
3d1e2d9c
RS
1990 GCPRO2 (before_change_functions, after_change_functions);
1991
1992 /* Actually run the hook functions. */
1993 args[0] = Qafter_change_functions;
3be11131
RS
1994 XSETFASTINT (args[1], charpos);
1995 XSETFASTINT (args[2], charpos + lenins);
3d1e2d9c
RS
1996 XSETFASTINT (args[3], lendel);
1997 run_hook_list_with_args (after_change_functions,
1998 4, args);
1999
2000 /* "Unbind" the variables we "bound" to nil. */
2001 Vbefore_change_functions = before_change_functions;
2002 Vafter_change_functions = after_change_functions;
2003 UNGCPRO;
e45fb8bf 2004 }
d07c0804
RS
2005
2006 if (!NILP (current_buffer->overlays_before)
2007 || !NILP (current_buffer->overlays_after))
3be11131
RS
2008 report_overlay_modification (make_number (charpos),
2009 make_number (charpos + lenins),
d07c0804 2010 1,
3be11131
RS
2011 make_number (charpos),
2012 make_number (charpos + lenins),
d07c0804 2013 make_number (lendel));
c5ca0786
RS
2014
2015 /* After an insertion, call the text properties
2016 insert-behind-hooks or insert-in-front-hooks. */
2017 if (lendel == 0)
d6b81c0f
AS
2018 report_interval_modification (make_number (charpos),
2019 make_number (charpos + lenins));
b45433b3 2020}
fb2e7d14
RS
2021
2022Lisp_Object
2023Fcombine_after_change_execute_1 (val)
2024 Lisp_Object val;
2025{
2026 Vcombine_after_change_calls = val;
2027 return val;
2028}
2029
2030DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
2031 Scombine_after_change_execute, 0, 0, 0,
2032 "This function is for use internally in `combine-after-change-calls'.")
2033 ()
2034{
fb2e7d14
RS
2035 int count = specpdl_ptr - specpdl;
2036 int beg, end, change;
2037 int begpos, endpos;
2038 Lisp_Object tail;
2039
101e446f
KH
2040 if (NILP (combine_after_change_list))
2041 return Qnil;
2042
fb2e7d14
RS
2043 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2044
2045 Fset_buffer (combine_after_change_buffer);
2046
2047 /* # chars unchanged at beginning of buffer. */
2048 beg = Z - BEG;
2049 /* # chars unchanged at end of buffer. */
2050 end = beg;
2051 /* Total amount of insertion (negative for deletion). */
2052 change = 0;
2053
2054 /* Scan the various individual changes,
2055 accumulating the range info in BEG, END and CHANGE. */
2056 for (tail = combine_after_change_list; CONSP (tail);
03699b14 2057 tail = XCDR (tail))
fb2e7d14 2058 {
e688a080
KH
2059 Lisp_Object elt;
2060 int thisbeg, thisend, thischange;
fb2e7d14
RS
2061
2062 /* Extract the info from the next element. */
03699b14 2063 elt = XCAR (tail);
fb2e7d14
RS
2064 if (! CONSP (elt))
2065 continue;
03699b14 2066 thisbeg = XINT (XCAR (elt));
fb2e7d14 2067
03699b14 2068 elt = XCDR (elt);
fb2e7d14
RS
2069 if (! CONSP (elt))
2070 continue;
03699b14 2071 thisend = XINT (XCAR (elt));
fb2e7d14 2072
03699b14 2073 elt = XCDR (elt);
fb2e7d14
RS
2074 if (! CONSP (elt))
2075 continue;
03699b14 2076 thischange = XINT (XCAR (elt));
fb2e7d14
RS
2077
2078 /* Merge this range into the accumulated range. */
2079 change += thischange;
2080 if (thisbeg < beg)
2081 beg = thisbeg;
2082 if (thisend < end)
2083 end = thisend;
2084 }
2085
2086 /* Get the current start and end positions of the range
2087 that was changed. */
2088 begpos = BEG + beg;
2089 endpos = Z - end;
2090
2091 /* We are about to handle these, so discard them. */
2092 combine_after_change_list = Qnil;
2093
2094 /* Now run the after-change functions for real.
2095 Turn off the flag that defers them. */
2096 record_unwind_protect (Fcombine_after_change_execute_1,
2097 Vcombine_after_change_calls);
2098 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
0ef71121 2099 update_compositions (begpos, endpos, CHECK_ALL);
fb2e7d14 2100
101e446f 2101 return unbind_to (count, Qnil);
fb2e7d14
RS
2102}
2103\f
dfcf069d 2104void
fb2e7d14
RS
2105syms_of_insdel ()
2106{
2107 staticpro (&combine_after_change_list);
2108 combine_after_change_list = Qnil;
101e446f 2109 combine_after_change_buffer = Qnil;
fb2e7d14 2110
60ea6052
RS
2111 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag,
2112 "Non-nil means enable debugging checks for invalid marker positions.");
2113 check_markers_debug_flag = 0;
fb2e7d14 2114 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
60ea6052 2115 "Used internally by the `combine-after-change-calls' macro.");
fb2e7d14
RS
2116 Vcombine_after_change_calls = Qnil;
2117
7baf49cf
RS
2118 DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks,
2119 "Non-nil means don't run any of the hooks that respond to buffer changes.\n\
2120This affects `before-change-functions' and `after-change-functions',\n\
2121as well as hooks attached to text properties and overlays.");
2122 inhibit_modification_hooks = 0;
2123
fb2e7d14
RS
2124 defsubr (&Scombine_after_change_execute);
2125}