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