mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-13 16:38:14 +00:00
Revision: miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-370
Move `display-supports-face-attributes-p' entirely into C code Previously only the tty-related portion of display-supports-face-attributes-p was done in C. This just moves the graphical-display related bits into C too, which allows us to implement them properly (the previous attempt to do a halfway-proper job in lisp didn't work because of funny conditions during emacs startup).
This commit is contained in:
parent
5129f10c94
commit
9717e36cff
@ -5,6 +5,14 @@
|
||||
Shawn Boyette <mdxi@collapsar.net> in
|
||||
http://lists.gnu.org/archive/html/emacs-devel/2004-05/msg00442.html.
|
||||
|
||||
2004-06-04 Miles Bader <miles@gnu.org>
|
||||
|
||||
* faces.el (display-supports-face-attributes-p): Function moved to
|
||||
C code. Previously only the tty-related portion of this function
|
||||
was done in C; however the previous attempt to do a halfway-proper
|
||||
job for non-tty displays in lisp didn't work properly because of
|
||||
funny conditions during emacs startup.
|
||||
|
||||
2004-06-04 Miles Bader <miles@gnu.org>
|
||||
|
||||
* faces.el (face-differs-from-default-p): Use a different
|
||||
|
@ -1505,47 +1505,6 @@ If omitted or nil, that stands for the selected frame's display."
|
||||
(t
|
||||
(> (tty-color-gray-shades display) 2)))))
|
||||
|
||||
(defun display-supports-face-attributes-p (attributes &optional display)
|
||||
"Return non-nil if all the face attributes in ATTRIBUTES are supported.
|
||||
The optional argument DISPLAY can be a display name, a frame, or
|
||||
nil (meaning the selected frame's display)
|
||||
|
||||
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 display that can display bold, and a `:foreground \"yellow\"' as long
|
||||
as it 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."
|
||||
(let ((frame
|
||||
(if (framep display)
|
||||
display
|
||||
(car (frames-on-display-list display)))))
|
||||
(if (not (memq (framep frame) '(x w32 mac)))
|
||||
;; On ttys, `tty-supports-face-attributes-p' does all the work we need.
|
||||
(tty-supports-face-attributes-p attributes frame)
|
||||
;; For now, we assume that non-tty displays can support everything,
|
||||
;; and so we just check to see if any of the specified attributes is
|
||||
;; different from the default -- though this probably isn't always
|
||||
;; accurate for font-related attributes. Later, we should add the
|
||||
;; ability to query about specific fonts, colors, etc.
|
||||
(while (and attributes
|
||||
(let* ((attr (car attributes))
|
||||
(val (cadr attributes))
|
||||
(default-val (face-attribute 'default attr frame)))
|
||||
(if (and (stringp val) (stringp default-val))
|
||||
;; compare string attributes case-insensitively
|
||||
(eq (compare-strings val nil nil default-val nil nil t)
|
||||
t)
|
||||
(equal val default-val))))
|
||||
(setq attributes (cddr attributes)))
|
||||
(not (null attributes)))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Background mode.
|
||||
|
@ -1,3 +1,14 @@
|
||||
2004-06-04 Miles Bader <miles@gnu.org>
|
||||
|
||||
* xfaces.c (tty_supports_face_attributes_p): New function, mostly
|
||||
from Ftty_supports_face_attributes_p.
|
||||
(x_supports_face_attributes_p): New function.
|
||||
(Ftty_supports_face_attributes_p): Function deleted.
|
||||
(Fdisplay_supports_face_attributes_p): New function.
|
||||
(syms_of_xfaces): Initialize Sdisplay_supports_face_attributes_p.
|
||||
(face_attr_equal_p): New function
|
||||
(lface_equal_p): Use it.
|
||||
|
||||
2004-06-03 Juanma Barranquero <lektu@terra.es>
|
||||
|
||||
* w32fns.c (Fx_display_grayscale_p, Fw32_send_sys_command)
|
||||
|
574
src/xfaces.c
574
src/xfaces.c
@ -4867,6 +4867,39 @@ If FRAME is omitted or nil, use the selected frame. */)
|
||||
}
|
||||
|
||||
|
||||
/* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
|
||||
all attributes are `equal'. Tries to be fast because this function
|
||||
is called quite often. */
|
||||
|
||||
static INLINE int
|
||||
face_attr_equal_p (v1, v2)
|
||||
{
|
||||
/* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
|
||||
and the other is specified. */
|
||||
if (XTYPE (v1) != XTYPE (v2))
|
||||
return 0;
|
||||
|
||||
if (EQ (v1, v2))
|
||||
return 1;
|
||||
|
||||
switch (XTYPE (v1))
|
||||
{
|
||||
case Lisp_String:
|
||||
if (SBYTES (v1) != SBYTES (v2))
|
||||
return 0;
|
||||
|
||||
return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
|
||||
|
||||
case Lisp_Int:
|
||||
case Lisp_Symbol:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return !NILP (Fequal (v1, v2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Compare face vectors V1 and V2 for equality. Value is non-zero if
|
||||
all attributes are `equal'. Tries to be fast because this function
|
||||
is called quite often. */
|
||||
@ -4878,38 +4911,7 @@ lface_equal_p (v1, v2)
|
||||
int i, equal_p = 1;
|
||||
|
||||
for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
|
||||
{
|
||||
Lisp_Object a = v1[i];
|
||||
Lisp_Object b = v2[i];
|
||||
|
||||
/* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
|
||||
and the other is specified. */
|
||||
equal_p = XTYPE (a) == XTYPE (b);
|
||||
if (!equal_p)
|
||||
break;
|
||||
|
||||
if (!EQ (a, b))
|
||||
{
|
||||
switch (XTYPE (a))
|
||||
{
|
||||
case Lisp_String:
|
||||
equal_p = ((SBYTES (a)
|
||||
== SBYTES (b))
|
||||
&& bcmp (SDATA (a), SDATA (b),
|
||||
SBYTES (a)) == 0);
|
||||
break;
|
||||
|
||||
case Lisp_Int:
|
||||
case Lisp_Symbol:
|
||||
equal_p = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
equal_p = !NILP (Fequal (a, b));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
equal_p = face_attr_equal_p (v1[i], v2[i]);
|
||||
|
||||
return equal_p;
|
||||
}
|
||||
@ -5207,192 +5209,6 @@ If FRAME is unspecified or nil, the current frame is used. */)
|
||||
return make_number (color_distance (&cdef1, &cdef2));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Face Cache
|
||||
@ -5912,6 +5728,326 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Face capability testing
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
/* Return non-zero if all the face attributes in ATTRS are supported
|
||||
on the window-system frame F.
|
||||
|
||||
The definition of `supported' is somewhat heuristic, but basically means
|
||||
that a face containing all the attributes in ATTRS, 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.
|
||||
|
||||
This function modifies ATTRS by merging from the default face. */
|
||||
|
||||
static int
|
||||
x_supports_face_attributes_p (f, attrs)
|
||||
struct frame *f;
|
||||
Lisp_Object *attrs;
|
||||
{
|
||||
Lisp_Object *def_attrs;
|
||||
struct face *def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
|
||||
|
||||
if (def_face == NULL)
|
||||
{
|
||||
if (! realize_basic_faces (f))
|
||||
signal_error ("Cannot realize default face", 0);
|
||||
def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
|
||||
}
|
||||
|
||||
def_attrs = def_face->lface;
|
||||
|
||||
/* Check that other specified attributes are different that the default
|
||||
face. */
|
||||
if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
|
||||
def_attrs[LFACE_UNDERLINE_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
|
||||
def_attrs[LFACE_INVERSE_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
|
||||
def_attrs[LFACE_FOREGROUND_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
|
||||
def_attrs[LFACE_BACKGROUND_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
|
||||
def_attrs[LFACE_STIPPLE_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
|
||||
def_attrs[LFACE_OVERLINE_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
|
||||
def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
|
||||
|| (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
|
||||
&& face_attr_equal_p (attrs[LFACE_BOX_INDEX],
|
||||
def_attrs[LFACE_BOX_INDEX])))
|
||||
return 0;
|
||||
|
||||
/* Check font-related attributes, as those are the most commonly
|
||||
"unsupported" on a window-system (because of missing fonts). */
|
||||
if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
|
||||
|| !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
|
||||
|| !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
|
||||
|| !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
|
||||
|| !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
|
||||
|| !UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX]))
|
||||
{
|
||||
struct face *face;
|
||||
Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
|
||||
|
||||
bcopy (def_attrs, merged_attrs, sizeof merged_attrs);
|
||||
|
||||
merge_face_vectors (f, attrs, merged_attrs, Qnil);
|
||||
|
||||
face = FACE_FROM_ID (f, lookup_face (f, merged_attrs, 0, 0));
|
||||
|
||||
if (! face)
|
||||
signal_error ("cannot make face", 0);
|
||||
|
||||
/* If the font is the same, then not supported. */
|
||||
if (face->font == def_face->font)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Everything checks out, this face is supported. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Return non-zero if all the face attributes in ATTRS are supported
|
||||
on the tty frame F.
|
||||
|
||||
The definition of `supported' is somewhat heuristic, but basically means
|
||||
that a face containing all the attributes in ATTRS, 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. */
|
||||
|
||||
static int
|
||||
tty_supports_face_attributes_p (f, attrs)
|
||||
struct frame *f;
|
||||
Lisp_Object *attrs;
|
||||
{
|
||||
int weight, i;
|
||||
Lisp_Object val, fg, bg;
|
||||
XColor fg_tty_color, fg_std_color;
|
||||
XColor bg_tty_color, bg_std_color;
|
||||
unsigned test_caps = 0;
|
||||
|
||||
/* 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 0;
|
||||
|
||||
/* font height */
|
||||
val = attrs[LFACE_HEIGHT_INDEX];
|
||||
if (!UNSPECIFIEDP (val) && !NILP (val))
|
||||
return 0;
|
||||
|
||||
/* font width */
|
||||
val = attrs[LFACE_SWIDTH_INDEX];
|
||||
if (!UNSPECIFIEDP (val) && !NILP (val)
|
||||
&& face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM)
|
||||
return 0;
|
||||
|
||||
/* overline */
|
||||
val = attrs[LFACE_OVERLINE_INDEX];
|
||||
if (!UNSPECIFIEDP (val) && !NILP (val))
|
||||
return 0;
|
||||
|
||||
/* strike-through */
|
||||
val = attrs[LFACE_STRIKE_THROUGH_INDEX];
|
||||
if (!UNSPECIFIEDP (val) && !NILP (val))
|
||||
return 0;
|
||||
|
||||
/* boxes */
|
||||
val = attrs[LFACE_BOX_INDEX];
|
||||
if (!UNSPECIFIEDP (val) && !NILP (val))
|
||||
return 0;
|
||||
|
||||
/* 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 0;
|
||||
|
||||
|
||||
/* 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 0; /* 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 0;
|
||||
else if (color_distance (&fg_tty_color, &fg_std_color)
|
||||
> TTY_SAME_COLOR_THRESHOLD)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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 0;
|
||||
else if (color_distance (&bg_tty_color, &bg_std_color)
|
||||
> TTY_SAME_COLOR_THRESHOLD)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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 0;
|
||||
}
|
||||
|
||||
|
||||
/* 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 0;
|
||||
|
||||
|
||||
/* Hmmm, everything checks out, this terminal must support this face. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("display-supports-face-attributes-p",
|
||||
Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
|
||||
1, 2, 0,
|
||||
doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
|
||||
The optional argument DISPLAY can be a display name, a frame, or
|
||||
nil (meaning the selected frame's display)
|
||||
|
||||
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 display that can display bold, and a `:foreground \"yellow\"' as long
|
||||
as it 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, display)
|
||||
Lisp_Object attributes, display;
|
||||
{
|
||||
int supports, i;
|
||||
Lisp_Object frame;
|
||||
struct frame *f;
|
||||
Lisp_Object attrs[LFACE_VECTOR_SIZE];
|
||||
|
||||
if (NILP (display))
|
||||
frame = selected_frame;
|
||||
else if (FRAMEP (display))
|
||||
frame = display;
|
||||
else
|
||||
{
|
||||
/* Find any frame on DISPLAY. */
|
||||
Lisp_Object fl_tail;
|
||||
|
||||
frame = Qnil;
|
||||
for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
|
||||
{
|
||||
frame = XCAR (fl_tail);
|
||||
if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
|
||||
XFRAME (frame)->param_alist)),
|
||||
display)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Dispatch to the appropriate handler. */
|
||||
if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
|
||||
supports = tty_supports_face_attributes_p (f, attrs);
|
||||
else
|
||||
supports = x_supports_face_attributes_p (f, attrs);
|
||||
|
||||
return supports ? Qt : Qnil;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Font selection
|
||||
@ -7713,7 +7849,7 @@ syms_of_xfaces ()
|
||||
defsubr (&Sinternal_merge_in_global_face);
|
||||
defsubr (&Sface_font);
|
||||
defsubr (&Sframe_face_alist);
|
||||
defsubr (&Stty_supports_face_attributes_p);
|
||||
defsubr (&Sdisplay_supports_face_attributes_p);
|
||||
defsubr (&Scolor_distance);
|
||||
defsubr (&Sinternal_set_font_selection_order);
|
||||
defsubr (&Sinternal_set_alternative_font_family_alist);
|
||||
|
Loading…
Reference in New Issue
Block a user