(Vafter_change_functions, Vbefore_change_functions): Declared.
[bpt/emacs.git] / src / insdel.c
CommitLineData
b45433b3 1/* Buffer insertion/deletion and gap motion for GNU Emacs.
2f545eea 2 Copyright (C) 1985, 1986, 1993 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
8the Free Software Foundation; either version 1, or (at your option)
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
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
18160b98 21#include <config.h>
b45433b3 22#include "lisp.h"
679194a6 23#include "intervals.h"
b45433b3
JB
24#include "buffer.h"
25#include "window.h"
d014bf88 26#include "blockinput.h"
b45433b3 27
395ec62e
KH
28static void insert_1 ();
29static void insert_from_string_1 ();
30
b45433b3
JB
31/* Move gap to position `pos'.
32 Note that this can quit! */
33
34move_gap (pos)
35 int pos;
36{
37 if (pos < GPT)
38 gap_left (pos, 0);
39 else if (pos > GPT)
40 gap_right (pos);
41}
42
43/* Move the gap to POS, which is less than the current GPT.
44 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
45
46gap_left (pos, newgap)
47 register int pos;
48 int newgap;
49{
50 register unsigned char *to, *from;
51 register int i;
52 int new_s1;
53
54 pos--;
55
56 if (!newgap)
57 {
58 if (unchanged_modified == MODIFF)
59 {
60 beg_unchanged = pos;
61 end_unchanged = Z - pos - 1;
62 }
63 else
64 {
65 if (Z - GPT < end_unchanged)
66 end_unchanged = Z - GPT;
67 if (pos < beg_unchanged)
68 beg_unchanged = pos;
69 }
70 }
71
72 i = GPT;
73 to = GAP_END_ADDR;
74 from = GPT_ADDR;
75 new_s1 = GPT - BEG;
76
77 /* Now copy the characters. To move the gap down,
78 copy characters up. */
79
80 while (1)
81 {
82 /* I gets number of characters left to copy. */
83 i = new_s1 - pos;
84 if (i == 0)
85 break;
86 /* If a quit is requested, stop copying now.
87 Change POS to be where we have actually moved the gap to. */
88 if (QUITP)
89 {
90 pos = new_s1;
91 break;
92 }
93 /* Move at most 32000 chars before checking again for a quit. */
94 if (i > 32000)
95 i = 32000;
96#ifdef GAP_USE_BCOPY
97 if (i >= 128
98 /* bcopy is safe if the two areas of memory do not overlap
99 or on systems where bcopy is always safe for moving upward. */
100 && (BCOPY_UPWARD_SAFE
101 || to - from >= 128))
102 {
103 /* If overlap is not safe, avoid it by not moving too many
104 characters at once. */
105 if (!BCOPY_UPWARD_SAFE && i > to - from)
106 i = to - from;
107 new_s1 -= i;
108 from -= i, to -= i;
109 bcopy (from, to, i);
110 }
111 else
112#endif
113 {
114 new_s1 -= i;
115 while (--i >= 0)
116 *--to = *--from;
117 }
118 }
119
120 /* Adjust markers, and buffer data structure, to put the gap at POS.
121 POS is where the loop above stopped, which may be what was specified
122 or may be where a quit was detected. */
123 adjust_markers (pos + 1, GPT, GAP_SIZE);
124 GPT = pos + 1;
125 QUIT;
126}
127
128gap_right (pos)
129 register int pos;
130{
131 register unsigned char *to, *from;
132 register int i;
133 int new_s1;
134
135 pos--;
136
137 if (unchanged_modified == MODIFF)
138 {
139 beg_unchanged = pos;
140 end_unchanged = Z - pos - 1;
141 }
142 else
143 {
144 if (Z - pos - 1 < end_unchanged)
145 end_unchanged = Z - pos - 1;
146 if (GPT - BEG < beg_unchanged)
147 beg_unchanged = GPT - BEG;
148 }
149
150 i = GPT;
151 from = GAP_END_ADDR;
152 to = GPT_ADDR;
153 new_s1 = GPT - 1;
154
155 /* Now copy the characters. To move the gap up,
156 copy characters down. */
157
158 while (1)
159 {
160 /* I gets number of characters left to copy. */
161 i = pos - new_s1;
162 if (i == 0)
163 break;
164 /* If a quit is requested, stop copying now.
165 Change POS to be where we have actually moved the gap to. */
166 if (QUITP)
167 {
168 pos = new_s1;
169 break;
170 }
171 /* Move at most 32000 chars before checking again for a quit. */
172 if (i > 32000)
173 i = 32000;
174#ifdef GAP_USE_BCOPY
175 if (i >= 128
176 /* bcopy is safe if the two areas of memory do not overlap
177 or on systems where bcopy is always safe for moving downward. */
178 && (BCOPY_DOWNWARD_SAFE
179 || from - to >= 128))
180 {
181 /* If overlap is not safe, avoid it by not moving too many
182 characters at once. */
183 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
184 i = from - to;
185 new_s1 += i;
186 bcopy (from, to, i);
187 from += i, to += i;
188 }
189 else
190#endif
191 {
192 new_s1 += i;
193 while (--i >= 0)
194 *to++ = *from++;
195 }
196 }
197
198 adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
199 GPT = pos + 1;
200 QUIT;
201}
202
203/* Add `amount' to the position of every marker in the current buffer
204 whose current position is between `from' (exclusive) and `to' (inclusive).
205 Also, any markers past the outside of that interval, in the direction
206 of adjustment, are first moved back to the near end of the interval
207 and then adjusted by `amount'. */
208
209adjust_markers (from, to, amount)
210 register int from, to, amount;
211{
212 Lisp_Object marker;
213 register struct Lisp_Marker *m;
214 register int mpos;
215
216 marker = current_buffer->markers;
217
d427b66a 218 while (!NILP (marker))
b45433b3
JB
219 {
220 m = XMARKER (marker);
221 mpos = m->bufpos;
222 if (amount > 0)
223 {
224 if (mpos > to && mpos < to + amount)
225 mpos = to + amount;
226 }
227 else
228 {
229 if (mpos > from + amount && mpos <= from)
230 mpos = from + amount;
231 }
232 if (mpos > from && mpos <= to)
233 mpos += amount;
234 m->bufpos = mpos;
235 marker = m->chain;
236 }
237}
238\f
239/* Make the gap INCREMENT characters longer. */
240
241make_gap (increment)
242 int increment;
243{
244 unsigned char *result;
245 Lisp_Object tem;
246 int real_gap_loc;
247 int old_gap_size;
248
249 /* If we have to get more space, get enough to last a while. */
250 increment += 2000;
251
9ac0d9e0 252 BLOCK_INPUT;
b45433b3 253 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
9ac0d9e0
JB
254 UNBLOCK_INPUT;
255
b45433b3
JB
256 if (result == 0)
257 memory_full ();
258 BEG_ADDR = result;
259
260 /* Prevent quitting in move_gap. */
261 tem = Vinhibit_quit;
262 Vinhibit_quit = Qt;
263
264 real_gap_loc = GPT;
265 old_gap_size = GAP_SIZE;
266
267 /* Call the newly allocated space a gap at the end of the whole space. */
268 GPT = Z + GAP_SIZE;
269 GAP_SIZE = increment;
270
271 /* Move the new gap down to be consecutive with the end of the old one.
272 This adjusts the markers properly too. */
273 gap_left (real_gap_loc + old_gap_size, 1);
274
275 /* Now combine the two into one large gap. */
276 GAP_SIZE += old_gap_size;
277 GPT = real_gap_loc;
278
279 Vinhibit_quit = tem;
280}
281\f
282/* Insert a string of specified length before point.
283 DO NOT use this for the contents of a Lisp string!
284 prepare_to_modify_buffer could relocate the string. */
285
286insert (string, length)
287 register unsigned char *string;
288 register length;
289{
395ec62e
KH
290 if (length > 0)
291 {
292 insert_1 (string, length);
293 signal_after_change (point-length, 0, length);
294 }
295}
b45433b3 296
395ec62e
KH
297static void
298insert_1 (string, length)
299 register unsigned char *string;
300 register length;
301{
302 register Lisp_Object temp;
b45433b3
JB
303
304 /* Make sure point-max won't overflow after this insertion. */
305 XSET (temp, Lisp_Int, length + Z);
306 if (length + Z != XINT (temp))
307 error ("maximum buffer size exceeded");
308
309 prepare_to_modify_buffer (point, point);
310
311 if (point != GPT)
312 move_gap (point);
313 if (GAP_SIZE < length)
314 make_gap (length - GAP_SIZE);
315
316 record_insert (point, length);
317 MODIFF++;
318
319 bcopy (string, GPT_ADDR, length);
320
679194a6
JA
321 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
322 offset_intervals (current_buffer, point, length);
323
b45433b3
JB
324 GAP_SIZE -= length;
325 GPT += length;
326 ZV += length;
327 Z += length;
328 SET_PT (point + length);
b45433b3
JB
329}
330
679194a6
JA
331/* Insert the part of the text of STRING, a Lisp object assumed to be
332 of type string, consisting of the LENGTH characters starting at
333 position POS. If the text of STRING has properties, they are absorbed
334 into the buffer.
335
336 It does not work to use `insert' for this, because a GC could happen
7e1ea612
JB
337 before we bcopy the stuff into the buffer, and relocate the string
338 without insert noticing. */
679194a6 339
9391e591 340insert_from_string (string, pos, length, inherit)
b45433b3
JB
341 Lisp_Object string;
342 register int pos, length;
9391e591 343 int inherit;
395ec62e
KH
344{
345 if (length > 0)
346 {
347 insert_from_string_1 (string, pos, length, inherit);
348 signal_after_change (point-length, 0, length);
349 }
350}
351
352static void
353insert_from_string_1 (string, pos, length, inherit)
354 Lisp_Object string;
355 register int pos, length;
356 int inherit;
b45433b3
JB
357{
358 register Lisp_Object temp;
359 struct gcpro gcpro1;
360
b45433b3
JB
361 /* Make sure point-max won't overflow after this insertion. */
362 XSET (temp, Lisp_Int, length + Z);
363 if (length + Z != XINT (temp))
364 error ("maximum buffer size exceeded");
365
366 GCPRO1 (string);
367 prepare_to_modify_buffer (point, point);
368
369 if (point != GPT)
370 move_gap (point);
371 if (GAP_SIZE < length)
372 make_gap (length - GAP_SIZE);
373
374 record_insert (point, length);
375 MODIFF++;
376 UNGCPRO;
377
378 bcopy (XSTRING (string)->data, GPT_ADDR, length);
379
679194a6
JA
380 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
381 offset_intervals (current_buffer, point, length);
382
b45433b3
JB
383 GAP_SIZE -= length;
384 GPT += length;
385 ZV += length;
386 Z += length;
679194a6
JA
387
388 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
af9015f9 389 graft_intervals_into_buffer (XSTRING (string)->intervals, point, length,
9391e591 390 current_buffer, inherit);
679194a6 391
d427b66a 392 SET_PT (point + length);
b45433b3
JB
393}
394
395/* Insert the character C before point */
396
397void
398insert_char (c)
399 unsigned char c;
400{
401 insert (&c, 1);
402}
403
404/* Insert the null-terminated string S before point */
405
406void
407insert_string (s)
408 char *s;
409{
410 insert (s, strlen (s));
411}
412
413/* Like `insert' except that all markers pointing at the place where
414 the insertion happens are adjusted to point after it.
415 Don't use this function to insert part of a Lisp string,
416 since gc could happen and relocate it. */
417
418insert_before_markers (string, length)
419 unsigned char *string;
420 register int length;
421{
395ec62e
KH
422 if (length > 0)
423 {
424 register int opoint = point;
425 insert_1 (string, length);
426 adjust_markers (opoint - 1, opoint, length);
427 signal_after_change (point-length, 0, length);
428 }
b45433b3
JB
429}
430
431/* Insert part of a Lisp string, relocating markers after. */
432
9391e591 433insert_from_string_before_markers (string, pos, length, inherit)
b45433b3
JB
434 Lisp_Object string;
435 register int pos, length;
9391e591 436 int inherit;
b45433b3 437{
395ec62e
KH
438 if (length > 0)
439 {
440 register int opoint = point;
441 insert_from_string_1 (string, pos, length, inherit);
442 adjust_markers (opoint - 1, opoint, length);
443 signal_after_change (point-length, 0, length);
444 }
b45433b3
JB
445}
446\f
447/* Delete characters in current buffer
448 from FROM up to (but not including) TO. */
449
450del_range (from, to)
451 register int from, to;
47c64747
RS
452{
453 return del_range_1 (from, to, 1);
454}
455
456/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
457
458del_range_1 (from, to, prepare)
459 register int from, to, prepare;
b45433b3
JB
460{
461 register int numdel;
462
463 /* Make args be valid */
464 if (from < BEGV)
465 from = BEGV;
466 if (to > ZV)
467 to = ZV;
468
469 if ((numdel = to - from) <= 0)
470 return;
471
472 /* Make sure the gap is somewhere in or next to what we are deleting. */
473 if (from > GPT)
474 gap_right (from);
475 if (to < GPT)
476 gap_left (to, 0);
477
47c64747
RS
478 if (prepare)
479 prepare_to_modify_buffer (from, to);
b45433b3 480
be09561e
RS
481 record_delete (from, numdel);
482 MODIFF++;
483
b45433b3
JB
484 /* Relocate point as if it were a marker. */
485 if (from < point)
486 {
487 if (point < to)
488 SET_PT (from);
489 else
490 SET_PT (point - numdel);
491 }
492
16032db6 493 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
83010cd6 494 offset_intervals (current_buffer, from, - numdel);
16032db6 495
b45433b3
JB
496 /* Relocate all markers pointing into the new, larger gap
497 to point at the end of the text before the gap. */
498 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
499
500 GAP_SIZE += numdel;
501 ZV -= numdel;
502 Z -= numdel;
503 GPT = from;
504
505 if (GPT - BEG < beg_unchanged)
506 beg_unchanged = GPT - BEG;
507 if (Z - GPT < end_unchanged)
508 end_unchanged = Z - GPT;
509
510 signal_after_change (from, numdel, 0);
511}
512\f
04a759c8
JB
513/* Call this if you're about to change the region of BUFFER from START
514 to END. This checks the read-only properties of the region, calls
515 the necessary modification hooks, and warns the next redisplay that
516 it should pay attention to that area. */
517modify_region (buffer, start, end)
518 struct buffer *buffer;
b45433b3
JB
519 int start, end;
520{
04a759c8
JB
521 struct buffer *old_buffer = current_buffer;
522
523 if (buffer != old_buffer)
524 set_buffer_internal (buffer);
525
b45433b3
JB
526 prepare_to_modify_buffer (start, end);
527
528 if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
529 beg_unchanged = start - 1;
530 if (Z - end < end_unchanged
531 || unchanged_modified == MODIFF)
532 end_unchanged = Z - end;
83010cd6
RS
533
534 if (MODIFF <= current_buffer->save_modified)
535 record_first_change ();
b45433b3 536 MODIFF++;
04a759c8
JB
537
538 if (buffer != old_buffer)
539 set_buffer_internal (old_buffer);
b45433b3
JB
540}
541
542/* Check that it is okay to modify the buffer between START and END.
679194a6
JA
543 Run the before-change-function, if any. If intervals are in use,
544 verify that the text to be modified is not read-only, and call
545 any modification properties the text may have. */
b45433b3
JB
546
547prepare_to_modify_buffer (start, end)
548 Lisp_Object start, end;
549{
d427b66a 550 if (!NILP (current_buffer->read_only))
b45433b3
JB
551 Fbarf_if_buffer_read_only ();
552
679194a6
JA
553 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
554 verify_interval_modification (current_buffer, start, end);
b45433b3 555
f256353c
RS
556 verify_overlay_modification (start, end);
557
b45433b3 558#ifdef CLASH_DETECTION
d427b66a 559 if (!NILP (current_buffer->filename)
b45433b3
JB
560 && current_buffer->save_modified >= MODIFF)
561 lock_file (current_buffer->filename);
562#else
563 /* At least warn if this file has changed on disk since it was visited. */
d427b66a 564 if (!NILP (current_buffer->filename)
b45433b3 565 && current_buffer->save_modified >= MODIFF
d427b66a
JB
566 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
567 && !NILP (Ffile_exists_p (current_buffer->filename)))
b45433b3
JB
568 call1 (intern ("ask-user-about-supersession-threat"),
569 current_buffer->filename);
570#endif /* not CLASH_DETECTION */
571
572 signal_before_change (start, end);
2f545eea
RS
573
574 Vdeactivate_mark = Qt;
b45433b3
JB
575}
576\f
577static Lisp_Object
578before_change_function_restore (value)
579 Lisp_Object value;
580{
581 Vbefore_change_function = value;
582}
583
584static Lisp_Object
585after_change_function_restore (value)
586 Lisp_Object value;
587{
588 Vafter_change_function = value;
589}
590
eb8c3be9 591/* Signal a change to the buffer immediately before it happens.
b45433b3
JB
592 START and END are the bounds of the text to be changed,
593 as Lisp objects. */
594
595signal_before_change (start, end)
596 Lisp_Object start, end;
597{
598 /* If buffer is unmodified, run a special hook for that case. */
599 if (current_buffer->save_modified >= MODIFF
dbc4e1c1
JB
600 && !NILP (Vfirst_change_hook)
601 && !NILP (Vrun_hooks))
602 call1 (Vrun_hooks, Qfirst_change_hook);
603
b45433b3 604 /* Now in any case run the before-change-function if any. */
d427b66a 605 if (!NILP (Vbefore_change_function))
b45433b3
JB
606 {
607 int count = specpdl_ptr - specpdl;
608 Lisp_Object function;
609
610 function = Vbefore_change_function;
611 record_unwind_protect (after_change_function_restore,
612 Vafter_change_function);
613 record_unwind_protect (before_change_function_restore,
614 Vbefore_change_function);
615 Vafter_change_function = Qnil;
616 Vbefore_change_function = Qnil;
617
618 call2 (function, start, end);
619 unbind_to (count, Qnil);
620 }
621}
622
eb8c3be9 623/* Signal a change immediately after it happens.
b45433b3
JB
624 POS is the address of the start of the changed text.
625 LENDEL is the number of characters of the text before the change.
626 (Not the whole buffer; just the part that was changed.)
627 LENINS is the number of characters in the changed text. */
628
629signal_after_change (pos, lendel, lenins)
630 int pos, lendel, lenins;
631{
d427b66a 632 if (!NILP (Vafter_change_function))
b45433b3
JB
633 {
634 int count = specpdl_ptr - specpdl;
635 Lisp_Object function;
636 function = Vafter_change_function;
637
638 record_unwind_protect (after_change_function_restore,
639 Vafter_change_function);
640 record_unwind_protect (before_change_function_restore,
641 Vbefore_change_function);
642 Vafter_change_function = Qnil;
643 Vbefore_change_function = Qnil;
644
645 call3 (function, make_number (pos), make_number (pos + lenins),
646 make_number (lendel));
647 unbind_to (count, Qnil);
648 }
649}