* configure.in (BROKEN_SA_RESTART): Doc fix.
[bpt/emacs.git] / src / xfaces.c
CommitLineData
82641697 1/* xfaces.c -- "Face" primitives.
e9bffc61 2
acaf905b 3Copyright (C) 1993-1994, 1998-2012 Free Software Foundation, Inc.
7b7739b1 4
c115973b
JB
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
c115973b 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
c115973b
JB
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
c115973b 19
82641697
GM
20/* New face implementation by Gerd Moellmann <gerd@gnu.org>. */
21
22/* Faces.
23
24 When using Emacs with X, the display style of characters can be
25 changed by defining `faces'. Each face can specify the following
26 display attributes:
27
39506348 28 1. Font family name.
178c5d9c 29
40a8bdf6 30 2. Font foundry name.
53aaf1e2
KH
31
32 3. Relative proportionate width, aka character set width or set
82641697 33 width (swidth), e.g. `semi-compressed'.
178c5d9c 34
53aaf1e2 35 4. Font height in 1/10pt.
178c5d9c 36
53aaf1e2 37 5. Font weight, e.g. `bold'.
178c5d9c 38
53aaf1e2 39 6. Font slant, e.g. `italic'.
178c5d9c 40
53aaf1e2 41 7. Foreground color.
178c5d9c 42
53aaf1e2 43 8. Background color.
82641697 44
53aaf1e2 45 9. Whether or not characters should be underlined, and in what color.
82641697 46
53aaf1e2 47 10. Whether or not characters should be displayed in inverse video.
82641697 48
53aaf1e2 49 11. A background stipple, a bitmap.
82641697 50
53aaf1e2 51 12. Whether or not characters should be overlined, and in what color.
82641697 52
53aaf1e2 53 13. Whether or not characters should be strike-through, and in what
82641697
GM
54 color.
55
53aaf1e2 56 14. Whether or not a box should be drawn around characters, the box
82641697
GM
57 type, and, for simple boxes, in what color.
58
53aaf1e2 59 15. Font-spec, or nil. This is a special attribute.
2dee4c0b
KH
60
61 A font-spec is a collection of font attributes (specs).
62
63 When this attribute is specified, the face uses a font matching
64 with the specs as is except for what overwritten by the specs in
65 the fontset (see below). In addition, the other font-related
66 attributes (1st thru 5th) are updated from the spec.
67
39506348 68 On the other hand, if one of the other font-related attributes are
e4769531 69 specified, the corresponding specs in this attribute is set to nil.
39506348 70
2c20458f
MB
71 15. A face name or list of face names from which to inherit attributes.
72
a08332c0
GM
73 16. A specified average font width, which is invisible from Lisp,
74 and is used to ensure that a font specified on the command line,
75 for example, can be matched exactly.
76
2dee4c0b
KH
77 17. A fontset name. This is another special attribute.
78
79 A fontset is a mappings from characters to font-specs, and the
80 specs overwrite the font-spec in the 14th attribute.
81
763bc839 82
82641697
GM
83 Faces are frame-local by nature because Emacs allows to define the
84 same named face (face names are symbols) differently for different
85 frames. Each frame has an alist of face definitions for all named
86 faces. The value of a named face in such an alist is a Lisp vector
39506348
KH
87 with the symbol `face' in slot 0, and a slot for each of the face
88 attributes mentioned above.
82641697
GM
89
90 There is also a global face alist `Vface_new_frame_defaults'. Face
91 definitions from this list are used to initialize faces of newly
92 created frames.
178c5d9c 93
82641697 94 A face doesn't have to specify all attributes. Those not specified
39506348
KH
95 have a value of `unspecified'. Faces specifying all attributes but
96 the 14th are called `fully-specified'.
82641697
GM
97
98
99 Face merging.
100
101 The display style of a given character in the text is determined by
102 combining several faces. This process is called `face merging'.
103 Any aspect of the display style that isn't specified by overlays or
104 text properties is taken from the `default' face. Since it is made
105 sure that the default face is always fully-specified, face merging
106 always results in a fully-specified face.
107
108
109 Face realization.
178c5d9c 110
82641697
GM
111 After all face attributes for a character have been determined by
112 merging faces of that character, that face is `realized'. The
113 realization process maps face attributes to what is physically
114 available on the system where Emacs runs. The result is a
115 `realized face' in form of a struct face which is stored in the
116 face cache of the frame on which it was realized.
117
39506348
KH
118 Face realization is done in the context of the character to display
119 because different fonts may be used for different characters. In
120 other words, for characters that have different font
121 specifications, different realized faces are needed to display
82641697
GM
122 them.
123
39506348
KH
124 Font specification is done by fontsets. See the comment in
125 fontset.c for the details. In the current implementation, all ASCII
126 characters share the same font in a fontset.
127
128 Faces are at first realized for ASCII characters, and, at that
129 time, assigned a specific realized fontset. Hereafter, we call
130 such a face as `ASCII face'. When a face for a multibyte character
131 is realized, it inherits (thus shares) a fontset of an ASCII face
132 that has the same attributes other than font-related ones.
133
763bc839 134 Thus, all realized faces have a realized fontset.
82641697
GM
135
136
137 Unibyte text.
138
39506348
KH
139 Unibyte text (i.e. raw 8-bit characters) is displayed with the same
140 font as ASCII characters. That is because it is expected that
141 unibyte text users specify a font that is suitable both for ASCII
142 and raw 8-bit characters.
143
82641697
GM
144
145 Font selection.
146
147 Font selection tries to find the best available matching font for a
39506348 148 given (character, face) combination.
82641697 149
39506348
KH
150 If the face specifies a fontset name, that fontset determines a
151 pattern for fonts of the given character. If the face specifies a
152 font name or the other font-related attributes, a fontset is
153 realized from the default fontset. In that case, that
154 specification determines a pattern for ASCII characters and the
155 default fontset determines a pattern for multibyte characters.
82641697
GM
156
157 Available fonts on the system on which Emacs runs are then matched
158 against the font pattern. The result of font selection is the best
159 match for the given face attributes in this font list.
160
161 Font selection can be influenced by the user.
162
163 1. The user can specify the relative importance he gives the face
164 attributes width, height, weight, and slant by setting
165 face-font-selection-order (faces.el) to a list of face attribute
166 names. The default is '(:width :height :weight :slant), and means
167 that font selection first tries to find a good match for the font
168 width specified by a face, then---within fonts with that
169 width---tries to find a best match for the specified font height,
170 etc.
171
c824bfbc 172 2. Setting face-font-family-alternatives allows the user to
82641697
GM
173 specify alternative font families to try if a family specified by a
174 face doesn't exist.
175
c824bfbc
KH
176 3. Setting face-font-registry-alternatives allows the user to
177 specify all alternative font registries to try for a face
178 specifying a registry.
179
180 4. Setting face-ignored-fonts allows the user to ignore specific
181 fonts.
182
82641697 183
ec7a10e3 184 Character composition.
39506348
KH
185
186 Usually, the realization process is already finished when Emacs
187 actually reflects the desired glyph matrix on the screen. However,
188 on displaying a composition (sequence of characters to be composed
189 on the screen), a suitable font for the components of the
190 composition is selected and realized while drawing them on the
191 screen, i.e. the realization process is delayed but in principle
192 the same.
82641697 193
178c5d9c 194
82641697
GM
195 Initialization of basic faces.
196
197 The faces `default', `modeline' are considered `basic faces'.
198 When redisplay happens the first time for a newly created frame,
199 basic faces are realized for CHARSET_ASCII. Frame parameters are
200 used to fill in unspecified attributes of the default face. */
201
68c45bf0 202#include <config.h>
6b61353c 203#include <stdio.h>
c115973b
JB
204#include <sys/types.h>
205#include <sys/stat.h>
4d553a13 206#include <stdio.h> /* This needs to be before termchar.h */
d7306fe6 207#include <setjmp.h>
7ee72033 208
c115973b 209#include "lisp.h"
81b39386 210#include "character.h"
a8517066 211#include "charset.h"
9763806e 212#include "keyboard.h"
b5c53576 213#include "frame.h"
428a555e 214#include "termhooks.h"
b5c53576 215
87485d6f 216#ifdef HAVE_X_WINDOWS
c115973b 217#include "xterm.h"
c7ae3284
GM
218#ifdef USE_MOTIF
219#include <Xm/Xm.h>
220#include <Xm/XmStrDefs.h>
221#endif /* USE_MOTIF */
d12d0a9b 222#endif /* HAVE_X_WINDOWS */
82641697 223
87485d6f
MW
224#ifdef MSDOS
225#include "dosfns.h"
226#endif
82641697 227
c3cee013
JR
228#ifdef WINDOWSNT
229#include "w32term.h"
230#include "fontset.h"
231/* Redefine X specifics to W32 equivalents to avoid cluttering the
232 code with #ifdef blocks. */
9763806e 233#undef FRAME_X_DISPLAY_INFO
c3cee013
JR
234#define FRAME_X_DISPLAY_INFO FRAME_W32_DISPLAY_INFO
235#define x_display_info w32_display_info
236#define FRAME_X_FONT_TABLE FRAME_W32_FONT_TABLE
237#define check_x check_w32
c3cee013 238#define GCGraphicsExposures 0
d12d0a9b 239#endif /* WINDOWSNT */
c3cee013 240
edfda783
AR
241#ifdef HAVE_NS
242#include "nsterm.h"
243#undef FRAME_X_DISPLAY_INFO
244#define FRAME_X_DISPLAY_INFO FRAME_NS_DISPLAY_INFO
245#define x_display_info ns_display_info
246#define FRAME_X_FONT_TABLE FRAME_NS_FONT_TABLE
247#define check_x check_ns
edfda783
AR
248#define GCGraphicsExposures 0
249#endif /* HAVE_NS */
250
c115973b 251#include "buffer.h"
f211082d 252#include "dispextern.h"
357f32fc 253#include "blockinput.h"
b6d40e46 254#include "window.h"
bde7c500 255#include "intervals.h"
28d440ab 256#include "termchar.h"
c115973b 257
426b2119 258#include "font.h"
ad00e1a3 259#ifdef HAVE_WINDOW_SYSTEM
2dee4c0b
KH
260#include "fontset.h"
261#endif /* HAVE_WINDOW_SYSTEM */
426b2119 262
87485d6f 263#ifdef HAVE_X_WINDOWS
82641697
GM
264
265/* Compensate for a bug in Xos.h on some systems, on which it requires
657070ac
JB
266 time.h. On some such systems, Xos.h tries to redefine struct
267 timeval and struct timezone if USG is #defined while it is
268 #included. */
657070ac 269
82641697 270#ifdef XOS_NEEDS_TIME_H
e11d186d 271#include <time.h>
657070ac
JB
272#undef USG
273#include <X11/Xos.h>
274#define USG
e11d186d 275#define __TIMEVAL__
875975e9
PE
276#if defined USG || defined __TIMEVAL__ /* Don't warn about unused macros. */
277#endif
82641697
GM
278#else /* not XOS_NEEDS_TIME_H */
279#include <X11/Xos.h>
280#endif /* not XOS_NEEDS_TIME_H */
e11d186d 281
82641697 282#endif /* HAVE_X_WINDOWS */
7a4d2269 283
82641697 284#include <ctype.h>
c115973b 285
c660ce4e
GM
286/* Number of pt per inch (from the TeXbook). */
287
288#define PT_PER_INCH 72.27
289
82641697
GM
290/* Non-zero if face attribute ATTR is unspecified. */
291
292#define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
293
2ff10663
CY
294/* Non-zero if face attribute ATTR is `ignore-defface'. */
295
a3720aa2 296#define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface)
2ff10663 297
82641697
GM
298/* Value is the number of elements of VECTOR. */
299
300#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
301
178c5d9c 302/* Size of hash table of realized faces in face caches (should be a
82641697
GM
303 prime number). */
304
305#define FACE_CACHE_BUCKETS_SIZE 1001
306
307/* Keyword symbols used for face attribute names. */
308
955cbe7b
PE
309Lisp_Object QCfamily, QCheight, QCweight, QCslant;
310static Lisp_Object QCunderline;
311static Lisp_Object QCinverse_video, QCstipple;
312Lisp_Object QCforeground, QCbackground;
313Lisp_Object QCwidth;
314static Lisp_Object QCfont, QCbold, QCitalic;
315static Lisp_Object QCreverse_video;
316static Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
317static Lisp_Object QCfontset;
82641697
GM
318
319/* Symbols used for attribute values. */
320
955cbe7b 321Lisp_Object Qnormal;
cc39a9db 322Lisp_Object Qbold;
9b0e3eba 323static Lisp_Object Qline, Qwave;
cc39a9db 324static Lisp_Object Qultra_light, Qextra_light, Qlight;
955cbe7b 325static Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold;
cc39a9db
BK
326static Lisp_Object Qoblique, Qreverse_oblique, Qreverse_italic;
327Lisp_Object Qitalic;
328static Lisp_Object Qultra_condensed, Qextra_condensed;
329Lisp_Object Qcondensed;
330static Lisp_Object Qsemi_condensed, Qsemi_expanded, Qextra_expanded;
331Lisp_Object Qexpanded;
955cbe7b
PE
332static Lisp_Object Qultra_expanded;
333static Lisp_Object Qreleased_button, Qpressed_button;
334static Lisp_Object QCstyle, QCcolor, QCline_width;
1b2de274 335Lisp_Object Qunspecified; /* used in dosfns.c */
a3720aa2 336static Lisp_Object QCignore_defface;
ef917393
EZ
337
338char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
82641697 339
92610620 340/* The name of the function to call when the background of the frame
c20577bc 341 has changed, frame_set_background_mode. */
92610620 342
19d5c50c 343static Lisp_Object Qframe_set_background_mode;
92610620 344
82641697
GM
345/* Names of basic faces. */
346
955cbe7b
PE
347Lisp_Object Qdefault, Qtool_bar, Qfringe;
348static Lisp_Object Qregion;
349Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
350static Lisp_Object Qborder, Qmouse, Qmenu;
351Lisp_Object Qmode_line_inactive;
352static Lisp_Object Qvertical_border;
8bd201d6 353
92610620
GM
354/* The symbol `face-alias'. A symbols having that property is an
355 alias for another face. Value of the property is the name of
356 the aliased face. */
357
955cbe7b 358static Lisp_Object Qface_alias;
92610620 359
82641697
GM
360/* Alist of alternative font families. Each element is of the form
361 (FAMILY FAMILY1 FAMILY2 ...). If fonts of FAMILY can't be loaded,
362 try FAMILY1, then FAMILY2, ... */
363
364Lisp_Object Vface_alternative_font_family_alist;
365
32fcc231
GM
366/* Alist of alternative font registries. Each element is of the form
367 (REGISTRY REGISTRY1 REGISTRY2...). If fonts of REGISTRY can't be
368 loaded, try REGISTRY1, then REGISTRY2, ... */
369
370Lisp_Object Vface_alternative_font_registry_alist;
371
82641697
GM
372/* Allowed scalable fonts. A value of nil means don't allow any
373 scalable fonts. A value of t means allow the use of any scalable
374 font. Otherwise, value must be a list of regular expressions. A
375 font may be scaled if its name matches a regular expression in the
376 list. */
377
955cbe7b 378static Lisp_Object Qscalable_fonts_allowed;
c824bfbc 379
057df17c
GM
380#define DEFAULT_FONT_LIST_LIMIT 100
381
82641697
GM
382/* The symbols `foreground-color' and `background-color' which can be
383 used as part of a `face' property. This is for compatibility with
384 Emacs 20.2. */
385
386Lisp_Object Qforeground_color, Qbackground_color;
387
388/* The symbols `face' and `mouse-face' used as text properties. */
7b7739b1 389
ff83dbb1 390Lisp_Object Qface;
82641697 391
46b00436
KS
392/* Property for basic faces which other faces cannot inherit. */
393
955cbe7b 394static Lisp_Object Qface_no_inherit;
46b00436 395
82641697
GM
396/* Error symbol for wrong_type_argument in load_pixmap. */
397
955cbe7b 398static Lisp_Object Qbitmap_spec_p;
f211082d 399
82641697 400/* The next ID to assign to Lisp faces. */
cb637678 401
82641697 402static int next_lface_id;
c115973b 403
82641697 404/* A vector mapping Lisp face Id's to face names. */
c115973b 405
82641697 406static Lisp_Object *lface_id_to_name;
0065d054 407static ptrdiff_t lface_id_to_name_size;
c115973b 408
ae4b4ba5
GM
409/* TTY color-related functions (defined in tty-colors.el). */
410
955cbe7b 411static Lisp_Object Qtty_color_desc, Qtty_color_by_index, Qtty_color_standard_values;
82641697 412
ae4b4ba5
GM
413/* The name of the function used to compute colors on TTYs. */
414
955cbe7b 415static Lisp_Object Qtty_color_alist;
ae4b4ba5 416
82641697
GM
417/* Counter for calls to clear_face_cache. If this counter reaches
418 CLEAR_FONT_TABLE_COUNT, and a frame has more than
419 CLEAR_FONT_TABLE_NFONTS load, unused fonts are freed. */
420
421static int clear_font_table_count;
422#define CLEAR_FONT_TABLE_COUNT 100
423#define CLEAR_FONT_TABLE_NFONTS 10
424
425/* Non-zero means face attributes have been changed since the last
426 redisplay. Used in redisplay_internal. */
427
428int face_change_count;
429
a4a76b61
GM
430/* Non-zero means don't display bold text if a face's foreground
431 and background colors are the inverse of the default colors of the
432 display. This is a kluge to suppress `bold black' foreground text
433 which is hard to read on an LCD monitor. */
434
435f4c28 435static int tty_suppress_bold_inverse_default_colors_p;
a4a76b61 436
dbc968b8
GM
437/* A list of the form `((x . y))' used to avoid consing in
438 Finternal_set_lisp_face_attribute. */
439
440static Lisp_Object Vparam_value_alist;
441
82641697
GM
442/* The total number of colors currently allocated. */
443
e509cfa6 444#ifdef GLYPH_DEBUG
82641697
GM
445static int ncolors_allocated;
446static int npixmaps_allocated;
447static int ngcs;
448#endif
449
ceeda019
GM
450/* Non-zero means the definition of the `menu' face for new frames has
451 been changed. */
452
435f4c28 453static int menu_face_changed_default;
82641697
GM
454
455\f
456/* Function prototypes. */
457
82641697 458struct table_entry;
a0a23346 459struct named_merge_point;
82641697 460
f57e2426 461static void map_tty_color (struct frame *, struct face *,
b5f03016 462 enum lface_attribute_index, int *);
f57e2426 463static Lisp_Object resolve_face_name (Lisp_Object, int);
f57e2426
J
464static void set_font_frame_param (Lisp_Object, Lisp_Object);
465static int get_lface_attributes (struct frame *, Lisp_Object, Lisp_Object *,
b5f03016 466 int, struct named_merge_point *);
0766b489
PE
467static ptrdiff_t load_pixmap (struct frame *, Lisp_Object,
468 unsigned *, unsigned *);
f57e2426
J
469static struct frame *frame_or_selected_frame (Lisp_Object, int);
470static void load_face_colors (struct frame *, struct face *, Lisp_Object *);
471static void free_face_colors (struct frame *, struct face *);
eec47d6b 472static int face_color_gray_p (struct frame *, const char *);
f57e2426 473static struct face *realize_face (struct face_cache *, Lisp_Object *,
b5f03016 474 int);
f57e2426 475static struct face *realize_non_ascii_face (struct frame *, Lisp_Object,
b5f03016 476 struct face *);
f57e2426
J
477static struct face *realize_x_face (struct face_cache *, Lisp_Object *);
478static struct face *realize_tty_face (struct face_cache *, Lisp_Object *);
479static int realize_basic_faces (struct frame *);
480static int realize_default_face (struct frame *);
481static void realize_named_face (struct frame *, Lisp_Object, int);
482static int lface_fully_specified_p (Lisp_Object *);
483static int lface_equal_p (Lisp_Object *, Lisp_Object *);
484static unsigned hash_string_case_insensitive (Lisp_Object);
485static unsigned lface_hash (Lisp_Object *);
486static int lface_same_font_attributes_p (Lisp_Object *, Lisp_Object *);
487static struct face_cache *make_face_cache (struct frame *);
488static void clear_face_gcs (struct face_cache *);
489static void free_face_cache (struct face_cache *);
490static int face_fontset (Lisp_Object *);
491static void merge_face_vectors (struct frame *, Lisp_Object *, Lisp_Object*,
b5f03016 492 struct named_merge_point *);
f57e2426 493static int merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *,
b5f03016 494 int, struct named_merge_point *);
f57e2426 495static int set_lface_from_font (struct frame *, Lisp_Object, Lisp_Object,
b5f03016 496 int);
f57e2426
J
497static Lisp_Object lface_from_face_name (struct frame *, Lisp_Object, int);
498static struct face *make_realized_face (Lisp_Object *);
499static void cache_face (struct face_cache *, struct face *, unsigned);
500static void uncache_face (struct face_cache *, struct face *);
82641697 501
c3cee013 502#ifdef HAVE_WINDOW_SYSTEM
82641697 503
f57e2426
J
504static GC x_create_gc (struct frame *, unsigned long, XGCValues *);
505static void x_free_gc (struct frame *, GC);
82641697 506
bce72079 507#ifdef USE_X_TOOLKIT
f57e2426 508static void x_update_menu_appearance (struct frame *);
9180dc8c 509
f57e2426 510extern void free_frame_menubar (struct frame *);
bce72079
GM
511#endif /* USE_X_TOOLKIT */
512
c3cee013 513#endif /* HAVE_WINDOW_SYSTEM */
c115973b 514
cb637678 515\f
82641697
GM
516/***********************************************************************
517 Utilities
518 ***********************************************************************/
c115973b 519
87485d6f 520#ifdef HAVE_X_WINDOWS
cb637678 521
a435fc2a
GM
522#ifdef DEBUG_X_COLORS
523
524/* The following is a poor mans infrastructure for debugging X color
525 allocation problems on displays with PseudoColor-8. Some X servers
526 like 3.3.5 XF86_SVGA with Matrox cards apparently don't implement
527 color reference counts completely so that they don't signal an
528 error when a color is freed whose reference count is already 0.
529 Other X servers do. To help me debug this, the following code
530 implements a simple reference counting schema of its own, for a
531 single display/screen. --gerd. */
532
533/* Reference counts for pixel colors. */
534
535int color_count[256];
536
537/* Register color PIXEL as allocated. */
538
539void
1dae0f0a 540register_color (unsigned long pixel)
a435fc2a 541{
a54e2c05 542 eassert (pixel < 256);
a435fc2a
GM
543 ++color_count[pixel];
544}
545
546
547/* Register color PIXEL as deallocated. */
548
549void
1dae0f0a 550unregister_color (unsigned long pixel)
a435fc2a 551{
a54e2c05 552 eassert (pixel < 256);
a435fc2a
GM
553 if (color_count[pixel] > 0)
554 --color_count[pixel];
555 else
556 abort ();
557}
558
559
560/* Register N colors from PIXELS as deallocated. */
561
562void
1dae0f0a 563unregister_colors (unsigned long *pixels, int n)
a435fc2a
GM
564{
565 int i;
566 for (i = 0; i < n; ++i)
567 unregister_color (pixels[i]);
568}
569
08dc08dc 570
a7ca3326 571DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
7ee72033 572 doc: /* Dump currently allocated colors to stderr. */)
5842a27b 573 (void)
08dc08dc
GM
574{
575 int i, n;
576
577 fputc ('\n', stderr);
178c5d9c 578
08dc08dc
GM
579 for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i)
580 if (color_count[i])
581 {
582 fprintf (stderr, "%3d: %5d", i, color_count[i]);
583 ++n;
584 if (n % 5 == 0)
585 fputc ('\n', stderr);
586 else
587 fputc ('\t', stderr);
588 }
589
590 if (n % 5 != 0)
591 fputc ('\n', stderr);
592 return Qnil;
593}
594
a435fc2a
GM
595#endif /* DEBUG_X_COLORS */
596
d12d0a9b 597
1f847cf8
GM
598/* Free colors used on frame F. PIXELS is an array of NPIXELS pixel
599 color values. Interrupt input must be blocked when this function
600 is called. */
601
602void
971de7fb 603x_free_colors (struct frame *f, long unsigned int *pixels, int npixels)
1f847cf8
GM
604{
605 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
606
607 /* If display has an immutable color map, freeing colors is not
608 necessary and some servers don't allow it. So don't do it. */
609 if (class != StaticColor && class != StaticGray && class != TrueColor)
610 {
a435fc2a 611#ifdef DEBUG_X_COLORS
08dc08dc 612 unregister_colors (pixels, npixels);
a435fc2a 613#endif
513c5806
GM
614 XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
615 pixels, npixels, 0);
08dc08dc
GM
616 }
617}
618
619
435f4c28
PE
620#ifdef USE_X_TOOLKIT
621
08dc08dc
GM
622/* Free colors used on frame F. PIXELS is an array of NPIXELS pixel
623 color values. Interrupt input must be blocked when this function
624 is called. */
625
626void
b5f03016
AS
627x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap,
628 long unsigned int *pixels, int npixels)
08dc08dc
GM
629{
630 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
631 int class = dpyinfo->visual->class;
632
633 /* If display has an immutable color map, freeing colors is not
634 necessary and some servers don't allow it. So don't do it. */
635 if (class != StaticColor && class != StaticGray && class != TrueColor)
636 {
a435fc2a 637#ifdef DEBUG_X_COLORS
08dc08dc 638 unregister_colors (pixels, npixels);
a435fc2a 639#endif
513c5806 640 XFreeColors (dpy, cmap, pixels, npixels, 0);
1f847cf8
GM
641 }
642}
435f4c28 643#endif /* USE_X_TOOLKIT */
08dc08dc 644
82641697
GM
645/* Create and return a GC for use on frame F. GC values and mask
646 are given by XGCV and MASK. */
647
55d4c1b2 648static inline GC
971de7fb 649x_create_gc (struct frame *f, long unsigned int mask, XGCValues *xgcv)
c115973b
JB
650{
651 GC gc;
82641697
GM
652 BLOCK_INPUT;
653 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv);
654 UNBLOCK_INPUT;
655 IF_DEBUG (++ngcs);
656 return gc;
657}
c115973b 658
42120bc7 659
82641697
GM
660/* Free GC which was used on frame F. */
661
55d4c1b2 662static inline void
971de7fb 663x_free_gc (struct frame *f, GC gc)
82641697 664{
ed0c79c6 665 eassert (interrupt_input_blocked);
a54e2c05 666 IF_DEBUG (eassert (--ngcs >= 0));
82641697 667 XFreeGC (FRAME_X_DISPLAY (f), gc);
82641697 668}
660ed669 669
82641697 670#endif /* HAVE_X_WINDOWS */
660ed669 671
c3cee013
JR
672#ifdef WINDOWSNT
673/* W32 emulation of GCs */
674
55d4c1b2 675static inline GC
7c3320d8 676x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
c3cee013
JR
677{
678 GC gc;
679 BLOCK_INPUT;
680 gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, xgcv);
681 UNBLOCK_INPUT;
682 IF_DEBUG (++ngcs);
683 return gc;
684}
685
686
687/* Free GC which was used on frame F. */
688
55d4c1b2 689static inline void
7c3320d8 690x_free_gc (struct frame *f, GC gc)
c3cee013 691{
a54e2c05 692 IF_DEBUG (eassert (--ngcs >= 0));
c3cee013 693 xfree (gc);
c3cee013
JR
694}
695
696#endif /* WINDOWSNT */
660ed669 697
edfda783
AR
698#ifdef HAVE_NS
699/* NS emulation of GCs */
700
55d4c1b2 701static inline GC
3d608a86 702x_create_gc (struct frame *f,
b5f03016
AS
703 unsigned long mask,
704 XGCValues *xgcv)
edfda783 705{
38182d90
PE
706 GC gc = xmalloc (sizeof *gc);
707 memcpy (gc, xgcv, sizeof (XGCValues));
edfda783
AR
708 return gc;
709}
710
55d4c1b2 711static inline void
3d608a86 712x_free_gc (struct frame *f, GC gc)
edfda783 713{
5f445726 714 xfree (gc);
edfda783
AR
715}
716#endif /* HAVE_NS */
717
c0617987
GM
718/* If FRAME is nil, return a pointer to the selected frame.
719 Otherwise, check that FRAME is a live frame, and return a pointer
720 to it. NPARAM is the parameter number of FRAME, for
721 CHECK_LIVE_FRAME. This is here because it's a frequent pattern in
722 Lisp function definitions. */
82641697 723
55d4c1b2 724static inline struct frame *
971de7fb 725frame_or_selected_frame (Lisp_Object frame, int nparam)
82641697 726{
82641697 727 if (NILP (frame))
c0617987 728 frame = selected_frame;
178c5d9c 729
b7826503 730 CHECK_LIVE_FRAME (frame);
c0617987 731 return XFRAME (frame);
42120bc7 732}
82641697 733
42120bc7 734\f
82641697
GM
735/***********************************************************************
736 Frames and faces
737 ***********************************************************************/
cd0bb842 738
82641697 739/* Initialize face cache and basic faces for frame F. */
cb637678 740
82641697 741void
971de7fb 742init_frame_faces (struct frame *f)
cb637678 743{
82641697
GM
744 /* Make a face cache, if F doesn't have one. */
745 if (FRAME_FACE_CACHE (f) == NULL)
746 FRAME_FACE_CACHE (f) = make_face_cache (f);
178c5d9c 747
c3cee013 748#ifdef HAVE_WINDOW_SYSTEM
82641697 749 /* Make the image cache. */
c3cee013 750 if (FRAME_WINDOW_P (f))
82641697 751 {
91c37b7e
CY
752 /* We initialize the image cache when creating the first frame
753 on a terminal, and not during terminal creation. This way,
754 `x-open-connection' on a tty won't create an image cache. */
354884c4 755 if (FRAME_IMAGE_CACHE (f) == NULL)
354884c4
SM
756 FRAME_IMAGE_CACHE (f) = make_image_cache ();
757 ++FRAME_IMAGE_CACHE (f)->refcount;
82641697 758 }
c3cee013 759#endif /* HAVE_WINDOW_SYSTEM */
cb637678 760
178c5d9c 761 /* Realize basic faces. Must have enough information in frame
82641697
GM
762 parameters to realize basic faces at this point. */
763#ifdef HAVE_X_WINDOWS
764 if (!FRAME_X_P (f) || FRAME_X_WINDOW (f))
c3cee013
JR
765#endif
766#ifdef WINDOWSNT
767 if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f))
f00691a3 768#endif
edfda783
AR
769#ifdef HAVE_NS
770 if (!FRAME_NS_P (f) || FRAME_NS_WINDOW (f))
82641697
GM
771#endif
772 if (!realize_basic_faces (f))
b5f03016 773 abort ();
82641697 774}
cb637678 775
cb637678 776
e2749141 777/* Free face cache of frame F. Called from delete_frame. */
cb637678 778
82641697 779void
971de7fb 780free_frame_faces (struct frame *f)
cb637678 781{
82641697 782 struct face_cache *face_cache = FRAME_FACE_CACHE (f);
178c5d9c 783
82641697
GM
784 if (face_cache)
785 {
786 free_face_cache (face_cache);
787 FRAME_FACE_CACHE (f) = NULL;
788 }
660ed669 789
c3cee013
JR
790#ifdef HAVE_WINDOW_SYSTEM
791 if (FRAME_WINDOW_P (f))
195f798e 792 {
354884c4 793 struct image_cache *image_cache = FRAME_IMAGE_CACHE (f);
82641697 794 if (image_cache)
195f798e 795 {
82641697
GM
796 --image_cache->refcount;
797 if (image_cache->refcount == 0)
798 free_image_cache (f);
195f798e
RS
799 }
800 }
c3cee013 801#endif /* HAVE_WINDOW_SYSTEM */
cb637678
JB
802}
803
82641697 804
8bd201d6
GM
805/* Clear face caches, and recompute basic faces for frame F. Call
806 this after changing frame parameters on which those faces depend,
807 or when realized faces have been freed due to changing attributes
808 of named faces. */
82641697
GM
809
810void
971de7fb 811recompute_basic_faces (struct frame *f)
cb637678 812{
82641697
GM
813 if (FRAME_FACE_CACHE (f))
814 {
8bd201d6 815 clear_face_cache (0);
18df9369
GM
816 if (!realize_basic_faces (f))
817 abort ();
82641697
GM
818 }
819}
cb637678 820
cb637678 821
82641697
GM
822/* Clear the face caches of all frames. CLEAR_FONTS_P non-zero means
823 try to free unused fonts, too. */
cb637678 824
adfea139 825void
971de7fb 826clear_face_cache (int clear_fonts_p)
cb637678 827{
c3cee013 828#ifdef HAVE_WINDOW_SYSTEM
82641697 829 Lisp_Object tail, frame;
828e66d1 830
82641697
GM
831 if (clear_fonts_p
832 || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
828e66d1 833 {
2dee4c0b
KH
834#if 0
835 /* Not yet implemented. */
836 clear_font_cache (frame);
837#endif
838
82641697
GM
839 /* From time to time see if we can unload some fonts. This also
840 frees all realized faces on all frames. Fonts needed by
841 faces will be loaded again when faces are realized again. */
842 clear_font_table_count = 0;
195f798e 843
82641697 844 FOR_EACH_FRAME (tail, frame)
195f798e 845 {
d5641fc5 846 struct frame *f = XFRAME (frame);
c3cee013 847 if (FRAME_WINDOW_P (f)
82641697 848 && FRAME_X_DISPLAY_INFO (f)->n_fonts > CLEAR_FONT_TABLE_NFONTS)
d5641fc5 849 free_all_realized_faces (frame);
82641697
GM
850 }
851 }
852 else
853 {
854 /* Clear GCs of realized faces. */
855 FOR_EACH_FRAME (tail, frame)
856 {
071048a3 857 struct frame *f = XFRAME (frame);
c3cee013 858 if (FRAME_WINDOW_P (f))
82641697 859 clear_face_gcs (FRAME_FACE_CACHE (f));
195f798e 860 }
a2bc5bdd 861 clear_image_caches (Qnil);
828e66d1 862 }
c3cee013 863#endif /* HAVE_WINDOW_SYSTEM */
cd0bb842
RS
864}
865
82641697 866
a7ca3326 867DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0,
7ee72033
MB
868 doc: /* Clear face caches on all frames.
869Optional THOROUGHLY non-nil means try to free unused fonts, too. */)
5842a27b 870 (Lisp_Object thoroughly)
cd0bb842 871{
6a3f48c7 872 clear_face_cache (!NILP (thoroughly));
ae4b4ba5
GM
873 ++face_change_count;
874 ++windows_or_buffers_changed;
82641697
GM
875 return Qnil;
876}
877
82641697
GM
878\f
879/***********************************************************************
880 X Pixmaps
881 ***********************************************************************/
882
c3cee013 883#ifdef HAVE_WINDOW_SYSTEM
82641697 884
fef04523 885DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
7ee72033 886 doc: /* Value is non-nil if OBJECT is a valid bitmap specification.
228299fa
GM
887A bitmap specification is either a string, a file name, or a list
888\(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,
889HEIGHT is its height, and DATA is a string containing the bits of
890the pixmap. Bits are stored row by row, each row occupies
7ee72033 891\(WIDTH + 7)/8 bytes. */)
5842a27b 892 (Lisp_Object object)
82641697 893{
c7ae3284 894 int pixmap_p = 0;
178c5d9c 895
c7ae3284
GM
896 if (STRINGP (object))
897 /* If OBJECT is a string, it's a file name. */
898 pixmap_p = 1;
899 else if (CONSP (object))
900 {
901 /* Otherwise OBJECT must be (WIDTH HEIGHT DATA), WIDTH and
d311d28c 902 HEIGHT must be ints > 0, and DATA must be string large
c7ae3284
GM
903 enough to hold a bitmap of the specified size. */
904 Lisp_Object width, height, data;
905
906 height = width = data = Qnil;
178c5d9c 907
c7ae3284
GM
908 if (CONSP (object))
909 {
910 width = XCAR (object);
911 object = XCDR (object);
912 if (CONSP (object))
913 {
914 height = XCAR (object);
915 object = XCDR (object);
916 if (CONSP (object))
917 data = XCAR (object);
918 }
919 }
cd0bb842 920
c8907a93 921 if (STRINGP (data)
d311d28c
PE
922 && RANGED_INTEGERP (1, width, INT_MAX)
923 && RANGED_INTEGERP (1, height, INT_MAX))
c7ae3284 924 {
d311d28c
PE
925 int bytes_per_row = ((XINT (width) + BITS_PER_CHAR - 1)
926 / BITS_PER_CHAR);
c8907a93 927 if (XINT (height) <= SBYTES (data) / bytes_per_row)
c7ae3284
GM
928 pixmap_p = 1;
929 }
930 }
931
932 return pixmap_p ? Qt : Qnil;
cd0bb842
RS
933}
934
cd0bb842 935
82641697
GM
936/* Load a bitmap according to NAME (which is either a file name or a
937 pixmap spec) for use on frame F. Value is the bitmap_id (see
938 xfns.c). If NAME is nil, return with a bitmap id of zero. If
939 bitmap cannot be loaded, display a message saying so, and return
940 zero. Store the bitmap width in *W_PTR and its height in *H_PTR,
941 if these pointers are not null. */
cd0bb842 942
0766b489 943static ptrdiff_t
b5f03016
AS
944load_pixmap (FRAME_PTR f, Lisp_Object name, unsigned int *w_ptr,
945 unsigned int *h_ptr)
cd0bb842 946{
0766b489 947 ptrdiff_t bitmap_id;
cd0bb842
RS
948
949 if (NILP (name))
82641697 950 return 0;
cd0bb842 951
d5ddd1a3 952 CHECK_TYPE (!NILP (Fbitmap_spec_p (name)), Qbitmap_spec_p, name);
cd0bb842
RS
953
954 BLOCK_INPUT;
cd0bb842
RS
955 if (CONSP (name))
956 {
957 /* Decode a bitmap spec into a bitmap. */
958
959 int h, w;
960 Lisp_Object bits;
961
962 w = XINT (Fcar (name));
963 h = XINT (Fcar (Fcdr (name)));
964 bits = Fcar (Fcdr (Fcdr (name)));
965
42a5b22f 966 bitmap_id = x_create_bitmap_from_data (f, SSDATA (bits),
cd0bb842
RS
967 w, h);
968 }
969 else
970 {
971 /* It must be a string -- a file name. */
972 bitmap_id = x_create_bitmap_from_file (f, name);
973 }
974 UNBLOCK_INPUT;
975
7812a96f 976 if (bitmap_id < 0)
82641697 977 {
2eb582ae 978 add_to_log ("Invalid or undefined bitmap `%s'", name, Qnil);
82641697 979 bitmap_id = 0;
cd0bb842 980
82641697
GM
981 if (w_ptr)
982 *w_ptr = 0;
983 if (h_ptr)
984 *h_ptr = 0;
985 }
986 else
987 {
e509cfa6 988#ifdef GLYPH_DEBUG
82641697
GM
989 ++npixmaps_allocated;
990#endif
991 if (w_ptr)
992 *w_ptr = x_bitmap_width (f, bitmap_id);
993
994 if (h_ptr)
995 *h_ptr = x_bitmap_height (f, bitmap_id);
996 }
cd0bb842
RS
997
998 return bitmap_id;
cb637678 999}
87485d6f 1000
c3cee013 1001#endif /* HAVE_WINDOW_SYSTEM */
82641697 1002
87485d6f 1003
82641697 1004\f
82641697
GM
1005/***********************************************************************
1006 X Colors
1007 ***********************************************************************/
1008
b35df831
MB
1009/* Parse RGB_LIST, and fill in the RGB fields of COLOR.
1010 RGB_LIST should contain (at least) 3 lisp integers.
1011 Return 0 if there's a problem with RGB_LIST, otherwise return 1. */
1012
1013static int
971de7fb 1014parse_rgb_list (Lisp_Object rgb_list, XColor *color)
b35df831
MB
1015{
1016#define PARSE_RGB_LIST_FIELD(field) \
1017 if (CONSP (rgb_list) && INTEGERP (XCAR (rgb_list))) \
1018 { \
1019 color->field = XINT (XCAR (rgb_list)); \
1020 rgb_list = XCDR (rgb_list); \
1021 } \
1022 else \
1023 return 0;
1024
1025 PARSE_RGB_LIST_FIELD (red);
1026 PARSE_RGB_LIST_FIELD (green);
1027 PARSE_RGB_LIST_FIELD (blue);
1028
1029 return 1;
1030}
1031
1032
1033/* Lookup on frame F the color described by the lisp string COLOR.
1034 The resulting tty color is returned in TTY_COLOR; if STD_COLOR is
1035 non-zero, then the `standard' definition of the same color is
1036 returned in it. */
1037
1038static int
b5f03016
AS
1039tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
1040 XColor *std_color)
b35df831
MB
1041{
1042 Lisp_Object frame, color_desc;
1043
1044 if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc)))
1045 return 0;
1046
1047 XSETFRAME (frame, f);
1048
1049 color_desc = call2 (Qtty_color_desc, color, frame);
1050 if (CONSP (color_desc) && CONSP (XCDR (color_desc)))
1051 {
1052 Lisp_Object rgb;
1053
1054 if (! INTEGERP (XCAR (XCDR (color_desc))))
1055 return 0;
1056
1057 tty_color->pixel = XINT (XCAR (XCDR (color_desc)));
1058
1059 rgb = XCDR (XCDR (color_desc));
1060 if (! parse_rgb_list (rgb, tty_color))
1061 return 0;
1062
1063 /* Should we fill in STD_COLOR too? */
1064 if (std_color)
1065 {
1066 /* Default STD_COLOR to the same as TTY_COLOR. */
1067 *std_color = *tty_color;
1068
1069 /* Do a quick check to see if the returned descriptor is
1070 actually _exactly_ equal to COLOR, otherwise we have to
1071 lookup STD_COLOR separately. If it's impossible to lookup
1072 a standard color, we just give up and use TTY_COLOR. */
1073 if ((!STRINGP (XCAR (color_desc))
1074 || NILP (Fstring_equal (color, XCAR (color_desc))))
51f86bfc 1075 && !NILP (Ffboundp (Qtty_color_standard_values)))
b35df831
MB
1076 {
1077 /* Look up STD_COLOR separately. */
1078 rgb = call1 (Qtty_color_standard_values, color);
1079 if (! parse_rgb_list (rgb, std_color))
1080 return 0;
1081 }
1082 }
1083
1084 return 1;
1085 }
1086 else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
1087 /* We were called early during startup, and the colors are not
1088 yet set up in tty-defined-color-alist. Don't return a failure
1089 indication, since this produces the annoying "Unable to
1090 load color" messages in the *Messages* buffer. */
1091 return 1;
1092 else
1093 /* tty-color-desc seems to have returned a bad value. */
1094 return 0;
1095}
1096
2d764c78 1097/* A version of defined_color for non-X frames. */
08dc08dc 1098
6b463e58 1099static int
eec47d6b
DN
1100tty_defined_color (struct frame *f, const char *color_name,
1101 XColor *color_def, int alloc)
2d764c78 1102{
2d764c78
EZ
1103 int status = 1;
1104
b35df831 1105 /* Defaults. */
177c0ea7 1106 color_def->pixel = FACE_TTY_DEFAULT_COLOR;
b35df831
MB
1107 color_def->red = 0;
1108 color_def->blue = 0;
1109 color_def->green = 0;
a61c12d5 1110
b35df831 1111 if (*color_name)
3062711f 1112 status = tty_lookup_color (f, build_string (color_name), color_def, NULL);
b35df831
MB
1113
1114 if (color_def->pixel == FACE_TTY_DEFAULT_COLOR && *color_name)
f9d2fdc4
EZ
1115 {
1116 if (strcmp (color_name, "unspecified-fg") == 0)
b35df831 1117 color_def->pixel = FACE_TTY_DEFAULT_FG_COLOR;
f9d2fdc4 1118 else if (strcmp (color_name, "unspecified-bg") == 0)
b35df831 1119 color_def->pixel = FACE_TTY_DEFAULT_BG_COLOR;
f9d2fdc4
EZ
1120 }
1121
b35df831 1122 if (color_def->pixel != FACE_TTY_DEFAULT_COLOR)
3b451f74
EZ
1123 status = 1;
1124
2d764c78
EZ
1125 return status;
1126}
1127
08dc08dc
GM
1128
1129/* Decide if color named COLOR_NAME is valid for the display
1130 associated with the frame F; if so, return the rgb values in
1131 COLOR_DEF. If ALLOC is nonzero, allocate a new colormap cell.
2d764c78
EZ
1132
1133 This does the right thing for any type of frame. */
08dc08dc 1134
435f4c28 1135static int
b5f03016
AS
1136defined_color (struct frame *f, const char *color_name, XColor *color_def,
1137 int alloc)
2d764c78
EZ
1138{
1139 if (!FRAME_WINDOW_P (f))
1140 return tty_defined_color (f, color_name, color_def, alloc);
82641697 1141#ifdef HAVE_X_WINDOWS
2d764c78
EZ
1142 else if (FRAME_X_P (f))
1143 return x_defined_color (f, color_name, color_def, alloc);
1144#endif
1145#ifdef WINDOWSNT
1146 else if (FRAME_W32_P (f))
2d764c78
EZ
1147 return w32_defined_color (f, color_name, color_def, alloc);
1148#endif
edfda783
AR
1149#ifdef HAVE_NS
1150 else if (FRAME_NS_P (f))
1151 return ns_defined_color (f, color_name, color_def, alloc, 1);
2d764c78
EZ
1152#endif
1153 else
1154 abort ();
1155}
1156
08dc08dc
GM
1157
1158/* Given the index IDX of a tty color on frame F, return its name, a
1159 Lisp string. */
2d764c78
EZ
1160
1161Lisp_Object
971de7fb 1162tty_color_name (struct frame *f, int idx)
2d764c78 1163{
2d764c78
EZ
1164 if (idx >= 0 && !NILP (Ffboundp (Qtty_color_by_index)))
1165 {
a61c12d5
EZ
1166 Lisp_Object frame;
1167 Lisp_Object coldesc;
1168
1169 XSETFRAME (frame, f);
1170 coldesc = call2 (Qtty_color_by_index, make_number (idx), frame);
2d764c78
EZ
1171
1172 if (!NILP (coldesc))
1173 return XCAR (coldesc);
1174 }
1175#ifdef MSDOS
1176 /* We can have an MSDOG frame under -nw for a short window of
1177 opportunity before internal_terminal_init is called. DTRT. */
1178 if (FRAME_MSDOS_P (f) && !inhibit_window_system)
1179 return msdos_stdcolor_name (idx);
1180#endif
1181
ef917393
EZ
1182 if (idx == FACE_TTY_DEFAULT_FG_COLOR)
1183 return build_string (unspecified_fg);
1184 if (idx == FACE_TTY_DEFAULT_BG_COLOR)
1185 return build_string (unspecified_bg);
c3cee013 1186
ef917393 1187 return Qunspecified;
2d764c78 1188}
82641697 1189
08dc08dc 1190
82641697 1191/* Return non-zero if COLOR_NAME is a shade of gray (or white or
71433d39
RS
1192 black) on frame F.
1193
1194 The criterion implemented here is not a terribly sophisticated one. */
82641697
GM
1195
1196static int
eec47d6b 1197face_color_gray_p (struct frame *f, const char *color_name)
82641697
GM
1198{
1199 XColor color;
1200 int gray_p;
1201
1202 if (defined_color (f, color_name, &color, 0))
e4769531 1203 gray_p = (/* Any color sufficiently close to black counts as gray. */
71433d39
RS
1204 (color.red < 5000 && color.green < 5000 && color.blue < 5000)
1205 ||
1ea40aa2 1206 ((eabs (color.red - color.green)
71433d39 1207 < max (color.red, color.green) / 20)
1ea40aa2 1208 && (eabs (color.green - color.blue)
71433d39 1209 < max (color.green, color.blue) / 20)
1ea40aa2 1210 && (eabs (color.blue - color.red)
71433d39 1211 < max (color.blue, color.red) / 20)));
87485d6f 1212 else
82641697 1213 gray_p = 0;
178c5d9c 1214
82641697 1215 return gray_p;
87485d6f 1216}
87485d6f 1217
cb637678 1218
82641697
GM
1219/* Return non-zero if color COLOR_NAME can be displayed on frame F.
1220 BACKGROUND_P non-zero means the color will be used as background
1221 color. */
1222
1223static int
b5f03016
AS
1224face_color_supported_p (struct frame *f, const char *color_name,
1225 int background_p)
82641697
GM
1226{
1227 Lisp_Object frame;
2d764c78 1228 XColor not_used;
82641697
GM
1229
1230 XSETFRAME (frame, f);
6b61353c 1231 return
6a46b96b 1232#ifdef HAVE_WINDOW_SYSTEM
6b61353c
KH
1233 FRAME_WINDOW_P (f)
1234 ? (!NILP (Fxw_display_color_p (frame))
05131107
JR
1235 || xstrcasecmp (color_name, "black") == 0
1236 || xstrcasecmp (color_name, "white") == 0
6b61353c
KH
1237 || (background_p
1238 && face_color_gray_p (f, color_name))
1239 || (!NILP (Fx_display_grayscale_p (frame))
1240 && face_color_gray_p (f, color_name)))
1241 :
1242#endif
1243 tty_defined_color (f, color_name, &not_used, 0);
2d764c78 1244}
82641697
GM
1245
1246
da47150d 1247DEFUN ("color-gray-p", Fcolor_gray_p, Scolor_gray_p, 1, 2, 0,
7ee72033 1248 doc: /* Return non-nil if COLOR is a shade of gray (or white or black).
228299fa 1249FRAME specifies the frame and thus the display for interpreting COLOR.
7ee72033 1250If FRAME is nil or omitted, use the selected frame. */)
5842a27b 1251 (Lisp_Object color, Lisp_Object frame)
cb637678 1252{
2d764c78
EZ
1253 struct frame *f;
1254
b7826503 1255 CHECK_STRING (color);
6b61353c
KH
1256 if (NILP (frame))
1257 frame = selected_frame;
1258 else
1259 CHECK_FRAME (frame);
2d764c78 1260 f = XFRAME (frame);
42a5b22f 1261 return face_color_gray_p (f, SSDATA (color)) ? Qt : Qnil;
82641697 1262}
660ed669 1263
fffc2367 1264
da47150d 1265DEFUN ("color-supported-p", Fcolor_supported_p,
2e1bb1c3 1266 Scolor_supported_p, 1, 3, 0,
7ee72033 1267 doc: /* Return non-nil if COLOR can be displayed on FRAME.
228299fa 1268BACKGROUND-P non-nil means COLOR is used as a background.
fc820cc5 1269Otherwise, this function tells whether it can be used as a foreground.
228299fa 1270If FRAME is nil or omitted, use the selected frame.
7ee72033 1271COLOR must be a valid color name. */)
5842a27b 1272 (Lisp_Object color, Lisp_Object frame, Lisp_Object background_p)
82641697 1273{
2d764c78
EZ
1274 struct frame *f;
1275
b7826503 1276 CHECK_STRING (color);
6b61353c
KH
1277 if (NILP (frame))
1278 frame = selected_frame;
1279 else
1280 CHECK_FRAME (frame);
2d764c78 1281 f = XFRAME (frame);
42a5b22f 1282 if (face_color_supported_p (f, SSDATA (color), !NILP (background_p)))
82641697
GM
1283 return Qt;
1284 return Qnil;
1285}
7b37f67b 1286
08dc08dc 1287
82641697
GM
1288/* Load color with name NAME for use by face FACE on frame F.
1289 TARGET_INDEX must be one of LFACE_FOREGROUND_INDEX,
1290 LFACE_BACKGROUND_INDEX, LFACE_UNDERLINE_INDEX, LFACE_OVERLINE_INDEX,
1291 LFACE_STRIKE_THROUGH_INDEX, or LFACE_BOX_INDEX. Value is the
1292 pixel color. If color cannot be loaded, display a message, and
1293 return the foreground, background or underline color of F, but
1294 record that fact in flags of the face so that we don't try to free
1295 these colors. */
1296
44747bd0 1297unsigned long
b5f03016
AS
1298load_color (struct frame *f, struct face *face, Lisp_Object name,
1299 enum lface_attribute_index target_index)
82641697
GM
1300{
1301 XColor color;
178c5d9c 1302
a54e2c05
DA
1303 eassert (STRINGP (name));
1304 eassert (target_index == LFACE_FOREGROUND_INDEX
82641697
GM
1305 || target_index == LFACE_BACKGROUND_INDEX
1306 || target_index == LFACE_UNDERLINE_INDEX
1307 || target_index == LFACE_OVERLINE_INDEX
1308 || target_index == LFACE_STRIKE_THROUGH_INDEX
1309 || target_index == LFACE_BOX_INDEX);
178c5d9c 1310
82641697
GM
1311 /* if the color map is full, defined_color will return a best match
1312 to the values in an existing cell. */
42a5b22f 1313 if (!defined_color (f, SSDATA (name), &color, 1))
82641697 1314 {
2d764c78 1315 add_to_log ("Unable to load color \"%s\"", name, Qnil);
178c5d9c 1316
82641697 1317 switch (target_index)
1120eb5e 1318 {
82641697
GM
1319 case LFACE_FOREGROUND_INDEX:
1320 face->foreground_defaulted_p = 1;
1321 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1322 break;
178c5d9c 1323
82641697
GM
1324 case LFACE_BACKGROUND_INDEX:
1325 face->background_defaulted_p = 1;
1326 color.pixel = FRAME_BACKGROUND_PIXEL (f);
1327 break;
178c5d9c 1328
82641697
GM
1329 case LFACE_UNDERLINE_INDEX:
1330 face->underline_defaulted_p = 1;
1331 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1332 break;
178c5d9c 1333
82641697
GM
1334 case LFACE_OVERLINE_INDEX:
1335 face->overline_color_defaulted_p = 1;
1336 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1120eb5e 1337 break;
178c5d9c 1338
82641697
GM
1339 case LFACE_STRIKE_THROUGH_INDEX:
1340 face->strike_through_color_defaulted_p = 1;
1341 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1342 break;
178c5d9c 1343
82641697
GM
1344 case LFACE_BOX_INDEX:
1345 face->box_color_defaulted_p = 1;
1346 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1347 break;
1348
1349 default:
1350 abort ();
1120eb5e 1351 }
82641697 1352 }
e509cfa6 1353#ifdef GLYPH_DEBUG
82641697
GM
1354 else
1355 ++ncolors_allocated;
1356#endif
178c5d9c 1357
82641697
GM
1358 return color.pixel;
1359}
1120eb5e 1360
08dc08dc 1361
c3cee013 1362#ifdef HAVE_WINDOW_SYSTEM
1120eb5e 1363
82641697
GM
1364/* Load colors for face FACE which is used on frame F. Colors are
1365 specified by slots LFACE_BACKGROUND_INDEX and LFACE_FOREGROUND_INDEX
1366 of ATTRS. If the background color specified is not supported on F,
1367 try to emulate gray colors with a stipple from Vface_default_stipple. */
1368
1369static void
971de7fb 1370load_face_colors (struct frame *f, struct face *face, Lisp_Object *attrs)
82641697
GM
1371{
1372 Lisp_Object fg, bg;
1373
1374 bg = attrs[LFACE_BACKGROUND_INDEX];
1375 fg = attrs[LFACE_FOREGROUND_INDEX];
1376
1377 /* Swap colors if face is inverse-video. */
1378 if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
1379 {
1380 Lisp_Object tmp;
1381 tmp = fg;
1382 fg = bg;
1383 bg = tmp;
1384 }
1385
1386 /* Check for support for foreground, not for background because
1387 face_color_supported_p is smart enough to know that grays are
1388 "supported" as background because we are supposed to use stipple
1389 for them. */
42a5b22f 1390 if (!face_color_supported_p (f, SSDATA (bg), 0)
fef04523 1391 && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
82641697
GM
1392 {
1393 x_destroy_bitmap (f, face->stipple);
1394 face->stipple = load_pixmap (f, Vface_default_stipple,
1395 &face->pixmap_w, &face->pixmap_h);
1396 }
82641697 1397
be8a72f4 1398 face->background = load_color (f, face, bg, LFACE_BACKGROUND_INDEX);
82641697 1399 face->foreground = load_color (f, face, fg, LFACE_FOREGROUND_INDEX);
cb637678
JB
1400}
1401
660ed669 1402
82641697 1403/* Free color PIXEL on frame F. */
cd0bb842 1404
cb637678 1405void
971de7fb 1406unload_color (struct frame *f, long unsigned int pixel)
cb637678 1407{
c3cee013 1408#ifdef HAVE_X_WINDOWS
30a7ac22
GM
1409 if (pixel != -1)
1410 {
1411 BLOCK_INPUT;
1412 x_free_colors (f, &pixel, 1);
1413 UNBLOCK_INPUT;
1414 }
c3cee013 1415#endif
82641697
GM
1416}
1417
1418
1419/* Free colors allocated for FACE. */
1420
1421static void
971de7fb 1422free_face_colors (struct frame *f, struct face *face)
82641697 1423{
edfda783 1424/* PENDING(NS): need to do something here? */
c3cee013 1425#ifdef HAVE_X_WINDOWS
28a072fe
GM
1426 if (face->colors_copied_bitwise_p)
1427 return;
1428
08dc08dc 1429 BLOCK_INPUT;
178c5d9c 1430
08dc08dc
GM
1431 if (!face->foreground_defaulted_p)
1432 {
1433 x_free_colors (f, &face->foreground, 1);
1434 IF_DEBUG (--ncolors_allocated);
1435 }
178c5d9c 1436
08dc08dc
GM
1437 if (!face->background_defaulted_p)
1438 {
1439 x_free_colors (f, &face->background, 1);
1440 IF_DEBUG (--ncolors_allocated);
1441 }
82641697 1442
08dc08dc
GM
1443 if (face->underline_p
1444 && !face->underline_defaulted_p)
1445 {
1446 x_free_colors (f, &face->underline_color, 1);
1447 IF_DEBUG (--ncolors_allocated);
1448 }
82641697 1449
08dc08dc
GM
1450 if (face->overline_p
1451 && !face->overline_color_defaulted_p)
1452 {
1453 x_free_colors (f, &face->overline_color, 1);
1454 IF_DEBUG (--ncolors_allocated);
1455 }
82641697 1456
08dc08dc
GM
1457 if (face->strike_through_p
1458 && !face->strike_through_color_defaulted_p)
1459 {
1460 x_free_colors (f, &face->strike_through_color, 1);
1461 IF_DEBUG (--ncolors_allocated);
1462 }
82641697 1463
08dc08dc
GM
1464 if (face->box != FACE_NO_BOX
1465 && !face->box_color_defaulted_p)
1466 {
1467 x_free_colors (f, &face->box_color, 1);
1468 IF_DEBUG (--ncolors_allocated);
82641697 1469 }
08dc08dc
GM
1470
1471 UNBLOCK_INPUT;
2d764c78 1472#endif /* HAVE_X_WINDOWS */
c3cee013 1473}
08dc08dc 1474
c3cee013 1475#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
1476
1477
1478\f
1479/***********************************************************************
1480 XLFD Font Names
1481 ***********************************************************************/
1482
1483/* An enumerator for each field of an XLFD font name. */
1484
1485enum xlfd_field
1486{
1487 XLFD_FOUNDRY,
1488 XLFD_FAMILY,
1489 XLFD_WEIGHT,
1490 XLFD_SLANT,
1491 XLFD_SWIDTH,
1492 XLFD_ADSTYLE,
1493 XLFD_PIXEL_SIZE,
1494 XLFD_POINT_SIZE,
1495 XLFD_RESX,
1496 XLFD_RESY,
1497 XLFD_SPACING,
1498 XLFD_AVGWIDTH,
1499 XLFD_REGISTRY,
1500 XLFD_ENCODING,
1501 XLFD_LAST
1502};
1503
178c5d9c 1504/* An enumerator for each possible slant value of a font. Taken from
82641697
GM
1505 the XLFD specification. */
1506
1507enum xlfd_slant
1508{
1509 XLFD_SLANT_UNKNOWN,
1510 XLFD_SLANT_ROMAN,
1511 XLFD_SLANT_ITALIC,
1512 XLFD_SLANT_OBLIQUE,
1513 XLFD_SLANT_REVERSE_ITALIC,
1514 XLFD_SLANT_REVERSE_OBLIQUE,
1515 XLFD_SLANT_OTHER
1516};
1517
1518/* Relative font weight according to XLFD documentation. */
1519
1520enum xlfd_weight
1521{
1522 XLFD_WEIGHT_UNKNOWN,
1523 XLFD_WEIGHT_ULTRA_LIGHT, /* 10 */
1524 XLFD_WEIGHT_EXTRA_LIGHT, /* 20 */
1525 XLFD_WEIGHT_LIGHT, /* 30 */
1526 XLFD_WEIGHT_SEMI_LIGHT, /* 40: SemiLight, Book, ... */
1527 XLFD_WEIGHT_MEDIUM, /* 50: Medium, Normal, Regular, ... */
1528 XLFD_WEIGHT_SEMI_BOLD, /* 60: SemiBold, DemiBold, ... */
1529 XLFD_WEIGHT_BOLD, /* 70: Bold, ... */
1530 XLFD_WEIGHT_EXTRA_BOLD, /* 80: ExtraBold, Heavy, ... */
1531 XLFD_WEIGHT_ULTRA_BOLD /* 90: UltraBold, Black, ... */
1532};
1533
1534/* Relative proportionate width. */
1535
1536enum xlfd_swidth
1537{
1538 XLFD_SWIDTH_UNKNOWN,
1539 XLFD_SWIDTH_ULTRA_CONDENSED, /* 10 */
1540 XLFD_SWIDTH_EXTRA_CONDENSED, /* 20 */
1541 XLFD_SWIDTH_CONDENSED, /* 30: Condensed, Narrow, Compressed, ... */
1542 XLFD_SWIDTH_SEMI_CONDENSED, /* 40: semicondensed */
1543 XLFD_SWIDTH_MEDIUM, /* 50: Medium, Normal, Regular, ... */
1544 XLFD_SWIDTH_SEMI_EXPANDED, /* 60: SemiExpanded, DemiExpanded, ... */
1545 XLFD_SWIDTH_EXPANDED, /* 70: Expanded... */
1546 XLFD_SWIDTH_EXTRA_EXPANDED, /* 80: ExtraExpanded, Wide... */
1547 XLFD_SWIDTH_ULTRA_EXPANDED /* 90: UltraExpanded... */
1548};
1549
82641697
GM
1550/* Order by which font selection chooses fonts. The default values
1551 mean `first, find a best match for the font width, then for the
1552 font height, then for weight, then for slant.' This variable can be
1553 set via set-face-font-sort-order. */
1554
1555static int font_sort_order[4];
82641697 1556
2dee4c0b
KH
1557#ifdef HAVE_WINDOW_SYSTEM
1558
2dee4c0b 1559static enum font_property_index font_props_for_sorting[FONT_SIZE_INDEX];
82641697 1560
2dee4c0b 1561static int
971de7fb 1562compare_fonts_by_sort_order (const void *v1, const void *v2)
2dee4c0b
KH
1563{
1564 Lisp_Object font1 = *(Lisp_Object *) v1;
1565 Lisp_Object font2 = *(Lisp_Object *) v2;
1566 int i;
d5ab09cd 1567
2dee4c0b
KH
1568 for (i = 0; i < FONT_SIZE_INDEX; i++)
1569 {
1570 enum font_property_index idx = font_props_for_sorting[i];
1571 Lisp_Object val1 = AREF (font1, idx), val2 = AREF (font2, idx);
1572 int result;
82641697 1573
2dee4c0b
KH
1574 if (idx <= FONT_REGISTRY_INDEX)
1575 {
1576 if (STRINGP (val1))
42a5b22f 1577 result = STRINGP (val2) ? strcmp (SSDATA (val1), SSDATA (val2)) : -1;
2dee4c0b
KH
1578 else
1579 result = STRINGP (val2) ? 1 : 0;
1580 }
1581 else
1582 {
1583 if (INTEGERP (val1))
d311d28c
PE
1584 result = (INTEGERP (val2) && XINT (val1) >= XINT (val2)
1585 ? XINT (val1) > XINT (val2)
1586 : -1);
2dee4c0b
KH
1587 else
1588 result = INTEGERP (val2) ? 1 : 0;
1589 }
1590 if (result)
1591 return result;
1592 }
1593 return 0;
82641697
GM
1594}
1595
2dee4c0b
KH
1596DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
1597 doc: /* Return a list of available fonts of family FAMILY on FRAME.
1598If FAMILY is omitted or nil, list all families.
1599Otherwise, FAMILY must be a string, possibly containing wildcards
1600`?' and `*'.
1601If FRAME is omitted or nil, use the selected frame.
1602Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
1603SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
1604FAMILY is the font family name. POINT-SIZE is the size of the
1605font in 1/10 pt. WIDTH, WEIGHT, and SLANT are symbols describing the
1606width, weight and slant of the font. These symbols are the same as for
1607face attributes. FIXED-P is non-nil if the font is fixed-pitch.
1608FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
1609giving the registry and encoding of the font.
1610The result list is sorted according to the current setting of
1611the face font sort order. */)
5842a27b 1612 (Lisp_Object family, Lisp_Object frame)
2dee4c0b 1613{
022eef62 1614 Lisp_Object font_spec, list, *drivers, vec;
d311d28c
PE
1615 ptrdiff_t i, nfonts;
1616 EMACS_INT ndrivers;
2dee4c0b 1617 Lisp_Object result;
d311d28c 1618 USE_SAFE_ALLOCA;
82641697 1619
62057df6
KH
1620 if (NILP (frame))
1621 frame = selected_frame;
1622 CHECK_LIVE_FRAME (frame);
1623
1624 font_spec = Ffont_spec (0, NULL);
2dee4c0b
KH
1625 if (!NILP (family))
1626 {
1627 CHECK_STRING (family);
6b1f69f1 1628 font_parse_family_registry (family, Qnil, font_spec);
2dee4c0b 1629 }
022eef62
CY
1630
1631 list = font_list_entities (frame, font_spec);
1632 if (NILP (list))
2dee4c0b 1633 return Qnil;
022eef62
CY
1634
1635 /* Sort the font entities. */
1636 for (i = 0; i < 4; i++)
1637 switch (font_sort_order[i])
1638 {
1639 case XLFD_SWIDTH:
1640 font_props_for_sorting[i] = FONT_WIDTH_INDEX; break;
1641 case XLFD_POINT_SIZE:
1642 font_props_for_sorting[i] = FONT_SIZE_INDEX; break;
1643 case XLFD_WEIGHT:
1644 font_props_for_sorting[i] = FONT_WEIGHT_INDEX; break;
1645 default:
1646 font_props_for_sorting[i] = FONT_SLANT_INDEX; break;
1647 }
1648 font_props_for_sorting[i++] = FONT_FAMILY_INDEX;
1649 font_props_for_sorting[i++] = FONT_FOUNDRY_INDEX;
1650 font_props_for_sorting[i++] = FONT_ADSTYLE_INDEX;
1651 font_props_for_sorting[i++] = FONT_REGISTRY_INDEX;
1652
1653 ndrivers = XINT (Flength (list));
d311d28c 1654 SAFE_ALLOCA_LISP (drivers, ndrivers);
022eef62
CY
1655 for (i = 0; i < ndrivers; i++, list = XCDR (list))
1656 drivers[i] = XCAR (list);
1657 vec = Fvconcat (ndrivers, drivers);
1658 nfonts = ASIZE (vec);
1659
1660 qsort (XVECTOR (vec)->contents, nfonts, sizeof (Lisp_Object),
1661 compare_fonts_by_sort_order);
82641697 1662
2dee4c0b
KH
1663 result = Qnil;
1664 for (i = nfonts - 1; i >= 0; --i)
1665 {
1666 Lisp_Object font = AREF (vec, i);
1667 Lisp_Object v = Fmake_vector (make_number (8), Qnil);
1668 int point;
1669 Lisp_Object spacing;
1670
1671 ASET (v, 0, AREF (font, FONT_FAMILY_INDEX));
1672 ASET (v, 1, FONT_WIDTH_SYMBOLIC (font));
1673 point = PIXEL_TO_POINT (XINT (AREF (font, FONT_SIZE_INDEX)) * 10,
62057df6 1674 XFRAME (frame)->resy);
2dee4c0b
KH
1675 ASET (v, 2, make_number (point));
1676 ASET (v, 3, FONT_WEIGHT_SYMBOLIC (font));
1677 ASET (v, 4, FONT_SLANT_SYMBOLIC (font));
1678 spacing = Ffont_get (font, QCspacing);
1679 ASET (v, 5, (NILP (spacing) || EQ (spacing, Qp)) ? Qnil : Qt);
62057df6 1680 ASET (v, 6, Ffont_xlfd_name (font, Qnil));
2dee4c0b 1681 ASET (v, 7, AREF (font, FONT_REGISTRY_INDEX));
82641697 1682
2dee4c0b
KH
1683 result = Fcons (v, result);
1684 }
82641697 1685
d311d28c 1686 SAFE_FREE ();
2dee4c0b 1687 return result;
82641697
GM
1688}
1689
2dee4c0b
KH
1690DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
1691 doc: /* Return a list of the names of available fonts matching PATTERN.
1692If optional arguments FACE and FRAME are specified, return only fonts
1693the same size as FACE on FRAME.
21bdb81a
CY
1694
1695PATTERN should be a string containing a font name in the XLFD,
1696Fontconfig, or GTK format. A font name given in the XLFD format may
1697contain wildcard characters:
2dee4c0b
KH
1698 the * character matches any substring, and
1699 the ? character matches any single character.
1700 PATTERN is case-insensitive.
2dee4c0b
KH
1701
1702The return value is a list of strings, suitable as arguments to
d5ab09cd 1703`set-face-font'.
82641697 1704
2dee4c0b
KH
1705Fonts Emacs can't use may or may not be excluded
1706even if they match PATTERN and FACE.
1707The optional fourth argument MAXIMUM sets a limit on how many
1708fonts to match. The first MAXIMUM fonts are reported.
1709The optional fifth argument WIDTH, if specified, is a number of columns
1710occupied by a character of a font. In that case, return only fonts
1711the WIDTH times as wide as FACE on FRAME. */)
b5f03016
AS
1712 (Lisp_Object pattern, Lisp_Object face, Lisp_Object frame,
1713 Lisp_Object maximum, Lisp_Object width)
82641697 1714{
2dee4c0b 1715 struct frame *f;
1e9966ea 1716 int size, avgwidth IF_LINT (= 0);
82641697 1717
2dee4c0b
KH
1718 check_x ();
1719 CHECK_STRING (pattern);
82641697 1720
2dee4c0b
KH
1721 if (! NILP (maximum))
1722 CHECK_NATNUM (maximum);
82641697 1723
2dee4c0b
KH
1724 if (!NILP (width))
1725 CHECK_NUMBER (width);
82641697 1726
2dee4c0b
KH
1727 /* We can't simply call check_x_frame because this function may be
1728 called before any frame is created. */
1729 if (NILP (frame))
1730 frame = selected_frame;
1731 f = frame_or_selected_frame (frame, 2);
1732 if (! FRAME_WINDOW_P (f))
1733 {
1734 /* Perhaps we have not yet created any frame. */
1735 f = NULL;
1736 frame = Qnil;
1737 face = Qnil;
1738 }
82641697 1739
2dee4c0b 1740 /* Determine the width standard for comparison with the fonts we find. */
82641697 1741
2dee4c0b
KH
1742 if (NILP (face))
1743 size = 0;
1744 else
1745 {
1746 /* This is of limited utility since it works with character
1747 widths. Keep it for compatibility. --gerd. */
1748 int face_id = lookup_named_face (f, face, 0);
071048a3
PE
1749 struct face *width_face = (face_id < 0
1750 ? NULL
1751 : FACE_FROM_ID (f, face_id));
82641697 1752
071048a3 1753 if (width_face && width_face->font)
2dee4c0b 1754 {
071048a3
PE
1755 size = width_face->font->pixel_size;
1756 avgwidth = width_face->font->average_width;
2dee4c0b
KH
1757 }
1758 else
1759 {
1760 size = FRAME_FONT (f)->pixel_size;
1761 avgwidth = FRAME_FONT (f)->average_width;
1762 }
1763 if (!NILP (width))
1764 avgwidth *= XINT (width);
1765 }
82641697 1766
2dee4c0b
KH
1767 {
1768 Lisp_Object font_spec;
a4eec626 1769 Lisp_Object args[2], tail;
82641697 1770
2dee4c0b 1771 font_spec = font_spec_from_name (pattern);
21bdb81a
CY
1772 if (!FONTP (font_spec))
1773 signal_error ("Invalid font name", pattern);
1774
2dee4c0b
KH
1775 if (size)
1776 {
1777 Ffont_put (font_spec, QCsize, make_number (size));
1778 Ffont_put (font_spec, QCavgwidth, make_number (avgwidth));
1779 }
34e97272 1780 args[0] = Flist_fonts (font_spec, frame, maximum, font_spec);
a4eec626 1781 for (tail = args[0]; CONSP (tail); tail = XCDR (tail))
493dcf2c
KH
1782 {
1783 Lisp_Object font_entity;
1784
1785 font_entity = XCAR (tail);
1786 if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
1787 || XINT (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
1788 && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
1789 {
1790 /* This is a scalable font. For backward compatibility,
1791 we set the specified size. */
92470028 1792 font_entity = copy_font_spec (font_entity);
493dcf2c
KH
1793 ASET (font_entity, FONT_SIZE_INDEX,
1794 AREF (font_spec, FONT_SIZE_INDEX));
1795 }
1796 XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
1797 }
2dee4c0b
KH
1798 if (NILP (frame))
1799 /* We don't have to check fontsets. */
1800 return args[0];
1801 args[1] = list_fontsets (f, pattern, size);
1802 return Fnconc (2, args);
1803 }
82641697 1804}
178c5d9c 1805
2dee4c0b 1806#endif /* HAVE_WINDOW_SYSTEM */
82641697 1807
82641697
GM
1808\f
1809/***********************************************************************
1810 Lisp Faces
1811 ***********************************************************************/
1812
a08332c0
GM
1813/* Access face attributes of face LFACE, a Lisp vector. */
1814
1815#define LFACE_FAMILY(LFACE) AREF ((LFACE), LFACE_FAMILY_INDEX)
53aaf1e2 1816#define LFACE_FOUNDRY(LFACE) AREF ((LFACE), LFACE_FOUNDRY_INDEX)
a08332c0
GM
1817#define LFACE_HEIGHT(LFACE) AREF ((LFACE), LFACE_HEIGHT_INDEX)
1818#define LFACE_WEIGHT(LFACE) AREF ((LFACE), LFACE_WEIGHT_INDEX)
1819#define LFACE_SLANT(LFACE) AREF ((LFACE), LFACE_SLANT_INDEX)
1820#define LFACE_UNDERLINE(LFACE) AREF ((LFACE), LFACE_UNDERLINE_INDEX)
1821#define LFACE_INVERSE(LFACE) AREF ((LFACE), LFACE_INVERSE_INDEX)
1822#define LFACE_FOREGROUND(LFACE) AREF ((LFACE), LFACE_FOREGROUND_INDEX)
1823#define LFACE_BACKGROUND(LFACE) AREF ((LFACE), LFACE_BACKGROUND_INDEX)
1824#define LFACE_STIPPLE(LFACE) AREF ((LFACE), LFACE_STIPPLE_INDEX)
1825#define LFACE_SWIDTH(LFACE) AREF ((LFACE), LFACE_SWIDTH_INDEX)
1826#define LFACE_OVERLINE(LFACE) AREF ((LFACE), LFACE_OVERLINE_INDEX)
1827#define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
1828#define LFACE_BOX(LFACE) AREF ((LFACE), LFACE_BOX_INDEX)
1829#define LFACE_FONT(LFACE) AREF ((LFACE), LFACE_FONT_INDEX)
1830#define LFACE_INHERIT(LFACE) AREF ((LFACE), LFACE_INHERIT_INDEX)
763bc839 1831#define LFACE_FONTSET(LFACE) AREF ((LFACE), LFACE_FONTSET_INDEX)
82641697
GM
1832
1833/* Non-zero if LFACE is a Lisp face. A Lisp face is a vector of size
1834 LFACE_VECTOR_SIZE which has the symbol `face' in slot 0. */
1835
1836#define LFACEP(LFACE) \
1837 (VECTORP (LFACE) \
77b37c05 1838 && ASIZE (LFACE) == LFACE_VECTOR_SIZE \
a08332c0 1839 && EQ (AREF (LFACE, 0), Qface))
82641697 1840
178c5d9c 1841
e509cfa6 1842#ifdef GLYPH_DEBUG
82641697
GM
1843
1844/* Check consistency of Lisp face attribute vector ATTRS. */
1845
1846static void
7d7d0045 1847check_lface_attrs (Lisp_Object *attrs)
82641697 1848{
a54e2c05 1849 eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
2ff10663 1850 || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
82641697 1851 || STRINGP (attrs[LFACE_FAMILY_INDEX]));
a54e2c05 1852 eassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
53aaf1e2
KH
1853 || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX])
1854 || STRINGP (attrs[LFACE_FOUNDRY_INDEX]));
a54e2c05 1855 eassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
2ff10663 1856 || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
82641697 1857 || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
a54e2c05 1858 eassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
2ff10663 1859 || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
2c20458f
MB
1860 || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
1861 || FLOATP (attrs[LFACE_HEIGHT_INDEX])
1862 || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
a54e2c05 1863 eassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
2ff10663 1864 || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX])
82641697 1865 || SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
a54e2c05 1866 eassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
2ff10663 1867 || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX])
82641697 1868 || SYMBOLP (attrs[LFACE_SLANT_INDEX]));
a54e2c05 1869 eassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
2ff10663 1870 || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
82641697 1871 || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
9b0e3eba
AA
1872 || STRINGP (attrs[LFACE_UNDERLINE_INDEX])
1873 || CONSP (attrs[LFACE_UNDERLINE_INDEX]));
a54e2c05 1874 eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
2ff10663 1875 || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
82641697
GM
1876 || SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
1877 || STRINGP (attrs[LFACE_OVERLINE_INDEX]));
a54e2c05 1878 eassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
2ff10663 1879 || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
82641697
GM
1880 || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX])
1881 || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX]));
a54e2c05 1882 eassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
2ff10663 1883 || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX])
82641697
GM
1884 || SYMBOLP (attrs[LFACE_BOX_INDEX])
1885 || STRINGP (attrs[LFACE_BOX_INDEX])
1886 || INTEGERP (attrs[LFACE_BOX_INDEX])
1887 || CONSP (attrs[LFACE_BOX_INDEX]));
a54e2c05 1888 eassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
2ff10663 1889 || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX])
82641697 1890 || SYMBOLP (attrs[LFACE_INVERSE_INDEX]));
a54e2c05 1891 eassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
2ff10663 1892 || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX])
82641697 1893 || STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
a54e2c05 1894 eassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
2ff10663 1895 || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX])
82641697 1896 || STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
a54e2c05 1897 eassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
2ff10663 1898 || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX])
2c20458f
MB
1899 || NILP (attrs[LFACE_INHERIT_INDEX])
1900 || SYMBOLP (attrs[LFACE_INHERIT_INDEX])
1901 || CONSP (attrs[LFACE_INHERIT_INDEX]));
82641697 1902#ifdef HAVE_WINDOW_SYSTEM
a54e2c05 1903 eassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
2ff10663 1904 || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX])
82641697 1905 || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
fef04523 1906 || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
a54e2c05 1907 eassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
2ff10663 1908 || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
2dee4c0b 1909 || FONTP (attrs[LFACE_FONT_INDEX]));
a54e2c05 1910 eassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
f25e39b4
EZ
1911 || STRINGP (attrs[LFACE_FONTSET_INDEX])
1912 || NILP (attrs[LFACE_FONTSET_INDEX]));
82641697
GM
1913#endif
1914}
1915
1916
1917/* Check consistency of attributes of Lisp face LFACE (a Lisp vector). */
1918
1919static void
7d7d0045 1920check_lface (Lisp_Object lface)
82641697
GM
1921{
1922 if (!NILP (lface))
1923 {
a54e2c05 1924 eassert (LFACEP (lface));
82641697
GM
1925 check_lface_attrs (XVECTOR (lface)->contents);
1926 }
1927}
1928
e509cfa6 1929#else /* not GLYPH_DEBUG */
82641697
GM
1930
1931#define check_lface_attrs(attrs) (void) 0
1932#define check_lface(lface) (void) 0
1933
e509cfa6 1934#endif /* GLYPH_DEBUG */
82641697
GM
1935
1936
a0a23346
MB
1937\f
1938/* Face-merge cycle checking. */
1939
f2cec7a9
MB
1940enum named_merge_point_kind
1941{
1942 NAMED_MERGE_POINT_NORMAL,
1943 NAMED_MERGE_POINT_REMAP
1944};
1945
a0a23346
MB
1946/* A `named merge point' is simply a point during face-merging where we
1947 look up a face by name. We keep a stack of which named lookups we're
1948 currently processing so that we can easily detect cycles, using a
1949 linked- list of struct named_merge_point structures, typically
1950 allocated on the stack frame of the named lookup functions which are
1951 active (so no consing is required). */
1952struct named_merge_point
1953{
1954 Lisp_Object face_name;
f2cec7a9 1955 enum named_merge_point_kind named_merge_point_kind;
a0a23346
MB
1956 struct named_merge_point *prev;
1957};
1958
1959
1960/* If a face merging cycle is detected for FACE_NAME, return 0,
1961 otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
f2cec7a9
MB
1962 FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
1963 pointed to by NAMED_MERGE_POINTS, and return 1. */
a0a23346 1964
55d4c1b2 1965static inline int
a0a23346
MB
1966push_named_merge_point (struct named_merge_point *new_named_merge_point,
1967 Lisp_Object face_name,
f2cec7a9 1968 enum named_merge_point_kind named_merge_point_kind,
a0a23346
MB
1969 struct named_merge_point **named_merge_points)
1970{
1971 struct named_merge_point *prev;
1972
1973 for (prev = *named_merge_points; prev; prev = prev->prev)
1974 if (EQ (face_name, prev->face_name))
f2cec7a9
MB
1975 {
1976 if (prev->named_merge_point_kind == named_merge_point_kind)
1977 /* A cycle, so fail. */
1978 return 0;
1979 else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
1980 /* A remap `hides ' any previous normal merge points
1981 (because the remap means that it's actually different face),
1982 so as we know the current merge point must be normal, we
1983 can just assume it's OK. */
1984 break;
1985 }
a0a23346
MB
1986
1987 new_named_merge_point->face_name = face_name;
f2cec7a9 1988 new_named_merge_point->named_merge_point_kind = named_merge_point_kind;
a0a23346
MB
1989 new_named_merge_point->prev = *named_merge_points;
1990
1991 *named_merge_points = new_named_merge_point;
1992
1993 return 1;
1994}
1995
1996\f
39506348 1997/* Resolve face name FACE_NAME. If FACE_NAME is a string, intern it
d1bf13b3
KS
1998 to make it a symbol. If FACE_NAME is an alias for another face,
1999 return that face's name.
2000
2001 Return default face in case of errors. */
c7ae3284
GM
2002
2003static Lisp_Object
971de7fb 2004resolve_face_name (Lisp_Object face_name, int signal_p)
c7ae3284 2005{
d1bf13b3
KS
2006 Lisp_Object orig_face;
2007 Lisp_Object tortoise, hare;
178c5d9c 2008
c7ae3284 2009 if (STRINGP (face_name))
42a5b22f 2010 face_name = intern (SSDATA (face_name));
c7ae3284 2011
d1bf13b3
KS
2012 if (NILP (face_name) || !SYMBOLP (face_name))
2013 return face_name;
2014
2015 orig_face = face_name;
2016 tortoise = hare = face_name;
2017
2018 while (1)
c7ae3284 2019 {
d1bf13b3
KS
2020 face_name = hare;
2021 hare = Fget (hare, Qface_alias);
2022 if (NILP (hare) || !SYMBOLP (hare))
c7ae3284 2023 break;
d1bf13b3
KS
2024
2025 face_name = hare;
2026 hare = Fget (hare, Qface_alias);
2027 if (NILP (hare) || !SYMBOLP (hare))
f3745204 2028 break;
d1bf13b3
KS
2029
2030 tortoise = Fget (tortoise, Qface_alias);
2031 if (EQ (hare, tortoise))
2032 {
2033 if (signal_p)
8009eb44 2034 xsignal1 (Qcircular_list, orig_face);
d1bf13b3
KS
2035 return Qdefault;
2036 }
c7ae3284
GM
2037 }
2038
2039 return face_name;
2040}
2041
2042
82641697 2043/* Return the face definition of FACE_NAME on frame F. F null means
45d9f1ef
GM
2044 return the definition for new frames. FACE_NAME may be a string or
2045 a symbol (apparently Emacs 20.2 allowed strings as face names in
f2cec7a9
MB
2046 face text properties; Ediff uses that). If SIGNAL_P is non-zero,
2047 signal an error if FACE_NAME is not a valid face name. If SIGNAL_P
2048 is zero, value is nil if FACE_NAME is not a valid face name. */
55d4c1b2 2049static inline Lisp_Object
b5f03016
AS
2050lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
2051 int signal_p)
82641697 2052{
c7ae3284 2053 Lisp_Object lface;
82641697
GM
2054
2055 if (f)
2056 lface = assq_no_quit (face_name, f->face_alist);
2057 else
2058 lface = assq_no_quit (face_name, Vface_new_frame_defaults);
2059
2060 if (CONSP (lface))
2061 lface = XCDR (lface);
2062 else if (signal_p)
2063 signal_error ("Invalid face", face_name);
2064
2065 check_lface (lface);
f2cec7a9 2066
82641697
GM
2067 return lface;
2068}
2069
f2cec7a9
MB
2070/* Return the face definition of FACE_NAME on frame F. F null means
2071 return the definition for new frames. FACE_NAME may be a string or
2072 a symbol (apparently Emacs 20.2 allowed strings as face names in
2073 face text properties; Ediff uses that). If FACE_NAME is an alias
2074 for another face, return that face's definition. If SIGNAL_P is
2075 non-zero, signal an error if FACE_NAME is not a valid face name.
2076 If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
2077 name. */
55d4c1b2 2078static inline Lisp_Object
971de7fb 2079lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
f2cec7a9
MB
2080{
2081 face_name = resolve_face_name (face_name, signal_p);
2082 return lface_from_face_name_no_resolve (f, face_name, signal_p);
2083}
2084
82641697 2085
e7d7fd8c
MB
2086/* Get face attributes of face FACE_NAME from frame-local faces on
2087 frame F. Store the resulting attributes in ATTRS which must point
2088 to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If SIGNAL_P
2089 is non-zero, signal an error if FACE_NAME does not name a face.
2090 Otherwise, value is zero if FACE_NAME is not a face. */
2091
55d4c1b2 2092static inline int
b5f03016
AS
2093get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
2094 Lisp_Object *attrs, int signal_p)
e7d7fd8c
MB
2095{
2096 Lisp_Object lface;
e7d7fd8c 2097
f2cec7a9
MB
2098 lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
2099
2100 if (! NILP (lface))
72af86bd
AS
2101 memcpy (attrs, XVECTOR (lface)->contents,
2102 LFACE_VECTOR_SIZE * sizeof *attrs);
f2cec7a9
MB
2103
2104 return !NILP (lface);
2105}
2106
2107/* Get face attributes of face FACE_NAME from frame-local faces on frame
2108 F. Store the resulting attributes in ATTRS which must point to a
2109 vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an
2110 alias for another face, use that face's definition. If SIGNAL_P is
2111 non-zero, signal an error if FACE_NAME does not name a face.
2112 Otherwise, value is zero if FACE_NAME is not a face. */
2113
55d4c1b2 2114static inline int
b5f03016
AS
2115get_lface_attributes (struct frame *f, Lisp_Object face_name,
2116 Lisp_Object *attrs, int signal_p,
2117 struct named_merge_point *named_merge_points)
f2cec7a9
MB
2118{
2119 Lisp_Object face_remapping;
2120
2121 face_name = resolve_face_name (face_name, signal_p);
2122
2123 /* See if SYMBOL has been remapped to some other face (usually this
2124 is done buffer-locally). */
2125 face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
2126 if (CONSP (face_remapping))
e7d7fd8c 2127 {
f2cec7a9
MB
2128 struct named_merge_point named_merge_point;
2129
2130 if (push_named_merge_point (&named_merge_point,
2131 face_name, NAMED_MERGE_POINT_REMAP,
2132 &named_merge_points))
2133 {
2134 int i;
2135
2136 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2137 attrs[i] = Qunspecified;
2138
2139 return merge_face_ref (f, XCDR (face_remapping), attrs,
2140 signal_p, named_merge_points);
2141 }
e7d7fd8c 2142 }
e7d7fd8c 2143
f2cec7a9
MB
2144 /* Default case, no remapping. */
2145 return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
e7d7fd8c
MB
2146}
2147
2148
82641697
GM
2149/* Non-zero if all attributes in face attribute vector ATTRS are
2150 specified, i.e. are non-nil. */
2151
2152static int
971de7fb 2153lface_fully_specified_p (Lisp_Object *attrs)
82641697
GM
2154{
2155 int i;
2156
2157 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2dee4c0b 2158 if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX)
9e2a2647 2159 if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i])))
b5f03016 2160 break;
82641697
GM
2161
2162 return i == LFACE_VECTOR_SIZE;
2163}
2164
c3cee013 2165#ifdef HAVE_WINDOW_SYSTEM
82641697 2166
2dee4c0b
KH
2167/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT.
2168 If FORCE_P is zero, set only unspecified attributes of LFACE. The
2169 exception is `font' attribute. It is set to FONT_OBJECT regardless
2170 of FORCE_P. */
178c5d9c 2171
82641697 2172static int
b5f03016
AS
2173set_lface_from_font (struct frame *f, Lisp_Object lface,
2174 Lisp_Object font_object, int force_p)
f4d3bea3 2175{
f4d3bea3 2176 Lisp_Object val;
2dee4c0b 2177 struct font *font = XFONT_OBJECT (font_object);
f4d3bea3
KH
2178
2179 /* Set attributes only if unspecified, otherwise face defaults for
2180 new frames would never take effect. If the font doesn't have a
2181 specific property, set a normal value for that. */
2182
2183 if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
2184 {
2dee4c0b 2185 Lisp_Object family = AREF (font_object, FONT_FAMILY_INDEX);
f4d3bea3 2186
53aaf1e2
KH
2187 LFACE_FAMILY (lface) = SYMBOL_NAME (family);
2188 }
2189
2190 if (force_p || UNSPECIFIEDP (LFACE_FOUNDRY (lface)))
2191 {
2192 Lisp_Object foundry = AREF (font_object, FONT_FOUNDRY_INDEX);
2193
2194 LFACE_FOUNDRY (lface) = SYMBOL_NAME (foundry);
f4d3bea3
KH
2195 }
2196
2197 if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
2198 {
2dee4c0b 2199 int pt = PIXEL_TO_POINT (font->pixel_size * 10, f->resy);
f4d3bea3 2200
a54e2c05 2201 eassert (pt > 0);
f4d3bea3
KH
2202 LFACE_HEIGHT (lface) = make_number (pt);
2203 }
2204
f4d3bea3
KH
2205 if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
2206 {
2dee4c0b
KH
2207 val = FONT_WEIGHT_FOR_FACE (font_object);
2208 LFACE_WEIGHT (lface) = ! NILP (val) ? val :Qnormal;
f4d3bea3
KH
2209 }
2210 if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
2211 {
2dee4c0b
KH
2212 val = FONT_SLANT_FOR_FACE (font_object);
2213 LFACE_SLANT (lface) = ! NILP (val) ? val : Qnormal;
f4d3bea3
KH
2214 }
2215 if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
2216 {
2dee4c0b
KH
2217 val = FONT_WIDTH_FOR_FACE (font_object);
2218 LFACE_SWIDTH (lface) = ! NILP (val) ? val : Qnormal;
f4d3bea3
KH
2219 }
2220
2dee4c0b
KH
2221 LFACE_FONT (lface) = font_object;
2222 return 1;
f4d3bea3 2223}
f4d3bea3 2224
c3cee013 2225#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
2226
2227
2c20458f
MB
2228/* Merges the face height FROM with the face height TO, and returns the
2229 merged height. If FROM is an invalid height, then INVALID is
cdfaafa9
MB
2230 returned instead. FROM and TO may be either absolute face heights or
2231 `relative' heights; the returned value is always an absolute height
fe69cf00 2232 unless both FROM and TO are relative. */
2c20458f 2233
6b463e58 2234static Lisp_Object
971de7fb 2235merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2c20458f 2236{
cdfaafa9 2237 Lisp_Object result = invalid;
2c20458f
MB
2238
2239 if (INTEGERP (from))
cdfaafa9
MB
2240 /* FROM is absolute, just use it as is. */
2241 result = from;
2242 else if (FLOATP (from))
2243 /* FROM is a scale, use it to adjust TO. */
2244 {
2245 if (INTEGERP (to))
2246 /* relative X absolute => absolute */
d311d28c 2247 result = make_number (XFLOAT_DATA (from) * XINT (to));
cdfaafa9
MB
2248 else if (FLOATP (to))
2249 /* relative X relative => relative */
2250 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
a0a23346
MB
2251 else if (UNSPECIFIEDP (to))
2252 result = from;
2c20458f 2253 }
2c20458f 2254 else if (FUNCTIONP (from))
cdfaafa9 2255 /* FROM is a function, which use to adjust TO. */
2c20458f
MB
2256 {
2257 /* Call function with current height as argument.
2258 From is the new height. */
cdfaafa9 2259 Lisp_Object args[2];
2c20458f
MB
2260
2261 args[0] = from;
2262 args[1] = to;
cdfaafa9 2263 result = safe_call (2, args);
2c20458f 2264
cdfaafa9
MB
2265 /* Ensure that if TO was absolute, so is the result. */
2266 if (INTEGERP (to) && !INTEGERP (result))
2267 result = invalid;
2c20458f
MB
2268 }
2269
cdfaafa9 2270 return result;
2c20458f
MB
2271}
2272
2273
2274/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
613fa7f2 2275 store the resulting attributes in TO, which must be already be
e7d7fd8c
MB
2276 completely specified and contain only absolute attributes. Every
2277 specified attribute of FROM overrides the corresponding attribute of
2278 TO; relative attributes in FROM are merged with the absolute value in
2279 TO and replace it. NAMED_MERGE_POINTS is used internally to detect
f2cec7a9
MB
2280 loops in face inheritance/remapping; it should be 0 when called from
2281 other places. */
82641697 2282
55d4c1b2 2283static inline void
b5f03016
AS
2284merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2285 struct named_merge_point *named_merge_points)
82641697
GM
2286{
2287 int i;
2c20458f
MB
2288
2289 /* If FROM inherits from some other faces, merge their attributes into
2290 TO before merging FROM's direct attributes. Note that an :inherit
2291 attribute of `unspecified' is the same as one of nil; we never
2292 merge :inherit attributes, so nil is more correct, but lots of
2293 other code uses `unspecified' as a generic value for face attributes. */
2294 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2295 && !NILP (from[LFACE_INHERIT_INDEX]))
a0a23346 2296 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
2c20458f 2297
2dee4c0b
KH
2298 i = LFACE_FONT_INDEX;
2299 if (!UNSPECIFIEDP (from[i]))
2300 {
2301 if (!UNSPECIFIEDP (to[i]))
92470028 2302 to[i] = merge_font_spec (from[i], to[i]);
2dee4c0b 2303 else
92470028 2304 to[i] = copy_font_spec (from[i]);
89dc9a8e
KH
2305 if (! NILP (AREF (to[i], FONT_FOUNDRY_INDEX)))
2306 to[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FOUNDRY_INDEX));
2307 if (! NILP (AREF (to[i], FONT_FAMILY_INDEX)))
2308 to[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FAMILY_INDEX));
2309 if (! NILP (AREF (to[i], FONT_WEIGHT_INDEX)))
2310 to[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (to[i]);
2311 if (! NILP (AREF (to[i], FONT_SLANT_INDEX)))
2312 to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (to[i]);
2313 if (! NILP (AREF (to[i], FONT_WIDTH_INDEX)))
2314 to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (to[i]);
2dee4c0b
KH
2315 ASET (to[i], FONT_SIZE_INDEX, Qnil);
2316 }
87188200 2317
82641697
GM
2318 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2319 if (!UNSPECIFIEDP (from[i]))
ab8469eb
PJ
2320 {
2321 if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
2dee4c0b
KH
2322 {
2323 to[i] = merge_face_heights (from[i], to[i], to[i]);
2324 font_clear_prop (to, FONT_SIZE_INDEX);
2325 }
89dc9a8e
KH
2326 else if (i != LFACE_FONT_INDEX
2327 && ! EQ (to[i], from[i]))
2dee4c0b
KH
2328 {
2329 to[i] = from[i];
2330 if (i >= LFACE_FAMILY_INDEX && i <=LFACE_SLANT_INDEX)
2331 font_clear_prop (to,
2332 (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX
53aaf1e2 2333 : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX
2dee4c0b
KH
2334 : i == LFACE_SWIDTH_INDEX ? FONT_WIDTH_INDEX
2335 : i == LFACE_HEIGHT_INDEX ? FONT_SIZE_INDEX
2336 : i == LFACE_WEIGHT_INDEX ? FONT_WEIGHT_INDEX
2337 : FONT_SLANT_INDEX));
2338 }
ab8469eb 2339 }
2c20458f
MB
2340
2341 /* TO is always an absolute face, which should inherit from nothing.
2342 We blindly copy the :inherit attribute above and fix it up here. */
2343 to[LFACE_INHERIT_INDEX] = Qnil;
2344}
2345
a0a23346
MB
2346/* Merge the named face FACE_NAME on frame F, into the vector of face
2347 attributes TO. NAMED_MERGE_POINTS is used to detect loops in face
2348 inheritance. Returns true if FACE_NAME is a valid face name and
2349 merging succeeded. */
6288c62f 2350
a0a23346 2351static int
b5f03016
AS
2352merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2353 struct named_merge_point *named_merge_points)
2c20458f 2354{
a0a23346 2355 struct named_merge_point named_merge_point;
2c20458f 2356
a0a23346 2357 if (push_named_merge_point (&named_merge_point,
f2cec7a9
MB
2358 face_name, NAMED_MERGE_POINT_NORMAL,
2359 &named_merge_points))
2c20458f 2360 {
e1e419ec 2361 struct gcpro gcpro1;
e7d7fd8c 2362 Lisp_Object from[LFACE_VECTOR_SIZE];
f2cec7a9 2363 int ok = get_lface_attributes (f, face_name, from, 0, named_merge_points);
2c20458f 2364
e7d7fd8c
MB
2365 if (ok)
2366 {
2367 GCPRO1 (named_merge_point.face_name);
2368 merge_face_vectors (f, from, to, named_merge_points);
2369 UNGCPRO;
2370 }
2371
2372 return ok;
2c20458f 2373 }
a0a23346
MB
2374 else
2375 return 0;
82641697
GM
2376}
2377
2378
a0a23346
MB
2379/* Merge face attributes from the lisp `face reference' FACE_REF on
2380 frame F into the face attribute vector TO. If ERR_MSGS is non-zero,
2381 problems with FACE_REF cause an error message to be shown. Return
2382 non-zero if no errors occurred (regardless of the value of ERR_MSGS).
2383 NAMED_MERGE_POINTS is used to detect loops in face inheritance or
2384 list structure; it may be 0 for most callers.
2385
2386 FACE_REF may be a single face specification or a list of such
2387 specifications. Each face specification can be:
82641697
GM
2388
2389 1. A symbol or string naming a Lisp face.
2390
2391 2. A property list of the form (KEYWORD VALUE ...) where each
2392 KEYWORD is a face attribute name, and value is an appropriate value
2393 for that attribute.
2394
2395 3. Conses or the form (FOREGROUND-COLOR . COLOR) or
2396 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is
2397 for compatibility with 20.2.
2398
2399 Face specifications earlier in lists take precedence over later
2400 specifications. */
178c5d9c 2401
a0a23346 2402static int
b5f03016
AS
2403merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2404 int err_msgs, struct named_merge_point *named_merge_points)
82641697 2405{
a0a23346
MB
2406 int ok = 1; /* Succeed without an error? */
2407
2408 if (CONSP (face_ref))
82641697 2409 {
a0a23346 2410 Lisp_Object first = XCAR (face_ref);
178c5d9c 2411
82641697
GM
2412 if (EQ (first, Qforeground_color)
2413 || EQ (first, Qbackground_color))
2414 {
2415 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
2416 . COLOR). COLOR must be a string. */
a0a23346 2417 Lisp_Object color_name = XCDR (face_ref);
82641697
GM
2418 Lisp_Object color = first;
2419
2420 if (STRINGP (color_name))
2421 {
2422 if (EQ (color, Qforeground_color))
2423 to[LFACE_FOREGROUND_INDEX] = color_name;
2424 else
2425 to[LFACE_BACKGROUND_INDEX] = color_name;
2426 }
2427 else
a0a23346
MB
2428 {
2429 if (err_msgs)
2430 add_to_log ("Invalid face color", color_name, Qnil);
2431 ok = 0;
2432 }
82641697
GM
2433 }
2434 else if (SYMBOLP (first)
d5db4077 2435 && *SDATA (SYMBOL_NAME (first)) == ':')
82641697
GM
2436 {
2437 /* Assume this is the property list form. */
a0a23346 2438 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
82641697 2439 {
a0a23346
MB
2440 Lisp_Object keyword = XCAR (face_ref);
2441 Lisp_Object value = XCAR (XCDR (face_ref));
2442 int err = 0;
82641697 2443
d9639b25
RS
2444 /* Specifying `unspecified' is a no-op. */
2445 if (EQ (value, Qunspecified))
2446 ;
2447 else if (EQ (keyword, QCfamily))
82641697
GM
2448 {
2449 if (STRINGP (value))
2dee4c0b
KH
2450 {
2451 to[LFACE_FAMILY_INDEX] = value;
2452 font_clear_prop (to, FONT_FAMILY_INDEX);
2453 }
82641697 2454 else
a0a23346 2455 err = 1;
82641697 2456 }
53aaf1e2
KH
2457 else if (EQ (keyword, QCfoundry))
2458 {
2459 if (STRINGP (value))
2460 {
2461 to[LFACE_FOUNDRY_INDEX] = value;
2462 font_clear_prop (to, FONT_FOUNDRY_INDEX);
2463 }
2464 else
2465 err = 1;
2466 }
82641697
GM
2467 else if (EQ (keyword, QCheight))
2468 {
2c20458f 2469 Lisp_Object new_height =
e1e419ec 2470 merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil);
2c20458f 2471
a0a23346 2472 if (! NILP (new_height))
2dee4c0b
KH
2473 {
2474 to[LFACE_HEIGHT_INDEX] = new_height;
2475 font_clear_prop (to, FONT_SIZE_INDEX);
2476 }
a0a23346
MB
2477 else
2478 err = 1;
82641697
GM
2479 }
2480 else if (EQ (keyword, QCweight))
2481 {
2dee4c0b
KH
2482 if (SYMBOLP (value) && FONT_WEIGHT_NAME_NUMERIC (value) >= 0)
2483 {
2484 to[LFACE_WEIGHT_INDEX] = value;
2485 font_clear_prop (to, FONT_WEIGHT_INDEX);
2486 }
82641697 2487 else
a0a23346 2488 err = 1;
82641697
GM
2489 }
2490 else if (EQ (keyword, QCslant))
2491 {
2dee4c0b
KH
2492 if (SYMBOLP (value) && FONT_SLANT_NAME_NUMERIC (value) >= 0)
2493 {
2494 to[LFACE_SLANT_INDEX] = value;
2495 font_clear_prop (to, FONT_SLANT_INDEX);
2496 }
82641697 2497 else
a0a23346 2498 err = 1;
82641697
GM
2499 }
2500 else if (EQ (keyword, QCunderline))
2501 {
2502 if (EQ (value, Qt)
2503 || NILP (value)
9b0e3eba
AA
2504 || STRINGP (value)
2505 || CONSP (value))
82641697
GM
2506 to[LFACE_UNDERLINE_INDEX] = value;
2507 else
a0a23346 2508 err = 1;
82641697
GM
2509 }
2510 else if (EQ (keyword, QCoverline))
2511 {
2512 if (EQ (value, Qt)
2513 || NILP (value)
2514 || STRINGP (value))
2515 to[LFACE_OVERLINE_INDEX] = value;
2516 else
a0a23346 2517 err = 1;
82641697
GM
2518 }
2519 else if (EQ (keyword, QCstrike_through))
2520 {
2521 if (EQ (value, Qt)
2522 || NILP (value)
2523 || STRINGP (value))
2524 to[LFACE_STRIKE_THROUGH_INDEX] = value;
2525 else
a0a23346 2526 err = 1;
82641697
GM
2527 }
2528 else if (EQ (keyword, QCbox))
2529 {
2530 if (EQ (value, Qt))
2531 value = make_number (1);
2532 if (INTEGERP (value)
2533 || STRINGP (value)
2534 || CONSP (value)
2535 || NILP (value))
2536 to[LFACE_BOX_INDEX] = value;
2537 else
a0a23346 2538 err = 1;
82641697
GM
2539 }
2540 else if (EQ (keyword, QCinverse_video)
2541 || EQ (keyword, QCreverse_video))
2542 {
2543 if (EQ (value, Qt) || NILP (value))
2544 to[LFACE_INVERSE_INDEX] = value;
2545 else
a0a23346 2546 err = 1;
82641697
GM
2547 }
2548 else if (EQ (keyword, QCforeground))
2549 {
2550 if (STRINGP (value))
2551 to[LFACE_FOREGROUND_INDEX] = value;
2552 else
a0a23346 2553 err = 1;
82641697
GM
2554 }
2555 else if (EQ (keyword, QCbackground))
2556 {
2557 if (STRINGP (value))
2558 to[LFACE_BACKGROUND_INDEX] = value;
2559 else
a0a23346 2560 err = 1;
82641697
GM
2561 }
2562 else if (EQ (keyword, QCstipple))
2563 {
5e617bc2 2564#if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
fef04523 2565 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
82641697
GM
2566 if (!NILP (pixmap_p))
2567 to[LFACE_STIPPLE_INDEX] = value;
2568 else
a0a23346 2569 err = 1;
82641697
GM
2570#endif
2571 }
2572 else if (EQ (keyword, QCwidth))
2573 {
2dee4c0b
KH
2574 if (SYMBOLP (value) && FONT_WIDTH_NAME_NUMERIC (value) >= 0)
2575 {
2576 to[LFACE_SWIDTH_INDEX] = value;
2577 font_clear_prop (to, FONT_WIDTH_INDEX);
2578 }
82641697 2579 else
a0a23346 2580 err = 1;
82641697 2581 }
2c20458f
MB
2582 else if (EQ (keyword, QCinherit))
2583 {
a0a23346
MB
2584 /* This is not really very useful; it's just like a
2585 normal face reference. */
2586 if (! merge_face_ref (f, value, to,
2587 err_msgs, named_merge_points))
2588 err = 1;
2c20458f 2589 }
82641697 2590 else
a0a23346 2591 err = 1;
82641697 2592
a0a23346
MB
2593 if (err)
2594 {
2595 add_to_log ("Invalid face attribute %S %S", keyword, value);
2596 ok = 0;
2597 }
82641697 2598
a0a23346 2599 face_ref = XCDR (XCDR (face_ref));
82641697
GM
2600 }
2601 }
2602 else
2603 {
a0a23346
MB
2604 /* This is a list of face refs. Those at the beginning of the
2605 list take precedence over what follows, so we have to merge
2606 from the end backwards. */
2607 Lisp_Object next = XCDR (face_ref);
2608
2609 if (! NILP (next))
2610 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points);
2611
2612 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points))
2613 ok = 0;
82641697
GM
2614 }
2615 }
2616 else
2617 {
a0a23346
MB
2618 /* FACE_REF ought to be a face name. */
2619 ok = merge_named_face (f, face_ref, to, named_merge_points);
2620 if (!ok && err_msgs)
2621 add_to_log ("Invalid face reference: %s", face_ref, Qnil);
82641697 2622 }
a0a23346
MB
2623
2624 return ok;
82641697
GM
2625}
2626
2627
2628DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
2629 Sinternal_make_lisp_face, 1, 2, 0,
7ee72033 2630 doc: /* Make FACE, a symbol, a Lisp face with all attributes nil.
228299fa
GM
2631If FACE was not known as a face before, create a new one.
2632If optional argument FRAME is specified, make a frame-local face
2633for that frame. Otherwise operate on the global face definition.
7ee72033 2634Value is a vector of face attributes. */)
5842a27b 2635 (Lisp_Object face, Lisp_Object frame)
82641697
GM
2636{
2637 Lisp_Object global_lface, lface;
2638 struct frame *f;
2639 int i;
2640
b7826503 2641 CHECK_SYMBOL (face);
82641697 2642 global_lface = lface_from_face_name (NULL, face, 0);
178c5d9c 2643
82641697
GM
2644 if (!NILP (frame))
2645 {
b7826503 2646 CHECK_LIVE_FRAME (frame);
82641697
GM
2647 f = XFRAME (frame);
2648 lface = lface_from_face_name (f, face, 0);
2649 }
2650 else
2651 f = NULL, lface = Qnil;
2652
2653 /* Add a global definition if there is none. */
2654 if (NILP (global_lface))
2655 {
2656 global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
2657 Qunspecified);
dfae5f9a 2658 ASET (global_lface, 0, Qface);
178c5d9c 2659 Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
82641697 2660 Vface_new_frame_defaults);
178c5d9c 2661
82641697
GM
2662 /* Assign the new Lisp face a unique ID. The mapping from Lisp
2663 face id to Lisp face is given by the vector lface_id_to_name.
2664 The mapping from Lisp face to Lisp face id is given by the
2665 property `face' of the Lisp face name. */
2666 if (next_lface_id == lface_id_to_name_size)
0065d054 2667 lface_id_to_name =
d311d28c 2668 xpalloc (lface_id_to_name, &lface_id_to_name_size, 1, MAX_FACE_ID,
0065d054 2669 sizeof *lface_id_to_name);
178c5d9c 2670
82641697
GM
2671 lface_id_to_name[next_lface_id] = face;
2672 Fput (face, Qface, make_number (next_lface_id));
2673 ++next_lface_id;
2674 }
2675 else if (f == NULL)
2676 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
dfae5f9a 2677 ASET (global_lface, i, Qunspecified);
178c5d9c 2678
82641697
GM
2679 /* Add a frame-local definition. */
2680 if (f)
2681 {
2682 if (NILP (lface))
2683 {
2684 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
2685 Qunspecified);
dfae5f9a 2686 ASET (lface, 0, Qface);
82641697
GM
2687 f->face_alist = Fcons (Fcons (face, lface), f->face_alist);
2688 }
2689 else
2690 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
dfae5f9a 2691 ASET (lface, i, Qunspecified);
82641697
GM
2692 }
2693 else
2694 lface = global_lface;
2695
33565969
RS
2696 /* Changing a named face means that all realized faces depending on
2697 that face are invalid. Since we cannot tell which realized faces
2698 depend on the face, make sure they are all removed. This is done
2699 by incrementing face_change_count. The next call to
2700 init_iterator will then free realized faces. */
46b00436
KS
2701 if (NILP (Fget (face, Qface_no_inherit)))
2702 {
2703 ++face_change_count;
2704 ++windows_or_buffers_changed;
2705 }
33565969 2706
a54e2c05 2707 eassert (LFACEP (lface));
82641697
GM
2708 check_lface (lface);
2709 return lface;
2710}
2711
2712
2713DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
2714 Sinternal_lisp_face_p, 1, 2, 0,
7ee72033 2715 doc: /* Return non-nil if FACE names a face.
b84ce3c5 2716FACE should be a symbol or string.
1d256714 2717If optional second argument FRAME is non-nil, check for the
228299fa 2718existence of a frame-local face with name FACE on that frame.
7ee72033 2719Otherwise check for the existence of a global face. */)
5842a27b 2720 (Lisp_Object face, Lisp_Object frame)
82641697
GM
2721{
2722 Lisp_Object lface;
178c5d9c 2723
65fddb74
JB
2724 face = resolve_face_name (face, 1);
2725
82641697
GM
2726 if (!NILP (frame))
2727 {
b7826503 2728 CHECK_LIVE_FRAME (frame);
82641697
GM
2729 lface = lface_from_face_name (XFRAME (frame), face, 0);
2730 }
2731 else
2732 lface = lface_from_face_name (NULL, face, 0);
2733
2734 return lface;
2735}
2736
2737
2738DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
2739 Sinternal_copy_lisp_face, 4, 4, 0,
7ee72033 2740 doc: /* Copy face FROM to TO.
5e9bab6f
RS
2741If FRAME is t, copy the global face definition of FROM.
2742Otherwise, copy the frame-local definition of FROM on FRAME.
2743If NEW-FRAME is a frame, copy that data into the frame-local
d5ab09cd 2744definition of TO on NEW-FRAME. If NEW-FRAME is nil,
5e9bab6f 2745FRAME controls where the data is copied to.
228299fa 2746
5e9bab6f 2747The value is TO. */)
5842a27b 2748 (Lisp_Object from, Lisp_Object to, Lisp_Object frame, Lisp_Object new_frame)
82641697
GM
2749{
2750 Lisp_Object lface, copy;
178c5d9c 2751
b7826503
PJ
2752 CHECK_SYMBOL (from);
2753 CHECK_SYMBOL (to);
82641697
GM
2754
2755 if (EQ (frame, Qt))
2756 {
2757 /* Copy global definition of FROM. We don't make copies of
2758 strings etc. because 20.2 didn't do it either. */
2759 lface = lface_from_face_name (NULL, from, 1);
2760 copy = Finternal_make_lisp_face (to, Qnil);
2761 }
2762 else
2763 {
2764 /* Copy frame-local definition of FROM. */
5e9bab6f
RS
2765 if (NILP (new_frame))
2766 new_frame = frame;
b7826503
PJ
2767 CHECK_LIVE_FRAME (frame);
2768 CHECK_LIVE_FRAME (new_frame);
82641697
GM
2769 lface = lface_from_face_name (XFRAME (frame), from, 1);
2770 copy = Finternal_make_lisp_face (to, new_frame);
2771 }
178c5d9c 2772
72af86bd
AS
2773 memcpy (XVECTOR (copy)->contents, XVECTOR (lface)->contents,
2774 LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
178c5d9c 2775
33565969
RS
2776 /* Changing a named face means that all realized faces depending on
2777 that face are invalid. Since we cannot tell which realized faces
2778 depend on the face, make sure they are all removed. This is done
2779 by incrementing face_change_count. The next call to
2780 init_iterator will then free realized faces. */
46b00436
KS
2781 if (NILP (Fget (to, Qface_no_inherit)))
2782 {
2783 ++face_change_count;
2784 ++windows_or_buffers_changed;
2785 }
33565969 2786
82641697
GM
2787 return to;
2788}
2789
2790
2791DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
2792 Sinternal_set_lisp_face_attribute, 3, 4, 0,
7ee72033 2793 doc: /* Set attribute ATTR of FACE to VALUE.
228299fa
GM
2794FRAME being a frame means change the face on that frame.
2795FRAME nil means change the face of the selected frame.
2796FRAME t means change the default for new frames.
2797FRAME 0 means change the face on all frames, and change the default
7ee72033 2798 for new frames. */)
5842a27b 2799 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
82641697
GM
2800{
2801 Lisp_Object lface;
2802 Lisp_Object old_value = Qnil;
2dee4c0b
KH
2803 /* Set one of enum font_property_index (> 0) if ATTR is one of
2804 font-related attributes other than QCfont and QCfontset. */
2805 enum font_property_index prop_index = 0;
178c5d9c 2806
b7826503
PJ
2807 CHECK_SYMBOL (face);
2808 CHECK_SYMBOL (attr);
82641697 2809
d1bf13b3 2810 face = resolve_face_name (face, 1);
c7ae3284 2811
628436fb
GM
2812 /* If FRAME is 0, change face on all frames, and change the
2813 default for new frames. */
2814 if (INTEGERP (frame) && XINT (frame) == 0)
2815 {
2816 Lisp_Object tail;
d12d0a9b 2817 Finternal_set_lisp_face_attribute (face, attr, value, Qt);
628436fb
GM
2818 FOR_EACH_FRAME (tail, frame)
2819 Finternal_set_lisp_face_attribute (face, attr, value, frame);
d12d0a9b 2820 return face;
628436fb
GM
2821 }
2822
82641697
GM
2823 /* Set lface to the Lisp attribute vector of FACE. */
2824 if (EQ (frame, Qt))
0268cef3
CY
2825 {
2826 lface = lface_from_face_name (NULL, face, 1);
67d23e01
CY
2827
2828 /* When updating face-new-frame-defaults, we put :ignore-defface
2829 where the caller wants `unspecified'. This forces the frame
2830 defaults to ignore the defface value. Otherwise, the defface
2831 will take effect, which is generally not what is intended.
2832 The value of that attribute will be inherited from some other
2833 face during face merging. See internal_merge_in_global_face. */
0268cef3 2834 if (UNSPECIFIEDP (value))
a3720aa2 2835 value = QCignore_defface;
0268cef3 2836 }
82641697
GM
2837 else
2838 {
2839 if (NILP (frame))
c0617987 2840 frame = selected_frame;
178c5d9c 2841
b7826503 2842 CHECK_LIVE_FRAME (frame);
82641697 2843 lface = lface_from_face_name (XFRAME (frame), face, 0);
178c5d9c 2844
82641697
GM
2845 /* If a frame-local face doesn't exist yet, create one. */
2846 if (NILP (lface))
2847 lface = Finternal_make_lisp_face (face, frame);
2848 }
2849
2850 if (EQ (attr, QCfamily))
2851 {
2ff10663 2852 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2853 {
b7826503 2854 CHECK_STRING (value);
d5db4077 2855 if (SCHARS (value) == 0)
82641697
GM
2856 signal_error ("Invalid face family", value);
2857 }
2858 old_value = LFACE_FAMILY (lface);
2859 LFACE_FAMILY (lface) = value;
2dee4c0b 2860 prop_index = FONT_FAMILY_INDEX;
82641697 2861 }
53aaf1e2
KH
2862 else if (EQ (attr, QCfoundry))
2863 {
2864 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2865 {
2866 CHECK_STRING (value);
2867 if (SCHARS (value) == 0)
2868 signal_error ("Invalid face foundry", value);
2869 }
2870 old_value = LFACE_FOUNDRY (lface);
2871 LFACE_FOUNDRY (lface) = value;
2872 prop_index = FONT_FOUNDRY_INDEX;
2873 }
82641697
GM
2874 else if (EQ (attr, QCheight))
2875 {
2ff10663 2876 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2877 {
e66d5363
CY
2878 if (EQ (face, Qdefault))
2879 {
2880 /* The default face must have an absolute size. */
2881 if (!INTEGERP (value) || XINT (value) <= 0)
b5f03016
AS
2882 signal_error ("Default face height not absolute and positive",
2883 value);
e66d5363
CY
2884 }
2885 else
2886 {
2887 /* For non-default faces, do a test merge with a random
2888 height to see if VALUE's ok. */
2889 Lisp_Object test = merge_face_heights (value,
2890 make_number (10),
2891 Qnil);
2892 if (!INTEGERP (test) || XINT (test) <= 0)
b5f03016
AS
2893 signal_error ("Face height does not produce a positive integer",
2894 value);
e66d5363 2895 }
82641697 2896 }
2c20458f 2897
82641697
GM
2898 old_value = LFACE_HEIGHT (lface);
2899 LFACE_HEIGHT (lface) = value;
2dee4c0b 2900 prop_index = FONT_SIZE_INDEX;
82641697
GM
2901 }
2902 else if (EQ (attr, QCweight))
2903 {
2ff10663 2904 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2905 {
b7826503 2906 CHECK_SYMBOL (value);
2dee4c0b 2907 if (FONT_WEIGHT_NAME_NUMERIC (value) < 0)
82641697
GM
2908 signal_error ("Invalid face weight", value);
2909 }
2910 old_value = LFACE_WEIGHT (lface);
2911 LFACE_WEIGHT (lface) = value;
2dee4c0b 2912 prop_index = FONT_WEIGHT_INDEX;
82641697
GM
2913 }
2914 else if (EQ (attr, QCslant))
2915 {
2ff10663 2916 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2917 {
b7826503 2918 CHECK_SYMBOL (value);
2dee4c0b 2919 if (FONT_SLANT_NAME_NUMERIC (value) < 0)
82641697
GM
2920 signal_error ("Invalid face slant", value);
2921 }
2922 old_value = LFACE_SLANT (lface);
2923 LFACE_SLANT (lface) = value;
2dee4c0b 2924 prop_index = FONT_SLANT_INDEX;
82641697
GM
2925 }
2926 else if (EQ (attr, QCunderline))
2927 {
9b0e3eba 2928 int valid_p = 0;
38182d90 2929
9b0e3eba
AA
2930 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
2931 valid_p = 1;
2932 else if (NILP (value) || EQ (value, Qt))
2933 valid_p = 1;
2934 else if (STRINGP (value) && SCHARS (value) > 0)
2935 valid_p = 1;
2936 else if (CONSP (value))
2937 {
2938 Lisp_Object key, val, list;
2939
2940 list = value;
2941 valid_p = 1;
2942
2943 while (!NILP (CAR_SAFE(list)))
2944 {
2945 key = CAR_SAFE (list);
2946 list = CDR_SAFE (list);
2947 val = CAR_SAFE (list);
2948 list = CDR_SAFE (list);
38182d90
PE
2949
2950 if (NILP (key) || NILP (val))
9b0e3eba
AA
2951 {
2952 valid_p = 0;
2953 break;
2954 }
2955
2956 else if (EQ (key, QCcolor)
2957 && !(EQ (val, Qforeground_color)
2958 || (STRINGP (val) && SCHARS (val) > 0)))
2959 {
2960 valid_p = 0;
2961 break;
2962 }
38182d90
PE
2963
2964 else if (EQ (key, QCstyle)
9b0e3eba
AA
2965 && !(EQ (val, Qline) || EQ (val, Qwave)))
2966 {
2967 valid_p = 0;
2968 break;
2969 }
2970 }
2971 }
38182d90 2972
9b0e3eba
AA
2973 if (!valid_p)
2974 signal_error ("Invalid face underline", value);
38182d90 2975
82641697
GM
2976 old_value = LFACE_UNDERLINE (lface);
2977 LFACE_UNDERLINE (lface) = value;
2978 }
2979 else if (EQ (attr, QCoverline))
2980 {
2ff10663 2981 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
2982 if ((SYMBOLP (value)
2983 && !EQ (value, Qt)
2984 && !EQ (value, Qnil))
2985 /* Overline color. */
2986 || (STRINGP (value)
d5db4077 2987 && SCHARS (value) == 0))
82641697 2988 signal_error ("Invalid face overline", value);
178c5d9c 2989
82641697
GM
2990 old_value = LFACE_OVERLINE (lface);
2991 LFACE_OVERLINE (lface) = value;
2992 }
2993 else if (EQ (attr, QCstrike_through))
2994 {
2ff10663 2995 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
2996 if ((SYMBOLP (value)
2997 && !EQ (value, Qt)
2998 && !EQ (value, Qnil))
2999 /* Strike-through color. */
3000 || (STRINGP (value)
d5db4077 3001 && SCHARS (value) == 0))
82641697 3002 signal_error ("Invalid face strike-through", value);
178c5d9c 3003
82641697
GM
3004 old_value = LFACE_STRIKE_THROUGH (lface);
3005 LFACE_STRIKE_THROUGH (lface) = value;
3006 }
3007 else if (EQ (attr, QCbox))
3008 {
3009 int valid_p;
178c5d9c 3010
82641697 3011 /* Allow t meaning a simple box of width 1 in foreground color
b5f03016 3012 of the face. */
82641697
GM
3013 if (EQ (value, Qt))
3014 value = make_number (1);
3015
2ff10663 3016 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
82641697
GM
3017 valid_p = 1;
3018 else if (NILP (value))
3019 valid_p = 1;
3020 else if (INTEGERP (value))
89624b8b 3021 valid_p = XINT (value) != 0;
82641697 3022 else if (STRINGP (value))
d5db4077 3023 valid_p = SCHARS (value) > 0;
82641697
GM
3024 else if (CONSP (value))
3025 {
3026 Lisp_Object tem;
178c5d9c 3027
82641697
GM
3028 tem = value;
3029 while (CONSP (tem))
3030 {
3031 Lisp_Object k, v;
3032
3033 k = XCAR (tem);
3034 tem = XCDR (tem);
3035 if (!CONSP (tem))
3036 break;
3037 v = XCAR (tem);
3038 tem = XCDR (tem);
178c5d9c 3039
82641697
GM
3040 if (EQ (k, QCline_width))
3041 {
89624b8b 3042 if (!INTEGERP (v) || XINT (v) == 0)
82641697
GM
3043 break;
3044 }
3045 else if (EQ (k, QCcolor))
3046 {
91c212f1 3047 if (!NILP (v) && (!STRINGP (v) || SCHARS (v) == 0))
82641697
GM
3048 break;
3049 }
3050 else if (EQ (k, QCstyle))
3051 {
3052 if (!EQ (v, Qpressed_button) && !EQ (v, Qreleased_button))
3053 break;
3054 }
3055 else
3056 break;
3057 }
3058
3059 valid_p = NILP (tem);
3060 }
3061 else
3062 valid_p = 0;
3063
3064 if (!valid_p)
3065 signal_error ("Invalid face box", value);
178c5d9c 3066
82641697
GM
3067 old_value = LFACE_BOX (lface);
3068 LFACE_BOX (lface) = value;
3069 }
3070 else if (EQ (attr, QCinverse_video)
3071 || EQ (attr, QCreverse_video))
3072 {
2ff10663 3073 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 3074 {
b7826503 3075 CHECK_SYMBOL (value);
82641697
GM
3076 if (!EQ (value, Qt) && !NILP (value))
3077 signal_error ("Invalid inverse-video face attribute value", value);
3078 }
3079 old_value = LFACE_INVERSE (lface);
3080 LFACE_INVERSE (lface) = value;
3081 }
3082 else if (EQ (attr, QCforeground))
3083 {
ca6888b6
CY
3084 /* Compatibility with 20.x. */
3085 if (NILP (value))
3086 value = Qunspecified;
2ff10663 3087 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
3088 {
3089 /* Don't check for valid color names here because it depends
3090 on the frame (display) whether the color will be valid
3091 when the face is realized. */
b7826503 3092 CHECK_STRING (value);
d5db4077 3093 if (SCHARS (value) == 0)
82641697
GM
3094 signal_error ("Empty foreground color value", value);
3095 }
3096 old_value = LFACE_FOREGROUND (lface);
3097 LFACE_FOREGROUND (lface) = value;
3098 }
3099 else if (EQ (attr, QCbackground))
3100 {
ca6888b6
CY
3101 /* Compatibility with 20.x. */
3102 if (NILP (value))
3103 value = Qunspecified;
2ff10663 3104 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
3105 {
3106 /* Don't check for valid color names here because it depends
3107 on the frame (display) whether the color will be valid
3108 when the face is realized. */
b7826503 3109 CHECK_STRING (value);
d5db4077 3110 if (SCHARS (value) == 0)
82641697
GM
3111 signal_error ("Empty background color value", value);
3112 }
3113 old_value = LFACE_BACKGROUND (lface);
3114 LFACE_BACKGROUND (lface) = value;
3115 }
3116 else if (EQ (attr, QCstipple))
3117 {
5e617bc2 3118#if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
2ff10663 3119 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
82641697 3120 && !NILP (value)
fef04523 3121 && NILP (Fbitmap_spec_p (value)))
82641697
GM
3122 signal_error ("Invalid stipple attribute", value);
3123 old_value = LFACE_STIPPLE (lface);
3124 LFACE_STIPPLE (lface) = value;
edfda783 3125#endif /* HAVE_X_WINDOWS || HAVE_NS */
82641697
GM
3126 }
3127 else if (EQ (attr, QCwidth))
3128 {
2ff10663 3129 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 3130 {
b7826503 3131 CHECK_SYMBOL (value);
2dee4c0b 3132 if (FONT_WIDTH_NAME_NUMERIC (value) < 0)
82641697
GM
3133 signal_error ("Invalid face width", value);
3134 }
3135 old_value = LFACE_SWIDTH (lface);
3136 LFACE_SWIDTH (lface) = value;
2dee4c0b 3137 prop_index = FONT_WIDTH_INDEX;
82641697 3138 }
2dee4c0b 3139 else if (EQ (attr, QCfont))
82641697 3140 {
c3cee013 3141#ifdef HAVE_WINDOW_SYSTEM
3d90c96c 3142 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
96fbd2c6 3143 {
2dee4c0b 3144 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
f4d3bea3 3145 {
2dee4c0b
KH
3146 FRAME_PTR f;
3147
3148 old_value = LFACE_FONT (lface);
3149 if (! FONTP (value))
f4d3bea3 3150 {
2dee4c0b
KH
3151 if (STRINGP (value))
3152 {
21bdb81a
CY
3153 Lisp_Object name = value;
3154 int fontset = fs_query_fontset (name, 0);
2dee4c0b
KH
3155
3156 if (fontset >= 0)
21bdb81a
CY
3157 name = fontset_ascii (fontset);
3158 value = font_spec_from_name (name);
3159 if (!FONTP (value))
3160 signal_error ("Invalid font name", name);
2dee4c0b
KH
3161 }
3162 else
3163 signal_error ("Invalid font or font-spec", value);
f4d3bea3 3164 }
2dee4c0b
KH
3165 if (EQ (frame, Qt))
3166 f = XFRAME (selected_frame);
f4d3bea3 3167 else
2dee4c0b
KH
3168 f = XFRAME (frame);
3169 if (! FONT_OBJECT_P (value))
f4d3bea3 3170 {
2dee4c0b 3171 Lisp_Object *attrs = XVECTOR (lface)->contents;
f4d3bea3
KH
3172 Lisp_Object font_object;
3173
2dee4c0b 3174 font_object = font_load_for_lface (f, attrs, value);
db1c10a2 3175 if (NILP (font_object))
2dee4c0b
KH
3176 signal_error ("Font not available", value);
3177 value = font_object;
f4d3bea3 3178 }
2dee4c0b 3179 set_lface_from_font (f, lface, value, 1);
f4d3bea3
KH
3180 }
3181 else
2dee4c0b
KH
3182 LFACE_FONT (lface) = value;
3183 }
3184#endif /* HAVE_WINDOW_SYSTEM */
3185 }
3186 else if (EQ (attr, QCfontset))
3187 {
3188#ifdef HAVE_WINDOW_SYSTEM
3189 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
3190 {
3191 Lisp_Object tmp;
39506348 3192
2dee4c0b
KH
3193 old_value = LFACE_FONTSET (lface);
3194 tmp = Fquery_fontset (value, Qnil);
3195 if (NILP (tmp))
3196 signal_error ("Invalid fontset name", value);
3197 LFACE_FONTSET (lface) = value = tmp;
96fbd2c6 3198 }
c3cee013 3199#endif /* HAVE_WINDOW_SYSTEM */
82641697 3200 }
2c20458f
MB
3201 else if (EQ (attr, QCinherit))
3202 {
3203 Lisp_Object tail;
3204 if (SYMBOLP (value))
3205 tail = Qnil;
3206 else
3207 for (tail = value; CONSP (tail); tail = XCDR (tail))
3208 if (!SYMBOLP (XCAR (tail)))
3209 break;
3210 if (NILP (tail))
3211 LFACE_INHERIT (lface) = value;
3212 else
6288c62f 3213 signal_error ("Invalid face inheritance", value);
2c20458f 3214 }
82641697
GM
3215 else if (EQ (attr, QCbold))
3216 {
3217 old_value = LFACE_WEIGHT (lface);
3218 LFACE_WEIGHT (lface) = NILP (value) ? Qnormal : Qbold;
2dee4c0b 3219 prop_index = FONT_WEIGHT_INDEX;
82641697
GM
3220 }
3221 else if (EQ (attr, QCitalic))
3222 {
2dee4c0b 3223 attr = QCslant;
82641697
GM
3224 old_value = LFACE_SLANT (lface);
3225 LFACE_SLANT (lface) = NILP (value) ? Qnormal : Qitalic;
2dee4c0b 3226 prop_index = FONT_SLANT_INDEX;
82641697
GM
3227 }
3228 else
3229 signal_error ("Invalid face attribute name", attr);
3230
2dee4c0b 3231 if (prop_index)
e69a00b7
CY
3232 {
3233 /* If a font-related attribute other than QCfont and QCfontset
3234 is specified, and if the original QCfont attribute has a font
3235 (font-spec or font-object), set the corresponding property in
3236 the font to nil so that the font selector doesn't think that
3237 the attribute is mandatory. Also, clear the average
3238 width. */
3239 font_clear_prop (XVECTOR (lface)->contents, prop_index);
e69a00b7 3240 }
39506348 3241
82641697
GM
3242 /* Changing a named face means that all realized faces depending on
3243 that face are invalid. Since we cannot tell which realized faces
3244 depend on the face, make sure they are all removed. This is done
3245 by incrementing face_change_count. The next call to
3246 init_iterator will then free realized faces. */
3247 if (!EQ (frame, Qt)
46b00436 3248 && NILP (Fget (face, Qface_no_inherit))
2dee4c0b 3249 && NILP (Fequal (old_value, value)))
82641697
GM
3250 {
3251 ++face_change_count;
3252 ++windows_or_buffers_changed;
3253 }
3254
2ff10663 3255 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
82641697 3256 && NILP (Fequal (old_value, value)))
8bd201d6
GM
3257 {
3258 Lisp_Object param;
3259
3260 param = Qnil;
178c5d9c 3261
8bd201d6
GM
3262 if (EQ (face, Qdefault))
3263 {
b9c769f8 3264#ifdef HAVE_WINDOW_SYSTEM
8bd201d6
GM
3265 /* Changed font-related attributes of the `default' face are
3266 reflected in changed `font' frame parameters. */
ceeda019 3267 if (FRAMEP (frame)
2dee4c0b 3268 && (prop_index || EQ (attr, QCfont))
8bd201d6
GM
3269 && lface_fully_specified_p (XVECTOR (lface)->contents))
3270 set_font_frame_param (frame, lface);
b9c769f8
EZ
3271 else
3272#endif /* HAVE_WINDOW_SYSTEM */
3273
3274 if (EQ (attr, QCforeground))
8bd201d6
GM
3275 param = Qforeground_color;
3276 else if (EQ (attr, QCbackground))
3277 param = Qbackground_color;
3278 }
b9c769f8 3279#ifdef HAVE_WINDOW_SYSTEM
c3cee013 3280#ifndef WINDOWSNT
8bd201d6
GM
3281 else if (EQ (face, Qscroll_bar))
3282 {
3283 /* Changing the colors of `scroll-bar' sets frame parameters
3284 `scroll-bar-foreground' and `scroll-bar-background'. */
3285 if (EQ (attr, QCforeground))
3286 param = Qscroll_bar_foreground;
3287 else if (EQ (attr, QCbackground))
3288 param = Qscroll_bar_background;
3289 }
d12d0a9b 3290#endif /* not WINDOWSNT */
8bd201d6
GM
3291 else if (EQ (face, Qborder))
3292 {
3293 /* Changing background color of `border' sets frame parameter
3294 `border-color'. */
3295 if (EQ (attr, QCbackground))
3296 param = Qborder_color;
3297 }
3298 else if (EQ (face, Qcursor))
3299 {
3300 /* Changing background color of `cursor' sets frame parameter
3301 `cursor-color'. */
3302 if (EQ (attr, QCbackground))
3303 param = Qcursor_color;
3304 }
3305 else if (EQ (face, Qmouse))
3306 {
3307 /* Changing background color of `mouse' sets frame parameter
3308 `mouse-color'. */
3309 if (EQ (attr, QCbackground))
3310 param = Qmouse_color;
3311 }
b9c769f8 3312#endif /* HAVE_WINDOW_SYSTEM */
563f68f1 3313 else if (EQ (face, Qmenu))
ceeda019
GM
3314 {
3315 /* Indicate that we have to update the menu bar when
3316 realizing faces on FRAME. FRAME t change the
3317 default for new frames. We do this by setting
3318 setting the flag in new face caches */
3319 if (FRAMEP (frame))
3320 {
3321 struct frame *f = XFRAME (frame);
3322 if (FRAME_FACE_CACHE (f) == NULL)
3323 FRAME_FACE_CACHE (f) = make_face_cache (f);
3324 FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
3325 }
3326 else
3327 menu_face_changed_default = 1;
3328 }
8bd201d6 3329
39506348 3330 if (!NILP (param))
ab8469eb
PJ
3331 {
3332 if (EQ (frame, Qt))
3333 /* Update `default-frame-alist', which is used for new frames. */
3334 {
3335 store_in_alist (&Vdefault_frame_alist, param, value);
3336 }
3337 else
3338 /* Update the current frame's parameters. */
3339 {
3340 Lisp_Object cons;
3341 cons = XCAR (Vparam_value_alist);
3342 XSETCAR (cons, param);
3343 XSETCDR (cons, value);
3344 Fmodify_frame_parameters (frame, Vparam_value_alist);
3345 }
3346 }
8bd201d6 3347 }
82641697 3348
82641697
GM
3349 return face;
3350}
3351
3352
8bd201d6
GM
3353/* Update the corresponding face when frame parameter PARAM on frame F
3354 has been assigned the value NEW_VALUE. */
3355
3356void
b5f03016
AS
3357update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
3358 Lisp_Object new_value)
8bd201d6 3359{
46b00436 3360 Lisp_Object face = Qnil;
8bd201d6
GM
3361 Lisp_Object lface;
3362
3363 /* If there are no faces yet, give up. This is the case when called
3364 from Fx_create_frame, and we do the necessary things later in
92610620 3365 face-set-after-frame-defaults. */
8bd201d6
GM
3366 if (NILP (f->face_alist))
3367 return;
178c5d9c 3368
8bd201d6
GM
3369 if (EQ (param, Qforeground_color))
3370 {
46b00436
KS
3371 face = Qdefault;
3372 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3373 LFACE_FOREGROUND (lface) = (STRINGP (new_value)
3374 ? new_value : Qunspecified);
3375 realize_basic_faces (f);
3376 }
3377 else if (EQ (param, Qbackground_color))
3378 {
92610620
GM
3379 Lisp_Object frame;
3380
3381 /* Changing the background color might change the background
c20577bc 3382 mode, so that we have to load new defface specs.
64677d90 3383 Call frame-set-background-mode to do that. */
92610620 3384 XSETFRAME (frame, f);
c20577bc 3385 call1 (Qframe_set_background_mode, frame);
178c5d9c 3386
46b00436
KS
3387 face = Qdefault;
3388 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3389 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3390 ? new_value : Qunspecified);
3391 realize_basic_faces (f);
3392 }
76ea4cc9 3393#ifdef HAVE_WINDOW_SYSTEM
46b00436 3394 else if (EQ (param, Qborder_color))
8bd201d6 3395 {
46b00436
KS
3396 face = Qborder;
3397 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3398 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3399 ? new_value : Qunspecified);
3400 }
3401 else if (EQ (param, Qcursor_color))
3402 {
46b00436
KS
3403 face = Qcursor;
3404 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3405 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3406 ? new_value : Qunspecified);
3407 }
3408 else if (EQ (param, Qmouse_color))
3409 {
46b00436
KS
3410 face = Qmouse;
3411 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3412 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3413 ? new_value : Qunspecified);
3414 }
76ea4cc9 3415#endif
46b00436
KS
3416
3417 /* Changing a named face means that all realized faces depending on
3418 that face are invalid. Since we cannot tell which realized faces
3419 depend on the face, make sure they are all removed. This is done
3420 by incrementing face_change_count. The next call to
3421 init_iterator will then free realized faces. */
3422 if (!NILP (face)
3423 && NILP (Fget (face, Qface_no_inherit)))
3424 {
3425 ++face_change_count;
3426 ++windows_or_buffers_changed;
3427 }
8bd201d6
GM
3428}
3429
3430
76ea4cc9
EZ
3431#ifdef HAVE_WINDOW_SYSTEM
3432
3433/* Set the `font' frame parameter of FRAME determined from the
3434 font-object set in `default' face attributes LFACE. */
3435
3436static void
971de7fb 3437set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
76ea4cc9
EZ
3438{
3439 struct frame *f = XFRAME (frame);
3440 Lisp_Object font;
3441
3442 if (FRAME_WINDOW_P (f)
3443 /* Don't do anything if the font is `unspecified'. This can
3444 happen during frame creation. */
3445 && (font = LFACE_FONT (lface),
3446 ! UNSPECIFIEDP (font)))
3447 {
3448 if (FONT_SPEC_P (font))
3449 {
3450 font = font_load_for_lface (f, XVECTOR (lface)->contents, font);
3451 if (NILP (font))
3452 return;
3453 LFACE_FONT (lface) = font;
3454 }
3455 f->default_face_done_p = 0;
3456 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font), Qnil));
3457 }
3458}
3459
3460
82641697
GM
3461/* Get the value of X resource RESOURCE, class CLASS for the display
3462 of frame FRAME. This is here because ordinary `x-get-resource'
3463 doesn't take a frame argument. */
3464
3465DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
7ee72033 3466 Sinternal_face_x_get_resource, 3, 3, 0, doc: /* */)
5842a27b 3467 (Lisp_Object resource, Lisp_Object class, Lisp_Object frame)
82641697 3468{
c3cee013 3469 Lisp_Object value = Qnil;
b7826503
PJ
3470 CHECK_STRING (resource);
3471 CHECK_STRING (class);
3472 CHECK_LIVE_FRAME (frame);
82641697
GM
3473 BLOCK_INPUT;
3474 value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
3475 resource, class, Qnil, Qnil);
3476 UNBLOCK_INPUT;
3477 return value;
3478}
3479
3480
3481/* Return resource string VALUE as a boolean value, i.e. nil, or t.
3482 If VALUE is "on" or "true", return t. If VALUE is "off" or
3483 "false", return nil. Otherwise, if SIGNAL_P is non-zero, signal an
3484 error; if SIGNAL_P is zero, return 0. */
178c5d9c 3485
82641697 3486static Lisp_Object
971de7fb 3487face_boolean_x_resource_value (Lisp_Object value, int signal_p)
82641697
GM
3488{
3489 Lisp_Object result = make_number (0);
3490
a54e2c05 3491 eassert (STRINGP (value));
178c5d9c 3492
25a48bd0
PE
3493 if (xstrcasecmp (SSDATA (value), "on") == 0
3494 || xstrcasecmp (SSDATA (value), "true") == 0)
82641697 3495 result = Qt;
25a48bd0
PE
3496 else if (xstrcasecmp (SSDATA (value), "off") == 0
3497 || xstrcasecmp (SSDATA (value), "false") == 0)
82641697 3498 result = Qnil;
25a48bd0 3499 else if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
82641697
GM
3500 result = Qunspecified;
3501 else if (signal_p)
3502 signal_error ("Invalid face attribute value from X resource", value);
3503
3504 return result;
3505}
3506
3507
3508DEFUN ("internal-set-lisp-face-attribute-from-resource",
3509 Finternal_set_lisp_face_attribute_from_resource,
3510 Sinternal_set_lisp_face_attribute_from_resource,
7ee72033 3511 3, 4, 0, doc: /* */)
5842a27b 3512 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
82641697 3513{
b7826503
PJ
3514 CHECK_SYMBOL (face);
3515 CHECK_SYMBOL (attr);
3516 CHECK_STRING (value);
82641697 3517
25a48bd0 3518 if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
82641697
GM
3519 value = Qunspecified;
3520 else if (EQ (attr, QCheight))
3521 {
3522 value = Fstring_to_number (value, make_number (10));
3523 if (XINT (value) <= 0)
3524 signal_error ("Invalid face height from X resource", value);
3525 }
3526 else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
3527 value = face_boolean_x_resource_value (value, 1);
3528 else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
42a5b22f 3529 value = intern (SSDATA (value));
82641697
GM
3530 else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video))
3531 value = face_boolean_x_resource_value (value, 1);
3532 else if (EQ (attr, QCunderline)
3533 || EQ (attr, QCoverline)
27188d11 3534 || EQ (attr, QCstrike_through))
82641697
GM
3535 {
3536 Lisp_Object boolean_value;
3537
3538 /* If the result of face_boolean_x_resource_value is t or nil,
3539 VALUE does NOT specify a color. */
3540 boolean_value = face_boolean_x_resource_value (value, 0);
3541 if (SYMBOLP (boolean_value))
3542 value = boolean_value;
3543 }
0ad040ff 3544 else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
27188d11 3545 value = Fcar (Fread_from_string (value, Qnil, Qnil));
82641697
GM
3546
3547 return Finternal_set_lisp_face_attribute (face, attr, value, frame);
3548}
3549
c3cee013 3550#endif /* HAVE_WINDOW_SYSTEM */
82641697 3551
c7ae3284
GM
3552\f
3553/***********************************************************************
3554 Menu face
3555 ***********************************************************************/
3556
bce72079 3557#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
c7ae3284 3558
bce72079
GM
3559/* Make menus on frame F appear as specified by the `menu' face. */
3560
3561static void
ebd15611 3562x_update_menu_appearance (struct frame *f)
c7ae3284 3563{
a03ad468 3564 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
bce72079 3565 XrmDatabase rdb;
178c5d9c 3566
bce72079
GM
3567 if (dpyinfo
3568 && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
3569 rdb != NULL))
c7ae3284 3570 {
bce72079 3571 char line[512];
670741ab
PE
3572 char *buf = line;
3573 ptrdiff_t bufsize = sizeof line;
bce72079
GM
3574 Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
3575 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
42a5b22f 3576 const char *myname = SSDATA (Vx_resource_name);
bce72079 3577 int changed_p = 0;
8ad582ac
GM
3578#ifdef USE_MOTIF
3579 const char *popup_path = "popup_menu";
3580#else
3581 const char *popup_path = "menu.popup";
3582#endif
177c0ea7 3583
bce72079
GM
3584 if (STRINGP (LFACE_FOREGROUND (lface)))
3585 {
670741ab
PE
3586 exprintf (&buf, &bufsize, line, -1, "%s.%s*foreground: %s",
3587 myname, popup_path,
3588 SDATA (LFACE_FOREGROUND (lface)));
bce72079 3589 XrmPutLineResource (&rdb, line);
670741ab
PE
3590 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s",
3591 myname, SDATA (LFACE_FOREGROUND (lface)));
bce72079
GM
3592 XrmPutLineResource (&rdb, line);
3593 changed_p = 1;
3594 }
178c5d9c 3595
bce72079
GM
3596 if (STRINGP (LFACE_BACKGROUND (lface)))
3597 {
670741ab
PE
3598 exprintf (&buf, &bufsize, line, -1, "%s.%s*background: %s",
3599 myname, popup_path,
3600 SDATA (LFACE_BACKGROUND (lface)));
bce72079 3601 XrmPutLineResource (&rdb, line);
670741ab
PE
3602
3603 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s",
3604 myname, SDATA (LFACE_BACKGROUND (lface)));
bce72079
GM
3605 XrmPutLineResource (&rdb, line);
3606 changed_p = 1;
3607 }
177c0ea7 3608
2dee4c0b 3609 if (face->font
23888717
CY
3610 /* On Solaris 5.8, it's been reported that the `menu' face
3611 can be unspecified here, during startup. Why this
3612 happens remains unknown. -- cyd */
3613 && FONTP (LFACE_FONT (lface))
bce72079 3614 && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
53aaf1e2 3615 || !UNSPECIFIEDP (LFACE_FOUNDRY (lface))
bce72079 3616 || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
bce72079
GM
3617 || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
3618 || !UNSPECIFIEDP (LFACE_SLANT (lface))
3619 || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
3620 {
47ae3723 3621 Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
a03ad468 3622#ifdef USE_MOTIF
bce72079 3623 const char *suffix = "List";
211f2210 3624 Bool motif = True;
a2d7e722
JD
3625#else
3626#if defined HAVE_X_I18N
3627
3628 const char *suffix = "Set";
a03ad468 3629#else
bce72079 3630 const char *suffix = "";
a2d7e722 3631#endif
211f2210 3632 Bool motif = False;
2defe37f 3633#endif
2dee4c0b
KH
3634
3635 if (! NILP (xlfd))
3636 {
211f2210 3637#if defined HAVE_X_I18N
42a5b22f 3638 char *fontsetname = xic_create_fontsetname (SSDATA (xlfd), motif);
2defe37f 3639#else
51b59d79 3640 char *fontsetname = SSDATA (xlfd);
bce72079 3641#endif
670741ab
PE
3642 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*font%s: %s",
3643 myname, suffix, fontsetname);
2dee4c0b 3644 XrmPutLineResource (&rdb, line);
670741ab
PE
3645
3646 exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s",
3647 myname, popup_path, suffix, fontsetname);
2dee4c0b
KH
3648 XrmPutLineResource (&rdb, line);
3649 changed_p = 1;
51b59d79 3650 if (fontsetname != SSDATA (xlfd))
2dee4c0b
KH
3651 xfree (fontsetname);
3652 }
bce72079 3653 }
c7ae3284 3654
bce72079 3655 if (changed_p && f->output_data.x->menubar_widget)
ac17f0bf 3656 free_frame_menubar (f);
670741ab
PE
3657
3658 if (buf != line)
3659 xfree (buf);
c7ae3284
GM
3660 }
3661}
3662
bce72079 3663#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
82641697
GM
3664
3665
177c0ea7 3666DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
cdfaafa9
MB
3667 Sface_attribute_relative_p,
3668 2, 2, 0,
2d6228e7
RS
3669 doc: /* Check whether a face attribute value is relative.
3670Specifically, this function returns t if the attribute ATTRIBUTE
3671with the value VALUE is relative.
3672
3673A relative value is one that doesn't entirely override whatever is
3674inherited from another face. For most possible attributes,
3675the only relative value that users see is `unspecified'.
3676However, for :height, floating point values are also relative. */)
5842a27b 3677 (Lisp_Object attribute, Lisp_Object value)
cdfaafa9 3678{
a3720aa2 3679 if (EQ (value, Qunspecified) || (EQ (value, QCignore_defface)))
cdfaafa9
MB
3680 return Qt;
3681 else if (EQ (attribute, QCheight))
3682 return INTEGERP (value) ? Qnil : Qt;
3683 else
3684 return Qnil;
3685}
3686
3687DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
3688 3, 3, 0,
3689 doc: /* Return face ATTRIBUTE VALUE1 merged with VALUE2.
3690If VALUE1 or VALUE2 are absolute (see `face-attribute-relative-p'), then
3691the result will be absolute, otherwise it will be relative. */)
5842a27b 3692 (Lisp_Object attribute, Lisp_Object value1, Lisp_Object value2)
cdfaafa9 3693{
a3720aa2 3694 if (EQ (value1, Qunspecified) || EQ (value1, QCignore_defface))
cdfaafa9
MB
3695 return value2;
3696 else if (EQ (attribute, QCheight))
e1e419ec 3697 return merge_face_heights (value1, value2, value1);
cdfaafa9
MB
3698 else
3699 return value1;
3700}
3701
82641697
GM
3702
3703DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
3704 Sinternal_get_lisp_face_attribute,
3705 2, 3, 0,
7ee72033 3706 doc: /* Return face attribute KEYWORD of face SYMBOL.
228299fa
GM
3707If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid
3708face attribute name, signal an error.
7fc92635
JB
3709If the optional argument FRAME is given, report on face SYMBOL in that
3710frame. If FRAME is t, report on the defaults for face SYMBOL (for new
7ee72033 3711frames). If FRAME is omitted or nil, use the selected frame. */)
5842a27b 3712 (Lisp_Object symbol, Lisp_Object keyword, Lisp_Object frame)
82641697
GM
3713{
3714 Lisp_Object lface, value = Qnil;
178c5d9c 3715
b7826503
PJ
3716 CHECK_SYMBOL (symbol);
3717 CHECK_SYMBOL (keyword);
82641697
GM
3718
3719 if (EQ (frame, Qt))
3720 lface = lface_from_face_name (NULL, symbol, 1);
3721 else
3722 {
3723 if (NILP (frame))
c0617987 3724 frame = selected_frame;
b7826503 3725 CHECK_LIVE_FRAME (frame);
82641697
GM
3726 lface = lface_from_face_name (XFRAME (frame), symbol, 1);
3727 }
3728
3729 if (EQ (keyword, QCfamily))
3730 value = LFACE_FAMILY (lface);
53aaf1e2
KH
3731 else if (EQ (keyword, QCfoundry))
3732 value = LFACE_FOUNDRY (lface);
82641697
GM
3733 else if (EQ (keyword, QCheight))
3734 value = LFACE_HEIGHT (lface);
3735 else if (EQ (keyword, QCweight))
3736 value = LFACE_WEIGHT (lface);
3737 else if (EQ (keyword, QCslant))
3738 value = LFACE_SLANT (lface);
3739 else if (EQ (keyword, QCunderline))
3740 value = LFACE_UNDERLINE (lface);
3741 else if (EQ (keyword, QCoverline))
3742 value = LFACE_OVERLINE (lface);
3743 else if (EQ (keyword, QCstrike_through))
3744 value = LFACE_STRIKE_THROUGH (lface);
3745 else if (EQ (keyword, QCbox))
3746 value = LFACE_BOX (lface);
3747 else if (EQ (keyword, QCinverse_video)
3748 || EQ (keyword, QCreverse_video))
3749 value = LFACE_INVERSE (lface);
3750 else if (EQ (keyword, QCforeground))
3751 value = LFACE_FOREGROUND (lface);
3752 else if (EQ (keyword, QCbackground))
3753 value = LFACE_BACKGROUND (lface);
3754 else if (EQ (keyword, QCstipple))
3755 value = LFACE_STIPPLE (lface);
3756 else if (EQ (keyword, QCwidth))
3757 value = LFACE_SWIDTH (lface);
2c20458f
MB
3758 else if (EQ (keyword, QCinherit))
3759 value = LFACE_INHERIT (lface);
39506348
KH
3760 else if (EQ (keyword, QCfont))
3761 value = LFACE_FONT (lface);
763bc839
KH
3762 else if (EQ (keyword, QCfontset))
3763 value = LFACE_FONTSET (lface);
82641697
GM
3764 else
3765 signal_error ("Invalid face attribute name", keyword);
3766
0268cef3
CY
3767 if (IGNORE_DEFFACE_P (value))
3768 return Qunspecified;
3769
82641697
GM
3770 return value;
3771}
3772
3773
3774DEFUN ("internal-lisp-face-attribute-values",
3775 Finternal_lisp_face_attribute_values,
3776 Sinternal_lisp_face_attribute_values, 1, 1, 0,
7ee72033
MB
3777 doc: /* Return a list of valid discrete values for face attribute ATTR.
3778Value is nil if ATTR doesn't have a discrete set of valid values. */)
5842a27b 3779 (Lisp_Object attr)
82641697
GM
3780{
3781 Lisp_Object result = Qnil;
178c5d9c 3782
b7826503 3783 CHECK_SYMBOL (attr);
178c5d9c 3784
2dee4c0b 3785 if (EQ (attr, QCunderline))
82641697
GM
3786 result = Fcons (Qt, Fcons (Qnil, Qnil));
3787 else if (EQ (attr, QCoverline))
3788 result = Fcons (Qt, Fcons (Qnil, Qnil));
3789 else if (EQ (attr, QCstrike_through))
3790 result = Fcons (Qt, Fcons (Qnil, Qnil));
3791 else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video))
3792 result = Fcons (Qt, Fcons (Qnil, Qnil));
3793
3794 return result;
3795}
178c5d9c 3796
82641697
GM
3797
3798DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
178c5d9c 3799 Sinternal_merge_in_global_face, 2, 2, 0,
e3cd9e7f 3800 doc: /* Add attributes from frame-default definition of FACE to FACE on FRAME.
7ee72033 3801Default face attributes override any local face attributes. */)
5842a27b 3802 (Lisp_Object face, Lisp_Object frame)
82641697 3803{
aad40737
MB
3804 int i;
3805 Lisp_Object global_lface, local_lface, *gvec, *lvec;
8d3810fd 3806 struct frame *f = XFRAME (frame);
aad40737 3807
b7826503 3808 CHECK_LIVE_FRAME (frame);
82641697 3809 global_lface = lface_from_face_name (NULL, face, 1);
8d3810fd 3810 local_lface = lface_from_face_name (f, face, 0);
82641697
GM
3811 if (NILP (local_lface))
3812 local_lface = Finternal_make_lisp_face (face, frame);
aad40737 3813
cec33c90
SM
3814 /* Make every specified global attribute override the local one.
3815 BEWARE!! This is only used from `face-set-after-frame-default' where
3816 the local frame is defined from default specs in `face-defface-spec'
3817 and those should be overridden by global settings. Hence the strange
3818 "global before local" priority. */
aad40737
MB
3819 lvec = XVECTOR (local_lface)->contents;
3820 gvec = XVECTOR (global_lface)->contents;
3821 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
8d3810fd
CY
3822 if (IGNORE_DEFFACE_P (gvec[i]))
3823 lvec[i] = Qunspecified;
3824 else if (! UNSPECIFIEDP (gvec[i]))
3825 lvec[i] = gvec[i];
3826
fa9fa316 3827 /* If the default face was changed, update the face cache and the
811029d3 3828 `font' frame parameter. */
8d3810fd
CY
3829 if (EQ (face, Qdefault))
3830 {
3831 struct face_cache *c = FRAME_FACE_CACHE (f);
3832 struct face *newface, *oldface = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3833 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3834
0421a7a7
CY
3835 /* This can be NULL (e.g., in batch mode). */
3836 if (oldface)
8d3810fd 3837 {
fa9fa316
CY
3838 /* Ensure that the face vector is fully specified by merging
3839 the previously-cached vector. */
72af86bd 3840 memcpy (attrs, oldface->lface, sizeof attrs);
0421a7a7 3841 merge_face_vectors (f, lvec, attrs, 0);
72af86bd 3842 memcpy (lvec, attrs, sizeof attrs);
fa9fa316 3843 newface = realize_face (c, lvec, DEFAULT_FACE_ID);
0421a7a7
CY
3844
3845 if ((! UNSPECIFIEDP (gvec[LFACE_FAMILY_INDEX])
3846 || ! UNSPECIFIEDP (gvec[LFACE_FOUNDRY_INDEX])
3847 || ! UNSPECIFIEDP (gvec[LFACE_HEIGHT_INDEX])
3848 || ! UNSPECIFIEDP (gvec[LFACE_WEIGHT_INDEX])
3849 || ! UNSPECIFIEDP (gvec[LFACE_SLANT_INDEX])
3850 || ! UNSPECIFIEDP (gvec[LFACE_SWIDTH_INDEX])
3851 || ! UNSPECIFIEDP (gvec[LFACE_FONT_INDEX]))
3852 && newface->font)
3853 {
3854 Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
3855 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, name),
3856 Qnil));
3857 }
1485f4c0
CY
3858
3859 if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
3860 Fmodify_frame_parameters (frame,
3861 Fcons (Fcons (Qforeground_color,
3862 gvec[LFACE_FOREGROUND_INDEX]),
3863 Qnil));
3864
3865 if (STRINGP (gvec[LFACE_BACKGROUND_INDEX]))
3866 Fmodify_frame_parameters (frame,
3867 Fcons (Fcons (Qbackground_color,
3868 gvec[LFACE_BACKGROUND_INDEX]),
3869 Qnil));
8d3810fd
CY
3870 }
3871 }
334a2e2a
GM
3872
3873 return Qnil;
82641697
GM
3874}
3875
3876
3877/* The following function is implemented for compatibility with 20.2.
3878 The function is used in x-resolve-fonts when it is asked to
3879 return fonts with the same size as the font of a face. This is
3880 done in fontset.el. */
3881
2db4bfe5 3882DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
e3cd9e7f 3883 doc: /* Return the font name of face FACE, or nil if it is unspecified.
2db4bfe5 3884The font name is, by default, for ASCII characters.
228299fa
GM
3885If the optional argument FRAME is given, report on face FACE in that frame.
3886If FRAME is t, report on the defaults for face FACE (for new frames).
3887 The font default for a face is either nil, or a list
3888 of the form (bold), (italic) or (bold italic).
2db4bfe5
KH
3889If FRAME is omitted or nil, use the selected frame. And, in this case,
3890if the optional third argument CHARACTER is given,
3891return the font name used for CHARACTER. */)
5842a27b 3892 (Lisp_Object face, Lisp_Object frame, Lisp_Object character)
82641697
GM
3893{
3894 if (EQ (frame, Qt))
3895 {
3896 Lisp_Object result = Qnil;
3897 Lisp_Object lface = lface_from_face_name (NULL, face, 1);
3898
3899 if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
3900 && !EQ (LFACE_WEIGHT (lface), Qnormal))
3901 result = Fcons (Qbold, result);
178c5d9c 3902
0f2c6573 3903 if (!UNSPECIFIEDP (LFACE_SLANT (lface))
82641697
GM
3904 && !EQ (LFACE_SLANT (lface), Qnormal))
3905 result = Fcons (Qitalic, result);
178c5d9c 3906
82641697
GM
3907 return result;
3908 }
3909 else
3910 {
3911 struct frame *f = frame_or_selected_frame (frame, 1);
000fc2b1 3912 int face_id = lookup_named_face (f, face, 1);
071048a3 3913 struct face *fface = FACE_FROM_ID (f, face_id);
2db4bfe5 3914
071048a3 3915 if (! fface)
2db4bfe5 3916 return Qnil;
a1a552b3 3917#ifdef HAVE_WINDOW_SYSTEM
75dad34a 3918 if (FRAME_WINDOW_P (f) && !NILP (character))
a1a552b3
KH
3919 {
3920 CHECK_CHARACTER (character);
071048a3
PE
3921 face_id = FACE_FOR_CHAR (f, fface, XINT (character), -1, Qnil);
3922 fface = FACE_FROM_ID (f, face_id);
a1a552b3 3923 }
071048a3
PE
3924 return (fface->font
3925 ? fface->font->props[FONT_NAME_INDEX]
2dee4c0b 3926 : Qnil);
1ccdfd33
EZ
3927#else /* !HAVE_WINDOW_SYSTEM */
3928 return build_string (FRAME_MSDOS_P (f)
3929 ? "ms-dos"
3930 : FRAME_W32_P (f) ? "w32term"
3931 :"tty");
3932#endif
82641697
GM
3933 }
3934}
3935
3936
9717e36c 3937/* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
82641697
GM
3938 all attributes are `equal'. Tries to be fast because this function
3939 is called quite often. */
3940
55d4c1b2 3941static inline int
971de7fb 3942face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
82641697 3943{
9717e36c
MB
3944 /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
3945 and the other is specified. */
3946 if (XTYPE (v1) != XTYPE (v2))
3947 return 0;
82641697 3948
9717e36c
MB
3949 if (EQ (v1, v2))
3950 return 1;
82641697 3951
9717e36c
MB
3952 switch (XTYPE (v1))
3953 {
3954 case Lisp_String:
3955 if (SBYTES (v1) != SBYTES (v2))
3956 return 0;
82641697 3957
72af86bd 3958 return memcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
178c5d9c 3959
2de9f71c 3960 case_Lisp_Int:
9717e36c
MB
3961 case Lisp_Symbol:
3962 return 0;
178c5d9c 3963
9717e36c
MB
3964 default:
3965 return !NILP (Fequal (v1, v2));
82641697 3966 }
9717e36c
MB
3967}
3968
3969
3970/* Compare face vectors V1 and V2 for equality. Value is non-zero if
3971 all attributes are `equal'. Tries to be fast because this function
3972 is called quite often. */
3973
55d4c1b2 3974static inline int
971de7fb 3975lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
9717e36c
MB
3976{
3977 int i, equal_p = 1;
3978
3979 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
3980 equal_p = face_attr_equal_p (v1[i], v2[i]);
178c5d9c 3981
82641697
GM
3982 return equal_p;
3983}
3984
3985
3986DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
3987 Sinternal_lisp_face_equal_p, 2, 3, 0,
7ee72033 3988 doc: /* True if FACE1 and FACE2 are equal.
03f11322
JB
3989If the optional argument FRAME is given, report on FACE1 and FACE2 in that frame.
3990If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames).
7ee72033 3991If FRAME is omitted or nil, use the selected frame. */)
5842a27b 3992 (Lisp_Object face1, Lisp_Object face2, Lisp_Object frame)
82641697
GM
3993{
3994 int equal_p;
7b953c9c 3995 struct frame *f;
82641697 3996 Lisp_Object lface1, lface2;
178c5d9c 3997
7b953c9c
MB
3998 if (EQ (frame, Qt))
3999 f = NULL;
4000 else
4001 /* Don't use check_x_frame here because this function is called
4002 before X frames exist. At that time, if FRAME is nil,
4003 selected_frame will be used which is the frame dumped with
4004 Emacs. That frame is not an X frame. */
4005 f = frame_or_selected_frame (frame, 2);
4006
03f11322
JB
4007 lface1 = lface_from_face_name (f, face1, 1);
4008 lface2 = lface_from_face_name (f, face2, 1);
82641697
GM
4009 equal_p = lface_equal_p (XVECTOR (lface1)->contents,
4010 XVECTOR (lface2)->contents);
4011 return equal_p ? Qt : Qnil;
4012}
4013
178c5d9c 4014
82641697
GM
4015DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
4016 Sinternal_lisp_face_empty_p, 1, 2, 0,
7ee72033 4017 doc: /* True if FACE has no attribute specified.
228299fa
GM
4018If the optional argument FRAME is given, report on face FACE in that frame.
4019If FRAME is t, report on the defaults for face FACE (for new frames).
7ee72033 4020If FRAME is omitted or nil, use the selected frame. */)
5842a27b 4021 (Lisp_Object face, Lisp_Object frame)
82641697
GM
4022{
4023 struct frame *f;
4024 Lisp_Object lface;
4025 int i;
4026
4027 if (NILP (frame))
c0617987 4028 frame = selected_frame;
b7826503 4029 CHECK_LIVE_FRAME (frame);
c0617987 4030 f = XFRAME (frame);
178c5d9c 4031
82641697
GM
4032 if (EQ (frame, Qt))
4033 lface = lface_from_face_name (NULL, face, 1);
4034 else
4035 lface = lface_from_face_name (f, face, 1);
4036
4037 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
a08332c0 4038 if (!UNSPECIFIEDP (AREF (lface, i)))
82641697 4039 break;
178c5d9c 4040
82641697
GM
4041 return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
4042}
4043
4044
4045DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
178c5d9c 4046 0, 1, 0,
7ee72033
MB
4047 doc: /* Return an alist of frame-local faces defined on FRAME.
4048For internal use only. */)
5842a27b 4049 (Lisp_Object frame)
82641697
GM
4050{
4051 struct frame *f = frame_or_selected_frame (frame, 0);
4052 return f->face_alist;
4053}
4054
4055
4056/* Return a hash code for Lisp string STRING with case ignored. Used
4057 below in computing a hash value for a Lisp face. */
4058
55d4c1b2 4059static inline unsigned
971de7fb 4060hash_string_case_insensitive (Lisp_Object string)
82641697 4061{
53c208f6 4062 const unsigned char *s;
82641697 4063 unsigned hash = 0;
a54e2c05 4064 eassert (STRINGP (string));
d5db4077 4065 for (s = SDATA (string); *s; ++s)
82641697
GM
4066 hash = (hash << 1) ^ tolower (*s);
4067 return hash;
4068}
4069
4070
4071/* Return a hash code for face attribute vector V. */
4072
55d4c1b2 4073static inline unsigned
971de7fb 4074lface_hash (Lisp_Object *v)
82641697
GM
4075{
4076 return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
53aaf1e2 4077 ^ hash_string_case_insensitive (v[LFACE_FOUNDRY_INDEX])
82641697
GM
4078 ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
4079 ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
a2bc5bdd
SM
4080 ^ XHASH (v[LFACE_WEIGHT_INDEX])
4081 ^ XHASH (v[LFACE_SLANT_INDEX])
4082 ^ XHASH (v[LFACE_SWIDTH_INDEX])
4083 ^ XHASH (v[LFACE_HEIGHT_INDEX]));
82641697
GM
4084}
4085
4086
4087/* Return non-zero if LFACE1 and LFACE2 specify the same font (without
4088 considering charsets/registries). They do if they specify the same
2dee4c0b 4089 family, point size, weight, width, slant, and font. Both
763bc839 4090 LFACE1 and LFACE2 must be fully-specified. */
82641697 4091
55d4c1b2 4092static inline int
971de7fb 4093lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
82641697 4094{
a54e2c05 4095 eassert (lface_fully_specified_p (lface1)
82641697 4096 && lface_fully_specified_p (lface2));
25a48bd0 4097 return (xstrcasecmp (SSDATA (lface1[LFACE_FAMILY_INDEX]),
b5f03016 4098 SSDATA (lface2[LFACE_FAMILY_INDEX])) == 0
25a48bd0
PE
4099 && xstrcasecmp (SSDATA (lface1[LFACE_FOUNDRY_INDEX]),
4100 SSDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
2c20458f 4101 && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
82641697
GM
4102 && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
4103 && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
39506348 4104 && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
2dee4c0b 4105 && EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
763bc839
KH
4106 && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
4107 || (STRINGP (lface1[LFACE_FONTSET_INDEX])
4108 && STRINGP (lface2[LFACE_FONTSET_INDEX])
25a48bd0 4109 && ! xstrcasecmp (SSDATA (lface1[LFACE_FONTSET_INDEX]),
b5f03016 4110 SSDATA (lface2[LFACE_FONTSET_INDEX]))))
763bc839 4111 );
82641697
GM
4112}
4113
4114
4115\f
4116/***********************************************************************
4117 Realized Faces
4118 ***********************************************************************/
4119
4120/* Allocate and return a new realized face for Lisp face attribute
39506348 4121 vector ATTR. */
82641697
GM
4122
4123static struct face *
971de7fb 4124make_realized_face (Lisp_Object *attr)
82641697 4125{
23f86fce 4126 struct face *face = xzalloc (sizeof *face);
39506348 4127 face->ascii_face = face;
72af86bd 4128 memcpy (face->lface, attr, sizeof face->lface);
82641697
GM
4129 return face;
4130}
4131
4132
4133/* Free realized face FACE, including its X resources. FACE may
4134 be null. */
4135
435f4c28 4136static void
971de7fb 4137free_realized_face (struct frame *f, struct face *face)
82641697
GM
4138{
4139 if (face)
4140 {
c3cee013
JR
4141#ifdef HAVE_WINDOW_SYSTEM
4142 if (FRAME_WINDOW_P (f))
82641697 4143 {
39506348
KH
4144 /* Free fontset of FACE if it is ASCII face. */
4145 if (face->fontset >= 0 && face == face->ascii_face)
4146 free_face_fontset (f, face);
82641697
GM
4147 if (face->gc)
4148 {
985773c9 4149 BLOCK_INPUT;
2dee4c0b 4150 if (face->font)
426b2119 4151 font_done_for_face (f, face);
82641697
GM
4152 x_free_gc (f, face->gc);
4153 face->gc = 0;
ed0c79c6 4154 UNBLOCK_INPUT;
82641697 4155 }
178c5d9c 4156
82641697
GM
4157 free_face_colors (f, face);
4158 x_destroy_bitmap (f, face->stipple);
4159 }
c3cee013 4160#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
4161
4162 xfree (face);
4163 }
4164}
4165
4166
4167/* Prepare face FACE for subsequent display on frame F. This
4168 allocated GCs if they haven't been allocated yet or have been freed
4169 by clearing the face cache. */
4170
4171void
971de7fb 4172prepare_face_for_display (struct frame *f, struct face *face)
82641697 4173{
c3cee013 4174#ifdef HAVE_WINDOW_SYSTEM
a54e2c05 4175 eassert (FRAME_WINDOW_P (f));
178c5d9c 4176
82641697
GM
4177 if (face->gc == 0)
4178 {
4179 XGCValues xgcv;
4180 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
4181
4182 xgcv.foreground = face->foreground;
4183 xgcv.background = face->background;
c3cee013 4184#ifdef HAVE_X_WINDOWS
82641697 4185 xgcv.graphics_exposures = False;
c3cee013 4186#endif
82641697
GM
4187
4188 BLOCK_INPUT;
c3cee013 4189#ifdef HAVE_X_WINDOWS
82641697
GM
4190 if (face->stipple)
4191 {
be8a72f4 4192 xgcv.fill_style = FillOpaqueStippled;
82641697
GM
4193 xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
4194 mask |= GCFillStyle | GCStipple;
4195 }
c3cee013 4196#endif
82641697 4197 face->gc = x_create_gc (f, mask, &xgcv);
2dee4c0b 4198 if (face->font)
426b2119 4199 font_prepare_for_face (f, face);
82641697
GM
4200 UNBLOCK_INPUT;
4201 }
c3cee013 4202#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
4203}
4204
82641697 4205\f
b35df831
MB
4206/* Returns the `distance' between the colors X and Y. */
4207
4208static int
971de7fb 4209color_distance (XColor *x, XColor *y)
b35df831 4210{
da6062e6 4211 /* This formula is from a paper titled `Colour metric' by Thiadmer Riemersma.
b35df831
MB
4212 Quoting from that paper:
4213
b5f03016
AS
4214 This formula has results that are very close to L*u*v* (with the
4215 modified lightness curve) and, more importantly, it is a more even
da6062e6 4216 algorithm: it does not have a range of colors where it suddenly
b5f03016 4217 gives far from optimal results.
b35df831
MB
4218
4219 See <http://www.compuphase.com/cmetric.htm> for more info. */
4220
4221 long r = (x->red - y->red) >> 8;
4222 long g = (x->green - y->green) >> 8;
4223 long b = (x->blue - y->blue) >> 8;
4224 long r_mean = (x->red + y->red) >> 9;
4225
4226 return
4227 (((512 + r_mean) * r * r) >> 8)
4228 + 4 * g * g
4229 + (((767 - r_mean) * b * b) >> 8);
4230}
4231
4232
4233DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 3, 0,
4234 doc: /* Return an integer distance between COLOR1 and COLOR2 on FRAME.
4235COLOR1 and COLOR2 may be either strings containing the color name,
4236or lists of the form (RED GREEN BLUE).
4237If FRAME is unspecified or nil, the current frame is used. */)
5842a27b 4238 (Lisp_Object color1, Lisp_Object color2, Lisp_Object frame)
b35df831
MB
4239{
4240 struct frame *f;
4241 XColor cdef1, cdef2;
4242
4243 if (NILP (frame))
4244 frame = selected_frame;
4245 CHECK_LIVE_FRAME (frame);
4246 f = XFRAME (frame);
4247
6c8e1d62 4248 if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
42a5b22f 4249 && !(STRINGP (color1) && defined_color (f, SSDATA (color1), &cdef1, 0)))
b35df831 4250 signal_error ("Invalid color", color1);
6c8e1d62 4251 if (!(CONSP (color2) && parse_rgb_list (color2, &cdef2))
42a5b22f 4252 && !(STRINGP (color2) && defined_color (f, SSDATA (color2), &cdef2, 0)))
b35df831
MB
4253 signal_error ("Invalid color", color2);
4254
4255 return make_number (color_distance (&cdef1, &cdef2));
4256}
4257
4258\f
82641697
GM
4259/***********************************************************************
4260 Face Cache
4261 ***********************************************************************/
4262
4263/* Return a new face cache for frame F. */
4264
4265static struct face_cache *
971de7fb 4266make_face_cache (struct frame *f)
82641697
GM
4267{
4268 struct face_cache *c;
4269 int size;
4270
23f86fce 4271 c = xzalloc (sizeof *c);
82641697 4272 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
23f86fce 4273 c->buckets = xzalloc (size);
82641697 4274 c->size = 50;
23f86fce 4275 c->faces_by_id = xmalloc (c->size * sizeof *c->faces_by_id);
82641697 4276 c->f = f;
ceeda019 4277 c->menu_face_changed_p = menu_face_changed_default;
82641697
GM
4278 return c;
4279}
4280
4281
4282/* Clear out all graphics contexts for all realized faces, except for
4283 the basic faces. This should be done from time to time just to avoid
4284 keeping too many graphics contexts that are no longer needed. */
4285
4286static void
971de7fb 4287clear_face_gcs (struct face_cache *c)
82641697 4288{
c3cee013 4289 if (c && FRAME_WINDOW_P (c->f))
82641697 4290 {
c3cee013 4291#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
4292 int i;
4293 for (i = BASIC_FACE_ID_SENTINEL; i < c->used; ++i)
4294 {
4295 struct face *face = c->faces_by_id[i];
4296 if (face && face->gc)
4297 {
985773c9 4298 BLOCK_INPUT;
2dee4c0b 4299 if (face->font)
426b2119 4300 font_done_for_face (c->f, face);
82641697
GM
4301 x_free_gc (c->f, face->gc);
4302 face->gc = 0;
ed0c79c6 4303 UNBLOCK_INPUT;
82641697
GM
4304 }
4305 }
c3cee013 4306#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
4307 }
4308}
4309
4310
7fc92635
JB
4311/* Free all realized faces in face cache C, including basic faces.
4312 C may be null. If faces are freed, make sure the frame's current
82641697
GM
4313 matrix is marked invalid, so that a display caused by an expose
4314 event doesn't try to use faces we destroyed. */
4315
4316static void
971de7fb 4317free_realized_faces (struct face_cache *c)
82641697
GM
4318{
4319 if (c && c->used)
4320 {
4321 int i, size;
4322 struct frame *f = c->f;
4323
84ec3b4b
GM
4324 /* We must block input here because we can't process X events
4325 safely while only some faces are freed, or when the frame's
4326 current matrix still references freed faces. */
4327 BLOCK_INPUT;
4328
82641697
GM
4329 for (i = 0; i < c->used; ++i)
4330 {
4331 free_realized_face (f, c->faces_by_id[i]);
4332 c->faces_by_id[i] = NULL;
4333 }
178c5d9c 4334
82641697
GM
4335 c->used = 0;
4336 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
72af86bd 4337 memset (c->buckets, 0, size);
82641697
GM
4338
4339 /* Must do a thorough redisplay the next time. Mark current
4340 matrices as invalid because they will reference faces freed
4341 above. This function is also called when a frame is
4342 destroyed. In this case, the root window of F is nil. */
4343 if (WINDOWP (f->root_window))
4344 {
4345 clear_current_matrices (f);
4346 ++windows_or_buffers_changed;
4347 }
84ec3b4b
GM
4348
4349 UNBLOCK_INPUT;
82641697
GM
4350 }
4351}
4352
4353
4354/* Free all realized faces on FRAME or on all frames if FRAME is nil.
4355 This is done after attributes of a named face have been changed,
4356 because we can't tell which realized faces depend on that face. */
4357
4358void
971de7fb 4359free_all_realized_faces (Lisp_Object frame)
82641697
GM
4360{
4361 if (NILP (frame))
4362 {
4363 Lisp_Object rest;
4364 FOR_EACH_FRAME (rest, frame)
4365 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4366 }
4367 else
4368 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4369}
4370
4371
4372/* Free face cache C and faces in it, including their X resources. */
4373
4374static void
971de7fb 4375free_face_cache (struct face_cache *c)
82641697
GM
4376{
4377 if (c)
4378 {
4379 free_realized_faces (c);
4380 xfree (c->buckets);
4381 xfree (c->faces_by_id);
4382 xfree (c);
4383 }
4384}
4385
4386
4387/* Cache realized face FACE in face cache C. HASH is the hash value
af53b43c
KH
4388 of FACE. If FACE is for ASCII characters (i.e. FACE->ascii_face ==
4389 FACE), insert the new face to the beginning of the collision list
4390 of the face hash table of C. Otherwise, add the new face to the
4391 end of the collision list. This way, lookup_face can quickly find
4392 that a requested face is not cached. */
82641697
GM
4393
4394static void
971de7fb 4395cache_face (struct face_cache *c, struct face *face, unsigned int hash)
82641697
GM
4396{
4397 int i = hash % FACE_CACHE_BUCKETS_SIZE;
4398
4399 face->hash = hash;
4400
af53b43c 4401 if (face->ascii_face != face)
82641697
GM
4402 {
4403 struct face *last = c->buckets[i];
4404 if (last)
4405 {
4406 while (last->next)
4407 last = last->next;
4408 last->next = face;
4409 face->prev = last;
4410 face->next = NULL;
4411 }
4412 else
4413 {
4414 c->buckets[i] = face;
4415 face->prev = face->next = NULL;
4416 }
4417 }
4418 else
4419 {
4420 face->prev = NULL;
4421 face->next = c->buckets[i];
4422 if (face->next)
4423 face->next->prev = face;
4424 c->buckets[i] = face;
4425 }
4426
4427 /* Find a free slot in C->faces_by_id and use the index of the free
4428 slot as FACE->id. */
4429 for (i = 0; i < c->used; ++i)
4430 if (c->faces_by_id[i] == NULL)
4431 break;
4432 face->id = i;
178c5d9c 4433
e509cfa6 4434#ifdef GLYPH_DEBUG
85fece3e
PE
4435 /* Check that FACE got a unique id. */
4436 {
4437 int j, n;
4438 struct face *face1;
4439
4440 for (j = n = 0; j < FACE_CACHE_BUCKETS_SIZE; ++j)
4441 for (face1 = c->buckets[j]; face1; face1 = face1->next)
4442 if (face1->id == i)
4443 ++n;
4444
a54e2c05 4445 eassert (n == 1);
85fece3e
PE
4446 }
4447#endif /* GLYPH_DEBUG */
4448
82641697 4449 /* Maybe enlarge C->faces_by_id. */
6b61353c 4450 if (i == c->used)
82641697 4451 {
6b61353c 4452 if (c->used == c->size)
0065d054
PE
4453 c->faces_by_id = xpalloc (c->faces_by_id, &c->size, 1, MAX_FACE_ID,
4454 sizeof *c->faces_by_id);
6b61353c 4455 c->used++;
82641697
GM
4456 }
4457
82641697 4458 c->faces_by_id[i] = face;
82641697
GM
4459}
4460
4461
4462/* Remove face FACE from cache C. */
4463
4464static void
971de7fb 4465uncache_face (struct face_cache *c, struct face *face)
82641697
GM
4466{
4467 int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
178c5d9c 4468
82641697
GM
4469 if (face->prev)
4470 face->prev->next = face->next;
4471 else
4472 c->buckets[i] = face->next;
178c5d9c 4473
82641697
GM
4474 if (face->next)
4475 face->next->prev = face->prev;
178c5d9c 4476
82641697
GM
4477 c->faces_by_id[face->id] = NULL;
4478 if (face->id == c->used)
4479 --c->used;
4480}
4481
4482
4483/* Look up a realized face with face attributes ATTR in the face cache
af53b43c
KH
4484 of frame F. The face will be used to display ASCII characters.
4485 Value is the ID of the face found. If no suitable face is found,
4486 realize a new one. */
82641697 4487
55d4c1b2 4488static inline int
971de7fb 4489lookup_face (struct frame *f, Lisp_Object *attr)
82641697 4490{
39506348 4491 struct face_cache *cache = FRAME_FACE_CACHE (f);
82641697
GM
4492 unsigned hash;
4493 int i;
4494 struct face *face;
4495
a54e2c05 4496 eassert (cache != NULL);
82641697
GM
4497 check_lface_attrs (attr);
4498
4499 /* Look up ATTR in the face cache. */
4500 hash = lface_hash (attr);
4501 i = hash % FACE_CACHE_BUCKETS_SIZE;
178c5d9c 4502
39506348 4503 for (face = cache->buckets[i]; face; face = face->next)
af53b43c
KH
4504 {
4505 if (face->ascii_face != face)
4506 {
4507 /* There's no more ASCII face. */
4508 face = NULL;
4509 break;
4510 }
4511 if (face->hash == hash
4512 && lface_equal_p (face->lface, attr))
4513 break;
4514 }
82641697
GM
4515
4516 /* If not found, realize a new face. */
4517 if (face == NULL)
af53b43c 4518 face = realize_face (cache, attr, -1);
82641697 4519
e509cfa6 4520#ifdef GLYPH_DEBUG
a54e2c05 4521 eassert (face == FACE_FROM_ID (f, face->id));
82641697 4522#endif /* GLYPH_DEBUG */
178c5d9c 4523
82641697
GM
4524 return face->id;
4525}
4526
2dee4c0b
KH
4527#ifdef HAVE_WINDOW_SYSTEM
4528/* Look up a realized face that has the same attributes as BASE_FACE
4529 except for the font in the face cache of frame F. If FONT-OBJECT
4530 is not nil, it is an already opened font. If FONT-OBJECT is nil,
4531 the face has no font. Value is the ID of the face found. If no
4532 suitable face is found, realize a new one. */
426b2119 4533
426b2119 4534int
971de7fb 4535face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
426b2119
KH
4536{
4537 struct face_cache *cache = FRAME_FACE_CACHE (f);
4538 unsigned hash;
4539 int i;
4540 struct face *face;
4541
a54e2c05 4542 eassert (cache != NULL);
426b2119
KH
4543 base_face = base_face->ascii_face;
4544 hash = lface_hash (base_face->lface);
4545 i = hash % FACE_CACHE_BUCKETS_SIZE;
4546
4547 for (face = cache->buckets[i]; face; face = face->next)
4548 {
4549 if (face->ascii_face == face)
4550 continue;
4551 if (face->ascii_face == base_face
2dee4c0b
KH
4552 && face->font == (NILP (font_object) ? NULL
4553 : XFONT_OBJECT (font_object))
4554 && lface_equal_p (face->lface, base_face->lface))
426b2119
KH
4555 return face->id;
4556 }
4557
4558 /* If not found, realize a new face. */
2dee4c0b 4559 face = realize_non_ascii_face (f, font_object, base_face);
426b2119
KH
4560 return face->id;
4561}
8c6204de 4562#endif /* HAVE_WINDOW_SYSTEM */
82641697 4563
82641697 4564/* Return the face id of the realized face for named face SYMBOL on
af53b43c
KH
4565 frame F suitable for displaying ASCII characters. Value is -1 if
4566 the face couldn't be determined, which might happen if the default
4567 face isn't realized and cannot be realized. */
82641697
GM
4568
4569int
971de7fb 4570lookup_named_face (struct frame *f, Lisp_Object symbol, int signal_p)
82641697 4571{
e7d7fd8c
MB
4572 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4573 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
82641697
GM
4574 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4575
b5de343d
GM
4576 if (default_face == NULL)
4577 {
4578 if (!realize_basic_faces (f))
4579 return -1;
4580 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
418ca4d2
RS
4581 if (default_face == NULL)
4582 abort (); /* realize_basic_faces must have set it up */
b5de343d
GM
4583 }
4584
f2cec7a9 4585 if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
2272e967
KS
4586 return -1;
4587
72af86bd 4588 memcpy (attrs, default_face->lface, sizeof attrs);
e7d7fd8c 4589 merge_face_vectors (f, symbol_attrs, attrs, 0);
a0a23346 4590
af53b43c 4591 return lookup_face (f, attrs);
82641697
GM
4592}
4593
4594
1682701f 4595/* Return the display face-id of the basic face whose canonical face-id
f2cec7a9
MB
4596 is FACE_ID. The return value will usually simply be FACE_ID, unless that
4597 basic face has bee remapped via Vface_remapping_alist. This function is
4598 conservative: if something goes wrong, it will simply return FACE_ID
4599 rather than signal an error. */
4600
4601int
971de7fb 4602lookup_basic_face (struct frame *f, int face_id)
f2cec7a9
MB
4603{
4604 Lisp_Object name, mapping;
4605 int remapped_face_id;
4606
4607 if (NILP (Vface_remapping_alist))
4608 return face_id; /* Nothing to do. */
4609
4610 switch (face_id)
4611 {
4612 case DEFAULT_FACE_ID: name = Qdefault; break;
4613 case MODE_LINE_FACE_ID: name = Qmode_line; break;
4614 case MODE_LINE_INACTIVE_FACE_ID: name = Qmode_line_inactive; break;
4615 case HEADER_LINE_FACE_ID: name = Qheader_line; break;
4616 case TOOL_BAR_FACE_ID: name = Qtool_bar; break;
4617 case FRINGE_FACE_ID: name = Qfringe; break;
4618 case SCROLL_BAR_FACE_ID: name = Qscroll_bar; break;
4619 case BORDER_FACE_ID: name = Qborder; break;
4620 case CURSOR_FACE_ID: name = Qcursor; break;
4621 case MOUSE_FACE_ID: name = Qmouse; break;
4622 case MENU_FACE_ID: name = Qmenu; break;
4623
4624 default:
4625 abort (); /* the caller is supposed to pass us a basic face id */
4626 }
4627
4628 /* Do a quick scan through Vface_remapping_alist, and return immediately
4629 if there is no remapping for face NAME. This is just an optimization
4630 for the very common no-remapping case. */
4631 mapping = assq_no_quit (name, Vface_remapping_alist);
4632 if (NILP (mapping))
4633 return face_id; /* Give up. */
4634
4635 /* If there is a remapping entry, lookup the face using NAME, which will
4636 handle the remapping too. */
4637 remapped_face_id = lookup_named_face (f, name, 0);
4638 if (remapped_face_id < 0)
4639 return face_id; /* Give up. */
4640
4641 return remapped_face_id;
4642}
4643
4644
82641697
GM
4645/* Return a face for charset ASCII that is like the face with id
4646 FACE_ID on frame F, but has a font that is STEPS steps smaller.
4647 STEPS < 0 means larger. Value is the id of the face. */
4648
4649int
971de7fb 4650smaller_face (struct frame *f, int face_id, int steps)
39506348 4651{
c3cee013 4652#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
4653 struct face *face;
4654 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4655 int pt, last_pt, last_height;
4656 int delta;
4657 int new_face_id;
4658 struct face *new_face;
4659
4660 /* If not called for an X frame, just return the original face. */
4661 if (FRAME_TERMCAP_P (f))
4662 return face_id;
4663
4664 /* Try in increments of 1/2 pt. */
4665 delta = steps < 0 ? 5 : -5;
1ea40aa2 4666 steps = eabs (steps);
178c5d9c 4667
82641697 4668 face = FACE_FROM_ID (f, face_id);
72af86bd 4669 memcpy (attrs, face->lface, sizeof attrs);
82641697
GM
4670 pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
4671 new_face_id = face_id;
4672 last_height = FONT_HEIGHT (face->font);
4673
4674 while (steps
4675 && pt + delta > 0
4676 /* Give up if we cannot find a font within 10pt. */
1ea40aa2 4677 && eabs (last_pt - pt) < 100)
82641697
GM
4678 {
4679 /* Look up a face for a slightly smaller/larger font. */
4680 pt += delta;
4681 attrs[LFACE_HEIGHT_INDEX] = make_number (pt);
af53b43c 4682 new_face_id = lookup_face (f, attrs);
82641697
GM
4683 new_face = FACE_FROM_ID (f, new_face_id);
4684
4685 /* If height changes, count that as one step. */
b4c3ca09
GM
4686 if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
4687 || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
82641697
GM
4688 {
4689 --steps;
4690 last_height = FONT_HEIGHT (new_face->font);
4691 last_pt = pt;
4692 }
4693 }
4694
4695 return new_face_id;
4696
c3cee013 4697#else /* not HAVE_WINDOW_SYSTEM */
82641697
GM
4698
4699 return face_id;
178c5d9c 4700
c3cee013 4701#endif /* not HAVE_WINDOW_SYSTEM */
82641697
GM
4702}
4703
4704
4705/* Return a face for charset ASCII that is like the face with id
4706 FACE_ID on frame F, but has height HEIGHT. */
4707
4708int
971de7fb 4709face_with_height (struct frame *f, int face_id, int height)
82641697 4710{
c3cee013 4711#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
4712 struct face *face;
4713 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4714
4715 if (FRAME_TERMCAP_P (f)
4716 || height <= 0)
4717 return face_id;
4718
4719 face = FACE_FROM_ID (f, face_id);
72af86bd 4720 memcpy (attrs, face->lface, sizeof attrs);
82641697 4721 attrs[LFACE_HEIGHT_INDEX] = make_number (height);
a8c0cc18 4722 font_clear_prop (attrs, FONT_SIZE_INDEX);
af53b43c 4723 face_id = lookup_face (f, attrs);
c3cee013 4724#endif /* HAVE_WINDOW_SYSTEM */
178c5d9c 4725
82641697
GM
4726 return face_id;
4727}
4728
b5de343d 4729
44747bd0 4730/* Return the face id of the realized face for named face SYMBOL on
af53b43c
KH
4731 frame F suitable for displaying ASCII characters, and use
4732 attributes of the face FACE_ID for attributes that aren't
4733 completely specified by SYMBOL. This is like lookup_named_face,
4734 except that the default attributes come from FACE_ID, not from the
4735 default face. FACE_ID is assumed to be already realized. */
44747bd0
EZ
4736
4737int
b5f03016
AS
4738lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id,
4739 int signal_p)
44747bd0 4740{
e7d7fd8c 4741 Lisp_Object attrs[LFACE_VECTOR_SIZE];
44747bd0
EZ
4742 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
4743 struct face *default_face = FACE_FROM_ID (f, face_id);
4744
4745 if (!default_face)
4746 abort ();
4747
d8453278
CY
4748 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
4749 return -1;
4750
72af86bd 4751 memcpy (attrs, default_face->lface, sizeof attrs);
e7d7fd8c 4752 merge_face_vectors (f, symbol_attrs, attrs, 0);
af53b43c 4753 return lookup_face (f, attrs);
44747bd0
EZ
4754}
4755
f6608d5c
RS
4756DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
4757 Sface_attributes_as_vector, 1, 1, 0,
4bb962be 4758 doc: /* Return a vector of face attributes corresponding to PLIST. */)
5842a27b 4759 (Lisp_Object plist)
f6608d5c
RS
4760{
4761 Lisp_Object lface;
4762 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4763 Qunspecified);
a0a23346
MB
4764 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents,
4765 1, 0);
f6608d5c
RS
4766 return lface;
4767}
4768
82641697
GM
4769
4770\f
9717e36c
MB
4771/***********************************************************************
4772 Face capability testing
4773 ***********************************************************************/
4774
4775
4776/* If the distance (as returned by color_distance) between two colors is
4777 less than this, then they are considered the same, for determining
4778 whether a color is supported or not. The range of values is 0-65535. */
4779
4780#define TTY_SAME_COLOR_THRESHOLD 10000
4781
ccda4e3c 4782#ifdef HAVE_WINDOW_SYSTEM
9717e36c
MB
4783
4784/* Return non-zero if all the face attributes in ATTRS are supported
4785 on the window-system frame F.
4786
4787 The definition of `supported' is somewhat heuristic, but basically means
4788 that a face containing all the attributes in ATTRS, when merged with the
4789 default face for display, can be represented in a way that's
4790
4791 \(1) different in appearance than the default face, and
8e330b22 4792 \(2) `close in spirit' to what the attributes specify, if not exact. */
9717e36c
MB
4793
4794static int
b5f03016
AS
4795x_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
4796 struct face *def_face)
9717e36c 4797{
8e330b22 4798 Lisp_Object *def_attrs = def_face->lface;
9717e36c
MB
4799
4800 /* Check that other specified attributes are different that the default
4801 face. */
4802 if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
4803 && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
4804 def_attrs[LFACE_UNDERLINE_INDEX]))
4805 || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
4806 && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
4807 def_attrs[LFACE_INVERSE_INDEX]))
4808 || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
4809 && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
4810 def_attrs[LFACE_FOREGROUND_INDEX]))
4811 || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
4812 && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
4813 def_attrs[LFACE_BACKGROUND_INDEX]))
4814 || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
4815 && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
4816 def_attrs[LFACE_STIPPLE_INDEX]))
4817 || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
4818 && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
4819 def_attrs[LFACE_OVERLINE_INDEX]))
4820 || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
4821 && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
4822 def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
4823 || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
4824 && face_attr_equal_p (attrs[LFACE_BOX_INDEX],
4825 def_attrs[LFACE_BOX_INDEX])))
4826 return 0;
4827
4828 /* Check font-related attributes, as those are the most commonly
4829 "unsupported" on a window-system (because of missing fonts). */
4830 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
53aaf1e2 4831 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
9717e36c
MB
4832 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
4833 || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
4834 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
2dee4c0b 4835 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]))
9717e36c 4836 {
327719ee 4837 int face_id;
9717e36c
MB
4838 struct face *face;
4839 Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
2dee4c0b 4840 int i;
9717e36c 4841
72af86bd 4842 memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
9717e36c 4843
a0a23346 4844 merge_face_vectors (f, attrs, merged_attrs, 0);
9717e36c 4845
327719ee
MB
4846 face_id = lookup_face (f, merged_attrs);
4847 face = FACE_FROM_ID (f, face_id);
9717e36c
MB
4848
4849 if (! face)
2010ba8c 4850 error ("Cannot make face");
9717e36c 4851
4fc1984a
KH
4852 /* If the font is the same, or no font is found, then not
4853 supported. */
4854 if (face->font == def_face->font
4855 || ! face->font)
9717e36c 4856 return 0;
2dee4c0b
KH
4857 for (i = FONT_TYPE_INDEX; i <= FONT_SIZE_INDEX; i++)
4858 if (! EQ (face->font->props[i], def_face->font->props[i]))
4859 {
4860 Lisp_Object s1, s2;
4861
4862 if (i < FONT_FOUNDRY_INDEX || i > FONT_REGISTRY_INDEX
4863 || face->font->driver->case_sensitive)
4864 return 1;
4865 s1 = SYMBOL_NAME (face->font->props[i]);
4866 s2 = SYMBOL_NAME (def_face->font->props[i]);
4867 if (! EQ (Fcompare_strings (s1, make_number (0), Qnil,
4868 s2, make_number (0), Qnil, Qt), Qt))
4869 return 1;
4870 }
4871 return 0;
9717e36c
MB
4872 }
4873
4874 /* Everything checks out, this face is supported. */
4875 return 1;
4876}
4877
ccda4e3c 4878#endif /* HAVE_WINDOW_SYSTEM */
9717e36c
MB
4879
4880/* Return non-zero if all the face attributes in ATTRS are supported
4881 on the tty frame F.
4882
4883 The definition of `supported' is somewhat heuristic, but basically means
4884 that a face containing all the attributes in ATTRS, when merged
4885 with the default face for display, can be represented in a way that's
4886
4887 \(1) different in appearance than the default face, and
4888 \(2) `close in spirit' to what the attributes specify, if not exact.
4889
4890 Point (2) implies that a `:weight black' attribute will be satisfied
4891 by any terminal that can display bold, and a `:foreground "yellow"' as
4892 long as the terminal can display a yellowish color, but `:slant italic'
4893 will _not_ be satisfied by the tty display code's automatic
4894 substitution of a `dim' face for italic. */
4895
4896static int
b5f03016
AS
4897tty_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
4898 struct face *def_face)
9717e36c 4899{
cd4eb164 4900 int weight, slant;
9717e36c
MB
4901 Lisp_Object val, fg, bg;
4902 XColor fg_tty_color, fg_std_color;
4903 XColor bg_tty_color, bg_std_color;
4904 unsigned test_caps = 0;
8e330b22 4905 Lisp_Object *def_attrs = def_face->lface;
9717e36c 4906
8e330b22
MB
4907 /* First check some easy-to-check stuff; ttys support none of the
4908 following attributes, so we can just return false if any are requested
4909 (even if `nominal' values are specified, we should still return false,
4910 as that will be the same value that the default face uses). We
4911 consider :slant unsupportable on ttys, even though the face code
4912 actually `fakes' them using a dim attribute if possible. This is
4913 because the faked result is too different from what the face
4914 specifies. */
4915 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
53aaf1e2 4916 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
8e330b22
MB
4917 || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
4918 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
4919 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
4920 || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
4921 || !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
cd4eb164 4922 || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]))
9717e36c
MB
4923 return 0;
4924
9717e36c
MB
4925 /* Test for terminal `capabilities' (non-color character attributes). */
4926
4927 /* font weight (bold/dim) */
337fbd17
CY
4928 val = attrs[LFACE_WEIGHT_INDEX];
4929 if (!UNSPECIFIEDP (val)
4930 && (weight = FONT_WEIGHT_NAME_NUMERIC (val), weight >= 0))
9717e36c 4931 {
2dee4c0b 4932 int def_weight = FONT_WEIGHT_NAME_NUMERIC (def_attrs[LFACE_WEIGHT_INDEX]);
8e330b22 4933
2dee4c0b 4934 if (weight > 100)
8e330b22 4935 {
2dee4c0b 4936 if (def_weight > 100)
8e330b22
MB
4937 return 0; /* same as default */
4938 test_caps = TTY_CAP_BOLD;
4939 }
2dee4c0b 4940 else if (weight < 100)
8e330b22 4941 {
2dee4c0b 4942 if (def_weight < 100)
8e330b22
MB
4943 return 0; /* same as default */
4944 test_caps = TTY_CAP_DIM;
4945 }
2dee4c0b 4946 else if (def_weight == 100)
8e330b22 4947 return 0; /* same as default */
9717e36c
MB
4948 }
4949
cd4eb164
CY
4950 /* font slant */
4951 val = attrs[LFACE_SLANT_INDEX];
4952 if (!UNSPECIFIEDP (val)
4953 && (slant = FONT_SLANT_NAME_NUMERIC (val), slant >= 0))
4954 {
4955 int def_slant = FONT_SLANT_NAME_NUMERIC (def_attrs[LFACE_SLANT_INDEX]);
4956 if (slant == 100 || slant == def_slant)
4957 return 0; /* same as default */
4958 else
4959 test_caps |= TTY_CAP_ITALIC;
4960 }
4961
9717e36c
MB
4962 /* underlining */
4963 val = attrs[LFACE_UNDERLINE_INDEX];
8e330b22 4964 if (!UNSPECIFIEDP (val))
9717e36c
MB
4965 {
4966 if (STRINGP (val))
8e330b22
MB
4967 return 0; /* ttys can't use colored underlines */
4968 else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
4969 return 0; /* same as default */
9717e36c
MB
4970 else
4971 test_caps |= TTY_CAP_UNDERLINE;
4972 }
4973
4974 /* inverse video */
4975 val = attrs[LFACE_INVERSE_INDEX];
8e330b22
MB
4976 if (!UNSPECIFIEDP (val))
4977 {
a13ab63f 4978 if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
8e330b22
MB
4979 return 0; /* same as default */
4980 else
4981 test_caps |= TTY_CAP_INVERSE;
4982 }
9717e36c
MB
4983
4984
4985 /* Color testing. */
4986
4987 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
4988 we use them when calling `tty_capable_p' below, even if the face
4989 specifies no colors. */
4990 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
4991 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
4992
4993 /* Check if foreground color is close enough. */
4994 fg = attrs[LFACE_FOREGROUND_INDEX];
4995 if (STRINGP (fg))
4996 {
8e330b22
MB
4997 Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
4998
4999 if (face_attr_equal_p (fg, def_fg))
5000 return 0; /* same as default */
5001 else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
5002 return 0; /* not a valid color */
9717e36c
MB
5003 else if (color_distance (&fg_tty_color, &fg_std_color)
5004 > TTY_SAME_COLOR_THRESHOLD)
8e330b22
MB
5005 return 0; /* displayed color is too different */
5006 else
5007 /* Make sure the color is really different than the default. */
5008 {
5009 XColor def_fg_color;
5010 if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
5011 && (color_distance (&fg_tty_color, &def_fg_color)
5012 <= TTY_SAME_COLOR_THRESHOLD))
5013 return 0;
5014 }
9717e36c
MB
5015 }
5016
5017 /* Check if background color is close enough. */
5018 bg = attrs[LFACE_BACKGROUND_INDEX];
5019 if (STRINGP (bg))
5020 {
a13ab63f 5021 Lisp_Object def_bg = def_attrs[LFACE_BACKGROUND_INDEX];
8e330b22
MB
5022
5023 if (face_attr_equal_p (bg, def_bg))
5024 return 0; /* same as default */
5025 else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5026 return 0; /* not a valid color */
9717e36c
MB
5027 else if (color_distance (&bg_tty_color, &bg_std_color)
5028 > TTY_SAME_COLOR_THRESHOLD)
8e330b22
MB
5029 return 0; /* displayed color is too different */
5030 else
5031 /* Make sure the color is really different than the default. */
5032 {
5033 XColor def_bg_color;
5034 if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
5035 && (color_distance (&bg_tty_color, &def_bg_color)
5036 <= TTY_SAME_COLOR_THRESHOLD))
5037 return 0;
5038 }
9717e36c
MB
5039 }
5040
5041 /* If both foreground and background are requested, see if the
5042 distance between them is OK. We just check to see if the distance
5043 between the tty's foreground and background is close enough to the
5044 distance between the standard foreground and background. */
5045 if (STRINGP (fg) && STRINGP (bg))
5046 {
5047 int delta_delta
5048 = (color_distance (&fg_std_color, &bg_std_color)
5049 - color_distance (&fg_tty_color, &bg_tty_color));
5050 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5051 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5052 return 0;
5053 }
5054
5055
5056 /* See if the capabilities we selected above are supported, with the
5057 given colors. */
5058 if (test_caps != 0 &&
b5f03016
AS
5059 ! tty_capable_p (FRAME_TTY (f), test_caps, fg_tty_color.pixel,
5060 bg_tty_color.pixel))
9717e36c
MB
5061 return 0;
5062
5063
5064 /* Hmmm, everything checks out, this terminal must support this face. */
5065 return 1;
5066}
5067
5068
5069DEFUN ("display-supports-face-attributes-p",
5070 Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
5071 1, 2, 0,
5072 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
5073The optional argument DISPLAY can be a display name, a frame, or
9fed2905 5074nil (meaning the selected frame's display).
9717e36c
MB
5075
5076The definition of `supported' is somewhat heuristic, but basically means
5077that a face containing all the attributes in ATTRIBUTES, when merged
5078with the default face for display, can be represented in a way that's
5079
5080 \(1) different in appearance than the default face, and
5081 \(2) `close in spirit' to what the attributes specify, if not exact.
5082
5083Point (2) implies that a `:weight black' attribute will be satisfied by
5084any display that can display bold, and a `:foreground \"yellow\"' as long
5085as it can display a yellowish color, but `:slant italic' will _not_ be
5086satisfied by the tty display code's automatic substitution of a `dim'
9fed2905 5087face for italic. */)
5842a27b 5088 (Lisp_Object attributes, Lisp_Object display)
9717e36c 5089{
221439a0 5090 int supports = 0, i;
9717e36c
MB
5091 Lisp_Object frame;
5092 struct frame *f;
8e330b22 5093 struct face *def_face;
9717e36c
MB
5094 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5095
0722292b
MB
5096 if (noninteractive || !initialized)
5097 /* We may not be able to access low-level face information in batch
5098 mode, or before being dumped, and this function is not going to
5099 be very useful in those cases anyway, so just give up. */
5100 return Qnil;
5101
9717e36c
MB
5102 if (NILP (display))
5103 frame = selected_frame;
5104 else if (FRAMEP (display))
5105 frame = display;
5106 else
5107 {
5108 /* Find any frame on DISPLAY. */
5109 Lisp_Object fl_tail;
5110
5111 frame = Qnil;
5112 for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
5113 {
5114 frame = XCAR (fl_tail);
5115 if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
5116 XFRAME (frame)->param_alist)),
5117 display)))
5118 break;
5119 }
5120 }
5121
5122 CHECK_LIVE_FRAME (frame);
5123 f = XFRAME (frame);
5124
5125 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
5126 attrs[i] = Qunspecified;
a0a23346 5127 merge_face_ref (f, attributes, attrs, 1, 0);
9717e36c 5128
8e330b22
MB
5129 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5130 if (def_face == NULL)
5131 {
5132 if (! realize_basic_faces (f))
734e9514 5133 error ("Cannot realize default face");
8e330b22 5134 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
418ca4d2
RS
5135 if (def_face == NULL)
5136 abort (); /* realize_basic_faces must have set it up */
8e330b22
MB
5137 }
5138
9717e36c
MB
5139 /* Dispatch to the appropriate handler. */
5140 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
8e330b22 5141 supports = tty_supports_face_attributes_p (f, attrs, def_face);
ccda4e3c 5142#ifdef HAVE_WINDOW_SYSTEM
9717e36c 5143 else
8e330b22
MB
5144 supports = x_supports_face_attributes_p (f, attrs, def_face);
5145#endif
9717e36c
MB
5146
5147 return supports ? Qt : Qnil;
5148}
5149
5150\f
82641697
GM
5151/***********************************************************************
5152 Font selection
5153 ***********************************************************************/
5154
2c7d1565 5155DEFUN ("internal-set-font-selection-order",
82641697
GM
5156 Finternal_set_font_selection_order,
5157 Sinternal_set_font_selection_order, 1, 1, 0,
7ee72033 5158 doc: /* Set font selection order for face font selection to ORDER.
228299fa
GM
5159ORDER must be a list of length 4 containing the symbols `:width',
5160`:height', `:weight', and `:slant'. Face attributes appearing
5161first in ORDER are matched first, e.g. if `:height' appears before
5162`:weight' in ORDER, font selection first tries to find a font with
5163a suitable height, and then tries to match the font weight.
7ee72033 5164Value is ORDER. */)
5842a27b 5165 (Lisp_Object order)
82641697
GM
5166{
5167 Lisp_Object list;
5168 int i;
a08332c0 5169 int indices[DIM (font_sort_order)];
178c5d9c 5170
b7826503 5171 CHECK_LIST (order);
72af86bd 5172 memset (indices, 0, sizeof indices);
82641697
GM
5173 i = 0;
5174
5175 for (list = order;
5176 CONSP (list) && i < DIM (indices);
5177 list = XCDR (list), ++i)
5178 {
5179 Lisp_Object attr = XCAR (list);
5180 int xlfd;
5181
5182 if (EQ (attr, QCwidth))
5183 xlfd = XLFD_SWIDTH;
5184 else if (EQ (attr, QCheight))
5185 xlfd = XLFD_POINT_SIZE;
5186 else if (EQ (attr, QCweight))
5187 xlfd = XLFD_WEIGHT;
5188 else if (EQ (attr, QCslant))
5189 xlfd = XLFD_SLANT;
5190 else
5191 break;
5192
5193 if (indices[i] != 0)
5194 break;
5195 indices[i] = xlfd;
5196 }
5197
a08332c0 5198 if (!NILP (list) || i != DIM (indices))
82641697 5199 signal_error ("Invalid font sort order", order);
a08332c0
GM
5200 for (i = 0; i < DIM (font_sort_order); ++i)
5201 if (indices[i] == 0)
5202 signal_error ("Invalid font sort order", order);
82641697 5203
72af86bd 5204 if (memcmp (indices, font_sort_order, sizeof indices) != 0)
82641697 5205 {
72af86bd 5206 memcpy (font_sort_order, indices, sizeof font_sort_order);
82641697
GM
5207 free_all_realized_faces (Qnil);
5208 }
178c5d9c 5209
2dee4c0b 5210 font_update_sort_order (font_sort_order);
426b2119 5211
82641697
GM
5212 return Qnil;
5213}
5214
5215
5216DEFUN ("internal-set-alternative-font-family-alist",
5217 Finternal_set_alternative_font_family_alist,
5218 Sinternal_set_alternative_font_family_alist, 1, 1, 0,
c71f3632 5219 doc: /* Define alternative font families to try in face font selection.
228299fa
GM
5220ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
5221Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
7ee72033 5222be found. Value is ALIST. */)
5842a27b 5223 (Lisp_Object alist)
82641697 5224{
a77d5bb2 5225 Lisp_Object entry, tail, tail2;
53aaf1e2 5226
b7826503 5227 CHECK_LIST (alist);
53aaf1e2
KH
5228 alist = Fcopy_sequence (alist);
5229 for (tail = alist; CONSP (tail); tail = XCDR (tail))
a77d5bb2
CY
5230 {
5231 entry = XCAR (tail);
5232 CHECK_LIST (entry);
5233 entry = Fcopy_sequence (entry);
5234 XSETCAR (tail, entry);
5235 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5236 XSETCAR (tail2, Fintern (XCAR (tail2), Qnil));
5237 }
5238
82641697
GM
5239 Vface_alternative_font_family_alist = alist;
5240 free_all_realized_faces (Qnil);
5241 return alist;
5242}
5243
5244
32fcc231
GM
5245DEFUN ("internal-set-alternative-font-registry-alist",
5246 Finternal_set_alternative_font_registry_alist,
5247 Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
e3cd9e7f 5248 doc: /* Define alternative font registries to try in face font selection.
228299fa
GM
5249ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
5250Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
7ee72033 5251be found. Value is ALIST. */)
5842a27b 5252 (Lisp_Object alist)
32fcc231 5253{
a77d5bb2 5254 Lisp_Object entry, tail, tail2;
53aaf1e2 5255
b7826503 5256 CHECK_LIST (alist);
53aaf1e2
KH
5257 alist = Fcopy_sequence (alist);
5258 for (tail = alist; CONSP (tail); tail = XCDR (tail))
a77d5bb2
CY
5259 {
5260 entry = XCAR (tail);
5261 CHECK_LIST (entry);
5262 entry = Fcopy_sequence (entry);
5263 XSETCAR (tail, entry);
5264 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5265 XSETCAR (tail2, Fdowncase (XCAR (tail2)));
5266 }
32fcc231
GM
5267 Vface_alternative_font_registry_alist = alist;
5268 free_all_realized_faces (Qnil);
5269 return alist;
5270}
5271
5272
c3cee013 5273#ifdef HAVE_WINDOW_SYSTEM
82641697 5274
39506348
KH
5275/* Return the fontset id of the base fontset name or alias name given
5276 by the fontset attribute of ATTRS. Value is -1 if the fontset
5277 attribute of ATTRS doesn't name a fontset. */
82641697
GM
5278
5279static int
971de7fb 5280face_fontset (Lisp_Object *attrs)
82641697 5281{
39506348 5282 Lisp_Object name;
178c5d9c 5283
763bc839 5284 name = attrs[LFACE_FONTSET_INDEX];
39506348
KH
5285 if (!STRINGP (name))
5286 return -1;
5287 return fs_query_fontset (name, 0);
82641697
GM
5288}
5289
c3cee013 5290#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5291
5292
5293\f
5294/***********************************************************************
5295 Face Realization
5296 ***********************************************************************/
5297
5298/* Realize basic faces on frame F. Value is zero if frame parameters
5299 of F don't contain enough information needed to realize the default
5300 face. */
5301
5302static int
971de7fb 5303realize_basic_faces (struct frame *f)
82641697
GM
5304{
5305 int success_p = 0;
d311d28c 5306 ptrdiff_t count = SPECPDL_INDEX ();
17e8204b 5307
04386463
GM
5308 /* Block input here so that we won't be surprised by an X expose
5309 event, for instance, without having the faces set up. */
17e8204b 5310 BLOCK_INPUT;
eeffb293 5311 specbind (Qscalable_fonts_allowed, Qt);
178c5d9c 5312
82641697
GM
5313 if (realize_default_face (f))
5314 {
92610620 5315 realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
039b6394 5316 realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
9ea173e8 5317 realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
4e50fa8b 5318 realize_named_face (f, Qfringe, FRINGE_FACE_ID);
045dee35 5319 realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
8bd201d6
GM
5320 realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
5321 realize_named_face (f, Qborder, BORDER_FACE_ID);
5322 realize_named_face (f, Qcursor, CURSOR_FACE_ID);
5323 realize_named_face (f, Qmouse, MOUSE_FACE_ID);
c7ae3284 5324 realize_named_face (f, Qmenu, MENU_FACE_ID);
53abc3bf 5325 realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
563f68f1 5326
b5de343d 5327 /* Reflect changes in the `menu' face in menu bars. */
ceeda019 5328 if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
563f68f1 5329 {
ceeda019 5330 FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
563f68f1 5331#ifdef USE_X_TOOLKIT
b5f03016
AS
5332 if (FRAME_WINDOW_P (f))
5333 x_update_menu_appearance (f);
a03ad468 5334#endif
563f68f1 5335 }
177c0ea7 5336
82641697
GM
5337 success_p = 1;
5338 }
5339
eeffb293 5340 unbind_to (count, Qnil);
17e8204b 5341 UNBLOCK_INPUT;
82641697
GM
5342 return success_p;
5343}
5344
5345
5346/* Realize the default face on frame F. If the face is not fully
5347 specified, make it fully-specified. Attributes of the default face
5348 that are not explicitly specified are taken from frame parameters. */
5349
5350static int
971de7fb 5351realize_default_face (struct frame *f)
82641697
GM
5352{
5353 struct face_cache *c = FRAME_FACE_CACHE (f);
5354 Lisp_Object lface;
5355 Lisp_Object attrs[LFACE_VECTOR_SIZE];
82641697 5356 struct face *face;
82641697
GM
5357
5358 /* If the `default' face is not yet known, create it. */
5359 lface = lface_from_face_name (f, Qdefault, 0);
5360 if (NILP (lface))
1682701f 5361 {
07446869
GM
5362 Lisp_Object frame;
5363 XSETFRAME (frame, f);
5364 lface = Finternal_make_lisp_face (Qdefault, frame);
1682701f 5365 }
07446869 5366
c3cee013
JR
5367#ifdef HAVE_WINDOW_SYSTEM
5368 if (FRAME_WINDOW_P (f))
82641697 5369 {
2dee4c0b
KH
5370 Lisp_Object font_object;
5371
5372 XSETFONT (font_object, FRAME_FONT (f));
5373 set_lface_from_font (f, lface, font_object, f->default_face_done_p);
5374 LFACE_FONTSET (lface) = fontset_name (FRAME_FONTSET (f));
a5f696ac 5375 f->default_face_done_p = 1;
82641697 5376 }
c3cee013 5377#endif /* HAVE_WINDOW_SYSTEM */
82641697 5378
44747bd0 5379 if (!FRAME_WINDOW_P (f))
82641697
GM
5380 {
5381 LFACE_FAMILY (lface) = build_string ("default");
53aaf1e2 5382 LFACE_FOUNDRY (lface) = LFACE_FAMILY (lface);
82641697
GM
5383 LFACE_SWIDTH (lface) = Qnormal;
5384 LFACE_HEIGHT (lface) = make_number (1);
c1e7532d
EZ
5385 if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
5386 LFACE_WEIGHT (lface) = Qnormal;
5387 if (UNSPECIFIEDP (LFACE_SLANT (lface)))
5388 LFACE_SLANT (lface) = Qnormal;
70d6ecc6
KH
5389 if (UNSPECIFIEDP (LFACE_FONTSET (lface)))
5390 LFACE_FONTSET (lface) = Qnil;
82641697 5391 }
178c5d9c 5392
82641697
GM
5393 if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
5394 LFACE_UNDERLINE (lface) = Qnil;
178c5d9c 5395
82641697
GM
5396 if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
5397 LFACE_OVERLINE (lface) = Qnil;
178c5d9c 5398
82641697
GM
5399 if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
5400 LFACE_STRIKE_THROUGH (lface) = Qnil;
178c5d9c 5401
82641697
GM
5402 if (UNSPECIFIEDP (LFACE_BOX (lface)))
5403 LFACE_BOX (lface) = Qnil;
178c5d9c 5404
82641697
GM
5405 if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
5406 LFACE_INVERSE (lface) = Qnil;
178c5d9c 5407
82641697
GM
5408 if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
5409 {
5410 /* This function is called so early that colors are not yet
5411 set in the frame parameter list. */
5412 Lisp_Object color = Fassq (Qforeground_color, f->param_alist);
178c5d9c 5413
82641697
GM
5414 if (CONSP (color) && STRINGP (XCDR (color)))
5415 LFACE_FOREGROUND (lface) = XCDR (color);
c3cee013 5416 else if (FRAME_WINDOW_P (f))
82641697 5417 return 0;
3224dac1 5418 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ef917393 5419 LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
f9d2fdc4 5420 else
82641697
GM
5421 abort ();
5422 }
178c5d9c 5423
82641697
GM
5424 if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
5425 {
5426 /* This function is called so early that colors are not yet
5427 set in the frame parameter list. */
5428 Lisp_Object color = Fassq (Qbackground_color, f->param_alist);
5429 if (CONSP (color) && STRINGP (XCDR (color)))
5430 LFACE_BACKGROUND (lface) = XCDR (color);
c3cee013 5431 else if (FRAME_WINDOW_P (f))
82641697 5432 return 0;
3224dac1 5433 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ef917393 5434 LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
f9d2fdc4 5435 else
82641697
GM
5436 abort ();
5437 }
178c5d9c 5438
82641697
GM
5439 if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
5440 LFACE_STIPPLE (lface) = Qnil;
5441
5442 /* Realize the face; it must be fully-specified now. */
a54e2c05 5443 eassert (lface_fully_specified_p (XVECTOR (lface)->contents));
82641697 5444 check_lface (lface);
72af86bd 5445 memcpy (attrs, XVECTOR (lface)->contents, sizeof attrs);
af53b43c 5446 face = realize_face (c, attrs, DEFAULT_FACE_ID);
4da9c136
KH
5447
5448#ifdef HAVE_WINDOW_SYSTEM
41a9b76e 5449#ifdef HAVE_X_WINDOWS
361c0d6e 5450 if (FRAME_X_P (f) && face->font != FRAME_FONT (f))
73158a39
CY
5451 {
5452 /* This can happen when making a frame on a display that does
b5f03016 5453 not support the default font. */
73158a39 5454 if (!face->font)
b5f03016 5455 return 0;
d5ab09cd 5456
73158a39 5457 /* Otherwise, the font specified for the frame was not
b5f03016
AS
5458 acceptable as a font for the default face (perhaps because
5459 auto-scaled fonts are rejected), so we must adjust the frame
5460 font. */
2dee4c0b 5461 x_set_font (f, LFACE_FONT (lface), Qnil);
73158a39 5462 }
4da9c136
KH
5463#endif /* HAVE_X_WINDOWS */
5464#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5465 return 1;
5466}
5467
5468
5469/* Realize basic faces other than the default face in face cache C.
5470 SYMBOL is the face name, ID is the face id the realized face must
5471 have. The default face must have been realized already. */
5472
5473static void
971de7fb 5474realize_named_face (struct frame *f, Lisp_Object symbol, int id)
82641697 5475{
e7d7fd8c 5476 struct face_cache *c = FRAME_FACE_CACHE (f);
82641697
GM
5477 Lisp_Object lface = lface_from_face_name (f, symbol, 0);
5478 Lisp_Object attrs[LFACE_VECTOR_SIZE];
e7d7fd8c 5479 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
82641697
GM
5480
5481 /* The default face must exist and be fully specified. */
f2cec7a9 5482 get_lface_attributes_no_remap (f, Qdefault, attrs, 1);
82641697 5483 check_lface_attrs (attrs);
a54e2c05 5484 eassert (lface_fully_specified_p (attrs));
82641697 5485
e7d7fd8c 5486 /* If SYMBOL isn't know as a face, create it. */
82641697
GM
5487 if (NILP (lface))
5488 {
5489 Lisp_Object frame;
5490 XSETFRAME (frame, f);
5491 lface = Finternal_make_lisp_face (symbol, frame);
5492 }
5493
5494 /* Merge SYMBOL's face with the default face. */
f2cec7a9 5495 get_lface_attributes_no_remap (f, symbol, symbol_attrs, 1);
e7d7fd8c
MB
5496 merge_face_vectors (f, symbol_attrs, attrs, 0);
5497
5498 /* Realize the face. */
a5a62657 5499 realize_face (c, attrs, id);
82641697
GM
5500}
5501
5502
5503/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
5504 cache CACHE for ASCII characters. If FORMER_FACE_ID is
5505 non-negative, it is an ID of face to remove before caching the new
5506 face. Value is a pointer to the newly created realized face. */
82641697
GM
5507
5508static struct face *
971de7fb 5509realize_face (struct face_cache *cache, Lisp_Object *attrs, int former_face_id)
82641697
GM
5510{
5511 struct face *face;
178c5d9c 5512
82641697 5513 /* LFACE must be fully specified. */
a54e2c05 5514 eassert (cache != NULL);
82641697
GM
5515 check_lface_attrs (attrs);
5516
39506348
KH
5517 if (former_face_id >= 0 && cache->used > former_face_id)
5518 {
5519 /* Remove the former face. */
5520 struct face *former_face = cache->faces_by_id[former_face_id];
5521 uncache_face (cache, former_face);
5522 free_realized_face (cache->f, former_face);
7c33a057 5523 SET_FRAME_GARBAGED (cache->f);
39506348
KH
5524 }
5525
5526 if (FRAME_WINDOW_P (cache->f))
af53b43c 5527 face = realize_x_face (cache, attrs);
e689ec06 5528 else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
af53b43c 5529 face = realize_tty_face (cache, attrs);
d448e982
KL
5530 else if (FRAME_INITIAL_P (cache->f))
5531 {
5532 /* Create a dummy face. */
5533 face = make_realized_face (attrs);
5534 }
82641697
GM
5535 else
5536 abort ();
5537
39506348
KH
5538 /* Insert the new face. */
5539 cache_face (cache, face, lface_hash (attrs));
af53b43c
KH
5540 return face;
5541}
5542
5543
8c6204de 5544#ifdef HAVE_WINDOW_SYSTEM
2dee4c0b
KH
5545/* Realize the fully-specified face that uses FONT-OBJECT and has the
5546 same attributes as BASE_FACE except for the font on frame F.
5547 FONT-OBJECT may be nil, in which case, realized a face of
5548 no-font. */
af53b43c
KH
5549
5550static struct face *
b5f03016
AS
5551realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
5552 struct face *base_face)
af53b43c
KH
5553{
5554 struct face_cache *cache = FRAME_FACE_CACHE (f);
8f924df7 5555 struct face *face;
af53b43c 5556
23f86fce 5557 face = xmalloc (sizeof *face);
af53b43c
KH
5558 *face = *base_face;
5559 face->gc = 0;
bdd10de6 5560 face->extra = NULL;
2dee4c0b
KH
5561 face->overstrike
5562 = (! NILP (font_object)
5563 && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100
5564 && FONT_WEIGHT_NUMERIC (font_object) <= 100);
af53b43c
KH
5565
5566 /* Don't try to free the colors copied bitwise from BASE_FACE. */
5567 face->colors_copied_bitwise_p = 1;
2dee4c0b 5568 face->font = NILP (font_object) ? NULL : XFONT_OBJECT (font_object);
af53b43c
KH
5569 face->gc = 0;
5570
5571 cache_face (cache, face, face->hash);
5572
82641697
GM
5573 return face;
5574}
8c6204de 5575#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5576
5577
5578/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
5579 cache CACHE for ASCII characters. Do it for X frame CACHE->f. If
5580 the new face doesn't share font with the default face, a fontname
5581 is allocated from the heap and set in `font_name' of the new face,
5582 but it is not yet loaded here. Value is a pointer to the newly
5583 created realized face. */
82641697
GM
5584
5585static struct face *
971de7fb 5586realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
82641697 5587{
7d603e3f 5588 struct face *face = NULL;
c3cee013 5589#ifdef HAVE_WINDOW_SYSTEM
7d603e3f 5590 struct face *default_face;
78d2079c 5591 struct frame *f;
9b0e3eba 5592 Lisp_Object stipple, underline, overline, strike_through, box;
82641697 5593
a54e2c05 5594 eassert (FRAME_WINDOW_P (cache->f));
82641697
GM
5595
5596 /* Allocate a new realized face. */
39506348 5597 face = make_realized_face (attrs);
af53b43c 5598 face->ascii_face = face;
39506348
KH
5599
5600 f = cache->f;
5601
82641697
GM
5602 /* Determine the font to use. Most of the time, the font will be
5603 the same as the font of the default face, so try that first. */
5604 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5605 if (default_face
82641697
GM
5606 && lface_same_font_attributes_p (default_face->lface, attrs))
5607 {
5608 face->font = default_face->font;
76f54ecc
KH
5609 face->fontset
5610 = make_fontset_for_ascii_face (f, default_face->fontset, face);
82641697
GM
5611 }
5612 else
5613 {
39506348 5614 /* If the face attribute ATTRS specifies a fontset, use it as
fc8c4797
KH
5615 the base of a new realized fontset. Otherwise, use the same
5616 base fontset as of the default face. The base determines
5617 registry and encoding of a font. It may also determine
5618 foundry and family. The other fields of font name pattern
5619 are constructed from ATTRS. */
5620 int fontset = face_fontset (attrs);
5621
af53b43c
KH
5622 /* If we are realizing the default face, ATTRS should specify a
5623 fontset. In other words, if FONTSET is -1, we are not
5624 realizing the default face, thus the default face should have
5625 already been realized. */
5626 if (fontset == -1)
d78494f9
CY
5627 {
5628 if (default_face)
5629 fontset = default_face->fontset;
5630 if (fontset == -1)
5631 abort ();
5632 }
2dee4c0b
KH
5633 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
5634 attrs[LFACE_FONT_INDEX]
5635 = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]);
5636 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
5637 {
5638 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
5639 face->fontset = make_fontset_for_ascii_face (f, fontset, face);
5640 }
426b2119 5641 else
2dee4c0b
KH
5642 {
5643 face->font = NULL;
5644 face->fontset = -1;
5645 }
82641697
GM
5646 }
5647
2dee4c0b
KH
5648 if (face->font
5649 && FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]) > 100
5650 && FONT_WEIGHT_NUMERIC (attrs[LFACE_FONT_INDEX]) <= 100)
5651 face->overstrike = 1;
5652
82641697 5653 /* Load colors, and set remaining attributes. */
178c5d9c 5654
82641697 5655 load_face_colors (f, face, attrs);
660ed669 5656
82641697
GM
5657 /* Set up box. */
5658 box = attrs[LFACE_BOX_INDEX];
5659 if (STRINGP (box))
cb637678 5660 {
82641697
GM
5661 /* A simple box of line width 1 drawn in color given by
5662 the string. */
5663 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
5664 LFACE_BOX_INDEX);
5665 face->box = FACE_SIMPLE_BOX;
5666 face->box_line_width = 1;
cb637678 5667 }
82641697 5668 else if (INTEGERP (box))
42120bc7 5669 {
82641697 5670 /* Simple box of specified line width in foreground color of the
b5f03016 5671 face. */
a54e2c05 5672 eassert (XINT (box) != 0);
82641697 5673 face->box = FACE_SIMPLE_BOX;
89624b8b 5674 face->box_line_width = XINT (box);
82641697
GM
5675 face->box_color = face->foreground;
5676 face->box_color_defaulted_p = 1;
5677 }
5678 else if (CONSP (box))
5679 {
5680 /* `(:width WIDTH :color COLOR :shadow SHADOW)'. SHADOW
5681 being one of `raised' or `sunken'. */
5682 face->box = FACE_SIMPLE_BOX;
5683 face->box_color = face->foreground;
5684 face->box_color_defaulted_p = 1;
5685 face->box_line_width = 1;
5686
5687 while (CONSP (box))
42120bc7 5688 {
82641697
GM
5689 Lisp_Object keyword, value;
5690
5691 keyword = XCAR (box);
5692 box = XCDR (box);
5693
5694 if (!CONSP (box))
5695 break;
5696 value = XCAR (box);
5697 box = XCDR (box);
5698
5699 if (EQ (keyword, QCline_width))
5700 {
89624b8b
KH
5701 if (INTEGERP (value) && XINT (value) != 0)
5702 face->box_line_width = XINT (value);
82641697
GM
5703 }
5704 else if (EQ (keyword, QCcolor))
5705 {
5706 if (STRINGP (value))
5707 {
5708 face->box_color = load_color (f, face, value,
5709 LFACE_BOX_INDEX);
5710 face->use_box_color_for_shadows_p = 1;
5711 }
5712 }
5713 else if (EQ (keyword, QCstyle))
a8517066 5714 {
82641697
GM
5715 if (EQ (value, Qreleased_button))
5716 face->box = FACE_RAISED_BOX;
5717 else if (EQ (value, Qpressed_button))
5718 face->box = FACE_SUNKEN_BOX;
a8517066 5719 }
42120bc7
RS
5720 }
5721 }
195f798e 5722
82641697 5723 /* Text underline, overline, strike-through. */
178c5d9c 5724
9b0e3eba
AA
5725 underline = attrs[LFACE_UNDERLINE_INDEX];
5726 if (EQ (underline, Qt))
178c5d9c 5727 {
82641697
GM
5728 /* Use default color (same as foreground color). */
5729 face->underline_p = 1;
9b0e3eba 5730 face->underline_type = FACE_UNDER_LINE;
82641697
GM
5731 face->underline_defaulted_p = 1;
5732 face->underline_color = 0;
5733 }
9b0e3eba 5734 else if (STRINGP (underline))
195f798e 5735 {
82641697
GM
5736 /* Use specified color. */
5737 face->underline_p = 1;
9b0e3eba 5738 face->underline_type = FACE_UNDER_LINE;
82641697
GM
5739 face->underline_defaulted_p = 0;
5740 face->underline_color
9b0e3eba 5741 = load_color (f, face, underline,
82641697 5742 LFACE_UNDERLINE_INDEX);
195f798e 5743 }
9b0e3eba 5744 else if (NILP (underline))
7b00de84 5745 {
82641697
GM
5746 face->underline_p = 0;
5747 face->underline_defaulted_p = 0;
5748 face->underline_color = 0;
7b00de84 5749 }
9b0e3eba
AA
5750 else if (CONSP (underline))
5751 {
38182d90 5752 /* `(:color COLOR :style STYLE)'.
9b0e3eba
AA
5753 STYLE being one of `line' or `wave'. */
5754 face->underline_p = 1;
5755 face->underline_color = 0;
5756 face->underline_defaulted_p = 1;
5757 face->underline_type = FACE_UNDER_LINE;
5758
5759 while (CONSP (underline))
5760 {
5761 Lisp_Object keyword, value;
5762
5763 keyword = XCAR (underline);
5764 underline = XCDR (underline);
5765
5766 if (!CONSP (underline))
5767 break;
5768 value = XCAR (underline);
5769 underline = XCDR (underline);
5770
5771 if (EQ (keyword, QCcolor))
5772 {
5773 if (EQ (value, Qforeground_color))
5774 {
5775 face->underline_defaulted_p = 1;
5776 face->underline_color = 0;
5777 }
5778 else if (STRINGP (value))
5779 {
5780 face->underline_defaulted_p = 0;
5781 face->underline_color = load_color (f, face, value,
5782 LFACE_UNDERLINE_INDEX);
5783 }
5784 }
5785 else if (EQ (keyword, QCstyle))
5786 {
5787 if (EQ (value, Qline))
5788 face->underline_type = FACE_UNDER_LINE;
5789 else if (EQ (value, Qwave))
5790 face->underline_type = FACE_UNDER_WAVE;
5791 }
5792 }
5793 }
38182d90 5794
82641697
GM
5795 overline = attrs[LFACE_OVERLINE_INDEX];
5796 if (STRINGP (overline))
cb637678 5797 {
82641697
GM
5798 face->overline_color
5799 = load_color (f, face, attrs[LFACE_OVERLINE_INDEX],
5800 LFACE_OVERLINE_INDEX);
5801 face->overline_p = 1;
cb637678 5802 }
82641697 5803 else if (EQ (overline, Qt))
cb637678 5804 {
82641697
GM
5805 face->overline_color = face->foreground;
5806 face->overline_color_defaulted_p = 1;
5807 face->overline_p = 1;
cb637678
JB
5808 }
5809
82641697
GM
5810 strike_through = attrs[LFACE_STRIKE_THROUGH_INDEX];
5811 if (STRINGP (strike_through))
5812 {
5813 face->strike_through_color
5814 = load_color (f, face, attrs[LFACE_STRIKE_THROUGH_INDEX],
5815 LFACE_STRIKE_THROUGH_INDEX);
5816 face->strike_through_p = 1;
5817 }
5818 else if (EQ (strike_through, Qt))
5819 {
5820 face->strike_through_color = face->foreground;
5821 face->strike_through_color_defaulted_p = 1;
5822 face->strike_through_p = 1;
5823 }
867dd159 5824
82641697
GM
5825 stipple = attrs[LFACE_STIPPLE_INDEX];
5826 if (!NILP (stipple))
5827 face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
c3cee013 5828#endif /* HAVE_WINDOW_SYSTEM */
660ed669 5829
82641697 5830 return face;
660ed669
JB
5831}
5832
729425b1 5833
ae4b4ba5
GM
5834/* Map a specified color of face FACE on frame F to a tty color index.
5835 IDX is either LFACE_FOREGROUND_INDEX or LFACE_BACKGROUND_INDEX, and
5836 specifies which color to map. Set *DEFAULTED to 1 if mapping to the
5837 default foreground/background colors. */
5838
5839static void
b5f03016
AS
5840map_tty_color (struct frame *f, struct face *face,
5841 enum lface_attribute_index idx, int *defaulted)
ae4b4ba5
GM
5842{
5843 Lisp_Object frame, color, def;
5844 int foreground_p = idx == LFACE_FOREGROUND_INDEX;
a5a62657
PE
5845 unsigned long default_pixel =
5846 foreground_p ? FACE_TTY_DEFAULT_FG_COLOR : FACE_TTY_DEFAULT_BG_COLOR;
5847 unsigned long pixel = default_pixel;
5848#ifdef MSDOS
5849 unsigned long default_other_pixel =
5850 foreground_p ? FACE_TTY_DEFAULT_BG_COLOR : FACE_TTY_DEFAULT_FG_COLOR;
5851#endif
ae4b4ba5 5852
a54e2c05 5853 eassert (idx == LFACE_FOREGROUND_INDEX || idx == LFACE_BACKGROUND_INDEX);
ae4b4ba5 5854
ae4b4ba5
GM
5855 XSETFRAME (frame, f);
5856 color = face->lface[idx];
177c0ea7 5857
ae4b4ba5 5858 if (STRINGP (color)
d5db4077 5859 && SCHARS (color)
ae4b4ba5
GM
5860 && CONSP (Vtty_defined_color_alist)
5861 && (def = assq_no_quit (color, call1 (Qtty_color_alist, frame)),
5862 CONSP (def)))
5863 {
5864 /* Associations in tty-defined-color-alist are of the form
5865 (NAME INDEX R G B). We need the INDEX part. */
5866 pixel = XINT (XCAR (XCDR (def)));
5867 }
5868
5869 if (pixel == default_pixel && STRINGP (color))
5870 {
5871 pixel = load_color (f, face, color, idx);
5872
8d05ec51 5873#ifdef MSDOS
ae4b4ba5
GM
5874 /* If the foreground of the default face is the default color,
5875 use the foreground color defined by the frame. */
ae4b4ba5
GM
5876 if (FRAME_MSDOS_P (f))
5877 {
ae4b4ba5
GM
5878 if (pixel == default_pixel
5879 || pixel == FACE_TTY_DEFAULT_COLOR)
5880 {
5881 if (foreground_p)
5882 pixel = FRAME_FOREGROUND_PIXEL (f);
5883 else
5884 pixel = FRAME_BACKGROUND_PIXEL (f);
5885 face->lface[idx] = tty_color_name (f, pixel);
5886 *defaulted = 1;
5887 }
5888 else if (pixel == default_other_pixel)
5889 {
5890 if (foreground_p)
5891 pixel = FRAME_BACKGROUND_PIXEL (f);
5892 else
5893 pixel = FRAME_FOREGROUND_PIXEL (f);
5894 face->lface[idx] = tty_color_name (f, pixel);
5895 *defaulted = 1;
5896 }
b5f03016 5897 }
8d05ec51 5898#endif /* MSDOS */
ae4b4ba5
GM
5899 }
5900
5901 if (foreground_p)
5902 face->foreground = pixel;
5903 else
5904 face->background = pixel;
5905}
5906
5907
82641697 5908/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
5909 cache CACHE for ASCII characters. Do it for TTY frame CACHE->f.
5910 Value is a pointer to the newly created realized face. */
a8517066 5911
82641697 5912static struct face *
971de7fb 5913realize_tty_face (struct face_cache *cache, Lisp_Object *attrs)
82641697
GM
5914{
5915 struct face *face;
5916 int weight, slant;
2d764c78 5917 int face_colors_defaulted = 0;
ae4b4ba5 5918 struct frame *f = cache->f;
729425b1 5919
82641697 5920 /* Frame must be a termcap frame. */
a54e2c05 5921 eassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
178c5d9c 5922
82641697 5923 /* Allocate a new realized face. */
39506348 5924 face = make_realized_face (attrs);
2dee4c0b 5925#if 0
e689ec06 5926 face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
2dee4c0b 5927#endif
82641697 5928
cd4eb164 5929 /* Map face attributes to TTY appearances. */
2dee4c0b
KH
5930 weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
5931 slant = FONT_SLANT_NAME_NUMERIC (attrs[LFACE_SLANT_INDEX]);
5932 if (weight > 100)
82641697 5933 face->tty_bold_p = 1;
cd4eb164
CY
5934 if (slant != 100)
5935 face->tty_italic_p = 1;
82641697
GM
5936 if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
5937 face->tty_underline_p = 1;
5938 if (!NILP (attrs[LFACE_INVERSE_INDEX]))
5939 face->tty_reverse_p = 1;
5940
5941 /* Map color names to color indices. */
ae4b4ba5
GM
5942 map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
5943 map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
177c0ea7 5944
2d764c78
EZ
5945 /* Swap colors if face is inverse-video. If the colors are taken
5946 from the frame colors, they are already inverted, since the
5947 frame-creation function calls x-handle-reverse-video. */
5948 if (face->tty_reverse_p && !face_colors_defaulted)
44747bd0
EZ
5949 {
5950 unsigned long tem = face->foreground;
44747bd0
EZ
5951 face->foreground = face->background;
5952 face->background = tem;
5953 }
44747bd0 5954
a4a76b61
GM
5955 if (tty_suppress_bold_inverse_default_colors_p
5956 && face->tty_bold_p
5957 && face->background == FACE_TTY_DEFAULT_FG_COLOR
5958 && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
5959 face->tty_bold_p = 0;
5960
82641697 5961 return face;
729425b1 5962}
867dd159 5963
82641697 5964
a4a76b61
GM
5965DEFUN ("tty-suppress-bold-inverse-default-colors",
5966 Ftty_suppress_bold_inverse_default_colors,
5967 Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
e3cd9e7f 5968 doc: /* Suppress/allow boldness of faces with inverse default colors.
228299fa
GM
5969SUPPRESS non-nil means suppress it.
5970This affects bold faces on TTYs whose foreground is the default background
5971color of the display and whose background is the default foreground color.
5972For such faces, the bold face attribute is ignored if this variable
7ee72033 5973is non-nil. */)
5842a27b 5974 (Lisp_Object suppress)
a4a76b61
GM
5975{
5976 tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
5977 ++face_change_count;
5978 return suppress;
5979}
5980
5981
82641697
GM
5982\f
5983/***********************************************************************
5984 Computing Faces
5985 ***********************************************************************/
5986
5987/* Return the ID of the face to use to display character CH with face
5988 property PROP on frame F in current_buffer. */
2e16580f
RS
5989
5990int
971de7fb 5991compute_char_face (struct frame *f, int ch, Lisp_Object prop)
2e16580f 5992{
82641697 5993 int face_id;
39506348 5994
4b4deea2 5995 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
522d42f7 5996 ch = 0;
178c5d9c 5997
82641697 5998 if (NILP (prop))
39506348
KH
5999 {
6000 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
779c6fb6 6001 face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
39506348 6002 }
82641697 6003 else
2e16580f 6004 {
82641697
GM
6005 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6006 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
72af86bd 6007 memcpy (attrs, default_face->lface, sizeof attrs);
a0a23346 6008 merge_face_ref (f, prop, attrs, 1, 0);
af53b43c 6009 face_id = lookup_face (f, attrs);
2e16580f
RS
6010 }
6011
82641697 6012 return face_id;
2e16580f 6013}
bc0db68d 6014
82641697
GM
6015/* Return the face ID associated with buffer position POS for
6016 displaying ASCII characters. Return in *ENDPTR the position at
6017 which a different face is needed, as far as text properties and
6018 overlays are concerned. W is a window displaying current_buffer.
6019
6020 REGION_BEG, REGION_END delimit the region, so it can be
6021 highlighted.
6f134486 6022
82641697
GM
6023 LIMIT is a position not to scan beyond. That is to limit the time
6024 this function can take.
6025
6026 If MOUSE is non-zero, use the character's mouse-face, not its face.
6027
6970f632
CY
6028 BASE_FACE_ID, if non-negative, specifies a base face id to use
6029 instead of DEFAULT_FACE_ID.
6030
39506348 6031 The face returned is suitable for displaying ASCII characters. */
bc0db68d 6032
cb637678 6033int
d311d28c
PE
6034face_at_buffer_position (struct window *w, ptrdiff_t pos,
6035 ptrdiff_t region_beg, ptrdiff_t region_end,
6036 ptrdiff_t *endptr, ptrdiff_t limit,
d5a3eaaf 6037 int mouse, int base_face_id)
7b7739b1 6038{
82641697
GM
6039 struct frame *f = XFRAME (w->frame);
6040 Lisp_Object attrs[LFACE_VECTOR_SIZE];
b6d40e46 6041 Lisp_Object prop, position;
b081724f 6042 ptrdiff_t i, noverlays;
7b7739b1 6043 Lisp_Object *overlay_vec;
f211082d 6044 Lisp_Object frame;
d311d28c 6045 ptrdiff_t endpos;
82641697
GM
6046 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6047 Lisp_Object limit1, end;
6048 struct face *default_face;
f6b98e0b
JB
6049
6050 /* W must display the current buffer. We could write this function
6051 to use the frame and buffer of W, but right now it doesn't. */
a54e2c05 6052 /* eassert (XBUFFER (w->buffer) == current_buffer); */
f211082d 6053
ac22a6c4 6054 XSETFRAME (frame, f);
82641697 6055 XSETFASTINT (position, pos);
7b7739b1 6056
f6b98e0b 6057 endpos = ZV;
bc0db68d
RS
6058 if (pos < region_beg && region_beg < endpos)
6059 endpos = region_beg;
f6b98e0b 6060
82641697
GM
6061 /* Get the `face' or `mouse_face' text property at POS, and
6062 determine the next position at which the property changes. */
6f134486 6063 prop = Fget_text_property (position, propname, w->buffer);
82641697
GM
6064 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6065 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
6066 if (INTEGERP (end))
6067 endpos = XINT (end);
6f134486 6068
82641697 6069 /* Look at properties from overlays. */
b6d40e46 6070 {
d311d28c 6071 ptrdiff_t next_overlay;
b6d40e46 6072
0bc90bba 6073 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, 0);
f6b98e0b
JB
6074 if (next_overlay < endpos)
6075 endpos = next_overlay;
b6d40e46
JB
6076 }
6077
6078 *endptr = endpos;
7b7739b1 6079
823564e5
EZ
6080 {
6081 int face_id;
6082
6083 if (base_face_id >= 0)
6084 face_id = base_face_id;
6085 else if (NILP (Vface_remapping_alist))
6086 face_id = DEFAULT_FACE_ID;
6087 else
6088 face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
6089
6090 default_face = FACE_FROM_ID (f, face_id);
6091 }
178c5d9c 6092
82641697
GM
6093 /* Optimize common cases where we can use the default face. */
6094 if (noverlays == 0
6095 && NILP (prop)
39506348 6096 && !(pos >= region_beg && pos < region_end))
f2cec7a9 6097 return default_face->id;
82641697
GM
6098
6099 /* Begin with attributes from the default face. */
72af86bd 6100 memcpy (attrs, default_face->lface, sizeof attrs);
82641697
GM
6101
6102 /* Merge in attributes specified via text properties. */
6103 if (!NILP (prop))
a0a23346 6104 merge_face_ref (f, prop, attrs, 1, 0);
82641697
GM
6105
6106 /* Now merge the overlay data. */
18195655 6107 noverlays = sort_overlays (overlay_vec, noverlays, w);
18195655 6108 for (i = 0; i < noverlays; i++)
4699e6d2 6109 {
18195655
RS
6110 Lisp_Object oend;
6111 int oendpos;
6112
6113 prop = Foverlay_get (overlay_vec[i], propname);
82641697 6114 if (!NILP (prop))
a0a23346 6115 merge_face_ref (f, prop, attrs, 1, 0);
18195655
RS
6116
6117 oend = OVERLAY_END (overlay_vec[i]);
6118 oendpos = OVERLAY_POSITION (oend);
6119 if (oendpos < endpos)
6120 endpos = oendpos;
6121 }
6122
82641697 6123 /* If in the region, merge in the region face. */
18195655
RS
6124 if (pos >= region_beg && pos < region_end)
6125 {
a0a23346 6126 merge_named_face (f, Qregion, attrs, 0);
178c5d9c 6127
18195655
RS
6128 if (region_end < endpos)
6129 endpos = region_end;
18195655
RS
6130 }
6131
6132 *endptr = endpos;
6133
82641697 6134 /* Look up a realized face with the given face attributes,
39506348 6135 or realize a new one for ASCII characters. */
af53b43c 6136 return lookup_face (f, attrs);
18195655
RS
6137}
6138
a193ecf1
RS
6139/* Return the face ID at buffer position POS for displaying ASCII
6140 characters associated with overlay strings for overlay OVERLAY.
6141
6142 Like face_at_buffer_position except for OVERLAY. Currently it
6143 simply disregards the `face' properties of all overlays. */
03e1d617
RS
6144
6145int
d311d28c
PE
6146face_for_overlay_string (struct window *w, ptrdiff_t pos,
6147 ptrdiff_t region_beg, ptrdiff_t region_end,
6148 ptrdiff_t *endptr, ptrdiff_t limit,
d5a3eaaf 6149 int mouse, Lisp_Object overlay)
03e1d617
RS
6150{
6151 struct frame *f = XFRAME (w->frame);
6152 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6153 Lisp_Object prop, position;
03e1d617
RS
6154 Lisp_Object frame;
6155 int endpos;
6156 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6157 Lisp_Object limit1, end;
6158 struct face *default_face;
6159
6160 /* W must display the current buffer. We could write this function
6161 to use the frame and buffer of W, but right now it doesn't. */
a54e2c05 6162 /* eassert (XBUFFER (w->buffer) == current_buffer); */
03e1d617
RS
6163
6164 XSETFRAME (frame, f);
6165 XSETFASTINT (position, pos);
6166
6167 endpos = ZV;
6168 if (pos < region_beg && region_beg < endpos)
6169 endpos = region_beg;
6170
6171 /* Get the `face' or `mouse_face' text property at POS, and
6172 determine the next position at which the property changes. */
6173 prop = Fget_text_property (position, propname, w->buffer);
6174 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6175 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
6176 if (INTEGERP (end))
6177 endpos = XINT (end);
6178
6179 *endptr = endpos;
6180
1682701f 6181 /* Optimize common case where we can use the default face. */
03e1d617 6182 if (NILP (prop)
1682701f
CY
6183 && !(pos >= region_beg && pos < region_end)
6184 && NILP (Vface_remapping_alist))
03e1d617
RS
6185 return DEFAULT_FACE_ID;
6186
6187 /* Begin with attributes from the default face. */
1682701f 6188 default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
72af86bd 6189 memcpy (attrs, default_face->lface, sizeof attrs);
03e1d617
RS
6190
6191 /* Merge in attributes specified via text properties. */
6192 if (!NILP (prop))
6193 merge_face_ref (f, prop, attrs, 1, 0);
6194
6195 /* If in the region, merge in the region face. */
6196 if (pos >= region_beg && pos < region_end)
6197 {
6198 merge_named_face (f, Qregion, attrs, 0);
6199
6200 if (region_end < endpos)
6201 endpos = region_end;
6202 }
6203
6204 *endptr = endpos;
6205
6206 /* Look up a realized face with the given face attributes,
6207 or realize a new one for ASCII characters. */
ce9c2e7b 6208 return lookup_face (f, attrs);
03e1d617
RS
6209}
6210
60573a90 6211
82641697 6212/* Compute the face at character position POS in Lisp string STRING on
39506348 6213 window W, for ASCII characters.
7b7739b1 6214
82641697
GM
6215 If STRING is an overlay string, it comes from position BUFPOS in
6216 current_buffer, otherwise BUFPOS is zero to indicate that STRING is
6217 not an overlay string. W must display the current buffer.
6218 REGION_BEG and REGION_END give the start and end positions of the
8714a182
GM
6219 region; both are -1 if no region is visible.
6220
6221 BASE_FACE_ID is the id of a face to merge with. For strings coming
6222 from overlays or the `display' property it is the face at BUFPOS.
178c5d9c 6223
48a4ca99
GM
6224 If MOUSE_P is non-zero, use the character's mouse-face, not its face.
6225
82641697
GM
6226 Set *ENDPTR to the next position where to check for faces in
6227 STRING; -1 if the face is constant from POS to the end of the
6228 string.
18195655 6229
82641697 6230 Value is the id of the face to use. The face returned is suitable
39506348 6231 for displaying ASCII characters. */
fffc2367 6232
82641697 6233int
d5a3eaaf 6234face_at_string_position (struct window *w, Lisp_Object string,
d311d28c
PE
6235 ptrdiff_t pos, ptrdiff_t bufpos,
6236 ptrdiff_t region_beg, ptrdiff_t region_end,
6237 ptrdiff_t *endptr, enum face_id base_face_id,
d5a3eaaf 6238 int mouse_p)
660ed669 6239{
82641697
GM
6240 Lisp_Object prop, position, end, limit;
6241 struct frame *f = XFRAME (WINDOW_FRAME (w));
6242 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6243 struct face *base_face;
6244 int multibyte_p = STRING_MULTIBYTE (string);
48a4ca99 6245 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
82641697
GM
6246
6247 /* Get the value of the face property at the current position within
6248 STRING. Value is nil if there is no face property. */
6249 XSETFASTINT (position, pos);
48a4ca99 6250 prop = Fget_text_property (position, prop_name, string);
82641697
GM
6251
6252 /* Get the next position at which to check for faces. Value of end
6253 is nil if face is constant all the way to the end of the string.
6254 Otherwise it is a string position where to check faces next.
6255 Limit is the maximum position up to which to check for property
6256 changes in Fnext_single_property_change. Strings are usually
6257 short, so set the limit to the end of the string. */
d5db4077 6258 XSETFASTINT (limit, SCHARS (string));
48a4ca99 6259 end = Fnext_single_property_change (position, prop_name, string, limit);
82641697
GM
6260 if (INTEGERP (end))
6261 *endptr = XFASTINT (end);
6262 else
6263 *endptr = -1;
6264
6265 base_face = FACE_FROM_ID (f, base_face_id);
a54e2c05 6266 eassert (base_face);
82641697
GM
6267
6268 /* Optimize the default case that there is no face property and we
6269 are not in the region. */
6270 if (NILP (prop)
6271 && (base_face_id != DEFAULT_FACE_ID
6272 /* BUFPOS <= 0 means STRING is not an overlay string, so
6273 that the region doesn't have to be taken into account. */
6274 || bufpos <= 0
6275 || bufpos < region_beg
6276 || bufpos >= region_end)
6277 && (multibyte_p
6278 /* We can't realize faces for different charsets differently
6279 if we don't have fonts, so we can stop here if not working
6280 on a window-system frame. */
6281 || !FRAME_WINDOW_P (f)
239f9db9 6282 || FACE_SUITABLE_FOR_ASCII_CHAR_P (base_face, 0)))
82641697
GM
6283 return base_face->id;
6284
6285 /* Begin with attributes from the base face. */
72af86bd 6286 memcpy (attrs, base_face->lface, sizeof attrs);
82641697
GM
6287
6288 /* Merge in attributes specified via text properties. */
6289 if (!NILP (prop))
a0a23346 6290 merge_face_ref (f, prop, attrs, 1, 0);
82641697
GM
6291
6292 /* If in the region, merge in the region face. */
6293 if (bufpos
6294 && bufpos >= region_beg
6295 && bufpos < region_end)
a0a23346 6296 merge_named_face (f, Qregion, attrs, 0);
660ed669 6297
82641697 6298 /* Look up a realized face with the given face attributes,
39506348 6299 or realize a new one for ASCII characters. */
af53b43c 6300 return lookup_face (f, attrs);
660ed669
JB
6301}
6302
6303
fd998c7f
KS
6304/* Merge a face into a realized face.
6305
6306 F is frame where faces are (to be) realized.
6307
dc91a0ed
KS
6308 FACE_NAME is named face to merge.
6309
6310 If FACE_NAME is nil, FACE_ID is face_id of realized face to merge.
6311
6312 If FACE_NAME is t, FACE_ID is lface_id of face to merge.
fd998c7f
KS
6313
6314 BASE_FACE_ID is realized face to merge into.
6315
dc91a0ed 6316 Return new face id.
fd998c7f
KS
6317*/
6318
6319int
d311d28c 6320merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
9910e595 6321 int base_face_id)
fd998c7f
KS
6322{
6323 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6324 struct face *base_face;
6325
6326 base_face = FACE_FROM_ID (f, base_face_id);
6327 if (!base_face)
6328 return base_face_id;
6329
dc91a0ed
KS
6330 if (EQ (face_name, Qt))
6331 {
6332 if (face_id < 0 || face_id >= lface_id_to_name_size)
6333 return base_face_id;
6334 face_name = lface_id_to_name[face_id];
d8453278
CY
6335 /* When called during make-frame, lookup_derived_face may fail
6336 if the faces are uninitialized. Don't signal an error. */
6337 face_id = lookup_derived_face (f, face_name, base_face_id, 0);
6338 return (face_id >= 0 ? face_id : base_face_id);
dc91a0ed
KS
6339 }
6340
fd998c7f 6341 /* Begin with attributes from the base face. */
72af86bd 6342 memcpy (attrs, base_face->lface, sizeof attrs);
fd998c7f
KS
6343
6344 if (!NILP (face_name))
6345 {
6346 if (!merge_named_face (f, face_name, attrs, 0))
6347 return base_face_id;
6348 }
6349 else
6350 {
6351 struct face *face;
dc91a0ed
KS
6352 if (face_id < 0)
6353 return base_face_id;
fd998c7f
KS
6354 face = FACE_FROM_ID (f, face_id);
6355 if (!face)
6356 return base_face_id;
6357 merge_face_vectors (f, face->lface, attrs, 0);
6358 }
6359
6360 /* Look up a realized face with the given face attributes,
6361 or realize a new one for ASCII characters. */
0e3ae538 6362 return lookup_face (f, attrs);
fd998c7f
KS
6363}
6364
c115973b 6365\f
7ded3383
AR
6366
6367#ifndef HAVE_X_WINDOWS
6368DEFUN ("x-load-color-file", Fx_load_color_file,
6369 Sx_load_color_file, 1, 1, 0,
6370 doc: /* Create an alist of color entries from an external file.
6371
6372The file should define one named RGB color per line like so:
6373 R G B name
6374where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
5842a27b 6375 (Lisp_Object filename)
7ded3383
AR
6376{
6377 FILE *fp;
6378 Lisp_Object cmap = Qnil;
6379 Lisp_Object abspath;
6380
6381 CHECK_STRING (filename);
6382 abspath = Fexpand_file_name (filename, Qnil);
6383
45763476 6384 fp = fopen (SDATA (abspath), "rt");
7ded3383
AR
6385 if (fp)
6386 {
6387 char buf[512];
6388 int red, green, blue;
6389 int num;
6390
6391 BLOCK_INPUT;
6392
6393 while (fgets (buf, sizeof (buf), fp) != NULL) {
6394 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
6395 {
6396 char *name = buf + num;
6397 num = strlen (name) - 1;
40aa3f13 6398 if (num >= 0 && name[num] == '\n')
7ded3383
AR
6399 name[num] = 0;
6400 cmap = Fcons (Fcons (build_string (name),
dee8cd43
JB
6401#ifdef WINDOWSNT
6402 make_number (RGB (red, green, blue))),
ebadbfa6 6403#else
dee8cd43 6404 make_number ((red << 16) | (green << 8) | blue)),
ebadbfa6 6405#endif
7ded3383
AR
6406 cmap);
6407 }
6408 }
6409 fclose (fp);
6410
6411 UNBLOCK_INPUT;
6412 }
6413
6414 return cmap;
6415}
6416#endif
6417
6418\f
82641697
GM
6419/***********************************************************************
6420 Tests
6421 ***********************************************************************/
c115973b 6422
e509cfa6 6423#ifdef GLYPH_DEBUG
c115973b 6424
82641697 6425/* Print the contents of the realized face FACE to stderr. */
c115973b 6426
82641697 6427static void
7d7d0045 6428dump_realized_face (struct face *face)
82641697
GM
6429{
6430 fprintf (stderr, "ID: %d\n", face->id);
6431#ifdef HAVE_X_WINDOWS
2defe37f 6432 fprintf (stderr, "gc: %ld\n", (long) face->gc);
82641697
GM
6433#endif
6434 fprintf (stderr, "foreground: 0x%lx (%s)\n",
6435 face->foreground,
d5db4077 6436 SDATA (face->lface[LFACE_FOREGROUND_INDEX]));
82641697
GM
6437 fprintf (stderr, "background: 0x%lx (%s)\n",
6438 face->background,
d5db4077 6439 SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
2dee4c0b
KH
6440 if (face->font)
6441 fprintf (stderr, "font_name: %s (%s)\n",
6442 SDATA (face->font->props[FONT_NAME_INDEX]),
6443 SDATA (face->lface[LFACE_FAMILY_INDEX]));
82641697
GM
6444#ifdef HAVE_X_WINDOWS
6445 fprintf (stderr, "font = %p\n", face->font);
6446#endif
82641697
GM
6447 fprintf (stderr, "fontset: %d\n", face->fontset);
6448 fprintf (stderr, "underline: %d (%s)\n",
6449 face->underline_p,
d5db4077 6450 SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
82641697 6451 fprintf (stderr, "hash: %d\n", face->hash);
c115973b
JB
6452}
6453
6454
a7ca3326 6455DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */)
5842a27b 6456 (Lisp_Object n)
c115973b 6457{
82641697 6458 if (NILP (n))
c115973b 6459 {
82641697 6460 int i;
178c5d9c 6461
82641697
GM
6462 fprintf (stderr, "font selection order: ");
6463 for (i = 0; i < DIM (font_sort_order); ++i)
6464 fprintf (stderr, "%d ", font_sort_order[i]);
6465 fprintf (stderr, "\n");
6466
6467 fprintf (stderr, "alternative fonts: ");
6468 debug_print (Vface_alternative_font_family_alist);
6469 fprintf (stderr, "\n");
178c5d9c 6470
c0617987 6471 for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
82641697 6472 Fdump_face (make_number (i));
c115973b
JB
6473 }
6474 else
f5e278c7 6475 {
82641697 6476 struct face *face;
b7826503 6477 CHECK_NUMBER (n);
c0617987 6478 face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
82641697
GM
6479 if (face == NULL)
6480 error ("Not a valid face");
6481 dump_realized_face (face);
f5e278c7 6482 }
178c5d9c 6483
c115973b
JB
6484 return Qnil;
6485}
b5c53576 6486
b5c53576 6487
a7ca3326 6488DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
7ee72033 6489 0, 0, 0, doc: /* */)
5842a27b 6490 (void)
b5c53576 6491{
82641697
GM
6492 fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
6493 fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
6494 fprintf (stderr, "number of GCs = %d\n", ngcs);
6495 return Qnil;
b5c53576
RS
6496}
6497
e509cfa6 6498#endif /* GLYPH_DEBUG */
82641697 6499
b5c53576 6500
c115973b 6501\f
82641697
GM
6502/***********************************************************************
6503 Initialization
6504 ***********************************************************************/
cb637678 6505
c115973b 6506void
971de7fb 6507syms_of_xfaces (void)
c115973b 6508{
cd3520a4
JB
6509 DEFSYM (Qface, "face");
6510 DEFSYM (Qface_no_inherit, "face-no-inherit");
6511 DEFSYM (Qbitmap_spec_p, "bitmap-spec-p");
6512 DEFSYM (Qframe_set_background_mode, "frame-set-background-mode");
178c5d9c 6513
82641697 6514 /* Lisp face attribute keywords. */
cd3520a4
JB
6515 DEFSYM (QCfamily, ":family");
6516 DEFSYM (QCheight, ":height");
6517 DEFSYM (QCweight, ":weight");
6518 DEFSYM (QCslant, ":slant");
6519 DEFSYM (QCunderline, ":underline");
6520 DEFSYM (QCinverse_video, ":inverse-video");
6521 DEFSYM (QCreverse_video, ":reverse-video");
6522 DEFSYM (QCforeground, ":foreground");
6523 DEFSYM (QCbackground, ":background");
6524 DEFSYM (QCstipple, ":stipple");
6525 DEFSYM (QCwidth, ":width");
6526 DEFSYM (QCfont, ":font");
6527 DEFSYM (QCfontset, ":fontset");
6528 DEFSYM (QCbold, ":bold");
6529 DEFSYM (QCitalic, ":italic");
6530 DEFSYM (QCoverline, ":overline");
6531 DEFSYM (QCstrike_through, ":strike-through");
6532 DEFSYM (QCbox, ":box");
6533 DEFSYM (QCinherit, ":inherit");
82641697
GM
6534
6535 /* Symbols used for Lisp face attribute values. */
cd3520a4
JB
6536 DEFSYM (QCcolor, ":color");
6537 DEFSYM (QCline_width, ":line-width");
6538 DEFSYM (QCstyle, ":style");
9b0e3eba
AA
6539 DEFSYM (Qline, "line");
6540 DEFSYM (Qwave, "wave");
cd3520a4
JB
6541 DEFSYM (Qreleased_button, "released-button");
6542 DEFSYM (Qpressed_button, "pressed-button");
6543 DEFSYM (Qnormal, "normal");
6544 DEFSYM (Qultra_light, "ultra-light");
6545 DEFSYM (Qextra_light, "extra-light");
6546 DEFSYM (Qlight, "light");
6547 DEFSYM (Qsemi_light, "semi-light");
6548 DEFSYM (Qsemi_bold, "semi-bold");
6549 DEFSYM (Qbold, "bold");
6550 DEFSYM (Qextra_bold, "extra-bold");
6551 DEFSYM (Qultra_bold, "ultra-bold");
6552 DEFSYM (Qoblique, "oblique");
6553 DEFSYM (Qitalic, "italic");
6554 DEFSYM (Qreverse_oblique, "reverse-oblique");
6555 DEFSYM (Qreverse_italic, "reverse-italic");
6556 DEFSYM (Qultra_condensed, "ultra-condensed");
6557 DEFSYM (Qextra_condensed, "extra-condensed");
6558 DEFSYM (Qcondensed, "condensed");
6559 DEFSYM (Qsemi_condensed, "semi-condensed");
6560 DEFSYM (Qsemi_expanded, "semi-expanded");
6561 DEFSYM (Qexpanded, "expanded");
6562 DEFSYM (Qextra_expanded, "extra-expanded");
6563 DEFSYM (Qultra_expanded, "ultra-expanded");
6564 DEFSYM (Qbackground_color, "background-color");
6565 DEFSYM (Qforeground_color, "foreground-color");
6566 DEFSYM (Qunspecified, "unspecified");
a3720aa2 6567 DEFSYM (QCignore_defface, ":ignore-defface");
cd3520a4
JB
6568
6569 DEFSYM (Qface_alias, "face-alias");
6570 DEFSYM (Qdefault, "default");
6571 DEFSYM (Qtool_bar, "tool-bar");
6572 DEFSYM (Qregion, "region");
6573 DEFSYM (Qfringe, "fringe");
6574 DEFSYM (Qheader_line, "header-line");
6575 DEFSYM (Qscroll_bar, "scroll-bar");
6576 DEFSYM (Qmenu, "menu");
6577 DEFSYM (Qcursor, "cursor");
6578 DEFSYM (Qborder, "border");
6579 DEFSYM (Qmouse, "mouse");
6580 DEFSYM (Qmode_line_inactive, "mode-line-inactive");
6581 DEFSYM (Qvertical_border, "vertical-border");
6582 DEFSYM (Qtty_color_desc, "tty-color-desc");
6583 DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
6584 DEFSYM (Qtty_color_by_index, "tty-color-by-index");
6585 DEFSYM (Qtty_color_alist, "tty-color-alist");
6586 DEFSYM (Qscalable_fonts_allowed, "scalable-fonts-allowed");
82641697 6587
dbc968b8
GM
6588 Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
6589 staticpro (&Vparam_value_alist);
434b9cc5
GM
6590 Vface_alternative_font_family_alist = Qnil;
6591 staticpro (&Vface_alternative_font_family_alist);
32fcc231
GM
6592 Vface_alternative_font_registry_alist = Qnil;
6593 staticpro (&Vface_alternative_font_registry_alist);
434b9cc5 6594
82641697
GM
6595 defsubr (&Sinternal_make_lisp_face);
6596 defsubr (&Sinternal_lisp_face_p);
6597 defsubr (&Sinternal_set_lisp_face_attribute);
c3cee013 6598#ifdef HAVE_WINDOW_SYSTEM
82641697 6599 defsubr (&Sinternal_set_lisp_face_attribute_from_resource);
42608ba8 6600#endif
ea4fa0af
GM
6601 defsubr (&Scolor_gray_p);
6602 defsubr (&Scolor_supported_p);
7ded3383
AR
6603#ifndef HAVE_X_WINDOWS
6604 defsubr (&Sx_load_color_file);
6605#endif
cdfaafa9
MB
6606 defsubr (&Sface_attribute_relative_p);
6607 defsubr (&Smerge_face_attribute);
82641697
GM
6608 defsubr (&Sinternal_get_lisp_face_attribute);
6609 defsubr (&Sinternal_lisp_face_attribute_values);
6610 defsubr (&Sinternal_lisp_face_equal_p);
6611 defsubr (&Sinternal_lisp_face_empty_p);
6612 defsubr (&Sinternal_copy_lisp_face);
6613 defsubr (&Sinternal_merge_in_global_face);
6614 defsubr (&Sface_font);
6615 defsubr (&Sframe_face_alist);
9717e36c 6616 defsubr (&Sdisplay_supports_face_attributes_p);
b35df831 6617 defsubr (&Scolor_distance);
82641697
GM
6618 defsubr (&Sinternal_set_font_selection_order);
6619 defsubr (&Sinternal_set_alternative_font_family_alist);
32fcc231 6620 defsubr (&Sinternal_set_alternative_font_registry_alist);
f6608d5c 6621 defsubr (&Sface_attributes_as_vector);
e509cfa6 6622#ifdef GLYPH_DEBUG
82641697
GM
6623 defsubr (&Sdump_face);
6624 defsubr (&Sshow_face_resources);
6625#endif /* GLYPH_DEBUG */
6626 defsubr (&Sclear_face_cache);
a4a76b61 6627 defsubr (&Stty_suppress_bold_inverse_default_colors);
82641697 6628
38426dee 6629#if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
08dc08dc
GM
6630 defsubr (&Sdump_colors);
6631#endif
6632
29208e82 6633 DEFVAR_LISP ("font-list-limit", Vfont_list_limit,
fb7ada5f 6634 doc: /* Limit for font matching.
228299fa
GM
6635If an integer > 0, font matching functions won't load more than
6636that number of fonts when searching for a matching font. */);
057df17c
GM
6637 Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
6638
29208e82 6639 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults,
7ee72033 6640 doc: /* List of global face definitions (for internal use only.) */);
82641697 6641 Vface_new_frame_defaults = Qnil;
178c5d9c 6642
29208e82 6643 DEFVAR_LISP ("face-default-stipple", Vface_default_stipple,
fb7ada5f 6644 doc: /* Default stipple pattern used on monochrome displays.
228299fa
GM
6645This stipple pattern is used on monochrome displays
6646instead of shades of gray for a face background color.
6647See `set-face-stipple' for possible values for this variable. */);
a4ada374 6648 Vface_default_stipple = make_pure_c_string ("gray3");
82641697 6649
29208e82 6650 DEFVAR_LISP ("tty-defined-color-alist", Vtty_defined_color_alist,
46710489
GM
6651 doc: /* An alist of defined terminal colors and their RGB values.
6652See the docstring of `tty-color-alist' for the details. */);
ae4b4ba5
GM
6653 Vtty_defined_color_alist = Qnil;
6654
29208e82 6655 DEFVAR_LISP ("scalable-fonts-allowed", Vscalable_fonts_allowed,
7ee72033 6656 doc: /* Allowed scalable fonts.
228299fa
GM
6657A value of nil means don't allow any scalable fonts.
6658A value of t means allow any scalable font.
6659Otherwise, value must be a list of regular expressions. A font may be
6660scaled if its name matches a regular expression in the list.
6661Note that if value is nil, a scalable font might still be used, if no
6662other font of the appropriate family and registry is available. */);
3cf80731 6663 Vscalable_fonts_allowed = Qnil;
b5c53576 6664
29208e82 6665 DEFVAR_LISP ("face-ignored-fonts", Vface_ignored_fonts,
7ee72033 6666 doc: /* List of ignored fonts.
228299fa
GM
6667Each element is a regular expression that matches names of fonts to
6668ignore. */);
c824bfbc
KH
6669 Vface_ignored_fonts = Qnil;
6670
29208e82 6671 DEFVAR_LISP ("face-remapping-alist", Vface_remapping_alist,
f2cec7a9
MB
6672 doc: /* Alist of face remappings.
6673Each element is of the form:
6674
fb5b8aca 6675 (FACE . REPLACEMENT),
f2cec7a9 6676
fb5b8aca
CY
6677which causes display of the face FACE to use REPLACEMENT instead.
6678REPLACEMENT is a face specification, i.e. one of the following:
f2cec7a9 6679
fb5b8aca
CY
6680 (1) a face name
6681 (2) a property list of attribute/value pairs, or
6682 (3) a list in which each element has the form of (1) or (2).
f2cec7a9 6683
fb5b8aca
CY
6684List values for REPLACEMENT are merged to form the final face
6685specification, with earlier entries taking precedence, in the same as
6686as in the `face' text property.
6687
6688Face-name remapping cycles are suppressed; recursive references use
6689the underlying face instead of the remapped face. So a remapping of
6690the form:
f2cec7a9
MB
6691
6692 (FACE EXTRA-FACE... FACE)
6693
6694or:
6695
6696 (FACE (FACE-ATTR VAL ...) FACE)
6697
fb5b8aca
CY
6698causes EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
6699existing definition of FACE. Note that this isn't necessary for the
6700default face, since every face inherits from the default face.
f2cec7a9 6701
fb5b8aca
CY
6702If this variable is made buffer-local, the face remapping takes effect
6703only in that buffer. For instance, the mode my-mode could define a
6704face `my-mode-default', and then in the mode setup function, do:
f2cec7a9
MB
6705
6706 (set (make-local-variable 'face-remapping-alist)
b5f03016 6707 '((default my-mode-default)))).
635c0aa1
CY
6708
6709Because Emacs normally only redraws screen areas when the underlying
6710buffer contents change, you may need to call `redraw-display' after
6711changing this variable for it to take effect. */);
f2cec7a9
MB
6712 Vface_remapping_alist = Qnil;
6713
29208e82 6714 DEFVAR_LISP ("face-font-rescale-alist", Vface_font_rescale_alist,
f70400f2 6715 doc: /* Alist of fonts vs the rescaling factors.
96f9306b
KH
6716Each element is a cons (FONT-PATTERN . RESCALE-RATIO), where
6717FONT-PATTERN is a font-spec or a regular expression matching a font name, and
f70400f2
KH
6718RESCALE-RATIO is a floating point number to specify how much larger
6719\(or smaller) font we should use. For instance, if a face requests
6720a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point. */);
6721 Vface_font_rescale_alist = Qnil;
6722
c3cee013 6723#ifdef HAVE_WINDOW_SYSTEM
fef04523 6724 defsubr (&Sbitmap_spec_p);
82641697
GM
6725 defsubr (&Sx_list_fonts);
6726 defsubr (&Sinternal_face_x_get_resource);
92610620 6727 defsubr (&Sx_family_fonts);
32247e3d 6728#endif
c115973b 6729}