comparison src/xfaces.c @ 83145:fe5ecb72e304

Merged in changes from CVS trunk. Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-366 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-367 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-368 Improve display-supports-face-attributes-p on non-ttys * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-369 Rewrite face-differs-from-default-p * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-370 Move `display-supports-face-attributes-p' entirely into C code * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-371 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-372 Simplify face-differs-from-default-p; don't consider :stipple. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-373 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-374 (tty_supports_face_attributes_p): Ensure attributes differ from default * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-375 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-185
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 05 Jun 2004 17:21:43 +0000
parents ad01ab3c6f4d 0b7bab25fcec
children cf8f0a3b5cb4
comparison
equal deleted inserted replaced
83144:2e868590c17b 83145:fe5ecb72e304
4868 return face ? build_string (face->font_name) : Qnil; 4868 return face ? build_string (face->font_name) : Qnil;
4869 } 4869 }
4870 } 4870 }
4871 4871
4872 4872
4873 /* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
4874 all attributes are `equal'. Tries to be fast because this function
4875 is called quite often. */
4876
4877 static INLINE int
4878 face_attr_equal_p (v1, v2)
4879 {
4880 /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
4881 and the other is specified. */
4882 if (XTYPE (v1) != XTYPE (v2))
4883 return 0;
4884
4885 if (EQ (v1, v2))
4886 return 1;
4887
4888 switch (XTYPE (v1))
4889 {
4890 case Lisp_String:
4891 if (SBYTES (v1) != SBYTES (v2))
4892 return 0;
4893
4894 return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
4895
4896 case Lisp_Int:
4897 case Lisp_Symbol:
4898 return 0;
4899
4900 default:
4901 return !NILP (Fequal (v1, v2));
4902 }
4903 }
4904
4905
4873 /* Compare face vectors V1 and V2 for equality. Value is non-zero if 4906 /* Compare face vectors V1 and V2 for equality. Value is non-zero if
4874 all attributes are `equal'. Tries to be fast because this function 4907 all attributes are `equal'. Tries to be fast because this function
4875 is called quite often. */ 4908 is called quite often. */
4876 4909
4877 static INLINE int 4910 static INLINE int
4879 Lisp_Object *v1, *v2; 4912 Lisp_Object *v1, *v2;
4880 { 4913 {
4881 int i, equal_p = 1; 4914 int i, equal_p = 1;
4882 4915
4883 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) 4916 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
4884 { 4917 equal_p = face_attr_equal_p (v1[i], v2[i]);
4885 Lisp_Object a = v1[i];
4886 Lisp_Object b = v2[i];
4887
4888 /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
4889 and the other is specified. */
4890 equal_p = XTYPE (a) == XTYPE (b);
4891 if (!equal_p)
4892 break;
4893
4894 if (!EQ (a, b))
4895 {
4896 switch (XTYPE (a))
4897 {
4898 case Lisp_String:
4899 equal_p = ((SBYTES (a)
4900 == SBYTES (b))
4901 && bcmp (SDATA (a), SDATA (b),
4902 SBYTES (a)) == 0);
4903 break;
4904
4905 case Lisp_Int:
4906 case Lisp_Symbol:
4907 equal_p = 0;
4908 break;
4909
4910 default:
4911 equal_p = !NILP (Fequal (a, b));
4912 break;
4913 }
4914 }
4915 }
4916 4918
4917 return equal_p; 4919 return equal_p;
4918 } 4920 }
4919 4921
4920 4922
5210 return make_number (color_distance (&cdef1, &cdef2)); 5212 return make_number (color_distance (&cdef1, &cdef2));
5211 } 5213 }
5212 5214
5213 5215
5214 /*********************************************************************** 5216 /***********************************************************************
5215 Face capability testing for ttys
5216 ***********************************************************************/
5217
5218
5219 /* If the distance (as returned by color_distance) between two colors is
5220 less than this, then they are considered the same, for determining
5221 whether a color is supported or not. The range of values is 0-65535. */
5222
5223 #define TTY_SAME_COLOR_THRESHOLD 10000
5224
5225
5226 DEFUN ("tty-supports-face-attributes-p",
5227 Ftty_supports_face_attributes_p, Stty_supports_face_attributes_p,
5228 1, 2, 0,
5229 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
5230 The optional argument FRAME is the frame on which to test; if it is nil
5231 or unspecified, then the current frame is used. If FRAME is not a tty
5232 frame, then nil is returned.
5233
5234 The definition of `supported' is somewhat heuristic, but basically means
5235 that a face containing all the attributes in ATTRIBUTES, when merged
5236 with the default face for display, can be represented in a way that's
5237
5238 \(1) different in appearance than the default face, and
5239 \(2) `close in spirit' to what the attributes specify, if not exact.
5240
5241 Point (2) implies that a `:weight black' attribute will be satisfied
5242 by any terminal that can display bold, and a `:foreground "yellow"' as
5243 long as the terminal can display a yellowish color, but `:slant italic'
5244 will _not_ be satisfied by the tty display code's automatic
5245 substitution of a `dim' face for italic. */)
5246 (attributes, frame)
5247 Lisp_Object attributes, frame;
5248 {
5249 int weight, i;
5250 struct frame *f;
5251 Lisp_Object val, fg, bg;
5252 XColor fg_tty_color, fg_std_color;
5253 XColor bg_tty_color, bg_std_color;
5254 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5255 unsigned test_caps = 0;
5256
5257 if (NILP (frame))
5258 frame = selected_frame;
5259 CHECK_LIVE_FRAME (frame);
5260 f = XFRAME (frame);
5261
5262 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
5263 attrs[i] = Qunspecified;
5264 merge_face_vector_with_property (f, attrs, attributes);
5265
5266 /* This function only works on ttys. */
5267 if (!FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
5268 return Qnil;
5269
5270 /* First check some easy-to-check stuff; ttys support none of the
5271 following attributes, so we can just return nil if any are requested. */
5272
5273 /* stipple */
5274 val = attrs[LFACE_STIPPLE_INDEX];
5275 if (!UNSPECIFIEDP (val) && !NILP (val))
5276 return Qnil;
5277
5278 /* font height */
5279 val = attrs[LFACE_HEIGHT_INDEX];
5280 if (!UNSPECIFIEDP (val) && !NILP (val))
5281 return Qnil;
5282
5283 /* font width */
5284 val = attrs[LFACE_SWIDTH_INDEX];
5285 if (!UNSPECIFIEDP (val) && !NILP (val)
5286 && face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM)
5287 return Qnil;
5288
5289 /* overline */
5290 val = attrs[LFACE_OVERLINE_INDEX];
5291 if (!UNSPECIFIEDP (val) && !NILP (val))
5292 return Qnil;
5293
5294 /* strike-through */
5295 val = attrs[LFACE_STRIKE_THROUGH_INDEX];
5296 if (!UNSPECIFIEDP (val) && !NILP (val))
5297 return Qnil;
5298
5299 /* boxes */
5300 val = attrs[LFACE_BOX_INDEX];
5301 if (!UNSPECIFIEDP (val) && !NILP (val))
5302 return Qnil;
5303
5304 /* slant (italics/oblique); We consider any non-default value
5305 unsupportable on ttys, even though the face code actually `fakes'
5306 them using a dim attribute if possible. This is because the faked
5307 result is too different from what the face specifies. */
5308 val = attrs[LFACE_SLANT_INDEX];
5309 if (!UNSPECIFIEDP (val) && !NILP (val)
5310 && face_numeric_slant (val) != XLFD_SLANT_ROMAN)
5311 return Qnil;
5312
5313
5314 /* Test for terminal `capabilities' (non-color character attributes). */
5315
5316 /* font weight (bold/dim) */
5317 weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
5318 if (weight >= 0)
5319 {
5320 if (weight > XLFD_WEIGHT_MEDIUM)
5321 test_caps = TTY_CAP_BOLD;
5322 else if (weight < XLFD_WEIGHT_MEDIUM)
5323 test_caps = TTY_CAP_DIM;
5324 }
5325
5326 /* underlining */
5327 val = attrs[LFACE_UNDERLINE_INDEX];
5328 if (!UNSPECIFIEDP (val) && !NILP (val))
5329 {
5330 if (STRINGP (val))
5331 return Qnil; /* ttys don't support colored underlines */
5332 else
5333 test_caps |= TTY_CAP_UNDERLINE;
5334 }
5335
5336 /* inverse video */
5337 val = attrs[LFACE_INVERSE_INDEX];
5338 if (!UNSPECIFIEDP (val) && !NILP (val))
5339 test_caps |= TTY_CAP_INVERSE;
5340
5341
5342 /* Color testing. */
5343
5344 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
5345 we use them when calling `tty_capable_p' below, even if the face
5346 specifies no colors. */
5347 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
5348 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
5349
5350 /* Check if foreground color is close enough. */
5351 fg = attrs[LFACE_FOREGROUND_INDEX];
5352 if (STRINGP (fg))
5353 {
5354 if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
5355 return Qnil;
5356 else if (color_distance (&fg_tty_color, &fg_std_color)
5357 > TTY_SAME_COLOR_THRESHOLD)
5358 return Qnil;
5359 }
5360
5361 /* Check if background color is close enough. */
5362 bg = attrs[LFACE_BACKGROUND_INDEX];
5363 if (STRINGP (bg))
5364 {
5365 if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5366 return Qnil;
5367 else if (color_distance (&bg_tty_color, &bg_std_color)
5368 > TTY_SAME_COLOR_THRESHOLD)
5369 return Qnil;
5370 }
5371
5372 /* If both foreground and background are requested, see if the
5373 distance between them is OK. We just check to see if the distance
5374 between the tty's foreground and background is close enough to the
5375 distance between the standard foreground and background. */
5376 if (STRINGP (fg) && STRINGP (bg))
5377 {
5378 int delta_delta
5379 = (color_distance (&fg_std_color, &bg_std_color)
5380 - color_distance (&fg_tty_color, &bg_tty_color));
5381 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5382 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5383 return Qnil;
5384 }
5385
5386
5387 /* See if the capabilities we selected above are supported, with the
5388 given colors. */
5389 if (test_caps != 0 &&
5390 ! tty_capable_p (FRAME_TTY (f), test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
5391 return Qnil;
5392
5393
5394 /* Hmmm, everything checks out, this terminal must support this face. */
5395 return Qt;
5396 }
5397
5398
5399
5400 /***********************************************************************
5401 Face Cache 5217 Face Cache
5402 ***********************************************************************/ 5218 ***********************************************************************/
5403 5219
5404 /* Return a new face cache for frame F. */ 5220 /* Return a new face cache for frame F. */
5405 5221
5912 XVECTOR (lface)->contents, 5728 XVECTOR (lface)->contents,
5913 plist); 5729 plist);
5914 return lface; 5730 return lface;
5915 } 5731 }
5916 5732
5733
5734
5735 /***********************************************************************
5736 Face capability testing
5737 ***********************************************************************/
5738
5739
5740 /* If the distance (as returned by color_distance) between two colors is
5741 less than this, then they are considered the same, for determining
5742 whether a color is supported or not. The range of values is 0-65535. */
5743
5744 #define TTY_SAME_COLOR_THRESHOLD 10000
5745
5746 #ifdef HAVE_WINDOW_SYSTEM
5747
5748 /* Return non-zero if all the face attributes in ATTRS are supported
5749 on the window-system frame F.
5750
5751 The definition of `supported' is somewhat heuristic, but basically means
5752 that a face containing all the attributes in ATTRS, when merged with the
5753 default face for display, can be represented in a way that's
5754
5755 \(1) different in appearance than the default face, and
5756 \(2) `close in spirit' to what the attributes specify, if not exact. */
5757
5758 static int
5759 x_supports_face_attributes_p (f, attrs, def_face)
5760 struct frame *f;
5761 Lisp_Object *attrs;
5762 struct face *def_face;
5763 {
5764 Lisp_Object *def_attrs = def_face->lface;
5765
5766 /* Check that other specified attributes are different that the default
5767 face. */
5768 if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
5769 && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
5770 def_attrs[LFACE_UNDERLINE_INDEX]))
5771 || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
5772 && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
5773 def_attrs[LFACE_INVERSE_INDEX]))
5774 || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
5775 && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
5776 def_attrs[LFACE_FOREGROUND_INDEX]))
5777 || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
5778 && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
5779 def_attrs[LFACE_BACKGROUND_INDEX]))
5780 || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
5781 && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
5782 def_attrs[LFACE_STIPPLE_INDEX]))
5783 || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
5784 && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
5785 def_attrs[LFACE_OVERLINE_INDEX]))
5786 || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
5787 && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
5788 def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
5789 || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
5790 && face_attr_equal_p (attrs[LFACE_BOX_INDEX],
5791 def_attrs[LFACE_BOX_INDEX])))
5792 return 0;
5793
5794 /* Check font-related attributes, as those are the most commonly
5795 "unsupported" on a window-system (because of missing fonts). */
5796 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
5797 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
5798 || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
5799 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
5800 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
5801 || !UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX]))
5802 {
5803 struct face *face;
5804 Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
5805
5806 bcopy (def_attrs, merged_attrs, sizeof merged_attrs);
5807
5808 merge_face_vectors (f, attrs, merged_attrs, Qnil);
5809
5810 face = FACE_FROM_ID (f, lookup_face (f, merged_attrs, 0, 0));
5811
5812 if (! face)
5813 signal_error ("cannot make face", 0);
5814
5815 /* If the font is the same, then not supported. */
5816 if (face->font == def_face->font)
5817 return 0;
5818 }
5819
5820 /* Everything checks out, this face is supported. */
5821 return 1;
5822 }
5823
5824 #endif /* HAVE_WINDOW_SYSTEM */
5825
5826 /* Return non-zero if all the face attributes in ATTRS are supported
5827 on the tty frame F.
5828
5829 The definition of `supported' is somewhat heuristic, but basically means
5830 that a face containing all the attributes in ATTRS, when merged
5831 with the default face for display, can be represented in a way that's
5832
5833 \(1) different in appearance than the default face, and
5834 \(2) `close in spirit' to what the attributes specify, if not exact.
5835
5836 Point (2) implies that a `:weight black' attribute will be satisfied
5837 by any terminal that can display bold, and a `:foreground "yellow"' as
5838 long as the terminal can display a yellowish color, but `:slant italic'
5839 will _not_ be satisfied by the tty display code's automatic
5840 substitution of a `dim' face for italic. */
5841
5842 static int
5843 tty_supports_face_attributes_p (f, attrs, def_face)
5844 struct frame *f;
5845 Lisp_Object *attrs;
5846 struct face *def_face;
5847 {
5848 int weight, i;
5849 Lisp_Object val, fg, bg;
5850 XColor fg_tty_color, fg_std_color;
5851 XColor bg_tty_color, bg_std_color;
5852 unsigned test_caps = 0;
5853 Lisp_Object *def_attrs = def_face->lface;
5854
5855
5856 /* First check some easy-to-check stuff; ttys support none of the
5857 following attributes, so we can just return false if any are requested
5858 (even if `nominal' values are specified, we should still return false,
5859 as that will be the same value that the default face uses). We
5860 consider :slant unsupportable on ttys, even though the face code
5861 actually `fakes' them using a dim attribute if possible. This is
5862 because the faked result is too different from what the face
5863 specifies. */
5864 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
5865 || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
5866 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
5867 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
5868 || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
5869 || !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
5870 || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
5871 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]))
5872 return 0;
5873
5874
5875 /* Test for terminal `capabilities' (non-color character attributes). */
5876
5877 /* font weight (bold/dim) */
5878 weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
5879 if (weight >= 0)
5880 {
5881 int def_weight = face_numeric_weight (def_attrs[LFACE_WEIGHT_INDEX]);
5882
5883 if (weight > XLFD_WEIGHT_MEDIUM)
5884 {
5885 if (def_weight > XLFD_WEIGHT_MEDIUM)
5886 return 0; /* same as default */
5887 test_caps = TTY_CAP_BOLD;
5888 }
5889 else if (weight < XLFD_WEIGHT_MEDIUM)
5890 {
5891 if (def_weight < XLFD_WEIGHT_MEDIUM)
5892 return 0; /* same as default */
5893 test_caps = TTY_CAP_DIM;
5894 }
5895 else if (def_weight == XLFD_WEIGHT_MEDIUM)
5896 return 0; /* same as default */
5897 }
5898
5899 /* underlining */
5900 val = attrs[LFACE_UNDERLINE_INDEX];
5901 if (!UNSPECIFIEDP (val))
5902 {
5903 if (STRINGP (val))
5904 return 0; /* ttys can't use colored underlines */
5905 else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
5906 return 0; /* same as default */
5907 else
5908 test_caps |= TTY_CAP_UNDERLINE;
5909 }
5910
5911 /* inverse video */
5912 val = attrs[LFACE_INVERSE_INDEX];
5913 if (!UNSPECIFIEDP (val))
5914 {
5915 if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
5916 return 0; /* same as default */
5917 else
5918 test_caps |= TTY_CAP_INVERSE;
5919 }
5920
5921
5922 /* Color testing. */
5923
5924 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
5925 we use them when calling `tty_capable_p' below, even if the face
5926 specifies no colors. */
5927 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
5928 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
5929
5930 /* Check if foreground color is close enough. */
5931 fg = attrs[LFACE_FOREGROUND_INDEX];
5932 if (STRINGP (fg))
5933 {
5934 Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
5935
5936 if (face_attr_equal_p (fg, def_fg))
5937 return 0; /* same as default */
5938 else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
5939 return 0; /* not a valid color */
5940 else if (color_distance (&fg_tty_color, &fg_std_color)
5941 > TTY_SAME_COLOR_THRESHOLD)
5942 return 0; /* displayed color is too different */
5943 else
5944 /* Make sure the color is really different than the default. */
5945 {
5946 XColor def_fg_color;
5947 if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
5948 && (color_distance (&fg_tty_color, &def_fg_color)
5949 <= TTY_SAME_COLOR_THRESHOLD))
5950 return 0;
5951 }
5952 }
5953
5954 /* Check if background color is close enough. */
5955 bg = attrs[LFACE_BACKGROUND_INDEX];
5956 if (STRINGP (bg))
5957 {
5958 Lisp_Object def_bg = def_attrs[LFACE_FOREGROUND_INDEX];
5959
5960 if (face_attr_equal_p (bg, def_bg))
5961 return 0; /* same as default */
5962 else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5963 return 0; /* not a valid color */
5964 else if (color_distance (&bg_tty_color, &bg_std_color)
5965 > TTY_SAME_COLOR_THRESHOLD)
5966 return 0; /* displayed color is too different */
5967 else
5968 /* Make sure the color is really different than the default. */
5969 {
5970 XColor def_bg_color;
5971 if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
5972 && (color_distance (&bg_tty_color, &def_bg_color)
5973 <= TTY_SAME_COLOR_THRESHOLD))
5974 return 0;
5975 }
5976 }
5977
5978 /* If both foreground and background are requested, see if the
5979 distance between them is OK. We just check to see if the distance
5980 between the tty's foreground and background is close enough to the
5981 distance between the standard foreground and background. */
5982 if (STRINGP (fg) && STRINGP (bg))
5983 {
5984 int delta_delta
5985 = (color_distance (&fg_std_color, &bg_std_color)
5986 - color_distance (&fg_tty_color, &bg_tty_color));
5987 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5988 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5989 return 0;
5990 }
5991
5992
5993 /* See if the capabilities we selected above are supported, with the
5994 given colors. */
5995 if (test_caps != 0 &&
5996 ! tty_capable_p (FRAME_TTY (f), test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
5997 return 0;
5998
5999
6000 /* Hmmm, everything checks out, this terminal must support this face. */
6001 return 1;
6002 }
6003
6004
6005 DEFUN ("display-supports-face-attributes-p",
6006 Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
6007 1, 2, 0,
6008 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
6009 The optional argument DISPLAY can be a display name, a frame, or
6010 nil (meaning the selected frame's display)
6011
6012 The definition of `supported' is somewhat heuristic, but basically means
6013 that a face containing all the attributes in ATTRIBUTES, when merged
6014 with the default face for display, can be represented in a way that's
6015
6016 \(1) different in appearance than the default face, and
6017 \(2) `close in spirit' to what the attributes specify, if not exact.
6018
6019 Point (2) implies that a `:weight black' attribute will be satisfied by
6020 any display that can display bold, and a `:foreground \"yellow\"' as long
6021 as it can display a yellowish color, but `:slant italic' will _not_ be
6022 satisfied by the tty display code's automatic substitution of a `dim'
6023 face for italic. */)
6024 (attributes, display)
6025 Lisp_Object attributes, display;
6026 {
6027 int supports, i;
6028 Lisp_Object frame;
6029 struct frame *f;
6030 struct face *def_face;
6031 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6032
6033 if (NILP (display))
6034 frame = selected_frame;
6035 else if (FRAMEP (display))
6036 frame = display;
6037 else
6038 {
6039 /* Find any frame on DISPLAY. */
6040 Lisp_Object fl_tail;
6041
6042 frame = Qnil;
6043 for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
6044 {
6045 frame = XCAR (fl_tail);
6046 if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
6047 XFRAME (frame)->param_alist)),
6048 display)))
6049 break;
6050 }
6051 }
6052
6053 CHECK_LIVE_FRAME (frame);
6054 f = XFRAME (frame);
6055
6056 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
6057 attrs[i] = Qunspecified;
6058 merge_face_vector_with_property (f, attrs, attributes);
6059
6060 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6061 if (def_face == NULL)
6062 {
6063 if (! realize_basic_faces (f))
6064 signal_error ("Cannot realize default face", 0);
6065 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6066 }
6067
6068 /* Dispatch to the appropriate handler. */
6069 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
6070 supports = tty_supports_face_attributes_p (f, attrs, def_face);
6071 #ifdef HAVE_WINDOW_SYSTEM
6072 else
6073 supports = x_supports_face_attributes_p (f, attrs, def_face);
6074 #endif
6075
6076 return supports ? Qt : Qnil;
6077 }
5917 6078
5918 6079
5919 /*********************************************************************** 6080 /***********************************************************************
5920 Font selection 6081 Font selection
5921 ***********************************************************************/ 6082 ***********************************************************************/
7720 defsubr (&Sinternal_lisp_face_empty_p); 7881 defsubr (&Sinternal_lisp_face_empty_p);
7721 defsubr (&Sinternal_copy_lisp_face); 7882 defsubr (&Sinternal_copy_lisp_face);
7722 defsubr (&Sinternal_merge_in_global_face); 7883 defsubr (&Sinternal_merge_in_global_face);
7723 defsubr (&Sface_font); 7884 defsubr (&Sface_font);
7724 defsubr (&Sframe_face_alist); 7885 defsubr (&Sframe_face_alist);
7725 defsubr (&Stty_supports_face_attributes_p); 7886 defsubr (&Sdisplay_supports_face_attributes_p);
7726 defsubr (&Scolor_distance); 7887 defsubr (&Scolor_distance);
7727 defsubr (&Sinternal_set_font_selection_order); 7888 defsubr (&Sinternal_set_font_selection_order);
7728 defsubr (&Sinternal_set_alternative_font_family_alist); 7889 defsubr (&Sinternal_set_alternative_font_family_alist);
7729 defsubr (&Sinternal_set_alternative_font_registry_alist); 7890 defsubr (&Sinternal_set_alternative_font_registry_alist);
7730 defsubr (&Sface_attributes_as_vector); 7891 defsubr (&Sface_attributes_as_vector);