(Fcall_process): Calculate CARRYOVER correctly.
[bpt/emacs.git] / src / insdel.c
CommitLineData
b45433b3 1/* Buffer insertion/deletion and gap motion for GNU Emacs.
4a2f9c6a 2 Copyright (C) 1985, 86, 93, 94, 95, 97, 1998 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"
b45433b3 29
d206af14
RS
30#ifndef NULL
31#define NULL 0
32#endif
33
14f6194b
RS
34#define min(x, y) ((x) < (y) ? (x) : (y))
35
2b083808 36static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int, int));
ef29f213 37static void insert_from_buffer_1 ();
3be11131
RS
38static void gap_left P_ ((int, int, int));
39static void gap_right P_ ((int, int));
40static void adjust_markers_gap_motion P_ ((int, int, int));
41static void adjust_markers_for_insert P_ ((int, int, int, int, int));
42static void adjust_markers_for_delete P_ ((int, int, int, int));
43static void adjust_point P_ ((int, int));
395ec62e 44
fb2e7d14
RS
45Lisp_Object Fcombine_after_change_execute ();
46
47/* Non-nil means don't call the after-change-functions right away,
48 just record an element in Vcombine_after_change_calls_list. */
49Lisp_Object Vcombine_after_change_calls;
50
51/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
52 describing changes which happened while combine_after_change_calls
53 was nonzero. We use this to decide how to call them
54 once the deferral ends.
55
56 In each element.
57 BEG-UNCHANGED is the number of chars before the changed range.
58 END-UNCHANGED is the number of chars after the changed range,
59 and CHANGE-AMOUNT is the number of characters inserted by the change
60 (negative for a deletion). */
61Lisp_Object combine_after_change_list;
62
63/* Buffer which combine_after_change_list is about. */
64Lisp_Object combine_after_change_buffer;
65
2b083808
RS
66#define DEFAULT_NONASCII_INSERT_OFFSET 0x800
67\f
3be11131 68/* Move gap to position CHARPOS.
b45433b3
JB
69 Note that this can quit! */
70
c660b094 71void
3be11131
RS
72move_gap (charpos)
73 int charpos;
b45433b3 74{
3be11131 75 move_gap_both (charpos, charpos_to_bytepos (charpos));
b45433b3
JB
76}
77
3be11131
RS
78/* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
79 Note that this can quit! */
80
81void
82move_gap_both (charpos, bytepos)
83 int charpos, bytepos;
84{
85 if (bytepos < GPT_BYTE)
86 gap_left (charpos, bytepos, 0);
87 else if (bytepos > GPT_BYTE)
88 gap_right (charpos, bytepos);
89}
90
91/* Move the gap to a position less than the current GPT.
92 BYTEPOS describes the new position as a byte position,
93 and CHARPOS is the corresponding char position.
b45433b3
JB
94 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
95
2bcaed71 96static void
3be11131
RS
97gap_left (charpos, bytepos, newgap)
98 register int charpos, bytepos;
b45433b3
JB
99 int newgap;
100{
101 register unsigned char *to, *from;
102 register int i;
103 int new_s1;
104
b45433b3
JB
105 if (!newgap)
106 {
894ab630
RS
107 if (unchanged_modified == MODIFF
108 && overlay_unchanged_modified == OVERLAY_MODIFF)
b45433b3 109 {
3be11131
RS
110 beg_unchanged = charpos - BEG;
111 end_unchanged = Z - charpos;
b45433b3
JB
112 }
113 else
114 {
115 if (Z - GPT < end_unchanged)
116 end_unchanged = Z - GPT;
3be11131
RS
117 if (charpos < beg_unchanged)
118 beg_unchanged = charpos - BEG;
b45433b3
JB
119 }
120 }
121
3be11131 122 i = GPT_BYTE;
b45433b3
JB
123 to = GAP_END_ADDR;
124 from = GPT_ADDR;
3be11131 125 new_s1 = GPT_BYTE;
b45433b3
JB
126
127 /* Now copy the characters. To move the gap down,
128 copy characters up. */
129
130 while (1)
131 {
132 /* I gets number of characters left to copy. */
3be11131 133 i = new_s1 - bytepos;
b45433b3
JB
134 if (i == 0)
135 break;
136 /* If a quit is requested, stop copying now.
3be11131 137 Change BYTEPOS to be where we have actually moved the gap to. */
b45433b3
JB
138 if (QUITP)
139 {
3be11131
RS
140 bytepos = new_s1;
141 charpos = BYTE_TO_CHAR (bytepos);
b45433b3
JB
142 break;
143 }
144 /* Move at most 32000 chars before checking again for a quit. */
145 if (i > 32000)
146 i = 32000;
147#ifdef GAP_USE_BCOPY
148 if (i >= 128
149 /* bcopy is safe if the two areas of memory do not overlap
150 or on systems where bcopy is always safe for moving upward. */
151 && (BCOPY_UPWARD_SAFE
152 || to - from >= 128))
153 {
154 /* If overlap is not safe, avoid it by not moving too many
155 characters at once. */
156 if (!BCOPY_UPWARD_SAFE && i > to - from)
157 i = to - from;
158 new_s1 -= i;
159 from -= i, to -= i;
160 bcopy (from, to, i);
161 }
162 else
163#endif
164 {
165 new_s1 -= i;
166 while (--i >= 0)
167 *--to = *--from;
168 }
169 }
170
3be11131
RS
171 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
172 BYTEPOS is where the loop above stopped, which may be what was specified
b45433b3 173 or may be where a quit was detected. */
3be11131
RS
174 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
175 GPT_BYTE = bytepos;
176 GPT = charpos;
177 if (bytepos < charpos)
178 abort ();
469ff680 179 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
180 QUIT;
181}
182
3be11131
RS
183/* Move the gap to a position greater than than the current GPT.
184 BYTEPOS describes the new position as a byte position,
185 and CHARPOS is the corresponding char position. */
186
2bcaed71 187static void
3be11131
RS
188gap_right (charpos, bytepos)
189 register int charpos, bytepos;
b45433b3
JB
190{
191 register unsigned char *to, *from;
192 register int i;
193 int new_s1;
194
894ab630
RS
195 if (unchanged_modified == MODIFF
196 && overlay_unchanged_modified == OVERLAY_MODIFF)
b45433b3 197 {
3be11131
RS
198 beg_unchanged = charpos - BEG;
199 end_unchanged = Z - charpos;
b45433b3
JB
200 }
201 else
202 {
3be11131
RS
203 if (Z - charpos - 1 < end_unchanged)
204 end_unchanged = Z - charpos;
b45433b3
JB
205 if (GPT - BEG < beg_unchanged)
206 beg_unchanged = GPT - BEG;
207 }
208
3be11131 209 i = GPT_BYTE;
b45433b3
JB
210 from = GAP_END_ADDR;
211 to = GPT_ADDR;
3be11131 212 new_s1 = GPT_BYTE;
b45433b3
JB
213
214 /* Now copy the characters. To move the gap up,
215 copy characters down. */
216
217 while (1)
218 {
219 /* I gets number of characters left to copy. */
3be11131 220 i = bytepos - new_s1;
b45433b3
JB
221 if (i == 0)
222 break;
223 /* If a quit is requested, stop copying now.
3be11131 224 Change BYTEPOS to be where we have actually moved the gap to. */
b45433b3
JB
225 if (QUITP)
226 {
3be11131
RS
227 bytepos = new_s1;
228 charpos = BYTE_TO_CHAR (bytepos);
b45433b3
JB
229 break;
230 }
231 /* Move at most 32000 chars before checking again for a quit. */
232 if (i > 32000)
233 i = 32000;
234#ifdef GAP_USE_BCOPY
235 if (i >= 128
236 /* bcopy is safe if the two areas of memory do not overlap
237 or on systems where bcopy is always safe for moving downward. */
238 && (BCOPY_DOWNWARD_SAFE
239 || from - to >= 128))
240 {
241 /* If overlap is not safe, avoid it by not moving too many
242 characters at once. */
243 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
244 i = from - to;
245 new_s1 += i;
246 bcopy (from, to, i);
247 from += i, to += i;
248 }
249 else
250#endif
251 {
252 new_s1 += i;
253 while (--i >= 0)
254 *to++ = *from++;
255 }
256 }
257
3be11131
RS
258 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
259 - GAP_SIZE);
260 GPT = charpos;
261 GPT_BYTE = bytepos;
262 if (bytepos < charpos)
263 abort ();
469ff680 264 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3
JB
265 QUIT;
266}
2b083808 267\f
3be11131
RS
268/* Add AMOUNT to the byte position of every marker in the current buffer
269 whose current byte position is between FROM (exclusive) and TO (inclusive).
8948d317 270
b45433b3
JB
271 Also, any markers past the outside of that interval, in the direction
272 of adjustment, are first moved back to the near end of the interval
8948d317
RS
273 and then adjusted by AMOUNT.
274
275 When the latter adjustment is done, if AMOUNT is negative,
276 we record the adjustment for undo. (This case happens only for
3be11131
RS
277 deletion.)
278
279 The markers' character positions are not altered,
280 because gap motion does not affect character positions. */
281
282int adjust_markers_test;
b45433b3 283
2bcaed71 284static void
3be11131 285adjust_markers_gap_motion (from, to, amount)
b45433b3
JB
286 register int from, to, amount;
287{
80f6e77c
RS
288 /* Now that a marker has a bytepos, not counting the gap,
289 nothing needs to be done here. */
290#if 0
b45433b3
JB
291 Lisp_Object marker;
292 register struct Lisp_Marker *m;
293 register int mpos;
294
9fbf87cd 295 marker = BUF_MARKERS (current_buffer);
b45433b3 296
d427b66a 297 while (!NILP (marker))
b45433b3
JB
298 {
299 m = XMARKER (marker);
80f6e77c 300 mpos = m->bytepos;
b45433b3
JB
301 if (amount > 0)
302 {
303 if (mpos > to && mpos < to + amount)
3be11131
RS
304 {
305 if (adjust_markers_test)
306 abort ();
307 mpos = to + amount;
308 }
b45433b3
JB
309 }
310 else
311 {
8948d317
RS
312 /* Here's the case where a marker is inside text being deleted.
313 AMOUNT can be negative for gap motion, too,
314 but then this range contains no markers. */
b45433b3 315 if (mpos > from + amount && mpos <= from)
8948d317 316 {
3be11131
RS
317 if (adjust_markers_test)
318 abort ();
319 mpos = from + amount;
8948d317 320 }
b45433b3
JB
321 }
322 if (mpos > from && mpos <= to)
323 mpos += amount;
324 m->bufpos = mpos;
325 marker = m->chain;
326 }
80f6e77c 327#endif
b45433b3 328}
2b083808 329\f
3be11131
RS
330/* Adjust all markers for a deletion
331 whose range in bytes is FROM_BYTE to TO_BYTE.
332 The range in charpos is FROM to TO.
333
334 This function assumes that the gap is adjacent to
335 or inside of the range being deleted. */
beecb55b
RS
336
337static void
3be11131
RS
338adjust_markers_for_delete (from, from_byte, to, to_byte)
339 register int from, from_byte, to, to_byte;
340{
341 Lisp_Object marker;
342 register struct Lisp_Marker *m;
343 register int charpos;
344 /* This is what GAP_SIZE will be when this deletion is finished. */
345 int coming_gap_size = GAP_SIZE + to_byte - from_byte;
346
347 marker = BUF_MARKERS (current_buffer);
348
349 while (!NILP (marker))
350 {
351 m = XMARKER (marker);
352 charpos = m->charpos;
353
354 if (charpos > Z)
355 abort ();
356
357 /* If the marker is after the deletion,
80f6e77c 358 relocate by number of chars / bytes deleted. */
3be11131 359 if (charpos > to)
80f6e77c
RS
360 {
361 m->charpos -= to - from;
362 m->bytepos -= to_byte - from_byte;
363 }
3be11131 364
80f6e77c 365 /* Here's the case where a marker is inside text being deleted. */
3be11131
RS
366 else if (charpos > from)
367 {
368 record_marker_adjustment (marker, from - charpos);
369 m->charpos = from;
80f6e77c 370 m->bytepos = from_byte;
3be11131
RS
371 }
372
373 /* In a single-byte buffer, a marker's two positions must be equal. */
374 if (Z == Z_BYTE)
375 {
80f6e77c 376 register int i = m->bytepos;
3be11131 377
80f6e77c 378#if 0
3be11131
RS
379 /* We use FROM_BYTE here instead of GPT_BYTE
380 because FROM_BYTE is where the gap will be after the deletion. */
381 if (i > from_byte + coming_gap_size)
382 i -= coming_gap_size;
383 else if (i > from_byte)
384 i = from_byte;
80f6e77c 385#endif
3be11131
RS
386
387 if (m->charpos != i)
388 abort ();
389 }
390
391 marker = m->chain;
392 }
393}
2b083808 394\f
3be11131
RS
395/* Adjust markers for an insertion at CHARPOS / BYTEPOS
396 consisting of NCHARS chars, which are NBYTES bytes.
397
398 We have to relocate the charpos of every marker that points
80f6e77c 399 after the insertion (but not their bytepos).
3be11131
RS
400
401 When a marker points at the insertion point,
402 we advance it if either its insertion-type is t
403 or BEFORE_MARKERS is true. */
404
405static void
406adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
407 register int from, from_byte, to, to_byte, before_markers;
beecb55b
RS
408{
409 Lisp_Object marker;
469ff680 410 int adjusted = 0;
3be11131
RS
411 int nchars = to - from;
412 int nbytes = to_byte - from_byte;
beecb55b
RS
413
414 marker = BUF_MARKERS (current_buffer);
415
416 while (!NILP (marker))
417 {
418 register struct Lisp_Marker *m = XMARKER (marker);
80f6e77c 419 if (m->bytepos == from_byte
3be11131 420 && (m->insertion_type || before_markers))
469ff680 421 {
80f6e77c 422 m->bytepos += nbytes;
3be11131
RS
423 m->charpos += nchars;
424 if (m->insertion_type)
425 adjusted = 1;
469ff680 426 }
80f6e77c
RS
427 else if (m->bytepos > from_byte)
428 {
429 m->bytepos += nbytes;
430 m->charpos += nchars;
431 }
3be11131
RS
432
433 /* In a single-byte buffer, a marker's two positions must be equal. */
434 if (Z == Z_BYTE)
435 {
80f6e77c 436 register int i = m->bytepos;
3be11131 437
80f6e77c 438#if 0
3be11131
RS
439 if (i > GPT_BYTE + GAP_SIZE)
440 i -= GAP_SIZE;
441 else if (i > GPT_BYTE)
442 i = GPT_BYTE;
80f6e77c 443#endif
3be11131
RS
444
445 if (m->charpos != i)
446 abort ();
447 }
448
beecb55b
RS
449 marker = m->chain;
450 }
3be11131
RS
451
452 /* Adjusting only markers whose insertion-type is t may result in
453 disordered overlays in the slot `overlays_before'. */
469ff680 454 if (adjusted)
3be11131 455 fix_overlays_before (current_buffer, from, to);
beecb55b
RS
456}
457
3be11131
RS
458/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
459
460 This is used only when the value of point changes due to an insert
461 or delete; it does not represent a conceptual change in point as a
462 marker. In particular, point is not crossing any interval
463 boundaries, so there's no need to use the usual SET_PT macro. In
464 fact it would be incorrect to do so, because either the old or the
465 new value of point is out of sync with the current set of
466 intervals. */
467
a27a38d8 468static void
3be11131
RS
469adjust_point (nchars, nbytes)
470 int nchars, nbytes;
a27a38d8 471{
3be11131
RS
472 BUF_PT (current_buffer) += nchars;
473 BUF_PT_BYTE (current_buffer) += nbytes;
474
475 /* In a single-byte buffer, the two positions must be equal. */
476 if (ZV == ZV_BYTE
477 && PT != PT_BYTE)
478 abort ();
a27a38d8 479}
b45433b3 480\f
3be11131 481/* Make the gap NBYTES_ADDED bytes longer. */
b45433b3 482
c660b094 483void
3be11131
RS
484make_gap (nbytes_added)
485 int nbytes_added;
b45433b3
JB
486{
487 unsigned char *result;
488 Lisp_Object tem;
489 int real_gap_loc;
3be11131 490 int real_gap_loc_byte;
b45433b3
JB
491 int old_gap_size;
492
493 /* If we have to get more space, get enough to last a while. */
3be11131 494 nbytes_added += 2000;
b45433b3 495
94056516
RS
496 /* Don't allow a buffer size that won't fit in an int
497 even if it will fit in a Lisp integer.
498 That won't work because so many places use `int'. */
499
3be11131 500 if (Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added
68be917d 501 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
14f6194b 502 error ("Buffer exceeds maximum size");
94056516 503
9ac0d9e0 504 BLOCK_INPUT;
469ff680 505 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
3be11131
RS
506 result = BUFFER_REALLOC (BEG_ADDR, (Z_BYTE - BEG_BYTE
507 + GAP_SIZE + nbytes_added + 1));
9ac0d9e0 508
b45433b3 509 if (result == 0)
270c2138
RS
510 {
511 UNBLOCK_INPUT;
512 memory_full ();
513 }
514
515 /* We can't unblock until the new address is properly stored. */
b45433b3 516 BEG_ADDR = result;
270c2138 517 UNBLOCK_INPUT;
b45433b3
JB
518
519 /* Prevent quitting in move_gap. */
520 tem = Vinhibit_quit;
521 Vinhibit_quit = Qt;
522
523 real_gap_loc = GPT;
3be11131 524 real_gap_loc_byte = GPT_BYTE;
b45433b3
JB
525 old_gap_size = GAP_SIZE;
526
527 /* Call the newly allocated space a gap at the end of the whole space. */
528 GPT = Z + GAP_SIZE;
7d92db58 529 GPT_BYTE = Z_BYTE + GAP_SIZE;
3be11131 530 GAP_SIZE = nbytes_added;
b45433b3
JB
531
532 /* Move the new gap down to be consecutive with the end of the old one.
533 This adjusts the markers properly too. */
3be11131 534 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
b45433b3
JB
535
536 /* Now combine the two into one large gap. */
537 GAP_SIZE += old_gap_size;
538 GPT = real_gap_loc;
3be11131 539 GPT_BYTE = real_gap_loc_byte;
b45433b3 540
469ff680
KH
541 /* Put an anchor. */
542 *(Z_ADDR) = 0;
543
b45433b3
JB
544 Vinhibit_quit = tem;
545}
546\f
2b083808
RS
547/* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
548 FROM_MULTIBYTE says whether the incoming text is multibyte.
549 TO_MULTIBYTE says whether to store the text as multibyte.
550 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
551
552 Return the number of bytes stored at TO_ADDR. */
553
554int
555copy_text (from_addr, to_addr, nbytes,
556 from_multibyte, to_multibyte)
557 unsigned char *from_addr;
558 unsigned char *to_addr;
559 int nbytes;
560 int from_multibyte, to_multibyte;
561{
562 if (from_multibyte == to_multibyte)
563 {
564 bcopy (from_addr, to_addr, nbytes);
565 return nbytes;
566 }
567 else if (from_multibyte)
568 {
569 int nchars = 0;
570 int bytes_left = nbytes;
571
572 /* Convert multibyte to single byte. */
573 while (bytes_left > 0)
574 {
575 int thislen, c;
576 c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen);
cb97b980 577 *to_addr++ = SINGLE_BYTE_CHAR_P (c) ? c : (c & 0177) + 0200;
2b083808
RS
578 from_addr += thislen;
579 bytes_left--;
580 nchars++;
581 }
582 return nchars;
583 }
584 else
585 {
586 unsigned char *initial_to_addr = to_addr;
587
588 /* Convert single-byte to multibyte. */
589 while (nbytes > 0)
590 {
591 int c = *from_addr++;
592 unsigned char workbuf[4], *str;
593 int len;
594
595 if (c >= 0200 && c < 0400)
596 {
2c3af338
RS
597 if (! NILP (Vnonascii_translate_table))
598 c = XINT (Faref (Vnonascii_translate_table, make_number (c)));
599 else if (nonascii_insert_offset > 0)
2b083808
RS
600 c += nonascii_insert_offset;
601 else
602 c += DEFAULT_NONASCII_INSERT_OFFSET;
603
604 len = CHAR_STRING (c, workbuf, str);
605 bcopy (str, to_addr, len);
606 to_addr += len;
607 nbytes--;
608 }
609 else
610 /* Special case for speed. */
611 *to_addr++ = c, nbytes--;
612 }
613 return to_addr - initial_to_addr;
614 }
615}
616
617/* Return the number of bytes it would take
618 to convert some single-byte text to multibyte.
619 The single-byte text consists of NBYTES bytes at PTR. */
620
621int
622count_size_as_multibyte (ptr, nbytes)
623 unsigned char *ptr;
624 int nbytes;
625{
626 int i;
627 int outgoing_nbytes = 0;
628
629 for (i = 0; i < nbytes; i++)
630 {
631 unsigned int c = *ptr++;
632 if (c >= 0200 && c < 0400)
633 {
2c3af338
RS
634 if (! NILP (Vnonascii_translate_table))
635 c = XINT (Faref (Vnonascii_translate_table, make_number (c)));
636 else if (nonascii_insert_offset > 0)
2b083808
RS
637 c += nonascii_insert_offset;
638 else
639 c += DEFAULT_NONASCII_INSERT_OFFSET;
640 }
641 outgoing_nbytes += XINT (Fchar_bytes (make_number (c)));
642 }
643
644 return outgoing_nbytes;
645}
646\f
b45433b3 647/* Insert a string of specified length before point.
2b083808
RS
648 This function judges multibyteness based on
649 enable_multibyte_characters in the current buffer;
650 it never converts between single-byte and multibyte.
651
ef29f213
KH
652 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
653 prepare_to_modify_buffer could relocate the text. */
b45433b3 654
c660b094 655void
3be11131 656insert (string, nbytes)
b45433b3 657 register unsigned char *string;
3be11131 658 register nbytes;
b45433b3 659{
3be11131 660 if (nbytes > 0)
395ec62e 661 {
3be11131
RS
662 int opoint = PT;
663 insert_1 (string, nbytes, 0, 1, 0);
664 signal_after_change (opoint, 0, PT - opoint);
cd11ef31
RS
665 }
666}
667
2b083808
RS
668/* Likewise, but inherit text properties from neighboring characters. */
669
c660b094 670void
3be11131 671insert_and_inherit (string, nbytes)
cd11ef31 672 register unsigned char *string;
3be11131 673 register nbytes;
cd11ef31 674{
3be11131 675 if (nbytes > 0)
cd11ef31 676 {
3be11131
RS
677 int opoint = PT;
678 insert_1 (string, nbytes, 1, 1, 0);
679 signal_after_change (opoint, 0, PT - opoint);
395ec62e
KH
680 }
681}
b45433b3 682
2b083808 683/* Insert the character C before point. Do not inherit text properties. */
3be11131 684
c660b094 685void
3be11131
RS
686insert_char (c)
687 int c;
688{
689 unsigned char workbuf[4], *str;
2b083808
RS
690 int len;
691
692 if (! NILP (current_buffer->enable_multibyte_characters))
693 len = CHAR_STRING (c, workbuf, str);
694 else
695 {
696 len = 1;
697 workbuf[0] = c;
698 str = workbuf;
699 }
3be11131
RS
700
701 insert (str, len);
702}
703
2b083808 704/* Insert the null-terminated string S before point. */
3be11131
RS
705
706void
707insert_string (s)
708 char *s;
709{
710 insert (s, strlen (s));
711}
712
713/* Like `insert' except that all markers pointing at the place where
714 the insertion happens are adjusted to point after it.
715 Don't use this function to insert part of a Lisp string,
716 since gc could happen and relocate it. */
717
718void
719insert_before_markers (string, nbytes)
720 unsigned char *string;
721 register int nbytes;
722{
723 if (nbytes > 0)
724 {
725 int opoint = PT;
726
727 insert_1 (string, nbytes, 0, 1, 1);
728 signal_after_change (opoint, 0, PT - opoint);
729 }
730}
731
2b083808
RS
732/* Likewise, but inherit text properties from neighboring characters. */
733
3be11131
RS
734void
735insert_before_markers_and_inherit (string, nbytes)
736 unsigned char *string;
737 register int nbytes;
738{
739 if (nbytes > 0)
740 {
741 int opoint = PT;
742
743 insert_1 (string, nbytes, 1, 1, 1);
744 signal_after_change (opoint, 0, PT - opoint);
745 }
746}
2b083808 747\f
3be11131
RS
748/* Subroutine used by the insert functions above. */
749
750void
751insert_1 (string, nbytes, inherit, prepare, before_markers)
395ec62e 752 register unsigned char *string;
3be11131
RS
753 register int nbytes;
754 int inherit, prepare, before_markers;
395ec62e
KH
755{
756 register Lisp_Object temp;
3be11131 757 int nchars = chars_in_text (string, nbytes);
b45433b3 758
c660b094 759 if (prepare)
d206af14 760 prepare_to_modify_buffer (PT, PT, NULL);
b45433b3 761
2bcaed71 762 if (PT != GPT)
3be11131
RS
763 move_gap_both (PT, PT_BYTE);
764 if (GAP_SIZE < nbytes)
765 make_gap (nbytes - GAP_SIZE);
b45433b3 766
3be11131 767 record_insert (PT, nchars);
b45433b3
JB
768 MODIFF++;
769
3be11131 770 bcopy (string, GPT_ADDR, nbytes);
b45433b3 771
648c4c55 772#ifdef USE_TEXT_PROPERTIES
9fbf87cd 773 if (BUF_INTERVALS (current_buffer) != 0)
648c4c55 774 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
3be11131 775 offset_intervals (current_buffer, PT, nchars);
648c4c55 776#endif
679194a6 777
3be11131
RS
778 GAP_SIZE -= nbytes;
779 GPT += nchars;
780 ZV += nchars;
781 Z += nchars;
782 GPT_BYTE += nbytes;
783 ZV_BYTE += nbytes;
784 Z_BYTE += nbytes;
469ff680 785 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
3be11131
RS
786 adjust_overlays_for_insert (PT, nchars);
787 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes,
788 before_markers);
789 adjust_point (nchars, nbytes);
790
791 if (GPT_BYTE < GPT)
792 abort ();
cd11ef31 793
648c4c55 794#ifdef USE_TEXT_PROPERTIES
9fbf87cd 795 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
3be11131 796 Fset_text_properties (make_number (PT - nchars), make_number (PT),
cd11ef31 797 Qnil, Qnil);
648c4c55 798#endif
b45433b3 799}
2b083808
RS
800
801/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
802 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
803 are the same as in insert_1. */
804
805void
806insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
807 register unsigned char *string;
808 register int nchars, nbytes;
809 int inherit, prepare, before_markers;
810{
811 register Lisp_Object temp;
812
813 if (prepare)
814 prepare_to_modify_buffer (PT, PT, NULL);
815
816 if (PT != GPT)
817 move_gap_both (PT, PT_BYTE);
818 if (GAP_SIZE < nbytes)
819 make_gap (nbytes - GAP_SIZE);
820
821 record_insert (PT, nchars);
822 MODIFF++;
823
824 bcopy (string, GPT_ADDR, nbytes);
825
826#ifdef USE_TEXT_PROPERTIES
827 if (BUF_INTERVALS (current_buffer) != 0)
828 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
829 offset_intervals (current_buffer, PT, nchars);
830#endif
831
832 GAP_SIZE -= nbytes;
833 GPT += nchars;
834 ZV += nchars;
835 Z += nchars;
836 GPT_BYTE += nbytes;
837 ZV_BYTE += nbytes;
838 Z_BYTE += nbytes;
839 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
840 adjust_overlays_for_insert (PT, nchars);
841 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes,
842 before_markers);
843 adjust_point (nchars, nbytes);
844
845 if (GPT_BYTE < GPT)
846 abort ();
847
848#ifdef USE_TEXT_PROPERTIES
849 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
850 Fset_text_properties (make_number (PT - nchars), make_number (PT),
851 Qnil, Qnil);
852#endif
853}
3be11131 854\f
679194a6 855/* Insert the part of the text of STRING, a Lisp object assumed to be
2b083808
RS
856 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
857 starting at position POS / POS_BYTE. If the text of STRING has properties,
858 copy them into the buffer.
679194a6
JA
859
860 It does not work to use `insert' for this, because a GC could happen
7e1ea612
JB
861 before we bcopy the stuff into the buffer, and relocate the string
862 without insert noticing. */
679194a6 863
c660b094 864void
2b083808 865insert_from_string (string, pos, pos_byte, length, length_byte, inherit)
b45433b3 866 Lisp_Object string;
2b083808 867 register int pos, pos_byte, length, length_byte;
9391e591 868 int inherit;
395ec62e
KH
869{
870 if (length > 0)
871 {
3be11131 872 int opoint = PT;
2b083808
RS
873 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
874 inherit, 0);
3be11131 875 signal_after_change (opoint, 0, PT - opoint);
395ec62e
KH
876 }
877}
878
2b083808
RS
879/* Like `insert_from_string' except that all markers pointing
880 at the place where the insertion happens are adjusted to point after it. */
3be11131
RS
881
882void
2b083808
RS
883insert_from_string_before_markers (string, pos, pos_byte,
884 length, length_byte, inherit)
395ec62e 885 Lisp_Object string;
2b083808 886 register int pos, pos_byte, length, length_byte;
395ec62e 887 int inherit;
3be11131
RS
888{
889 if (length > 0)
890 {
891 int opoint = PT;
2b083808
RS
892 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
893 inherit, 1);
3be11131
RS
894 signal_after_change (opoint, 0, PT - opoint);
895 }
896}
897
898/* Subroutine of the insertion functions above. */
899
900static void
2b083808
RS
901insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
902 inherit, before_markers)
3be11131 903 Lisp_Object string;
2b083808 904 register int pos, pos_byte, nchars, nbytes;
3be11131 905 int inherit, before_markers;
b45433b3
JB
906{
907 register Lisp_Object temp;
908 struct gcpro gcpro1;
2b083808
RS
909 int outgoing_nbytes = nbytes;
910
911 /* Make OUTGOING_NBYTES describe the text
912 as it will be inserted in this buffer. */
913
914 if (NILP (current_buffer->enable_multibyte_characters))
915 outgoing_nbytes = nchars;
916 else if (nchars == nbytes)
917 outgoing_nbytes
918 = count_size_as_multibyte (&XSTRING (string)->data[pos_byte],
919 nbytes);
b45433b3 920
b45433b3 921 /* Make sure point-max won't overflow after this insertion. */
2b083808
RS
922 XSETINT (temp, outgoing_nbytes + Z);
923 if (outgoing_nbytes + Z != XINT (temp))
3be11131 924 error ("Maximum buffer size exceeded");
b45433b3
JB
925
926 GCPRO1 (string);
d206af14 927 prepare_to_modify_buffer (PT, PT, NULL);
b45433b3 928
2bcaed71 929 if (PT != GPT)
3be11131
RS
930 move_gap_both (PT, PT_BYTE);
931 if (GAP_SIZE < nbytes)
2b083808 932 make_gap (outgoing_nbytes - GAP_SIZE);
b45433b3 933
3be11131 934 record_insert (PT, nchars);
b45433b3
JB
935 MODIFF++;
936 UNGCPRO;
937
2b083808
RS
938 /* Copy the string text into the buffer, perhaps converting
939 between single-byte and multibyte. */
940 copy_text (XSTRING (string)->data + pos_byte, GPT_ADDR, nbytes,
941 /* If these are equal, it is a single-byte string.
942 Its chars are either ASCII, in which case copy_text
943 won't change it, or single-byte non-ASCII chars,
944 that need to be changed. */
945 nchars != nbytes,
946 ! NILP (current_buffer->enable_multibyte_characters));
b45433b3 947
679194a6 948 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3be11131
RS
949 offset_intervals (current_buffer, PT, nchars);
950
7792090e 951 GAP_SIZE -= outgoing_nbytes;
3be11131
RS
952 GPT += nchars;
953 ZV += nchars;
954 Z += nchars;
2b083808
RS
955 GPT_BYTE += outgoing_nbytes;
956 ZV_BYTE += outgoing_nbytes;
957 Z_BYTE += outgoing_nbytes;
469ff680 958 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
3be11131 959 adjust_overlays_for_insert (PT, nchars);
2b083808
RS
960 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
961 PT_BYTE + outgoing_nbytes,
3be11131
RS
962 before_markers);
963
964 if (GPT_BYTE < GPT)
965 abort ();
679194a6 966
3be11131 967 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, nchars,
9391e591 968 current_buffer, inherit);
679194a6 969
2b083808 970 adjust_point (nchars, outgoing_nbytes);
b45433b3 971}
3be11131
RS
972\f
973/* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
ef29f213
KH
974 current buffer. If the text in BUF has properties, they are absorbed
975 into the current buffer.
976
977 It does not work to use `insert' for this, because a malloc could happen
978 and relocate BUF's text before the bcopy happens. */
979
980void
3be11131 981insert_from_buffer (buf, charpos, nchars, inherit)
ef29f213 982 struct buffer *buf;
3be11131 983 int charpos, nchars;
ef29f213
KH
984 int inherit;
985{
3be11131 986 if (nchars > 0)
ef29f213 987 {
3be11131
RS
988 int opoint = PT;
989
990 insert_from_buffer_1 (buf, charpos, nchars, inherit);
991 signal_after_change (opoint, 0, PT - opoint);
ef29f213
KH
992 }
993}
994
995static void
3be11131 996insert_from_buffer_1 (buf, from, nchars, inherit)
ef29f213 997 struct buffer *buf;
3be11131 998 int from, nchars;
ef29f213
KH
999 int inherit;
1000{
1001 register Lisp_Object temp;
1002 int chunk;
3be11131
RS
1003 int from_byte = buf_charpos_to_bytepos (buf, from);
1004 int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
2b083808
RS
1005 int incoming_nbytes = to_byte - from_byte;
1006 int outgoing_nbytes = incoming_nbytes;
1007
1008 /* Make OUTGOING_NBYTES describe the text
1009 as it will be inserted in this buffer. */
1010
1011 if (NILP (current_buffer->enable_multibyte_characters))
1012 outgoing_nbytes = nchars;
1013 else if (NILP (buf->enable_multibyte_characters))
1014 outgoing_nbytes
1015 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
1016 incoming_nbytes);
ef29f213
KH
1017
1018 /* Make sure point-max won't overflow after this insertion. */
2b083808
RS
1019 XSETINT (temp, outgoing_nbytes + Z);
1020 if (outgoing_nbytes + Z != XINT (temp))
3be11131 1021 error ("Maximum buffer size exceeded");
ef29f213 1022
d206af14 1023 prepare_to_modify_buffer (PT, PT, NULL);
ef29f213
KH
1024
1025 if (PT != GPT)
3be11131 1026 move_gap_both (PT, PT_BYTE);
2b083808
RS
1027 if (GAP_SIZE < outgoing_nbytes)
1028 make_gap (outgoing_nbytes - GAP_SIZE);
ef29f213 1029
3be11131 1030 record_insert (PT, nchars);
ef29f213
KH
1031 MODIFF++;
1032
3be11131 1033 if (from < BUF_GPT (buf))
ef29f213 1034 {
3be11131 1035 chunk = BUF_GPT_BYTE (buf) - from_byte;
2b083808
RS
1036 if (chunk > incoming_nbytes)
1037 chunk = incoming_nbytes;
1038 copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
1039 GPT_ADDR, chunk,
1040 ! NILP (buf->enable_multibyte_characters),
1041 ! NILP (current_buffer->enable_multibyte_characters));
ef29f213
KH
1042 }
1043 else
1044 chunk = 0;
2b083808
RS
1045 if (chunk < incoming_nbytes)
1046 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
1047 GPT_ADDR + chunk, incoming_nbytes - chunk,
1048 ! NILP (buf->enable_multibyte_characters),
1049 ! NILP (current_buffer->enable_multibyte_characters));
ef29f213
KH
1050
1051#ifdef USE_TEXT_PROPERTIES
9fbf87cd 1052 if (BUF_INTERVALS (current_buffer) != 0)
3be11131 1053 offset_intervals (current_buffer, PT, nchars);
ef29f213
KH
1054#endif
1055
2b083808 1056 GAP_SIZE -= outgoing_nbytes;
3be11131
RS
1057 GPT += nchars;
1058 ZV += nchars;
1059 Z += nchars;
2b083808
RS
1060 GPT_BYTE += outgoing_nbytes;
1061 ZV_BYTE += outgoing_nbytes;
1062 Z_BYTE += outgoing_nbytes;
469ff680 1063 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
3be11131 1064 adjust_overlays_for_insert (PT, nchars);
2b083808
RS
1065 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1066 PT_BYTE + outgoing_nbytes, 0);
1067 adjust_point (nchars, outgoing_nbytes);
3be11131
RS
1068
1069 if (GPT_BYTE < GPT)
1070 abort ();
ef29f213
KH
1071
1072 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd 1073 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
3be11131
RS
1074 from, nchars),
1075 PT - nchars, nchars,
1076 current_buffer, inherit);
b45433b3
JB
1077}
1078\f
2d9eea44
KH
1079/* This function should be called after moving gap to FROM and before
1080 altering LEN chars of text starting from FROM. This adjusts
1081 various position keepers and markers and as if the text is deleted.
1082 Don't forget to call adjust_after_replace after you actually alter
1083 the text. */
1084
1e9c7b7d
KH
1085void
1086adjust_before_replace (from, from_byte, to, to_byte)
1087 int from, from_byte, to, to_byte;
1088{
1089 adjust_markers_for_delete (from, from_byte, to, to_byte);
1090 record_delete (from, to - from);
1091}
1092
2d9eea44
KH
1093/* This function should be called after altering the text between FROM
1094 and TO to a new text of LEN chars (LEN_BYTE bytes). */
1095
1e9c7b7d
KH
1096void
1097adjust_after_replace (from, from_byte, to, to_byte, len, len_byte)
1098 int from, from_byte, to, to_byte, len, len_byte;
1099{
1100 record_insert (from, len);
1101 if (from < PT)
2d9eea44 1102 adjust_point (len - (to - from), len_byte - (to_byte - from_byte));
1e9c7b7d
KH
1103#ifdef USE_TEXT_PROPERTIES
1104 offset_intervals (current_buffer, PT, len - (to - from));
1105#endif
1106 adjust_overlays_for_delete (from, to - from);
1107 adjust_overlays_for_insert (from, len);
1108 adjust_markers_for_insert (from, from_byte,
1109 from + len, from_byte + len_byte, 0);
1110 if (len == 0)
1111 evaporate_overlays (from);
1112 MODIFF++;
1e9c7b7d
KH
1113}
1114
3be11131 1115/* Replace the text from character positions FROM to TO with NEW,
c5ca4d3a
RS
1116 If PREPARE is nonzero, call prepare_to_modify_buffer.
1117 If INHERIT, the newly inserted text should inherit text properties
1118 from the surrounding non-deleted text. */
1119
1120/* Note that this does not yet handle markers quite right.
1121 Also it needs to record a single undo-entry that does a replacement
1122 rather than a separate delete and insert.
1123 That way, undo will also handle markers properly. */
1124
1125void
1126replace_range (from, to, new, prepare, inherit)
1127 Lisp_Object new;
1128 int from, to, prepare, inherit;
1129{
2b083808
RS
1130 int inschars = XSTRING (new)->size;
1131 int insbytes = XSTRING (new)->size_byte;
3be11131
RS
1132 int from_byte, to_byte;
1133 int nbytes_del, nchars_del;
c5ca4d3a
RS
1134 register Lisp_Object temp;
1135 struct gcpro gcpro1;
1136
1137 GCPRO1 (new);
1138
1139 if (prepare)
1140 {
1141 int range_length = to - from;
1142 prepare_to_modify_buffer (from, to, &from);
1143 to = from + range_length;
1144 }
1145
3be11131
RS
1146 UNGCPRO;
1147
c5ca4d3a
RS
1148 /* Make args be valid */
1149 if (from < BEGV)
1150 from = BEGV;
1151 if (to > ZV)
1152 to = ZV;
1153
3be11131
RS
1154 from_byte = CHAR_TO_BYTE (from);
1155 to_byte = CHAR_TO_BYTE (to);
c5ca4d3a 1156
3be11131
RS
1157 nchars_del = to - from;
1158 nbytes_del = to_byte - from_byte;
1159
1160 if (nbytes_del <= 0 && insbytes == 0)
1161 return;
c5ca4d3a
RS
1162
1163 /* Make sure point-max won't overflow after this insertion. */
3be11131
RS
1164 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
1165 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
1166 error ("Maximum buffer size exceeded");
c5ca4d3a 1167
c5ca4d3a
RS
1168 GCPRO1 (new);
1169
1170 /* Make sure the gap is somewhere in or next to what we are deleting. */
1171 if (from > GPT)
3be11131 1172 gap_right (from, from_byte);
c5ca4d3a 1173 if (to < GPT)
3be11131 1174 gap_left (to, to_byte, 0);
c5ca4d3a
RS
1175
1176 /* Relocate all markers pointing into the new, larger gap
1177 to point at the end of the text before the gap.
3be11131
RS
1178 Do this before recording the deletion,
1179 so that undo handles this after reinserting the text. */
1180 adjust_markers_for_delete (from, from_byte, to, to_byte);
c5ca4d3a 1181
3be11131 1182 record_delete (from, nchars_del);
c5ca4d3a 1183
3be11131
RS
1184 GAP_SIZE += nbytes_del;
1185 ZV -= nchars_del;
1186 Z -= nchars_del;
1187 ZV_BYTE -= nbytes_del;
1188 Z_BYTE -= nbytes_del;
c5ca4d3a 1189 GPT = from;
3be11131 1190 GPT_BYTE = from_byte;
c5ca4d3a
RS
1191 *(GPT_ADDR) = 0; /* Put an anchor. */
1192
3be11131
RS
1193 if (GPT_BYTE < GPT)
1194 abort ();
1195
c5ca4d3a
RS
1196 if (GPT - BEG < beg_unchanged)
1197 beg_unchanged = GPT - BEG;
1198 if (Z - GPT < end_unchanged)
1199 end_unchanged = Z - GPT;
1200
3be11131
RS
1201 if (GAP_SIZE < insbytes)
1202 make_gap (insbytes - GAP_SIZE);
c5ca4d3a 1203
3be11131 1204 record_insert (from, inschars);
c5ca4d3a 1205
3be11131 1206 bcopy (XSTRING (new)->data, GPT_ADDR, insbytes);
c5ca4d3a
RS
1207
1208 /* Relocate point as if it were a marker. */
1209 if (from < PT)
3be11131
RS
1210 adjust_point (from + inschars - (PT < to ? PT : to),
1211 (from_byte + insbytes
1212 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
c5ca4d3a
RS
1213
1214#ifdef USE_TEXT_PROPERTIES
3be11131 1215 offset_intervals (current_buffer, PT, inschars - nchars_del);
c5ca4d3a
RS
1216#endif
1217
3be11131
RS
1218 GAP_SIZE -= insbytes;
1219 GPT += inschars;
1220 ZV += inschars;
1221 Z += inschars;
1222 GPT_BYTE += insbytes;
1223 ZV_BYTE += insbytes;
1224 ZV_BYTE += insbytes;
c5ca4d3a
RS
1225 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
1226
3be11131
RS
1227 if (GPT_BYTE < GPT)
1228 abort ();
1229
c5ca4d3a
RS
1230 /* Adjust the overlay center as needed. This must be done after
1231 adjusting the markers that bound the overlays. */
3be11131
RS
1232 adjust_overlays_for_delete (from, nchars_del);
1233 adjust_overlays_for_insert (from, inschars);
1234 adjust_markers_for_insert (from, from_byte, from + inschars,
1235 from_byte + insbytes, 0);
c5ca4d3a
RS
1236
1237#ifdef USE_TEXT_PROPERTIES
1238 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3be11131
RS
1239 graft_intervals_into_buffer (XSTRING (new)->intervals, from,
1240 inschars, current_buffer, inherit);
c5ca4d3a
RS
1241#endif
1242
3be11131 1243 if (insbytes == 0)
c5ca4d3a
RS
1244 evaporate_overlays (from);
1245
1246 MODIFF++;
1247 UNGCPRO;
1248
3be11131 1249 signal_after_change (from, nchars_del, inschars);
c5ca4d3a
RS
1250}
1251\f
b45433b3 1252/* Delete characters in current buffer
3be11131
RS
1253 from FROM up to (but not including) TO.
1254 If TO comes before FROM, we delete nothing. */
b45433b3 1255
c660b094 1256void
b45433b3
JB
1257del_range (from, to)
1258 register int from, to;
47c64747 1259{
c660b094 1260 del_range_1 (from, to, 1);
47c64747
RS
1261}
1262
1263/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
1264
c660b094 1265void
47c64747 1266del_range_1 (from, to, prepare)
d206af14 1267 int from, to, prepare;
b45433b3 1268{
3be11131
RS
1269 int from_byte, to_byte;
1270
1271 /* Make args be valid */
1272 if (from < BEGV)
1273 from = BEGV;
1274 if (to > ZV)
1275 to = ZV;
1276
1277 if (to <= from)
1278 return;
1279
1280 if (prepare)
1281 {
1282 int range_length = to - from;
1283 prepare_to_modify_buffer (from, to, &from);
1284 to = from + range_length;
1285 }
1286
1287 from_byte = CHAR_TO_BYTE (from);
1288 to_byte = CHAR_TO_BYTE (to);
1289
a66afea0 1290 del_range_2 (from, from_byte, to, to_byte);
3be11131
RS
1291}
1292
1293/* Like del_range_1 but args are byte positions, not char positions. */
1294
1295void
1296del_range_byte (from_byte, to_byte, prepare)
1297 int from_byte, to_byte, prepare;
1298{
1299 int from, to;
1300
1301 /* Make args be valid */
1302 if (from_byte < BEGV_BYTE)
1303 from_byte = BEGV_BYTE;
1304 if (to_byte > ZV_BYTE)
1305 to_byte = ZV_BYTE;
1306
1307 if (to_byte <= from_byte)
1308 return;
1309
1310 from = BYTE_TO_CHAR (from_byte);
1311 to = BYTE_TO_CHAR (to_byte);
b45433b3 1312
d206af14
RS
1313 if (prepare)
1314 {
3be11131 1315 int old_from = from, old_to = Z - to;
d206af14
RS
1316 int range_length = to - from;
1317 prepare_to_modify_buffer (from, to, &from);
1318 to = from + range_length;
3be11131
RS
1319
1320 if (old_from != from)
1321 from_byte = CHAR_TO_BYTE (from);
1322 if (old_to == Z - to)
1323 to_byte = CHAR_TO_BYTE (to);
d206af14
RS
1324 }
1325
a66afea0 1326 del_range_2 (from, from_byte, to, to_byte);
3be11131
RS
1327}
1328
1329/* Like del_range_1, but positions are specified both as charpos
1330 and bytepos. */
1331
1332void
353800c7
KH
1333del_range_both (from, from_byte, to, to_byte, prepare)
1334 int from, from_byte, to, to_byte, prepare;
3be11131 1335{
b45433b3 1336 /* Make args be valid */
3be11131
RS
1337 if (from_byte < BEGV_BYTE)
1338 from_byte = BEGV_BYTE;
1339 if (to_byte > ZV_BYTE)
1340 to_byte = ZV_BYTE;
1341
1342 if (to_byte <= from_byte)
1343 return;
1344
b45433b3
JB
1345 if (from < BEGV)
1346 from = BEGV;
1347 if (to > ZV)
1348 to = ZV;
1349
3be11131
RS
1350 if (prepare)
1351 {
1352 int old_from = from, old_to = Z - to;
1353 int range_length = to - from;
1354 prepare_to_modify_buffer (from, to, &from);
1355 to = from + range_length;
1356
1357 if (old_from != from)
1358 from_byte = CHAR_TO_BYTE (from);
1359 if (old_to == Z - to)
1360 to_byte = CHAR_TO_BYTE (to);
1361 }
1362
a66afea0 1363 del_range_2 (from, from_byte, to, to_byte);
3be11131
RS
1364}
1365
1366/* Delete a range of text, specified both as character positions
1367 and byte positions. FROM and TO are character positions,
1368 while FROM_BYTE and TO_BYTE are byte positions. */
1369
1370void
a66afea0
KH
1371del_range_2 (from, from_byte, to, to_byte)
1372 int from, from_byte, to, to_byte;
3be11131
RS
1373{
1374 register int nbytes_del, nchars_del;
1375
1376 nchars_del = to - from;
1377 nbytes_del = to_byte - from_byte;
b45433b3
JB
1378
1379 /* Make sure the gap is somewhere in or next to what we are deleting. */
1380 if (from > GPT)
3be11131 1381 gap_right (from, from_byte);
b45433b3 1382 if (to < GPT)
3be11131 1383 gap_left (to, to_byte, 0);
b45433b3 1384
8948d317
RS
1385 /* Relocate all markers pointing into the new, larger gap
1386 to point at the end of the text before the gap.
3be11131
RS
1387 Do this before recording the deletion,
1388 so that undo handles this after reinserting the text. */
1389 adjust_markers_for_delete (from, from_byte, to, to_byte);
8948d317 1390
3be11131 1391 record_delete (from, nchars_del);
be09561e
RS
1392 MODIFF++;
1393
b45433b3 1394 /* Relocate point as if it were a marker. */
2bcaed71 1395 if (from < PT)
3be11131
RS
1396 adjust_point (from - (PT < to ? PT : to),
1397 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
b45433b3 1398
16032db6 1399 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3be11131 1400 offset_intervals (current_buffer, from, - nchars_del);
16032db6 1401
adde4858 1402 /* Adjust the overlay center as needed. This must be done after
a7f38d28 1403 adjusting the markers that bound the overlays. */
3be11131 1404 adjust_overlays_for_delete (from_byte, nchars_del);
adde4858 1405
3be11131
RS
1406 GAP_SIZE += nbytes_del;
1407 ZV_BYTE -= nbytes_del;
1408 Z_BYTE -= nbytes_del;
1409 ZV -= nchars_del;
1410 Z -= nchars_del;
b45433b3 1411 GPT = from;
3be11131 1412 GPT_BYTE = from_byte;
469ff680 1413 *(GPT_ADDR) = 0; /* Put an anchor. */
b45433b3 1414
3be11131
RS
1415 if (GPT_BYTE < GPT)
1416 abort ();
1417
b45433b3
JB
1418 if (GPT - BEG < beg_unchanged)
1419 beg_unchanged = GPT - BEG;
1420 if (Z - GPT < end_unchanged)
1421 end_unchanged = Z - GPT;
1422
d386034e 1423 evaporate_overlays (from);
3be11131 1424 signal_after_change (from, nchars_del, 0);
b45433b3
JB
1425}
1426\f
3be11131
RS
1427/* Call this if you're about to change the region of BUFFER from
1428 character positions START to END. This checks the read-only
1429 properties of the region, calls the necessary modification hooks,
1430 and warns the next redisplay that it should pay attention to that
1431 area. */
1432
c660b094 1433void
04a759c8
JB
1434modify_region (buffer, start, end)
1435 struct buffer *buffer;
b45433b3
JB
1436 int start, end;
1437{
04a759c8
JB
1438 struct buffer *old_buffer = current_buffer;
1439
1440 if (buffer != old_buffer)
1441 set_buffer_internal (buffer);
1442
d206af14 1443 prepare_to_modify_buffer (start, end, NULL);
b45433b3 1444
894ab630
RS
1445 if (start - 1 < beg_unchanged
1446 || (unchanged_modified == MODIFF
1447 && overlay_unchanged_modified == OVERLAY_MODIFF))
b45433b3
JB
1448 beg_unchanged = start - 1;
1449 if (Z - end < end_unchanged
894ab630
RS
1450 || (unchanged_modified == MODIFF
1451 && overlay_unchanged_modified == OVERLAY_MODIFF))
b45433b3 1452 end_unchanged = Z - end;
83010cd6 1453
9fbf87cd 1454 if (MODIFF <= SAVE_MODIFF)
83010cd6 1455 record_first_change ();
b45433b3 1456 MODIFF++;
04a759c8 1457
069cdc4f
RS
1458 buffer->point_before_scroll = Qnil;
1459
04a759c8
JB
1460 if (buffer != old_buffer)
1461 set_buffer_internal (old_buffer);
b45433b3 1462}
d206af14 1463\f
3be11131
RS
1464/* Check that it is okay to modify the buffer between START and END,
1465 which are char positions.
1466
679194a6
JA
1467 Run the before-change-function, if any. If intervals are in use,
1468 verify that the text to be modified is not read-only, and call
d206af14
RS
1469 any modification properties the text may have.
1470
1471 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1472 by holding its value temporarily in a marker. */
b45433b3 1473
c660b094 1474void
d206af14 1475prepare_to_modify_buffer (start, end, preserve_ptr)
fb4ee5cd 1476 int start, end;
d206af14 1477 int *preserve_ptr;
b45433b3 1478{
d427b66a 1479 if (!NILP (current_buffer->read_only))
b45433b3
JB
1480 Fbarf_if_buffer_read_only ();
1481
679194a6 1482 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
9fbf87cd 1483 if (BUF_INTERVALS (current_buffer) != 0)
d206af14
RS
1484 {
1485 if (preserve_ptr)
1486 {
1487 Lisp_Object preserve_marker;
1488 struct gcpro gcpro1;
1489 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
1490 GCPRO1 (preserve_marker);
1491 verify_interval_modification (current_buffer, start, end);
1492 *preserve_ptr = marker_position (preserve_marker);
1493 unchain_marker (preserve_marker);
1494 UNGCPRO;
1495 }
1496 else
1497 verify_interval_modification (current_buffer, start, end);
1498 }
b45433b3
JB
1499
1500#ifdef CLASH_DETECTION
f173b650 1501 if (!NILP (current_buffer->file_truename)
ab6c5c0c
RS
1502 /* Make binding buffer-file-name to nil effective. */
1503 && !NILP (current_buffer->filename)
9fbf87cd 1504 && SAVE_MODIFF >= MODIFF)
f173b650 1505 lock_file (current_buffer->file_truename);
b45433b3
JB
1506#else
1507 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 1508 if (!NILP (current_buffer->filename)
9fbf87cd 1509 && SAVE_MODIFF >= MODIFF
d427b66a
JB
1510 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
1511 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
1512 call1 (intern ("ask-user-about-supersession-threat"),
1513 current_buffer->filename);
1514#endif /* not CLASH_DETECTION */
1515
d206af14 1516 signal_before_change (start, end, preserve_ptr);
2f545eea 1517
56e1065e
JB
1518 if (current_buffer->newline_cache)
1519 invalidate_region_cache (current_buffer,
1520 current_buffer->newline_cache,
1521 start - BEG, Z - end);
1522 if (current_buffer->width_run_cache)
1523 invalidate_region_cache (current_buffer,
1524 current_buffer->width_run_cache,
1525 start - BEG, Z - end);
1526
2f545eea 1527 Vdeactivate_mark = Qt;
b45433b3
JB
1528}
1529\f
d206af14
RS
1530/* These macros work with an argument named `preserve_ptr'
1531 and a local variable named `preserve_marker'. */
1532
1533#define PRESERVE_VALUE \
1534 if (preserve_ptr && NILP (preserve_marker)) \
1535 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
1536
1537#define RESTORE_VALUE \
1538 if (! NILP (preserve_marker)) \
1539 { \
1540 *preserve_ptr = marker_position (preserve_marker); \
1541 unchain_marker (preserve_marker); \
1542 }
1543
b86e0aaf
RS
1544#define PRESERVE_START_END \
1545 if (NILP (start_marker)) \
1546 start_marker = Fcopy_marker (start, Qnil); \
1547 if (NILP (end_marker)) \
1548 end_marker = Fcopy_marker (end, Qnil);
1549
1550#define FETCH_START \
1551 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
1552
1553#define FETCH_END \
1554 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
1555
eb8c3be9 1556/* Signal a change to the buffer immediately before it happens.
d206af14
RS
1557 START_INT and END_INT are the bounds of the text to be changed.
1558
1559 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1560 by holding its value temporarily in a marker. */
b45433b3 1561
c660b094 1562void
d206af14 1563signal_before_change (start_int, end_int, preserve_ptr)
6022d493 1564 int start_int, end_int;
d206af14 1565 int *preserve_ptr;
b45433b3 1566{
fb4ee5cd 1567 Lisp_Object start, end;
b86e0aaf 1568 Lisp_Object start_marker, end_marker;
d206af14 1569 Lisp_Object preserve_marker;
b86e0aaf 1570 struct gcpro gcpro1, gcpro2, gcpro3;
fb4ee5cd
RS
1571
1572 start = make_number (start_int);
1573 end = make_number (end_int);
d206af14 1574 preserve_marker = Qnil;
b86e0aaf
RS
1575 start_marker = Qnil;
1576 end_marker = Qnil;
1577 GCPRO3 (preserve_marker, start_marker, end_marker);
fb4ee5cd 1578
b45433b3 1579 /* If buffer is unmodified, run a special hook for that case. */
9fbf87cd 1580 if (SAVE_MODIFF >= MODIFF
dbc4e1c1
JB
1581 && !NILP (Vfirst_change_hook)
1582 && !NILP (Vrun_hooks))
d206af14
RS
1583 {
1584 PRESERVE_VALUE;
b86e0aaf 1585 PRESERVE_START_END;
d206af14
RS
1586 call1 (Vrun_hooks, Qfirst_change_hook);
1587 }
dbc4e1c1 1588
3d1e2d9c
RS
1589 /* Run the before-change-function if any.
1590 We don't bother "binding" this variable to nil
1591 because it is obsolete anyway and new code should not use it. */
d427b66a 1592 if (!NILP (Vbefore_change_function))
d206af14
RS
1593 {
1594 PRESERVE_VALUE;
b86e0aaf
RS
1595 PRESERVE_START_END;
1596 call2 (Vbefore_change_function, FETCH_START, FETCH_END);
d206af14 1597 }
e45fb8bf 1598
3d1e2d9c 1599 /* Now run the before-change-functions if any. */
e45fb8bf
RS
1600 if (!NILP (Vbefore_change_functions))
1601 {
3d1e2d9c
RS
1602 Lisp_Object args[3];
1603 Lisp_Object before_change_functions;
1604 Lisp_Object after_change_functions;
1605 struct gcpro gcpro1, gcpro2;
1606
d206af14 1607 PRESERVE_VALUE;
b86e0aaf 1608 PRESERVE_START_END;
d206af14 1609
3d1e2d9c
RS
1610 /* "Bind" before-change-functions and after-change-functions
1611 to nil--but in a way that errors don't know about.
1612 That way, if there's an error in them, they will stay nil. */
1613 before_change_functions = Vbefore_change_functions;
1614 after_change_functions = Vafter_change_functions;
c82c1da0
KH
1615 Vbefore_change_functions = Qnil;
1616 Vafter_change_functions = Qnil;
3d1e2d9c
RS
1617 GCPRO2 (before_change_functions, after_change_functions);
1618
1619 /* Actually run the hook functions. */
1620 args[0] = Qbefore_change_functions;
b86e0aaf
RS
1621 args[1] = FETCH_START;
1622 args[2] = FETCH_END;
3d1e2d9c
RS
1623 run_hook_list_with_args (before_change_functions, 3, args);
1624
1625 /* "Unbind" the variables we "bound" to nil. */
1626 Vbefore_change_functions = before_change_functions;
1627 Vafter_change_functions = after_change_functions;
1628 UNGCPRO;
e45fb8bf 1629 }
d07c0804
RS
1630
1631 if (!NILP (current_buffer->overlays_before)
1632 || !NILP (current_buffer->overlays_after))
d206af14
RS
1633 {
1634 PRESERVE_VALUE;
b86e0aaf
RS
1635 report_overlay_modification (FETCH_START, FETCH_END, 0,
1636 FETCH_START, FETCH_END, Qnil);
d206af14
RS
1637 }
1638
b86e0aaf
RS
1639 if (! NILP (start_marker))
1640 free_marker (start_marker);
1641 if (! NILP (end_marker))
1642 free_marker (end_marker);
d206af14
RS
1643 RESTORE_VALUE;
1644 UNGCPRO;
b45433b3
JB
1645}
1646
eb8c3be9 1647/* Signal a change immediately after it happens.
3be11131 1648 CHARPOS is the character position of the start of the changed text.
b45433b3
JB
1649 LENDEL is the number of characters of the text before the change.
1650 (Not the whole buffer; just the part that was changed.)
8b09e5d0
RS
1651 LENINS is the number of characters in that part of the text
1652 after the change. */
b45433b3 1653
c660b094 1654void
3be11131
RS
1655signal_after_change (charpos, lendel, lenins)
1656 int charpos, lendel, lenins;
b45433b3 1657{
fb2e7d14
RS
1658 /* If we are deferring calls to the after-change functions
1659 and there are no before-change functions,
1660 just record the args that we were going to use. */
1661 if (! NILP (Vcombine_after_change_calls)
1662 && NILP (Vbefore_change_function) && NILP (Vbefore_change_functions)
1663 && NILP (current_buffer->overlays_before)
1664 && NILP (current_buffer->overlays_after))
1665 {
1666 Lisp_Object elt;
1667
1668 if (!NILP (combine_after_change_list)
1669 && current_buffer != XBUFFER (combine_after_change_buffer))
1670 Fcombine_after_change_execute ();
1671
3be11131
RS
1672 elt = Fcons (make_number (charpos - BEG),
1673 Fcons (make_number (Z - (charpos - lendel + lenins)),
fb2e7d14
RS
1674 Fcons (make_number (lenins - lendel), Qnil)));
1675 combine_after_change_list
1676 = Fcons (elt, combine_after_change_list);
1677 combine_after_change_buffer = Fcurrent_buffer ();
1678
1679 return;
1680 }
1681
1682 if (!NILP (combine_after_change_list))
1683 Fcombine_after_change_execute ();
1684
3d1e2d9c
RS
1685 /* Run the after-change-function if any.
1686 We don't bother "binding" this variable to nil
1687 because it is obsolete anyway and new code should not use it. */
d427b66a 1688 if (!NILP (Vafter_change_function))
3d1e2d9c 1689 call3 (Vafter_change_function,
3be11131 1690 make_number (charpos), make_number (charpos + lenins),
3d1e2d9c 1691 make_number (lendel));
b45433b3 1692
e45fb8bf
RS
1693 if (!NILP (Vafter_change_functions))
1694 {
3d1e2d9c
RS
1695 Lisp_Object args[4];
1696 Lisp_Object before_change_functions;
1697 Lisp_Object after_change_functions;
1698 struct gcpro gcpro1, gcpro2;
1699
1700 /* "Bind" before-change-functions and after-change-functions
1701 to nil--but in a way that errors don't know about.
1702 That way, if there's an error in them, they will stay nil. */
1703 before_change_functions = Vbefore_change_functions;
1704 after_change_functions = Vafter_change_functions;
c82c1da0
KH
1705 Vbefore_change_functions = Qnil;
1706 Vafter_change_functions = Qnil;
3d1e2d9c
RS
1707 GCPRO2 (before_change_functions, after_change_functions);
1708
1709 /* Actually run the hook functions. */
1710 args[0] = Qafter_change_functions;
3be11131
RS
1711 XSETFASTINT (args[1], charpos);
1712 XSETFASTINT (args[2], charpos + lenins);
3d1e2d9c
RS
1713 XSETFASTINT (args[3], lendel);
1714 run_hook_list_with_args (after_change_functions,
1715 4, args);
1716
1717 /* "Unbind" the variables we "bound" to nil. */
1718 Vbefore_change_functions = before_change_functions;
1719 Vafter_change_functions = after_change_functions;
1720 UNGCPRO;
e45fb8bf 1721 }
d07c0804
RS
1722
1723 if (!NILP (current_buffer->overlays_before)
1724 || !NILP (current_buffer->overlays_after))
3be11131
RS
1725 report_overlay_modification (make_number (charpos),
1726 make_number (charpos + lenins),
d07c0804 1727 1,
3be11131
RS
1728 make_number (charpos),
1729 make_number (charpos + lenins),
d07c0804 1730 make_number (lendel));
c5ca0786
RS
1731
1732 /* After an insertion, call the text properties
1733 insert-behind-hooks or insert-in-front-hooks. */
1734 if (lendel == 0)
3be11131 1735 report_interval_modification (charpos, charpos + lenins);
b45433b3 1736}
fb2e7d14
RS
1737
1738Lisp_Object
1739Fcombine_after_change_execute_1 (val)
1740 Lisp_Object val;
1741{
1742 Vcombine_after_change_calls = val;
1743 return val;
1744}
1745
1746DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
1747 Scombine_after_change_execute, 0, 0, 0,
1748 "This function is for use internally in `combine-after-change-calls'.")
1749 ()
1750{
1751 register Lisp_Object val;
1752 int count = specpdl_ptr - specpdl;
1753 int beg, end, change;
1754 int begpos, endpos;
1755 Lisp_Object tail;
1756
1757 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
1758
1759 Fset_buffer (combine_after_change_buffer);
1760
1761 /* # chars unchanged at beginning of buffer. */
1762 beg = Z - BEG;
1763 /* # chars unchanged at end of buffer. */
1764 end = beg;
1765 /* Total amount of insertion (negative for deletion). */
1766 change = 0;
1767
1768 /* Scan the various individual changes,
1769 accumulating the range info in BEG, END and CHANGE. */
1770 for (tail = combine_after_change_list; CONSP (tail);
1771 tail = XCONS (tail)->cdr)
1772 {
e688a080
KH
1773 Lisp_Object elt;
1774 int thisbeg, thisend, thischange;
fb2e7d14
RS
1775
1776 /* Extract the info from the next element. */
1777 elt = XCONS (tail)->car;
1778 if (! CONSP (elt))
1779 continue;
1780 thisbeg = XINT (XCONS (elt)->car);
1781
1782 elt = XCONS (elt)->cdr;
1783 if (! CONSP (elt))
1784 continue;
1785 thisend = XINT (XCONS (elt)->car);
1786
1787 elt = XCONS (elt)->cdr;
1788 if (! CONSP (elt))
1789 continue;
1790 thischange = XINT (XCONS (elt)->car);
1791
1792 /* Merge this range into the accumulated range. */
1793 change += thischange;
1794 if (thisbeg < beg)
1795 beg = thisbeg;
1796 if (thisend < end)
1797 end = thisend;
1798 }
1799
1800 /* Get the current start and end positions of the range
1801 that was changed. */
1802 begpos = BEG + beg;
1803 endpos = Z - end;
1804
1805 /* We are about to handle these, so discard them. */
1806 combine_after_change_list = Qnil;
1807
1808 /* Now run the after-change functions for real.
1809 Turn off the flag that defers them. */
1810 record_unwind_protect (Fcombine_after_change_execute_1,
1811 Vcombine_after_change_calls);
1812 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
1813
1814 return unbind_to (count, val);
1815}
1816\f
1817syms_of_insdel ()
1818{
1819 staticpro (&combine_after_change_list);
1820 combine_after_change_list = Qnil;
1821
1822 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
1823 "Used internally by the `combine-after-change-calls' macro.");
1824 Vcombine_after_change_calls = Qnil;
1825
1826 defsubr (&Scombine_after_change_execute);
1827}