diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/xfaces.c | 574 |
2 files changed, 366 insertions, 219 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index fd108641f22..5c87b950403 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2004-06-04 Miles Bader <miles@gnu.org> | ||
| 2 | |||
| 3 | * xfaces.c (tty_supports_face_attributes_p): New function, mostly | ||
| 4 | from Ftty_supports_face_attributes_p. | ||
| 5 | (x_supports_face_attributes_p): New function. | ||
| 6 | (Ftty_supports_face_attributes_p): Function deleted. | ||
| 7 | (Fdisplay_supports_face_attributes_p): New function. | ||
| 8 | (syms_of_xfaces): Initialize Sdisplay_supports_face_attributes_p. | ||
| 9 | (face_attr_equal_p): New function | ||
| 10 | (lface_equal_p): Use it. | ||
| 11 | |||
| 1 | 2004-06-03 Juanma Barranquero <lektu@terra.es> | 12 | 2004-06-03 Juanma Barranquero <lektu@terra.es> |
| 2 | 13 | ||
| 3 | * w32fns.c (Fx_display_grayscale_p, Fw32_send_sys_command) | 14 | * w32fns.c (Fx_display_grayscale_p, Fw32_send_sys_command) |
diff --git a/src/xfaces.c b/src/xfaces.c index 2bd3f31d6ea..bd19d32c990 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -4867,49 +4867,51 @@ If FRAME is omitted or nil, use the selected frame. */) | |||
| 4867 | } | 4867 | } |
| 4868 | 4868 | ||
| 4869 | 4869 | ||
| 4870 | /* Compare face vectors V1 and V2 for equality. Value is non-zero if | 4870 | /* 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 | 4871 | all attributes are `equal'. Tries to be fast because this function |
| 4872 | is called quite often. */ | 4872 | is called quite often. */ |
| 4873 | 4873 | ||
| 4874 | static INLINE int | 4874 | static INLINE int |
| 4875 | lface_equal_p (v1, v2) | 4875 | face_attr_equal_p (v1, v2) |
| 4876 | Lisp_Object *v1, *v2; | ||
| 4877 | { | 4876 | { |
| 4878 | int i, equal_p = 1; | 4877 | /* 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; | ||
| 4879 | 4881 | ||
| 4880 | for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) | 4882 | if (EQ (v1, v2)) |
| 4881 | { | 4883 | return 1; |
| 4882 | Lisp_Object a = v1[i]; | ||
| 4883 | Lisp_Object b = v2[i]; | ||
| 4884 | 4884 | ||
| 4885 | /* Type can differ, e.g. when one attribute is unspecified, i.e. nil, | 4885 | switch (XTYPE (v1)) |
| 4886 | and the other is specified. */ | 4886 | { |
| 4887 | equal_p = XTYPE (a) == XTYPE (b); | 4887 | case Lisp_String: |
| 4888 | if (!equal_p) | 4888 | if (SBYTES (v1) != SBYTES (v2)) |
| 4889 | break; | 4889 | return 0; |
| 4890 | 4890 | ||
| 4891 | if (!EQ (a, b)) | 4891 | return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0; |
| 4892 | { | ||
| 4893 | switch (XTYPE (a)) | ||
| 4894 | { | ||
| 4895 | case Lisp_String: | ||
| 4896 | equal_p = ((SBYTES (a) | ||
| 4897 | == SBYTES (b)) | ||
| 4898 | && bcmp (SDATA (a), SDATA (b), | ||
| 4899 | SBYTES (a)) == 0); | ||
| 4900 | break; | ||
| 4901 | 4892 | ||
| 4902 | case Lisp_Int: | 4893 | case Lisp_Int: |
| 4903 | case Lisp_Symbol: | 4894 | case Lisp_Symbol: |
| 4904 | equal_p = 0; | 4895 | return 0; |
| 4905 | break; | ||
| 4906 | 4896 | ||
| 4907 | default: | 4897 | default: |
| 4908 | equal_p = !NILP (Fequal (a, b)); | 4898 | return !NILP (Fequal (v1, v2)); |
| 4909 | break; | ||
| 4910 | } | ||
| 4911 | } | ||
| 4912 | } | 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]); | ||
| 4913 | 4915 | ||
| 4914 | return equal_p; | 4916 | return equal_p; |
| 4915 | } | 4917 | } |
| @@ -5209,192 +5211,6 @@ If FRAME is unspecified or nil, the current frame is used. */) | |||
| 5209 | 5211 | ||
| 5210 | 5212 | ||
| 5211 | /*********************************************************************** | 5213 | /*********************************************************************** |
| 5212 | Face capability testing for ttys | ||
| 5213 | ***********************************************************************/ | ||
| 5214 | |||
| 5215 | |||
| 5216 | /* If the distance (as returned by color_distance) between two colors is | ||
| 5217 | less than this, then they are considered the same, for determining | ||
| 5218 | whether a color is supported or not. The range of values is 0-65535. */ | ||
| 5219 | |||
| 5220 | #define TTY_SAME_COLOR_THRESHOLD 10000 | ||
| 5221 | |||
| 5222 | |||
| 5223 | DEFUN ("tty-supports-face-attributes-p", | ||
| 5224 | Ftty_supports_face_attributes_p, Stty_supports_face_attributes_p, | ||
| 5225 | 1, 2, 0, | ||
| 5226 | doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported. | ||
| 5227 | The optional argument FRAME is the frame on which to test; if it is nil | ||
| 5228 | or unspecified, then the current frame is used. If FRAME is not a tty | ||
| 5229 | frame, then nil is returned. | ||
| 5230 | |||
| 5231 | The definition of `supported' is somewhat heuristic, but basically means | ||
| 5232 | that a face containing all the attributes in ATTRIBUTES, when merged | ||
| 5233 | with the default face for display, can be represented in a way that's | ||
| 5234 | |||
| 5235 | \(1) different in appearance than the default face, and | ||
| 5236 | \(2) `close in spirit' to what the attributes specify, if not exact. | ||
| 5237 | |||
| 5238 | Point (2) implies that a `:weight black' attribute will be satisfied | ||
| 5239 | by any terminal that can display bold, and a `:foreground "yellow"' as | ||
| 5240 | long as the terminal can display a yellowish color, but `:slant italic' | ||
| 5241 | will _not_ be satisfied by the tty display code's automatic | ||
| 5242 | substitution of a `dim' face for italic. */) | ||
| 5243 | (attributes, frame) | ||
| 5244 | Lisp_Object attributes, frame; | ||
| 5245 | { | ||
| 5246 | int weight, i; | ||
| 5247 | struct frame *f; | ||
| 5248 | Lisp_Object val, fg, bg; | ||
| 5249 | XColor fg_tty_color, fg_std_color; | ||
| 5250 | XColor bg_tty_color, bg_std_color; | ||
| 5251 | Lisp_Object attrs[LFACE_VECTOR_SIZE]; | ||
| 5252 | unsigned test_caps = 0; | ||
| 5253 | |||
| 5254 | if (NILP (frame)) | ||
| 5255 | frame = selected_frame; | ||
| 5256 | CHECK_LIVE_FRAME (frame); | ||
| 5257 | f = XFRAME (frame); | ||
| 5258 | |||
| 5259 | for (i = 0; i < LFACE_VECTOR_SIZE; i++) | ||
| 5260 | attrs[i] = Qunspecified; | ||
| 5261 | merge_face_vector_with_property (f, attrs, attributes); | ||
| 5262 | |||
| 5263 | /* This function only works on ttys. */ | ||
| 5264 | if (!FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f)) | ||
| 5265 | return Qnil; | ||
| 5266 | |||
| 5267 | /* First check some easy-to-check stuff; ttys support none of the | ||
| 5268 | following attributes, so we can just return nil if any are requested. */ | ||
| 5269 | |||
| 5270 | /* stipple */ | ||
| 5271 | val = attrs[LFACE_STIPPLE_INDEX]; | ||
| 5272 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5273 | return Qnil; | ||
| 5274 | |||
| 5275 | /* font height */ | ||
| 5276 | val = attrs[LFACE_HEIGHT_INDEX]; | ||
| 5277 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5278 | return Qnil; | ||
| 5279 | |||
| 5280 | /* font width */ | ||
| 5281 | val = attrs[LFACE_SWIDTH_INDEX]; | ||
| 5282 | if (!UNSPECIFIEDP (val) && !NILP (val) | ||
| 5283 | && face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM) | ||
| 5284 | return Qnil; | ||
| 5285 | |||
| 5286 | /* overline */ | ||
| 5287 | val = attrs[LFACE_OVERLINE_INDEX]; | ||
| 5288 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5289 | return Qnil; | ||
| 5290 | |||
| 5291 | /* strike-through */ | ||
| 5292 | val = attrs[LFACE_STRIKE_THROUGH_INDEX]; | ||
| 5293 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5294 | return Qnil; | ||
| 5295 | |||
| 5296 | /* boxes */ | ||
| 5297 | val = attrs[LFACE_BOX_INDEX]; | ||
| 5298 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5299 | return Qnil; | ||
| 5300 | |||
| 5301 | /* slant (italics/oblique); We consider any non-default value | ||
| 5302 | unsupportable on ttys, even though the face code actually `fakes' | ||
| 5303 | them using a dim attribute if possible. This is because the faked | ||
| 5304 | result is too different from what the face specifies. */ | ||
| 5305 | val = attrs[LFACE_SLANT_INDEX]; | ||
| 5306 | if (!UNSPECIFIEDP (val) && !NILP (val) | ||
| 5307 | && face_numeric_slant (val) != XLFD_SLANT_ROMAN) | ||
| 5308 | return Qnil; | ||
| 5309 | |||
| 5310 | |||
| 5311 | /* Test for terminal `capabilities' (non-color character attributes). */ | ||
| 5312 | |||
| 5313 | /* font weight (bold/dim) */ | ||
| 5314 | weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]); | ||
| 5315 | if (weight >= 0) | ||
| 5316 | { | ||
| 5317 | if (weight > XLFD_WEIGHT_MEDIUM) | ||
| 5318 | test_caps = TTY_CAP_BOLD; | ||
| 5319 | else if (weight < XLFD_WEIGHT_MEDIUM) | ||
| 5320 | test_caps = TTY_CAP_DIM; | ||
| 5321 | } | ||
| 5322 | |||
| 5323 | /* underlining */ | ||
| 5324 | val = attrs[LFACE_UNDERLINE_INDEX]; | ||
| 5325 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5326 | { | ||
| 5327 | if (STRINGP (val)) | ||
| 5328 | return Qnil; /* ttys don't support colored underlines */ | ||
| 5329 | else | ||
| 5330 | test_caps |= TTY_CAP_UNDERLINE; | ||
| 5331 | } | ||
| 5332 | |||
| 5333 | /* inverse video */ | ||
| 5334 | val = attrs[LFACE_INVERSE_INDEX]; | ||
| 5335 | if (!UNSPECIFIEDP (val) && !NILP (val)) | ||
| 5336 | test_caps |= TTY_CAP_INVERSE; | ||
| 5337 | |||
| 5338 | |||
| 5339 | /* Color testing. */ | ||
| 5340 | |||
| 5341 | /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since | ||
| 5342 | we use them when calling `tty_capable_p' below, even if the face | ||
| 5343 | specifies no colors. */ | ||
| 5344 | fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR; | ||
| 5345 | bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR; | ||
| 5346 | |||
| 5347 | /* Check if foreground color is close enough. */ | ||
| 5348 | fg = attrs[LFACE_FOREGROUND_INDEX]; | ||
| 5349 | if (STRINGP (fg)) | ||
| 5350 | { | ||
| 5351 | if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color)) | ||
| 5352 | return Qnil; | ||
| 5353 | else if (color_distance (&fg_tty_color, &fg_std_color) | ||
| 5354 | > TTY_SAME_COLOR_THRESHOLD) | ||
| 5355 | return Qnil; | ||
| 5356 | } | ||
| 5357 | |||
| 5358 | /* Check if background color is close enough. */ | ||
| 5359 | bg = attrs[LFACE_BACKGROUND_INDEX]; | ||
| 5360 | if (STRINGP (bg)) | ||
| 5361 | { | ||
| 5362 | if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color)) | ||
| 5363 | return Qnil; | ||
| 5364 | else if (color_distance (&bg_tty_color, &bg_std_color) | ||
| 5365 | > TTY_SAME_COLOR_THRESHOLD) | ||
| 5366 | return Qnil; | ||
| 5367 | } | ||
| 5368 | |||
| 5369 | /* If both foreground and background are requested, see if the | ||
| 5370 | distance between them is OK. We just check to see if the distance | ||
| 5371 | between the tty's foreground and background is close enough to the | ||
| 5372 | distance between the standard foreground and background. */ | ||
| 5373 | if (STRINGP (fg) && STRINGP (bg)) | ||
| 5374 | { | ||
| 5375 | int delta_delta | ||
| 5376 | = (color_distance (&fg_std_color, &bg_std_color) | ||
| 5377 | - color_distance (&fg_tty_color, &bg_tty_color)); | ||
| 5378 | if (delta_delta > TTY_SAME_COLOR_THRESHOLD | ||
| 5379 | || delta_delta < -TTY_SAME_COLOR_THRESHOLD) | ||
| 5380 | return Qnil; | ||
| 5381 | } | ||
| 5382 | |||
| 5383 | |||
| 5384 | /* See if the capabilities we selected above are supported, with the | ||
| 5385 | given colors. */ | ||
| 5386 | if (test_caps != 0 && | ||
| 5387 | ! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel)) | ||
| 5388 | return Qnil; | ||
| 5389 | |||
| 5390 | |||
| 5391 | /* Hmmm, everything checks out, this terminal must support this face. */ | ||
| 5392 | return Qt; | ||
| 5393 | } | ||
| 5394 | |||
| 5395 | |||
| 5396 | |||
| 5397 | /*********************************************************************** | ||
| 5398 | Face Cache | 5214 | Face Cache |
| 5399 | ***********************************************************************/ | 5215 | ***********************************************************************/ |
| 5400 | 5216 | ||
| @@ -5914,6 +5730,326 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector, | |||
| 5914 | 5730 | ||
| 5915 | 5731 | ||
| 5916 | /*********************************************************************** | 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 | /*********************************************************************** | ||
| 5917 | Font selection | 6053 | Font selection |
| 5918 | ***********************************************************************/ | 6054 | ***********************************************************************/ |
| 5919 | 6055 | ||
| @@ -7713,7 +7849,7 @@ syms_of_xfaces () | |||
| 7713 | defsubr (&Sinternal_merge_in_global_face); | 7849 | defsubr (&Sinternal_merge_in_global_face); |
| 7714 | defsubr (&Sface_font); | 7850 | defsubr (&Sface_font); |
| 7715 | defsubr (&Sframe_face_alist); | 7851 | defsubr (&Sframe_face_alist); |
| 7716 | defsubr (&Stty_supports_face_attributes_p); | 7852 | defsubr (&Sdisplay_supports_face_attributes_p); |
| 7717 | defsubr (&Scolor_distance); | 7853 | defsubr (&Scolor_distance); |
| 7718 | defsubr (&Sinternal_set_font_selection_order); | 7854 | defsubr (&Sinternal_set_font_selection_order); |
| 7719 | defsubr (&Sinternal_set_alternative_font_family_alist); | 7855 | defsubr (&Sinternal_set_alternative_font_family_alist); |