diff options
| author | Karoly Lorentey | 2004-06-05 17:21:43 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2004-06-05 17:21:43 +0000 |
| commit | 3d63dd9d07a4ce2fbff5c4dd674f2593c1e3a278 (patch) | |
| tree | 148939ccc16f4f81c8231987a0556ec21d529e7b /src | |
| parent | bf2d7b586bf6add7527739fcbdc007e921259397 (diff) | |
| parent | 8e330b2257db682ec067cdd72d8e7a4580f97505 (diff) | |
| download | emacs-3d63dd9d07a4ce2fbff5c4dd674f2593c1e3a278.tar.gz emacs-3d63dd9d07a4ce2fbff5c4dd674f2593c1e3a278.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 23 | ||||
| -rw-r--r-- | src/xfaces.c | 599 |
2 files changed, 403 insertions, 219 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index fd108641f22..d9000d6dd05 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,26 @@ | |||
| 1 | 2004-06-05 Miles Bader <miles@gnu.org> | ||
| 2 | |||
| 3 | * xfaces.c (tty_supports_face_attributes_p): Make sure the specified | ||
| 4 | attributes have different values than the default face. | ||
| 5 | |||
| 6 | 2004-06-04 Eli Zaretskii <eliz@gnu.org> | ||
| 7 | |||
| 8 | * xfaces.c (x_supports_face_attributes_p): Make this function | ||
| 9 | conditional on HAVE_WINDOW_SYSTEM. | ||
| 10 | (Fdisplay_supports_face_attributes_p) [HAVE_WINDOW_SYSTEM]: Don't | ||
| 11 | call x_supports_face_attributes_p if it was not compiled in. | ||
| 12 | |||
| 13 | 2004-06-04 Miles Bader <miles@gnu.org> | ||
| 14 | |||
| 15 | * xfaces.c (tty_supports_face_attributes_p): New function, mostly | ||
| 16 | from Ftty_supports_face_attributes_p. | ||
| 17 | (x_supports_face_attributes_p): New function. | ||
| 18 | (Ftty_supports_face_attributes_p): Function deleted. | ||
| 19 | (Fdisplay_supports_face_attributes_p): New function. | ||
| 20 | (syms_of_xfaces): Initialize Sdisplay_supports_face_attributes_p. | ||
| 21 | (face_attr_equal_p): New function | ||
| 22 | (lface_equal_p): Use it. | ||
| 23 | |||
| 1 | 2004-06-03 Juanma Barranquero <lektu@terra.es> | 24 | 2004-06-03 Juanma Barranquero <lektu@terra.es> |
| 2 | 25 | ||
| 3 | * w32fns.c (Fx_display_grayscale_p, Fw32_send_sys_command) | 26 | * w32fns.c (Fx_display_grayscale_p, Fw32_send_sys_command) |
diff --git a/src/xfaces.c b/src/xfaces.c index bae9b569f1a..6e447e0cb0e 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -4870,49 +4870,51 @@ If FRAME is omitted or nil, use the selected frame. */) | |||
| 4870 | } | 4870 | } |
| 4871 | 4871 | ||
| 4872 | 4872 | ||
| 4873 | /* Compare face vectors V1 and V2 for equality. Value is non-zero if | 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 | 4874 | all attributes are `equal'. Tries to be fast because this function |
| 4875 | is called quite often. */ | 4875 | is called quite often. */ |
| 4876 | 4876 | ||
| 4877 | static INLINE int | 4877 | static INLINE int |
| 4878 | lface_equal_p (v1, v2) | 4878 | face_attr_equal_p (v1, v2) |
| 4879 | Lisp_Object *v1, *v2; | ||
| 4880 | { | 4879 | { |
| 4881 | int i, equal_p = 1; | 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; | ||
| 4882 | 4884 | ||
| 4883 | for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) | 4885 | if (EQ (v1, v2)) |
| 4884 | { | 4886 | return 1; |
| 4885 | Lisp_Object a = v1[i]; | ||
| 4886 | Lisp_Object b = v2[i]; | ||
| 4887 | 4887 | ||
| 4888 | /* Type can differ, e.g. when one attribute is unspecified, i.e. nil, | 4888 | switch (XTYPE (v1)) |
| 4889 | and the other is specified. */ | 4889 | { |
| 4890 | equal_p = XTYPE (a) == XTYPE (b); | 4890 | case Lisp_String: |
| 4891 | if (!equal_p) | 4891 | if (SBYTES (v1) != SBYTES (v2)) |
| 4892 | break; | 4892 | return 0; |
| 4893 | 4893 | ||
| 4894 | if (!EQ (a, b)) | 4894 | return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0; |
| 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 | 4895 | ||
| 4905 | case Lisp_Int: | 4896 | case Lisp_Int: |
| 4906 | case Lisp_Symbol: | 4897 | case Lisp_Symbol: |
| 4907 | equal_p = 0; | 4898 | return 0; |
| 4908 | break; | ||
| 4909 | 4899 | ||
| 4910 | default: | 4900 | default: |
| 4911 | equal_p = !NILP (Fequal (a, b)); | 4901 | return !NILP (Fequal (v1, v2)); |
| 4912 | break; | ||
| 4913 | } | ||
| 4914 | } | ||
| 4915 | } | 4902 | } |
| 4903 | } | ||
| 4904 | |||
| 4905 | |||
| 4906 | /* Compare face vectors V1 and V2 for equality. Value is non-zero if | ||
| 4907 | all attributes are `equal'. Tries to be fast because this function | ||
| 4908 | is called quite often. */ | ||
| 4909 | |||
| 4910 | static INLINE int | ||
| 4911 | lface_equal_p (v1, v2) | ||
| 4912 | Lisp_Object *v1, *v2; | ||
| 4913 | { | ||
| 4914 | int i, equal_p = 1; | ||
| 4915 | |||
| 4916 | for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) | ||
| 4917 | equal_p = face_attr_equal_p (v1[i], v2[i]); | ||
| 4916 | 4918 | ||
| 4917 | return equal_p; | 4919 | return equal_p; |
| 4918 | } | 4920 | } |
| @@ -5212,192 +5214,6 @@ If FRAME is unspecified or nil, the current frame is used. */) | |||
| 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 | ||
| @@ -5917,6 +5733,351 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector, | |||
| 5917 | 5733 | ||
| 5918 | 5734 | ||
| 5919 | /*********************************************************************** | 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 | } | ||
| 6078 | |||
| 6079 | |||
| 6080 | /*********************************************************************** | ||
| 5920 | Font selection | 6081 | Font selection |
| 5921 | ***********************************************************************/ | 6082 | ***********************************************************************/ |
| 5922 | 6083 | ||
| @@ -7722,7 +7883,7 @@ syms_of_xfaces () | |||
| 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); |