diff options
| author | Eli Zaretskii | 2019-11-25 17:52:24 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2019-11-25 17:52:24 +0200 |
| commit | 19aecd340b7b3ab54629b790ba70a90130bad63d (patch) | |
| tree | c323d0ef86896e8f660250c7d88ec61c1d0c30f1 /src | |
| parent | 2d12d4d2d467f5df81e232707ad9191264b7c2b0 (diff) | |
| download | emacs-19aecd340b7b3ab54629b790ba70a90130bad63d.tar.gz emacs-19aecd340b7b3ab54629b790ba70a90130bad63d.zip | |
Fix face merging when some have :extend non-nil and some are inherited
* src/xfaces.c (face_inherited_attr): New function.
(merge_named_face): Call 'face_inherited_attr' when testing
whether a face that inherits from another fits the filtering
criteria specified by ATTR_FILTER.
(merge_face_vectors): Revert the changes made in this function
for filtering by ATTR_FILTER, and remove that argument as
well. These tests are now completely done by the caller, see
'merge_named_face'. (Bug#37774)
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfaces.c | 110 |
1 files changed, 55 insertions, 55 deletions
diff --git a/src/xfaces.c b/src/xfaces.c index 7ca60c87b1a..c3b455c928e 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -2052,53 +2052,23 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid) | |||
| 2052 | be 0 when called from other places. If window W is non-NULL, use W | 2052 | be 0 when called from other places. If window W is non-NULL, use W |
| 2053 | to interpret face specifications. */ | 2053 | to interpret face specifications. */ |
| 2054 | static void | 2054 | static void |
| 2055 | merge_face_vectors (struct window *w, struct frame *f, | 2055 | merge_face_vectors (struct window *w, |
| 2056 | const Lisp_Object *from, Lisp_Object *to, | 2056 | struct frame *f, const Lisp_Object *from, Lisp_Object *to, |
| 2057 | struct named_merge_point *named_merge_points, | 2057 | struct named_merge_point *named_merge_points) |
| 2058 | enum lface_attribute_index attr_filter) | ||
| 2059 | { | 2058 | { |
| 2060 | int i; | 2059 | int i; |
| 2061 | Lisp_Object font = Qnil; | 2060 | Lisp_Object font = Qnil; |
| 2062 | 2061 | ||
| 2063 | eassert (attr_filter < LFACE_VECTOR_SIZE); | ||
| 2064 | |||
| 2065 | /* When FROM sets attr_filter explicitly to nil or unspecified | ||
| 2066 | without inheriting don't merge it. */ | ||
| 2067 | if (attr_filter > 0 | ||
| 2068 | && (NILP(from[attr_filter]) | ||
| 2069 | || (UNSPECIFIEDP(from[attr_filter]) | ||
| 2070 | && (NILP (from[LFACE_INHERIT_INDEX]) | ||
| 2071 | || UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]))))) | ||
| 2072 | return; | ||
| 2073 | |||
| 2074 | /* If FROM inherits from some other faces, merge their attributes into | 2062 | /* If FROM inherits from some other faces, merge their attributes into |
| 2075 | TO before merging FROM's direct attributes. Note that an :inherit | 2063 | TO before merging FROM's direct attributes. Note that an :inherit |
| 2076 | attribute of `unspecified' is the same as one of nil; we never | 2064 | attribute of `unspecified' is the same as one of nil; we never |
| 2077 | merge :inherit attributes, so nil is more correct, but lots of | 2065 | merge :inherit attributes, so nil is more correct, but lots of |
| 2078 | other code uses `unspecified' as a generic value for face | 2066 | other code uses `unspecified' as a generic value for face attributes. */ |
| 2079 | attributes. */ | 2067 | if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]) |
| 2080 | if (!NILP (from[LFACE_INHERIT_INDEX]) | 2068 | && !NILP (from[LFACE_INHERIT_INDEX])) |
| 2081 | && !UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])) | 2069 | merge_face_ref (w, f, from[LFACE_INHERIT_INDEX], |
| 2082 | { | 2070 | to, false, named_merge_points, |
| 2083 | if (attr_filter == 0 /* No Filter */ | 2071 | 0); |
| 2084 | || !UNSPECIFIEDP (from[attr_filter])) /* FROM specifies filter */ | ||
| 2085 | merge_face_ref (w, f, from[LFACE_INHERIT_INDEX], | ||
| 2086 | to, false, named_merge_points, 0); | ||
| 2087 | else if (UNSPECIFIEDP (from[attr_filter])) /* FROM don't specify filter */ | ||
| 2088 | { | ||
| 2089 | Lisp_Object tmp[LFACE_VECTOR_SIZE]; | ||
| 2090 | memcpy (tmp, to, LFACE_VECTOR_SIZE * sizeof(*tmp)); | ||
| 2091 | |||
| 2092 | merge_face_ref (w, f, from[LFACE_INHERIT_INDEX], | ||
| 2093 | tmp, false, named_merge_points, attr_filter); | ||
| 2094 | |||
| 2095 | if (NILP (tmp[attr_filter]) | ||
| 2096 | || UNSPECIFIEDP (tmp[attr_filter])) | ||
| 2097 | return; | ||
| 2098 | |||
| 2099 | memcpy (to, tmp, LFACE_VECTOR_SIZE * sizeof *to); | ||
| 2100 | } | ||
| 2101 | } | ||
| 2102 | 2072 | ||
| 2103 | if (FONT_SPEC_P (from[LFACE_FONT_INDEX])) | 2073 | if (FONT_SPEC_P (from[LFACE_FONT_INDEX])) |
| 2104 | { | 2074 | { |
| @@ -2120,7 +2090,7 @@ merge_face_vectors (struct window *w, struct frame *f, | |||
| 2120 | else if (i != LFACE_FONT_INDEX && ! EQ (to[i], from[i])) | 2090 | else if (i != LFACE_FONT_INDEX && ! EQ (to[i], from[i])) |
| 2121 | { | 2091 | { |
| 2122 | to[i] = from[i]; | 2092 | to[i] = from[i]; |
| 2123 | if (i >= LFACE_FAMILY_INDEX && i <=LFACE_SLANT_INDEX) | 2093 | if (i >= LFACE_FAMILY_INDEX && i <= LFACE_SLANT_INDEX) |
| 2124 | font_clear_prop (to, | 2094 | font_clear_prop (to, |
| 2125 | (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX | 2095 | (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX |
| 2126 | : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX | 2096 | : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX |
| @@ -2155,6 +2125,34 @@ merge_face_vectors (struct window *w, struct frame *f, | |||
| 2155 | to[LFACE_INHERIT_INDEX] = Qnil; | 2125 | to[LFACE_INHERIT_INDEX] = Qnil; |
| 2156 | } | 2126 | } |
| 2157 | 2127 | ||
| 2128 | /* Chase the chain of face inheritance of frame F's face whose | ||
| 2129 | attributes are in ATTRS, for a non-'unspecified' value of face | ||
| 2130 | attribute whose index is ATTR_IDX, and return that value. Window | ||
| 2131 | W, if non-NULL, is used to filter face specifications. */ | ||
| 2132 | static Lisp_Object | ||
| 2133 | face_inherited_attr (struct window *w, struct frame *f, | ||
| 2134 | Lisp_Object attrs[LFACE_VECTOR_SIZE], | ||
| 2135 | enum lface_attribute_index attr_idx, | ||
| 2136 | struct named_merge_point *named_merge_points) | ||
| 2137 | { | ||
| 2138 | Lisp_Object inherited_attrs[LFACE_VECTOR_SIZE]; | ||
| 2139 | Lisp_Object attr_val = attrs[attr_idx]; | ||
| 2140 | |||
| 2141 | memcpy (inherited_attrs, attrs, LFACE_VECTOR_SIZE * sizeof (attrs[0])); | ||
| 2142 | while (UNSPECIFIEDP (attr_val) | ||
| 2143 | && !NILP (inherited_attrs[LFACE_INHERIT_INDEX]) | ||
| 2144 | && !UNSPECIFIEDP (inherited_attrs[LFACE_INHERIT_INDEX])) | ||
| 2145 | { | ||
| 2146 | Lisp_Object parent_face = inherited_attrs[LFACE_INHERIT_INDEX]; | ||
| 2147 | bool ok = get_lface_attributes (w, f, parent_face, inherited_attrs, | ||
| 2148 | false, named_merge_points); | ||
| 2149 | if (!ok) | ||
| 2150 | break; | ||
| 2151 | attr_val = inherited_attrs[attr_idx]; | ||
| 2152 | } | ||
| 2153 | return attr_val; | ||
| 2154 | } | ||
| 2155 | |||
| 2158 | /* Merge the named face FACE_NAME on frame F, into the vector of face | 2156 | /* Merge the named face FACE_NAME on frame F, into the vector of face |
| 2159 | attributes TO. Use NAMED_MERGE_POINTS to detect loops in face | 2157 | attributes TO. Use NAMED_MERGE_POINTS to detect loops in face |
| 2160 | inheritance. Return true if FACE_NAME is a valid face name and | 2158 | inheritance. Return true if FACE_NAME is a valid face name and |
| @@ -2173,18 +2171,20 @@ merge_named_face (struct window *w, | |||
| 2173 | face_name, NAMED_MERGE_POINT_NORMAL, | 2171 | face_name, NAMED_MERGE_POINT_NORMAL, |
| 2174 | &named_merge_points)) | 2172 | &named_merge_points)) |
| 2175 | { | 2173 | { |
| 2176 | Lisp_Object from[LFACE_VECTOR_SIZE]; | 2174 | Lisp_Object from[LFACE_VECTOR_SIZE], val; |
| 2177 | bool ok = get_lface_attributes (w, f, face_name, from, false, | 2175 | bool ok = get_lface_attributes (w, f, face_name, from, false, |
| 2178 | named_merge_points); | 2176 | named_merge_points); |
| 2179 | 2177 | ||
| 2180 | if (ok && (attr_filter == 0 /* No filter. */ | 2178 | if (ok && (attr_filter == 0 /* No filter. */ |
| 2181 | || (!NILP(from[attr_filter]) /* Filter, but specified. */ | 2179 | || (!NILP (from[attr_filter]) /* Filter, but specified. */ |
| 2182 | && !UNSPECIFIEDP(from[attr_filter])) | 2180 | && !UNSPECIFIEDP (from[attr_filter])) |
| 2183 | || (!NILP(from[attr_filter]) /* Filter, unspecified, but inherited. */ | 2181 | /* Filter, unspecified, but inherited. */ |
| 2184 | && UNSPECIFIEDP(from[attr_filter]) | 2182 | || (!NILP (from[LFACE_INHERIT_INDEX]) |
| 2185 | && !NILP (from[LFACE_INHERIT_INDEX]) | 2183 | && !UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]) |
| 2186 | && !UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])))) | 2184 | && (val = face_inherited_attr (w, f, from, attr_filter, |
| 2187 | merge_face_vectors (w, f, from, to, named_merge_points, attr_filter); | 2185 | named_merge_points), |
| 2186 | (!NILP (val) && !UNSPECIFIEDP (val)))))) | ||
| 2187 | merge_face_vectors (w, f, from, to, named_merge_points); | ||
| 2188 | 2188 | ||
| 2189 | return ok; | 2189 | return ok; |
| 2190 | } | 2190 | } |
| @@ -3883,7 +3883,7 @@ Default face attributes override any local face attributes. */) | |||
| 3883 | /* Ensure that the face vector is fully specified by merging | 3883 | /* Ensure that the face vector is fully specified by merging |
| 3884 | the previously-cached vector. */ | 3884 | the previously-cached vector. */ |
| 3885 | memcpy (attrs, oldface->lface, sizeof attrs); | 3885 | memcpy (attrs, oldface->lface, sizeof attrs); |
| 3886 | merge_face_vectors (NULL, f, lvec, attrs, 0, 0); | 3886 | merge_face_vectors (NULL, f, lvec, attrs, 0); |
| 3887 | vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); | 3887 | vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); |
| 3888 | newface = realize_face (c, lvec, DEFAULT_FACE_ID); | 3888 | newface = realize_face (c, lvec, DEFAULT_FACE_ID); |
| 3889 | 3889 | ||
| @@ -4639,7 +4639,7 @@ lookup_named_face (struct window *w, struct frame *f, | |||
| 4639 | return -1; | 4639 | return -1; |
| 4640 | 4640 | ||
| 4641 | memcpy (attrs, default_face->lface, sizeof attrs); | 4641 | memcpy (attrs, default_face->lface, sizeof attrs); |
| 4642 | merge_face_vectors (w, f, symbol_attrs, attrs, 0, 0); | 4642 | merge_face_vectors (w, f, symbol_attrs, attrs, 0); |
| 4643 | 4643 | ||
| 4644 | return lookup_face (f, attrs); | 4644 | return lookup_face (f, attrs); |
| 4645 | } | 4645 | } |
| @@ -4808,7 +4808,7 @@ lookup_derived_face (struct window *w, | |||
| 4808 | 4808 | ||
| 4809 | default_face = FACE_FROM_ID (f, face_id); | 4809 | default_face = FACE_FROM_ID (f, face_id); |
| 4810 | memcpy (attrs, default_face->lface, sizeof attrs); | 4810 | memcpy (attrs, default_face->lface, sizeof attrs); |
| 4811 | merge_face_vectors (w, f, symbol_attrs, attrs, 0, 0); | 4811 | merge_face_vectors (w, f, symbol_attrs, attrs, 0); |
| 4812 | return lookup_face (f, attrs); | 4812 | return lookup_face (f, attrs); |
| 4813 | } | 4813 | } |
| 4814 | 4814 | ||
| @@ -4906,7 +4906,7 @@ gui_supports_face_attributes_p (struct frame *f, | |||
| 4906 | 4906 | ||
| 4907 | memcpy (merged_attrs, def_attrs, sizeof merged_attrs); | 4907 | memcpy (merged_attrs, def_attrs, sizeof merged_attrs); |
| 4908 | 4908 | ||
| 4909 | merge_face_vectors (NULL, f, attrs, merged_attrs, 0, 0); | 4909 | merge_face_vectors (NULL, f, attrs, merged_attrs, 0); |
| 4910 | 4910 | ||
| 4911 | face_id = lookup_face (f, merged_attrs); | 4911 | face_id = lookup_face (f, merged_attrs); |
| 4912 | face = FACE_FROM_ID_OR_NULL (f, face_id); | 4912 | face = FACE_FROM_ID_OR_NULL (f, face_id); |
| @@ -5551,7 +5551,7 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id) | |||
| 5551 | 5551 | ||
| 5552 | /* Merge SYMBOL's face with the default face. */ | 5552 | /* Merge SYMBOL's face with the default face. */ |
| 5553 | get_lface_attributes_no_remap (f, symbol, symbol_attrs, true); | 5553 | get_lface_attributes_no_remap (f, symbol, symbol_attrs, true); |
| 5554 | merge_face_vectors (NULL, f, symbol_attrs, attrs, 0, 0); | 5554 | merge_face_vectors (NULL, f, symbol_attrs, attrs, 0); |
| 5555 | 5555 | ||
| 5556 | /* Realize the face. */ | 5556 | /* Realize the face. */ |
| 5557 | realize_face (c, attrs, id); | 5557 | realize_face (c, attrs, id); |
| @@ -6418,7 +6418,7 @@ merge_faces (struct window *w, Lisp_Object face_name, int face_id, | |||
| 6418 | if (!face) | 6418 | if (!face) |
| 6419 | return base_face_id; | 6419 | return base_face_id; |
| 6420 | 6420 | ||
| 6421 | merge_face_vectors (w, f, face->lface, attrs, 0, 0); | 6421 | merge_face_vectors (w, f, face->lface, attrs, 0); |
| 6422 | } | 6422 | } |
| 6423 | 6423 | ||
| 6424 | /* Look up a realized face with the given face attributes, | 6424 | /* Look up a realized face with the given face attributes, |