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