]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement pseudo-value 'reset' of face attrributes
authorEli Zaretskii <eliz@gnu.org>
Sun, 3 Jul 2022 09:30:24 +0000 (12:30 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sun, 3 Jul 2022 09:30:24 +0000 (12:30 +0300)
* 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)

doc/lispref/display.texi
etc/NEWS
src/xfaces.c

index 81799a2a5770547a496b944a6b0c573b97508ca5..08bf7441df07099b9c246e9cbd7a2c4fb5c49e0c 100644 (file)
@@ -2474,6 +2474,7 @@ Otherwise, it returns @code{nil}.
 The following table lists all the face attributes, their possible
 values, and their effects.
 
+@cindex unspecified, face attribute value
   Apart from the values given below, each face attribute can have the
 value @code{unspecified}.  This special value means that the face
 doesn't specify that attribute directly.  An @code{unspecified}
@@ -2482,7 +2483,13 @@ description @code{:inherit} attribute below); or, failing that, to an
 underlying face (@pxref{Displaying Faces}).  (However,
 @code{unspecified} is not a valid value in @code{defface}.)
 
-  The @code{default} face must specify all attributes.
+@cindex reset, face attribute value
+  A face attribute can also have the value @code{reset}.  This special
+value stands for the value of the corresponding attribute of the
+@code{default} face.
+
+  The @code{default} face must explicitly specify all attributes, and
+cannot use the special value @code{reset}.
 
   Some of these attributes are meaningful only on certain kinds of
 displays.  If your display cannot handle a certain attribute, the
index 47ca9c4b6ea1b3a3b94f9f6dc64f2dc57ede777c..740375067706fcad660c1272d9e51044ce9237f6 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -515,6 +515,12 @@ mixed.
 This inherits from the 'mode-line' face, but is the face actually used
 on the mode lines (along with 'mode-line-inactive').
 
++++
+** New face attribute pseudo-value 'reset'.
+This value stands for the value of the corresponding attribute of the
+'default' face.  It can be used to reset attribute values produced by
+inheriting from other faces.
+
 +++
 ** New function 'buffer-text-pixel-size'.
 This is similar to 'window-text-pixel-size', but can be used when the
index f70fe87c95e50b4466fa91e9517b24eb5a5384fc..57c888ad9c77eb8978b9dbdce811b6c81a0030be 100644 (file)
@@ -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