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