aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2019-11-25 17:52:24 +0200
committerEli Zaretskii2019-11-25 17:52:24 +0200
commit19aecd340b7b3ab54629b790ba70a90130bad63d (patch)
treec323d0ef86896e8f660250c7d88ec61c1d0c30f1 /src
parent2d12d4d2d467f5df81e232707ad9191264b7c2b0 (diff)
downloademacs-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.c110
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. */
2054static void 2054static void
2055merge_face_vectors (struct window *w, struct frame *f, 2055merge_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. */
2132static Lisp_Object
2133face_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,