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