4867 |
} |
} |
4868 |
|
|
4869 |
|
|
4870 |
/* Compare face vectors V1 and V2 for equality. Value is non-zero if |
/* Compare face-attribute values v1 and v2 for equality. Value is non-zero if |
4871 |
all attributes are `equal'. Tries to be fast because this function |
all attributes are `equal'. Tries to be fast because this function |
4872 |
is called quite often. */ |
is called quite often. */ |
4873 |
|
|
4874 |
static INLINE int |
static INLINE int |
4875 |
lface_equal_p (v1, v2) |
face_attr_equal_p (v1, v2) |
|
Lisp_Object *v1, *v2; |
|
4876 |
{ |
{ |
4877 |
int i, equal_p = 1; |
/* Type can differ, e.g. when one attribute is unspecified, i.e. nil, |
4878 |
|
and the other is specified. */ |
4879 |
|
if (XTYPE (v1) != XTYPE (v2)) |
4880 |
|
return 0; |
4881 |
|
|
4882 |
for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) |
if (EQ (v1, v2)) |
4883 |
|
return 1; |
4884 |
|
|
4885 |
|
switch (XTYPE (v1)) |
4886 |
{ |
{ |
4887 |
Lisp_Object a = v1[i]; |
case Lisp_String: |
4888 |
Lisp_Object b = v2[i]; |
if (SBYTES (v1) != SBYTES (v2)) |
4889 |
|
return 0; |
4890 |
|
|
4891 |
/* Type can differ, e.g. when one attribute is unspecified, i.e. nil, |
return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0; |
|
and the other is specified. */ |
|
|
equal_p = XTYPE (a) == XTYPE (b); |
|
|
if (!equal_p) |
|
|
break; |
|
4892 |
|
|
4893 |
if (!EQ (a, b)) |
case Lisp_Int: |
4894 |
{ |
case Lisp_Symbol: |
4895 |
switch (XTYPE (a)) |
return 0; |
|
{ |
|
|
case Lisp_String: |
|
|
equal_p = ((SBYTES (a) |
|
|
== SBYTES (b)) |
|
|
&& bcmp (SDATA (a), SDATA (b), |
|
|
SBYTES (a)) == 0); |
|
|
break; |
|
4896 |
|
|
4897 |
case Lisp_Int: |
default: |
4898 |
case Lisp_Symbol: |
return !NILP (Fequal (v1, v2)); |
|
equal_p = 0; |
|
|
break; |
|
|
|
|
|
default: |
|
|
equal_p = !NILP (Fequal (a, b)); |
|
|
break; |
|
|
} |
|
|
} |
|
4899 |
} |
} |
4900 |
|
} |
4901 |
|
|
4902 |
|
|
4903 |
|
/* Compare face vectors V1 and V2 for equality. Value is non-zero if |
4904 |
|
all attributes are `equal'. Tries to be fast because this function |
4905 |
|
is called quite often. */ |
4906 |
|
|
4907 |
|
static INLINE int |
4908 |
|
lface_equal_p (v1, v2) |
4909 |
|
Lisp_Object *v1, *v2; |
4910 |
|
{ |
4911 |
|
int i, equal_p = 1; |
4912 |
|
|
4913 |
|
for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) |
4914 |
|
equal_p = face_attr_equal_p (v1[i], v2[i]); |
4915 |
|
|
4916 |
return equal_p; |
return equal_p; |
4917 |
} |
} |
5211 |
|
|
5212 |
|
|
5213 |
/*********************************************************************** |
/*********************************************************************** |
|
Face capability testing for ttys |
|
|
***********************************************************************/ |
|
|
|
|
|
|
|
|
/* If the distance (as returned by color_distance) between two colors is |
|
|
less than this, then they are considered the same, for determining |
|
|
whether a color is supported or not. The range of values is 0-65535. */ |
|
|
|
|
|
#define TTY_SAME_COLOR_THRESHOLD 10000 |
|
|
|
|
|
|
|
|
DEFUN ("tty-supports-face-attributes-p", |
|
|
Ftty_supports_face_attributes_p, Stty_supports_face_attributes_p, |
|
|
1, 2, 0, |
|
|
doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported. |
|
|
The optional argument FRAME is the frame on which to test; if it is nil |
|
|
or unspecified, then the current frame is used. If FRAME is not a tty |
|
|
frame, then nil is returned. |
|
|
|
|
|
The definition of `supported' is somewhat heuristic, but basically means |
|
|
that a face containing all the attributes in ATTRIBUTES, when merged |
|
|
with the default face for display, can be represented in a way that's |
|
|
|
|
|
\(1) different in appearance than the default face, and |
|
|
\(2) `close in spirit' to what the attributes specify, if not exact. |
|
|
|
|
|
Point (2) implies that a `:weight black' attribute will be satisfied |
|
|
by any terminal that can display bold, and a `:foreground "yellow"' as |
|
|
long as the terminal can display a yellowish color, but `:slant italic' |
|
|
will _not_ be satisfied by the tty display code's automatic |
|
|
substitution of a `dim' face for italic. */) |
|
|
(attributes, frame) |
|
|
Lisp_Object attributes, frame; |
|
|
{ |
|
|
int weight, i; |
|
|
struct frame *f; |
|
|
Lisp_Object val, fg, bg; |
|
|
XColor fg_tty_color, fg_std_color; |
|
|
XColor bg_tty_color, bg_std_color; |
|
|
Lisp_Object attrs[LFACE_VECTOR_SIZE]; |
|
|
unsigned test_caps = 0; |
|
|
|
|
|
if (NILP (frame)) |
|
|
frame = selected_frame; |
|
|
CHECK_LIVE_FRAME (frame); |
|
|
f = XFRAME (frame); |
|
|
|
|
|
for (i = 0; i < LFACE_VECTOR_SIZE; i++) |
|
|
attrs[i] = Qunspecified; |
|
|
merge_face_vector_with_property (f, attrs, attributes); |
|
|
|
|
|
/* This function only works on ttys. */ |
|
|
if (!FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f)) |
|
|
return Qnil; |
|
|
|
|
|
/* First check some easy-to-check stuff; ttys support none of the |
|
|
following attributes, so we can just return nil if any are requested. */ |
|
|
|
|
|
/* stipple */ |
|
|
val = attrs[LFACE_STIPPLE_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
return Qnil; |
|
|
|
|
|
/* font height */ |
|
|
val = attrs[LFACE_HEIGHT_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
return Qnil; |
|
|
|
|
|
/* font width */ |
|
|
val = attrs[LFACE_SWIDTH_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val) |
|
|
&& face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM) |
|
|
return Qnil; |
|
|
|
|
|
/* overline */ |
|
|
val = attrs[LFACE_OVERLINE_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
return Qnil; |
|
|
|
|
|
/* strike-through */ |
|
|
val = attrs[LFACE_STRIKE_THROUGH_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
return Qnil; |
|
|
|
|
|
/* boxes */ |
|
|
val = attrs[LFACE_BOX_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
return Qnil; |
|
|
|
|
|
/* slant (italics/oblique); We consider any non-default value |
|
|
unsupportable on ttys, even though the face code actually `fakes' |
|
|
them using a dim attribute if possible. This is because the faked |
|
|
result is too different from what the face specifies. */ |
|
|
val = attrs[LFACE_SLANT_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val) |
|
|
&& face_numeric_slant (val) != XLFD_SLANT_ROMAN) |
|
|
return Qnil; |
|
|
|
|
|
|
|
|
/* Test for terminal `capabilities' (non-color character attributes). */ |
|
|
|
|
|
/* font weight (bold/dim) */ |
|
|
weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]); |
|
|
if (weight >= 0) |
|
|
{ |
|
|
if (weight > XLFD_WEIGHT_MEDIUM) |
|
|
test_caps = TTY_CAP_BOLD; |
|
|
else if (weight < XLFD_WEIGHT_MEDIUM) |
|
|
test_caps = TTY_CAP_DIM; |
|
|
} |
|
|
|
|
|
/* underlining */ |
|
|
val = attrs[LFACE_UNDERLINE_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
{ |
|
|
if (STRINGP (val)) |
|
|
return Qnil; /* ttys don't support colored underlines */ |
|
|
else |
|
|
test_caps |= TTY_CAP_UNDERLINE; |
|
|
} |
|
|
|
|
|
/* inverse video */ |
|
|
val = attrs[LFACE_INVERSE_INDEX]; |
|
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
|
|
test_caps |= TTY_CAP_INVERSE; |
|
|
|
|
|
|
|
|
/* Color testing. */ |
|
|
|
|
|
/* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since |
|
|
we use them when calling `tty_capable_p' below, even if the face |
|
|
specifies no colors. */ |
|
|
fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR; |
|
|
bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR; |
|
|
|
|
|
/* Check if foreground color is close enough. */ |
|
|
fg = attrs[LFACE_FOREGROUND_INDEX]; |
|
|
if (STRINGP (fg)) |
|
|
{ |
|
|
if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color)) |
|
|
return Qnil; |
|
|
else if (color_distance (&fg_tty_color, &fg_std_color) |
|
|
> TTY_SAME_COLOR_THRESHOLD) |
|
|
return Qnil; |
|
|
} |
|
|
|
|
|
/* Check if background color is close enough. */ |
|
|
bg = attrs[LFACE_BACKGROUND_INDEX]; |
|
|
if (STRINGP (bg)) |
|
|
{ |
|
|
if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color)) |
|
|
return Qnil; |
|
|
else if (color_distance (&bg_tty_color, &bg_std_color) |
|
|
> TTY_SAME_COLOR_THRESHOLD) |
|
|
return Qnil; |
|
|
} |
|
|
|
|
|
/* If both foreground and background are requested, see if the |
|
|
distance between them is OK. We just check to see if the distance |
|
|
between the tty's foreground and background is close enough to the |
|
|
distance between the standard foreground and background. */ |
|
|
if (STRINGP (fg) && STRINGP (bg)) |
|
|
{ |
|
|
int delta_delta |
|
|
= (color_distance (&fg_std_color, &bg_std_color) |
|
|
- color_distance (&fg_tty_color, &bg_tty_color)); |
|
|
if (delta_delta > TTY_SAME_COLOR_THRESHOLD |
|
|
|| delta_delta < -TTY_SAME_COLOR_THRESHOLD) |
|
|
return Qnil; |
|
|
} |
|
|
|
|
|
|
|
|
/* See if the capabilities we selected above are supported, with the |
|
|
given colors. */ |
|
|
if (test_caps != 0 && |
|
|
! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel)) |
|
|
return Qnil; |
|
|
|
|
|
|
|
|
/* Hmmm, everything checks out, this terminal must support this face. */ |
|
|
return Qt; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************** |
|
5214 |
Face Cache |
Face Cache |
5215 |
***********************************************************************/ |
***********************************************************************/ |
5216 |
|
|
5730 |
|
|
5731 |
|
|
5732 |
/*********************************************************************** |
/*********************************************************************** |
5733 |
|
Face capability testing |
5734 |
|
***********************************************************************/ |
5735 |
|
|
5736 |
|
|
5737 |
|
/* If the distance (as returned by color_distance) between two colors is |
5738 |
|
less than this, then they are considered the same, for determining |
5739 |
|
whether a color is supported or not. The range of values is 0-65535. */ |
5740 |
|
|
5741 |
|
#define TTY_SAME_COLOR_THRESHOLD 10000 |
5742 |
|
|
5743 |
|
|
5744 |
|
/* Return non-zero if all the face attributes in ATTRS are supported |
5745 |
|
on the window-system frame F. |
5746 |
|
|
5747 |
|
The definition of `supported' is somewhat heuristic, but basically means |
5748 |
|
that a face containing all the attributes in ATTRS, when merged with the |
5749 |
|
default face for display, can be represented in a way that's |
5750 |
|
|
5751 |
|
\(1) different in appearance than the default face, and |
5752 |
|
\(2) `close in spirit' to what the attributes specify, if not exact. |
5753 |
|
|
5754 |
|
This function modifies ATTRS by merging from the default face. */ |
5755 |
|
|
5756 |
|
static int |
5757 |
|
x_supports_face_attributes_p (f, attrs) |
5758 |
|
struct frame *f; |
5759 |
|
Lisp_Object *attrs; |
5760 |
|
{ |
5761 |
|
Lisp_Object *def_attrs; |
5762 |
|
struct face *def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); |
5763 |
|
|
5764 |
|
if (def_face == NULL) |
5765 |
|
{ |
5766 |
|
if (! realize_basic_faces (f)) |
5767 |
|
signal_error ("Cannot realize default face", 0); |
5768 |
|
def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); |
5769 |
|
} |
5770 |
|
|
5771 |
|
def_attrs = def_face->lface; |
5772 |
|
|
5773 |
|
/* Check that other specified attributes are different that the default |
5774 |
|
face. */ |
5775 |
|
if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) |
5776 |
|
&& face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX], |
5777 |
|
def_attrs[LFACE_UNDERLINE_INDEX])) |
5778 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX]) |
5779 |
|
&& face_attr_equal_p (attrs[LFACE_INVERSE_INDEX], |
5780 |
|
def_attrs[LFACE_INVERSE_INDEX])) |
5781 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX]) |
5782 |
|
&& face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX], |
5783 |
|
def_attrs[LFACE_FOREGROUND_INDEX])) |
5784 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX]) |
5785 |
|
&& face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX], |
5786 |
|
def_attrs[LFACE_BACKGROUND_INDEX])) |
5787 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX]) |
5788 |
|
&& face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX], |
5789 |
|
def_attrs[LFACE_STIPPLE_INDEX])) |
5790 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) |
5791 |
|
&& face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX], |
5792 |
|
def_attrs[LFACE_OVERLINE_INDEX])) |
5793 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX]) |
5794 |
|
&& face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX], |
5795 |
|
def_attrs[LFACE_STRIKE_THROUGH_INDEX])) |
5796 |
|
|| (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]) |
5797 |
|
&& face_attr_equal_p (attrs[LFACE_BOX_INDEX], |
5798 |
|
def_attrs[LFACE_BOX_INDEX]))) |
5799 |
|
return 0; |
5800 |
|
|
5801 |
|
/* Check font-related attributes, as those are the most commonly |
5802 |
|
"unsupported" on a window-system (because of missing fonts). */ |
5803 |
|
if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX]) |
5804 |
|
|| !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX]) |
5805 |
|
|| !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX]) |
5806 |
|
|| !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]) |
5807 |
|
|| !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]) |
5808 |
|
|| !UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])) |
5809 |
|
{ |
5810 |
|
struct face *face; |
5811 |
|
Lisp_Object merged_attrs[LFACE_VECTOR_SIZE]; |
5812 |
|
|
5813 |
|
bcopy (def_attrs, merged_attrs, sizeof merged_attrs); |
5814 |
|
|
5815 |
|
merge_face_vectors (f, attrs, merged_attrs, Qnil); |
5816 |
|
|
5817 |
|
face = FACE_FROM_ID (f, lookup_face (f, merged_attrs, 0, 0)); |
5818 |
|
|
5819 |
|
if (! face) |
5820 |
|
signal_error ("cannot make face", 0); |
5821 |
|
|
5822 |
|
/* If the font is the same, then not supported. */ |
5823 |
|
if (face->font == def_face->font) |
5824 |
|
return 0; |
5825 |
|
} |
5826 |
|
|
5827 |
|
/* Everything checks out, this face is supported. */ |
5828 |
|
return 1; |
5829 |
|
} |
5830 |
|
|
5831 |
|
|
5832 |
|
/* Return non-zero if all the face attributes in ATTRS are supported |
5833 |
|
on the tty frame F. |
5834 |
|
|
5835 |
|
The definition of `supported' is somewhat heuristic, but basically means |
5836 |
|
that a face containing all the attributes in ATTRS, when merged |
5837 |
|
with the default face for display, can be represented in a way that's |
5838 |
|
|
5839 |
|
\(1) different in appearance than the default face, and |
5840 |
|
\(2) `close in spirit' to what the attributes specify, if not exact. |
5841 |
|
|
5842 |
|
Point (2) implies that a `:weight black' attribute will be satisfied |
5843 |
|
by any terminal that can display bold, and a `:foreground "yellow"' as |
5844 |
|
long as the terminal can display a yellowish color, but `:slant italic' |
5845 |
|
will _not_ be satisfied by the tty display code's automatic |
5846 |
|
substitution of a `dim' face for italic. */ |
5847 |
|
|
5848 |
|
static int |
5849 |
|
tty_supports_face_attributes_p (f, attrs) |
5850 |
|
struct frame *f; |
5851 |
|
Lisp_Object *attrs; |
5852 |
|
{ |
5853 |
|
int weight, i; |
5854 |
|
Lisp_Object val, fg, bg; |
5855 |
|
XColor fg_tty_color, fg_std_color; |
5856 |
|
XColor bg_tty_color, bg_std_color; |
5857 |
|
unsigned test_caps = 0; |
5858 |
|
|
5859 |
|
/* First check some easy-to-check stuff; ttys support none of the |
5860 |
|
following attributes, so we can just return nil if any are requested. */ |
5861 |
|
|
5862 |
|
/* stipple */ |
5863 |
|
val = attrs[LFACE_STIPPLE_INDEX]; |
5864 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5865 |
|
return 0; |
5866 |
|
|
5867 |
|
/* font height */ |
5868 |
|
val = attrs[LFACE_HEIGHT_INDEX]; |
5869 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5870 |
|
return 0; |
5871 |
|
|
5872 |
|
/* font width */ |
5873 |
|
val = attrs[LFACE_SWIDTH_INDEX]; |
5874 |
|
if (!UNSPECIFIEDP (val) && !NILP (val) |
5875 |
|
&& face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM) |
5876 |
|
return 0; |
5877 |
|
|
5878 |
|
/* overline */ |
5879 |
|
val = attrs[LFACE_OVERLINE_INDEX]; |
5880 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5881 |
|
return 0; |
5882 |
|
|
5883 |
|
/* strike-through */ |
5884 |
|
val = attrs[LFACE_STRIKE_THROUGH_INDEX]; |
5885 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5886 |
|
return 0; |
5887 |
|
|
5888 |
|
/* boxes */ |
5889 |
|
val = attrs[LFACE_BOX_INDEX]; |
5890 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5891 |
|
return 0; |
5892 |
|
|
5893 |
|
/* slant (italics/oblique); We consider any non-default value |
5894 |
|
unsupportable on ttys, even though the face code actually `fakes' |
5895 |
|
them using a dim attribute if possible. This is because the faked |
5896 |
|
result is too different from what the face specifies. */ |
5897 |
|
val = attrs[LFACE_SLANT_INDEX]; |
5898 |
|
if (!UNSPECIFIEDP (val) && !NILP (val) |
5899 |
|
&& face_numeric_slant (val) != XLFD_SLANT_ROMAN) |
5900 |
|
return 0; |
5901 |
|
|
5902 |
|
|
5903 |
|
/* Test for terminal `capabilities' (non-color character attributes). */ |
5904 |
|
|
5905 |
|
/* font weight (bold/dim) */ |
5906 |
|
weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]); |
5907 |
|
if (weight >= 0) |
5908 |
|
{ |
5909 |
|
if (weight > XLFD_WEIGHT_MEDIUM) |
5910 |
|
test_caps = TTY_CAP_BOLD; |
5911 |
|
else if (weight < XLFD_WEIGHT_MEDIUM) |
5912 |
|
test_caps = TTY_CAP_DIM; |
5913 |
|
} |
5914 |
|
|
5915 |
|
/* underlining */ |
5916 |
|
val = attrs[LFACE_UNDERLINE_INDEX]; |
5917 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5918 |
|
{ |
5919 |
|
if (STRINGP (val)) |
5920 |
|
return 0; /* ttys don't support colored underlines */ |
5921 |
|
else |
5922 |
|
test_caps |= TTY_CAP_UNDERLINE; |
5923 |
|
} |
5924 |
|
|
5925 |
|
/* inverse video */ |
5926 |
|
val = attrs[LFACE_INVERSE_INDEX]; |
5927 |
|
if (!UNSPECIFIEDP (val) && !NILP (val)) |
5928 |
|
test_caps |= TTY_CAP_INVERSE; |
5929 |
|
|
5930 |
|
|
5931 |
|
/* Color testing. */ |
5932 |
|
|
5933 |
|
/* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since |
5934 |
|
we use them when calling `tty_capable_p' below, even if the face |
5935 |
|
specifies no colors. */ |
5936 |
|
fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR; |
5937 |
|
bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR; |
5938 |
|
|
5939 |
|
/* Check if foreground color is close enough. */ |
5940 |
|
fg = attrs[LFACE_FOREGROUND_INDEX]; |
5941 |
|
if (STRINGP (fg)) |
5942 |
|
{ |
5943 |
|
if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color)) |
5944 |
|
return 0; |
5945 |
|
else if (color_distance (&fg_tty_color, &fg_std_color) |
5946 |
|
> TTY_SAME_COLOR_THRESHOLD) |
5947 |
|
return 0; |
5948 |
|
} |
5949 |
|
|
5950 |
|
/* Check if background color is close enough. */ |
5951 |
|
bg = attrs[LFACE_BACKGROUND_INDEX]; |
5952 |
|
if (STRINGP (bg)) |
5953 |
|
{ |
5954 |
|
if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color)) |
5955 |
|
return 0; |
5956 |
|
else if (color_distance (&bg_tty_color, &bg_std_color) |
5957 |
|
> TTY_SAME_COLOR_THRESHOLD) |
5958 |
|
return 0; |
5959 |
|
} |
5960 |
|
|
5961 |
|
/* If both foreground and background are requested, see if the |
5962 |
|
distance between them is OK. We just check to see if the distance |
5963 |
|
between the tty's foreground and background is close enough to the |
5964 |
|
distance between the standard foreground and background. */ |
5965 |
|
if (STRINGP (fg) && STRINGP (bg)) |
5966 |
|
{ |
5967 |
|
int delta_delta |
5968 |
|
= (color_distance (&fg_std_color, &bg_std_color) |
5969 |
|
- color_distance (&fg_tty_color, &bg_tty_color)); |
5970 |
|
if (delta_delta > TTY_SAME_COLOR_THRESHOLD |
5971 |
|
|| delta_delta < -TTY_SAME_COLOR_THRESHOLD) |
5972 |
|
return 0; |
5973 |
|
} |
5974 |
|
|
5975 |
|
|
5976 |
|
/* See if the capabilities we selected above are supported, with the |
5977 |
|
given colors. */ |
5978 |
|
if (test_caps != 0 && |
5979 |
|
! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel)) |
5980 |
|
return 0; |
5981 |
|
|
5982 |
|
|
5983 |
|
/* Hmmm, everything checks out, this terminal must support this face. */ |
5984 |
|
return 1; |
5985 |
|
} |
5986 |
|
|
5987 |
|
|
5988 |
|
DEFUN ("display-supports-face-attributes-p", |
5989 |
|
Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p, |
5990 |
|
1, 2, 0, |
5991 |
|
doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported. |
5992 |
|
The optional argument DISPLAY can be a display name, a frame, or |
5993 |
|
nil (meaning the selected frame's display) |
5994 |
|
|
5995 |
|
The definition of `supported' is somewhat heuristic, but basically means |
5996 |
|
that a face containing all the attributes in ATTRIBUTES, when merged |
5997 |
|
with the default face for display, can be represented in a way that's |
5998 |
|
|
5999 |
|
\(1) different in appearance than the default face, and |
6000 |
|
\(2) `close in spirit' to what the attributes specify, if not exact. |
6001 |
|
|
6002 |
|
Point (2) implies that a `:weight black' attribute will be satisfied by |
6003 |
|
any display that can display bold, and a `:foreground \"yellow\"' as long |
6004 |
|
as it can display a yellowish color, but `:slant italic' will _not_ be |
6005 |
|
satisfied by the tty display code's automatic substitution of a `dim' |
6006 |
|
face for italic. */) |
6007 |
|
(attributes, display) |
6008 |
|
Lisp_Object attributes, display; |
6009 |
|
{ |
6010 |
|
int supports, i; |
6011 |
|
Lisp_Object frame; |
6012 |
|
struct frame *f; |
6013 |
|
Lisp_Object attrs[LFACE_VECTOR_SIZE]; |
6014 |
|
|
6015 |
|
if (NILP (display)) |
6016 |
|
frame = selected_frame; |
6017 |
|
else if (FRAMEP (display)) |
6018 |
|
frame = display; |
6019 |
|
else |
6020 |
|
{ |
6021 |
|
/* Find any frame on DISPLAY. */ |
6022 |
|
Lisp_Object fl_tail; |
6023 |
|
|
6024 |
|
frame = Qnil; |
6025 |
|
for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail)) |
6026 |
|
{ |
6027 |
|
frame = XCAR (fl_tail); |
6028 |
|
if (!NILP (Fequal (Fcdr (Fassq (Qdisplay, |
6029 |
|
XFRAME (frame)->param_alist)), |
6030 |
|
display))) |
6031 |
|
break; |
6032 |
|
} |
6033 |
|
} |
6034 |
|
|
6035 |
|
CHECK_LIVE_FRAME (frame); |
6036 |
|
f = XFRAME (frame); |
6037 |
|
|
6038 |
|
for (i = 0; i < LFACE_VECTOR_SIZE; i++) |
6039 |
|
attrs[i] = Qunspecified; |
6040 |
|
merge_face_vector_with_property (f, attrs, attributes); |
6041 |
|
|
6042 |
|
/* Dispatch to the appropriate handler. */ |
6043 |
|
if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) |
6044 |
|
supports = tty_supports_face_attributes_p (f, attrs); |
6045 |
|
else |
6046 |
|
supports = x_supports_face_attributes_p (f, attrs); |
6047 |
|
|
6048 |
|
return supports ? Qt : Qnil; |
6049 |
|
} |
6050 |
|
|
6051 |
|
|
6052 |
|
/*********************************************************************** |
6053 |
Font selection |
Font selection |
6054 |
***********************************************************************/ |
***********************************************************************/ |
6055 |
|
|
7849 |
defsubr (&Sinternal_merge_in_global_face); |
defsubr (&Sinternal_merge_in_global_face); |
7850 |
defsubr (&Sface_font); |
defsubr (&Sface_font); |
7851 |
defsubr (&Sframe_face_alist); |
defsubr (&Sframe_face_alist); |
7852 |
defsubr (&Stty_supports_face_attributes_p); |
defsubr (&Sdisplay_supports_face_attributes_p); |
7853 |
defsubr (&Scolor_distance); |
defsubr (&Scolor_distance); |
7854 |
defsubr (&Sinternal_set_font_selection_order); |
defsubr (&Sinternal_set_font_selection_order); |
7855 |
defsubr (&Sinternal_set_alternative_font_family_alist); |
defsubr (&Sinternal_set_alternative_font_family_alist); |