diff options
| author | Richard M. Stallman | 1996-11-09 21:36:00 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-11-09 21:36:00 +0000 |
| commit | fb2e7d144a3b441fee3b822ad4cf80c20102973b (patch) | |
| tree | fa0f4d8c0b2e12fa75268fa7ac6676cccb45f35a /src | |
| parent | 6aac2ab02e693eaa200d9ae1b717fe4eb9930048 (diff) | |
| download | emacs-fb2e7d144a3b441fee3b822ad4cf80c20102973b.tar.gz emacs-fb2e7d144a3b441fee3b822ad4cf80c20102973b.zip | |
(signal_after_change): If Vcombine_after_change_calls,
save up changes in combine_after_change_list.
(Fcombine_after_change_execute)
(Fcombine_after_change_execute_1): New subroutines.
(syms_of_insdel): New function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/insdel.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/insdel.c b/src/insdel.c index 872858041eb..b3bc81467fd 100644 --- a/src/insdel.c +++ b/src/insdel.c | |||
| @@ -35,6 +35,27 @@ static void gap_right (); | |||
| 35 | static void adjust_markers (); | 35 | static void adjust_markers (); |
| 36 | static void adjust_point (); | 36 | static void adjust_point (); |
| 37 | 37 | ||
| 38 | Lisp_Object Fcombine_after_change_execute (); | ||
| 39 | |||
| 40 | /* Non-nil means don't call the after-change-functions right away, | ||
| 41 | just record an element in Vcombine_after_change_calls_list. */ | ||
| 42 | Lisp_Object Vcombine_after_change_calls; | ||
| 43 | |||
| 44 | /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT) | ||
| 45 | describing changes which happened while combine_after_change_calls | ||
| 46 | was nonzero. We use this to decide how to call them | ||
| 47 | once the deferral ends. | ||
| 48 | |||
| 49 | In each element. | ||
| 50 | BEG-UNCHANGED is the number of chars before the changed range. | ||
| 51 | END-UNCHANGED is the number of chars after the changed range, | ||
| 52 | and CHANGE-AMOUNT is the number of characters inserted by the change | ||
| 53 | (negative for a deletion). */ | ||
| 54 | Lisp_Object combine_after_change_list; | ||
| 55 | |||
| 56 | /* Buffer which combine_after_change_list is about. */ | ||
| 57 | Lisp_Object combine_after_change_buffer; | ||
| 58 | |||
| 38 | /* Move gap to position `pos'. | 59 | /* Move gap to position `pos'. |
| 39 | Note that this can quit! */ | 60 | Note that this can quit! */ |
| 40 | 61 | ||
| @@ -853,6 +874,33 @@ void | |||
| 853 | signal_after_change (pos, lendel, lenins) | 874 | signal_after_change (pos, lendel, lenins) |
| 854 | int pos, lendel, lenins; | 875 | int pos, lendel, lenins; |
| 855 | { | 876 | { |
| 877 | /* If we are deferring calls to the after-change functions | ||
| 878 | and there are no before-change functions, | ||
| 879 | just record the args that we were going to use. */ | ||
| 880 | if (! NILP (Vcombine_after_change_calls) | ||
| 881 | && NILP (Vbefore_change_function) && NILP (Vbefore_change_functions) | ||
| 882 | && NILP (current_buffer->overlays_before) | ||
| 883 | && NILP (current_buffer->overlays_after)) | ||
| 884 | { | ||
| 885 | Lisp_Object elt; | ||
| 886 | |||
| 887 | if (!NILP (combine_after_change_list) | ||
| 888 | && current_buffer != XBUFFER (combine_after_change_buffer)) | ||
| 889 | Fcombine_after_change_execute (); | ||
| 890 | |||
| 891 | elt = Fcons (make_number (pos - BEG), | ||
| 892 | Fcons (make_number (Z - (pos - lendel + lenins)), | ||
| 893 | Fcons (make_number (lenins - lendel), Qnil))); | ||
| 894 | combine_after_change_list | ||
| 895 | = Fcons (elt, combine_after_change_list); | ||
| 896 | combine_after_change_buffer = Fcurrent_buffer (); | ||
| 897 | |||
| 898 | return; | ||
| 899 | } | ||
| 900 | |||
| 901 | if (!NILP (combine_after_change_list)) | ||
| 902 | Fcombine_after_change_execute (); | ||
| 903 | |||
| 856 | /* Run the after-change-function if any. | 904 | /* Run the after-change-function if any. |
| 857 | We don't bother "binding" this variable to nil | 905 | We don't bother "binding" this variable to nil |
| 858 | because it is obsolete anyway and new code should not use it. */ | 906 | because it is obsolete anyway and new code should not use it. */ |
| @@ -904,3 +952,93 @@ signal_after_change (pos, lendel, lenins) | |||
| 904 | if (lendel == 0) | 952 | if (lendel == 0) |
| 905 | report_interval_modification (pos, pos + lenins); | 953 | report_interval_modification (pos, pos + lenins); |
| 906 | } | 954 | } |
| 955 | |||
| 956 | Lisp_Object | ||
| 957 | Fcombine_after_change_execute_1 (val) | ||
| 958 | Lisp_Object val; | ||
| 959 | { | ||
| 960 | Vcombine_after_change_calls = val; | ||
| 961 | return val; | ||
| 962 | } | ||
| 963 | |||
| 964 | DEFUN ("combine-after-change-execute", Fcombine_after_change_execute, | ||
| 965 | Scombine_after_change_execute, 0, 0, 0, | ||
| 966 | "This function is for use internally in `combine-after-change-calls'.") | ||
| 967 | () | ||
| 968 | { | ||
| 969 | register Lisp_Object val; | ||
| 970 | int count = specpdl_ptr - specpdl; | ||
| 971 | int beg, end, change; | ||
| 972 | int begpos, endpos; | ||
| 973 | Lisp_Object tail; | ||
| 974 | |||
| 975 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); | ||
| 976 | |||
| 977 | Fset_buffer (combine_after_change_buffer); | ||
| 978 | |||
| 979 | /* # chars unchanged at beginning of buffer. */ | ||
| 980 | beg = Z - BEG; | ||
| 981 | /* # chars unchanged at end of buffer. */ | ||
| 982 | end = beg; | ||
| 983 | /* Total amount of insertion (negative for deletion). */ | ||
| 984 | change = 0; | ||
| 985 | |||
| 986 | /* Scan the various individual changes, | ||
| 987 | accumulating the range info in BEG, END and CHANGE. */ | ||
| 988 | for (tail = combine_after_change_list; CONSP (tail); | ||
| 989 | tail = XCONS (tail)->cdr) | ||
| 990 | { | ||
| 991 | Lisp_Object elt, thisbeg, thisend, thischange; | ||
| 992 | |||
| 993 | /* Extract the info from the next element. */ | ||
| 994 | elt = XCONS (tail)->car; | ||
| 995 | if (! CONSP (elt)) | ||
| 996 | continue; | ||
| 997 | thisbeg = XINT (XCONS (elt)->car); | ||
| 998 | |||
| 999 | elt = XCONS (elt)->cdr; | ||
| 1000 | if (! CONSP (elt)) | ||
| 1001 | continue; | ||
| 1002 | thisend = XINT (XCONS (elt)->car); | ||
| 1003 | |||
| 1004 | elt = XCONS (elt)->cdr; | ||
| 1005 | if (! CONSP (elt)) | ||
| 1006 | continue; | ||
| 1007 | thischange = XINT (XCONS (elt)->car); | ||
| 1008 | |||
| 1009 | /* Merge this range into the accumulated range. */ | ||
| 1010 | change += thischange; | ||
| 1011 | if (thisbeg < beg) | ||
| 1012 | beg = thisbeg; | ||
| 1013 | if (thisend < end) | ||
| 1014 | end = thisend; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | /* Get the current start and end positions of the range | ||
| 1018 | that was changed. */ | ||
| 1019 | begpos = BEG + beg; | ||
| 1020 | endpos = Z - end; | ||
| 1021 | |||
| 1022 | /* We are about to handle these, so discard them. */ | ||
| 1023 | combine_after_change_list = Qnil; | ||
| 1024 | |||
| 1025 | /* Now run the after-change functions for real. | ||
| 1026 | Turn off the flag that defers them. */ | ||
| 1027 | record_unwind_protect (Fcombine_after_change_execute_1, | ||
| 1028 | Vcombine_after_change_calls); | ||
| 1029 | signal_after_change (begpos, endpos - begpos - change, endpos - begpos); | ||
| 1030 | |||
| 1031 | return unbind_to (count, val); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | syms_of_insdel () | ||
| 1035 | { | ||
| 1036 | staticpro (&combine_after_change_list); | ||
| 1037 | combine_after_change_list = Qnil; | ||
| 1038 | |||
| 1039 | DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls, | ||
| 1040 | "Used internally by the `combine-after-change-calls' macro."); | ||
| 1041 | Vcombine_after_change_calls = Qnil; | ||
| 1042 | |||
| 1043 | defsubr (&Scombine_after_change_execute); | ||
| 1044 | } | ||