diff options
author | Eli Zaretskii <eliz@gnu.org> | 2022-07-03 12:30:24 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2022-07-03 12:30:24 +0300 |
commit | 45badeceecab5e5975d2e1700fce819acd34a964 (patch) | |
tree | 8d98c493e4b4b8a59f125a654023a792844e3667 /src/xfaces.c | |
parent | 94d43f4942feff16a85786bcee67f551ccbbbe40 (diff) | |
download | emacs-45badeceecab5e5975d2e1700fce819acd34a964.tar.gz emacs-45badeceecab5e5975d2e1700fce819acd34a964.tar.bz2 emacs-45badeceecab5e5975d2e1700fce819acd34a964.zip |
Implement pseudo-value 'reset' of face attrributes
* doc/lispref/display.texi (Face Attributes):
* etc/NEWS: Document the new pseudo-value 'reset'.
* src/xfaces.c (realize_named_face, lookup_derived_face)
(gui_supports_face_attributes_p, lookup_named_face)
(Finternal_merge_in_global_face, merge_named_face, merge_faces):
Handle the 'reset' pseudo-value of a face's attribute.
(syms_of_xfaces): New symbol 'reset'.
(RESET_P): New macro.
(check_lface_attrs, Finternal_set_lisp_face_attribute): Allow
'reset' as a value of any attribute except ':inherit'.
(Bug#38771)
Diffstat (limited to 'src/xfaces.c')
-rw-r--r-- | src/xfaces.c | 169 |
1 files changed, 144 insertions, 25 deletions
diff --git a/src/xfaces.c b/src/xfaces.c index f70fe87c95e..57c888ad9c7 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -295,6 +295,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface) +/* True if face attribute ATTR is `reset'. */ + +#define RESET_P(ATTR) EQ ((ATTR), Qreset) + /* Size of hash table of realized faces in face caches (should be a prime number). */ @@ -1757,57 +1761,72 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE]) { eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX]) + || RESET_P (attrs[LFACE_FAMILY_INDEX]) || STRINGP (attrs[LFACE_FAMILY_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX]) + || RESET_P (attrs[LFACE_FOUNDRY_INDEX]) || STRINGP (attrs[LFACE_FOUNDRY_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX]) + || RESET_P (attrs[LFACE_SWIDTH_INDEX]) || SYMBOLP (attrs[LFACE_SWIDTH_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX]) + || RESET_P (attrs[LFACE_HEIGHT_INDEX]) || NUMBERP (attrs[LFACE_HEIGHT_INDEX]) || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX]) + || RESET_P (attrs[LFACE_WEIGHT_INDEX]) || SYMBOLP (attrs[LFACE_WEIGHT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX]) + || RESET_P (attrs[LFACE_SLANT_INDEX]) || SYMBOLP (attrs[LFACE_SLANT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX]) + || RESET_P (attrs[LFACE_UNDERLINE_INDEX]) || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX]) || STRINGP (attrs[LFACE_UNDERLINE_INDEX]) || CONSP (attrs[LFACE_UNDERLINE_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_EXTEND_INDEX]) + || RESET_P (attrs[LFACE_EXTEND_INDEX]) || SYMBOLP (attrs[LFACE_EXTEND_INDEX]) || STRINGP (attrs[LFACE_EXTEND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX]) + || RESET_P (attrs[LFACE_OVERLINE_INDEX]) || SYMBOLP (attrs[LFACE_OVERLINE_INDEX]) || STRINGP (attrs[LFACE_OVERLINE_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX]) + || RESET_P (attrs[LFACE_STRIKE_THROUGH_INDEX]) || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX]) || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX]) + || RESET_P (attrs[LFACE_BOX_INDEX]) || SYMBOLP (attrs[LFACE_BOX_INDEX]) || STRINGP (attrs[LFACE_BOX_INDEX]) || FIXNUMP (attrs[LFACE_BOX_INDEX]) || CONSP (attrs[LFACE_BOX_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX]) + || RESET_P (attrs[LFACE_INVERSE_INDEX]) || SYMBOLP (attrs[LFACE_INVERSE_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX]) + || RESET_P (attrs[LFACE_FOREGROUND_INDEX]) || STRINGP (attrs[LFACE_FOREGROUND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) + || RESET_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) || STRINGP (attrs[LFACE_DISTANT_FOREGROUND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX]) + || RESET_P (attrs[LFACE_BACKGROUND_INDEX]) || STRINGP (attrs[LFACE_BACKGROUND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX]) @@ -1817,13 +1836,16 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE]) #ifdef HAVE_WINDOW_SYSTEM eassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX]) + || RESET_P (attrs[LFACE_STIPPLE_INDEX]) || SYMBOLP (attrs[LFACE_STIPPLE_INDEX]) || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX]))); eassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX]) + || RESET_P (attrs[LFACE_FONT_INDEX]) || FONTP (attrs[LFACE_FONT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX]) || STRINGP (attrs[LFACE_FONTSET_INDEX]) + || RESET_P (attrs[LFACE_FONTSET_INDEX]) || NILP (attrs[LFACE_FONTSET_INDEX])); #endif } @@ -2083,7 +2105,7 @@ lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE]) #ifdef HAVE_WINDOW_SYSTEM /* Set font-related attributes of Lisp face LFACE from FONT-OBJECT. - If FORCE_P, set only unspecified attributes of LFACE. The + If FORCE_P is zero, set only unspecified attributes of LFACE. The exception is `font' attribute. It is set to FONT_OBJECT regardless of FORCE_P. */ @@ -2339,6 +2361,14 @@ merge_named_face (struct window *w, Lisp_Object from[LFACE_VECTOR_SIZE], val; bool ok = get_lface_attributes (w, f, face_name, from, false, named_merge_points); + if (ok && !EQ (face_name, Qdefault)) + { + struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID); + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (from[i], Qreset)) + from[i] = deflt->lface[i]; + } if (ok && (attr_filter == 0 /* No filter. */ || (!NILP (from[attr_filter]) /* Filter, but specified. */ @@ -3087,7 +3117,9 @@ FRAME 0 means change the face on all frames, and change the default if (EQ (attr, QCfamily)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_STRING (value); if (SCHARS (value) == 0) @@ -3099,7 +3131,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCfoundry)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_STRING (value); if (SCHARS (value) == 0) @@ -3111,7 +3145,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCheight)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { if (EQ (face, Qdefault)) { @@ -3139,7 +3175,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCweight)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (FONT_WEIGHT_NAME_NUMERIC (value) < 0) @@ -3151,7 +3189,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCslant)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (FONT_SLANT_NAME_NUMERIC (value) < 0) @@ -3165,7 +3205,7 @@ FRAME 0 means change the face on all frames, and change the default { bool valid_p = false; - if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value)) + if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value)) valid_p = true; else if (NILP (value) || EQ (value, Qt)) valid_p = true; @@ -3223,7 +3263,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCoverline)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !NILP (value)) @@ -3237,7 +3279,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCstrike_through)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !NILP (value)) @@ -3258,7 +3302,7 @@ FRAME 0 means change the face on all frames, and change the default if (EQ (value, Qt)) value = make_fixnum (1); - if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value)) + if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value)) valid_p = true; else if (NILP (value)) valid_p = true; @@ -3320,7 +3364,9 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (!EQ (value, Qt) && !NILP (value)) @@ -3331,7 +3377,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCextend)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (!EQ (value, Qt) && !NILP (value)) @@ -3345,7 +3393,9 @@ FRAME 0 means change the face on all frames, and change the default /* Compatibility with 20.x. */ if (NILP (value)) value = Qunspecified; - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -3362,7 +3412,9 @@ FRAME 0 means change the face on all frames, and change the default /* Compatibility with 20.x. */ if (NILP (value)) value = Qunspecified; - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -3379,7 +3431,9 @@ FRAME 0 means change the face on all frames, and change the default /* Compatibility with 20.x. */ if (NILP (value)) value = Qunspecified; - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -3394,7 +3448,9 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCstipple)) { #if defined (HAVE_WINDOW_SYSTEM) - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value) && !NILP (value) && NILP (Fbitmap_spec_p (value))) signal_error ("Invalid stipple attribute", value); @@ -3404,7 +3460,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCwidth)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (FONT_WIDTH_NAME_NUMERIC (value) < 0) @@ -3419,7 +3477,9 @@ FRAME 0 means change the face on all frames, and change the default #ifdef HAVE_WINDOW_SYSTEM if (EQ (frame, Qt) || FRAME_WINDOW_P (f)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { struct frame *f1; @@ -3479,9 +3539,12 @@ FRAME 0 means change the face on all frames, and change the default Lisp_Object tmp; old_value = LFACE_FONTSET (lface); - tmp = Fquery_fontset (value, Qnil); - if (NILP (tmp)) - signal_error ("Invalid fontset name", value); + if (!RESET_P (value)) + { + tmp = Fquery_fontset (value, Qnil); + if (NILP (tmp)) + signal_error ("Invalid fontset name", value); + } ASET (lface, LFACE_FONTSET_INDEX, value = tmp); } #endif /* HAVE_WINDOW_SYSTEM */ @@ -3503,14 +3566,20 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCbold)) { old_value = LFACE_WEIGHT (lface); - ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold); + if (RESET_P (value)) + ASET (lface, LFACE_WEIGHT_INDEX, value); + else + ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold); prop_index = FONT_WEIGHT_INDEX; } else if (EQ (attr, QCitalic)) { attr = QCslant; old_value = LFACE_SLANT (lface); - ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic); + if (RESET_P (value)) + ASET (lface, LFACE_SLANT_INDEX, value); + else + ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic); prop_index = FONT_SLANT_INDEX; } else @@ -4120,6 +4189,13 @@ Default face attributes override any local face attributes. */) /* Ensure that the face vector is fully specified by merging the previously-cached vector. */ memcpy (attrs, oldface->lface, sizeof attrs); + + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (lvec[i], Qreset)) + lvec[i] = attrs[i]; + merge_face_vectors (NULL, f, lvec, attrs, 0); vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); newface = realize_face (c, lvec, DEFAULT_FACE_ID); @@ -4886,6 +4962,13 @@ lookup_named_face (struct window *w, struct frame *f, return -1; memcpy (attrs, default_face->lface, sizeof attrs); + + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (symbol_attrs[i], Qreset)) + symbol_attrs[i] = attrs[i]; + merge_face_vectors (w, f, symbol_attrs, attrs, 0); return lookup_face (f, attrs); @@ -5056,6 +5139,13 @@ lookup_derived_face (struct window *w, default_face = FACE_FROM_ID (f, face_id); memcpy (attrs, default_face->lface, sizeof attrs); + + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (symbol_attrs[i], Qreset)) + symbol_attrs[i] = attrs[i]; + merge_face_vectors (w, f, symbol_attrs, attrs, 0); return lookup_face (f, attrs); } @@ -5104,6 +5194,12 @@ gui_supports_face_attributes_p (struct frame *f, { Lisp_Object *def_attrs = def_face->lface; + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (attrs[i], Qreset)) + attrs[i] = def_attrs[i]; + /* Check that other specified attributes are different from the default face. */ if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) @@ -5811,8 +5907,16 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id) lface = Finternal_make_lisp_face (symbol, frame); } - /* Merge SYMBOL's face with the default face. */ + get_lface_attributes_no_remap (f, symbol, symbol_attrs, true); + + /* Handle the 'reset' pseudo-value of any attribute by replacing it + with the corresponding value of the default face. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (symbol_attrs[i], Qreset)) + symbol_attrs[i] = attrs[i]; + /* Merge SYMBOL's face with the default face. */ merge_face_vectors (NULL, f, symbol_attrs, attrs, 0); /* Realize the face. */ @@ -6750,7 +6854,21 @@ merge_faces (struct window *w, Lisp_Object face_name, int face_id, if (!face) return base_face_id; - merge_face_vectors (w, f, face->lface, attrs, 0); + if (face_id != DEFAULT_FACE_ID) + { + struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID); + Lisp_Object lface_attrs[LFACE_VECTOR_SIZE]; + int i; + + memcpy (lface_attrs, face->lface, LFACE_VECTOR_SIZE); + /* Make explicit any attributes whose value is 'reset'. */ + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (lface_attrs[i], Qreset)) + lface_attrs[i] = deflt->lface[i]; + merge_face_vectors (w, f, lface_attrs, attrs, 0); + } + else + merge_face_vectors (w, f, face->lface, attrs, 0); } /* Look up a realized face with the given face attributes, @@ -7019,6 +7137,7 @@ syms_of_xfaces (void) DEFSYM (Qblack, "black"); DEFSYM (Qoblique, "oblique"); DEFSYM (Qitalic, "italic"); + DEFSYM (Qreset, "reset"); /* The symbols `foreground-color' and `background-color' which can be used as part of a `face' property. This is for compatibility with |