diff options
| author | Karl Heuer | 1994-02-04 01:18:01 +0000 |
|---|---|---|
| committer | Karl Heuer | 1994-02-04 01:18:01 +0000 |
| commit | 45d82bdc5d42e38100315a19c974aabb3572157f (patch) | |
| tree | 8771a29754346d906e2b6830f62726b993ea2384 /src/intervals.c | |
| parent | ee095968e6eec243a912a1e6aff6ed93125824e8 (diff) | |
| download | emacs-45d82bdc5d42e38100315a19c974aabb3572157f.tar.gz emacs-45d82bdc5d42e38100315a19c974aabb3572157f.zip | |
Add comments describing the rules used by the merge algorithm.
Diffstat (limited to 'src/intervals.c')
| -rw-r--r-- | src/intervals.c | 148 |
1 files changed, 102 insertions, 46 deletions
diff --git a/src/intervals.c b/src/intervals.c index 067f62c3053..7a843040e23 100644 --- a/src/intervals.c +++ b/src/intervals.c | |||
| @@ -47,6 +47,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 47 | /* The rest of the file is within this conditional. */ | 47 | /* The rest of the file is within this conditional. */ |
| 48 | #ifdef USE_TEXT_PROPERTIES | 48 | #ifdef USE_TEXT_PROPERTIES |
| 49 | 49 | ||
| 50 | /* Test for membership, allowing for t (actually any non-cons) to mean the | ||
| 51 | universal set. */ | ||
| 52 | |||
| 53 | #define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set)) | ||
| 54 | |||
| 50 | /* Factor for weight-balancing interval trees. */ | 55 | /* Factor for weight-balancing interval trees. */ |
| 51 | Lisp_Object interval_balance_threshold; | 56 | Lisp_Object interval_balance_threshold; |
| 52 | 57 | ||
| @@ -846,61 +851,105 @@ adjust_intervals_for_insertion (tree, position, length) | |||
| 846 | return tree; | 851 | return tree; |
| 847 | } | 852 | } |
| 848 | 853 | ||
| 854 | /* Any property might be front-sticky on the left, rear-sticky on the left, | ||
| 855 | front-sticky on the right, or rear-sticky on the right; the 16 combinations | ||
| 856 | can be arranged in a matrix with rows denoting the left conditions and | ||
| 857 | columns denoting the right conditions: | ||
| 858 | _ __ _ | ||
| 859 | _ FR FR FR FR | ||
| 860 | FR__ 0 1 2 3 | ||
| 861 | _FR 4 5 6 7 | ||
| 862 | FR 8 9 A B | ||
| 863 | FR C D E F | ||
| 864 | |||
| 865 | left-props = '(front-sticky (p8 p9 pa pb pc pd pe pf) | ||
| 866 | rear-nonsticky (p4 p5 p6 p7 p8 p9 pa pb) | ||
| 867 | p0 L p1 L p2 L p3 L p4 L p5 L p6 L p7 L | ||
| 868 | p8 L p9 L pa L pb L pc L pd L pe L pf L) | ||
| 869 | right-props = '(front-sticky (p2 p3 p6 p7 pa pb pe pf) | ||
| 870 | rear-nonsticky (p1 p2 p5 p6 p9 pa pd pe) | ||
| 871 | p0 R p1 R p2 R p3 R p4 R p5 R p6 R p7 R | ||
| 872 | p8 R p9 R pa R pb R pc R pd R pe R pf R) | ||
| 873 | |||
| 874 | We inherit from whoever has a sticky side facing us. If both sides | ||
| 875 | do (cases 2, 3, E, and F), then we inherit from whichever side has a | ||
| 876 | non-nil value for the current property. If both sides do, then we take | ||
| 877 | from the left. | ||
| 878 | |||
| 879 | When we inherit a property, we get its stickiness as well as its value. | ||
| 880 | So, when we merge the above two lists, we expect to get this: | ||
| 881 | |||
| 882 | result = '(front-sticky (p6 p7 pa pb pc pd pe pf) | ||
| 883 | rear-nonsticky (p6 pa) | ||
| 884 | p0 L p1 L p2 L p3 L p6 R p7 R | ||
| 885 | pa R pb R pc L pd L pe L pf L) | ||
| 886 | |||
| 887 | The optimizable special cases are: | ||
| 888 | left rear-nonsticky = nil, right front-sticky = nil (inherit left) | ||
| 889 | left rear-nonsticky = t, right front-sticky = t (inherit right) | ||
| 890 | left rear-nonsticky = t, right front-sticky = nil (inherit none) | ||
| 891 | */ | ||
| 892 | |||
| 849 | Lisp_Object | 893 | Lisp_Object |
| 850 | merge_properties_sticky (pleft, pright) | 894 | merge_properties_sticky (pleft, pright) |
| 851 | Lisp_Object pleft, pright; | 895 | Lisp_Object pleft, pright; |
| 852 | { | 896 | { |
| 853 | register Lisp_Object props = Qnil, front = Qnil, rear = Qnil; | 897 | register Lisp_Object props = Qnil, front = Qnil, rear = Qnil; |
| 854 | 898 | ||
| 855 | Lisp_Object lfront = textget (pleft, Qfront_sticky); | 899 | Lisp_Object lfront = textget (pleft, Qfront_sticky); |
| 856 | Lisp_Object lrear = textget (pleft, Qrear_nonsticky); | 900 | Lisp_Object lrear = textget (pleft, Qrear_nonsticky); |
| 857 | Lisp_Object rfront = textget (pright, Qfront_sticky); | 901 | Lisp_Object rfront = textget (pright, Qfront_sticky); |
| 858 | Lisp_Object rrear = textget (pright, Qrear_nonsticky); | 902 | Lisp_Object rrear = textget (pright, Qrear_nonsticky); |
| 859 | 903 | ||
| 860 | register Lisp_Object tail1, tail2, sym; | 904 | register Lisp_Object tail1, tail2, sym, lval, rval; |
| 905 | int use_left, use_right; | ||
| 861 | 906 | ||
| 862 | /* Go through each element of PLEFT. */ | 907 | /* Go through each element of PRIGHT. */ |
| 863 | for (tail1 = pleft; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) | 908 | for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) |
| 864 | { | 909 | { |
| 865 | sym = Fcar (tail1); | 910 | sym = Fcar (tail1); |
| 866 | 911 | ||
| 867 | /* Sticky properties get special treatment. */ | 912 | /* Sticky properties get special treatment. */ |
| 868 | if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) | 913 | if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) |
| 869 | continue; | 914 | continue; |
| 870 | 915 | ||
| 871 | if (CONSP (lrear) ? NILP (Fmemq (sym, lrear)) : NILP (lrear)) | 916 | rval = Fcar (Fcdr (tail1)); |
| 917 | for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | ||
| 918 | if (EQ (sym, Fcar (tail2))) | ||
| 919 | break; | ||
| 920 | lval = (NILP (tail2) ? Qnil : Fcar( Fcdr (tail2))); | ||
| 921 | |||
| 922 | use_left = ! TMEM (sym, lrear); | ||
| 923 | use_right = TMEM (sym, rfront); | ||
| 924 | if (use_left && use_right) | ||
| 925 | { | ||
| 926 | use_left = ! NILP (lval); | ||
| 927 | use_right = ! NILP (rval); | ||
| 928 | } | ||
| 929 | if (use_left) | ||
| 872 | { | 930 | { |
| 873 | /* rear-sticky is dominant, we needn't search in PRIGHT. */ | 931 | /* We build props as (value sym ...) rather than (sym value ...) |
| 874 | 932 | because we plan to nreverse it when we're done. */ | |
| 875 | props = Fcons (sym, Fcons (Fcar (Fcdr (tail1)), props)); | 933 | if (! NILP (lval)) |
| 876 | if ((CONSP (lfront) || NILP (lfront)) | 934 | props = Fcons (lval, Fcons (sym, props)); |
| 877 | && ! NILP (Fmemq (sym, lfront))) | 935 | if (TMEM (sym, lfront)) |
| 878 | front = Fcons (sym, front); | 936 | front = Fcons (sym, front); |
| 937 | if (TMEM (sym, lrear)) | ||
| 938 | rear = Fcons (sym, rear); | ||
| 879 | } | 939 | } |
| 880 | else | 940 | else if (use_right) |
| 881 | { | 941 | { |
| 882 | /* Go through PRIGHT, looking for sym. */ | 942 | if (! NILP (rval)) |
| 883 | for (tail2 = pright; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | 943 | props = Fcons (rval, Fcons (sym, props)); |
| 884 | if (EQ (sym, Fcar (tail2))) | 944 | if (TMEM (sym, rfront)) |
| 885 | { | 945 | front = Fcons (sym, front); |
| 886 | 946 | if (TMEM (sym, rrear)) | |
| 887 | if (CONSP (rfront) | 947 | rear = Fcons (sym, rear); |
| 888 | ? ! NILP (Fmemq (sym, rfront)) : ! NILP (rfront)) | ||
| 889 | { | ||
| 890 | /* Nonsticky at the left and sticky at the right, | ||
| 891 | so take the right one. */ | ||
| 892 | props = Fcons (sym, Fcons (Fcar (Fcdr (tail2)), props)); | ||
| 893 | front = Fcons (sym, front); | ||
| 894 | if ((CONSP (rrear) || NILP (rrear)) | ||
| 895 | && ! NILP (Fmemq (sym, rrear))) | ||
| 896 | rear = Fcons (sym, rear); | ||
| 897 | } | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | } | 948 | } |
| 901 | } | 949 | } |
| 902 | /* Now let's see what to keep from PRIGHT. */ | 950 | |
| 903 | for (tail2 = pright; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | 951 | /* Now go through each element of PLEFT. */ |
| 952 | for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | ||
| 904 | { | 953 | { |
| 905 | sym = Fcar (tail2); | 954 | sym = Fcar (tail2); |
| 906 | 955 | ||
| @@ -908,30 +957,37 @@ merge_properties_sticky (pleft, pright) | |||
| 908 | if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) | 957 | if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) |
| 909 | continue; | 958 | continue; |
| 910 | 959 | ||
| 911 | /* If it ain't sticky, we don't take it. */ | 960 | /* If sym is in PRIGHT, we've already considered it. */ |
| 912 | if (CONSP (rfront) | 961 | for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) |
| 913 | ? NILP (Fmemq (sym, rfront)) : NILP (rfront)) | ||
| 914 | continue; | ||
| 915 | |||
| 916 | /* If sym is in PLEFT we already got it. */ | ||
| 917 | for (tail1 = pleft; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) | ||
| 918 | if (EQ (sym, Fcar (tail1))) | 962 | if (EQ (sym, Fcar (tail1))) |
| 919 | break; | 963 | break; |
| 920 | 964 | if (! NILP (tail1)) | |
| 921 | if (NILP (tail1)) | 965 | continue; |
| 966 | |||
| 967 | lval = Fcar (Fcdr (tail2)); | ||
| 968 | |||
| 969 | /* Since rval is known to be nil in this loop, the test simplifies. */ | ||
| 970 | if (! TMEM (sym, lrear)) | ||
| 922 | { | 971 | { |
| 923 | props = Fcons (sym, Fcons (Fcar (Fcdr (tail2)), props)); | 972 | if (! NILP (lval)) |
| 973 | props = Fcons (lval, Fcons (sym, props)); | ||
| 974 | if (TMEM (sym, lfront)) | ||
| 975 | front = Fcons (sym, front); | ||
| 976 | } | ||
| 977 | else if (TMEM (sym, rfront)) | ||
| 978 | { | ||
| 979 | /* The value is nil, but we still inherit the stickiness | ||
| 980 | from the right. */ | ||
| 924 | front = Fcons (sym, front); | 981 | front = Fcons (sym, front); |
| 925 | if ((CONSP (rrear) || NILP (rrear)) | 982 | if (TMEM (sym, rrear)) |
| 926 | && ! NILP (Fmemq (sym, rrear))) | ||
| 927 | rear = Fcons (sym, rear); | 983 | rear = Fcons (sym, rear); |
| 928 | } | 984 | } |
| 929 | } | 985 | } |
| 930 | props = Fnreverse (props); | 986 | props = Fnreverse (props); |
| 931 | if (! NILP (front)) | ||
| 932 | props = Fcons (Qfront_sticky, Fcons (Fnreverse (front), props)); | ||
| 933 | if (! NILP (rear)) | 987 | if (! NILP (rear)) |
| 934 | props = Fcons (Qrear_nonsticky, Fcons (Fnreverse (rear), props)); | 988 | props = Fcons (Qrear_nonsticky, Fcons (Fnreverse (rear), props)); |
| 989 | if (! NILP (front)) | ||
| 990 | props = Fcons (Qfront_sticky, Fcons (Fnreverse (front), props)); | ||
| 935 | return props; | 991 | return props; |
| 936 | } | 992 | } |
| 937 | 993 | ||