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