Mercurial > emacs
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); |