1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include "intervals.h"
26 #include "blockinput.h"
28 static void insert_1 ();
29 static void insert_from_string_1 ();
30 static void gap_left ();
31 static void gap_right ();
32 static void adjust_markers ();
33 static void adjust_point ();
35 /* Move gap to position `pos'.
36 Note that this can quit! */
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. */
51 gap_left (pos
, newgap
)
55 register unsigned char *to
, *from
;
63 if (unchanged_modified
== MODIFF
)
66 end_unchanged
= Z
- pos
- 1;
70 if (Z
- GPT
< end_unchanged
)
71 end_unchanged
= Z
- GPT
;
72 if (pos
< beg_unchanged
)
82 /* Now copy the characters. To move the gap down,
83 copy characters up. */
87 /* I gets number of characters left to copy. */
91 /* If a quit is requested, stop copying now.
92 Change POS to be where we have actually moved the gap to. */
98 /* Move at most 32000 chars before checking again for a quit. */
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))
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
)
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
);
137 register unsigned char *to
, *from
;
143 if (unchanged_modified
== MODIFF
)
146 end_unchanged
= Z
- pos
- 1;
150 if (Z
- pos
- 1 < end_unchanged
)
151 end_unchanged
= Z
- pos
- 1;
152 if (GPT
- BEG
< beg_unchanged
)
153 beg_unchanged
= GPT
- BEG
;
161 /* Now copy the characters. To move the gap up,
162 copy characters down. */
166 /* I gets number of characters left to copy. */
170 /* If a quit is requested, stop copying now.
171 Change POS to be where we have actually moved the gap to. */
177 /* Move at most 32000 chars before checking again for a quit. */
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))
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
)
204 adjust_markers (GPT
+ GAP_SIZE
, pos
+ 1 + GAP_SIZE
, - GAP_SIZE
);
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'. */
216 adjust_markers (from
, to
, amount
)
217 register int from
, to
, amount
;
220 register struct Lisp_Marker
*m
;
223 marker
= current_buffer
->markers
;
225 while (!NILP (marker
))
227 m
= XMARKER (marker
);
231 if (mpos
> to
&& mpos
< to
+ amount
)
236 if (mpos
> from
+ amount
&& mpos
<= from
)
237 mpos
= from
+ amount
;
239 if (mpos
> from
&& mpos
<= to
)
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. */
254 adjust_point (amount
)
256 current_buffer
->text
.pt
+= amount
;
259 /* Make the gap INCREMENT characters longer. */
264 unsigned char *result
;
269 /* If we have to get more space, get enough to last a while. */
273 result
= BUFFER_REALLOC (BEG_ADDR
, (Z
- BEG
+ GAP_SIZE
+ increment
));
280 /* Prevent quitting in move_gap. */
285 old_gap_size
= GAP_SIZE
;
287 /* Call the newly allocated space a gap at the end of the whole space. */
289 GAP_SIZE
= increment
;
291 /* Move the new gap down to be consecutive with the end of the old one.
292 This adjusts the markers properly too. */
293 gap_left (real_gap_loc
+ old_gap_size
, 1);
295 /* Now combine the two into one large gap. */
296 GAP_SIZE
+= old_gap_size
;
302 /* Insert a string of specified length before point.
303 DO NOT use this for the contents of a Lisp string!
304 prepare_to_modify_buffer could relocate the string. */
306 insert (string
, length
)
307 register unsigned char *string
;
312 insert_1 (string
, length
, 0);
313 signal_after_change (PT
-length
, 0, length
);
317 insert_and_inherit (string
, length
)
318 register unsigned char *string
;
323 insert_1 (string
, length
, 1);
324 signal_after_change (PT
-length
, 0, length
);
329 insert_1 (string
, length
, inherit
)
330 register unsigned char *string
;
334 register Lisp_Object temp
;
336 /* Make sure point-max won't overflow after this insertion. */
337 XSET (temp
, Lisp_Int
, length
+ Z
);
338 if (length
+ Z
!= XINT (temp
))
339 error ("maximum buffer size exceeded");
341 prepare_to_modify_buffer (PT
, PT
);
345 if (GAP_SIZE
< length
)
346 make_gap (length
- GAP_SIZE
);
348 record_insert (PT
, length
);
351 bcopy (string
, GPT_ADDR
, length
);
353 #ifdef USE_TEXT_PROPERTIES
354 if (current_buffer
->intervals
!= 0)
355 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
356 offset_intervals (current_buffer
, PT
, length
);
363 adjust_point (length
);
365 #ifdef USE_TEXT_PROPERTIES
366 if (!inherit
&& current_buffer
->intervals
!= 0)
367 Fset_text_properties (make_number (PT
- length
), make_number (PT
),
372 /* Insert the part of the text of STRING, a Lisp object assumed to be
373 of type string, consisting of the LENGTH characters starting at
374 position POS. If the text of STRING has properties, they are absorbed
377 It does not work to use `insert' for this, because a GC could happen
378 before we bcopy the stuff into the buffer, and relocate the string
379 without insert noticing. */
381 insert_from_string (string
, pos
, length
, inherit
)
383 register int pos
, length
;
388 insert_from_string_1 (string
, pos
, length
, inherit
);
389 signal_after_change (PT
-length
, 0, length
);
394 insert_from_string_1 (string
, pos
, length
, inherit
)
396 register int pos
, length
;
399 register Lisp_Object temp
;
402 /* Make sure point-max won't overflow after this insertion. */
403 XSET (temp
, Lisp_Int
, length
+ Z
);
404 if (length
+ Z
!= XINT (temp
))
405 error ("maximum buffer size exceeded");
408 prepare_to_modify_buffer (PT
, PT
);
412 if (GAP_SIZE
< length
)
413 make_gap (length
- GAP_SIZE
);
415 record_insert (PT
, length
);
419 bcopy (XSTRING (string
)->data
, GPT_ADDR
, length
);
421 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
422 offset_intervals (current_buffer
, PT
, length
);
429 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
430 graft_intervals_into_buffer (XSTRING (string
)->intervals
, PT
, length
,
431 current_buffer
, inherit
);
433 adjust_point (length
);
436 /* Insert the character C before point */
445 /* Insert the null-terminated string S before point */
451 insert (s
, strlen (s
));
454 /* Like `insert' except that all markers pointing at the place where
455 the insertion happens are adjusted to point after it.
456 Don't use this function to insert part of a Lisp string,
457 since gc could happen and relocate it. */
459 insert_before_markers (string
, length
)
460 unsigned char *string
;
465 register int opoint
= PT
;
466 insert_1 (string
, length
, 1);
467 adjust_markers (opoint
- 1, opoint
, length
);
468 signal_after_change (PT
-length
, 0, length
);
472 insert_before_markers_and_inherit (string
, length
)
473 unsigned char *string
;
478 register int opoint
= PT
;
479 insert_1 (string
, length
, 1);
480 adjust_markers (opoint
- 1, opoint
, length
);
481 signal_after_change (PT
-length
, 0, length
);
485 /* Insert part of a Lisp string, relocating markers after. */
487 insert_from_string_before_markers (string
, pos
, length
, inherit
)
489 register int pos
, length
;
494 register int opoint
= PT
;
495 insert_from_string_1 (string
, pos
, length
, inherit
);
496 adjust_markers (opoint
- 1, opoint
, length
);
497 signal_after_change (PT
-length
, 0, length
);
501 /* Delete characters in current buffer
502 from FROM up to (but not including) TO. */
505 register int from
, to
;
507 return del_range_1 (from
, to
, 1);
510 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
512 del_range_1 (from
, to
, prepare
)
513 register int from
, to
, prepare
;
517 /* Make args be valid */
523 if ((numdel
= to
- from
) <= 0)
526 /* Make sure the gap is somewhere in or next to what we are deleting. */
533 prepare_to_modify_buffer (from
, to
);
535 record_delete (from
, numdel
);
538 /* Relocate point as if it were a marker. */
540 adjust_point (from
- (PT
< to
? PT
: to
));
542 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
543 offset_intervals (current_buffer
, from
, - numdel
);
545 /* Relocate all markers pointing into the new, larger gap
546 to point at the end of the text before the gap. */
547 adjust_markers (to
+ GAP_SIZE
, to
+ GAP_SIZE
, - numdel
- GAP_SIZE
);
554 if (GPT
- BEG
< beg_unchanged
)
555 beg_unchanged
= GPT
- BEG
;
556 if (Z
- GPT
< end_unchanged
)
557 end_unchanged
= Z
- GPT
;
559 evaporate_overlays (from
);
560 signal_after_change (from
, numdel
, 0);
563 /* Call this if you're about to change the region of BUFFER from START
564 to END. This checks the read-only properties of the region, calls
565 the necessary modification hooks, and warns the next redisplay that
566 it should pay attention to that area. */
567 modify_region (buffer
, start
, end
)
568 struct buffer
*buffer
;
571 struct buffer
*old_buffer
= current_buffer
;
573 if (buffer
!= old_buffer
)
574 set_buffer_internal (buffer
);
576 prepare_to_modify_buffer (start
, end
);
578 if (start
- 1 < beg_unchanged
|| unchanged_modified
== MODIFF
)
579 beg_unchanged
= start
- 1;
580 if (Z
- end
< end_unchanged
581 || unchanged_modified
== MODIFF
)
582 end_unchanged
= Z
- end
;
584 if (MODIFF
<= current_buffer
->save_modified
)
585 record_first_change ();
588 if (buffer
!= old_buffer
)
589 set_buffer_internal (old_buffer
);
592 /* Check that it is okay to modify the buffer between START and END.
593 Run the before-change-function, if any. If intervals are in use,
594 verify that the text to be modified is not read-only, and call
595 any modification properties the text may have. */
597 prepare_to_modify_buffer (start
, end
)
598 Lisp_Object start
, end
;
600 if (!NILP (current_buffer
->read_only
))
601 Fbarf_if_buffer_read_only ();
603 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
604 if (current_buffer
->intervals
!= 0)
605 verify_interval_modification (current_buffer
, start
, end
);
607 if (!NILP (current_buffer
->overlays_before
)
608 || !NILP (current_buffer
->overlays_after
))
609 verify_overlay_modification (start
, end
);
611 #ifdef CLASH_DETECTION
612 if (!NILP (current_buffer
->filename
)
613 && current_buffer
->save_modified
>= MODIFF
)
614 lock_file (current_buffer
->filename
);
616 /* At least warn if this file has changed on disk since it was visited. */
617 if (!NILP (current_buffer
->filename
)
618 && current_buffer
->save_modified
>= MODIFF
619 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
620 && !NILP (Ffile_exists_p (current_buffer
->filename
)))
621 call1 (intern ("ask-user-about-supersession-threat"),
622 current_buffer
->filename
);
623 #endif /* not CLASH_DETECTION */
625 signal_before_change (start
, end
);
627 Vdeactivate_mark
= Qt
;
631 before_change_function_restore (value
)
634 Vbefore_change_function
= value
;
638 after_change_function_restore (value
)
641 Vafter_change_function
= value
;
645 before_change_functions_restore (value
)
648 Vbefore_change_functions
= value
;
652 after_change_functions_restore (value
)
655 Vafter_change_functions
= value
;
658 /* Signal a change to the buffer immediately before it happens.
659 START and END are the bounds of the text to be changed,
662 signal_before_change (start
, end
)
663 Lisp_Object start
, end
;
665 /* If buffer is unmodified, run a special hook for that case. */
666 if (current_buffer
->save_modified
>= MODIFF
667 && !NILP (Vfirst_change_hook
)
668 && !NILP (Vrun_hooks
))
669 call1 (Vrun_hooks
, Qfirst_change_hook
);
671 /* Now in any case run the before-change-function if any. */
672 if (!NILP (Vbefore_change_function
))
674 int count
= specpdl_ptr
- specpdl
;
675 Lisp_Object function
;
677 function
= Vbefore_change_function
;
679 record_unwind_protect (after_change_function_restore
,
680 Vafter_change_function
);
681 record_unwind_protect (before_change_function_restore
,
682 Vbefore_change_function
);
683 record_unwind_protect (after_change_functions_restore
,
684 Vafter_change_functions
);
685 record_unwind_protect (before_change_functions_restore
,
686 Vbefore_change_functions
);
687 Vafter_change_function
= Qnil
;
688 Vbefore_change_function
= Qnil
;
689 Vafter_change_functions
= Qnil
;
690 Vbefore_change_functions
= Qnil
;
692 call2 (function
, start
, end
);
693 unbind_to (count
, Qnil
);
696 /* Now in any case run the before-change-function if any. */
697 if (!NILP (Vbefore_change_functions
))
699 int count
= specpdl_ptr
- specpdl
;
700 Lisp_Object functions
;
702 functions
= Vbefore_change_functions
;
704 record_unwind_protect (after_change_function_restore
,
705 Vafter_change_function
);
706 record_unwind_protect (before_change_function_restore
,
707 Vbefore_change_function
);
708 record_unwind_protect (after_change_functions_restore
,
709 Vafter_change_functions
);
710 record_unwind_protect (before_change_functions_restore
,
711 Vbefore_change_functions
);
712 Vafter_change_function
= Qnil
;
713 Vbefore_change_function
= Qnil
;
714 Vafter_change_functions
= Qnil
;
715 Vbefore_change_functions
= Qnil
;
717 while (CONSP (functions
))
719 call2 (XCONS (functions
)->car
, start
, end
);
720 functions
= XCONS (functions
)->cdr
;
722 unbind_to (count
, Qnil
);
726 /* Signal a change immediately after it happens.
727 POS is the address of the start of the changed text.
728 LENDEL is the number of characters of the text before the change.
729 (Not the whole buffer; just the part that was changed.)
730 LENINS is the number of characters in the changed text. */
732 signal_after_change (pos
, lendel
, lenins
)
733 int pos
, lendel
, lenins
;
735 if (!NILP (Vafter_change_function
))
737 int count
= specpdl_ptr
- specpdl
;
738 Lisp_Object function
;
739 function
= Vafter_change_function
;
741 record_unwind_protect (after_change_function_restore
,
742 Vafter_change_function
);
743 record_unwind_protect (before_change_function_restore
,
744 Vbefore_change_function
);
745 record_unwind_protect (after_change_functions_restore
,
746 Vafter_change_functions
);
747 record_unwind_protect (before_change_functions_restore
,
748 Vbefore_change_functions
);
749 Vafter_change_function
= Qnil
;
750 Vbefore_change_function
= Qnil
;
751 Vafter_change_functions
= Qnil
;
752 Vbefore_change_functions
= Qnil
;
754 call3 (function
, make_number (pos
), make_number (pos
+ lenins
),
755 make_number (lendel
));
756 unbind_to (count
, Qnil
);
758 if (!NILP (Vafter_change_functions
))
760 int count
= specpdl_ptr
- specpdl
;
761 Lisp_Object functions
;
762 functions
= Vafter_change_functions
;
764 record_unwind_protect (after_change_function_restore
,
765 Vafter_change_function
);
766 record_unwind_protect (before_change_function_restore
,
767 Vbefore_change_function
);
768 record_unwind_protect (after_change_functions_restore
,
769 Vafter_change_functions
);
770 record_unwind_protect (before_change_functions_restore
,
771 Vbefore_change_functions
);
772 Vafter_change_function
= Qnil
;
773 Vbefore_change_function
= Qnil
;
774 Vafter_change_functions
= Qnil
;
775 Vbefore_change_functions
= Qnil
;
777 while (CONSP (functions
))
779 call3 (XCONS (functions
)->car
,
780 make_number (pos
), make_number (pos
+ lenins
),
781 make_number (lendel
));
782 functions
= XCONS (functions
)->cdr
;
784 unbind_to (count
, Qnil
);