aboutsummaryrefslogtreecommitdiffstats
path: root/src/intervals.c
diff options
context:
space:
mode:
authorKarl Heuer1994-02-04 01:18:01 +0000
committerKarl Heuer1994-02-04 01:18:01 +0000
commit45d82bdc5d42e38100315a19c974aabb3572157f (patch)
tree8771a29754346d906e2b6830f62726b993ea2384 /src/intervals.c
parentee095968e6eec243a912a1e6aff6ed93125824e8 (diff)
downloademacs-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.c148
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. */
51Lisp_Object interval_balance_threshold; 56Lisp_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
860FR__ 0 1 2 3
861 _FR 4 5 6 7
862FR 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
849Lisp_Object 893Lisp_Object
850merge_properties_sticky (pleft, pright) 894merge_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