diff options
| author | Kenichi Handa | 1999-12-15 00:14:44 +0000 |
|---|---|---|
| committer | Kenichi Handa | 1999-12-15 00:14:44 +0000 |
| commit | f56b42ac9e43c1f77ecd782ceab46a65c10604fe (patch) | |
| tree | 16990cc466743dd598cc02c4797830ec925b6e32 /src | |
| parent | a5ecc8a3152f0d49340b51e2b906598413eb660c (diff) | |
| download | emacs-f56b42ac9e43c1f77ecd782ceab46a65c10604fe.tar.gz emacs-f56b42ac9e43c1f77ecd782ceab46a65c10604fe.zip | |
(adjust_intervals_for_insertion): To check stickines
of properties, pay attention to text-property-default-nonsticky.
(merge_properties_sticky): Likewise.
(get_property_and_range): New function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/intervals.c | 169 |
1 files changed, 140 insertions, 29 deletions
diff --git a/src/intervals.c b/src/intervals.c index 2699c71ee07..bba25d7de8c 100644 --- a/src/intervals.c +++ b/src/intervals.c | |||
| @@ -853,39 +853,69 @@ adjust_intervals_for_insertion (tree, position, length) | |||
| 853 | 853 | ||
| 854 | /* If in middle of an interval which is not sticky either way, | 854 | /* If in middle of an interval which is not sticky either way, |
| 855 | we must not just give its properties to the insertion. | 855 | we must not just give its properties to the insertion. |
| 856 | So split this interval at the insertion point. */ | 856 | So split this interval at the insertion point. |
| 857 | if (! (position == i->position || eobp) | 857 | |
| 858 | && END_NONSTICKY_P (i) | 858 | Originally, the if condition here was this: |
| 859 | && FRONT_NONSTICKY_P (i)) | 859 | (! (position == i->position || eobp) |
| 860 | && END_NONSTICKY_P (i) | ||
| 861 | && FRONT_NONSTICKY_P (i)) | ||
| 862 | But, these macros are now unreliable because of introduction of | ||
| 863 | Vtext_property_default_nonsticky. So, we always check properties | ||
| 864 | one by one if POSITION is in middle of an interval. */ | ||
| 865 | if (! (position == i->position || eobp)) | ||
| 860 | { | 866 | { |
| 861 | Lisp_Object tail; | 867 | Lisp_Object tail; |
| 862 | Lisp_Object front, rear; | 868 | Lisp_Object front, rear; |
| 863 | 869 | ||
| 870 | tail = i->plist; | ||
| 871 | |||
| 872 | /* Properties font-sticky and rear-nonsticky override | ||
| 873 | Vtext_property_default_nonsticky. So, if they are t, we can | ||
| 874 | skip one by one checking of properties. */ | ||
| 875 | rear = textget (i->plist, Qrear_nonsticky); | ||
| 876 | if (! CONSP (rear) && ! NILP (rear)) | ||
| 877 | { | ||
| 878 | /* All properties are nonsticky. We split the interval. */ | ||
| 879 | goto check_done; | ||
| 880 | } | ||
| 864 | front = textget (i->plist, Qfront_sticky); | 881 | front = textget (i->plist, Qfront_sticky); |
| 865 | rear = textget (i->plist, Qrear_nonsticky); | 882 | if (! CONSP (front) && ! NILP (front)) |
| 883 | { | ||
| 884 | /* All properties are sticky. We don't split the interval. */ | ||
| 885 | tail = Qnil; | ||
| 886 | goto check_done; | ||
| 887 | } | ||
| 866 | 888 | ||
| 867 | /* Does any actual property pose an actual problem? */ | 889 | /* Does any actual property pose an actual problem? We break |
| 868 | for (tail = i->plist; ! NILP (tail); tail = Fcdr (Fcdr (tail))) | 890 | the loop if we find a nonsticky property. */ |
| 891 | for (; CONSP (tail); tail = Fcdr (XCDR (tail))) | ||
| 869 | { | 892 | { |
| 870 | Lisp_Object prop; | 893 | Lisp_Object prop, tmp; |
| 871 | prop = XCAR (tail); | 894 | prop = XCAR (tail); |
| 872 | 895 | ||
| 873 | /* Is this particular property rear-sticky? | 896 | /* Is this particular property front-sticky? */ |
| 874 | Note, if REAR isn't a cons, it must be non-nil, | ||
| 875 | which means that all properties are rear-nonsticky. */ | ||
| 876 | if (CONSP (rear) && NILP (Fmemq (prop, rear))) | ||
| 877 | continue; | ||
| 878 | |||
| 879 | /* Is this particular property front-sticky? | ||
| 880 | Note, if FRONT isn't a cons, it must be nil, | ||
| 881 | which means that all properties are front-nonsticky. */ | ||
| 882 | if (CONSP (front) && ! NILP (Fmemq (prop, front))) | 897 | if (CONSP (front) && ! NILP (Fmemq (prop, front))) |
| 883 | continue; | 898 | continue; |
| 884 | 899 | ||
| 885 | /* PROP isn't sticky on either side => it is a real problem. */ | 900 | /* Is this particular property rear-nonsticky? */ |
| 886 | break; | 901 | if (CONSP (rear) && ! NILP (Fmemq (prop, rear))) |
| 902 | break; | ||
| 903 | |||
| 904 | /* Is this particular property recorded as sticky or | ||
| 905 | nonsticky in Vtext_property_default_nonsticky? */ | ||
| 906 | tmp = Fassq (prop, Vtext_property_default_nonsticky); | ||
| 907 | if (CONSP (tmp)) | ||
| 908 | { | ||
| 909 | if (NILP (tmp)) | ||
| 910 | continue; | ||
| 911 | break; | ||
| 912 | } | ||
| 913 | |||
| 914 | /* By default, a text property is rear-sticky, thus we | ||
| 915 | continue the loop. */ | ||
| 887 | } | 916 | } |
| 888 | 917 | ||
| 918 | check_done: | ||
| 889 | /* If any property is a real problem, split the interval. */ | 919 | /* If any property is a real problem, split the interval. */ |
| 890 | if (! NILP (tail)) | 920 | if (! NILP (tail)) |
| 891 | { | 921 | { |
| @@ -921,8 +951,16 @@ adjust_intervals_for_insertion (tree, position, length) | |||
| 921 | } | 951 | } |
| 922 | 952 | ||
| 923 | /* If at least one interval has sticky properties, | 953 | /* If at least one interval has sticky properties, |
| 924 | we check the stickiness property by property. */ | 954 | we check the stickiness property by property. |
| 925 | if (END_NONSTICKY_P (prev) || FRONT_STICKY_P (i)) | 955 | |
| 956 | Originally, the if condition here was this: | ||
| 957 | (END_NONSTICKY_P (prev) || FRONT_STICKY_P (i)) | ||
| 958 | But, these macros are now unreliable because of introduction | ||
| 959 | of Vtext_property_default_nonsticky. So, we always have to | ||
| 960 | check stickiness of properties one by one. If cache of | ||
| 961 | stickiness is implemented in the future, we may be able to | ||
| 962 | use those macros again. */ | ||
| 963 | if (1) | ||
| 926 | { | 964 | { |
| 927 | Lisp_Object pleft, pright; | 965 | Lisp_Object pleft, pright; |
| 928 | struct interval newi; | 966 | struct interval newi; |
| @@ -1030,8 +1068,10 @@ merge_properties_sticky (pleft, pright) | |||
| 1030 | rrear = textget (pright, Qrear_nonsticky); | 1068 | rrear = textget (pright, Qrear_nonsticky); |
| 1031 | 1069 | ||
| 1032 | /* Go through each element of PRIGHT. */ | 1070 | /* Go through each element of PRIGHT. */ |
| 1033 | for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) | 1071 | for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (Fcdr (tail1))) |
| 1034 | { | 1072 | { |
| 1073 | Lisp_Object tmp; | ||
| 1074 | |||
| 1035 | sym = Fcar (tail1); | 1075 | sym = Fcar (tail1); |
| 1036 | 1076 | ||
| 1037 | /* Sticky properties get special treatment. */ | 1077 | /* Sticky properties get special treatment. */ |
| @@ -1039,7 +1079,7 @@ merge_properties_sticky (pleft, pright) | |||
| 1039 | continue; | 1079 | continue; |
| 1040 | 1080 | ||
| 1041 | rval = Fcar (Fcdr (tail1)); | 1081 | rval = Fcar (Fcdr (tail1)); |
| 1042 | for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | 1082 | for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (Fcdr (tail2))) |
| 1043 | if (EQ (sym, Fcar (tail2))) | 1083 | if (EQ (sym, Fcar (tail2))) |
| 1044 | break; | 1084 | break; |
| 1045 | 1085 | ||
| @@ -1049,8 +1089,15 @@ merge_properties_sticky (pleft, pright) | |||
| 1049 | lpresent = ! NILP (tail2); | 1089 | lpresent = ! NILP (tail2); |
| 1050 | lval = (NILP (tail2) ? Qnil : Fcar (Fcdr (tail2))); | 1090 | lval = (NILP (tail2) ? Qnil : Fcar (Fcdr (tail2))); |
| 1051 | 1091 | ||
| 1052 | use_left = ! TMEM (sym, lrear) && lpresent; | 1092 | /* Even if lrear or rfront say nothing about the stickiness of |
| 1053 | use_right = TMEM (sym, rfront); | 1093 | SYM, Vtext_property_default_nonsticky may give default |
| 1094 | stickiness to SYM. */ | ||
| 1095 | tmp = Fassq (sym, Vtext_property_default_nonsticky); | ||
| 1096 | use_left = (lpresent | ||
| 1097 | && ! (TMEM (sym, lrear) | ||
| 1098 | || CONSP (tmp) && ! NILP (XCDR (tmp)))); | ||
| 1099 | use_right = (TMEM (sym, rfront) | ||
| 1100 | || (CONSP (tmp) && NILP (XCDR (tmp)))); | ||
| 1054 | if (use_left && use_right) | 1101 | if (use_left && use_right) |
| 1055 | { | 1102 | { |
| 1056 | if (NILP (lval)) | 1103 | if (NILP (lval)) |
| @@ -1079,8 +1126,10 @@ merge_properties_sticky (pleft, pright) | |||
| 1079 | } | 1126 | } |
| 1080 | 1127 | ||
| 1081 | /* Now go through each element of PLEFT. */ | 1128 | /* Now go through each element of PLEFT. */ |
| 1082 | for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | 1129 | for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (Fcdr (tail2))) |
| 1083 | { | 1130 | { |
| 1131 | Lisp_Object tmp; | ||
| 1132 | |||
| 1084 | sym = Fcar (tail2); | 1133 | sym = Fcar (tail2); |
| 1085 | 1134 | ||
| 1086 | /* Sticky properties get special treatment. */ | 1135 | /* Sticky properties get special treatment. */ |
| @@ -1088,7 +1137,7 @@ merge_properties_sticky (pleft, pright) | |||
| 1088 | continue; | 1137 | continue; |
| 1089 | 1138 | ||
| 1090 | /* If sym is in PRIGHT, we've already considered it. */ | 1139 | /* If sym is in PRIGHT, we've already considered it. */ |
| 1091 | for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) | 1140 | for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (Fcdr (tail1))) |
| 1092 | if (EQ (sym, Fcar (tail1))) | 1141 | if (EQ (sym, Fcar (tail1))) |
| 1093 | break; | 1142 | break; |
| 1094 | if (! NILP (tail1)) | 1143 | if (! NILP (tail1)) |
| @@ -1096,14 +1145,19 @@ merge_properties_sticky (pleft, pright) | |||
| 1096 | 1145 | ||
| 1097 | lval = Fcar (Fcdr (tail2)); | 1146 | lval = Fcar (Fcdr (tail2)); |
| 1098 | 1147 | ||
| 1148 | /* Even if lrear or rfront say nothing about the stickiness of | ||
| 1149 | SYM, Vtext_property_default_nonsticky may give default | ||
| 1150 | stickiness to SYM. */ | ||
| 1151 | tmp = Fassq (sym, Vtext_property_default_nonsticky); | ||
| 1152 | |||
| 1099 | /* Since rval is known to be nil in this loop, the test simplifies. */ | 1153 | /* Since rval is known to be nil in this loop, the test simplifies. */ |
| 1100 | if (! TMEM (sym, lrear)) | 1154 | if (! (TMEM (sym, lrear) || (CONSP (tmp) && ! NILP (XCDR (tmp))))) |
| 1101 | { | 1155 | { |
| 1102 | props = Fcons (lval, Fcons (sym, props)); | 1156 | props = Fcons (lval, Fcons (sym, props)); |
| 1103 | if (TMEM (sym, lfront)) | 1157 | if (TMEM (sym, lfront)) |
| 1104 | front = Fcons (sym, front); | 1158 | front = Fcons (sym, front); |
| 1105 | } | 1159 | } |
| 1106 | else if (TMEM (sym, rfront)) | 1160 | else if (TMEM (sym, rfront) || (CONSP (tmp) && NILP (XCDR (tmp)))) |
| 1107 | { | 1161 | { |
| 1108 | /* The value is nil, but we still inherit the stickiness | 1162 | /* The value is nil, but we still inherit the stickiness |
| 1109 | from the right. */ | 1163 | from the right. */ |
| @@ -1648,14 +1702,24 @@ graft_intervals_into_buffer (source, position, length, buffer, inherit) | |||
| 1648 | = split_interval_left (this, position - under->position); | 1702 | = split_interval_left (this, position - under->position); |
| 1649 | copy_properties (under, end_unchanged); | 1703 | copy_properties (under, end_unchanged); |
| 1650 | under->position = position; | 1704 | under->position = position; |
| 1705 | #if 0 | ||
| 1706 | /* This code has no effect. */ | ||
| 1651 | prev = 0; | 1707 | prev = 0; |
| 1652 | middle = 1; | 1708 | middle = 1; |
| 1709 | #endif /* 0 */ | ||
| 1653 | } | 1710 | } |
| 1654 | else | 1711 | else |
| 1655 | { | 1712 | { |
| 1713 | /* This call may have some effect because previous_interval may | ||
| 1714 | update `position' fields of intervals. Thus, don't ignore it | ||
| 1715 | for the moment. Someone please tell me the truth (K.Handa). */ | ||
| 1656 | prev = previous_interval (under); | 1716 | prev = previous_interval (under); |
| 1717 | #if 0 | ||
| 1718 | /* But, this code surely has no effect. And, anyway, | ||
| 1719 | END_NONSTICKY_P is unreliable now. */ | ||
| 1657 | if (prev && !END_NONSTICKY_P (prev)) | 1720 | if (prev && !END_NONSTICKY_P (prev)) |
| 1658 | prev = 0; | 1721 | prev = 0; |
| 1722 | #endif /* 0 */ | ||
| 1659 | } | 1723 | } |
| 1660 | 1724 | ||
| 1661 | /* Insertion is now at beginning of UNDER. */ | 1725 | /* Insertion is now at beginning of UNDER. */ |
| @@ -2017,6 +2081,53 @@ move_if_not_intangible (position) | |||
| 2017 | SET_PT (position); | 2081 | SET_PT (position); |
| 2018 | } | 2082 | } |
| 2019 | 2083 | ||
| 2084 | /* If text at position POS has property PROP, set *VAL to the property | ||
| 2085 | value, *START and *END to the beginning and end of a region that | ||
| 2086 | has the same property, and return 1. Otherwise return 0. | ||
| 2087 | |||
| 2088 | OBJECT is the string or buffer to look for the property in; | ||
| 2089 | nil means the current buffer. */ | ||
| 2090 | |||
| 2091 | int | ||
| 2092 | get_property_and_range (pos, prop, val, start, end, object) | ||
| 2093 | int pos; | ||
| 2094 | Lisp_Object prop, *val; | ||
| 2095 | int *start, *end; | ||
| 2096 | Lisp_Object object; | ||
| 2097 | { | ||
| 2098 | INTERVAL i, prev, next; | ||
| 2099 | |||
| 2100 | if (NILP (object)) | ||
| 2101 | i = find_interval (BUF_INTERVALS (current_buffer), pos); | ||
| 2102 | else if (BUFFERP (object)) | ||
| 2103 | i = find_interval (BUF_INTERVALS (XBUFFER (object)), pos); | ||
| 2104 | else if (STRINGP (object)) | ||
| 2105 | i = find_interval (XSTRING (object)->intervals, pos); | ||
| 2106 | else | ||
| 2107 | abort (); | ||
| 2108 | |||
| 2109 | if (NULL_INTERVAL_P (i) || (i->position + LENGTH (i) <= pos)) | ||
| 2110 | return 0; | ||
| 2111 | *val = textget (i->plist, prop); | ||
| 2112 | if (NILP (*val)) | ||
| 2113 | return 0; | ||
| 2114 | |||
| 2115 | next = i; /* remember it in advance */ | ||
| 2116 | prev = previous_interval (i); | ||
| 2117 | while (! NULL_INTERVAL_P (prev) | ||
| 2118 | && EQ (*val, textget (prev->plist, prop))) | ||
| 2119 | i = prev, prev = previous_interval (prev); | ||
| 2120 | *start = i->position; | ||
| 2121 | |||
| 2122 | next = next_interval (i); | ||
| 2123 | while (! NULL_INTERVAL_P (next) | ||
| 2124 | && EQ (*val, textget (next->plist, prop))) | ||
| 2125 | i = next, next = next_interval (next); | ||
| 2126 | *end = i->position + LENGTH (i); | ||
| 2127 | |||
| 2128 | return 1; | ||
| 2129 | } | ||
| 2130 | |||
| 2020 | /* Return the proper local map for position POSITION in BUFFER. | 2131 | /* Return the proper local map for position POSITION in BUFFER. |
| 2021 | Use the map specified by the local-map property, if any. | 2132 | Use the map specified by the local-map property, if any. |
| 2022 | Otherwise, use BUFFER's local map. */ | 2133 | Otherwise, use BUFFER's local map. */ |