This source file includes following definitions.
- register_color
- unregister_color
- unregister_colors
- DEFUN
- x_free_colors
- x_free_dpy_colors
- x_create_gc
- x_free_gc
- x_create_gc
- x_free_gc
- x_create_gc
- x_free_gc
- x_create_gc
- x_free_gc
- x_create_gc
- x_free_gc
- init_frame_faces
- free_frame_faces
- recompute_basic_faces
- clear_face_cache
- DEFUN
- DEFUN
- load_pixmap
- parse_hex_color_comp
- parse_float_color_comp
- parse_color_spec
- DEFUN
- parse_rgb_list
- tty_lookup_color
- tty_defined_color
- tty_color_name
- face_color_gray_p
- face_color_supported_p
- load_color2
- load_color
- load_face_colors
- unload_color
- free_face_colors
- compare_fonts_by_sort_order
- check_lface_attrs
- check_lface
- push_named_merge_point
- resolve_face_name
- lface_from_face_name_no_resolve
- lface_from_face_name
- get_lface_attributes_no_remap
- get_lface_attributes
- lface_fully_specified_p
- set_lface_from_font
- merge_face_heights
- merge_face_vectors
- face_inherited_attr
- merge_named_face
- evaluate_face_filter
- filter_face_ref
- merge_face_ref
- update_face_from_frame_parameter
- set_font_frame_param
- face_boolean_x_resource_value
- x_update_menu_appearance
- DEFUN
- face_attr_equal_p
- lface_equal_p
- DEFUN
- hash_string_case_insensitive
- lface_hash
- lface_same_font_attributes_p
- make_realized_face
- free_realized_face
- prepare_face_for_display
- color_distance
- make_face_cache
- clear_face_gcs
- free_realized_faces
- free_all_realized_faces
- free_face_cache
- cache_face
- uncache_face
- lookup_face
- face_for_font
- lookup_named_face
- lookup_basic_face
- smaller_face
- face_with_height
- lookup_derived_face
- DEFUN
- gui_supports_face_attributes_p
- tty_supports_face_attributes_p
- DEFUN
- DEFUN
- DEFUN
- face_fontset
- realize_basic_faces
- realize_default_face
- realize_named_face
- realize_face
- realize_non_ascii_face
- font_maybe_unset_attribute
- realize_gui_face
- map_tty_color
- realize_tty_face
- DEFUN
- compute_char_face
- face_at_buffer_position
- face_for_overlay_string
- face_at_string_position
- merge_faces
- DEFUN
- dump_realized_face
- DEFUN
- DEFUN
- init_xfaces
- syms_of_xfaces
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 #include <config.h>
220 #include <stdlib.h>
221 #include "sysstdio.h"
222 #include <sys/types.h>
223 #include <sys/stat.h>
224 #include <math.h>
225
226 #include "lisp.h"
227 #include "character.h"
228 #include "frame.h"
229
230 #ifdef USE_MOTIF
231 #include <Xm/Xm.h>
232 #include <Xm/XmStrDefs.h>
233 #endif
234
235 #ifdef MSDOS
236 #include "dosfns.h"
237 #endif
238
239 #ifdef HAVE_WINDOW_SYSTEM
240 #include TERM_HEADER
241 #include "fontset.h"
242 #ifdef HAVE_NTGUI
243 #define GCGraphicsExposures 0
244 #endif
245
246 #ifdef HAVE_NS
247 #define GCGraphicsExposures 0
248 #endif
249
250 #ifdef HAVE_PGTK
251 #define GCGraphicsExposures 0
252 #endif
253
254 #ifdef HAVE_HAIKU
255 #define GCGraphicsExposures 0
256 #endif
257
258 #ifdef HAVE_ANDROID
259 #define GCGraphicsExposures 0
260 #endif
261 #endif
262
263 #include "buffer.h"
264 #include "dispextern.h"
265 #include "blockinput.h"
266 #include "window.h"
267 #include "termchar.h"
268
269 #include "font.h"
270
271 #ifdef HAVE_X_WINDOWS
272
273
274
275
276
277
278 #ifdef XOS_NEEDS_TIME_H
279 #include <time.h>
280 #undef USG
281 #include <X11/Xos.h>
282 #define USG
283 #define __TIMEVAL__
284 #if defined USG || defined __TIMEVAL__
285 #endif
286 #else
287 #include <X11/Xos.h>
288 #endif
289
290 #endif
291
292 #include <c-ctype.h>
293
294
295
296 #define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
297
298
299
300 #define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface)
301
302
303
304 #define RESET_P(ATTR) EQ ((ATTR), Qreset)
305
306
307
308
309 #define FACE_CACHE_BUCKETS_SIZE 1009
310
311 char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
312
313
314
315
316
317 Lisp_Object Vface_alternative_font_family_alist;
318
319
320
321
322
323 Lisp_Object Vface_alternative_font_registry_alist;
324
325
326
327 static int next_lface_id;
328
329
330
331 static Lisp_Object *lface_id_to_name;
332 static ptrdiff_t lface_id_to_name_size;
333
334 #ifdef HAVE_WINDOW_SYSTEM
335
336
337
338
339
340 static int clear_font_table_count;
341 #define CLEAR_FONT_TABLE_COUNT 100
342 #define CLEAR_FONT_TABLE_NFONTS 10
343
344 #endif
345
346
347
348
349 bool face_change;
350
351
352
353
354
355
356 static bool tty_suppress_bold_inverse_default_colors_p;
357
358
359
360 #ifdef GLYPH_DEBUG
361 static int ncolors_allocated;
362 static int npixmaps_allocated;
363 static int ngcs;
364 #endif
365
366
367
368
369 static bool menu_face_changed_default;
370
371 struct named_merge_point;
372
373 static struct face *realize_face (struct face_cache *,
374 Lisp_Object [LFACE_VECTOR_SIZE],
375 int);
376 static struct face *realize_gui_face (struct face_cache *,
377 Lisp_Object [LFACE_VECTOR_SIZE]);
378 static struct face *realize_tty_face (struct face_cache *,
379 Lisp_Object [LFACE_VECTOR_SIZE]);
380 static bool realize_basic_faces (struct frame *);
381 static bool realize_default_face (struct frame *);
382 static void realize_named_face (struct frame *, Lisp_Object, int);
383 static struct face_cache *make_face_cache (struct frame *);
384 static void free_face_cache (struct face_cache *);
385 static bool merge_face_ref (struct window *w,
386 struct frame *, Lisp_Object, Lisp_Object *,
387 bool, struct named_merge_point *,
388 enum lface_attribute_index);
389 static int color_distance (Emacs_Color *x, Emacs_Color *y);
390
391 #ifdef HAVE_WINDOW_SYSTEM
392 static void set_font_frame_param (Lisp_Object, Lisp_Object);
393 static void clear_face_gcs (struct face_cache *);
394 static struct face *realize_non_ascii_face (struct frame *, Lisp_Object,
395 struct face *);
396 #endif
397
398
399
400
401
402 #ifdef HAVE_X_WINDOWS
403
404 #ifdef DEBUG_X_COLORS
405
406
407
408
409
410
411
412
413
414
415
416
417 int color_count[256];
418
419
420
421 void
422 register_color (unsigned long pixel)
423 {
424 eassert (pixel < 256);
425 ++color_count[pixel];
426 }
427
428
429
430
431 void
432 unregister_color (unsigned long pixel)
433 {
434 eassert (pixel < 256);
435 if (color_count[pixel] > 0)
436 --color_count[pixel];
437 else
438 emacs_abort ();
439 }
440
441
442
443
444 void
445 unregister_colors (unsigned long *pixels, int n)
446 {
447 int i;
448 for (i = 0; i < n; ++i)
449 unregister_color (pixels[i]);
450 }
451
452
453 DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
454 doc: )
455 (void)
456 {
457 int i, n;
458
459 putc ('\n', stderr);
460
461 for (i = n = 0; i < ARRAYELTS (color_count); ++i)
462 if (color_count[i])
463 {
464 fprintf (stderr, "%3d: %5d", i, color_count[i]);
465 ++n;
466 putc (n % 5 == 0 ? '\n' : '\t', stderr);
467 }
468
469 if (n % 5 != 0)
470 putc ('\n', stderr);
471 return Qnil;
472 }
473
474 #endif
475
476
477
478
479
480
481 void
482 x_free_colors (struct frame *f, unsigned long *pixels, int npixels)
483 {
484
485
486 if (x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
487 {
488 #ifdef DEBUG_X_COLORS
489 unregister_colors (pixels, npixels);
490 #endif
491 XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
492 pixels, npixels, 0);
493 }
494 }
495
496
497 #ifdef USE_X_TOOLKIT
498
499
500
501
502
503 void
504 x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap,
505 unsigned long *pixels, int npixels)
506 {
507 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
508
509
510
511 if (x_mutable_colormap (&dpyinfo->visual_info))
512 {
513 #ifdef DEBUG_X_COLORS
514 unregister_colors (pixels, npixels);
515 #endif
516 XFreeColors (dpy, cmap, pixels, npixels, 0);
517 }
518 }
519 #endif
520
521
522
523
524 static GC
525 x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
526 {
527 GC gc;
528 block_input ();
529 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, xgcv);
530 unblock_input ();
531 IF_DEBUG (++ngcs);
532 return gc;
533 }
534
535
536
537
538 static void
539 x_free_gc (struct frame *f, GC gc)
540 {
541 eassert (input_blocked_p ());
542 IF_DEBUG ((--ngcs, eassert (ngcs >= 0)));
543 XFreeGC (FRAME_X_DISPLAY (f), gc);
544 }
545
546 #endif
547
548 #ifdef HAVE_NTGUI
549
550
551 static Emacs_GC *
552 x_create_gc (struct frame *f, unsigned long mask, Emacs_GC *egc)
553 {
554 Emacs_GC *gc;
555 block_input ();
556 gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, egc);
557 unblock_input ();
558 IF_DEBUG (++ngcs);
559 return gc;
560 }
561
562
563
564
565 static void
566 x_free_gc (struct frame *f, Emacs_GC *gc)
567 {
568 IF_DEBUG ((--ngcs, eassert (ngcs >= 0)));
569 xfree (gc);
570 }
571
572 #endif
573
574 #if defined (HAVE_NS) || defined (HAVE_HAIKU)
575
576
577 static Emacs_GC *
578 x_create_gc (struct frame *f,
579 unsigned long mask,
580 Emacs_GC *egc)
581 {
582 Emacs_GC *gc = xmalloc (sizeof *gc);
583 *gc = *egc;
584 return gc;
585 }
586
587 static void
588 x_free_gc (struct frame *f, Emacs_GC *gc)
589 {
590 xfree (gc);
591 }
592 #endif
593
594 #ifdef HAVE_PGTK
595
596
597 static Emacs_GC *
598 x_create_gc (struct frame *f,
599 unsigned long mask,
600 Emacs_GC *xgcv)
601 {
602 Emacs_GC *gc = xmalloc (sizeof *gc);
603 *gc = *xgcv;
604 return gc;
605 }
606
607 static void
608 x_free_gc (struct frame *f, Emacs_GC *gc)
609 {
610 xfree (gc);
611 }
612 #endif
613
614 #ifdef HAVE_ANDROID
615
616
617
618 static struct android_gc *
619 x_create_gc (struct frame *f, unsigned long value_mask,
620 Emacs_GC *xgcv)
621 {
622 struct android_gc_values gcv;
623 unsigned long mask;
624
625 gcv.foreground = xgcv->foreground;
626 gcv.background = xgcv->background;
627
628 mask = 0;
629
630 if (value_mask & GCForeground)
631 mask |= ANDROID_GC_FOREGROUND;
632
633 if (value_mask & GCBackground)
634 mask |= ANDROID_GC_BACKGROUND;
635
636 return android_create_gc (mask, &gcv);
637 }
638
639 static void
640 x_free_gc (struct frame *f, struct android_gc *gc)
641 {
642 android_free_gc (gc);
643 }
644
645 #endif
646
647
648
649
650
651
652
653 void
654 init_frame_faces (struct frame *f)
655 {
656
657 if (FRAME_FACE_CACHE (f) == NULL)
658 FRAME_FACE_CACHE (f) = make_face_cache (f);
659
660 #ifdef HAVE_WINDOW_SYSTEM
661
662 if (FRAME_WINDOW_P (f))
663 {
664
665
666
667 if (FRAME_IMAGE_CACHE (f) == NULL)
668 FRAME_IMAGE_CACHE (f) = make_image_cache ();
669 ++FRAME_IMAGE_CACHE (f)->refcount;
670 }
671 #endif
672
673
674 if (!realize_basic_faces (f))
675 emacs_abort ();
676 }
677
678
679
680
681
682 void
683 free_frame_faces (struct frame *f)
684 {
685 struct face_cache *face_cache = FRAME_FACE_CACHE (f);
686
687 if (face_cache)
688 {
689 free_face_cache (face_cache);
690 FRAME_FACE_CACHE (f) = NULL;
691 }
692
693 #ifdef HAVE_WINDOW_SYSTEM
694 if (FRAME_WINDOW_P (f))
695 {
696 struct image_cache *image_cache = FRAME_IMAGE_CACHE (f);
697 if (image_cache)
698 {
699 --image_cache->refcount;
700 if (image_cache->refcount == 0)
701 free_image_cache (f);
702 }
703 }
704 #endif
705 }
706
707
708
709
710
711
712
713 void
714 recompute_basic_faces (struct frame *f)
715 {
716 if (FRAME_FACE_CACHE (f))
717 {
718 clear_face_cache (false);
719 if (!realize_basic_faces (f))
720 emacs_abort ();
721 }
722 }
723
724
725
726
727
728 void
729 clear_face_cache (bool clear_fonts_p)
730 {
731 #ifdef HAVE_WINDOW_SYSTEM
732 Lisp_Object tail, frame;
733
734 if (clear_fonts_p
735 || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
736 {
737
738
739
740 clear_font_table_count = 0;
741
742 FOR_EACH_FRAME (tail, frame)
743 {
744 struct frame *f = XFRAME (frame);
745 if (FRAME_WINDOW_P (f)
746 && FRAME_DISPLAY_INFO (f)->n_fonts > CLEAR_FONT_TABLE_NFONTS
747 && !f->inhibit_clear_image_cache)
748 {
749 clear_font_cache (f);
750 free_all_realized_faces (frame);
751 }
752 }
753 }
754 else
755 {
756
757 FOR_EACH_FRAME (tail, frame)
758 {
759 struct frame *f = XFRAME (frame);
760 if (FRAME_WINDOW_P (f))
761 clear_face_gcs (FRAME_FACE_CACHE (f));
762 }
763 clear_image_caches (Qnil);
764 }
765 #endif
766 }
767
768 DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0,
769 doc:
770 )
771 (Lisp_Object thoroughly)
772 {
773 clear_face_cache (!NILP (thoroughly));
774 face_change = true;
775 windows_or_buffers_changed = 53;
776 return Qnil;
777 }
778
779
780
781
782
783
784 #ifdef HAVE_WINDOW_SYSTEM
785
786 DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
787 doc:
788
789
790
791
792 )
793 (Lisp_Object object)
794 {
795 bool pixmap_p = false;
796
797 if (STRINGP (object))
798
799 pixmap_p = true;
800 else if (CONSP (object))
801 {
802
803
804
805 Lisp_Object width, height, data;
806
807 height = width = data = Qnil;
808
809 if (CONSP (object))
810 {
811 width = XCAR (object);
812 object = XCDR (object);
813 if (CONSP (object))
814 {
815 height = XCAR (object);
816 object = XCDR (object);
817 if (CONSP (object))
818 data = XCAR (object);
819 }
820 }
821
822 if (STRINGP (data)
823 && RANGED_FIXNUMP (1, width, INT_MAX)
824 && RANGED_FIXNUMP (1, height, INT_MAX))
825 {
826 int bytes_per_row = (XFIXNUM (width) + CHAR_BIT - 1) / CHAR_BIT;
827 if (XFIXNUM (height) <= SBYTES (data) / bytes_per_row)
828 pixmap_p = true;
829 }
830 }
831
832 return pixmap_p ? Qt : Qnil;
833 }
834
835
836
837
838
839
840
841
842 static ptrdiff_t
843 load_pixmap (struct frame *f, Lisp_Object name)
844 {
845 ptrdiff_t bitmap_id;
846
847 if (NILP (name))
848 return 0;
849
850 CHECK_TYPE (!NILP (Fbitmap_spec_p (name)), Qbitmap_spec_p, name);
851
852 block_input ();
853 if (CONSP (name))
854 {
855
856
857 int h, w;
858 Lisp_Object bits;
859
860 w = XFIXNUM (Fcar (name));
861 h = XFIXNUM (Fcar (Fcdr (name)));
862 bits = Fcar (Fcdr (Fcdr (name)));
863
864 bitmap_id = image_create_bitmap_from_data (f, SSDATA (bits),
865 w, h);
866 }
867 else
868 {
869
870 bitmap_id = image_create_bitmap_from_file (f, name);
871 }
872 unblock_input ();
873
874 if (bitmap_id < 0)
875 {
876 add_to_log ("Invalid or undefined bitmap `%s'", name);
877 bitmap_id = 0;
878 }
879 else
880 {
881 #ifdef GLYPH_DEBUG
882 ++npixmaps_allocated;
883 #endif
884 }
885
886 return bitmap_id;
887 }
888
889 #endif
890
891
892
893
894
895
896
897
898
899
900
901 static bool
902 parse_hex_color_comp (const char *s, const char *e, unsigned short *dst)
903 {
904 int n = e - s;
905 if (n <= 0 || n > 4)
906 return false;
907 int val = 0;
908 for (; s < e; s++)
909 {
910 int digit;
911 if (*s >= '0' && *s <= '9')
912 digit = *s - '0';
913 else if (*s >= 'A' && *s <= 'F')
914 digit = *s - 'A' + 10;
915 else if (*s >= 'a' && *s <= 'f')
916 digit = *s - 'a' + 10;
917 else
918 return false;
919 val = (val << 4) | digit;
920 }
921 int maxval = (1 << (n * 4)) - 1;
922 *dst = (unsigned)val * 65535 / maxval;
923 return true;
924 }
925
926
927
928
929 static double
930 parse_float_color_comp (const char *s, const char *e)
931 {
932
933 for (const char *p = s; p < e; p++)
934 if (!((*p >= '0' && *p <= '9')
935 || *p == '.' || *p == '+' || *p == '-' || *p == 'e' || *p == 'E'))
936 return -1;
937 char *end;
938 double x = strtod (s, &end);
939 return (end == e && x >= 0 && x <= 1) ? x : -1;
940 }
941
942
943
944
945
946
947
948
949
950
951
952
953
954 bool
955 parse_color_spec (const char *spec,
956 unsigned short *r, unsigned short *g, unsigned short *b)
957 {
958 int len = strlen (spec);
959 if (spec[0] == '#')
960 {
961 if ((len - 1) % 3 == 0)
962 {
963 int n = (len - 1) / 3;
964 return ( parse_hex_color_comp (spec + 1 + 0 * n,
965 spec + 1 + 1 * n, r)
966 && parse_hex_color_comp (spec + 1 + 1 * n,
967 spec + 1 + 2 * n, g)
968 && parse_hex_color_comp (spec + 1 + 2 * n,
969 spec + 1 + 3 * n, b));
970 }
971 }
972 else if (strncmp (spec, "rgb:", 4) == 0)
973 {
974 char *sep1, *sep2;
975 return ((sep1 = strchr (spec + 4, '/')) != NULL
976 && (sep2 = strchr (sep1 + 1, '/')) != NULL
977 && parse_hex_color_comp (spec + 4, sep1, r)
978 && parse_hex_color_comp (sep1 + 1, sep2, g)
979 && parse_hex_color_comp (sep2 + 1, spec + len, b));
980 }
981 else if (strncmp (spec, "rgbi:", 5) == 0)
982 {
983 char *sep1, *sep2;
984 double red, green, blue;
985 if ((sep1 = strchr (spec + 5, '/')) != NULL
986 && (sep2 = strchr (sep1 + 1, '/')) != NULL
987 && (red = parse_float_color_comp (spec + 5, sep1)) >= 0
988 && (green = parse_float_color_comp (sep1 + 1, sep2)) >= 0
989 && (blue = parse_float_color_comp (sep2 + 1, spec + len)) >= 0)
990 {
991 *r = lrint (red * 65535);
992 *g = lrint (green * 65535);
993 *b = lrint (blue * 65535);
994 return true;
995 }
996 }
997 return false;
998 }
999
1000 DEFUN ("color-values-from-color-spec",
1001 Fcolor_values_from_color_spec,
1002 Scolor_values_from_color_spec,
1003 1, 1, 0,
1004 doc:
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014 )
1015 (Lisp_Object spec)
1016 {
1017 CHECK_STRING (spec);
1018 unsigned short r, g, b;
1019 return (parse_color_spec (SSDATA (spec), &r, &g, &b)
1020 ? list3i (r, g, b)
1021 : Qnil);
1022 }
1023
1024
1025
1026
1027
1028 static bool
1029 parse_rgb_list (Lisp_Object rgb_list, Emacs_Color *color)
1030 {
1031 #define PARSE_RGB_LIST_FIELD(field) \
1032 if (CONSP (rgb_list) && FIXNUMP (XCAR (rgb_list))) \
1033 { \
1034 color->field = XFIXNUM (XCAR (rgb_list)); \
1035 rgb_list = XCDR (rgb_list); \
1036 } \
1037 else \
1038 return false;
1039
1040 PARSE_RGB_LIST_FIELD (red);
1041 PARSE_RGB_LIST_FIELD (green);
1042 PARSE_RGB_LIST_FIELD (blue);
1043
1044 return true;
1045 }
1046
1047
1048
1049
1050
1051
1052
1053 static bool
1054 tty_lookup_color (struct frame *f, Lisp_Object color, Emacs_Color *tty_color,
1055 Emacs_Color *std_color)
1056 {
1057 Lisp_Object frame, color_desc;
1058
1059 if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc)))
1060 return false;
1061
1062 XSETFRAME (frame, f);
1063
1064 color_desc = call2 (Qtty_color_desc, color, frame);
1065 if (CONSP (color_desc) && CONSP (XCDR (color_desc)))
1066 {
1067 Lisp_Object rgb;
1068
1069 if (! FIXNUMP (XCAR (XCDR (color_desc))))
1070 return false;
1071
1072 tty_color->pixel = XFIXNUM (XCAR (XCDR (color_desc)));
1073
1074 rgb = XCDR (XCDR (color_desc));
1075 if (! parse_rgb_list (rgb, tty_color))
1076 return false;
1077
1078
1079 if (std_color)
1080 {
1081
1082 *std_color = *tty_color;
1083
1084
1085
1086
1087
1088 if ((!STRINGP (XCAR (color_desc))
1089 || NILP (Fstring_equal (color, XCAR (color_desc))))
1090 && !NILP (Ffboundp (Qtty_color_standard_values)))
1091 {
1092
1093 rgb = call1 (Qtty_color_standard_values, color);
1094 if (! parse_rgb_list (rgb, std_color))
1095 return false;
1096 }
1097 }
1098
1099 return true;
1100 }
1101 else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
1102
1103
1104
1105
1106 return true;
1107 else
1108
1109 return false;
1110 }
1111
1112
1113
1114 bool
1115 tty_defined_color (struct frame *f, const char *color_name,
1116 Emacs_Color *color_def, bool alloc, bool _makeIndex)
1117 {
1118 bool status = true;
1119
1120
1121 color_def->pixel = FACE_TTY_DEFAULT_COLOR;
1122 color_def->red = 0;
1123 color_def->blue = 0;
1124 color_def->green = 0;
1125
1126 if (*color_name)
1127 status = tty_lookup_color (f, build_string (color_name), color_def, NULL);
1128
1129 if (color_def->pixel == FACE_TTY_DEFAULT_COLOR && *color_name)
1130 {
1131 if (strcmp (color_name, "unspecified-fg") == 0)
1132 color_def->pixel = FACE_TTY_DEFAULT_FG_COLOR;
1133 else if (strcmp (color_name, "unspecified-bg") == 0)
1134 color_def->pixel = FACE_TTY_DEFAULT_BG_COLOR;
1135 }
1136
1137 if (color_def->pixel != FACE_TTY_DEFAULT_COLOR)
1138 status = true;
1139
1140 return status;
1141 }
1142
1143
1144
1145
1146 Lisp_Object
1147 tty_color_name (struct frame *f, int idx)
1148 {
1149 if (idx >= 0 && !NILP (Ffboundp (Qtty_color_by_index)))
1150 {
1151 Lisp_Object frame;
1152 Lisp_Object coldesc;
1153
1154 XSETFRAME (frame, f);
1155 coldesc = call2 (Qtty_color_by_index, make_fixnum (idx), frame);
1156
1157 if (!NILP (coldesc))
1158 return XCAR (coldesc);
1159 }
1160 #ifdef MSDOS
1161
1162
1163 if (FRAME_MSDOS_P (f) && !inhibit_window_system)
1164 return msdos_stdcolor_name (idx);
1165 #endif
1166
1167 if (idx == FACE_TTY_DEFAULT_FG_COLOR)
1168 return build_string (unspecified_fg);
1169 if (idx == FACE_TTY_DEFAULT_BG_COLOR)
1170 return build_string (unspecified_bg);
1171
1172 return Qunspecified;
1173 }
1174
1175
1176
1177
1178
1179
1180
1181 static bool
1182 face_color_gray_p (struct frame *f, const char *color_name)
1183 {
1184 Emacs_Color color;
1185 bool gray_p;
1186
1187 if (FRAME_TERMINAL (f)->defined_color_hook
1188 (f, color_name, &color, false, true))
1189 gray_p = (
1190 (color.red < 5000 && color.green < 5000 && color.blue < 5000)
1191 ||
1192 ((eabs (color.red - color.green)
1193 < max (color.red, color.green) / 20)
1194 && (eabs (color.green - color.blue)
1195 < max (color.green, color.blue) / 20)
1196 && (eabs (color.blue - color.red)
1197 < max (color.blue, color.red) / 20)));
1198 else
1199 gray_p = false;
1200
1201 return gray_p;
1202 }
1203
1204
1205
1206
1207
1208 static bool
1209 face_color_supported_p (struct frame *f, const char *color_name,
1210 bool background_p)
1211 {
1212 Lisp_Object frame;
1213 Emacs_Color not_used;
1214
1215 XSETFRAME (frame, f);
1216 return
1217 #ifdef HAVE_WINDOW_SYSTEM
1218 FRAME_WINDOW_P (f)
1219 ? (!NILP (Fxw_display_color_p (frame))
1220 || xstrcasecmp (color_name, "black") == 0
1221 || xstrcasecmp (color_name, "white") == 0
1222 || (background_p
1223 && face_color_gray_p (f, color_name))
1224 || (!NILP (Fx_display_grayscale_p (frame))
1225 && face_color_gray_p (f, color_name)))
1226 :
1227 #endif
1228 tty_defined_color (f, color_name, ¬_used, false, false);
1229 }
1230
1231
1232 DEFUN ("color-gray-p", Fcolor_gray_p, Scolor_gray_p, 1, 2, 0,
1233 doc:
1234
1235 )
1236 (Lisp_Object color, Lisp_Object frame)
1237 {
1238 CHECK_STRING (color);
1239 return (face_color_gray_p (decode_any_frame (frame), SSDATA (color))
1240 ? Qt : Qnil);
1241 }
1242
1243
1244 DEFUN ("color-supported-p", Fcolor_supported_p,
1245 Scolor_supported_p, 1, 3, 0,
1246 doc:
1247
1248
1249
1250 )
1251 (Lisp_Object color, Lisp_Object frame, Lisp_Object background_p)
1252 {
1253 CHECK_STRING (color);
1254 return (face_color_supported_p (decode_any_frame (frame),
1255 SSDATA (color), !NILP (background_p))
1256 ? Qt : Qnil);
1257 }
1258
1259
1260 static unsigned long
1261 load_color2 (struct frame *f, struct face *face, Lisp_Object name,
1262 enum lface_attribute_index target_index, Emacs_Color *color)
1263 {
1264 eassert (STRINGP (name));
1265 eassert (target_index == LFACE_FOREGROUND_INDEX
1266 || target_index == LFACE_BACKGROUND_INDEX
1267 || target_index == LFACE_UNDERLINE_INDEX
1268 || target_index == LFACE_OVERLINE_INDEX
1269 || target_index == LFACE_STRIKE_THROUGH_INDEX
1270 || target_index == LFACE_BOX_INDEX);
1271
1272
1273
1274 if (!FRAME_TERMINAL (f)->defined_color_hook
1275 (f, SSDATA (name), color, true, true))
1276 {
1277 add_to_log ("Unable to load color \"%s\"", name);
1278
1279 switch (target_index)
1280 {
1281 case LFACE_FOREGROUND_INDEX:
1282 face->foreground_defaulted_p = true;
1283 color->pixel = FRAME_FOREGROUND_PIXEL (f);
1284 break;
1285
1286 case LFACE_BACKGROUND_INDEX:
1287 face->background_defaulted_p = true;
1288 color->pixel = FRAME_BACKGROUND_PIXEL (f);
1289 break;
1290
1291 case LFACE_UNDERLINE_INDEX:
1292 face->underline_defaulted_p = true;
1293 color->pixel = FRAME_FOREGROUND_PIXEL (f);
1294 break;
1295
1296 case LFACE_OVERLINE_INDEX:
1297 face->overline_color_defaulted_p = true;
1298 color->pixel = FRAME_FOREGROUND_PIXEL (f);
1299 break;
1300
1301 case LFACE_STRIKE_THROUGH_INDEX:
1302 face->strike_through_color_defaulted_p = true;
1303 color->pixel = FRAME_FOREGROUND_PIXEL (f);
1304 break;
1305
1306 case LFACE_BOX_INDEX:
1307 face->box_color_defaulted_p = true;
1308 color->pixel = FRAME_FOREGROUND_PIXEL (f);
1309 break;
1310
1311 default:
1312 emacs_abort ();
1313 }
1314 }
1315 #ifdef GLYPH_DEBUG
1316 else
1317 ++ncolors_allocated;
1318 #endif
1319
1320 return color->pixel;
1321 }
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332 unsigned long
1333 load_color (struct frame *f, struct face *face, Lisp_Object name,
1334 enum lface_attribute_index target_index)
1335 {
1336 Emacs_Color color;
1337 return load_color2 (f, face, name, target_index, &color);
1338 }
1339
1340
1341 #ifdef HAVE_WINDOW_SYSTEM
1342
1343
1344
1345
1346
1347
1348 static void
1349 load_face_colors (struct frame *f, struct face *face,
1350 Lisp_Object attrs[LFACE_VECTOR_SIZE])
1351 {
1352 Lisp_Object fg, bg, dfg;
1353 Emacs_Color xfg, xbg;
1354
1355 bg = attrs[LFACE_BACKGROUND_INDEX];
1356 fg = attrs[LFACE_FOREGROUND_INDEX];
1357
1358
1359 if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
1360 {
1361 Lisp_Object tmp;
1362 tmp = fg;
1363 fg = bg;
1364 bg = tmp;
1365 }
1366
1367
1368
1369
1370
1371 if (!face_color_supported_p (f, SSDATA (bg), false)
1372 && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
1373 {
1374 image_destroy_bitmap (f, face->stipple);
1375 face->stipple = load_pixmap (f, Vface_default_stipple);
1376 }
1377
1378 face->background = load_color2 (f, face, bg, LFACE_BACKGROUND_INDEX, &xbg);
1379 face->foreground = load_color2 (f, face, fg, LFACE_FOREGROUND_INDEX, &xfg);
1380
1381 dfg = attrs[LFACE_DISTANT_FOREGROUND_INDEX];
1382 if (!NILP (dfg) && !UNSPECIFIEDP (dfg)
1383 && color_distance (&xbg, &xfg) < face_near_same_color_threshold)
1384 {
1385 if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
1386 face->background = load_color (f, face, dfg, LFACE_BACKGROUND_INDEX);
1387 else
1388 face->foreground = load_color (f, face, dfg, LFACE_FOREGROUND_INDEX);
1389 }
1390 }
1391
1392 #ifdef HAVE_X_WINDOWS
1393
1394
1395
1396 void
1397 unload_color (struct frame *f, unsigned long pixel)
1398 {
1399 if (pixel != -1)
1400 {
1401 block_input ();
1402 x_free_colors (f, &pixel, 1);
1403 unblock_input ();
1404 }
1405 }
1406
1407
1408
1409 static void
1410 free_face_colors (struct frame *f, struct face *face)
1411 {
1412
1413
1414 if (face->colors_copied_bitwise_p)
1415 return;
1416
1417 block_input ();
1418
1419 if (!face->foreground_defaulted_p)
1420 {
1421 x_free_colors (f, &face->foreground, 1);
1422 IF_DEBUG (--ncolors_allocated);
1423 }
1424
1425 if (!face->background_defaulted_p)
1426 {
1427 x_free_colors (f, &face->background, 1);
1428 IF_DEBUG (--ncolors_allocated);
1429 }
1430
1431 if (face->underline
1432 && !face->underline_defaulted_p)
1433 {
1434 x_free_colors (f, &face->underline_color, 1);
1435 IF_DEBUG (--ncolors_allocated);
1436 }
1437
1438 if (face->overline_p
1439 && !face->overline_color_defaulted_p)
1440 {
1441 x_free_colors (f, &face->overline_color, 1);
1442 IF_DEBUG (--ncolors_allocated);
1443 }
1444
1445 if (face->strike_through_p
1446 && !face->strike_through_color_defaulted_p)
1447 {
1448 x_free_colors (f, &face->strike_through_color, 1);
1449 IF_DEBUG (--ncolors_allocated);
1450 }
1451
1452 if (face->box != FACE_NO_BOX
1453 && !face->box_color_defaulted_p)
1454 {
1455 x_free_colors (f, &face->box_color, 1);
1456 IF_DEBUG (--ncolors_allocated);
1457 }
1458
1459 unblock_input ();
1460 }
1461
1462 #endif
1463
1464 #endif
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474 enum xlfd_field
1475 {
1476 XLFD_FOUNDRY,
1477 XLFD_FAMILY,
1478 XLFD_WEIGHT,
1479 XLFD_SLANT,
1480 XLFD_SWIDTH,
1481 XLFD_ADSTYLE,
1482 XLFD_PIXEL_SIZE,
1483 XLFD_POINT_SIZE,
1484 XLFD_RESX,
1485 XLFD_RESY,
1486 XLFD_SPACING,
1487 XLFD_AVGWIDTH,
1488 XLFD_REGISTRY,
1489 XLFD_ENCODING,
1490 XLFD_LAST
1491 };
1492
1493
1494
1495
1496
1497
1498 static int font_sort_order[4];
1499
1500 #ifdef HAVE_WINDOW_SYSTEM
1501
1502 static enum font_property_index font_props_for_sorting[FONT_SIZE_INDEX];
1503
1504 static int
1505 compare_fonts_by_sort_order (const void *v1, const void *v2)
1506 {
1507 Lisp_Object const *p1 = v1;
1508 Lisp_Object const *p2 = v2;
1509 Lisp_Object font1 = *p1;
1510 Lisp_Object font2 = *p2;
1511 int i;
1512
1513 for (i = 0; i < FONT_SIZE_INDEX; i++)
1514 {
1515 enum font_property_index idx = font_props_for_sorting[i];
1516 Lisp_Object val1 = AREF (font1, idx), val2 = AREF (font2, idx);
1517 int result;
1518
1519 if (idx <= FONT_REGISTRY_INDEX)
1520 {
1521 if (STRINGP (val1))
1522 result = STRINGP (val2) ? strcmp (SSDATA (val1), SSDATA (val2)) : -1;
1523 else
1524 result = STRINGP (val2) ? 1 : 0;
1525 }
1526 else
1527 {
1528 if (FIXNUMP (val1))
1529 result = (FIXNUMP (val2) && XFIXNUM (val1) >= XFIXNUM (val2)
1530 ? XFIXNUM (val1) > XFIXNUM (val2)
1531 : -1);
1532 else
1533 result = FIXNUMP (val2) ? 1 : 0;
1534 }
1535 if (result)
1536 return result;
1537 }
1538 return 0;
1539 }
1540
1541 DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
1542 doc:
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562 )
1563 (Lisp_Object family, Lisp_Object frame)
1564 {
1565 Lisp_Object font_spec, list, *drivers, vec;
1566 struct frame *f = decode_live_frame (frame);
1567 ptrdiff_t i, nfonts;
1568 Lisp_Object result;
1569 USE_SAFE_ALLOCA;
1570
1571 font_spec = Ffont_spec (0, NULL);
1572 if (!NILP (family))
1573 {
1574 CHECK_STRING (family);
1575 font_parse_family_registry (family, Qnil, font_spec);
1576 }
1577
1578 list = font_list_entities (f, font_spec);
1579 if (NILP (list))
1580 return Qnil;
1581
1582
1583 for (i = 0; i < 4; i++)
1584 switch (font_sort_order[i])
1585 {
1586 case XLFD_SWIDTH:
1587 font_props_for_sorting[i] = FONT_WIDTH_INDEX; break;
1588 case XLFD_POINT_SIZE:
1589 font_props_for_sorting[i] = FONT_SIZE_INDEX; break;
1590 case XLFD_WEIGHT:
1591 font_props_for_sorting[i] = FONT_WEIGHT_INDEX; break;
1592 default:
1593 font_props_for_sorting[i] = FONT_SLANT_INDEX; break;
1594 }
1595 font_props_for_sorting[i++] = FONT_FAMILY_INDEX;
1596 font_props_for_sorting[i++] = FONT_FOUNDRY_INDEX;
1597 font_props_for_sorting[i++] = FONT_ADSTYLE_INDEX;
1598 font_props_for_sorting[i++] = FONT_REGISTRY_INDEX;
1599
1600 ptrdiff_t ndrivers = list_length (list);
1601 SAFE_ALLOCA_LISP (drivers, ndrivers);
1602 for (i = 0; i < ndrivers; i++, list = XCDR (list))
1603 drivers[i] = XCAR (list);
1604 vec = Fvconcat (ndrivers, drivers);
1605 nfonts = ASIZE (vec);
1606
1607 qsort (XVECTOR (vec)->contents, nfonts, word_size,
1608 compare_fonts_by_sort_order);
1609
1610 result = Qnil;
1611 for (i = nfonts - 1; i >= 0; --i)
1612 {
1613 Lisp_Object font = AREF (vec, i);
1614 int point = PIXEL_TO_POINT (XFIXNUM (AREF (font, FONT_SIZE_INDEX)) * 10,
1615 FRAME_RES (f));
1616 Lisp_Object spacing = Ffont_get (font, QCspacing);
1617 Lisp_Object v = CALLN (Fvector,
1618 AREF (font, FONT_FAMILY_INDEX),
1619 FONT_WIDTH_SYMBOLIC (font),
1620 make_fixnum (point),
1621 FONT_WEIGHT_SYMBOLIC (font),
1622 FONT_SLANT_SYMBOLIC (font),
1623 (NILP (spacing)
1624 || EQ (spacing, Qp)
1625
1626
1627
1628 || BASE_EQ (spacing,
1629 make_fixnum
1630 (FONT_SPACING_PROPORTIONAL)))
1631 ? Qnil : Qt,
1632 Ffont_xlfd_name (font, Qnil),
1633 AREF (font, FONT_REGISTRY_INDEX));
1634 result = Fcons (v, result);
1635 }
1636
1637 SAFE_FREE ();
1638 return result;
1639 }
1640
1641 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
1642 doc:
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662 )
1663 (Lisp_Object pattern, Lisp_Object face, Lisp_Object frame,
1664 Lisp_Object maximum, Lisp_Object width)
1665 {
1666 struct frame *f;
1667 int size, avgwidth;
1668
1669 check_window_system (NULL);
1670 CHECK_STRING (pattern);
1671
1672 if (! NILP (maximum))
1673 CHECK_FIXNAT (maximum);
1674
1675 if (!NILP (width))
1676 CHECK_FIXNUM (width);
1677
1678
1679
1680 f = decode_live_frame (frame);
1681 if (! FRAME_WINDOW_P (f))
1682 {
1683
1684 f = NULL;
1685 frame = Qnil;
1686 face = Qnil;
1687 }
1688 else
1689 XSETFRAME (frame, f);
1690
1691
1692
1693 if (NILP (face))
1694 size = 0;
1695 else
1696 {
1697
1698
1699 int face_id = lookup_named_face (NULL, f, face, false);
1700 struct face *width_face = FACE_FROM_ID_OR_NULL (f, face_id);
1701
1702 if (width_face && width_face->font)
1703 {
1704 size = width_face->font->pixel_size;
1705 avgwidth = width_face->font->average_width;
1706 }
1707 else
1708 {
1709 size = FRAME_FONT (f)->pixel_size;
1710 avgwidth = FRAME_FONT (f)->average_width;
1711 }
1712 if (!NILP (width))
1713 avgwidth *= XFIXNUM (width);
1714 }
1715
1716 Lisp_Object font_spec = font_spec_from_name (pattern);
1717 if (!FONTP (font_spec))
1718 signal_error ("Invalid font name", pattern);
1719
1720 if (size)
1721 {
1722 Ffont_put (font_spec, QCsize, make_fixnum (size));
1723 Ffont_put (font_spec, QCavgwidth, make_fixnum (avgwidth));
1724 }
1725 Lisp_Object fonts = Flist_fonts (font_spec, frame, maximum, font_spec);
1726 for (Lisp_Object tail = fonts; CONSP (tail); tail = XCDR (tail))
1727 {
1728 Lisp_Object font_entity;
1729
1730 font_entity = XCAR (tail);
1731 if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
1732 || XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
1733 && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
1734 {
1735
1736
1737 font_entity = copy_font_spec (font_entity);
1738 ASET (font_entity, FONT_SIZE_INDEX,
1739 AREF (font_spec, FONT_SIZE_INDEX));
1740 }
1741 XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
1742 }
1743 if (NILP (frame))
1744
1745 return fonts;
1746 Lisp_Object fontsets = list_fontsets (f, pattern, size);
1747 return nconc2 (fonts, fontsets);
1748 }
1749
1750 #endif
1751
1752
1753
1754
1755
1756
1757
1758
1759 #define LFACE_FAMILY(LFACE) AREF ((LFACE), LFACE_FAMILY_INDEX)
1760 #define LFACE_FOUNDRY(LFACE) AREF ((LFACE), LFACE_FOUNDRY_INDEX)
1761 #define LFACE_HEIGHT(LFACE) AREF ((LFACE), LFACE_HEIGHT_INDEX)
1762 #define LFACE_WEIGHT(LFACE) AREF ((LFACE), LFACE_WEIGHT_INDEX)
1763 #define LFACE_SLANT(LFACE) AREF ((LFACE), LFACE_SLANT_INDEX)
1764 #define LFACE_UNDERLINE(LFACE) AREF ((LFACE), LFACE_UNDERLINE_INDEX)
1765 #define LFACE_INVERSE(LFACE) AREF ((LFACE), LFACE_INVERSE_INDEX)
1766 #define LFACE_FOREGROUND(LFACE) AREF ((LFACE), LFACE_FOREGROUND_INDEX)
1767 #define LFACE_BACKGROUND(LFACE) AREF ((LFACE), LFACE_BACKGROUND_INDEX)
1768 #define LFACE_STIPPLE(LFACE) AREF ((LFACE), LFACE_STIPPLE_INDEX)
1769 #define LFACE_SWIDTH(LFACE) AREF ((LFACE), LFACE_SWIDTH_INDEX)
1770 #define LFACE_OVERLINE(LFACE) AREF ((LFACE), LFACE_OVERLINE_INDEX)
1771 #define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
1772 #define LFACE_BOX(LFACE) AREF ((LFACE), LFACE_BOX_INDEX)
1773 #define LFACE_FONT(LFACE) AREF ((LFACE), LFACE_FONT_INDEX)
1774 #define LFACE_INHERIT(LFACE) AREF ((LFACE), LFACE_INHERIT_INDEX)
1775 #define LFACE_FONTSET(LFACE) AREF ((LFACE), LFACE_FONTSET_INDEX)
1776 #define LFACE_EXTEND(LFACE) AREF ((LFACE), LFACE_EXTEND_INDEX)
1777 #define LFACE_DISTANT_FOREGROUND(LFACE) \
1778 AREF ((LFACE), LFACE_DISTANT_FOREGROUND_INDEX)
1779
1780
1781
1782
1783 #define LFACEP(LFACE) \
1784 (VECTORP (LFACE) \
1785 && ASIZE (LFACE) == LFACE_VECTOR_SIZE \
1786 && EQ (AREF (LFACE, 0), Qface))
1787
1788
1789
1790 static Lisp_Object face_attr_sym[LFACE_VECTOR_SIZE];
1791
1792 #ifdef GLYPH_DEBUG
1793
1794
1795
1796 static void
1797 check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE])
1798 {
1799 eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
1800 || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
1801 || RESET_P (attrs[LFACE_FAMILY_INDEX])
1802 || STRINGP (attrs[LFACE_FAMILY_INDEX]));
1803 eassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
1804 || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX])
1805 || RESET_P (attrs[LFACE_FOUNDRY_INDEX])
1806 || STRINGP (attrs[LFACE_FOUNDRY_INDEX]));
1807 eassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
1808 || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
1809 || RESET_P (attrs[LFACE_SWIDTH_INDEX])
1810 || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
1811 eassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
1812 || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
1813 || RESET_P (attrs[LFACE_HEIGHT_INDEX])
1814 || NUMBERP (attrs[LFACE_HEIGHT_INDEX])
1815 || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
1816 eassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
1817 || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX])
1818 || RESET_P (attrs[LFACE_WEIGHT_INDEX])
1819 || SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
1820 eassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
1821 || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX])
1822 || RESET_P (attrs[LFACE_SLANT_INDEX])
1823 || SYMBOLP (attrs[LFACE_SLANT_INDEX]));
1824 eassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
1825 || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
1826 || RESET_P (attrs[LFACE_UNDERLINE_INDEX])
1827 || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
1828 || STRINGP (attrs[LFACE_UNDERLINE_INDEX])
1829 || CONSP (attrs[LFACE_UNDERLINE_INDEX]));
1830 eassert (UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX])
1831 || IGNORE_DEFFACE_P (attrs[LFACE_EXTEND_INDEX])
1832 || RESET_P (attrs[LFACE_EXTEND_INDEX])
1833 || SYMBOLP (attrs[LFACE_EXTEND_INDEX])
1834 || STRINGP (attrs[LFACE_EXTEND_INDEX]));
1835 eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
1836 || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
1837 || RESET_P (attrs[LFACE_OVERLINE_INDEX])
1838 || SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
1839 || STRINGP (attrs[LFACE_OVERLINE_INDEX]));
1840 eassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
1841 || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
1842 || RESET_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
1843 || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX])
1844 || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX]));
1845 eassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
1846 || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX])
1847 || RESET_P (attrs[LFACE_BOX_INDEX])
1848 || SYMBOLP (attrs[LFACE_BOX_INDEX])
1849 || STRINGP (attrs[LFACE_BOX_INDEX])
1850 || FIXNUMP (attrs[LFACE_BOX_INDEX])
1851 || CONSP (attrs[LFACE_BOX_INDEX]));
1852 eassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
1853 || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX])
1854 || RESET_P (attrs[LFACE_INVERSE_INDEX])
1855 || SYMBOLP (attrs[LFACE_INVERSE_INDEX]));
1856 eassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
1857 || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX])
1858 || RESET_P (attrs[LFACE_FOREGROUND_INDEX])
1859 || STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
1860 eassert (UNSPECIFIEDP (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
1861 || IGNORE_DEFFACE_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
1862 || RESET_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
1863 || STRINGP (attrs[LFACE_DISTANT_FOREGROUND_INDEX]));
1864 eassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
1865 || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX])
1866 || RESET_P (attrs[LFACE_BACKGROUND_INDEX])
1867 || STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
1868 eassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
1869 || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX])
1870 || NILP (attrs[LFACE_INHERIT_INDEX])
1871 || SYMBOLP (attrs[LFACE_INHERIT_INDEX])
1872 || CONSP (attrs[LFACE_INHERIT_INDEX]));
1873 #ifdef HAVE_WINDOW_SYSTEM
1874 eassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
1875 || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX])
1876 || RESET_P (attrs[LFACE_STIPPLE_INDEX])
1877 || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
1878 || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
1879 eassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
1880 || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
1881 || RESET_P (attrs[LFACE_FONT_INDEX])
1882 || FONTP (attrs[LFACE_FONT_INDEX]));
1883 eassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
1884 || STRINGP (attrs[LFACE_FONTSET_INDEX])
1885 || RESET_P (attrs[LFACE_FONTSET_INDEX])
1886 || NILP (attrs[LFACE_FONTSET_INDEX]));
1887 #endif
1888 }
1889
1890
1891
1892
1893 static void
1894 check_lface (Lisp_Object lface)
1895 {
1896 if (!NILP (lface))
1897 {
1898 eassert (LFACEP (lface));
1899 check_lface_attrs (XVECTOR (lface)->contents);
1900 }
1901 }
1902
1903 #else
1904
1905 #define check_lface_attrs(attrs) (void) 0
1906 #define check_lface(lface) (void) 0
1907
1908 #endif
1909
1910
1911
1912
1913
1914 enum named_merge_point_kind
1915 {
1916 NAMED_MERGE_POINT_NORMAL,
1917 NAMED_MERGE_POINT_REMAP
1918 };
1919
1920
1921
1922
1923
1924
1925
1926 struct named_merge_point
1927 {
1928 Lisp_Object face_name;
1929 enum named_merge_point_kind named_merge_point_kind;
1930 struct named_merge_point *prev;
1931 };
1932
1933
1934
1935
1936
1937
1938
1939 static bool
1940 push_named_merge_point (struct named_merge_point *new_named_merge_point,
1941 Lisp_Object face_name,
1942 enum named_merge_point_kind named_merge_point_kind,
1943 struct named_merge_point **named_merge_points)
1944 {
1945 struct named_merge_point *prev;
1946
1947 for (prev = *named_merge_points; prev; prev = prev->prev)
1948 if (EQ (face_name, prev->face_name))
1949 {
1950 if (prev->named_merge_point_kind == named_merge_point_kind)
1951
1952 return false;
1953 else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
1954
1955
1956
1957
1958 break;
1959 }
1960
1961 new_named_merge_point->face_name = face_name;
1962 new_named_merge_point->named_merge_point_kind = named_merge_point_kind;
1963 new_named_merge_point->prev = *named_merge_points;
1964
1965 *named_merge_points = new_named_merge_point;
1966
1967 return true;
1968 }
1969
1970
1971
1972
1973
1974
1975
1976
1977 static Lisp_Object
1978 resolve_face_name (Lisp_Object face_name, bool signal_p)
1979 {
1980 Lisp_Object orig_face;
1981 Lisp_Object tortoise, hare;
1982
1983 if (STRINGP (face_name))
1984 face_name = Fintern (face_name, Qnil);
1985
1986 if (NILP (face_name) || !SYMBOLP (face_name))
1987 return face_name;
1988
1989 orig_face = face_name;
1990 tortoise = hare = face_name;
1991
1992 while (true)
1993 {
1994 face_name = hare;
1995 hare = Fget (hare, Qface_alias);
1996 if (NILP (hare) || !SYMBOLP (hare))
1997 break;
1998
1999 face_name = hare;
2000 hare = Fget (hare, Qface_alias);
2001 if (NILP (hare) || !SYMBOLP (hare))
2002 break;
2003
2004 tortoise = Fget (tortoise, Qface_alias);
2005 if (BASE_EQ (hare, tortoise))
2006 {
2007 if (signal_p)
2008 circular_list (orig_face);
2009 return Qdefault;
2010 }
2011 }
2012
2013 return face_name;
2014 }
2015
2016
2017
2018
2019
2020
2021
2022
2023 static Lisp_Object
2024 lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
2025 bool signal_p)
2026 {
2027 Lisp_Object lface;
2028
2029 if (f)
2030 lface = Fgethash (face_name, f->face_hash_table, Qnil);
2031 else
2032 lface = CDR (Fgethash (face_name, Vface_new_frame_defaults, Qnil));
2033
2034 if (signal_p && NILP (lface))
2035 signal_error ("Invalid face", face_name);
2036
2037 check_lface (lface);
2038
2039 return lface;
2040 }
2041
2042
2043
2044
2045
2046
2047
2048
2049 static Lisp_Object
2050 lface_from_face_name (struct frame *f, Lisp_Object face_name, bool signal_p)
2051 {
2052 face_name = resolve_face_name (face_name, signal_p);
2053 return lface_from_face_name_no_resolve (f, face_name, signal_p);
2054 }
2055
2056
2057
2058
2059
2060
2061
2062
2063 static bool
2064 get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
2065 Lisp_Object attrs[LFACE_VECTOR_SIZE],
2066 bool signal_p)
2067 {
2068 Lisp_Object lface;
2069
2070 lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
2071
2072 if (! NILP (lface))
2073 memcpy (attrs, xvector_contents (lface),
2074 LFACE_VECTOR_SIZE * sizeof *attrs);
2075
2076 return !NILP (lface);
2077 }
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087 static bool
2088 get_lface_attributes (struct window *w,
2089 struct frame *f, Lisp_Object face_name,
2090 Lisp_Object attrs[LFACE_VECTOR_SIZE], bool signal_p,
2091 struct named_merge_point *named_merge_points)
2092 {
2093 Lisp_Object face_remapping;
2094 eassert (w == NULL || WINDOW_XFRAME (w) == f);
2095
2096 face_name = resolve_face_name (face_name, signal_p);
2097
2098
2099
2100 face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
2101 if (CONSP (face_remapping))
2102 {
2103 struct named_merge_point named_merge_point;
2104
2105 if (push_named_merge_point (&named_merge_point,
2106 face_name, NAMED_MERGE_POINT_REMAP,
2107 &named_merge_points))
2108 {
2109 int i;
2110
2111 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2112 attrs[i] = Qunspecified;
2113
2114 return merge_face_ref (w, f, XCDR (face_remapping), attrs,
2115 signal_p, named_merge_points,
2116 0);
2117 }
2118 }
2119
2120
2121 return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
2122 }
2123
2124
2125
2126
2127
2128 static bool
2129 lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE])
2130 {
2131 int i;
2132
2133 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2134 if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
2135 && i != LFACE_DISTANT_FOREGROUND_INDEX)
2136 if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i])))
2137 break;
2138
2139 return i == LFACE_VECTOR_SIZE;
2140 }
2141
2142 #ifdef HAVE_WINDOW_SYSTEM
2143
2144
2145
2146
2147
2148
2149 static void
2150 set_lface_from_font (struct frame *f, Lisp_Object lface,
2151 Lisp_Object font_object, bool force_p)
2152 {
2153 Lisp_Object val;
2154 struct font *font = XFONT_OBJECT (font_object);
2155
2156
2157
2158
2159
2160 if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
2161 {
2162 Lisp_Object family = AREF (font_object, FONT_FAMILY_INDEX);
2163
2164 ASET (lface, LFACE_FAMILY_INDEX, SYMBOL_NAME (family));
2165 }
2166
2167 if (force_p || UNSPECIFIEDP (LFACE_FOUNDRY (lface)))
2168 {
2169 Lisp_Object foundry = AREF (font_object, FONT_FOUNDRY_INDEX);
2170
2171 ASET (lface, LFACE_FOUNDRY_INDEX, SYMBOL_NAME (foundry));
2172 }
2173
2174 if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
2175 {
2176 int pt = PIXEL_TO_POINT (font->pixel_size * 10, FRAME_RES (f));
2177
2178 eassert (pt > 0);
2179 ASET (lface, LFACE_HEIGHT_INDEX, make_fixnum (pt));
2180 }
2181
2182 if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
2183 {
2184 val = FONT_WEIGHT_FOR_FACE (font_object);
2185 ASET (lface, LFACE_WEIGHT_INDEX, ! NILP (val) ? val :Qnormal);
2186 }
2187 if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
2188 {
2189 val = FONT_SLANT_FOR_FACE (font_object);
2190 ASET (lface, LFACE_SLANT_INDEX, ! NILP (val) ? val : Qnormal);
2191 }
2192 if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
2193 {
2194 val = FONT_WIDTH_FOR_FACE (font_object);
2195 ASET (lface, LFACE_SWIDTH_INDEX, ! NILP (val) ? val : Qnormal);
2196 }
2197
2198 ASET (lface, LFACE_FONT_INDEX, font_object);
2199 }
2200
2201 #endif
2202
2203
2204
2205
2206
2207
2208
2209
2210 static Lisp_Object
2211 merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2212 {
2213 Lisp_Object result = invalid;
2214
2215 if (FIXNUMP (from))
2216
2217 result = from;
2218 else if (FLOATP (from))
2219
2220 {
2221 if (FIXNUMP (to))
2222
2223 result = make_fixnum (XFLOAT_DATA (from) * XFIXNUM (to));
2224 else if (FLOATP (to))
2225
2226 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
2227 else if (UNSPECIFIEDP (to))
2228 result = from;
2229 }
2230 else if (FUNCTIONP (from))
2231
2232 {
2233
2234
2235 result = safe_call1 (from, to);
2236
2237
2238 if (FIXNUMP (to) && !FIXNUMP (result))
2239 result = invalid;
2240 }
2241
2242 return result;
2243 }
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255 static void
2256 merge_face_vectors (struct window *w,
2257 struct frame *f, const Lisp_Object *from, Lisp_Object *to,
2258 struct named_merge_point *named_merge_points)
2259 {
2260 int i;
2261 Lisp_Object font = Qnil;
2262
2263
2264
2265
2266
2267
2268 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2269 && !NILP (from[LFACE_INHERIT_INDEX]))
2270 merge_face_ref (w, f, from[LFACE_INHERIT_INDEX],
2271 to, false, named_merge_points,
2272 0);
2273
2274 if (FONT_SPEC_P (from[LFACE_FONT_INDEX]))
2275 {
2276 if (!UNSPECIFIEDP (to[LFACE_FONT_INDEX]))
2277 font = merge_font_spec (from[LFACE_FONT_INDEX], to[LFACE_FONT_INDEX]);
2278 else
2279 font = copy_font_spec (from[LFACE_FONT_INDEX]);
2280 to[LFACE_FONT_INDEX] = font;
2281 }
2282
2283 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2284 if (!UNSPECIFIEDP (from[i]))
2285 {
2286 if (i == LFACE_HEIGHT_INDEX && !FIXNUMP (from[i]))
2287 {
2288 to[i] = merge_face_heights (from[i], to[i], to[i]);
2289 font_clear_prop (to, FONT_SIZE_INDEX);
2290 }
2291 else if (i != LFACE_FONT_INDEX && ! EQ (to[i], from[i]))
2292 {
2293 to[i] = from[i];
2294 if (i >= LFACE_FAMILY_INDEX && i <= LFACE_SLANT_INDEX)
2295 font_clear_prop (to,
2296 (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX
2297 : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX
2298 : i == LFACE_SWIDTH_INDEX ? FONT_WIDTH_INDEX
2299 : i == LFACE_HEIGHT_INDEX ? FONT_SIZE_INDEX
2300 : i == LFACE_WEIGHT_INDEX ? FONT_WEIGHT_INDEX
2301 : FONT_SLANT_INDEX));
2302 }
2303 }
2304
2305
2306
2307
2308
2309 if (!NILP (font))
2310 {
2311 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
2312 to[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX));
2313 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
2314 to[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX));
2315 if (! NILP (AREF (font, FONT_WEIGHT_INDEX)))
2316 to[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (font);
2317 if (! NILP (AREF (font, FONT_SLANT_INDEX)))
2318 to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (font);
2319 if (! NILP (AREF (font, FONT_WIDTH_INDEX)))
2320 to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (font);
2321 ASET (font, FONT_SIZE_INDEX, Qnil);
2322 }
2323
2324
2325
2326 to[LFACE_INHERIT_INDEX] = Qnil;
2327 }
2328
2329
2330
2331
2332
2333 static Lisp_Object
2334 face_inherited_attr (struct window *w, struct frame *f,
2335 Lisp_Object attrs[LFACE_VECTOR_SIZE],
2336 enum lface_attribute_index attr_idx,
2337 struct named_merge_point *named_merge_points)
2338 {
2339 Lisp_Object inherited_attrs[LFACE_VECTOR_SIZE];
2340 Lisp_Object attr_val = attrs[attr_idx];
2341
2342 memcpy (inherited_attrs, attrs, LFACE_VECTOR_SIZE * sizeof (attrs[0]));
2343 while (UNSPECIFIEDP (attr_val)
2344 && !NILP (inherited_attrs[LFACE_INHERIT_INDEX])
2345 && !UNSPECIFIEDP (inherited_attrs[LFACE_INHERIT_INDEX]))
2346 {
2347 Lisp_Object parent_face = inherited_attrs[LFACE_INHERIT_INDEX];
2348 bool ok;
2349
2350 if (CONSP (parent_face))
2351 {
2352 Lisp_Object tail;
2353 ok = false;
2354 for (tail = parent_face; !NILP (tail); tail = XCDR (tail))
2355 {
2356 ok = get_lface_attributes (w, f, XCAR (tail), inherited_attrs,
2357 false, named_merge_points);
2358 if (!ok)
2359 break;
2360 attr_val = face_inherited_attr (w, f, inherited_attrs, attr_idx,
2361 named_merge_points);
2362 if (!UNSPECIFIEDP (attr_val))
2363 break;
2364 }
2365 if (!ok)
2366 break;
2367 }
2368 else
2369 {
2370 ok = get_lface_attributes (w, f, parent_face, inherited_attrs,
2371 false, named_merge_points);
2372 if (!ok)
2373 break;
2374 attr_val = inherited_attrs[attr_idx];
2375 }
2376 }
2377 return attr_val;
2378 }
2379
2380
2381
2382
2383
2384
2385
2386 static bool
2387 merge_named_face (struct window *w,
2388 struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2389 struct named_merge_point *named_merge_points,
2390 enum lface_attribute_index attr_filter)
2391 {
2392 struct named_merge_point named_merge_point;
2393
2394 if (push_named_merge_point (&named_merge_point,
2395 face_name, NAMED_MERGE_POINT_NORMAL,
2396 &named_merge_points))
2397 {
2398 Lisp_Object from[LFACE_VECTOR_SIZE], val;
2399 bool ok = get_lface_attributes (w, f, face_name, from, false,
2400 named_merge_points);
2401 if (ok && !EQ (face_name, Qdefault))
2402 {
2403 struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
2404 int i;
2405 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
2406 if (EQ (from[i], Qreset))
2407 from[i] = deflt->lface[i];
2408 }
2409
2410 if (ok && (attr_filter == 0
2411 || (!NILP (from[attr_filter])
2412 && !UNSPECIFIEDP (from[attr_filter]))
2413
2414 || (!NILP (from[LFACE_INHERIT_INDEX])
2415 && !UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2416 && (val = face_inherited_attr (w, f, from, attr_filter,
2417 named_merge_points),
2418 (!NILP (val) && !UNSPECIFIEDP (val))))))
2419 merge_face_vectors (w, f, from, to, named_merge_points);
2420
2421 return ok;
2422 }
2423 else
2424 return false;
2425 }
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438 static bool
2439 evaluate_face_filter (Lisp_Object filter, struct window *w,
2440 bool *ok, bool err_msgs)
2441 {
2442 Lisp_Object orig_filter = filter;
2443
2444
2445
2446 {
2447 if (NILP (filter))
2448 return true;
2449
2450 if (face_filters_always_match)
2451 return true;
2452
2453 if (!CONSP (filter))
2454 goto err;
2455
2456 if (!EQ (XCAR (filter), QCwindow))
2457 goto err;
2458 filter = XCDR (filter);
2459
2460 Lisp_Object parameter = XCAR (filter);
2461 filter = XCDR (filter);
2462 if (!CONSP (filter))
2463 goto err;
2464
2465 Lisp_Object value = XCAR (filter);
2466 filter = XCDR (filter);
2467 if (!NILP (filter))
2468 goto err;
2469
2470 bool match = false;
2471 if (w)
2472 {
2473 Lisp_Object found = assq_no_quit (parameter, w->window_parameters);
2474 if (!NILP (found) && EQ (XCDR (found), value))
2475 match = true;
2476 }
2477
2478 return match;
2479 }
2480
2481 err:
2482 if (err_msgs)
2483 add_to_log ("Invalid face filter %S", orig_filter);
2484 *ok = false;
2485 return false;
2486 }
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500 static Lisp_Object
2501 filter_face_ref (Lisp_Object face_ref,
2502 struct window *w,
2503 bool *ok,
2504 bool err_msgs)
2505 {
2506 Lisp_Object orig_face_ref = face_ref;
2507 if (!CONSP (face_ref))
2508 return face_ref;
2509
2510
2511
2512 {
2513 if (!EQ (XCAR (face_ref), QCfiltered))
2514 return face_ref;
2515 face_ref = XCDR (face_ref);
2516
2517 if (!CONSP (face_ref))
2518 goto err;
2519 Lisp_Object filter = XCAR (face_ref);
2520 face_ref = XCDR (face_ref);
2521
2522 if (!CONSP (face_ref))
2523 goto err;
2524 Lisp_Object filtered_face_ref = XCAR (face_ref);
2525 face_ref = XCDR (face_ref);
2526
2527 if (!NILP (face_ref))
2528 goto err;
2529
2530 return evaluate_face_filter (filter, w, ok, err_msgs)
2531 ? filtered_face_ref : Qnil;
2532 }
2533
2534 err:
2535 if (err_msgs)
2536 add_to_log ("Invalid face ref %S", orig_face_ref);
2537 *ok = false;
2538 return Qnil;
2539 }
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579 static bool
2580 merge_face_ref (struct window *w,
2581 struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2582 bool err_msgs, struct named_merge_point *named_merge_points,
2583 enum lface_attribute_index attr_filter)
2584 {
2585 bool ok = true;
2586 Lisp_Object filtered_face_ref;
2587 bool attr_filter_passed = false;
2588
2589 filtered_face_ref = face_ref;
2590 do
2591 {
2592 face_ref = filtered_face_ref;
2593 filtered_face_ref = filter_face_ref (face_ref, w, &ok, err_msgs);
2594 }
2595 while (ok && !EQ (face_ref, filtered_face_ref));
2596
2597 if (!ok)
2598 return false;
2599
2600 if (NILP (face_ref))
2601 return true;
2602
2603 if (CONSP (face_ref))
2604 {
2605 Lisp_Object first = XCAR (face_ref);
2606
2607 if (EQ (first, Qforeground_color)
2608 || EQ (first, Qbackground_color))
2609 {
2610
2611
2612 Lisp_Object color_name = XCDR (face_ref);
2613 Lisp_Object color = first;
2614
2615 if (STRINGP (color_name))
2616 {
2617 if (EQ (color, Qforeground_color))
2618 to[LFACE_FOREGROUND_INDEX] = color_name;
2619 else
2620 to[LFACE_BACKGROUND_INDEX] = color_name;
2621 }
2622 else
2623 {
2624 if (err_msgs)
2625 add_to_log ("Invalid face color %S", color_name);
2626 ok = false;
2627 }
2628 }
2629 else if (SYMBOLP (first)
2630 && *SDATA (SYMBOL_NAME (first)) == ':')
2631 {
2632
2633 if (attr_filter > 0)
2634 {
2635 eassert (attr_filter < LFACE_VECTOR_SIZE);
2636
2637
2638
2639
2640
2641
2642 Lisp_Object parent_face = Qnil;
2643 bool attr_filter_seen = false;
2644 Lisp_Object face_ref_tem = face_ref;
2645 while (CONSP (face_ref_tem) && CONSP (XCDR (face_ref_tem)))
2646 {
2647 Lisp_Object keyword = XCAR (face_ref_tem);
2648 Lisp_Object value = XCAR (XCDR (face_ref_tem));
2649
2650 if (EQ (keyword, face_attr_sym[attr_filter])
2651 || (attr_filter == LFACE_INVERSE_INDEX
2652 && EQ (keyword, QCreverse_video)))
2653 {
2654 attr_filter_seen = true;
2655 if (NILP (value))
2656 return true;
2657 }
2658 else if (EQ (keyword, QCinherit))
2659 parent_face = value;
2660 face_ref_tem = XCDR (XCDR (face_ref_tem));
2661 }
2662 if (!attr_filter_seen)
2663 {
2664 if (NILP (parent_face))
2665 return true;
2666
2667 Lisp_Object scratch_attrs[LFACE_VECTOR_SIZE];
2668 int i;
2669
2670 scratch_attrs[0] = Qface;
2671 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
2672 scratch_attrs[i] = Qunspecified;
2673 if (!merge_face_ref (w, f, parent_face, scratch_attrs,
2674 err_msgs, named_merge_points, 0))
2675 {
2676 add_to_log ("Invalid face attribute %S %S",
2677 QCinherit, parent_face);
2678 return false;
2679 }
2680 if (NILP (scratch_attrs[attr_filter])
2681 || UNSPECIFIEDP (scratch_attrs[attr_filter]))
2682 return true;
2683 }
2684 attr_filter_passed = true;
2685 }
2686 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
2687 {
2688 Lisp_Object keyword = XCAR (face_ref);
2689 Lisp_Object value = XCAR (XCDR (face_ref));
2690 bool err = false;
2691
2692
2693 if (EQ (value, Qunspecified))
2694 ;
2695 else if (EQ (keyword, QCfamily))
2696 {
2697 if (STRINGP (value))
2698 {
2699 to[LFACE_FAMILY_INDEX] = value;
2700 font_clear_prop (to, FONT_FAMILY_INDEX);
2701 }
2702 else
2703 err = true;
2704 }
2705 else if (EQ (keyword, QCfoundry))
2706 {
2707 if (STRINGP (value))
2708 {
2709 to[LFACE_FOUNDRY_INDEX] = value;
2710 font_clear_prop (to, FONT_FOUNDRY_INDEX);
2711 }
2712 else
2713 err = true;
2714 }
2715 else if (EQ (keyword, QCheight))
2716 {
2717 Lisp_Object new_height =
2718 merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil);
2719
2720 if (! NILP (new_height))
2721 {
2722 to[LFACE_HEIGHT_INDEX] = new_height;
2723 font_clear_prop (to, FONT_SIZE_INDEX);
2724 }
2725 else
2726 err = true;
2727 }
2728 else if (EQ (keyword, QCweight))
2729 {
2730 if (SYMBOLP (value) && FONT_WEIGHT_NAME_NUMERIC (value) >= 0)
2731 {
2732 to[LFACE_WEIGHT_INDEX] = value;
2733 font_clear_prop (to, FONT_WEIGHT_INDEX);
2734 }
2735 else
2736 err = true;
2737 }
2738 else if (EQ (keyword, QCslant))
2739 {
2740 if (SYMBOLP (value) && FONT_SLANT_NAME_NUMERIC (value) >= 0)
2741 {
2742 to[LFACE_SLANT_INDEX] = value;
2743 font_clear_prop (to, FONT_SLANT_INDEX);
2744 }
2745 else
2746 err = true;
2747 }
2748 else if (EQ (keyword, QCunderline))
2749 {
2750 if (EQ (value, Qt)
2751 || NILP (value)
2752 || STRINGP (value)
2753 || CONSP (value))
2754 to[LFACE_UNDERLINE_INDEX] = value;
2755 else
2756 err = true;
2757 }
2758 else if (EQ (keyword, QCoverline))
2759 {
2760 if (EQ (value, Qt)
2761 || NILP (value)
2762 || STRINGP (value))
2763 to[LFACE_OVERLINE_INDEX] = value;
2764 else
2765 err = true;
2766 }
2767 else if (EQ (keyword, QCstrike_through))
2768 {
2769 if (EQ (value, Qt)
2770 || NILP (value)
2771 || STRINGP (value))
2772 to[LFACE_STRIKE_THROUGH_INDEX] = value;
2773 else
2774 err = true;
2775 }
2776 else if (EQ (keyword, QCbox))
2777 {
2778 if (EQ (value, Qt))
2779 value = make_fixnum (1);
2780 if ((FIXNUMP (value) && XFIXNUM (value) != 0)
2781 || STRINGP (value)
2782 || CONSP (value)
2783 || NILP (value))
2784 to[LFACE_BOX_INDEX] = value;
2785 else
2786 err = true;
2787 }
2788 else if (EQ (keyword, QCinverse_video)
2789 || EQ (keyword, QCreverse_video))
2790 {
2791 if (EQ (value, Qt) || NILP (value))
2792 to[LFACE_INVERSE_INDEX] = value;
2793 else
2794 err = true;
2795 }
2796 else if (EQ (keyword, QCforeground))
2797 {
2798 if (STRINGP (value))
2799 to[LFACE_FOREGROUND_INDEX] = value;
2800 else
2801 err = true;
2802 }
2803 else if (EQ (keyword, QCdistant_foreground))
2804 {
2805 if (STRINGP (value))
2806 to[LFACE_DISTANT_FOREGROUND_INDEX] = value;
2807 else
2808 err = true;
2809 }
2810 else if (EQ (keyword, QCbackground))
2811 {
2812 if (STRINGP (value))
2813 to[LFACE_BACKGROUND_INDEX] = value;
2814 else
2815 err = true;
2816 }
2817 else if (EQ (keyword, QCstipple))
2818 {
2819 #if defined (HAVE_WINDOW_SYSTEM)
2820 if (NILP (value) || !NILP (Fbitmap_spec_p (value)))
2821 to[LFACE_STIPPLE_INDEX] = value;
2822 else
2823 err = true;
2824 #endif
2825 }
2826 else if (EQ (keyword, QCwidth))
2827 {
2828 if (SYMBOLP (value) && FONT_WIDTH_NAME_NUMERIC (value) >= 0)
2829 {
2830 to[LFACE_SWIDTH_INDEX] = value;
2831 font_clear_prop (to, FONT_WIDTH_INDEX);
2832 }
2833 else
2834 err = true;
2835 }
2836 else if (EQ (keyword, QCfont))
2837 {
2838 if (FONTP (value))
2839 to[LFACE_FONT_INDEX] = value;
2840 else
2841 err = true;
2842 }
2843 else if (EQ (keyword, QCinherit))
2844 {
2845
2846
2847 if (attr_filter_passed)
2848 {
2849
2850
2851
2852
2853
2854
2855 if (! merge_face_ref (w, f, value, to,
2856 err_msgs, named_merge_points, 0))
2857 err = true;
2858 }
2859 else if (! merge_face_ref (w, f, value, to,
2860 err_msgs, named_merge_points,
2861 attr_filter))
2862 err = true;
2863 }
2864 else if (EQ (keyword, QCextend))
2865 {
2866 if (EQ (value, Qt) || NILP (value))
2867 to[LFACE_EXTEND_INDEX] = value;
2868 else
2869 err = true;
2870 }
2871 else
2872 err = true;
2873
2874 if (err)
2875 {
2876 add_to_log ("Invalid face attribute %S %S", keyword, value);
2877 ok = false;
2878 }
2879
2880 face_ref = XCDR (XCDR (face_ref));
2881 }
2882 }
2883 else
2884 {
2885
2886
2887
2888 Lisp_Object next = XCDR (face_ref);
2889
2890 if (! NILP (next))
2891 ok = merge_face_ref (w, f, next, to, err_msgs,
2892 named_merge_points, attr_filter);
2893
2894 if (! merge_face_ref (w, f, first, to, err_msgs,
2895 named_merge_points, attr_filter))
2896 ok = false;
2897 }
2898 }
2899 else
2900 {
2901
2902 ok = merge_named_face (w, f, face_ref, to, named_merge_points,
2903 attr_filter);
2904 if (!ok && err_msgs)
2905 add_to_log ("Invalid face reference: %s", face_ref);
2906 }
2907
2908 return ok;
2909 }
2910
2911
2912 DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
2913 Sinternal_make_lisp_face, 1, 2, 0,
2914 doc:
2915
2916
2917
2918 )
2919 (Lisp_Object face, Lisp_Object frame)
2920 {
2921 Lisp_Object global_lface, lface;
2922 struct frame *f;
2923 int i;
2924
2925 CHECK_SYMBOL (face);
2926 global_lface = lface_from_face_name (NULL, face, false);
2927
2928 if (!NILP (frame))
2929 {
2930 CHECK_LIVE_FRAME (frame);
2931 f = XFRAME (frame);
2932 lface = lface_from_face_name (f, face, false);
2933 }
2934 else
2935 f = NULL, lface = Qnil;
2936
2937
2938 if (NILP (global_lface))
2939 {
2940
2941
2942
2943
2944 if (next_lface_id == lface_id_to_name_size)
2945 lface_id_to_name =
2946 xpalloc (lface_id_to_name, &lface_id_to_name_size, 1, MAX_FACE_ID,
2947 sizeof *lface_id_to_name);
2948
2949 Lisp_Object face_id = make_fixnum (next_lface_id);
2950 lface_id_to_name[next_lface_id] = face;
2951 Fput (face, Qface, face_id);
2952 ++next_lface_id;
2953
2954 global_lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified);
2955 ASET (global_lface, 0, Qface);
2956 Fputhash (face, Fcons (face_id, global_lface), Vface_new_frame_defaults);
2957 }
2958 else if (f == NULL)
2959 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2960 ASET (global_lface, i, Qunspecified);
2961
2962
2963 if (f)
2964 {
2965 if (NILP (lface))
2966 {
2967 lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified);
2968 ASET (lface, 0, Qface);
2969 Fputhash (face, lface, f->face_hash_table);
2970 }
2971 else
2972 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2973 ASET (lface, i, Qunspecified);
2974 }
2975 else
2976 lface = global_lface;
2977
2978
2979
2980
2981
2982
2983 if (NILP (Fget (face, Qface_no_inherit)))
2984 {
2985 if (f)
2986 {
2987 f->face_change = true;
2988 fset_redisplay (f);
2989 }
2990 else
2991 {
2992 face_change = true;
2993 windows_or_buffers_changed = 54;
2994 }
2995 }
2996
2997 eassert (LFACEP (lface));
2998 check_lface (lface);
2999 return lface;
3000 }
3001
3002
3003 DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
3004 Sinternal_lisp_face_p, 1, 2, 0,
3005 doc:
3006
3007
3008
3009 )
3010 (Lisp_Object face, Lisp_Object frame)
3011 {
3012 Lisp_Object lface;
3013
3014 face = resolve_face_name (face, true);
3015
3016 if (!NILP (frame))
3017 {
3018 CHECK_LIVE_FRAME (frame);
3019 lface = lface_from_face_name (XFRAME (frame), face, false);
3020 }
3021 else
3022 lface = lface_from_face_name (NULL, face, false);
3023
3024 return lface;
3025 }
3026
3027
3028 DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
3029 Sinternal_copy_lisp_face, 4, 4, 0,
3030 doc:
3031
3032
3033
3034
3035
3036
3037 )
3038 (Lisp_Object from, Lisp_Object to, Lisp_Object frame, Lisp_Object new_frame)
3039 {
3040 Lisp_Object lface, copy;
3041 struct frame *f;
3042
3043 CHECK_SYMBOL (from);
3044 CHECK_SYMBOL (to);
3045
3046 if (EQ (frame, Qt))
3047 {
3048
3049
3050 lface = lface_from_face_name (NULL, from, true);
3051 copy = Finternal_make_lisp_face (to, Qnil);
3052 f = NULL;
3053 }
3054 else
3055 {
3056
3057 if (NILP (new_frame))
3058 new_frame = frame;
3059 CHECK_LIVE_FRAME (frame);
3060 CHECK_LIVE_FRAME (new_frame);
3061 lface = lface_from_face_name (XFRAME (frame), from, true);
3062 copy = Finternal_make_lisp_face (to, new_frame);
3063 f = XFRAME (new_frame);
3064 }
3065
3066 vcopy (copy, 0, xvector_contents (lface), LFACE_VECTOR_SIZE);
3067
3068
3069
3070
3071
3072
3073 if (NILP (Fget (to, Qface_no_inherit)))
3074 {
3075 if (f)
3076 {
3077 f->face_change = true;
3078 fset_redisplay (f);
3079 }
3080 else
3081 {
3082 face_change = true;
3083 windows_or_buffers_changed = 55;
3084 }
3085 }
3086
3087 return to;
3088 }
3089
3090
3091 #define HANDLE_INVALID_NIL_VALUE(A,F) \
3092 if (NILP (value)) \
3093 { \
3094 add_to_log ("Warning: setting attribute `%s' of face `%s': nil " \
3095 "value is invalid, use `unspecified' instead.", A, F); \
3096 \
3097 value = Qunspecified; \
3098 }
3099
3100 DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
3101 Sinternal_set_lisp_face_attribute, 3, 4, 0,
3102 doc:
3103
3104
3105
3106
3107 )
3108 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
3109 {
3110 Lisp_Object lface;
3111 Lisp_Object old_value = Qnil;
3112
3113
3114 enum font_property_index prop_index = 0;
3115 struct frame *f;
3116
3117 CHECK_SYMBOL (face);
3118 CHECK_SYMBOL (attr);
3119
3120 face = resolve_face_name (face, true);
3121
3122
3123
3124 if (FIXNUMP (frame) && XFIXNUM (frame) == 0)
3125 {
3126 Lisp_Object tail;
3127 Finternal_set_lisp_face_attribute (face, attr, value, Qt);
3128 FOR_EACH_FRAME (tail, frame)
3129 Finternal_set_lisp_face_attribute (face, attr, value, frame);
3130 return face;
3131 }
3132
3133
3134 if (EQ (frame, Qt))
3135 {
3136 f = NULL;
3137 lface = lface_from_face_name (NULL, face, true);
3138
3139
3140
3141
3142
3143
3144
3145 if (UNSPECIFIEDP (value))
3146 value = QCignore_defface;
3147 }
3148 else
3149 {
3150 if (NILP (frame))
3151 frame = selected_frame;
3152
3153 CHECK_LIVE_FRAME (frame);
3154 f = XFRAME (frame);
3155
3156 lface = lface_from_face_name (f, face, false);
3157
3158
3159 if (NILP (lface))
3160 lface = Finternal_make_lisp_face (face, frame);
3161 }
3162
3163 if (EQ (attr, QCfamily))
3164 {
3165 if (!UNSPECIFIEDP (value)
3166 && !IGNORE_DEFFACE_P (value)
3167 && !RESET_P (value))
3168 {
3169 CHECK_STRING (value);
3170 if (SCHARS (value) == 0)
3171 signal_error ("Invalid face family", value);
3172 }
3173 old_value = LFACE_FAMILY (lface);
3174 ASET (lface, LFACE_FAMILY_INDEX, value);
3175 prop_index = FONT_FAMILY_INDEX;
3176 }
3177 else if (EQ (attr, QCfoundry))
3178 {
3179 if (!UNSPECIFIEDP (value)
3180 && !IGNORE_DEFFACE_P (value)
3181 && !RESET_P (value))
3182 {
3183 CHECK_STRING (value);
3184 if (SCHARS (value) == 0)
3185 signal_error ("Invalid face foundry", value);
3186 }
3187 old_value = LFACE_FOUNDRY (lface);
3188 ASET (lface, LFACE_FOUNDRY_INDEX, value);
3189 prop_index = FONT_FOUNDRY_INDEX;
3190 }
3191 else if (EQ (attr, QCheight))
3192 {
3193 if (!UNSPECIFIEDP (value)
3194 && !IGNORE_DEFFACE_P (value)
3195 && !RESET_P (value))
3196 {
3197 if (EQ (face, Qdefault))
3198 {
3199
3200 if (!FIXNUMP (value) || XFIXNUM (value) <= 0)
3201 signal_error ("Default face height not absolute and positive",
3202 value);
3203 }
3204 else
3205 {
3206
3207
3208 Lisp_Object test = merge_face_heights (value,
3209 make_fixnum (10),
3210 Qnil);
3211 if (!FIXNUMP (test) || XFIXNUM (test) <= 0)
3212 signal_error ("Face height does not produce a positive integer",
3213 value);
3214 }
3215 }
3216
3217 old_value = LFACE_HEIGHT (lface);
3218 ASET (lface, LFACE_HEIGHT_INDEX, value);
3219 prop_index = FONT_SIZE_INDEX;
3220 }
3221 else if (EQ (attr, QCweight))
3222 {
3223 if (!UNSPECIFIEDP (value)
3224 && !IGNORE_DEFFACE_P (value)
3225 && !RESET_P (value))
3226 {
3227 CHECK_SYMBOL (value);
3228 if (FONT_WEIGHT_NAME_NUMERIC (value) < 0)
3229 signal_error ("Invalid face weight", value);
3230 }
3231 old_value = LFACE_WEIGHT (lface);
3232 ASET (lface, LFACE_WEIGHT_INDEX, value);
3233 prop_index = FONT_WEIGHT_INDEX;
3234 }
3235 else if (EQ (attr, QCslant))
3236 {
3237 if (!UNSPECIFIEDP (value)
3238 && !IGNORE_DEFFACE_P (value)
3239 && !RESET_P (value))
3240 {
3241 CHECK_SYMBOL (value);
3242 if (FONT_SLANT_NAME_NUMERIC (value) < 0)
3243 signal_error ("Invalid face slant", value);
3244 }
3245 old_value = LFACE_SLANT (lface);
3246 ASET (lface, LFACE_SLANT_INDEX, value);
3247 prop_index = FONT_SLANT_INDEX;
3248 }
3249 else if (EQ (attr, QCunderline))
3250 {
3251 bool valid_p = false;
3252
3253 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value))
3254 valid_p = true;
3255 else if (NILP (value) || EQ (value, Qt))
3256 valid_p = true;
3257 else if (STRINGP (value) && SCHARS (value) > 0)
3258 valid_p = true;
3259 else if (CONSP (value))
3260 {
3261 Lisp_Object key, val, list;
3262
3263 list = value;
3264
3265
3266
3267
3268
3269
3270 valid_p = true;
3271
3272 while (!NILP (CAR_SAFE (list)))
3273 {
3274 key = CAR_SAFE (list);
3275 list = CDR_SAFE (list);
3276 val = CAR_SAFE (list);
3277 list = CDR_SAFE (list);
3278
3279 if (NILP (key) || (NILP (val)
3280 && !EQ (key, QCposition)))
3281 {
3282 valid_p = false;
3283 break;
3284 }
3285
3286 else if (EQ (key, QCcolor)
3287 && !(EQ (val, Qforeground_color)
3288 || (STRINGP (val) && SCHARS (val) > 0)))
3289 {
3290 valid_p = false;
3291 break;
3292 }
3293
3294 else if (EQ (key, QCstyle)
3295 && !(EQ (val, Qline) || EQ (val, Qwave)))
3296 {
3297 valid_p = false;
3298 break;
3299 }
3300 }
3301 }
3302
3303 if (!valid_p)
3304 signal_error ("Invalid face underline", value);
3305
3306 old_value = LFACE_UNDERLINE (lface);
3307 ASET (lface, LFACE_UNDERLINE_INDEX, value);
3308 }
3309 else if (EQ (attr, QCoverline))
3310 {
3311 if (!UNSPECIFIEDP (value)
3312 && !IGNORE_DEFFACE_P (value)
3313 && !RESET_P (value))
3314 if ((SYMBOLP (value)
3315 && !EQ (value, Qt)
3316 && !NILP (value))
3317
3318 || (STRINGP (value)
3319 && SCHARS (value) == 0))
3320 signal_error ("Invalid face overline", value);
3321
3322 old_value = LFACE_OVERLINE (lface);
3323 ASET (lface, LFACE_OVERLINE_INDEX, value);
3324 }
3325 else if (EQ (attr, QCstrike_through))
3326 {
3327 if (!UNSPECIFIEDP (value)
3328 && !IGNORE_DEFFACE_P (value)
3329 && !RESET_P (value))
3330 if ((SYMBOLP (value)
3331 && !EQ (value, Qt)
3332 && !NILP (value))
3333
3334 || (STRINGP (value)
3335 && SCHARS (value) == 0))
3336 signal_error ("Invalid face strike-through", value);
3337
3338 old_value = LFACE_STRIKE_THROUGH (lface);
3339 ASET (lface, LFACE_STRIKE_THROUGH_INDEX, value);
3340 }
3341 else if (EQ (attr, QCbox))
3342 {
3343 bool valid_p;
3344
3345
3346
3347 if (EQ (value, Qt))
3348 value = make_fixnum (1);
3349
3350 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value))
3351 valid_p = true;
3352 else if (NILP (value))
3353 valid_p = true;
3354 else if (FIXNUMP (value))
3355 valid_p = XFIXNUM (value) != 0;
3356 else if (STRINGP (value))
3357 valid_p = SCHARS (value) > 0;
3358 else if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value)))
3359 valid_p = true;
3360 else if (CONSP (value))
3361 {
3362 Lisp_Object tem;
3363
3364 tem = value;
3365 while (CONSP (tem))
3366 {
3367 Lisp_Object k, v;
3368
3369 k = XCAR (tem);
3370 tem = XCDR (tem);
3371 if (!CONSP (tem))
3372 break;
3373 v = XCAR (tem);
3374 tem = XCDR (tem);
3375
3376 if (EQ (k, QCline_width))
3377 {
3378 if ((!CONSP(v) || !FIXNUMP (XCAR (v)) || XFIXNUM (XCAR (v)) == 0
3379 || !FIXNUMP (XCDR (v)) || XFIXNUM (XCDR (v)) == 0)
3380 && (!FIXNUMP (v) || XFIXNUM (v) == 0))
3381 break;
3382 }
3383 else if (EQ (k, QCcolor))
3384 {
3385 if (!NILP (v) && (!STRINGP (v) || SCHARS (v) == 0))
3386 break;
3387 }
3388 else if (EQ (k, QCstyle))
3389 {
3390 if (!EQ (v, Qpressed_button) && !EQ (v, Qreleased_button)
3391 && !EQ(v, Qflat_button))
3392 break;
3393 }
3394 else
3395 break;
3396 }
3397
3398 valid_p = NILP (tem);
3399 }
3400 else
3401 valid_p = false;
3402
3403 if (!valid_p)
3404 signal_error ("Invalid face box", value);
3405
3406 old_value = LFACE_BOX (lface);
3407 ASET (lface, LFACE_BOX_INDEX, value);
3408 }
3409 else if (EQ (attr, QCinverse_video)
3410 || EQ (attr, QCreverse_video))
3411 {
3412 if (!UNSPECIFIEDP (value)
3413 && !IGNORE_DEFFACE_P (value)
3414 && !RESET_P (value))
3415 {
3416 CHECK_SYMBOL (value);
3417 if (!EQ (value, Qt) && !NILP (value))
3418 signal_error ("Invalid inverse-video face attribute value", value);
3419 }
3420 old_value = LFACE_INVERSE (lface);
3421 ASET (lface, LFACE_INVERSE_INDEX, value);
3422 }
3423 else if (EQ (attr, QCextend))
3424 {
3425 if (!UNSPECIFIEDP (value)
3426 && !IGNORE_DEFFACE_P (value)
3427 && !RESET_P (value))
3428 {
3429 CHECK_SYMBOL (value);
3430 if (!EQ (value, Qt) && !NILP (value))
3431 signal_error ("Invalid extend face attribute value", value);
3432 }
3433 old_value = LFACE_EXTEND (lface);
3434 ASET (lface, LFACE_EXTEND_INDEX, value);
3435 }
3436 else if (EQ (attr, QCforeground))
3437 {
3438 HANDLE_INVALID_NIL_VALUE (QCforeground, face);
3439 if (!UNSPECIFIEDP (value)
3440 && !IGNORE_DEFFACE_P (value)
3441 && !RESET_P (value))
3442 {
3443
3444
3445
3446 CHECK_STRING (value);
3447 if (SCHARS (value) == 0)
3448 signal_error ("Empty foreground color value", value);
3449 }
3450 old_value = LFACE_FOREGROUND (lface);
3451 ASET (lface, LFACE_FOREGROUND_INDEX, value);
3452 }
3453 else if (EQ (attr, QCdistant_foreground))
3454 {
3455 HANDLE_INVALID_NIL_VALUE (QCdistant_foreground, face);
3456 if (!UNSPECIFIEDP (value)
3457 && !IGNORE_DEFFACE_P (value)
3458 && !RESET_P (value))
3459 {
3460
3461
3462
3463 CHECK_STRING (value);
3464 if (SCHARS (value) == 0)
3465 signal_error ("Empty distant-foreground color value", value);
3466 }
3467 old_value = LFACE_DISTANT_FOREGROUND (lface);
3468 ASET (lface, LFACE_DISTANT_FOREGROUND_INDEX, value);
3469 }
3470 else if (EQ (attr, QCbackground))
3471 {
3472 HANDLE_INVALID_NIL_VALUE (QCbackground, face);
3473 if (!UNSPECIFIEDP (value)
3474 && !IGNORE_DEFFACE_P (value)
3475 && !RESET_P (value))
3476 {
3477
3478
3479
3480 CHECK_STRING (value);
3481 if (SCHARS (value) == 0)
3482 signal_error ("Empty background color value", value);
3483 }
3484 old_value = LFACE_BACKGROUND (lface);
3485 ASET (lface, LFACE_BACKGROUND_INDEX, value);
3486 }
3487 else if (EQ (attr, QCstipple))
3488 {
3489 #if defined (HAVE_WINDOW_SYSTEM)
3490 if (!UNSPECIFIEDP (value)
3491 && !IGNORE_DEFFACE_P (value)
3492 && !RESET_P (value)
3493 && !NILP (value)
3494 && NILP (Fbitmap_spec_p (value)))
3495 signal_error ("Invalid stipple attribute", value);
3496 old_value = LFACE_STIPPLE (lface);
3497 ASET (lface, LFACE_STIPPLE_INDEX, value);
3498 #endif
3499 }
3500 else if (EQ (attr, QCwidth))
3501 {
3502 if (!UNSPECIFIEDP (value)
3503 && !IGNORE_DEFFACE_P (value)
3504 && !RESET_P (value))
3505 {
3506 CHECK_SYMBOL (value);
3507 if (FONT_WIDTH_NAME_NUMERIC (value) < 0)
3508 signal_error ("Invalid face width", value);
3509 }
3510 old_value = LFACE_SWIDTH (lface);
3511 ASET (lface, LFACE_SWIDTH_INDEX, value);
3512 prop_index = FONT_WIDTH_INDEX;
3513 }
3514 else if (EQ (attr, QCfont))
3515 {
3516 #ifdef HAVE_WINDOW_SYSTEM
3517 if (EQ (frame, Qt) || FRAME_WINDOW_P (f))
3518 {
3519 if (!UNSPECIFIEDP (value)
3520 && !IGNORE_DEFFACE_P (value)
3521 && !RESET_P (value))
3522 {
3523 struct frame *f1;
3524
3525 old_value = LFACE_FONT (lface);
3526 if (! FONTP (value))
3527 {
3528 if (STRINGP (value))
3529 {
3530 Lisp_Object name = value;
3531 int fontset = fs_query_fontset (name, 0);
3532
3533 if (fontset >= 0)
3534 name = fontset_ascii (fontset);
3535 value = font_spec_from_name (name);
3536 if (!FONTP (value))
3537 signal_error ("Invalid font name", name);
3538 }
3539 else
3540 signal_error ("Invalid font or font-spec", value);
3541 }
3542 if (EQ (frame, Qt))
3543 f1 = XFRAME (selected_frame);
3544 else
3545 f1 = XFRAME (frame);
3546
3547
3548
3549
3550
3551
3552 if (FRAME_WINDOW_P (f1))
3553 {
3554 if (! FONT_OBJECT_P (value))
3555 {
3556 Lisp_Object *attrs = XVECTOR (lface)->contents;
3557 Lisp_Object font_object;
3558
3559 font_object = font_load_for_lface (f1, attrs, value);
3560 if (NILP (font_object))
3561 signal_error ("Font not available", value);
3562 value = font_object;
3563 }
3564 set_lface_from_font (f1, lface, value, true);
3565 f1->face_change = 1;
3566 }
3567 }
3568 else
3569 ASET (lface, LFACE_FONT_INDEX, value);
3570 }
3571 #endif
3572 }
3573 else if (EQ (attr, QCfontset))
3574 {
3575 #ifdef HAVE_WINDOW_SYSTEM
3576 if (EQ (frame, Qt) || FRAME_WINDOW_P (f))
3577 {
3578 Lisp_Object tmp = value;
3579
3580 old_value = LFACE_FONTSET (lface);
3581 if (!RESET_P (value))
3582 {
3583 tmp = Fquery_fontset (value, Qnil);
3584 if (NILP (tmp))
3585 signal_error ("Invalid fontset name", value);
3586 }
3587 ASET (lface, LFACE_FONTSET_INDEX, value = tmp);
3588 }
3589 #endif
3590 }
3591 else if (EQ (attr, QCinherit))
3592 {
3593 Lisp_Object tail;
3594 if (SYMBOLP (value))
3595 tail = Qnil;
3596 else
3597 for (tail = value; CONSP (tail); tail = XCDR (tail))
3598 if (!SYMBOLP (XCAR (tail)))
3599 break;
3600 if (NILP (tail))
3601 ASET (lface, LFACE_INHERIT_INDEX, value);
3602 else
3603 signal_error ("Invalid face inheritance", value);
3604 }
3605 else if (EQ (attr, QCbold))
3606 {
3607 old_value = LFACE_WEIGHT (lface);
3608 if (RESET_P (value))
3609 ASET (lface, LFACE_WEIGHT_INDEX, value);
3610 else
3611 ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold);
3612 prop_index = FONT_WEIGHT_INDEX;
3613 }
3614 else if (EQ (attr, QCitalic))
3615 {
3616 attr = QCslant;
3617 old_value = LFACE_SLANT (lface);
3618 if (RESET_P (value))
3619 ASET (lface, LFACE_SLANT_INDEX, value);
3620 else
3621 ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic);
3622 prop_index = FONT_SLANT_INDEX;
3623 }
3624 else
3625 signal_error ("Invalid face attribute name", attr);
3626
3627 if (prop_index)
3628 {
3629
3630
3631
3632
3633
3634
3635 font_clear_prop (XVECTOR (lface)->contents, prop_index);
3636 }
3637
3638
3639
3640
3641
3642
3643 if (!EQ (frame, Qt)
3644 && NILP (Fget (face, Qface_no_inherit))
3645 && NILP (Fequal (old_value, value)))
3646 {
3647 f->face_change = true;
3648 fset_redisplay (f);
3649 }
3650
3651 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
3652 && NILP (Fequal (old_value, value)))
3653 {
3654 Lisp_Object param;
3655
3656 param = Qnil;
3657
3658 if (EQ (face, Qdefault))
3659 {
3660 #ifdef HAVE_WINDOW_SYSTEM
3661
3662
3663 if (FRAMEP (frame)
3664 && (prop_index || EQ (attr, QCfont))
3665 && lface_fully_specified_p (XVECTOR (lface)->contents))
3666 set_font_frame_param (frame, lface);
3667 else
3668 #endif
3669
3670 if (EQ (attr, QCforeground))
3671 param = Qforeground_color;
3672 else if (EQ (attr, QCbackground))
3673 param = Qbackground_color;
3674 }
3675 #ifdef HAVE_WINDOW_SYSTEM
3676 #ifndef HAVE_NTGUI
3677 else if (EQ (face, Qscroll_bar))
3678 {
3679
3680
3681 if (EQ (attr, QCforeground))
3682 param = Qscroll_bar_foreground;
3683 else if (EQ (attr, QCbackground))
3684 param = Qscroll_bar_background;
3685 }
3686 #endif
3687 else if (EQ (face, Qborder))
3688 {
3689
3690
3691 if (EQ (attr, QCbackground))
3692 param = Qborder_color;
3693 }
3694 else if (EQ (face, Qcursor))
3695 {
3696
3697
3698 if (EQ (attr, QCbackground))
3699 param = Qcursor_color;
3700 }
3701 else if (EQ (face, Qmouse))
3702 {
3703
3704
3705 if (EQ (attr, QCbackground))
3706 param = Qmouse_color;
3707 }
3708 #endif
3709 else if (EQ (face, Qmenu))
3710 {
3711
3712
3713
3714 if (FRAMEP (frame))
3715 {
3716 struct frame *f = XFRAME (frame);
3717 if (FRAME_FACE_CACHE (f) == NULL)
3718 FRAME_FACE_CACHE (f) = make_face_cache (f);
3719 FRAME_FACE_CACHE (f)->menu_face_changed_p = true;
3720 }
3721 else
3722 menu_face_changed_default = true;
3723 }
3724
3725 if (!NILP (param))
3726 {
3727 if (EQ (frame, Qt))
3728
3729 {
3730 store_in_alist (&Vdefault_frame_alist, param, value);
3731 }
3732 else
3733
3734 {
3735 AUTO_FRAME_ARG (arg, param, value);
3736 Fmodify_frame_parameters (frame, arg);
3737 }
3738 }
3739 }
3740
3741 return face;
3742 }
3743
3744
3745
3746
3747
3748 void
3749 update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
3750 Lisp_Object new_value)
3751 {
3752 Lisp_Object face = Qnil;
3753 Lisp_Object lface;
3754
3755
3756
3757
3758 if (XFIXNAT (Fhash_table_count (f->face_hash_table)) == 0)
3759 return;
3760
3761 if (EQ (param, Qforeground_color))
3762 {
3763 face = Qdefault;
3764 lface = lface_from_face_name (f, face, true);
3765 ASET (lface, LFACE_FOREGROUND_INDEX,
3766 (STRINGP (new_value) ? new_value : Qunspecified));
3767 realize_basic_faces (f);
3768 }
3769 else if (EQ (param, Qbackground_color))
3770 {
3771 Lisp_Object frame;
3772
3773
3774
3775
3776 XSETFRAME (frame, f);
3777 call1 (Qframe_set_background_mode, frame);
3778
3779 face = Qdefault;
3780 lface = lface_from_face_name (f, face, true);
3781 ASET (lface, LFACE_BACKGROUND_INDEX,
3782 (STRINGP (new_value) ? new_value : Qunspecified));
3783 realize_basic_faces (f);
3784 }
3785 #ifdef HAVE_WINDOW_SYSTEM
3786 else if (EQ (param, Qborder_color))
3787 {
3788 face = Qborder;
3789 lface = lface_from_face_name (f, face, true);
3790 ASET (lface, LFACE_BACKGROUND_INDEX,
3791 (STRINGP (new_value) ? new_value : Qunspecified));
3792 }
3793 else if (EQ (param, Qcursor_color))
3794 {
3795 face = Qcursor;
3796 lface = lface_from_face_name (f, face, true);
3797 ASET (lface, LFACE_BACKGROUND_INDEX,
3798 (STRINGP (new_value) ? new_value : Qunspecified));
3799 }
3800 else if (EQ (param, Qmouse_color))
3801 {
3802 face = Qmouse;
3803 lface = lface_from_face_name (f, face, true);
3804 ASET (lface, LFACE_BACKGROUND_INDEX,
3805 (STRINGP (new_value) ? new_value : Qunspecified));
3806 }
3807 #endif
3808
3809
3810
3811
3812
3813
3814 if (!NILP (face)
3815 && NILP (Fget (face, Qface_no_inherit)))
3816 {
3817 f->face_change = true;
3818 fset_redisplay (f);
3819 }
3820 }
3821
3822
3823 #ifdef HAVE_WINDOW_SYSTEM
3824
3825
3826
3827
3828 static void
3829 set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
3830 {
3831 struct frame *f = XFRAME (frame);
3832 Lisp_Object font;
3833
3834 if (FRAME_WINDOW_P (f)
3835
3836
3837 && (font = LFACE_FONT (lface),
3838 ! UNSPECIFIEDP (font)))
3839 {
3840 if (FONT_SPEC_P (font))
3841 {
3842 font = font_load_for_lface (f, XVECTOR (lface)->contents, font);
3843 if (NILP (font))
3844 return;
3845 ASET (lface, LFACE_FONT_INDEX, font);
3846 }
3847 f->default_face_done_p = false;
3848 AUTO_LIST2 (arg, AUTO_CONS_EXPR (Qfont, font),
3849
3850
3851
3852 AUTO_CONS_EXPR (Qfont_parameter, Qnil));
3853 gui_set_frame_parameters_1 (f, arg, true);
3854 }
3855 }
3856
3857 DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
3858 Sinternal_face_x_get_resource, 2, 3, 0,
3859 doc:
3860
3861
3862 )
3863 (Lisp_Object resource, Lisp_Object class, Lisp_Object frame)
3864 {
3865 Lisp_Object value = Qnil;
3866 struct frame *f;
3867
3868 CHECK_STRING (resource);
3869 CHECK_STRING (class);
3870 f = decode_live_frame (frame);
3871 block_input ();
3872 value = gui_display_get_resource (FRAME_DISPLAY_INFO (f),
3873 resource, class, Qnil, Qnil);
3874 unblock_input ();
3875 return value;
3876 }
3877
3878
3879
3880
3881
3882
3883
3884 static Lisp_Object
3885 face_boolean_x_resource_value (Lisp_Object value, bool signal_p)
3886 {
3887 Lisp_Object result = make_fixnum (0);
3888
3889 eassert (STRINGP (value));
3890
3891 if (xstrcasecmp (SSDATA (value), "on") == 0
3892 || xstrcasecmp (SSDATA (value), "true") == 0)
3893 result = Qt;
3894 else if (xstrcasecmp (SSDATA (value), "off") == 0
3895 || xstrcasecmp (SSDATA (value), "false") == 0)
3896 result = Qnil;
3897 else if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
3898 result = Qunspecified;
3899 else if (signal_p)
3900 signal_error ("Invalid face attribute value from X resource", value);
3901
3902 return result;
3903 }
3904
3905
3906 DEFUN ("internal-set-lisp-face-attribute-from-resource",
3907 Finternal_set_lisp_face_attribute_from_resource,
3908 Sinternal_set_lisp_face_attribute_from_resource,
3909 3, 4, 0, doc: )
3910 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
3911 {
3912 CHECK_SYMBOL (face);
3913 CHECK_SYMBOL (attr);
3914 CHECK_STRING (value);
3915
3916 if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
3917 value = Qunspecified;
3918 else if (EQ (attr, QCheight))
3919 {
3920 value = Fstring_to_number (value, Qnil);
3921 if (!FIXNUMP (value) || XFIXNUM (value) <= 0)
3922 signal_error ("Invalid face height from X resource", value);
3923 }
3924 else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
3925 value = face_boolean_x_resource_value (value, true);
3926 else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
3927 value = intern (SSDATA (value));
3928 else if (EQ (attr, QCreverse_video)
3929 || EQ (attr, QCinverse_video)
3930 || EQ (attr, QCextend))
3931 value = face_boolean_x_resource_value (value, true);
3932 else if (EQ (attr, QCunderline)
3933 || EQ (attr, QCoverline)
3934 || EQ (attr, QCstrike_through))
3935 {
3936 Lisp_Object boolean_value;
3937
3938
3939
3940 boolean_value = face_boolean_x_resource_value (value, false);
3941 if (SYMBOLP (boolean_value))
3942 value = boolean_value;
3943 }
3944 else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
3945 value = Fcar (Fread_from_string (value, Qnil, Qnil));
3946
3947 return Finternal_set_lisp_face_attribute (face, attr, value, frame);
3948 }
3949
3950 #endif
3951
3952
3953
3954
3955
3956
3957 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
3958
3959
3960
3961 static void
3962 x_update_menu_appearance (struct frame *f)
3963 {
3964 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3965 XrmDatabase rdb;
3966
3967 if (dpyinfo
3968 && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
3969 rdb != NULL))
3970 {
3971 char line[512];
3972 char *buf = line;
3973 ptrdiff_t bufsize = sizeof line;
3974 Lisp_Object lface = lface_from_face_name (f, Qmenu, true);
3975 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
3976 const char *myname = SSDATA (Vx_resource_name);
3977 bool changed_p = false;
3978 #ifdef USE_MOTIF
3979 const char *popup_path = "popup_menu";
3980 #else
3981 const char *popup_path = "menu.popup";
3982 #endif
3983
3984 if (STRINGP (LFACE_FOREGROUND (lface)))
3985 {
3986 exprintf (&buf, &bufsize, line, -1, "%s.%s*foreground: %s",
3987 myname, popup_path,
3988 SDATA (LFACE_FOREGROUND (lface)));
3989 XrmPutLineResource (&rdb, line);
3990 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s",
3991 myname, SDATA (LFACE_FOREGROUND (lface)));
3992 XrmPutLineResource (&rdb, line);
3993 changed_p = true;
3994 }
3995
3996 if (STRINGP (LFACE_BACKGROUND (lface)))
3997 {
3998 exprintf (&buf, &bufsize, line, -1, "%s.%s*background: %s",
3999 myname, popup_path,
4000 SDATA (LFACE_BACKGROUND (lface)));
4001 XrmPutLineResource (&rdb, line);
4002
4003 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s",
4004 myname, SDATA (LFACE_BACKGROUND (lface)));
4005 XrmPutLineResource (&rdb, line);
4006 changed_p = true;
4007 }
4008
4009 if (face->font
4010
4011
4012
4013 && FONTP (LFACE_FONT (lface))
4014 && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
4015 || !UNSPECIFIEDP (LFACE_FOUNDRY (lface))
4016 || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
4017 || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
4018 || !UNSPECIFIEDP (LFACE_SLANT (lface))
4019 || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
4020 {
4021 Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
4022 #ifdef USE_MOTIF
4023 const char *suffix = "List";
4024 bool motif = true;
4025 #else
4026 #if defined HAVE_X_I18N
4027
4028 const char *suffix = "Set";
4029 #else
4030 const char *suffix = "";
4031 #endif
4032 bool motif = false;
4033 #endif
4034
4035 if (! NILP (xlfd))
4036 {
4037 #if defined HAVE_X_I18N
4038 char *fontsetname = xic_create_fontsetname (SSDATA (xlfd), motif);
4039 #else
4040 char *fontsetname = SSDATA (xlfd);
4041 #endif
4042 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*font%s: %s",
4043 myname, suffix, fontsetname);
4044 XrmPutLineResource (&rdb, line);
4045
4046 exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s",
4047 myname, popup_path, suffix, fontsetname);
4048 XrmPutLineResource (&rdb, line);
4049 changed_p = true;
4050 if (fontsetname != SSDATA (xlfd))
4051 xfree (fontsetname);
4052 }
4053 }
4054
4055 if (changed_p && f->output_data.x->menubar_widget)
4056 free_frame_menubar (f);
4057
4058 if (buf != line)
4059 xfree (buf);
4060 }
4061 }
4062
4063 #endif
4064
4065
4066 DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
4067 Sface_attribute_relative_p,
4068 2, 2, 0,
4069 doc:
4070
4071
4072
4073
4074
4075
4076
4077 attributes: const)
4078 (Lisp_Object attribute, Lisp_Object value)
4079 {
4080 if (EQ (value, Qunspecified) || (EQ (value, QCignore_defface)))
4081 return Qt;
4082 else if (EQ (attribute, QCheight))
4083 return FIXNUMP (value) ? Qnil : Qt;
4084 else
4085 return Qnil;
4086 }
4087
4088 DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
4089 3, 3, 0,
4090 doc:
4091
4092 )
4093 (Lisp_Object attribute, Lisp_Object value1, Lisp_Object value2)
4094 {
4095 if (EQ (value1, Qunspecified) || EQ (value1, QCignore_defface))
4096 return value2;
4097 else if (EQ (attribute, QCheight))
4098 return merge_face_heights (value1, value2, value1);
4099 else
4100 return value1;
4101 }
4102
4103
4104 DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
4105 Sinternal_get_lisp_face_attribute,
4106 2, 3, 0,
4107 doc:
4108
4109
4110
4111
4112 )
4113 (Lisp_Object symbol, Lisp_Object keyword, Lisp_Object frame)
4114 {
4115 struct frame *f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
4116 Lisp_Object lface = lface_from_face_name (f, symbol, true), value = Qnil;
4117
4118 CHECK_SYMBOL (symbol);
4119 CHECK_SYMBOL (keyword);
4120
4121 if (EQ (keyword, QCfamily))
4122 value = LFACE_FAMILY (lface);
4123 else if (EQ (keyword, QCfoundry))
4124 value = LFACE_FOUNDRY (lface);
4125 else if (EQ (keyword, QCheight))
4126 value = LFACE_HEIGHT (lface);
4127 else if (EQ (keyword, QCweight))
4128 value = LFACE_WEIGHT (lface);
4129 else if (EQ (keyword, QCslant))
4130 value = LFACE_SLANT (lface);
4131 else if (EQ (keyword, QCunderline))
4132 value = LFACE_UNDERLINE (lface);
4133 else if (EQ (keyword, QCoverline))
4134 value = LFACE_OVERLINE (lface);
4135 else if (EQ (keyword, QCstrike_through))
4136 value = LFACE_STRIKE_THROUGH (lface);
4137 else if (EQ (keyword, QCbox))
4138 value = LFACE_BOX (lface);
4139 else if (EQ (keyword, QCinverse_video)
4140 || EQ (keyword, QCreverse_video))
4141 value = LFACE_INVERSE (lface);
4142 else if (EQ (keyword, QCforeground))
4143 value = LFACE_FOREGROUND (lface);
4144 else if (EQ (keyword, QCdistant_foreground))
4145 value = LFACE_DISTANT_FOREGROUND (lface);
4146 else if (EQ (keyword, QCbackground))
4147 value = LFACE_BACKGROUND (lface);
4148 else if (EQ (keyword, QCstipple))
4149 value = LFACE_STIPPLE (lface);
4150 else if (EQ (keyword, QCwidth))
4151 value = LFACE_SWIDTH (lface);
4152 else if (EQ (keyword, QCinherit))
4153 value = LFACE_INHERIT (lface);
4154 else if (EQ (keyword, QCextend))
4155 value = LFACE_EXTEND (lface);
4156 else if (EQ (keyword, QCfont))
4157 value = LFACE_FONT (lface);
4158 else if (EQ (keyword, QCfontset))
4159 value = LFACE_FONTSET (lface);
4160 else
4161 signal_error ("Invalid face attribute name", keyword);
4162
4163 if (IGNORE_DEFFACE_P (value))
4164 return Qunspecified;
4165
4166 return value;
4167 }
4168
4169
4170 DEFUN ("internal-lisp-face-attribute-values",
4171 Finternal_lisp_face_attribute_values,
4172 Sinternal_lisp_face_attribute_values, 1, 1, 0,
4173 doc:
4174 )
4175 (Lisp_Object attr)
4176 {
4177 Lisp_Object result = Qnil;
4178
4179 CHECK_SYMBOL (attr);
4180
4181 if (EQ (attr, QCunderline) || EQ (attr, QCoverline)
4182 || EQ (attr, QCstrike_through)
4183 || EQ (attr, QCinverse_video)
4184 || EQ (attr, QCreverse_video)
4185 || EQ (attr, QCextend))
4186 result = list2 (Qt, Qnil);
4187
4188 return result;
4189 }
4190
4191
4192 DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
4193 Sinternal_merge_in_global_face, 2, 2, 0,
4194 doc:
4195 )
4196 (Lisp_Object face, Lisp_Object frame)
4197 {
4198 int i;
4199 Lisp_Object global_lface, local_lface, *gvec, *lvec;
4200 struct frame *f = XFRAME (frame);
4201
4202 CHECK_LIVE_FRAME (frame);
4203 global_lface = lface_from_face_name (NULL, face, true);
4204 local_lface = lface_from_face_name (f, face, false);
4205 if (NILP (local_lface))
4206 local_lface = Finternal_make_lisp_face (face, frame);
4207
4208
4209
4210
4211
4212
4213 lvec = XVECTOR (local_lface)->contents;
4214 gvec = XVECTOR (global_lface)->contents;
4215 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
4216 if (IGNORE_DEFFACE_P (gvec[i]))
4217 ASET (local_lface, i, Qunspecified);
4218 else if (! UNSPECIFIEDP (gvec[i]))
4219 ASET (local_lface, i, AREF (global_lface, i));
4220
4221
4222
4223 if (EQ (face, Qdefault))
4224 {
4225 struct face_cache *c = FRAME_FACE_CACHE (f);
4226 struct face *newface;
4227 struct face *oldface =
4228 c ? FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID) : NULL;
4229 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4230
4231
4232 if (oldface)
4233 {
4234
4235
4236 memcpy (attrs, oldface->lface, sizeof attrs);
4237
4238 merge_face_vectors (NULL, f, lvec, attrs, 0);
4239 vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE);
4240 newface = realize_face (c, lvec, DEFAULT_FACE_ID);
4241
4242 if ((! UNSPECIFIEDP (gvec[LFACE_FAMILY_INDEX])
4243 || ! UNSPECIFIEDP (gvec[LFACE_FOUNDRY_INDEX])
4244 || ! UNSPECIFIEDP (gvec[LFACE_HEIGHT_INDEX])
4245 || ! UNSPECIFIEDP (gvec[LFACE_WEIGHT_INDEX])
4246 || ! UNSPECIFIEDP (gvec[LFACE_SLANT_INDEX])
4247 || ! UNSPECIFIEDP (gvec[LFACE_SWIDTH_INDEX])
4248 || ! UNSPECIFIEDP (gvec[LFACE_FONT_INDEX]))
4249 && newface->font)
4250 {
4251 Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
4252 AUTO_FRAME_ARG (arg, Qfont, name);
4253
4254 #ifdef HAVE_WINDOW_SYSTEM
4255 if (FRAME_WINDOW_P (f))
4256
4257
4258
4259
4260 gui_set_frame_parameters_1 (f, arg, true);
4261 else
4262 #endif
4263 Fmodify_frame_parameters (frame, arg);
4264 }
4265
4266 if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
4267 {
4268 AUTO_FRAME_ARG (arg, Qforeground_color,
4269 gvec[LFACE_FOREGROUND_INDEX]);
4270 Fmodify_frame_parameters (frame, arg);
4271 }
4272
4273 if (STRINGP (gvec[LFACE_BACKGROUND_INDEX]))
4274 {
4275 AUTO_FRAME_ARG (arg, Qbackground_color,
4276 gvec[LFACE_BACKGROUND_INDEX]);
4277 Fmodify_frame_parameters (frame, arg);
4278 }
4279 }
4280 }
4281
4282 return Qnil;
4283 }
4284
4285
4286
4287
4288
4289
4290
4291 DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
4292 doc:
4293
4294
4295
4296
4297
4298
4299
4300 )
4301 (Lisp_Object face, Lisp_Object frame, Lisp_Object character)
4302 {
4303 if (EQ (frame, Qt))
4304 {
4305 Lisp_Object result = Qnil;
4306 Lisp_Object lface = lface_from_face_name (NULL, face, true);
4307
4308 if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
4309 && !EQ (LFACE_WEIGHT (lface), Qnormal))
4310 result = Fcons (Qbold, result);
4311
4312 if (!UNSPECIFIEDP (LFACE_SLANT (lface))
4313 && !EQ (LFACE_SLANT (lface), Qnormal))
4314 result = Fcons (Qitalic, result);
4315
4316 return result;
4317 }
4318 else
4319 {
4320 struct frame *f = decode_live_frame (frame);
4321 int face_id = lookup_named_face (NULL, f, face, true);
4322 struct face *fface = FACE_FROM_ID_OR_NULL (f, face_id);
4323
4324 if (! fface)
4325 return Qnil;
4326 #ifdef HAVE_WINDOW_SYSTEM
4327 if (FRAME_WINDOW_P (f) && !NILP (character))
4328 {
4329 CHECK_CHARACTER (character);
4330 face_id = FACE_FOR_CHAR (f, fface, XFIXNUM (character), -1, Qnil);
4331 fface = FACE_FROM_ID_OR_NULL (f, face_id);
4332 }
4333 return ((fface && fface->font)
4334 ? fface->font->props[FONT_NAME_INDEX]
4335 : Qnil);
4336 #else
4337 return build_string (FRAME_MSDOS_P (f)
4338 ? "ms-dos"
4339 : FRAME_W32_P (f) ? "w32term"
4340 :"tty");
4341 #endif
4342 }
4343 }
4344
4345
4346
4347
4348
4349
4350 static bool
4351 face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
4352 {
4353
4354
4355 if (XTYPE (v1) != XTYPE (v2))
4356 return false;
4357
4358 if (EQ (v1, v2))
4359 return true;
4360
4361 switch (XTYPE (v1))
4362 {
4363 case Lisp_String:
4364 if (SBYTES (v1) != SBYTES (v2))
4365 return false;
4366
4367 return memcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
4368
4369 case_Lisp_Int:
4370 case Lisp_Symbol:
4371 return false;
4372
4373 default:
4374 return !NILP (Fequal (v1, v2));
4375 }
4376 }
4377
4378
4379
4380
4381
4382
4383 static bool
4384 lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
4385 {
4386 int i;
4387 bool equal_p = true;
4388
4389 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
4390 equal_p = face_attr_equal_p (v1[i], v2[i]);
4391
4392 return equal_p;
4393 }
4394
4395
4396 DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
4397 Sinternal_lisp_face_equal_p, 2, 3, 0,
4398 doc:
4399
4400
4401 )
4402 (Lisp_Object face1, Lisp_Object face2, Lisp_Object frame)
4403 {
4404 bool equal_p;
4405 struct frame *f;
4406 Lisp_Object lface1, lface2;
4407
4408
4409
4410
4411
4412 f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
4413
4414 lface1 = lface_from_face_name (f, face1, true);
4415 lface2 = lface_from_face_name (f, face2, true);
4416 equal_p = lface_equal_p (XVECTOR (lface1)->contents,
4417 XVECTOR (lface2)->contents);
4418 return equal_p ? Qt : Qnil;
4419 }
4420
4421
4422 DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
4423 Sinternal_lisp_face_empty_p, 1, 2, 0,
4424 doc:
4425
4426
4427 )
4428 (Lisp_Object face, Lisp_Object frame)
4429 {
4430 struct frame *f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
4431 Lisp_Object lface = lface_from_face_name (f, face, true);
4432 int i;
4433
4434 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
4435 if (!UNSPECIFIEDP (AREF (lface, i)))
4436 break;
4437
4438 return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
4439 }
4440
4441 DEFUN ("frame--face-hash-table", Fframe_face_hash_table, Sframe_face_hash_table,
4442 0, 1, 0,
4443 doc:
4444 )
4445 (Lisp_Object frame)
4446 {
4447 return decode_live_frame (frame)->face_hash_table;
4448 }
4449
4450
4451
4452
4453
4454 static uintptr_t
4455 hash_string_case_insensitive (Lisp_Object string)
4456 {
4457 const unsigned char *s;
4458 uintptr_t hash = 0;
4459 eassert (STRINGP (string));
4460 for (s = SDATA (string); *s; ++s)
4461 hash = (hash << 1) ^ c_tolower (*s);
4462 return hash;
4463 }
4464
4465
4466
4467
4468 static uintptr_t
4469 lface_hash (Lisp_Object *v)
4470 {
4471 return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
4472 ^ hash_string_case_insensitive (v[LFACE_FOUNDRY_INDEX])
4473 ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
4474 ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
4475 ^ XHASH (v[LFACE_WEIGHT_INDEX])
4476 ^ XHASH (v[LFACE_SLANT_INDEX])
4477 ^ XHASH (v[LFACE_SWIDTH_INDEX])
4478 ^ XHASH (v[LFACE_HEIGHT_INDEX]));
4479 }
4480
4481 #ifdef HAVE_WINDOW_SYSTEM
4482
4483
4484
4485
4486
4487
4488 static bool
4489 lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
4490 {
4491 eassert (lface_fully_specified_p (lface1)
4492 && lface_fully_specified_p (lface2));
4493 return (xstrcasecmp (SSDATA (lface1[LFACE_FAMILY_INDEX]),
4494 SSDATA (lface2[LFACE_FAMILY_INDEX])) == 0
4495 && xstrcasecmp (SSDATA (lface1[LFACE_FOUNDRY_INDEX]),
4496 SSDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
4497 && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
4498 && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
4499 && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
4500 && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
4501 && EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
4502 && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
4503 || (STRINGP (lface1[LFACE_FONTSET_INDEX])
4504 && STRINGP (lface2[LFACE_FONTSET_INDEX])
4505 && ! xstrcasecmp (SSDATA (lface1[LFACE_FONTSET_INDEX]),
4506 SSDATA (lface2[LFACE_FONTSET_INDEX]))))
4507 );
4508 }
4509
4510 #endif
4511
4512
4513
4514
4515
4516
4517
4518
4519 static struct face *
4520 make_realized_face (Lisp_Object *attr)
4521 {
4522 enum { off = offsetof (struct face, id) };
4523 struct face *face = xmalloc (sizeof *face);
4524
4525 memcpy (face->lface, attr, sizeof face->lface);
4526 memset (&face->id, 0, sizeof *face - off);
4527 face->ascii_face = face;
4528
4529 return face;
4530 }
4531
4532
4533
4534
4535
4536 static void
4537 free_realized_face (struct frame *f, struct face *face)
4538 {
4539 if (face)
4540 {
4541 #ifdef HAVE_WINDOW_SYSTEM
4542 if (FRAME_WINDOW_P (f))
4543 {
4544
4545 if (face->fontset >= 0 && face == face->ascii_face)
4546 free_face_fontset (f, face);
4547 if (face->gc)
4548 {
4549 block_input ();
4550 if (face->font)
4551 font_done_for_face (f, face);
4552 x_free_gc (f, face->gc);
4553 face->gc = 0;
4554 unblock_input ();
4555 }
4556 #ifdef HAVE_X_WINDOWS
4557 free_face_colors (f, face);
4558 #endif
4559 image_destroy_bitmap (f, face->stipple);
4560 }
4561 #endif
4562
4563 xfree (face);
4564 }
4565 }
4566
4567 #ifdef HAVE_WINDOW_SYSTEM
4568
4569
4570
4571
4572
4573 void
4574 prepare_face_for_display (struct frame *f, struct face *face)
4575 {
4576 Emacs_GC egc;
4577 unsigned long mask;
4578
4579 eassert (FRAME_WINDOW_P (f));
4580
4581 if (face->gc == 0)
4582 {
4583 mask = GCForeground | GCBackground | GCGraphicsExposures;
4584
4585 egc.foreground = face->foreground;
4586 egc.background = face->background;
4587 #ifdef HAVE_X_WINDOWS
4588 egc.graphics_exposures = False;
4589
4590
4591
4592
4593
4594 mask |= GCLineWidth;
4595 egc.line_width = 1;
4596 #endif
4597
4598 block_input ();
4599 #ifdef HAVE_X_WINDOWS
4600 if (face->stipple)
4601 {
4602 egc.fill_style = FillOpaqueStippled;
4603 egc.stipple = image_bitmap_pixmap (f, face->stipple);
4604 mask |= GCFillStyle | GCStipple;
4605 }
4606 #endif
4607 face->gc = x_create_gc (f, mask, &egc);
4608 if (face->font)
4609 font_prepare_for_face (f, face);
4610 unblock_input ();
4611 }
4612 }
4613
4614 #endif
4615
4616
4617
4618 static int
4619 color_distance (Emacs_Color *x, Emacs_Color *y)
4620 {
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631 long long r = x->red - y->red;
4632 long long g = x->green - y->green;
4633 long long b = x->blue - y->blue;
4634 long long r_mean = (x->red + y->red) >> 1;
4635
4636 return (((((2 * 65536 + r_mean) * r * r) >> 16)
4637 + 4 * g * g
4638 + (((2 * 65536 + 65535 - r_mean) * b * b) >> 16))
4639 >> 16);
4640 }
4641
4642
4643 DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 4, 0,
4644 doc:
4645
4646
4647
4648
4649
4650
4651 )
4652 (Lisp_Object color1, Lisp_Object color2, Lisp_Object frame,
4653 Lisp_Object metric)
4654 {
4655 struct frame *f = decode_live_frame (frame);
4656 Emacs_Color cdef1, cdef2;
4657
4658 if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
4659 && !(STRINGP (color1)
4660 && FRAME_TERMINAL (f)->defined_color_hook (f,
4661 SSDATA (color1),
4662 &cdef1,
4663 false,
4664 true)))
4665 signal_error ("Invalid color", color1);
4666 if (!(CONSP (color2) && parse_rgb_list (color2, &cdef2))
4667 && !(STRINGP (color2)
4668 && FRAME_TERMINAL (f)->defined_color_hook (f,
4669 SSDATA (color2),
4670 &cdef2,
4671 false,
4672 true)))
4673 signal_error ("Invalid color", color2);
4674
4675 if (NILP (metric))
4676 return make_fixnum (color_distance (&cdef1, &cdef2));
4677 else
4678 return call2 (metric,
4679 list3i (cdef1.red, cdef1.green, cdef1.blue),
4680 list3i (cdef2.red, cdef2.green, cdef2.blue));
4681 }
4682
4683
4684
4685
4686
4687
4688
4689
4690 static struct face_cache *
4691 make_face_cache (struct frame *f)
4692 {
4693 struct face_cache *c = xmalloc (sizeof *c);
4694
4695 c->buckets = xzalloc (FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets);
4696 c->size = 50;
4697 c->used = 0;
4698 c->faces_by_id = xmalloc (c->size * sizeof *c->faces_by_id);
4699 c->f = f;
4700 c->menu_face_changed_p = menu_face_changed_default;
4701 return c;
4702 }
4703
4704 #ifdef HAVE_WINDOW_SYSTEM
4705
4706
4707
4708
4709
4710 static void
4711 clear_face_gcs (struct face_cache *c)
4712 {
4713 if (c && FRAME_WINDOW_P (c->f))
4714 {
4715 int i;
4716 for (i = BASIC_FACE_ID_SENTINEL; i < c->used; ++i)
4717 {
4718 struct face *face = c->faces_by_id[i];
4719 if (face && face->gc)
4720 {
4721 block_input ();
4722 if (face->font)
4723 font_done_for_face (c->f, face);
4724 x_free_gc (c->f, face->gc);
4725 face->gc = 0;
4726 unblock_input ();
4727 }
4728 }
4729 }
4730 }
4731
4732 #endif
4733
4734
4735
4736
4737
4738
4739 static void
4740 free_realized_faces (struct face_cache *c)
4741 {
4742 if (c && c->used)
4743 {
4744 int i, size;
4745 struct frame *f = c->f;
4746
4747
4748
4749
4750 block_input ();
4751
4752 for (i = 0; i < c->used; ++i)
4753 {
4754 free_realized_face (f, c->faces_by_id[i]);
4755 c->faces_by_id[i] = NULL;
4756 }
4757
4758
4759 forget_escape_and_glyphless_faces ();
4760 c->used = 0;
4761 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4762 memset (c->buckets, 0, size);
4763
4764
4765
4766
4767
4768 if (WINDOWP (f->root_window))
4769 {
4770 clear_current_matrices (f);
4771 fset_redisplay (f);
4772 }
4773
4774 unblock_input ();
4775 }
4776 }
4777
4778
4779
4780
4781
4782
4783 void
4784 free_all_realized_faces (Lisp_Object frame)
4785 {
4786 if (NILP (frame))
4787 {
4788 Lisp_Object rest;
4789 FOR_EACH_FRAME (rest, frame)
4790 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4791 windows_or_buffers_changed = 58;
4792 }
4793 else
4794 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4795 }
4796
4797
4798
4799
4800 static void
4801 free_face_cache (struct face_cache *c)
4802 {
4803 if (c)
4804 {
4805 free_realized_faces (c);
4806 xfree (c->buckets);
4807 xfree (c->faces_by_id);
4808 xfree (c);
4809 }
4810 }
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820 static void
4821 cache_face (struct face_cache *c, struct face *face, uintptr_t hash)
4822 {
4823 int i = hash % FACE_CACHE_BUCKETS_SIZE;
4824
4825 face->hash = hash;
4826
4827 if (face->ascii_face != face)
4828 {
4829 struct face *last = c->buckets[i];
4830 if (last)
4831 {
4832 while (last->next)
4833 last = last->next;
4834 last->next = face;
4835 face->prev = last;
4836 face->next = NULL;
4837 }
4838 else
4839 {
4840 c->buckets[i] = face;
4841 face->prev = face->next = NULL;
4842 }
4843 }
4844 else
4845 {
4846 face->prev = NULL;
4847 face->next = c->buckets[i];
4848 if (face->next)
4849 face->next->prev = face;
4850 c->buckets[i] = face;
4851 }
4852
4853
4854
4855 for (i = 0; i < c->used; ++i)
4856 if (c->faces_by_id[i] == NULL)
4857 break;
4858 face->id = i;
4859
4860 #ifdef GLYPH_DEBUG
4861
4862 {
4863 int j, n;
4864 struct face *face1;
4865
4866 for (j = n = 0; j < FACE_CACHE_BUCKETS_SIZE; ++j)
4867 for (face1 = c->buckets[j]; face1; face1 = face1->next)
4868 if (face1->id == i)
4869 ++n;
4870
4871 eassert (n == 1);
4872 }
4873 #endif
4874
4875
4876 if (i == c->used)
4877 {
4878 if (c->used == c->size)
4879 c->faces_by_id = xpalloc (c->faces_by_id, &c->size, 1, MAX_FACE_ID,
4880 sizeof *c->faces_by_id);
4881 c->used++;
4882 }
4883
4884 c->faces_by_id[i] = face;
4885 }
4886
4887
4888
4889
4890 static void
4891 uncache_face (struct face_cache *c, struct face *face)
4892 {
4893 int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
4894
4895 if (face->prev)
4896 face->prev->next = face->next;
4897 else
4898 c->buckets[i] = face->next;
4899
4900 if (face->next)
4901 face->next->prev = face->prev;
4902
4903 c->faces_by_id[face->id] = NULL;
4904 if (face->id == c->used)
4905 --c->used;
4906 }
4907
4908
4909
4910
4911
4912
4913
4914 static int
4915 lookup_face (struct frame *f, Lisp_Object *attr)
4916 {
4917 struct face_cache *cache = FRAME_FACE_CACHE (f);
4918 struct face *face;
4919
4920 eassert (cache != NULL);
4921 check_lface_attrs (attr);
4922
4923
4924 uintptr_t hash = lface_hash (attr);
4925 int i = hash % FACE_CACHE_BUCKETS_SIZE;
4926
4927 for (face = cache->buckets[i]; face; face = face->next)
4928 {
4929 if (face->ascii_face != face)
4930 {
4931
4932 face = NULL;
4933 break;
4934 }
4935 if (face->hash == hash
4936 && lface_equal_p (face->lface, attr))
4937 break;
4938 }
4939
4940
4941 if (face == NULL)
4942 face = realize_face (cache, attr, -1);
4943
4944 #ifdef GLYPH_DEBUG
4945 eassert (face == FACE_FROM_ID_OR_NULL (f, face->id));
4946 #endif
4947
4948 return face->id;
4949 }
4950
4951 #ifdef HAVE_WINDOW_SYSTEM
4952
4953
4954
4955
4956
4957
4958 int
4959 face_for_font (struct frame *f, Lisp_Object font_object,
4960 struct face *base_face)
4961 {
4962 struct face_cache *cache = FRAME_FACE_CACHE (f);
4963 uintptr_t hash;
4964 int i;
4965 struct face *face;
4966
4967 eassert (cache != NULL);
4968 base_face = base_face->ascii_face;
4969 hash = lface_hash (base_face->lface);
4970 i = hash % FACE_CACHE_BUCKETS_SIZE;
4971
4972 for (face = cache->buckets[i]; face; face = face->next)
4973 {
4974 if (face->ascii_face == face)
4975 continue;
4976 if (face->ascii_face == base_face
4977 && face->font == (NILP (font_object) ? NULL
4978 : XFONT_OBJECT (font_object))
4979 && lface_equal_p (face->lface, base_face->lface))
4980 return face->id;
4981 }
4982
4983
4984 face = realize_non_ascii_face (f, font_object, base_face);
4985 return face->id;
4986 }
4987 #endif
4988
4989
4990
4991
4992
4993
4994
4995 int
4996 lookup_named_face (struct window *w, struct frame *f,
4997 Lisp_Object symbol, bool signal_p)
4998 {
4999 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5000 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
5001 struct face *default_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
5002
5003 if (default_face == NULL)
5004 {
5005 if (!realize_basic_faces (f))
5006 return -1;
5007 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5008 }
5009
5010 if (! get_lface_attributes (w, f, symbol, symbol_attrs, signal_p, 0))
5011 return -1;
5012
5013 memcpy (attrs, default_face->lface, sizeof attrs);
5014
5015
5016 int i;
5017 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
5018 if (EQ (symbol_attrs[i], Qreset))
5019 symbol_attrs[i] = attrs[i];
5020
5021 merge_face_vectors (w, f, symbol_attrs, attrs, 0);
5022
5023 return lookup_face (f, attrs);
5024 }
5025
5026
5027
5028
5029
5030
5031
5032
5033 int
5034 lookup_basic_face (struct window *w, struct frame *f, int face_id)
5035 {
5036 Lisp_Object name, mapping;
5037 int remapped_face_id;
5038
5039 if (NILP (Vface_remapping_alist))
5040 return face_id;
5041
5042 switch (face_id)
5043 {
5044 case DEFAULT_FACE_ID: name = Qdefault; break;
5045 case MODE_LINE_ACTIVE_FACE_ID: name = Qmode_line_active; break;
5046 case MODE_LINE_INACTIVE_FACE_ID: name = Qmode_line_inactive; break;
5047 case HEADER_LINE_FACE_ID: name = Qheader_line; break;
5048 case TAB_LINE_FACE_ID: name = Qtab_line; break;
5049 case TAB_BAR_FACE_ID: name = Qtab_bar; break;
5050 case TOOL_BAR_FACE_ID: name = Qtool_bar; break;
5051 case FRINGE_FACE_ID: name = Qfringe; break;
5052 case SCROLL_BAR_FACE_ID: name = Qscroll_bar; break;
5053 case BORDER_FACE_ID: name = Qborder; break;
5054 case CURSOR_FACE_ID: name = Qcursor; break;
5055 case MOUSE_FACE_ID: name = Qmouse; break;
5056 case MENU_FACE_ID: name = Qmenu; break;
5057 case WINDOW_DIVIDER_FACE_ID: name = Qwindow_divider; break;
5058 case VERTICAL_BORDER_FACE_ID: name = Qvertical_border; break;
5059 case WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID: name = Qwindow_divider_first_pixel; break;
5060 case WINDOW_DIVIDER_LAST_PIXEL_FACE_ID: name = Qwindow_divider_last_pixel; break;
5061 case INTERNAL_BORDER_FACE_ID: name = Qinternal_border; break;
5062 case CHILD_FRAME_BORDER_FACE_ID: name = Qchild_frame_border; break;
5063
5064 default:
5065 emacs_abort ();
5066 }
5067
5068
5069
5070
5071 mapping = assq_no_quit (name, Vface_remapping_alist);
5072 if (NILP (mapping))
5073 return face_id;
5074
5075
5076
5077 remapped_face_id = lookup_named_face (w, f, name, false);
5078 if (remapped_face_id < 0)
5079 return face_id;
5080
5081 return remapped_face_id;
5082 }
5083
5084
5085
5086
5087
5088
5089 int
5090 smaller_face (struct frame *f, int face_id, int steps)
5091 {
5092 #ifdef HAVE_WINDOW_SYSTEM
5093 struct face *face;
5094 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5095 int pt, last_pt, last_height;
5096 int delta;
5097 int new_face_id;
5098 struct face *new_face;
5099
5100
5101 if (FRAME_TERMCAP_P (f))
5102 return face_id;
5103
5104
5105 delta = steps < 0 ? 5 : -5;
5106 steps = eabs (steps);
5107
5108 face = FACE_FROM_ID (f, face_id);
5109 memcpy (attrs, face->lface, sizeof attrs);
5110 pt = last_pt = XFIXNAT (attrs[LFACE_HEIGHT_INDEX]);
5111 new_face_id = face_id;
5112 last_height = FONT_HEIGHT (face->font);
5113
5114 while (steps
5115 && pt + delta > 0
5116
5117 && eabs (last_pt - pt) < 100)
5118 {
5119
5120 pt += delta;
5121 attrs[LFACE_HEIGHT_INDEX] = make_fixnum (pt);
5122 new_face_id = lookup_face (f, attrs);
5123 new_face = FACE_FROM_ID (f, new_face_id);
5124
5125
5126 if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
5127 || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
5128 {
5129 --steps;
5130 last_height = FONT_HEIGHT (new_face->font);
5131 last_pt = pt;
5132 }
5133 }
5134
5135 return new_face_id;
5136
5137 #else
5138
5139 return face_id;
5140
5141 #endif
5142 }
5143
5144
5145
5146
5147
5148 int
5149 face_with_height (struct frame *f, int face_id, int height)
5150 {
5151 #ifdef HAVE_WINDOW_SYSTEM
5152 struct face *face;
5153 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5154
5155 if (FRAME_TERMCAP_P (f)
5156 || height <= 0)
5157 return face_id;
5158
5159 face = FACE_FROM_ID (f, face_id);
5160 memcpy (attrs, face->lface, sizeof attrs);
5161 attrs[LFACE_HEIGHT_INDEX] = make_fixnum (height);
5162 font_clear_prop (attrs, FONT_SIZE_INDEX);
5163 face_id = lookup_face (f, attrs);
5164 #endif
5165
5166 return face_id;
5167 }
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177 int
5178 lookup_derived_face (struct window *w,
5179 struct frame *f, Lisp_Object symbol, int face_id,
5180 bool signal_p)
5181 {
5182 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5183 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
5184 struct face *default_face;
5185
5186 if (!get_lface_attributes (w, f, symbol, symbol_attrs, signal_p, 0))
5187 return -1;
5188
5189 default_face = FACE_FROM_ID (f, face_id);
5190 memcpy (attrs, default_face->lface, sizeof attrs);
5191
5192
5193 int i;
5194 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
5195 if (EQ (symbol_attrs[i], Qreset))
5196 symbol_attrs[i] = attrs[i];
5197
5198 merge_face_vectors (w, f, symbol_attrs, attrs, 0);
5199 return lookup_face (f, attrs);
5200 }
5201
5202 DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
5203 Sface_attributes_as_vector, 1, 1, 0,
5204 doc: )
5205 (Lisp_Object plist)
5206 {
5207 Lisp_Object lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified);
5208 merge_face_ref (NULL, XFRAME (selected_frame),
5209 plist, XVECTOR (lface)->contents,
5210 true, NULL, 0);
5211 return lface;
5212 }
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225 #define TTY_SAME_COLOR_THRESHOLD 10000
5226
5227 #ifdef HAVE_WINDOW_SYSTEM
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239 static bool
5240 gui_supports_face_attributes_p (struct frame *f,
5241 Lisp_Object attrs[LFACE_VECTOR_SIZE],
5242 struct face *def_face)
5243 {
5244 Lisp_Object *def_attrs = def_face->lface;
5245 Lisp_Object lattrs[LFACE_VECTOR_SIZE];
5246
5247
5248 int i;
5249 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
5250 {
5251 if (EQ (attrs[i], Qreset))
5252 lattrs[i] = def_attrs[i];
5253 else
5254 lattrs[i] = attrs[i];
5255 }
5256
5257
5258
5259 if ((!UNSPECIFIEDP (lattrs[LFACE_UNDERLINE_INDEX])
5260 && face_attr_equal_p (lattrs[LFACE_UNDERLINE_INDEX],
5261 def_attrs[LFACE_UNDERLINE_INDEX]))
5262 || (!UNSPECIFIEDP (lattrs[LFACE_INVERSE_INDEX])
5263 && face_attr_equal_p (lattrs[LFACE_INVERSE_INDEX],
5264 def_attrs[LFACE_INVERSE_INDEX]))
5265 || (!UNSPECIFIEDP (lattrs[LFACE_EXTEND_INDEX])
5266 && face_attr_equal_p (lattrs[LFACE_EXTEND_INDEX],
5267 def_attrs[LFACE_EXTEND_INDEX]))
5268 || (!UNSPECIFIEDP (lattrs[LFACE_FOREGROUND_INDEX])
5269 && face_attr_equal_p (lattrs[LFACE_FOREGROUND_INDEX],
5270 def_attrs[LFACE_FOREGROUND_INDEX]))
5271 || (!UNSPECIFIEDP (lattrs[LFACE_DISTANT_FOREGROUND_INDEX])
5272 && face_attr_equal_p (lattrs[LFACE_DISTANT_FOREGROUND_INDEX],
5273 def_attrs[LFACE_DISTANT_FOREGROUND_INDEX]))
5274 || (!UNSPECIFIEDP (lattrs[LFACE_BACKGROUND_INDEX])
5275 && face_attr_equal_p (lattrs[LFACE_BACKGROUND_INDEX],
5276 def_attrs[LFACE_BACKGROUND_INDEX]))
5277 || (!UNSPECIFIEDP (lattrs[LFACE_STIPPLE_INDEX])
5278 && face_attr_equal_p (lattrs[LFACE_STIPPLE_INDEX],
5279 def_attrs[LFACE_STIPPLE_INDEX]))
5280 || (!UNSPECIFIEDP (lattrs[LFACE_OVERLINE_INDEX])
5281 && face_attr_equal_p (lattrs[LFACE_OVERLINE_INDEX],
5282 def_attrs[LFACE_OVERLINE_INDEX]))
5283 || (!UNSPECIFIEDP (lattrs[LFACE_STRIKE_THROUGH_INDEX])
5284 && face_attr_equal_p (lattrs[LFACE_STRIKE_THROUGH_INDEX],
5285 def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
5286 || (!UNSPECIFIEDP (lattrs[LFACE_BOX_INDEX])
5287 && face_attr_equal_p (lattrs[LFACE_BOX_INDEX],
5288 def_attrs[LFACE_BOX_INDEX])))
5289 return false;
5290
5291
5292
5293 if (!UNSPECIFIEDP (lattrs[LFACE_FAMILY_INDEX])
5294 || !UNSPECIFIEDP (lattrs[LFACE_FOUNDRY_INDEX])
5295 || !UNSPECIFIEDP (lattrs[LFACE_HEIGHT_INDEX])
5296 || !UNSPECIFIEDP (lattrs[LFACE_WEIGHT_INDEX])
5297 || !UNSPECIFIEDP (lattrs[LFACE_SLANT_INDEX])
5298 || !UNSPECIFIEDP (lattrs[LFACE_SWIDTH_INDEX]))
5299 {
5300 int face_id;
5301 struct face *face;
5302 Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
5303 int i;
5304
5305 memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
5306
5307 merge_face_vectors (NULL, f, attrs, merged_attrs, 0);
5308
5309 face_id = lookup_face (f, merged_attrs);
5310 face = FACE_FROM_ID_OR_NULL (f, face_id);
5311
5312 if (! face)
5313 error ("Cannot make face");
5314
5315
5316
5317 if (face->font == def_face->font
5318 || ! face->font)
5319 return false;
5320 for (i = FONT_TYPE_INDEX; i <= FONT_SIZE_INDEX; i++)
5321 if (! EQ (face->font->props[i], def_face->font->props[i]))
5322 {
5323 Lisp_Object s1, s2;
5324
5325 if (i < FONT_FOUNDRY_INDEX || i > FONT_REGISTRY_INDEX
5326 || face->font->driver->case_sensitive)
5327 return true;
5328 s1 = SYMBOL_NAME (face->font->props[i]);
5329 s2 = SYMBOL_NAME (def_face->font->props[i]);
5330 if (! BASE_EQ (Fcompare_strings (s1, make_fixnum (0), Qnil,
5331 s2, make_fixnum (0), Qnil, Qt),
5332 Qt))
5333 return true;
5334 }
5335 return false;
5336 }
5337
5338
5339 return true;
5340 }
5341
5342 #endif
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360 static bool
5361 tty_supports_face_attributes_p (struct frame *f,
5362 Lisp_Object attrs[LFACE_VECTOR_SIZE],
5363 struct face *def_face)
5364 {
5365 int weight, slant;
5366 Lisp_Object val, fg, bg;
5367 Emacs_Color fg_tty_color, fg_std_color;
5368 Emacs_Color bg_tty_color, bg_std_color;
5369 unsigned test_caps = 0;
5370 Lisp_Object *def_attrs = def_face->lface;
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
5381 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
5382 || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
5383 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
5384 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
5385 || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
5386 || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]))
5387 return false;
5388
5389
5390
5391
5392 val = attrs[LFACE_WEIGHT_INDEX];
5393 if (!UNSPECIFIEDP (val)
5394 && (weight = FONT_WEIGHT_NAME_NUMERIC (val), weight >= 0))
5395 {
5396 int def_weight = FONT_WEIGHT_NAME_NUMERIC (def_attrs[LFACE_WEIGHT_INDEX]);
5397
5398 if (weight > 100)
5399 {
5400 if (def_weight > 100)
5401 return false;
5402 test_caps = TTY_CAP_BOLD;
5403 }
5404 else if (weight < 100)
5405 {
5406 if (def_weight < 100)
5407 return false;
5408 test_caps = TTY_CAP_DIM;
5409 }
5410 else if (def_weight == 100)
5411 return false;
5412 }
5413
5414
5415 val = attrs[LFACE_SLANT_INDEX];
5416 if (!UNSPECIFIEDP (val)
5417 && (slant = FONT_SLANT_NAME_NUMERIC (val), slant >= 0))
5418 {
5419 int def_slant = FONT_SLANT_NAME_NUMERIC (def_attrs[LFACE_SLANT_INDEX]);
5420 if (slant == 100 || slant == def_slant)
5421 return false;
5422 else
5423 test_caps |= TTY_CAP_ITALIC;
5424 }
5425
5426
5427 val = attrs[LFACE_UNDERLINE_INDEX];
5428 if (!UNSPECIFIEDP (val))
5429 {
5430 if (STRINGP (val))
5431 return false;
5432 else if (EQ (CAR_SAFE (val), QCstyle) && EQ (CAR_SAFE (CDR_SAFE (val)), Qwave))
5433 return false;
5434 else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
5435 return false;
5436 else
5437 test_caps |= TTY_CAP_UNDERLINE;
5438 }
5439
5440
5441 val = attrs[LFACE_INVERSE_INDEX];
5442 if (!UNSPECIFIEDP (val))
5443 {
5444 if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
5445 return false;
5446 else
5447 test_caps |= TTY_CAP_INVERSE;
5448 }
5449
5450
5451 val = attrs[LFACE_STRIKE_THROUGH_INDEX];
5452 if (!UNSPECIFIEDP (val))
5453 {
5454 if (face_attr_equal_p (val, def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
5455 return false;
5456 else
5457 test_caps |= TTY_CAP_STRIKE_THROUGH;
5458 }
5459
5460
5461
5462
5463 fg = attrs[LFACE_FOREGROUND_INDEX];
5464 if (STRINGP (fg))
5465 {
5466 Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
5467
5468 if (face_attr_equal_p (fg, def_fg))
5469 return false;
5470 else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
5471 return false;
5472 else if (color_distance (&fg_tty_color, &fg_std_color)
5473 > TTY_SAME_COLOR_THRESHOLD)
5474 return false;
5475 else
5476
5477 {
5478 Emacs_Color def_fg_color;
5479 if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
5480 && (color_distance (&fg_tty_color, &def_fg_color)
5481 <= TTY_SAME_COLOR_THRESHOLD))
5482 return false;
5483 }
5484 }
5485
5486
5487 bg = attrs[LFACE_BACKGROUND_INDEX];
5488 if (STRINGP (bg))
5489 {
5490 Lisp_Object def_bg = def_attrs[LFACE_BACKGROUND_INDEX];
5491
5492 if (face_attr_equal_p (bg, def_bg))
5493 return false;
5494 else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5495 return false;
5496 else if (color_distance (&bg_tty_color, &bg_std_color)
5497 > TTY_SAME_COLOR_THRESHOLD)
5498 return false;
5499 else
5500
5501 {
5502 Emacs_Color def_bg_color;
5503 if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
5504 && (color_distance (&bg_tty_color, &def_bg_color)
5505 <= TTY_SAME_COLOR_THRESHOLD))
5506 return false;
5507 }
5508 }
5509
5510
5511
5512
5513
5514 if (STRINGP (fg) && STRINGP (bg))
5515 {
5516 int delta_delta
5517 = (color_distance (&fg_std_color, &bg_std_color)
5518 - color_distance (&fg_tty_color, &bg_tty_color));
5519 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5520 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5521 return false;
5522 }
5523
5524
5525
5526
5527 return tty_capable_p (FRAME_TTY (f), test_caps);
5528 }
5529
5530
5531 DEFUN ("display-supports-face-attributes-p",
5532 Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
5533 1, 2, 0,
5534 doc:
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553 )
5554 (Lisp_Object attributes, Lisp_Object display)
5555 {
5556 bool supports = false;
5557 int i;
5558 Lisp_Object frame;
5559 struct frame *f;
5560 struct face *def_face;
5561 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5562
5563 if (noninteractive || !initialized)
5564
5565
5566
5567 return Qnil;
5568
5569 if (NILP (display))
5570 frame = selected_frame;
5571 else if (FRAMEP (display))
5572 frame = display;
5573 else
5574 {
5575
5576 Lisp_Object tail;
5577
5578 frame = Qnil;
5579 FOR_EACH_FRAME (tail, frame)
5580 if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
5581 XFRAME (frame)->param_alist)),
5582 display)))
5583 break;
5584 }
5585
5586 CHECK_LIVE_FRAME (frame);
5587 f = XFRAME (frame);
5588
5589 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
5590 attrs[i] = Qunspecified;
5591 merge_face_ref (NULL, f, attributes, attrs, true, NULL, 0);
5592
5593 def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
5594 if (def_face == NULL)
5595 {
5596 if (! realize_basic_faces (f))
5597 error ("Cannot realize default face");
5598 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5599 }
5600
5601
5602 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
5603 supports = tty_supports_face_attributes_p (f, attrs, def_face);
5604 #ifdef HAVE_WINDOW_SYSTEM
5605 else
5606 supports = gui_supports_face_attributes_p (f, attrs, def_face);
5607 #endif
5608
5609 return supports ? Qt : Qnil;
5610 }
5611
5612
5613
5614
5615
5616
5617 DEFUN ("internal-set-font-selection-order",
5618 Finternal_set_font_selection_order,
5619 Sinternal_set_font_selection_order, 1, 1, 0,
5620 doc:
5621
5622
5623
5624
5625
5626 )
5627 (Lisp_Object order)
5628 {
5629 Lisp_Object list;
5630 int i;
5631 int indices[ARRAYELTS (font_sort_order)];
5632
5633 CHECK_LIST (order);
5634 memset (indices, 0, sizeof indices);
5635 i = 0;
5636
5637 for (list = order;
5638 CONSP (list) && i < ARRAYELTS (indices);
5639 list = XCDR (list), ++i)
5640 {
5641 Lisp_Object attr = XCAR (list);
5642 int xlfd;
5643
5644 if (EQ (attr, QCwidth))
5645 xlfd = XLFD_SWIDTH;
5646 else if (EQ (attr, QCheight))
5647 xlfd = XLFD_POINT_SIZE;
5648 else if (EQ (attr, QCweight))
5649 xlfd = XLFD_WEIGHT;
5650 else if (EQ (attr, QCslant))
5651 xlfd = XLFD_SLANT;
5652 else
5653 break;
5654
5655 if (indices[i] != 0)
5656 break;
5657 indices[i] = xlfd;
5658 }
5659
5660 if (!NILP (list) || i != ARRAYELTS (indices))
5661 signal_error ("Invalid font sort order", order);
5662 for (i = 0; i < ARRAYELTS (font_sort_order); ++i)
5663 if (indices[i] == 0)
5664 signal_error ("Invalid font sort order", order);
5665
5666 if (memcmp (indices, font_sort_order, sizeof indices) != 0)
5667 {
5668 memcpy (font_sort_order, indices, sizeof font_sort_order);
5669 free_all_realized_faces (Qnil);
5670 }
5671
5672 font_update_sort_order (font_sort_order);
5673
5674 return Qnil;
5675 }
5676
5677
5678 DEFUN ("internal-set-alternative-font-family-alist",
5679 Finternal_set_alternative_font_family_alist,
5680 Sinternal_set_alternative_font_family_alist, 1, 1, 0,
5681 doc:
5682
5683
5684 )
5685 (Lisp_Object alist)
5686 {
5687 Lisp_Object entry, tail, tail2;
5688
5689 CHECK_LIST (alist);
5690 alist = Fcopy_sequence (alist);
5691 for (tail = alist; CONSP (tail); tail = XCDR (tail))
5692 {
5693 entry = XCAR (tail);
5694 CHECK_LIST (entry);
5695 entry = Fcopy_sequence (entry);
5696 XSETCAR (tail, entry);
5697 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5698 XSETCAR (tail2, Fintern (XCAR (tail2), Qnil));
5699 }
5700
5701 Vface_alternative_font_family_alist = alist;
5702 free_all_realized_faces (Qnil);
5703 return alist;
5704 }
5705
5706
5707 DEFUN ("internal-set-alternative-font-registry-alist",
5708 Finternal_set_alternative_font_registry_alist,
5709 Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
5710 doc:
5711
5712
5713 )
5714 (Lisp_Object alist)
5715 {
5716 Lisp_Object entry, tail, tail2;
5717
5718 CHECK_LIST (alist);
5719 alist = Fcopy_sequence (alist);
5720 for (tail = alist; CONSP (tail); tail = XCDR (tail))
5721 {
5722 entry = XCAR (tail);
5723 CHECK_LIST (entry);
5724 entry = Fcopy_sequence (entry);
5725 XSETCAR (tail, entry);
5726 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5727 XSETCAR (tail2, Fdowncase (XCAR (tail2)));
5728 }
5729 Vface_alternative_font_registry_alist = alist;
5730 free_all_realized_faces (Qnil);
5731 return alist;
5732 }
5733
5734
5735 #ifdef HAVE_WINDOW_SYSTEM
5736
5737
5738
5739
5740
5741 static int
5742 face_fontset (Lisp_Object attrs[LFACE_VECTOR_SIZE])
5743 {
5744 Lisp_Object name;
5745
5746 name = attrs[LFACE_FONTSET_INDEX];
5747 if (!STRINGP (name))
5748 return -1;
5749 return fs_query_fontset (name, 0);
5750 }
5751
5752 #endif
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764 static bool
5765 realize_basic_faces (struct frame *f)
5766 {
5767 bool success_p = false;
5768
5769
5770
5771 block_input ();
5772
5773 if (realize_default_face (f))
5774 {
5775 realize_named_face (f, Qmode_line_active, MODE_LINE_ACTIVE_FACE_ID);
5776 realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
5777 realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
5778 realize_named_face (f, Qfringe, FRINGE_FACE_ID);
5779 realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
5780 realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
5781 realize_named_face (f, Qborder, BORDER_FACE_ID);
5782 realize_named_face (f, Qcursor, CURSOR_FACE_ID);
5783 realize_named_face (f, Qmouse, MOUSE_FACE_ID);
5784 realize_named_face (f, Qmenu, MENU_FACE_ID);
5785 realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
5786 realize_named_face (f, Qwindow_divider, WINDOW_DIVIDER_FACE_ID);
5787 realize_named_face (f, Qwindow_divider_first_pixel,
5788 WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
5789 realize_named_face (f, Qwindow_divider_last_pixel,
5790 WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
5791 realize_named_face (f, Qinternal_border, INTERNAL_BORDER_FACE_ID);
5792 realize_named_face (f, Qchild_frame_border, CHILD_FRAME_BORDER_FACE_ID);
5793 realize_named_face (f, Qtab_bar, TAB_BAR_FACE_ID);
5794 realize_named_face (f, Qtab_line, TAB_LINE_FACE_ID);
5795
5796
5797 if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
5798 {
5799 FRAME_FACE_CACHE (f)->menu_face_changed_p = false;
5800 #ifdef USE_X_TOOLKIT
5801 if (FRAME_WINDOW_P (f))
5802 x_update_menu_appearance (f);
5803 #endif
5804 }
5805
5806 success_p = true;
5807 }
5808
5809 unblock_input ();
5810 return success_p;
5811 }
5812
5813
5814
5815
5816
5817
5818 static bool
5819 realize_default_face (struct frame *f)
5820 {
5821 struct face_cache *c = FRAME_FACE_CACHE (f);
5822 Lisp_Object lface;
5823 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5824
5825
5826 lface = lface_from_face_name (f, Qdefault, false);
5827 if (NILP (lface))
5828 {
5829 Lisp_Object frame;
5830 XSETFRAME (frame, f);
5831 lface = Finternal_make_lisp_face (Qdefault, frame);
5832 }
5833
5834 #ifdef HAVE_WINDOW_SYSTEM
5835 if (FRAME_WINDOW_P (f))
5836 {
5837 Lisp_Object font_object;
5838
5839 XSETFONT (font_object, FRAME_FONT (f));
5840 set_lface_from_font (f, lface, font_object, f->default_face_done_p);
5841 ASET (lface, LFACE_FONTSET_INDEX, fontset_name (FRAME_FONTSET (f)));
5842 f->default_face_done_p = true;
5843 }
5844 #endif
5845
5846 if (!FRAME_WINDOW_P (f))
5847 {
5848 ASET (lface, LFACE_FAMILY_INDEX, build_string ("default"));
5849 ASET (lface, LFACE_FOUNDRY_INDEX, LFACE_FAMILY (lface));
5850 ASET (lface, LFACE_SWIDTH_INDEX, Qnormal);
5851 ASET (lface, LFACE_HEIGHT_INDEX, make_fixnum (1));
5852 if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
5853 ASET (lface, LFACE_WEIGHT_INDEX, Qnormal);
5854 if (UNSPECIFIEDP (LFACE_SLANT (lface)))
5855 ASET (lface, LFACE_SLANT_INDEX, Qnormal);
5856 if (UNSPECIFIEDP (LFACE_FONTSET (lface)))
5857 ASET (lface, LFACE_FONTSET_INDEX, Qnil);
5858 }
5859
5860 if (UNSPECIFIEDP (LFACE_EXTEND (lface)))
5861 ASET (lface, LFACE_EXTEND_INDEX, Qnil);
5862
5863 if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
5864 ASET (lface, LFACE_UNDERLINE_INDEX, Qnil);
5865
5866 if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
5867 ASET (lface, LFACE_OVERLINE_INDEX, Qnil);
5868
5869 if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
5870 ASET (lface, LFACE_STRIKE_THROUGH_INDEX, Qnil);
5871
5872 if (UNSPECIFIEDP (LFACE_BOX (lface)))
5873 ASET (lface, LFACE_BOX_INDEX, Qnil);
5874
5875 if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
5876 ASET (lface, LFACE_INVERSE_INDEX, Qnil);
5877
5878 if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
5879 {
5880
5881
5882 Lisp_Object color = Fassq (Qforeground_color, f->param_alist);
5883
5884 if (CONSP (color) && STRINGP (XCDR (color)))
5885 ASET (lface, LFACE_FOREGROUND_INDEX, XCDR (color));
5886 else if (FRAME_WINDOW_P (f))
5887 return false;
5888 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
5889 ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg));
5890 else
5891 emacs_abort ();
5892 }
5893
5894 if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
5895 {
5896
5897
5898 Lisp_Object color = Fassq (Qbackground_color, f->param_alist);
5899 if (CONSP (color) && STRINGP (XCDR (color)))
5900 ASET (lface, LFACE_BACKGROUND_INDEX, XCDR (color));
5901 else if (FRAME_WINDOW_P (f))
5902 return false;
5903 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
5904 ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg));
5905 else
5906 emacs_abort ();
5907 }
5908
5909 if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
5910 ASET (lface, LFACE_STIPPLE_INDEX, Qnil);
5911
5912
5913 eassert (lface_fully_specified_p (XVECTOR (lface)->contents));
5914 check_lface (lface);
5915 memcpy (attrs, xvector_contents (lface), sizeof attrs);
5916 struct face *face = realize_face (c, attrs, DEFAULT_FACE_ID);
5917
5918 #ifndef HAVE_WINDOW_SYSTEM
5919 (void) face;
5920 #else
5921 if (FRAME_X_P (f) && face->font != FRAME_FONT (f))
5922 {
5923
5924
5925 if (!face->font)
5926 return false;
5927
5928
5929
5930
5931
5932 gui_set_font (f, LFACE_FONT (lface), Qnil);
5933 }
5934 #endif
5935 return true;
5936 }
5937
5938
5939
5940
5941
5942
5943 static void
5944 realize_named_face (struct frame *f, Lisp_Object symbol, int id)
5945 {
5946 struct face_cache *c = FRAME_FACE_CACHE (f);
5947 Lisp_Object lface = lface_from_face_name (f, symbol, false);
5948 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5949 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
5950
5951
5952 get_lface_attributes_no_remap (f, Qdefault, attrs, true);
5953 check_lface_attrs (attrs);
5954 eassert (lface_fully_specified_p (attrs));
5955
5956
5957 if (NILP (lface))
5958 {
5959 Lisp_Object frame;
5960 XSETFRAME (frame, f);
5961 lface = Finternal_make_lisp_face (symbol, frame);
5962 }
5963
5964
5965 get_lface_attributes_no_remap (f, symbol, symbol_attrs, true);
5966
5967
5968
5969 int i;
5970 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
5971 if (EQ (symbol_attrs[i], Qreset))
5972 symbol_attrs[i] = attrs[i];
5973
5974 merge_face_vectors (NULL, f, symbol_attrs, attrs, 0);
5975
5976
5977 realize_face (c, attrs, id);
5978 }
5979
5980
5981
5982
5983
5984
5985
5986 static struct face *
5987 realize_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE],
5988 int former_face_id)
5989 {
5990 struct face *face;
5991
5992
5993 eassert (cache != NULL);
5994 check_lface_attrs (attrs);
5995
5996 if (former_face_id >= 0 && cache->used > former_face_id)
5997 {
5998
5999 struct face *former_face = cache->faces_by_id[former_face_id];
6000 uncache_face (cache, former_face);
6001 free_realized_face (cache->f, former_face);
6002 SET_FRAME_GARBAGED (cache->f);
6003 }
6004
6005 if (FRAME_WINDOW_P (cache->f))
6006 face = realize_gui_face (cache, attrs);
6007 else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
6008 face = realize_tty_face (cache, attrs);
6009 else if (FRAME_INITIAL_P (cache->f))
6010 {
6011
6012 face = make_realized_face (attrs);
6013 }
6014 else
6015 emacs_abort ();
6016
6017
6018 cache_face (cache, face, lface_hash (attrs));
6019 return face;
6020 }
6021
6022
6023 #ifdef HAVE_WINDOW_SYSTEM
6024
6025
6026
6027
6028
6029 static struct face *
6030 realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
6031 struct face *base_face)
6032 {
6033 struct face_cache *cache = FRAME_FACE_CACHE (f);
6034 struct face *face;
6035
6036 face = xmalloc (sizeof *face);
6037 *face = *base_face;
6038 face->gc = 0;
6039 face->overstrike
6040 = (! NILP (font_object)
6041 && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100
6042 && FONT_WEIGHT_NUMERIC (font_object) <= 100);
6043
6044
6045 face->colors_copied_bitwise_p = true;
6046 face->font = NILP (font_object) ? NULL : XFONT_OBJECT (font_object);
6047 face->gc = 0;
6048
6049 cache_face (cache, face, face->hash);
6050
6051 return face;
6052 }
6053
6054
6055
6056
6057 static void
6058 font_maybe_unset_attribute (Lisp_Object font_object,
6059 enum font_property_index index, Lisp_Object symbol)
6060 {
6061 Lisp_Object tail = Vface_font_lax_matched_attributes;
6062
6063 eassert (CONSP (tail));
6064
6065 FOR_EACH_TAIL_SAFE (tail)
6066 {
6067 if (EQ (XCAR (tail), symbol))
6068 ASET (font_object, index, Qnil);
6069 }
6070 }
6071 #endif
6072
6073
6074
6075
6076
6077
6078
6079
6080 static struct face *
6081 realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
6082 {
6083 struct face *face = NULL;
6084 #ifdef HAVE_WINDOW_SYSTEM
6085 struct face *default_face;
6086 struct frame *f;
6087 Lisp_Object stipple, underline, overline, strike_through, box;
6088
6089 eassert (FRAME_WINDOW_P (cache->f));
6090
6091
6092 face = make_realized_face (attrs);
6093 face->ascii_face = face;
6094
6095 f = cache->f;
6096
6097
6098
6099 default_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
6100 if (default_face
6101 && lface_same_font_attributes_p (default_face->lface, attrs))
6102 {
6103 face->font = default_face->font;
6104 face->fontset
6105 = make_fontset_for_ascii_face (f, default_face->fontset, face);
6106 }
6107 else
6108 {
6109
6110
6111
6112
6113
6114
6115 int fontset = face_fontset (attrs);
6116
6117
6118
6119
6120
6121 if (fontset == -1)
6122 {
6123 if (default_face)
6124 fontset = default_face->fontset;
6125 if (fontset == -1)
6126 emacs_abort ();
6127 }
6128 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
6129 {
6130 Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]);
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143 if (EQ (Vface_font_lax_matched_attributes, Qt))
6144 {
6145
6146
6147
6148 ASET (spec, FONT_WEIGHT_INDEX, Qnil);
6149 ASET (spec, FONT_SLANT_INDEX, Qnil);
6150 ASET (spec, FONT_WIDTH_INDEX, Qnil);
6151 }
6152 else if (!NILP (Vface_font_lax_matched_attributes))
6153 {
6154
6155
6156 font_maybe_unset_attribute (spec, FONT_WEIGHT_INDEX, QCweight);
6157 font_maybe_unset_attribute (spec, FONT_SLANT_INDEX, QCslant);
6158 font_maybe_unset_attribute (spec, FONT_WIDTH_INDEX, QCwidth);
6159 font_maybe_unset_attribute (spec, FONT_FAMILY_INDEX, QCfamily);
6160 font_maybe_unset_attribute (spec, FONT_FOUNDRY_INDEX, QCfoundry);
6161 font_maybe_unset_attribute (spec, FONT_REGISTRY_INDEX, QCregistry);
6162 font_maybe_unset_attribute (spec, FONT_ADSTYLE_INDEX, QCadstyle);
6163 font_maybe_unset_attribute (spec, FONT_SIZE_INDEX, QCsize);
6164 font_maybe_unset_attribute (spec, FONT_DPI_INDEX, QCdpi);
6165 font_maybe_unset_attribute (spec, FONT_SPACING_INDEX, QCspacing);
6166 font_maybe_unset_attribute (spec, FONT_AVGWIDTH_INDEX, QCavgwidth);
6167 }
6168
6169 attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec);
6170 }
6171 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
6172 {
6173 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
6174 face->fontset = make_fontset_for_ascii_face (f, fontset, face);
6175 }
6176 else
6177 {
6178 face->font = NULL;
6179 face->fontset = -1;
6180 }
6181 }
6182
6183 if (face->font
6184 && FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]) > 100
6185 && FONT_WEIGHT_NUMERIC (attrs[LFACE_FONT_INDEX]) <= 100)
6186 face->overstrike = true;
6187
6188
6189
6190 load_face_colors (f, face, attrs);
6191
6192
6193 box = attrs[LFACE_BOX_INDEX];
6194 if (STRINGP (box))
6195 {
6196
6197
6198 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
6199 LFACE_BOX_INDEX);
6200 face->box = FACE_SIMPLE_BOX;
6201 face->box_vertical_line_width = face->box_horizontal_line_width = 1;
6202 }
6203 else if (FIXNUMP (box))
6204 {
6205
6206
6207 eassert (XFIXNUM (box) != 0);
6208 face->box = FACE_SIMPLE_BOX;
6209 face->box_vertical_line_width = eabs(XFIXNUM (box));
6210 face->box_horizontal_line_width = XFIXNUM (box);
6211 face->box_color = face->foreground;
6212 face->box_color_defaulted_p = true;
6213 }
6214 else if (CONSP (box) && FIXNUMP (XCAR (box)) && FIXNUMP (XCDR (box)))
6215 {
6216
6217 face->box = FACE_SIMPLE_BOX;
6218 face->box_color = face->foreground;
6219 face->box_color_defaulted_p = true;
6220 face->box_vertical_line_width = XFIXNUM (XCAR (box));
6221 face->box_horizontal_line_width = XFIXNUM (XCDR (box));
6222 }
6223 else if (CONSP (box))
6224 {
6225 bool set_color = false;
6226
6227
6228
6229 face->box = FACE_SIMPLE_BOX;
6230 face->box_color = face->foreground;
6231 face->box_color_defaulted_p = true;
6232 face->box_vertical_line_width = face->box_horizontal_line_width = 1;
6233
6234 while (CONSP (box))
6235 {
6236 Lisp_Object keyword, value;
6237
6238 keyword = XCAR (box);
6239 box = XCDR (box);
6240
6241 if (!CONSP (box))
6242 break;
6243 value = XCAR (box);
6244 box = XCDR (box);
6245
6246 if (EQ (keyword, QCline_width))
6247 {
6248 if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value))) {
6249 face->box_vertical_line_width = XFIXNUM (XCAR (value));
6250 face->box_horizontal_line_width = XFIXNUM (XCDR (value));
6251 }
6252 else if (FIXNUMP (value) && XFIXNUM (value) != 0) {
6253 face->box_vertical_line_width = eabs (XFIXNUM (value));
6254 face->box_horizontal_line_width = XFIXNUM (value);
6255 }
6256 }
6257 else if (EQ (keyword, QCcolor))
6258 {
6259 if (STRINGP (value))
6260 {
6261 face->box_color = load_color (f, face, value,
6262 LFACE_BOX_INDEX);
6263 face->use_box_color_for_shadows_p = true;
6264 set_color = true;
6265 }
6266 }
6267 else if (EQ (keyword, QCstyle))
6268 {
6269 if (EQ (value, Qreleased_button))
6270 face->box = FACE_RAISED_BOX;
6271 else if (EQ (value, Qpressed_button))
6272 face->box = FACE_SUNKEN_BOX;
6273 else if (EQ (value, Qflat_button))
6274 {
6275 face->box = FACE_SIMPLE_BOX;
6276
6277 if (!set_color)
6278 face->box_color = face->background;
6279 }
6280 }
6281 }
6282 }
6283
6284
6285
6286 underline = attrs[LFACE_UNDERLINE_INDEX];
6287 if (EQ (underline, Qt))
6288 {
6289
6290 face->underline = FACE_UNDER_LINE;
6291 face->underline_defaulted_p = true;
6292 face->underline_color = 0;
6293 face->underline_at_descent_line_p = false;
6294 face->underline_pixels_above_descent_line = 0;
6295 }
6296 else if (STRINGP (underline))
6297 {
6298
6299 face->underline = FACE_UNDER_LINE;
6300 face->underline_defaulted_p = false;
6301 face->underline_color
6302 = load_color (f, face, underline,
6303 LFACE_UNDERLINE_INDEX);
6304 face->underline_at_descent_line_p = false;
6305 face->underline_pixels_above_descent_line = 0;
6306 }
6307 else if (NILP (underline))
6308 {
6309 face->underline = FACE_NO_UNDERLINE;
6310 face->underline_defaulted_p = false;
6311 face->underline_color = 0;
6312 face->underline_at_descent_line_p = false;
6313 face->underline_pixels_above_descent_line = 0;
6314 }
6315 else if (CONSP (underline))
6316 {
6317
6318
6319 face->underline = FACE_UNDER_LINE;
6320 face->underline_color = 0;
6321 face->underline_defaulted_p = true;
6322 face->underline_at_descent_line_p = false;
6323 face->underline_pixels_above_descent_line = 0;
6324
6325
6326
6327 while (CONSP (underline))
6328 {
6329 Lisp_Object keyword, value;
6330
6331 keyword = XCAR (underline);
6332 underline = XCDR (underline);
6333
6334 if (!CONSP (underline))
6335 break;
6336 value = XCAR (underline);
6337 underline = XCDR (underline);
6338
6339 if (EQ (keyword, QCcolor))
6340 {
6341 if (EQ (value, Qforeground_color))
6342 {
6343 face->underline_defaulted_p = true;
6344 face->underline_color = 0;
6345 }
6346 else if (STRINGP (value))
6347 {
6348 face->underline_defaulted_p = false;
6349 face->underline_color = load_color (f, face, value,
6350 LFACE_UNDERLINE_INDEX);
6351 }
6352 }
6353 else if (EQ (keyword, QCstyle))
6354 {
6355 if (EQ (value, Qline))
6356 face->underline = FACE_UNDER_LINE;
6357 else if (EQ (value, Qwave))
6358 face->underline = FACE_UNDER_WAVE;
6359 }
6360 else if (EQ (keyword, QCposition))
6361 {
6362 face->underline_at_descent_line_p = !NILP (value);
6363
6364 if (FIXNATP (value))
6365 face->underline_pixels_above_descent_line = XFIXNAT (value);
6366 }
6367 }
6368 }
6369
6370 overline = attrs[LFACE_OVERLINE_INDEX];
6371 if (STRINGP (overline))
6372 {
6373 face->overline_color
6374 = load_color (f, face, attrs[LFACE_OVERLINE_INDEX],
6375 LFACE_OVERLINE_INDEX);
6376 face->overline_p = true;
6377 }
6378 else if (EQ (overline, Qt))
6379 {
6380 face->overline_color = face->foreground;
6381 face->overline_color_defaulted_p = true;
6382 face->overline_p = true;
6383 }
6384
6385 strike_through = attrs[LFACE_STRIKE_THROUGH_INDEX];
6386 if (STRINGP (strike_through))
6387 {
6388 face->strike_through_color
6389 = load_color (f, face, attrs[LFACE_STRIKE_THROUGH_INDEX],
6390 LFACE_STRIKE_THROUGH_INDEX);
6391 face->strike_through_p = true;
6392 }
6393 else if (EQ (strike_through, Qt))
6394 {
6395 face->strike_through_color = face->foreground;
6396 face->strike_through_color_defaulted_p = true;
6397 face->strike_through_p = true;
6398 }
6399
6400 stipple = attrs[LFACE_STIPPLE_INDEX];
6401 if (!NILP (stipple))
6402 face->stipple = load_pixmap (f, stipple);
6403 #endif
6404
6405 return face;
6406 }
6407
6408
6409
6410
6411
6412
6413
6414 static void
6415 map_tty_color (struct frame *f, struct face *face,
6416 enum lface_attribute_index idx, bool *defaulted)
6417 {
6418 Lisp_Object frame, color, def;
6419 bool foreground_p = idx == LFACE_FOREGROUND_INDEX;
6420 unsigned long default_pixel =
6421 foreground_p ? FACE_TTY_DEFAULT_FG_COLOR : FACE_TTY_DEFAULT_BG_COLOR;
6422 unsigned long pixel = default_pixel;
6423 #ifdef MSDOS
6424 unsigned long default_other_pixel =
6425 foreground_p ? FACE_TTY_DEFAULT_BG_COLOR : FACE_TTY_DEFAULT_FG_COLOR;
6426 #endif
6427
6428 eassert (idx == LFACE_FOREGROUND_INDEX || idx == LFACE_BACKGROUND_INDEX);
6429
6430 XSETFRAME (frame, f);
6431 color = face->lface[idx];
6432
6433 if (STRINGP (color)
6434 && SCHARS (color)
6435 && CONSP (Vtty_defined_color_alist)
6436 && (def = assoc_no_quit (color, call1 (Qtty_color_alist, frame)),
6437 CONSP (def)))
6438 {
6439
6440
6441 pixel = XFIXNUM (XCAR (XCDR (def)));
6442 }
6443
6444 if (pixel == default_pixel && STRINGP (color))
6445 {
6446 pixel = load_color (f, face, color, idx);
6447
6448 #ifdef MSDOS
6449
6450
6451 if (FRAME_MSDOS_P (f))
6452 {
6453 if (pixel == default_pixel
6454 || pixel == FACE_TTY_DEFAULT_COLOR)
6455 {
6456 if (foreground_p)
6457 pixel = FRAME_FOREGROUND_PIXEL (f);
6458 else
6459 pixel = FRAME_BACKGROUND_PIXEL (f);
6460 face->lface[idx] = tty_color_name (f, pixel);
6461 *defaulted = true;
6462 }
6463 else if (pixel == default_other_pixel)
6464 {
6465 if (foreground_p)
6466 pixel = FRAME_BACKGROUND_PIXEL (f);
6467 else
6468 pixel = FRAME_FOREGROUND_PIXEL (f);
6469 face->lface[idx] = tty_color_name (f, pixel);
6470 *defaulted = true;
6471 }
6472 }
6473 #endif
6474 }
6475
6476 if (foreground_p)
6477 face->foreground = pixel;
6478 else
6479 face->background = pixel;
6480 }
6481
6482
6483
6484
6485
6486
6487 static struct face *
6488 realize_tty_face (struct face_cache *cache,
6489 Lisp_Object attrs[LFACE_VECTOR_SIZE])
6490 {
6491 struct face *face;
6492 int weight, slant;
6493 bool face_colors_defaulted = false;
6494 struct frame *f = cache->f;
6495
6496
6497 eassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
6498
6499
6500 face = make_realized_face (attrs);
6501 #if false
6502 face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
6503 #endif
6504
6505
6506 weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
6507 slant = FONT_SLANT_NAME_NUMERIC (attrs[LFACE_SLANT_INDEX]);
6508 if (weight > 100)
6509 face->tty_bold_p = true;
6510 if (slant != 100)
6511 face->tty_italic_p = true;
6512 if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
6513 face->tty_underline_p = true;
6514 if (!NILP (attrs[LFACE_INVERSE_INDEX]))
6515 face->tty_reverse_p = true;
6516 if (!NILP (attrs[LFACE_STRIKE_THROUGH_INDEX]))
6517 face->tty_strike_through_p = true;
6518
6519
6520 map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
6521 map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
6522
6523
6524
6525
6526 if (face->tty_reverse_p && !face_colors_defaulted)
6527 {
6528 unsigned long tem = face->foreground;
6529 face->foreground = face->background;
6530 face->background = tem;
6531 }
6532
6533 if (tty_suppress_bold_inverse_default_colors_p
6534 && face->tty_bold_p
6535 && face->background == FACE_TTY_DEFAULT_FG_COLOR
6536 && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
6537 face->tty_bold_p = false;
6538
6539 return face;
6540 }
6541
6542
6543 DEFUN ("tty-suppress-bold-inverse-default-colors",
6544 Ftty_suppress_bold_inverse_default_colors,
6545 Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
6546 doc:
6547
6548
6549
6550
6551 )
6552 (Lisp_Object suppress)
6553 {
6554 tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
6555 face_change = true;
6556 return suppress;
6557 }
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568 int
6569 compute_char_face (struct frame *f, int ch, Lisp_Object prop)
6570 {
6571 int face_id;
6572
6573 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
6574 ch = 0;
6575
6576 if (NILP (prop))
6577 {
6578 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6579 face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
6580 }
6581 else
6582 {
6583 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6584 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6585 memcpy (attrs, default_face->lface, sizeof attrs);
6586 merge_face_ref (NULL, f, prop, attrs, true, NULL, 0);
6587 face_id = lookup_face (f, attrs);
6588 }
6589
6590 return face_id;
6591 }
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616 int
6617 face_at_buffer_position (struct window *w, ptrdiff_t pos,
6618 ptrdiff_t *endptr, ptrdiff_t limit,
6619 bool mouse, int base_face_id,
6620 enum lface_attribute_index attr_filter)
6621 {
6622 struct frame *f = XFRAME (w->frame);
6623 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6624 Lisp_Object prop, position;
6625 ptrdiff_t i, noverlays;
6626 Lisp_Object *overlay_vec;
6627 ptrdiff_t endpos;
6628 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6629 Lisp_Object limit1, end;
6630 struct face *default_face;
6631
6632
6633
6634
6635
6636 XSETFASTINT (position, pos);
6637
6638 endpos = ZV;
6639
6640
6641
6642 prop = Fget_text_property (position, propname, w->contents);
6643 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6644 end = Fnext_single_property_change (position, propname, w->contents, limit1);
6645 if (FIXNUMP (end))
6646 endpos = XFIXNUM (end);
6647
6648
6649 USE_SAFE_ALLOCA;
6650 {
6651 ptrdiff_t next_overlay;
6652 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay);
6653 if (next_overlay < endpos)
6654 endpos = next_overlay;
6655 }
6656
6657 *endptr = endpos;
6658
6659 {
6660 int face_id;
6661
6662 if (base_face_id >= 0)
6663 face_id = base_face_id;
6664 else if (NILP (Vface_remapping_alist))
6665 face_id = DEFAULT_FACE_ID;
6666 else
6667 face_id = lookup_basic_face (w, f, DEFAULT_FACE_ID);
6668
6669 default_face = FACE_FROM_ID_OR_NULL (f, face_id);
6670
6671
6672
6673 if (!default_face)
6674 {
6675 if (FRAME_FACE_CACHE (f)->used == 0)
6676 recompute_basic_faces (f);
6677 default_face = FACE_FROM_ID (f,
6678 lookup_basic_face (w, f, DEFAULT_FACE_ID));
6679 }
6680 }
6681
6682
6683 if (noverlays == 0
6684 && NILP (prop))
6685 {
6686 SAFE_FREE ();
6687 return default_face->id;
6688 }
6689
6690
6691 memcpy (attrs, default_face->lface, sizeof(attrs));
6692
6693
6694 if (!NILP (prop))
6695 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6696
6697
6698 noverlays = sort_overlays (overlay_vec, noverlays, w);
6699
6700
6701 if (mouse)
6702 {
6703 for (prop = Qnil, i = noverlays - 1; i >= 0 && NILP (prop); --i)
6704 {
6705 ptrdiff_t oendpos;
6706
6707 prop = Foverlay_get (overlay_vec[i], propname);
6708 if (!NILP (prop))
6709 {
6710
6711
6712
6713 memcpy (attrs, default_face->lface, sizeof attrs);
6714 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6715 }
6716
6717 oendpos = OVERLAY_END (overlay_vec[i]);
6718 if (oendpos < endpos)
6719 endpos = oendpos;
6720 }
6721 }
6722 else
6723 {
6724 for (i = 0; i < noverlays; i++)
6725 {
6726 ptrdiff_t oendpos;
6727
6728 prop = Foverlay_get (overlay_vec[i], propname);
6729
6730 if (!NILP (prop))
6731 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6732
6733 oendpos = OVERLAY_END (overlay_vec[i]);
6734 if (oendpos < endpos)
6735 endpos = oendpos;
6736 }
6737 }
6738
6739 *endptr = endpos;
6740
6741 SAFE_FREE ();
6742
6743
6744
6745 return lookup_face (f, attrs);
6746 }
6747
6748
6749
6750
6751
6752
6753
6754 int
6755 face_for_overlay_string (struct window *w, ptrdiff_t pos,
6756 ptrdiff_t *endptr, ptrdiff_t limit,
6757 bool mouse, Lisp_Object overlay,
6758 enum lface_attribute_index attr_filter)
6759 {
6760 struct frame *f = XFRAME (w->frame);
6761 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6762 Lisp_Object prop, position;
6763 ptrdiff_t endpos;
6764 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6765 Lisp_Object limit1, end;
6766 struct face *default_face;
6767
6768
6769
6770
6771
6772 XSETFASTINT (position, pos);
6773
6774 endpos = ZV;
6775
6776
6777
6778 prop = Fget_text_property (position, propname, w->contents);
6779 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6780 end = Fnext_single_property_change (position, propname, w->contents, limit1);
6781 if (FIXNUMP (end))
6782 endpos = XFIXNUM (end);
6783
6784 *endptr = endpos;
6785
6786
6787 if (NILP (prop)
6788 && NILP (Vface_remapping_alist))
6789 return DEFAULT_FACE_ID;
6790
6791
6792 default_face = FACE_FROM_ID (f, lookup_basic_face (w, f, DEFAULT_FACE_ID));
6793 memcpy (attrs, default_face->lface, sizeof attrs);
6794
6795
6796 if (!NILP (prop))
6797 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6798
6799 *endptr = endpos;
6800
6801
6802
6803 return lookup_face (f, attrs);
6804 }
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828 int
6829 face_at_string_position (struct window *w, Lisp_Object string,
6830 ptrdiff_t pos, ptrdiff_t bufpos,
6831 ptrdiff_t *endptr, enum face_id base_face_id,
6832 bool mouse_p,
6833 enum lface_attribute_index attr_filter)
6834 {
6835 Lisp_Object prop, position, end, limit;
6836 struct frame *f = XFRAME (WINDOW_FRAME (w));
6837 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6838 struct face *base_face;
6839 bool multibyte_p = STRING_MULTIBYTE (string);
6840 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
6841
6842
6843
6844 XSETFASTINT (position, pos);
6845 prop = Fget_text_property (position, prop_name, string);
6846
6847
6848
6849
6850
6851
6852
6853 XSETFASTINT (limit, SCHARS (string));
6854 end = Fnext_single_property_change (position, prop_name, string, limit);
6855 if (FIXNUMP (end))
6856 *endptr = XFIXNAT (end);
6857 else
6858 *endptr = -1;
6859
6860 base_face = FACE_FROM_ID_OR_NULL (f, base_face_id);
6861 if (!base_face)
6862 base_face = FACE_FROM_ID (f, lookup_basic_face (w, f, DEFAULT_FACE_ID));
6863
6864
6865 if (NILP (prop)
6866 && (multibyte_p
6867
6868
6869
6870 || !FRAME_WINDOW_P (f)
6871 || FACE_SUITABLE_FOR_ASCII_CHAR_P (base_face)))
6872 return base_face->id;
6873
6874
6875 memcpy (attrs, base_face->lface, sizeof attrs);
6876
6877
6878 if (!NILP (prop))
6879 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6880
6881
6882
6883 return lookup_face (f, attrs);
6884 }
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902 int
6903 merge_faces (struct window *w, Lisp_Object face_name, int face_id,
6904 int base_face_id)
6905 {
6906 struct frame *f = WINDOW_XFRAME (w);
6907 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6908 struct face *base_face = FACE_FROM_ID_OR_NULL (f, base_face_id);
6909
6910 if (!base_face)
6911 return base_face_id;
6912
6913 if (EQ (face_name, Qt))
6914 {
6915 if (face_id < 0 || face_id >= lface_id_to_name_size)
6916 return base_face_id;
6917 face_name = lface_id_to_name[face_id];
6918
6919
6920 face_id = lookup_derived_face (w, f, face_name, base_face_id, 0);
6921 return (face_id >= 0 ? face_id : base_face_id);
6922 }
6923
6924
6925 memcpy (attrs, base_face->lface, sizeof attrs);
6926
6927 if (!NILP (face_name))
6928 {
6929 if (!merge_named_face (w, f, face_name, attrs, NULL, 0))
6930 return base_face_id;
6931 }
6932 else
6933 {
6934 if (face_id < 0)
6935 return base_face_id;
6936
6937 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
6938
6939 if (!face)
6940 return base_face_id;
6941
6942 if (face_id != DEFAULT_FACE_ID)
6943 {
6944 struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6945 Lisp_Object lface_attrs[LFACE_VECTOR_SIZE];
6946 int i;
6947
6948 memcpy (lface_attrs, face->lface, LFACE_VECTOR_SIZE);
6949
6950 for (i = 1; i < LFACE_VECTOR_SIZE; i++)
6951 if (EQ (lface_attrs[i], Qreset))
6952 lface_attrs[i] = deflt->lface[i];
6953 merge_face_vectors (w, f, lface_attrs, attrs, 0);
6954 }
6955 else
6956 merge_face_vectors (w, f, face->lface, attrs, 0);
6957 }
6958
6959
6960
6961 return lookup_face (f, attrs);
6962 }
6963
6964
6965
6966 #ifndef HAVE_X_WINDOWS
6967 DEFUN ("x-load-color-file", Fx_load_color_file,
6968 Sx_load_color_file, 1, 1, 0,
6969 doc:
6970
6971
6972
6973 )
6974 (Lisp_Object filename)
6975 {
6976 FILE *fp;
6977 Lisp_Object cmap = Qnil;
6978 Lisp_Object abspath;
6979
6980 CHECK_STRING (filename);
6981 abspath = Fexpand_file_name (filename, Qnil);
6982
6983 block_input ();
6984 fp = emacs_fopen (SSDATA (abspath), "r" FOPEN_TEXT);
6985 if (fp)
6986 {
6987 char buf[512];
6988 int red, green, blue;
6989 int num;
6990
6991 while (fgets (buf, sizeof (buf), fp) != NULL)
6992 {
6993 if (sscanf (buf, "%d %d %d %n", &red, &green, &blue, &num) == 3)
6994 {
6995 #ifdef HAVE_NTGUI
6996 int color = RGB (red, green, blue);
6997 #else
6998 int color = (red << 16) | (green << 8) | blue;
6999 #endif
7000 char *name = buf + num;
7001 ptrdiff_t len = strlen (name);
7002 len -= 0 < len && name[len - 1] == '\n';
7003 cmap = Fcons (Fcons (make_string (name, len), make_fixnum (color)),
7004 cmap);
7005 }
7006 }
7007 emacs_fclose (fp);
7008 }
7009 unblock_input ();
7010 return cmap;
7011 }
7012 #endif
7013
7014
7015
7016
7017
7018
7019 #ifdef GLYPH_DEBUG
7020
7021
7022
7023 static void
7024 dump_realized_face (struct face *face)
7025 {
7026 fprintf (stderr, "ID: %d\n", face->id);
7027 #ifdef HAVE_X_WINDOWS
7028 fprintf (stderr, "gc: %p\n", face->gc);
7029 #endif
7030 fprintf (stderr, "foreground: 0x%lx (%s)\n",
7031 face->foreground,
7032 SDATA (face->lface[LFACE_FOREGROUND_INDEX]));
7033 fprintf (stderr, "background: 0x%lx (%s)\n",
7034 face->background,
7035 SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
7036 if (face->font)
7037 fprintf (stderr, "font_name: %s (%s)\n",
7038 SDATA (face->font->props[FONT_NAME_INDEX]),
7039 SDATA (face->lface[LFACE_FAMILY_INDEX]));
7040 #ifdef HAVE_X_WINDOWS
7041 fprintf (stderr, "font = %p\n", face->font);
7042 #endif
7043 fprintf (stderr, "fontset: %d\n", face->fontset);
7044 fprintf (stderr, "underline: %d (%s)\n",
7045 face->underline,
7046 SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
7047 fprintf (stderr, "hash: %" PRIuPTR "\n", face->hash);
7048 }
7049
7050
7051 DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: )
7052 (Lisp_Object n)
7053 {
7054 if (NILP (n))
7055 {
7056 int i;
7057
7058 fputs ("font selection order: ", stderr);
7059 for (i = 0; i < ARRAYELTS (font_sort_order); ++i)
7060 fprintf (stderr, "%d ", font_sort_order[i]);
7061 putc ('\n', stderr);
7062
7063 fputs ("alternative fonts: ", stderr);
7064 debug_print (Vface_alternative_font_family_alist);
7065 putc ('\n', stderr);
7066
7067 for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
7068 Fdump_face (make_fixnum (i));
7069 }
7070 else
7071 {
7072 struct face *face;
7073 CHECK_FIXNUM (n);
7074 face = FACE_FROM_ID_OR_NULL (SELECTED_FRAME (), XFIXNUM (n));
7075 if (face == NULL)
7076 error ("Not a valid face");
7077 dump_realized_face (face);
7078 }
7079
7080 return Qnil;
7081 }
7082
7083
7084 DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
7085 0, 0, 0, doc: )
7086 (void)
7087 {
7088 fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
7089 fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
7090 fprintf (stderr, "number of GCs = %d\n", ngcs);
7091 return Qnil;
7092 }
7093
7094 #endif
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108 void
7109 init_xfaces (void)
7110 {
7111 #ifdef HAVE_PDUMPER
7112 int nfaces;
7113
7114 if (dumped_with_pdumper_p ())
7115 {
7116 nfaces = XFIXNAT (Fhash_table_count (Vface_new_frame_defaults));
7117 if (nfaces > 0)
7118 {
7119
7120 lface_id_to_name_size = next_lface_id = nfaces;
7121 lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name);
7122
7123
7124 struct Lisp_Hash_Table* table = XHASH_TABLE (Vface_new_frame_defaults);
7125 for (ptrdiff_t idx = 0; idx < nfaces; ++idx)
7126 {
7127 Lisp_Object lface = HASH_KEY (table, idx);
7128 Lisp_Object face_id = CAR (HASH_VALUE (table, idx));
7129 if (FIXNATP (face_id))
7130 {
7131 int id = XFIXNAT (face_id);
7132 eassert (id >= 0);
7133 lface_id_to_name[id] = lface;
7134 }
7135 }
7136 }
7137 }
7138 #endif
7139
7140 face_attr_sym[0] = Qface;
7141 face_attr_sym[LFACE_FOUNDRY_INDEX] = QCfoundry;
7142 face_attr_sym[LFACE_SWIDTH_INDEX] = QCwidth;
7143 face_attr_sym[LFACE_HEIGHT_INDEX] = QCheight;
7144 face_attr_sym[LFACE_WEIGHT_INDEX] = QCweight;
7145 face_attr_sym[LFACE_SLANT_INDEX] = QCslant;
7146 face_attr_sym[LFACE_UNDERLINE_INDEX] = QCunderline;
7147 face_attr_sym[LFACE_INVERSE_INDEX] = QCinverse_video;
7148 face_attr_sym[LFACE_FOREGROUND_INDEX] = QCforeground;
7149 face_attr_sym[LFACE_BACKGROUND_INDEX] = QCbackground;
7150 face_attr_sym[LFACE_STIPPLE_INDEX] = QCstipple;
7151 face_attr_sym[LFACE_OVERLINE_INDEX] = QCoverline;
7152 face_attr_sym[LFACE_STRIKE_THROUGH_INDEX] = QCstrike_through;
7153 face_attr_sym[LFACE_BOX_INDEX] = QCbox;
7154 face_attr_sym[LFACE_FONT_INDEX] = QCfont;
7155 face_attr_sym[LFACE_INHERIT_INDEX] = QCinherit;
7156 face_attr_sym[LFACE_FONTSET_INDEX] = QCfontset;
7157 face_attr_sym[LFACE_DISTANT_FOREGROUND_INDEX] = QCdistant_foreground;
7158 face_attr_sym[LFACE_EXTEND_INDEX] = QCextend;
7159 }
7160
7161 void
7162 syms_of_xfaces (void)
7163 {
7164
7165 DEFSYM (Qface, "face");
7166
7167
7168 DEFSYM (Qface_no_inherit, "face-no-inherit");
7169
7170
7171 DEFSYM (Qbitmap_spec_p, "bitmap-spec-p");
7172
7173
7174
7175 DEFSYM (Qframe_set_background_mode, "frame-set-background-mode");
7176
7177
7178 DEFSYM (QCfamily, ":family");
7179 DEFSYM (QCheight, ":height");
7180 DEFSYM (QCweight, ":weight");
7181 DEFSYM (QCslant, ":slant");
7182 DEFSYM (QCunderline, ":underline");
7183 DEFSYM (QCinverse_video, ":inverse-video");
7184 DEFSYM (QCreverse_video, ":reverse-video");
7185 DEFSYM (QCforeground, ":foreground");
7186 DEFSYM (QCbackground, ":background");
7187 DEFSYM (QCstipple, ":stipple");
7188 DEFSYM (QCwidth, ":width");
7189 DEFSYM (QCfont, ":font");
7190 DEFSYM (QCfontset, ":fontset");
7191 DEFSYM (QCdistant_foreground, ":distant-foreground");
7192 DEFSYM (QCbold, ":bold");
7193 DEFSYM (QCitalic, ":italic");
7194 DEFSYM (QCoverline, ":overline");
7195 DEFSYM (QCstrike_through, ":strike-through");
7196 DEFSYM (QCbox, ":box");
7197 DEFSYM (QCinherit, ":inherit");
7198 DEFSYM (QCextend, ":extend");
7199
7200
7201 DEFSYM (QCcolor, ":color");
7202 DEFSYM (QCline_width, ":line-width");
7203 DEFSYM (QCstyle, ":style");
7204 DEFSYM (QCposition, ":position");
7205 DEFSYM (Qline, "line");
7206 DEFSYM (Qwave, "wave");
7207 DEFSYM (Qreleased_button, "released-button");
7208 DEFSYM (Qpressed_button, "pressed-button");
7209 DEFSYM (Qflat_button, "flat-button");
7210 DEFSYM (Qnormal, "normal");
7211 DEFSYM (Qthin, "thin");
7212 DEFSYM (Qextra_light, "extra-light");
7213 DEFSYM (Qultra_light, "ultra-light");
7214 DEFSYM (Qlight, "light");
7215 DEFSYM (Qsemi_light, "semi-light");
7216 DEFSYM (Qmedium, "medium");
7217 DEFSYM (Qsemi_bold, "semi-bold");
7218 DEFSYM (Qbook, "book");
7219 DEFSYM (Qbold, "bold");
7220 DEFSYM (Qextra_bold, "extra-bold");
7221 DEFSYM (Qultra_bold, "ultra-bold");
7222 DEFSYM (Qheavy, "heavy");
7223 DEFSYM (Qultra_heavy, "ultra-heavy");
7224 DEFSYM (Qblack, "black");
7225 DEFSYM (Qoblique, "oblique");
7226 DEFSYM (Qitalic, "italic");
7227 DEFSYM (Qreset, "reset");
7228
7229
7230
7231
7232 DEFSYM (Qbackground_color, "background-color");
7233 DEFSYM (Qforeground_color, "foreground-color");
7234
7235 DEFSYM (Qunspecified, "unspecified");
7236 DEFSYM (QCignore_defface, ":ignore-defface");
7237
7238
7239
7240 DEFSYM (QCwindow, ":window");
7241 DEFSYM (QCfiltered, ":filtered");
7242
7243
7244
7245
7246 DEFSYM (Qface_alias, "face-alias");
7247
7248
7249 DEFSYM (Qdefault, "default");
7250 DEFSYM (Qtool_bar, "tool-bar");
7251 DEFSYM (Qtab_bar, "tab-bar");
7252 DEFSYM (Qfringe, "fringe");
7253 DEFSYM (Qtab_line, "tab-line");
7254 DEFSYM (Qheader_line, "header-line");
7255 DEFSYM (Qscroll_bar, "scroll-bar");
7256 DEFSYM (Qmenu, "menu");
7257 DEFSYM (Qcursor, "cursor");
7258 DEFSYM (Qborder, "border");
7259 DEFSYM (Qmouse, "mouse");
7260 DEFSYM (Qmode_line_inactive, "mode-line-inactive");
7261 DEFSYM (Qmode_line_active, "mode-line-active");
7262 DEFSYM (Qvertical_border, "vertical-border");
7263 DEFSYM (Qwindow_divider, "window-divider");
7264 DEFSYM (Qwindow_divider_first_pixel, "window-divider-first-pixel");
7265 DEFSYM (Qwindow_divider_last_pixel, "window-divider-last-pixel");
7266 DEFSYM (Qinternal_border, "internal-border");
7267 DEFSYM (Qchild_frame_border, "child-frame-border");
7268
7269
7270 DEFSYM (Qtty_color_desc, "tty-color-desc");
7271 DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
7272 DEFSYM (Qtty_color_by_index, "tty-color-by-index");
7273
7274
7275 DEFSYM (Qtty_color_alist, "tty-color-alist");
7276
7277 Vface_alternative_font_family_alist = Qnil;
7278 staticpro (&Vface_alternative_font_family_alist);
7279 Vface_alternative_font_registry_alist = Qnil;
7280 staticpro (&Vface_alternative_font_registry_alist);
7281
7282 defsubr (&Sinternal_make_lisp_face);
7283 defsubr (&Sinternal_lisp_face_p);
7284 defsubr (&Sinternal_set_lisp_face_attribute);
7285 #ifdef HAVE_WINDOW_SYSTEM
7286 defsubr (&Sinternal_set_lisp_face_attribute_from_resource);
7287 #endif
7288 defsubr (&Scolor_gray_p);
7289 defsubr (&Scolor_supported_p);
7290 #ifndef HAVE_X_WINDOWS
7291 defsubr (&Sx_load_color_file);
7292 #endif
7293 defsubr (&Sface_attribute_relative_p);
7294 defsubr (&Smerge_face_attribute);
7295 defsubr (&Sinternal_get_lisp_face_attribute);
7296 defsubr (&Sinternal_lisp_face_attribute_values);
7297 defsubr (&Sinternal_lisp_face_equal_p);
7298 defsubr (&Sinternal_lisp_face_empty_p);
7299 defsubr (&Sinternal_copy_lisp_face);
7300 defsubr (&Sinternal_merge_in_global_face);
7301 defsubr (&Sface_font);
7302 defsubr (&Sframe_face_hash_table);
7303 defsubr (&Sdisplay_supports_face_attributes_p);
7304 defsubr (&Scolor_distance);
7305 defsubr (&Sinternal_set_font_selection_order);
7306 defsubr (&Sinternal_set_alternative_font_family_alist);
7307 defsubr (&Sinternal_set_alternative_font_registry_alist);
7308 defsubr (&Sface_attributes_as_vector);
7309 #ifdef GLYPH_DEBUG
7310 defsubr (&Sdump_face);
7311 defsubr (&Sshow_face_resources);
7312 #endif
7313 defsubr (&Sclear_face_cache);
7314 defsubr (&Stty_suppress_bold_inverse_default_colors);
7315
7316 #if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
7317 defsubr (&Sdump_colors);
7318 #endif
7319
7320 DEFVAR_BOOL ("face-filters-always-match", face_filters_always_match,
7321 doc:
7322
7323
7324 );
7325
7326 DEFVAR_LISP ("face--new-frame-defaults", Vface_new_frame_defaults,
7327 doc: );
7328 Vface_new_frame_defaults =
7329
7330 make_hash_table (hashtest_eq, 33, DEFAULT_REHASH_SIZE,
7331 DEFAULT_REHASH_THRESHOLD, Qnil, false);
7332
7333 DEFVAR_LISP ("face-default-stipple", Vface_default_stipple,
7334 doc:
7335
7336
7337 );
7338 Vface_default_stipple = build_pure_c_string ("gray3");
7339
7340 DEFVAR_LISP ("tty-defined-color-alist", Vtty_defined_color_alist,
7341 doc:
7342 );
7343 Vtty_defined_color_alist = Qnil;
7344
7345 DEFVAR_LISP ("scalable-fonts-allowed", Vscalable_fonts_allowed,
7346 doc:
7347
7348
7349
7350
7351
7352 );
7353 Vscalable_fonts_allowed = Qnil;
7354
7355 DEFVAR_LISP ("face-ignored-fonts", Vface_ignored_fonts,
7356 doc:
7357
7358 );
7359 #ifdef HAVE_XFT
7360
7361 Vface_ignored_fonts = list1 (build_string ("Noto Color Emoji"));
7362 #else
7363 Vface_ignored_fonts = Qnil;
7364 #endif
7365 #ifdef HAVE_OTF_KANNADA_BUG
7366
7367
7368 Vface_ignored_fonts = Fcons (build_string ("Noto Serif Kannada"), Vface_ignored_fonts);
7369 #endif
7370
7371 DEFVAR_LISP ("face-remapping-alist", Vface_remapping_alist,
7372 doc:
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433 );
7434 Vface_remapping_alist = Qnil;
7435 DEFSYM (Qface_remapping_alist,"face-remapping-alist");
7436
7437 DEFVAR_LISP ("face-font-rescale-alist", Vface_font_rescale_alist,
7438 doc:
7439
7440
7441
7442
7443 );
7444 Vface_font_rescale_alist = Qnil;
7445
7446 DEFVAR_INT ("face-near-same-color-threshold", face_near_same_color_threshold,
7447 doc:
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457 );
7458 face_near_same_color_threshold = 30000;
7459
7460 DEFVAR_LISP ("face-font-lax-matched-attributes",
7461 Vface_font_lax_matched_attributes,
7462 doc:
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486 );
7487 Vface_font_lax_matched_attributes = Qt;
7488
7489 #ifdef HAVE_WINDOW_SYSTEM
7490 defsubr (&Sbitmap_spec_p);
7491 defsubr (&Sx_list_fonts);
7492 defsubr (&Sinternal_face_x_get_resource);
7493 defsubr (&Sx_family_fonts);
7494 #endif
7495 defsubr (&Scolor_values_from_color_spec);
7496 }