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