diff options
| author | Eli Zaretskii | 2019-11-26 19:29:45 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2019-11-26 19:29:45 +0200 |
| commit | d4515f3cabcb2e70d71cd4133d069f5286d30654 (patch) | |
| tree | 9976adeecf0264e8f728fd09ef95739e6195b561 | |
| parent | 094eb04ce5d8c1ccef78113c8cc6791d1d3b6bf8 (diff) | |
| download | emacs-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.c | 108 |
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. */ | ||
| 1624 | static 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 | ||