aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2019-11-26 19:29:45 +0200
committerEli Zaretskii2019-11-26 19:29:45 +0200
commitd4515f3cabcb2e70d71cd4133d069f5286d30654 (patch)
tree9976adeecf0264e8f728fd09ef95739e6195b561
parent094eb04ce5d8c1ccef78113c8cc6791d1d3b6bf8 (diff)
downloademacs-d4515f3cabcb2e70d71cd4133d069f5286d30654.tar.gz
emacs-d4515f3cabcb2e70d71cd4133d069f5286d30654.zip
Support ':extend' in faces defined by list of key/value pairs
* src/xfaces.c: Update and improve commentary at the beginning of the file. (face_attr_sym): New static array. (init_xfaces): Initialize 'face_attr_sym'. (merge_face_ref): Handle the :extend attribute in faces specified as lists of key/value pairs. (Bug#37774)
-rw-r--r--src/xfaces.c108
1 files changed, 99 insertions, 9 deletions
diff --git a/src/xfaces.c b/src/xfaces.c
index c3b455c928e..440cf4f1917 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -68,17 +68,25 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
68 On the other hand, if one of the other font-related attributes are 68 On the other hand, if one of the other font-related attributes are
69 specified, the corresponding specs in this attribute is set to nil. 69 specified, the corresponding specs in this attribute is set to nil.
70 70
71 15. A face name or list of face names from which to inherit attributes. 71 16. A face name or list of face names from which to inherit attributes.
72
73 16. A specified average font width, which is invisible from Lisp,
74 and is used to ensure that a font specified on the command line,
75 for example, can be matched exactly.
76 72
77 17. A fontset name. This is another special attribute. 73 17. A fontset name. This is another special attribute.
78 74
79 A fontset is a mappings from characters to font-specs, and the 75 A fontset is a mappings from characters to font-specs, and the
80 specs overwrite the font-spec in the 14th attribute. 76 specs overwrite the font-spec in the 14th attribute.
81 77
78 18. A "distant background" color, to be used when the foreground is
79 too close to the background and is hard to read.
80
81 19. Whether to extend the face to end of line when the face
82 "covers" the newline that ends the line.
83
84 On the C level, a Lisp face is completely represented by its array
85 of attributes. In that array, the zeroth element is Qface, and the
86 rest are the 19 face attributes described above. The
87 lface_attribute_index enumeration, defined on dispextern.h, with
88 values given by the LFACE_*_INDEX constants, is used to reference
89 the individual attributes.
82 90
83 Faces are frame-local by nature because Emacs allows you to define the 91 Faces are frame-local by nature because Emacs allows you to define the
84 same named face (face names are symbols) differently for different 92 same named face (face names are symbols) differently for different
@@ -100,10 +108,18 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
100 108
101 The display style of a given character in the text is determined by 109 The display style of a given character in the text is determined by
102 combining several faces. This process is called `face merging'. 110 combining several faces. This process is called `face merging'.
103 Any aspect of the display style that isn't specified by overlays or 111 Face merging combines the attributes of each of the faces being
104 text properties is taken from the `default' face. Since it is made 112 merged such that the attributes of the face that is merged later
105 sure that the default face is always fully-specified, face merging 113 override those of a face merged earlier in the process. In
106 always results in a fully-specified face. 114 particular, this replaces any 'unspecified' attributes with
115 non-'unspecified' values. Also, if a face inherits from another
116 (via the :inherit attribute), the attributes of the parent face,
117 recursively, are applied where the inheriting face doesn't specify
118 non-'unspecified' values. Any aspect of the display style that
119 isn't specified by overlays or text properties is taken from the
120 'default' face. Since it is made sure that the default face is
121 always fully-specified, face merging always results in a
122 fully-specified face.
107 123
108 124
109 Face realization. 125 Face realization.
@@ -1604,6 +1620,9 @@ the WIDTH times as wide as FACE on FRAME. */)
1604 && EQ (AREF (LFACE, 0), Qface)) 1620 && EQ (AREF (LFACE, 0), Qface))
1605 1621
1606 1622
1623/* Face attribute symbols for each value of LFACE_*_INDEX. */
1624static Lisp_Object face_attr_sym[LFACE_VECTOR_SIZE];
1625
1607#ifdef GLYPH_DEBUG 1626#ifdef GLYPH_DEBUG
1608 1627
1609/* Check consistency of Lisp face attribute vector ATTRS. */ 1628/* Check consistency of Lisp face attribute vector ATTRS. */
@@ -2397,6 +2416,58 @@ merge_face_ref (struct window *w,
2397 && *SDATA (SYMBOL_NAME (first)) == ':') 2416 && *SDATA (SYMBOL_NAME (first)) == ':')
2398 { 2417 {
2399 /* Assume this is the property list form. */ 2418 /* Assume this is the property list form. */
2419 if (attr_filter > 0)
2420 {
2421 eassert (attr_filter < LFACE_VECTOR_SIZE);
2422 /* ATTR_FILTER positive means don't merge this face if
2423 the corresponding attribute is nil, or not mentioned,
2424 or if it's unspecified and the face doesn't inherit
2425 from a face whose attribute is non-nil. The code
2426 below determines whether a face given as a property
2427 list shall be merged. */
2428 Lisp_Object parent_face = Qnil;
2429 bool attr_filter_seen = false;
2430 Lisp_Object face_ref_tem = face_ref;
2431 while (CONSP (face_ref_tem) && CONSP (XCDR (face_ref_tem)))
2432 {
2433 Lisp_Object keyword = XCAR (face_ref_tem);
2434 Lisp_Object value = XCAR (XCDR (face_ref_tem));
2435
2436 if (EQ (keyword, face_attr_sym[attr_filter])
2437 || (attr_filter == LFACE_INVERSE_INDEX
2438 && EQ (keyword, QCreverse_video)))
2439 {
2440 attr_filter_seen = true;
2441 if (NILP (value))
2442 return true;
2443 }
2444 else if (EQ (keyword, QCinherit))
2445 parent_face = value;
2446 face_ref_tem = XCDR (XCDR (face_ref_tem));
2447 }
2448 if (!attr_filter_seen)
2449 {
2450 if (NILP (parent_face))
2451 return true;
2452
2453 Lisp_Object scratch_attrs[LFACE_VECTOR_SIZE];
2454 int i;
2455
2456 scratch_attrs[0] = Qface;
2457 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
2458 scratch_attrs[i] = Qunspecified;
2459 if (!merge_face_ref (w, f, parent_face, scratch_attrs,
2460 err_msgs, named_merge_points, 0))
2461 {
2462 add_to_log ("Invalid face attribute %S %S",
2463 QCinherit, parent_face);
2464 return false;
2465 }
2466 if (NILP (scratch_attrs[attr_filter])
2467 || UNSPECIFIEDP (scratch_attrs[attr_filter]))
2468 return true;
2469 }
2470 }
2400 while (CONSP (face_ref) && CONSP (XCDR (face_ref))) 2471 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
2401 { 2472 {
2402 Lisp_Object keyword = XCAR (face_ref); 2473 Lisp_Object keyword = XCAR (face_ref);
@@ -6590,6 +6661,25 @@ init_xfaces (void)
6590 lface_id_to_name[i--] = XCAR (lface); 6661 lface_id_to_name[i--] = XCAR (lface);
6591 } 6662 }
6592 } 6663 }
6664 face_attr_sym[0] = Qface;
6665 face_attr_sym[LFACE_FOUNDRY_INDEX] = QCfoundry;
6666 face_attr_sym[LFACE_SWIDTH_INDEX] = QCwidth;
6667 face_attr_sym[LFACE_HEIGHT_INDEX] = QCheight;
6668 face_attr_sym[LFACE_WEIGHT_INDEX] = QCweight;
6669 face_attr_sym[LFACE_SLANT_INDEX] = QCslant;
6670 face_attr_sym[LFACE_UNDERLINE_INDEX] = QCunderline;
6671 face_attr_sym[LFACE_INVERSE_INDEX] = QCinverse_video;
6672 face_attr_sym[LFACE_FOREGROUND_INDEX] = QCforeground;
6673 face_attr_sym[LFACE_BACKGROUND_INDEX] = QCbackground;
6674 face_attr_sym[LFACE_STIPPLE_INDEX] = QCstipple;
6675 face_attr_sym[LFACE_OVERLINE_INDEX] = QCoverline;
6676 face_attr_sym[LFACE_STRIKE_THROUGH_INDEX] = QCstrike_through;
6677 face_attr_sym[LFACE_BOX_INDEX] = QCbox;
6678 face_attr_sym[LFACE_FONT_INDEX] = QCfont;
6679 face_attr_sym[LFACE_INHERIT_INDEX] = QCinherit;
6680 face_attr_sym[LFACE_FONTSET_INDEX] = QCfontset;
6681 face_attr_sym[LFACE_DISTANT_FOREGROUND_INDEX] = QCdistant_foreground;
6682 face_attr_sym[LFACE_EXTEND_INDEX] = QCextend;
6593} 6683}
6594#endif 6684#endif
6595 6685