Add 2012 to FSF copyright years for Emacs files
[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
925 HEIGHT must be integers > 0, and DATA must be string large
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
PE
944 if (STRINGP (data)
945 && INTEGERP (width) && 0 < XINT (width)
946 && INTEGERP (height) && 0 < XINT (height))
c7ae3284 947 {
c8907a93
PE
948 EMACS_INT bytes_per_row = ((XINT (width) + BITS_PER_CHAR - 1)
949 / BITS_PER_CHAR);
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))
1607 result = INTEGERP (val2) ? XINT (val1) - XINT (val2) : -1;
1608 else
1609 result = INTEGERP (val2) ? 1 : 0;
1610 }
1611 if (result)
1612 return result;
1613 }
1614 return 0;
82641697
GM
1615}
1616
2dee4c0b
KH
1617DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
1618 doc: /* Return a list of available fonts of family FAMILY on FRAME.
1619If FAMILY is omitted or nil, list all families.
1620Otherwise, FAMILY must be a string, possibly containing wildcards
1621`?' and `*'.
1622If FRAME is omitted or nil, use the selected frame.
1623Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
1624SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
1625FAMILY is the font family name. POINT-SIZE is the size of the
1626font in 1/10 pt. WIDTH, WEIGHT, and SLANT are symbols describing the
1627width, weight and slant of the font. These symbols are the same as for
1628face attributes. FIXED-P is non-nil if the font is fixed-pitch.
1629FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
1630giving the registry and encoding of the font.
1631The result list is sorted according to the current setting of
1632the face font sort order. */)
5842a27b 1633 (Lisp_Object family, Lisp_Object frame)
2dee4c0b 1634{
022eef62
CY
1635 Lisp_Object font_spec, list, *drivers, vec;
1636 int i, nfonts, ndrivers;
2dee4c0b 1637 Lisp_Object result;
82641697 1638
62057df6
KH
1639 if (NILP (frame))
1640 frame = selected_frame;
1641 CHECK_LIVE_FRAME (frame);
1642
1643 font_spec = Ffont_spec (0, NULL);
2dee4c0b
KH
1644 if (!NILP (family))
1645 {
1646 CHECK_STRING (family);
6b1f69f1 1647 font_parse_family_registry (family, Qnil, font_spec);
2dee4c0b 1648 }
022eef62
CY
1649
1650 list = font_list_entities (frame, font_spec);
1651 if (NILP (list))
2dee4c0b 1652 return Qnil;
022eef62
CY
1653
1654 /* Sort the font entities. */
1655 for (i = 0; i < 4; i++)
1656 switch (font_sort_order[i])
1657 {
1658 case XLFD_SWIDTH:
1659 font_props_for_sorting[i] = FONT_WIDTH_INDEX; break;
1660 case XLFD_POINT_SIZE:
1661 font_props_for_sorting[i] = FONT_SIZE_INDEX; break;
1662 case XLFD_WEIGHT:
1663 font_props_for_sorting[i] = FONT_WEIGHT_INDEX; break;
1664 default:
1665 font_props_for_sorting[i] = FONT_SLANT_INDEX; break;
1666 }
1667 font_props_for_sorting[i++] = FONT_FAMILY_INDEX;
1668 font_props_for_sorting[i++] = FONT_FOUNDRY_INDEX;
1669 font_props_for_sorting[i++] = FONT_ADSTYLE_INDEX;
1670 font_props_for_sorting[i++] = FONT_REGISTRY_INDEX;
1671
1672 ndrivers = XINT (Flength (list));
1673 drivers = alloca (sizeof (Lisp_Object) * ndrivers);
1674 for (i = 0; i < ndrivers; i++, list = XCDR (list))
1675 drivers[i] = XCAR (list);
1676 vec = Fvconcat (ndrivers, drivers);
1677 nfonts = ASIZE (vec);
1678
1679 qsort (XVECTOR (vec)->contents, nfonts, sizeof (Lisp_Object),
1680 compare_fonts_by_sort_order);
82641697 1681
2dee4c0b
KH
1682 result = Qnil;
1683 for (i = nfonts - 1; i >= 0; --i)
1684 {
1685 Lisp_Object font = AREF (vec, i);
1686 Lisp_Object v = Fmake_vector (make_number (8), Qnil);
1687 int point;
1688 Lisp_Object spacing;
1689
1690 ASET (v, 0, AREF (font, FONT_FAMILY_INDEX));
1691 ASET (v, 1, FONT_WIDTH_SYMBOLIC (font));
1692 point = PIXEL_TO_POINT (XINT (AREF (font, FONT_SIZE_INDEX)) * 10,
62057df6 1693 XFRAME (frame)->resy);
2dee4c0b
KH
1694 ASET (v, 2, make_number (point));
1695 ASET (v, 3, FONT_WEIGHT_SYMBOLIC (font));
1696 ASET (v, 4, FONT_SLANT_SYMBOLIC (font));
1697 spacing = Ffont_get (font, QCspacing);
1698 ASET (v, 5, (NILP (spacing) || EQ (spacing, Qp)) ? Qnil : Qt);
62057df6 1699 ASET (v, 6, Ffont_xlfd_name (font, Qnil));
2dee4c0b 1700 ASET (v, 7, AREF (font, FONT_REGISTRY_INDEX));
82641697 1701
2dee4c0b
KH
1702 result = Fcons (v, result);
1703 }
82641697 1704
2dee4c0b 1705 return result;
82641697
GM
1706}
1707
2dee4c0b
KH
1708DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
1709 doc: /* Return a list of the names of available fonts matching PATTERN.
1710If optional arguments FACE and FRAME are specified, return only fonts
1711the same size as FACE on FRAME.
21bdb81a
CY
1712
1713PATTERN should be a string containing a font name in the XLFD,
1714Fontconfig, or GTK format. A font name given in the XLFD format may
1715contain wildcard characters:
2dee4c0b
KH
1716 the * character matches any substring, and
1717 the ? character matches any single character.
1718 PATTERN is case-insensitive.
2dee4c0b
KH
1719
1720The return value is a list of strings, suitable as arguments to
d5ab09cd 1721`set-face-font'.
82641697 1722
2dee4c0b
KH
1723Fonts Emacs can't use may or may not be excluded
1724even if they match PATTERN and FACE.
1725The optional fourth argument MAXIMUM sets a limit on how many
1726fonts to match. The first MAXIMUM fonts are reported.
1727The optional fifth argument WIDTH, if specified, is a number of columns
1728occupied by a character of a font. In that case, return only fonts
1729the WIDTH times as wide as FACE on FRAME. */)
b5f03016
AS
1730 (Lisp_Object pattern, Lisp_Object face, Lisp_Object frame,
1731 Lisp_Object maximum, Lisp_Object width)
82641697 1732{
2dee4c0b 1733 struct frame *f;
1e9966ea 1734 int size, avgwidth IF_LINT (= 0);
82641697 1735
2dee4c0b
KH
1736 check_x ();
1737 CHECK_STRING (pattern);
82641697 1738
2dee4c0b
KH
1739 if (! NILP (maximum))
1740 CHECK_NATNUM (maximum);
82641697 1741
2dee4c0b
KH
1742 if (!NILP (width))
1743 CHECK_NUMBER (width);
82641697 1744
2dee4c0b
KH
1745 /* We can't simply call check_x_frame because this function may be
1746 called before any frame is created. */
1747 if (NILP (frame))
1748 frame = selected_frame;
1749 f = frame_or_selected_frame (frame, 2);
1750 if (! FRAME_WINDOW_P (f))
1751 {
1752 /* Perhaps we have not yet created any frame. */
1753 f = NULL;
1754 frame = Qnil;
1755 face = Qnil;
1756 }
82641697 1757
2dee4c0b 1758 /* Determine the width standard for comparison with the fonts we find. */
82641697 1759
2dee4c0b
KH
1760 if (NILP (face))
1761 size = 0;
1762 else
1763 {
1764 /* This is of limited utility since it works with character
1765 widths. Keep it for compatibility. --gerd. */
1766 int face_id = lookup_named_face (f, face, 0);
071048a3
PE
1767 struct face *width_face = (face_id < 0
1768 ? NULL
1769 : FACE_FROM_ID (f, face_id));
82641697 1770
071048a3 1771 if (width_face && width_face->font)
2dee4c0b 1772 {
071048a3
PE
1773 size = width_face->font->pixel_size;
1774 avgwidth = width_face->font->average_width;
2dee4c0b
KH
1775 }
1776 else
1777 {
1778 size = FRAME_FONT (f)->pixel_size;
1779 avgwidth = FRAME_FONT (f)->average_width;
1780 }
1781 if (!NILP (width))
1782 avgwidth *= XINT (width);
1783 }
82641697 1784
2dee4c0b
KH
1785 {
1786 Lisp_Object font_spec;
a4eec626 1787 Lisp_Object args[2], tail;
82641697 1788
2dee4c0b 1789 font_spec = font_spec_from_name (pattern);
21bdb81a
CY
1790 if (!FONTP (font_spec))
1791 signal_error ("Invalid font name", pattern);
1792
2dee4c0b
KH
1793 if (size)
1794 {
1795 Ffont_put (font_spec, QCsize, make_number (size));
1796 Ffont_put (font_spec, QCavgwidth, make_number (avgwidth));
1797 }
34e97272 1798 args[0] = Flist_fonts (font_spec, frame, maximum, font_spec);
a4eec626 1799 for (tail = args[0]; CONSP (tail); tail = XCDR (tail))
493dcf2c
KH
1800 {
1801 Lisp_Object font_entity;
1802
1803 font_entity = XCAR (tail);
1804 if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
1805 || XINT (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
1806 && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
1807 {
1808 /* This is a scalable font. For backward compatibility,
1809 we set the specified size. */
92470028 1810 font_entity = copy_font_spec (font_entity);
493dcf2c
KH
1811 ASET (font_entity, FONT_SIZE_INDEX,
1812 AREF (font_spec, FONT_SIZE_INDEX));
1813 }
1814 XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
1815 }
2dee4c0b
KH
1816 if (NILP (frame))
1817 /* We don't have to check fontsets. */
1818 return args[0];
1819 args[1] = list_fontsets (f, pattern, size);
1820 return Fnconc (2, args);
1821 }
82641697 1822}
178c5d9c 1823
2dee4c0b 1824#endif /* HAVE_WINDOW_SYSTEM */
82641697 1825
82641697
GM
1826\f
1827/***********************************************************************
1828 Lisp Faces
1829 ***********************************************************************/
1830
a08332c0
GM
1831/* Access face attributes of face LFACE, a Lisp vector. */
1832
1833#define LFACE_FAMILY(LFACE) AREF ((LFACE), LFACE_FAMILY_INDEX)
53aaf1e2 1834#define LFACE_FOUNDRY(LFACE) AREF ((LFACE), LFACE_FOUNDRY_INDEX)
a08332c0
GM
1835#define LFACE_HEIGHT(LFACE) AREF ((LFACE), LFACE_HEIGHT_INDEX)
1836#define LFACE_WEIGHT(LFACE) AREF ((LFACE), LFACE_WEIGHT_INDEX)
1837#define LFACE_SLANT(LFACE) AREF ((LFACE), LFACE_SLANT_INDEX)
1838#define LFACE_UNDERLINE(LFACE) AREF ((LFACE), LFACE_UNDERLINE_INDEX)
1839#define LFACE_INVERSE(LFACE) AREF ((LFACE), LFACE_INVERSE_INDEX)
1840#define LFACE_FOREGROUND(LFACE) AREF ((LFACE), LFACE_FOREGROUND_INDEX)
1841#define LFACE_BACKGROUND(LFACE) AREF ((LFACE), LFACE_BACKGROUND_INDEX)
1842#define LFACE_STIPPLE(LFACE) AREF ((LFACE), LFACE_STIPPLE_INDEX)
1843#define LFACE_SWIDTH(LFACE) AREF ((LFACE), LFACE_SWIDTH_INDEX)
1844#define LFACE_OVERLINE(LFACE) AREF ((LFACE), LFACE_OVERLINE_INDEX)
1845#define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
1846#define LFACE_BOX(LFACE) AREF ((LFACE), LFACE_BOX_INDEX)
1847#define LFACE_FONT(LFACE) AREF ((LFACE), LFACE_FONT_INDEX)
1848#define LFACE_INHERIT(LFACE) AREF ((LFACE), LFACE_INHERIT_INDEX)
763bc839 1849#define LFACE_FONTSET(LFACE) AREF ((LFACE), LFACE_FONTSET_INDEX)
82641697 1850
73719eba 1851#if XASSERTS
82641697
GM
1852/* Non-zero if LFACE is a Lisp face. A Lisp face is a vector of size
1853 LFACE_VECTOR_SIZE which has the symbol `face' in slot 0. */
1854
1855#define LFACEP(LFACE) \
1856 (VECTORP (LFACE) \
77b37c05 1857 && ASIZE (LFACE) == LFACE_VECTOR_SIZE \
a08332c0 1858 && EQ (AREF (LFACE, 0), Qface))
73719eba 1859#endif
82641697 1860
178c5d9c 1861
82641697
GM
1862#if GLYPH_DEBUG
1863
1864/* Check consistency of Lisp face attribute vector ATTRS. */
1865
1866static void
7d7d0045 1867check_lface_attrs (Lisp_Object *attrs)
82641697
GM
1868{
1869 xassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
2ff10663 1870 || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
82641697 1871 || STRINGP (attrs[LFACE_FAMILY_INDEX]));
53aaf1e2
KH
1872 xassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
1873 || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX])
1874 || STRINGP (attrs[LFACE_FOUNDRY_INDEX]));
82641697 1875 xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
2ff10663 1876 || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
82641697
GM
1877 || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
1878 xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
2ff10663 1879 || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
2c20458f
MB
1880 || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
1881 || FLOATP (attrs[LFACE_HEIGHT_INDEX])
1882 || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
82641697 1883 xassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
2ff10663 1884 || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX])
82641697
GM
1885 || SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
1886 xassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
2ff10663 1887 || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX])
82641697
GM
1888 || SYMBOLP (attrs[LFACE_SLANT_INDEX]));
1889 xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
2ff10663 1890 || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
82641697
GM
1891 || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
1892 || STRINGP (attrs[LFACE_UNDERLINE_INDEX]));
1893 xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
2ff10663 1894 || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
82641697
GM
1895 || SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
1896 || STRINGP (attrs[LFACE_OVERLINE_INDEX]));
1897 xassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
2ff10663 1898 || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
82641697
GM
1899 || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX])
1900 || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX]));
1901 xassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
2ff10663 1902 || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX])
82641697
GM
1903 || SYMBOLP (attrs[LFACE_BOX_INDEX])
1904 || STRINGP (attrs[LFACE_BOX_INDEX])
1905 || INTEGERP (attrs[LFACE_BOX_INDEX])
1906 || CONSP (attrs[LFACE_BOX_INDEX]));
1907 xassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
2ff10663 1908 || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX])
82641697
GM
1909 || SYMBOLP (attrs[LFACE_INVERSE_INDEX]));
1910 xassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
2ff10663 1911 || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX])
82641697
GM
1912 || STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
1913 xassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
2ff10663 1914 || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX])
82641697 1915 || STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
2c20458f 1916 xassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
2ff10663 1917 || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX])
2c20458f
MB
1918 || NILP (attrs[LFACE_INHERIT_INDEX])
1919 || SYMBOLP (attrs[LFACE_INHERIT_INDEX])
1920 || CONSP (attrs[LFACE_INHERIT_INDEX]));
82641697
GM
1921#ifdef HAVE_WINDOW_SYSTEM
1922 xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
2ff10663 1923 || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX])
82641697 1924 || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
fef04523 1925 || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
39506348 1926 xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
2ff10663 1927 || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
2dee4c0b 1928 || FONTP (attrs[LFACE_FONT_INDEX]));
763bc839 1929 xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
f25e39b4
EZ
1930 || STRINGP (attrs[LFACE_FONTSET_INDEX])
1931 || NILP (attrs[LFACE_FONTSET_INDEX]));
82641697
GM
1932#endif
1933}
1934
1935
1936/* Check consistency of attributes of Lisp face LFACE (a Lisp vector). */
1937
1938static void
7d7d0045 1939check_lface (Lisp_Object lface)
82641697
GM
1940{
1941 if (!NILP (lface))
1942 {
1943 xassert (LFACEP (lface));
1944 check_lface_attrs (XVECTOR (lface)->contents);
1945 }
1946}
1947
1948#else /* GLYPH_DEBUG == 0 */
1949
1950#define check_lface_attrs(attrs) (void) 0
1951#define check_lface(lface) (void) 0
1952
1953#endif /* GLYPH_DEBUG == 0 */
1954
1955
a0a23346
MB
1956\f
1957/* Face-merge cycle checking. */
1958
f2cec7a9
MB
1959enum named_merge_point_kind
1960{
1961 NAMED_MERGE_POINT_NORMAL,
1962 NAMED_MERGE_POINT_REMAP
1963};
1964
a0a23346
MB
1965/* A `named merge point' is simply a point during face-merging where we
1966 look up a face by name. We keep a stack of which named lookups we're
1967 currently processing so that we can easily detect cycles, using a
1968 linked- list of struct named_merge_point structures, typically
1969 allocated on the stack frame of the named lookup functions which are
1970 active (so no consing is required). */
1971struct named_merge_point
1972{
1973 Lisp_Object face_name;
f2cec7a9 1974 enum named_merge_point_kind named_merge_point_kind;
a0a23346
MB
1975 struct named_merge_point *prev;
1976};
1977
1978
1979/* If a face merging cycle is detected for FACE_NAME, return 0,
1980 otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
f2cec7a9
MB
1981 FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
1982 pointed to by NAMED_MERGE_POINTS, and return 1. */
a0a23346 1983
55d4c1b2 1984static inline int
a0a23346
MB
1985push_named_merge_point (struct named_merge_point *new_named_merge_point,
1986 Lisp_Object face_name,
f2cec7a9 1987 enum named_merge_point_kind named_merge_point_kind,
a0a23346
MB
1988 struct named_merge_point **named_merge_points)
1989{
1990 struct named_merge_point *prev;
1991
1992 for (prev = *named_merge_points; prev; prev = prev->prev)
1993 if (EQ (face_name, prev->face_name))
f2cec7a9
MB
1994 {
1995 if (prev->named_merge_point_kind == named_merge_point_kind)
1996 /* A cycle, so fail. */
1997 return 0;
1998 else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
1999 /* A remap `hides ' any previous normal merge points
2000 (because the remap means that it's actually different face),
2001 so as we know the current merge point must be normal, we
2002 can just assume it's OK. */
2003 break;
2004 }
a0a23346
MB
2005
2006 new_named_merge_point->face_name = face_name;
f2cec7a9 2007 new_named_merge_point->named_merge_point_kind = named_merge_point_kind;
a0a23346
MB
2008 new_named_merge_point->prev = *named_merge_points;
2009
2010 *named_merge_points = new_named_merge_point;
2011
2012 return 1;
2013}
2014
2015\f
39506348 2016/* Resolve face name FACE_NAME. If FACE_NAME is a string, intern it
d1bf13b3
KS
2017 to make it a symbol. If FACE_NAME is an alias for another face,
2018 return that face's name.
2019
2020 Return default face in case of errors. */
c7ae3284
GM
2021
2022static Lisp_Object
971de7fb 2023resolve_face_name (Lisp_Object face_name, int signal_p)
c7ae3284 2024{
d1bf13b3
KS
2025 Lisp_Object orig_face;
2026 Lisp_Object tortoise, hare;
178c5d9c 2027
c7ae3284 2028 if (STRINGP (face_name))
42a5b22f 2029 face_name = intern (SSDATA (face_name));
c7ae3284 2030
d1bf13b3
KS
2031 if (NILP (face_name) || !SYMBOLP (face_name))
2032 return face_name;
2033
2034 orig_face = face_name;
2035 tortoise = hare = face_name;
2036
2037 while (1)
c7ae3284 2038 {
d1bf13b3
KS
2039 face_name = hare;
2040 hare = Fget (hare, Qface_alias);
2041 if (NILP (hare) || !SYMBOLP (hare))
c7ae3284 2042 break;
d1bf13b3
KS
2043
2044 face_name = hare;
2045 hare = Fget (hare, Qface_alias);
2046 if (NILP (hare) || !SYMBOLP (hare))
f3745204 2047 break;
d1bf13b3
KS
2048
2049 tortoise = Fget (tortoise, Qface_alias);
2050 if (EQ (hare, tortoise))
2051 {
2052 if (signal_p)
8009eb44 2053 xsignal1 (Qcircular_list, orig_face);
d1bf13b3
KS
2054 return Qdefault;
2055 }
c7ae3284
GM
2056 }
2057
2058 return face_name;
2059}
2060
2061
82641697 2062/* Return the face definition of FACE_NAME on frame F. F null means
45d9f1ef
GM
2063 return the definition for new frames. FACE_NAME may be a string or
2064 a symbol (apparently Emacs 20.2 allowed strings as face names in
f2cec7a9
MB
2065 face text properties; Ediff uses that). If SIGNAL_P is non-zero,
2066 signal an error if FACE_NAME is not a valid face name. If SIGNAL_P
2067 is zero, value is nil if FACE_NAME is not a valid face name. */
55d4c1b2 2068static inline Lisp_Object
b5f03016
AS
2069lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
2070 int signal_p)
82641697 2071{
c7ae3284 2072 Lisp_Object lface;
82641697
GM
2073
2074 if (f)
2075 lface = assq_no_quit (face_name, f->face_alist);
2076 else
2077 lface = assq_no_quit (face_name, Vface_new_frame_defaults);
2078
2079 if (CONSP (lface))
2080 lface = XCDR (lface);
2081 else if (signal_p)
2082 signal_error ("Invalid face", face_name);
2083
2084 check_lface (lface);
f2cec7a9 2085
82641697
GM
2086 return lface;
2087}
2088
f2cec7a9
MB
2089/* Return the face definition of FACE_NAME on frame F. F null means
2090 return the definition for new frames. FACE_NAME may be a string or
2091 a symbol (apparently Emacs 20.2 allowed strings as face names in
2092 face text properties; Ediff uses that). If FACE_NAME is an alias
2093 for another face, return that face's definition. If SIGNAL_P is
2094 non-zero, signal an error if FACE_NAME is not a valid face name.
2095 If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
2096 name. */
55d4c1b2 2097static inline Lisp_Object
971de7fb 2098lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
f2cec7a9
MB
2099{
2100 face_name = resolve_face_name (face_name, signal_p);
2101 return lface_from_face_name_no_resolve (f, face_name, signal_p);
2102}
2103
82641697 2104
e7d7fd8c
MB
2105/* Get face attributes of face FACE_NAME from frame-local faces on
2106 frame F. Store the resulting attributes in ATTRS which must point
2107 to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If SIGNAL_P
2108 is non-zero, signal an error if FACE_NAME does not name a face.
2109 Otherwise, value is zero if FACE_NAME is not a face. */
2110
55d4c1b2 2111static inline int
b5f03016
AS
2112get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
2113 Lisp_Object *attrs, int signal_p)
e7d7fd8c
MB
2114{
2115 Lisp_Object lface;
e7d7fd8c 2116
f2cec7a9
MB
2117 lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
2118
2119 if (! NILP (lface))
72af86bd
AS
2120 memcpy (attrs, XVECTOR (lface)->contents,
2121 LFACE_VECTOR_SIZE * sizeof *attrs);
f2cec7a9
MB
2122
2123 return !NILP (lface);
2124}
2125
2126/* Get face attributes of face FACE_NAME from frame-local faces on frame
2127 F. Store the resulting attributes in ATTRS which must point to a
2128 vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an
2129 alias for another face, use that face's definition. If SIGNAL_P is
2130 non-zero, signal an error if FACE_NAME does not name a face.
2131 Otherwise, value is zero if FACE_NAME is not a face. */
2132
55d4c1b2 2133static inline int
b5f03016
AS
2134get_lface_attributes (struct frame *f, Lisp_Object face_name,
2135 Lisp_Object *attrs, int signal_p,
2136 struct named_merge_point *named_merge_points)
f2cec7a9
MB
2137{
2138 Lisp_Object face_remapping;
2139
2140 face_name = resolve_face_name (face_name, signal_p);
2141
2142 /* See if SYMBOL has been remapped to some other face (usually this
2143 is done buffer-locally). */
2144 face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
2145 if (CONSP (face_remapping))
e7d7fd8c 2146 {
f2cec7a9
MB
2147 struct named_merge_point named_merge_point;
2148
2149 if (push_named_merge_point (&named_merge_point,
2150 face_name, NAMED_MERGE_POINT_REMAP,
2151 &named_merge_points))
2152 {
2153 int i;
2154
2155 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2156 attrs[i] = Qunspecified;
2157
2158 return merge_face_ref (f, XCDR (face_remapping), attrs,
2159 signal_p, named_merge_points);
2160 }
e7d7fd8c 2161 }
e7d7fd8c 2162
f2cec7a9
MB
2163 /* Default case, no remapping. */
2164 return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
e7d7fd8c
MB
2165}
2166
2167
82641697
GM
2168/* Non-zero if all attributes in face attribute vector ATTRS are
2169 specified, i.e. are non-nil. */
2170
2171static int
971de7fb 2172lface_fully_specified_p (Lisp_Object *attrs)
82641697
GM
2173{
2174 int i;
2175
2176 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2dee4c0b 2177 if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX)
9e2a2647 2178 if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i])))
b5f03016 2179 break;
82641697
GM
2180
2181 return i == LFACE_VECTOR_SIZE;
2182}
2183
c3cee013 2184#ifdef HAVE_WINDOW_SYSTEM
82641697 2185
2dee4c0b
KH
2186/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT.
2187 If FORCE_P is zero, set only unspecified attributes of LFACE. The
2188 exception is `font' attribute. It is set to FONT_OBJECT regardless
2189 of FORCE_P. */
178c5d9c 2190
82641697 2191static int
b5f03016
AS
2192set_lface_from_font (struct frame *f, Lisp_Object lface,
2193 Lisp_Object font_object, int force_p)
f4d3bea3 2194{
f4d3bea3 2195 Lisp_Object val;
2dee4c0b 2196 struct font *font = XFONT_OBJECT (font_object);
f4d3bea3
KH
2197
2198 /* Set attributes only if unspecified, otherwise face defaults for
2199 new frames would never take effect. If the font doesn't have a
2200 specific property, set a normal value for that. */
2201
2202 if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
2203 {
2dee4c0b 2204 Lisp_Object family = AREF (font_object, FONT_FAMILY_INDEX);
f4d3bea3 2205
53aaf1e2
KH
2206 LFACE_FAMILY (lface) = SYMBOL_NAME (family);
2207 }
2208
2209 if (force_p || UNSPECIFIEDP (LFACE_FOUNDRY (lface)))
2210 {
2211 Lisp_Object foundry = AREF (font_object, FONT_FOUNDRY_INDEX);
2212
2213 LFACE_FOUNDRY (lface) = SYMBOL_NAME (foundry);
f4d3bea3
KH
2214 }
2215
2216 if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
2217 {
2dee4c0b 2218 int pt = PIXEL_TO_POINT (font->pixel_size * 10, f->resy);
f4d3bea3
KH
2219
2220 xassert (pt > 0);
2221 LFACE_HEIGHT (lface) = make_number (pt);
2222 }
2223
f4d3bea3
KH
2224 if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
2225 {
2dee4c0b
KH
2226 val = FONT_WEIGHT_FOR_FACE (font_object);
2227 LFACE_WEIGHT (lface) = ! NILP (val) ? val :Qnormal;
f4d3bea3
KH
2228 }
2229 if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
2230 {
2dee4c0b
KH
2231 val = FONT_SLANT_FOR_FACE (font_object);
2232 LFACE_SLANT (lface) = ! NILP (val) ? val : Qnormal;
f4d3bea3
KH
2233 }
2234 if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
2235 {
2dee4c0b
KH
2236 val = FONT_WIDTH_FOR_FACE (font_object);
2237 LFACE_SWIDTH (lface) = ! NILP (val) ? val : Qnormal;
f4d3bea3
KH
2238 }
2239
2dee4c0b
KH
2240 LFACE_FONT (lface) = font_object;
2241 return 1;
f4d3bea3 2242}
f4d3bea3 2243
c3cee013 2244#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
2245
2246
2c20458f
MB
2247/* Merges the face height FROM with the face height TO, and returns the
2248 merged height. If FROM is an invalid height, then INVALID is
cdfaafa9
MB
2249 returned instead. FROM and TO may be either absolute face heights or
2250 `relative' heights; the returned value is always an absolute height
fe69cf00 2251 unless both FROM and TO are relative. */
2c20458f 2252
6b463e58 2253static Lisp_Object
971de7fb 2254merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2c20458f 2255{
cdfaafa9 2256 Lisp_Object result = invalid;
2c20458f
MB
2257
2258 if (INTEGERP (from))
cdfaafa9
MB
2259 /* FROM is absolute, just use it as is. */
2260 result = from;
2261 else if (FLOATP (from))
2262 /* FROM is a scale, use it to adjust TO. */
2263 {
2264 if (INTEGERP (to))
2265 /* relative X absolute => absolute */
c319cf24 2266 result = make_number ((EMACS_INT)(XFLOAT_DATA (from) * XINT (to)));
cdfaafa9
MB
2267 else if (FLOATP (to))
2268 /* relative X relative => relative */
2269 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
a0a23346
MB
2270 else if (UNSPECIFIEDP (to))
2271 result = from;
2c20458f 2272 }
2c20458f 2273 else if (FUNCTIONP (from))
cdfaafa9 2274 /* FROM is a function, which use to adjust TO. */
2c20458f
MB
2275 {
2276 /* Call function with current height as argument.
2277 From is the new height. */
cdfaafa9 2278 Lisp_Object args[2];
2c20458f
MB
2279
2280 args[0] = from;
2281 args[1] = to;
cdfaafa9 2282 result = safe_call (2, args);
2c20458f 2283
cdfaafa9
MB
2284 /* Ensure that if TO was absolute, so is the result. */
2285 if (INTEGERP (to) && !INTEGERP (result))
2286 result = invalid;
2c20458f
MB
2287 }
2288
cdfaafa9 2289 return result;
2c20458f
MB
2290}
2291
2292
2293/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
613fa7f2 2294 store the resulting attributes in TO, which must be already be
e7d7fd8c
MB
2295 completely specified and contain only absolute attributes. Every
2296 specified attribute of FROM overrides the corresponding attribute of
2297 TO; relative attributes in FROM are merged with the absolute value in
2298 TO and replace it. NAMED_MERGE_POINTS is used internally to detect
f2cec7a9
MB
2299 loops in face inheritance/remapping; it should be 0 when called from
2300 other places. */
82641697 2301
55d4c1b2 2302static inline void
b5f03016
AS
2303merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2304 struct named_merge_point *named_merge_points)
82641697
GM
2305{
2306 int i;
2c20458f
MB
2307
2308 /* If FROM inherits from some other faces, merge their attributes into
2309 TO before merging FROM's direct attributes. Note that an :inherit
2310 attribute of `unspecified' is the same as one of nil; we never
2311 merge :inherit attributes, so nil is more correct, but lots of
2312 other code uses `unspecified' as a generic value for face attributes. */
2313 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2314 && !NILP (from[LFACE_INHERIT_INDEX]))
a0a23346 2315 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
2c20458f 2316
2dee4c0b
KH
2317 i = LFACE_FONT_INDEX;
2318 if (!UNSPECIFIEDP (from[i]))
2319 {
2320 if (!UNSPECIFIEDP (to[i]))
92470028 2321 to[i] = merge_font_spec (from[i], to[i]);
2dee4c0b 2322 else
92470028 2323 to[i] = copy_font_spec (from[i]);
89dc9a8e
KH
2324 if (! NILP (AREF (to[i], FONT_FOUNDRY_INDEX)))
2325 to[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FOUNDRY_INDEX));
2326 if (! NILP (AREF (to[i], FONT_FAMILY_INDEX)))
2327 to[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FAMILY_INDEX));
2328 if (! NILP (AREF (to[i], FONT_WEIGHT_INDEX)))
2329 to[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (to[i]);
2330 if (! NILP (AREF (to[i], FONT_SLANT_INDEX)))
2331 to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (to[i]);
2332 if (! NILP (AREF (to[i], FONT_WIDTH_INDEX)))
2333 to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (to[i]);
2dee4c0b
KH
2334 ASET (to[i], FONT_SIZE_INDEX, Qnil);
2335 }
87188200 2336
82641697
GM
2337 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2338 if (!UNSPECIFIEDP (from[i]))
ab8469eb
PJ
2339 {
2340 if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
2dee4c0b
KH
2341 {
2342 to[i] = merge_face_heights (from[i], to[i], to[i]);
2343 font_clear_prop (to, FONT_SIZE_INDEX);
2344 }
89dc9a8e
KH
2345 else if (i != LFACE_FONT_INDEX
2346 && ! EQ (to[i], from[i]))
2dee4c0b
KH
2347 {
2348 to[i] = from[i];
2349 if (i >= LFACE_FAMILY_INDEX && i <=LFACE_SLANT_INDEX)
2350 font_clear_prop (to,
2351 (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX
53aaf1e2 2352 : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX
2dee4c0b
KH
2353 : i == LFACE_SWIDTH_INDEX ? FONT_WIDTH_INDEX
2354 : i == LFACE_HEIGHT_INDEX ? FONT_SIZE_INDEX
2355 : i == LFACE_WEIGHT_INDEX ? FONT_WEIGHT_INDEX
2356 : FONT_SLANT_INDEX));
2357 }
ab8469eb 2358 }
2c20458f
MB
2359
2360 /* TO is always an absolute face, which should inherit from nothing.
2361 We blindly copy the :inherit attribute above and fix it up here. */
2362 to[LFACE_INHERIT_INDEX] = Qnil;
2363}
2364
a0a23346
MB
2365/* Merge the named face FACE_NAME on frame F, into the vector of face
2366 attributes TO. NAMED_MERGE_POINTS is used to detect loops in face
2367 inheritance. Returns true if FACE_NAME is a valid face name and
2368 merging succeeded. */
6288c62f 2369
a0a23346 2370static int
b5f03016
AS
2371merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2372 struct named_merge_point *named_merge_points)
2c20458f 2373{
a0a23346 2374 struct named_merge_point named_merge_point;
2c20458f 2375
a0a23346 2376 if (push_named_merge_point (&named_merge_point,
f2cec7a9
MB
2377 face_name, NAMED_MERGE_POINT_NORMAL,
2378 &named_merge_points))
2c20458f 2379 {
e1e419ec 2380 struct gcpro gcpro1;
e7d7fd8c 2381 Lisp_Object from[LFACE_VECTOR_SIZE];
f2cec7a9 2382 int ok = get_lface_attributes (f, face_name, from, 0, named_merge_points);
2c20458f 2383
e7d7fd8c
MB
2384 if (ok)
2385 {
2386 GCPRO1 (named_merge_point.face_name);
2387 merge_face_vectors (f, from, to, named_merge_points);
2388 UNGCPRO;
2389 }
2390
2391 return ok;
2c20458f 2392 }
a0a23346
MB
2393 else
2394 return 0;
82641697
GM
2395}
2396
2397
a0a23346
MB
2398/* Merge face attributes from the lisp `face reference' FACE_REF on
2399 frame F into the face attribute vector TO. If ERR_MSGS is non-zero,
2400 problems with FACE_REF cause an error message to be shown. Return
2401 non-zero if no errors occurred (regardless of the value of ERR_MSGS).
2402 NAMED_MERGE_POINTS is used to detect loops in face inheritance or
2403 list structure; it may be 0 for most callers.
2404
2405 FACE_REF may be a single face specification or a list of such
2406 specifications. Each face specification can be:
82641697
GM
2407
2408 1. A symbol or string naming a Lisp face.
2409
2410 2. A property list of the form (KEYWORD VALUE ...) where each
2411 KEYWORD is a face attribute name, and value is an appropriate value
2412 for that attribute.
2413
2414 3. Conses or the form (FOREGROUND-COLOR . COLOR) or
2415 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is
2416 for compatibility with 20.2.
2417
2418 Face specifications earlier in lists take precedence over later
2419 specifications. */
178c5d9c 2420
a0a23346 2421static int
b5f03016
AS
2422merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2423 int err_msgs, struct named_merge_point *named_merge_points)
82641697 2424{
a0a23346
MB
2425 int ok = 1; /* Succeed without an error? */
2426
2427 if (CONSP (face_ref))
82641697 2428 {
a0a23346 2429 Lisp_Object first = XCAR (face_ref);
178c5d9c 2430
82641697
GM
2431 if (EQ (first, Qforeground_color)
2432 || EQ (first, Qbackground_color))
2433 {
2434 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
2435 . COLOR). COLOR must be a string. */
a0a23346 2436 Lisp_Object color_name = XCDR (face_ref);
82641697
GM
2437 Lisp_Object color = first;
2438
2439 if (STRINGP (color_name))
2440 {
2441 if (EQ (color, Qforeground_color))
2442 to[LFACE_FOREGROUND_INDEX] = color_name;
2443 else
2444 to[LFACE_BACKGROUND_INDEX] = color_name;
2445 }
2446 else
a0a23346
MB
2447 {
2448 if (err_msgs)
2449 add_to_log ("Invalid face color", color_name, Qnil);
2450 ok = 0;
2451 }
82641697
GM
2452 }
2453 else if (SYMBOLP (first)
d5db4077 2454 && *SDATA (SYMBOL_NAME (first)) == ':')
82641697
GM
2455 {
2456 /* Assume this is the property list form. */
a0a23346 2457 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
82641697 2458 {
a0a23346
MB
2459 Lisp_Object keyword = XCAR (face_ref);
2460 Lisp_Object value = XCAR (XCDR (face_ref));
2461 int err = 0;
82641697 2462
d9639b25
RS
2463 /* Specifying `unspecified' is a no-op. */
2464 if (EQ (value, Qunspecified))
2465 ;
2466 else if (EQ (keyword, QCfamily))
82641697
GM
2467 {
2468 if (STRINGP (value))
2dee4c0b
KH
2469 {
2470 to[LFACE_FAMILY_INDEX] = value;
2471 font_clear_prop (to, FONT_FAMILY_INDEX);
2472 }
82641697 2473 else
a0a23346 2474 err = 1;
82641697 2475 }
53aaf1e2
KH
2476 else if (EQ (keyword, QCfoundry))
2477 {
2478 if (STRINGP (value))
2479 {
2480 to[LFACE_FOUNDRY_INDEX] = value;
2481 font_clear_prop (to, FONT_FOUNDRY_INDEX);
2482 }
2483 else
2484 err = 1;
2485 }
82641697
GM
2486 else if (EQ (keyword, QCheight))
2487 {
2c20458f 2488 Lisp_Object new_height =
e1e419ec 2489 merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil);
2c20458f 2490
a0a23346 2491 if (! NILP (new_height))
2dee4c0b
KH
2492 {
2493 to[LFACE_HEIGHT_INDEX] = new_height;
2494 font_clear_prop (to, FONT_SIZE_INDEX);
2495 }
a0a23346
MB
2496 else
2497 err = 1;
82641697
GM
2498 }
2499 else if (EQ (keyword, QCweight))
2500 {
2dee4c0b
KH
2501 if (SYMBOLP (value) && FONT_WEIGHT_NAME_NUMERIC (value) >= 0)
2502 {
2503 to[LFACE_WEIGHT_INDEX] = value;
2504 font_clear_prop (to, FONT_WEIGHT_INDEX);
2505 }
82641697 2506 else
a0a23346 2507 err = 1;
82641697
GM
2508 }
2509 else if (EQ (keyword, QCslant))
2510 {
2dee4c0b
KH
2511 if (SYMBOLP (value) && FONT_SLANT_NAME_NUMERIC (value) >= 0)
2512 {
2513 to[LFACE_SLANT_INDEX] = value;
2514 font_clear_prop (to, FONT_SLANT_INDEX);
2515 }
82641697 2516 else
a0a23346 2517 err = 1;
82641697
GM
2518 }
2519 else if (EQ (keyword, QCunderline))
2520 {
2521 if (EQ (value, Qt)
2522 || NILP (value)
2523 || STRINGP (value))
2524 to[LFACE_UNDERLINE_INDEX] = value;
2525 else
a0a23346 2526 err = 1;
82641697
GM
2527 }
2528 else if (EQ (keyword, QCoverline))
2529 {
2530 if (EQ (value, Qt)
2531 || NILP (value)
2532 || STRINGP (value))
2533 to[LFACE_OVERLINE_INDEX] = value;
2534 else
a0a23346 2535 err = 1;
82641697
GM
2536 }
2537 else if (EQ (keyword, QCstrike_through))
2538 {
2539 if (EQ (value, Qt)
2540 || NILP (value)
2541 || STRINGP (value))
2542 to[LFACE_STRIKE_THROUGH_INDEX] = value;
2543 else
a0a23346 2544 err = 1;
82641697
GM
2545 }
2546 else if (EQ (keyword, QCbox))
2547 {
2548 if (EQ (value, Qt))
2549 value = make_number (1);
2550 if (INTEGERP (value)
2551 || STRINGP (value)
2552 || CONSP (value)
2553 || NILP (value))
2554 to[LFACE_BOX_INDEX] = value;
2555 else
a0a23346 2556 err = 1;
82641697
GM
2557 }
2558 else if (EQ (keyword, QCinverse_video)
2559 || EQ (keyword, QCreverse_video))
2560 {
2561 if (EQ (value, Qt) || NILP (value))
2562 to[LFACE_INVERSE_INDEX] = value;
2563 else
a0a23346 2564 err = 1;
82641697
GM
2565 }
2566 else if (EQ (keyword, QCforeground))
2567 {
2568 if (STRINGP (value))
2569 to[LFACE_FOREGROUND_INDEX] = value;
2570 else
a0a23346 2571 err = 1;
82641697
GM
2572 }
2573 else if (EQ (keyword, QCbackground))
2574 {
2575 if (STRINGP (value))
2576 to[LFACE_BACKGROUND_INDEX] = value;
2577 else
a0a23346 2578 err = 1;
82641697
GM
2579 }
2580 else if (EQ (keyword, QCstipple))
2581 {
5e617bc2 2582#if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
fef04523 2583 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
82641697
GM
2584 if (!NILP (pixmap_p))
2585 to[LFACE_STIPPLE_INDEX] = value;
2586 else
a0a23346 2587 err = 1;
82641697
GM
2588#endif
2589 }
2590 else if (EQ (keyword, QCwidth))
2591 {
2dee4c0b
KH
2592 if (SYMBOLP (value) && FONT_WIDTH_NAME_NUMERIC (value) >= 0)
2593 {
2594 to[LFACE_SWIDTH_INDEX] = value;
2595 font_clear_prop (to, FONT_WIDTH_INDEX);
2596 }
82641697 2597 else
a0a23346 2598 err = 1;
82641697 2599 }
2c20458f
MB
2600 else if (EQ (keyword, QCinherit))
2601 {
a0a23346
MB
2602 /* This is not really very useful; it's just like a
2603 normal face reference. */
2604 if (! merge_face_ref (f, value, to,
2605 err_msgs, named_merge_points))
2606 err = 1;
2c20458f 2607 }
82641697 2608 else
a0a23346 2609 err = 1;
82641697 2610
a0a23346
MB
2611 if (err)
2612 {
2613 add_to_log ("Invalid face attribute %S %S", keyword, value);
2614 ok = 0;
2615 }
82641697 2616
a0a23346 2617 face_ref = XCDR (XCDR (face_ref));
82641697
GM
2618 }
2619 }
2620 else
2621 {
a0a23346
MB
2622 /* This is a list of face refs. Those at the beginning of the
2623 list take precedence over what follows, so we have to merge
2624 from the end backwards. */
2625 Lisp_Object next = XCDR (face_ref);
2626
2627 if (! NILP (next))
2628 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points);
2629
2630 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points))
2631 ok = 0;
82641697
GM
2632 }
2633 }
2634 else
2635 {
a0a23346
MB
2636 /* FACE_REF ought to be a face name. */
2637 ok = merge_named_face (f, face_ref, to, named_merge_points);
2638 if (!ok && err_msgs)
2639 add_to_log ("Invalid face reference: %s", face_ref, Qnil);
82641697 2640 }
a0a23346
MB
2641
2642 return ok;
82641697
GM
2643}
2644
2645
2646DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
2647 Sinternal_make_lisp_face, 1, 2, 0,
7ee72033 2648 doc: /* Make FACE, a symbol, a Lisp face with all attributes nil.
228299fa
GM
2649If FACE was not known as a face before, create a new one.
2650If optional argument FRAME is specified, make a frame-local face
2651for that frame. Otherwise operate on the global face definition.
7ee72033 2652Value is a vector of face attributes. */)
5842a27b 2653 (Lisp_Object face, Lisp_Object frame)
82641697
GM
2654{
2655 Lisp_Object global_lface, lface;
2656 struct frame *f;
2657 int i;
2658
b7826503 2659 CHECK_SYMBOL (face);
82641697 2660 global_lface = lface_from_face_name (NULL, face, 0);
178c5d9c 2661
82641697
GM
2662 if (!NILP (frame))
2663 {
b7826503 2664 CHECK_LIVE_FRAME (frame);
82641697
GM
2665 f = XFRAME (frame);
2666 lface = lface_from_face_name (f, face, 0);
2667 }
2668 else
2669 f = NULL, lface = Qnil;
2670
2671 /* Add a global definition if there is none. */
2672 if (NILP (global_lface))
2673 {
2674 global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
2675 Qunspecified);
dfae5f9a 2676 ASET (global_lface, 0, Qface);
178c5d9c 2677 Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
82641697 2678 Vface_new_frame_defaults);
178c5d9c 2679
82641697
GM
2680 /* Assign the new Lisp face a unique ID. The mapping from Lisp
2681 face id to Lisp face is given by the vector lface_id_to_name.
2682 The mapping from Lisp face to Lisp face id is given by the
2683 property `face' of the Lisp face name. */
2684 if (next_lface_id == lface_id_to_name_size)
0065d054
PE
2685 lface_id_to_name =
2686 xpalloc (lface_id_to_name, &lface_id_to_name_size, 1,
2687 min (INT_MAX, MOST_POSITIVE_FIXNUM),
2688 sizeof *lface_id_to_name);
178c5d9c 2689
82641697
GM
2690 lface_id_to_name[next_lface_id] = face;
2691 Fput (face, Qface, make_number (next_lface_id));
2692 ++next_lface_id;
2693 }
2694 else if (f == NULL)
2695 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
dfae5f9a 2696 ASET (global_lface, i, Qunspecified);
178c5d9c 2697
82641697
GM
2698 /* Add a frame-local definition. */
2699 if (f)
2700 {
2701 if (NILP (lface))
2702 {
2703 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
2704 Qunspecified);
dfae5f9a 2705 ASET (lface, 0, Qface);
82641697
GM
2706 f->face_alist = Fcons (Fcons (face, lface), f->face_alist);
2707 }
2708 else
2709 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
dfae5f9a 2710 ASET (lface, i, Qunspecified);
82641697
GM
2711 }
2712 else
2713 lface = global_lface;
2714
33565969
RS
2715 /* Changing a named face means that all realized faces depending on
2716 that face are invalid. Since we cannot tell which realized faces
2717 depend on the face, make sure they are all removed. This is done
2718 by incrementing face_change_count. The next call to
2719 init_iterator will then free realized faces. */
46b00436
KS
2720 if (NILP (Fget (face, Qface_no_inherit)))
2721 {
2722 ++face_change_count;
2723 ++windows_or_buffers_changed;
2724 }
33565969 2725
82641697
GM
2726 xassert (LFACEP (lface));
2727 check_lface (lface);
2728 return lface;
2729}
2730
2731
2732DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
2733 Sinternal_lisp_face_p, 1, 2, 0,
7ee72033 2734 doc: /* Return non-nil if FACE names a face.
b84ce3c5 2735FACE should be a symbol or string.
1d256714 2736If optional second argument FRAME is non-nil, check for the
228299fa 2737existence of a frame-local face with name FACE on that frame.
7ee72033 2738Otherwise check for the existence of a global face. */)
5842a27b 2739 (Lisp_Object face, Lisp_Object frame)
82641697
GM
2740{
2741 Lisp_Object lface;
178c5d9c 2742
65fddb74
JB
2743 face = resolve_face_name (face, 1);
2744
82641697
GM
2745 if (!NILP (frame))
2746 {
b7826503 2747 CHECK_LIVE_FRAME (frame);
82641697
GM
2748 lface = lface_from_face_name (XFRAME (frame), face, 0);
2749 }
2750 else
2751 lface = lface_from_face_name (NULL, face, 0);
2752
2753 return lface;
2754}
2755
2756
2757DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
2758 Sinternal_copy_lisp_face, 4, 4, 0,
7ee72033 2759 doc: /* Copy face FROM to TO.
5e9bab6f
RS
2760If FRAME is t, copy the global face definition of FROM.
2761Otherwise, copy the frame-local definition of FROM on FRAME.
2762If NEW-FRAME is a frame, copy that data into the frame-local
d5ab09cd 2763definition of TO on NEW-FRAME. If NEW-FRAME is nil,
5e9bab6f 2764FRAME controls where the data is copied to.
228299fa 2765
5e9bab6f 2766The value is TO. */)
5842a27b 2767 (Lisp_Object from, Lisp_Object to, Lisp_Object frame, Lisp_Object new_frame)
82641697
GM
2768{
2769 Lisp_Object lface, copy;
178c5d9c 2770
b7826503
PJ
2771 CHECK_SYMBOL (from);
2772 CHECK_SYMBOL (to);
82641697
GM
2773
2774 if (EQ (frame, Qt))
2775 {
2776 /* Copy global definition of FROM. We don't make copies of
2777 strings etc. because 20.2 didn't do it either. */
2778 lface = lface_from_face_name (NULL, from, 1);
2779 copy = Finternal_make_lisp_face (to, Qnil);
2780 }
2781 else
2782 {
2783 /* Copy frame-local definition of FROM. */
5e9bab6f
RS
2784 if (NILP (new_frame))
2785 new_frame = frame;
b7826503
PJ
2786 CHECK_LIVE_FRAME (frame);
2787 CHECK_LIVE_FRAME (new_frame);
82641697
GM
2788 lface = lface_from_face_name (XFRAME (frame), from, 1);
2789 copy = Finternal_make_lisp_face (to, new_frame);
2790 }
178c5d9c 2791
72af86bd
AS
2792 memcpy (XVECTOR (copy)->contents, XVECTOR (lface)->contents,
2793 LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
178c5d9c 2794
33565969
RS
2795 /* Changing a named face means that all realized faces depending on
2796 that face are invalid. Since we cannot tell which realized faces
2797 depend on the face, make sure they are all removed. This is done
2798 by incrementing face_change_count. The next call to
2799 init_iterator will then free realized faces. */
46b00436
KS
2800 if (NILP (Fget (to, Qface_no_inherit)))
2801 {
2802 ++face_change_count;
2803 ++windows_or_buffers_changed;
2804 }
33565969 2805
82641697
GM
2806 return to;
2807}
2808
2809
2810DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
2811 Sinternal_set_lisp_face_attribute, 3, 4, 0,
7ee72033 2812 doc: /* Set attribute ATTR of FACE to VALUE.
228299fa
GM
2813FRAME being a frame means change the face on that frame.
2814FRAME nil means change the face of the selected frame.
2815FRAME t means change the default for new frames.
2816FRAME 0 means change the face on all frames, and change the default
7ee72033 2817 for new frames. */)
5842a27b 2818 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
82641697
GM
2819{
2820 Lisp_Object lface;
2821 Lisp_Object old_value = Qnil;
2dee4c0b
KH
2822 /* Set one of enum font_property_index (> 0) if ATTR is one of
2823 font-related attributes other than QCfont and QCfontset. */
2824 enum font_property_index prop_index = 0;
178c5d9c 2825
b7826503
PJ
2826 CHECK_SYMBOL (face);
2827 CHECK_SYMBOL (attr);
82641697 2828
d1bf13b3 2829 face = resolve_face_name (face, 1);
c7ae3284 2830
628436fb
GM
2831 /* If FRAME is 0, change face on all frames, and change the
2832 default for new frames. */
2833 if (INTEGERP (frame) && XINT (frame) == 0)
2834 {
2835 Lisp_Object tail;
d12d0a9b 2836 Finternal_set_lisp_face_attribute (face, attr, value, Qt);
628436fb
GM
2837 FOR_EACH_FRAME (tail, frame)
2838 Finternal_set_lisp_face_attribute (face, attr, value, frame);
d12d0a9b 2839 return face;
628436fb
GM
2840 }
2841
82641697
GM
2842 /* Set lface to the Lisp attribute vector of FACE. */
2843 if (EQ (frame, Qt))
0268cef3
CY
2844 {
2845 lface = lface_from_face_name (NULL, face, 1);
67d23e01
CY
2846
2847 /* When updating face-new-frame-defaults, we put :ignore-defface
2848 where the caller wants `unspecified'. This forces the frame
2849 defaults to ignore the defface value. Otherwise, the defface
2850 will take effect, which is generally not what is intended.
2851 The value of that attribute will be inherited from some other
2852 face during face merging. See internal_merge_in_global_face. */
0268cef3 2853 if (UNSPECIFIEDP (value))
a3720aa2 2854 value = QCignore_defface;
0268cef3 2855 }
82641697
GM
2856 else
2857 {
2858 if (NILP (frame))
c0617987 2859 frame = selected_frame;
178c5d9c 2860
b7826503 2861 CHECK_LIVE_FRAME (frame);
82641697 2862 lface = lface_from_face_name (XFRAME (frame), face, 0);
178c5d9c 2863
82641697
GM
2864 /* If a frame-local face doesn't exist yet, create one. */
2865 if (NILP (lface))
2866 lface = Finternal_make_lisp_face (face, frame);
2867 }
2868
2869 if (EQ (attr, QCfamily))
2870 {
2ff10663 2871 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2872 {
b7826503 2873 CHECK_STRING (value);
d5db4077 2874 if (SCHARS (value) == 0)
82641697
GM
2875 signal_error ("Invalid face family", value);
2876 }
2877 old_value = LFACE_FAMILY (lface);
2878 LFACE_FAMILY (lface) = value;
2dee4c0b 2879 prop_index = FONT_FAMILY_INDEX;
82641697 2880 }
53aaf1e2
KH
2881 else if (EQ (attr, QCfoundry))
2882 {
2883 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2884 {
2885 CHECK_STRING (value);
2886 if (SCHARS (value) == 0)
2887 signal_error ("Invalid face foundry", value);
2888 }
2889 old_value = LFACE_FOUNDRY (lface);
2890 LFACE_FOUNDRY (lface) = value;
2891 prop_index = FONT_FOUNDRY_INDEX;
2892 }
82641697
GM
2893 else if (EQ (attr, QCheight))
2894 {
2ff10663 2895 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2896 {
e66d5363
CY
2897 if (EQ (face, Qdefault))
2898 {
2899 /* The default face must have an absolute size. */
2900 if (!INTEGERP (value) || XINT (value) <= 0)
b5f03016
AS
2901 signal_error ("Default face height not absolute and positive",
2902 value);
e66d5363
CY
2903 }
2904 else
2905 {
2906 /* For non-default faces, do a test merge with a random
2907 height to see if VALUE's ok. */
2908 Lisp_Object test = merge_face_heights (value,
2909 make_number (10),
2910 Qnil);
2911 if (!INTEGERP (test) || XINT (test) <= 0)
b5f03016
AS
2912 signal_error ("Face height does not produce a positive integer",
2913 value);
e66d5363 2914 }
82641697 2915 }
2c20458f 2916
82641697
GM
2917 old_value = LFACE_HEIGHT (lface);
2918 LFACE_HEIGHT (lface) = value;
2dee4c0b 2919 prop_index = FONT_SIZE_INDEX;
82641697
GM
2920 }
2921 else if (EQ (attr, QCweight))
2922 {
2ff10663 2923 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2924 {
b7826503 2925 CHECK_SYMBOL (value);
2dee4c0b 2926 if (FONT_WEIGHT_NAME_NUMERIC (value) < 0)
82641697
GM
2927 signal_error ("Invalid face weight", value);
2928 }
2929 old_value = LFACE_WEIGHT (lface);
2930 LFACE_WEIGHT (lface) = value;
2dee4c0b 2931 prop_index = FONT_WEIGHT_INDEX;
82641697
GM
2932 }
2933 else if (EQ (attr, QCslant))
2934 {
2ff10663 2935 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 2936 {
b7826503 2937 CHECK_SYMBOL (value);
2dee4c0b 2938 if (FONT_SLANT_NAME_NUMERIC (value) < 0)
82641697
GM
2939 signal_error ("Invalid face slant", value);
2940 }
2941 old_value = LFACE_SLANT (lface);
2942 LFACE_SLANT (lface) = value;
2dee4c0b 2943 prop_index = FONT_SLANT_INDEX;
82641697
GM
2944 }
2945 else if (EQ (attr, QCunderline))
2946 {
2ff10663 2947 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
2948 if ((SYMBOLP (value)
2949 && !EQ (value, Qt)
2950 && !EQ (value, Qnil))
2951 /* Underline color. */
2952 || (STRINGP (value)
d5db4077 2953 && SCHARS (value) == 0))
82641697 2954 signal_error ("Invalid face underline", value);
178c5d9c 2955
82641697
GM
2956 old_value = LFACE_UNDERLINE (lface);
2957 LFACE_UNDERLINE (lface) = value;
2958 }
2959 else if (EQ (attr, QCoverline))
2960 {
2ff10663 2961 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
2962 if ((SYMBOLP (value)
2963 && !EQ (value, Qt)
2964 && !EQ (value, Qnil))
2965 /* Overline color. */
2966 || (STRINGP (value)
d5db4077 2967 && SCHARS (value) == 0))
82641697 2968 signal_error ("Invalid face overline", value);
178c5d9c 2969
82641697
GM
2970 old_value = LFACE_OVERLINE (lface);
2971 LFACE_OVERLINE (lface) = value;
2972 }
2973 else if (EQ (attr, QCstrike_through))
2974 {
2ff10663 2975 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
2976 if ((SYMBOLP (value)
2977 && !EQ (value, Qt)
2978 && !EQ (value, Qnil))
2979 /* Strike-through color. */
2980 || (STRINGP (value)
d5db4077 2981 && SCHARS (value) == 0))
82641697 2982 signal_error ("Invalid face strike-through", value);
178c5d9c 2983
82641697
GM
2984 old_value = LFACE_STRIKE_THROUGH (lface);
2985 LFACE_STRIKE_THROUGH (lface) = value;
2986 }
2987 else if (EQ (attr, QCbox))
2988 {
2989 int valid_p;
178c5d9c 2990
82641697 2991 /* Allow t meaning a simple box of width 1 in foreground color
b5f03016 2992 of the face. */
82641697
GM
2993 if (EQ (value, Qt))
2994 value = make_number (1);
2995
2ff10663 2996 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
82641697
GM
2997 valid_p = 1;
2998 else if (NILP (value))
2999 valid_p = 1;
3000 else if (INTEGERP (value))
89624b8b 3001 valid_p = XINT (value) != 0;
82641697 3002 else if (STRINGP (value))
d5db4077 3003 valid_p = SCHARS (value) > 0;
82641697
GM
3004 else if (CONSP (value))
3005 {
3006 Lisp_Object tem;
178c5d9c 3007
82641697
GM
3008 tem = value;
3009 while (CONSP (tem))
3010 {
3011 Lisp_Object k, v;
3012
3013 k = XCAR (tem);
3014 tem = XCDR (tem);
3015 if (!CONSP (tem))
3016 break;
3017 v = XCAR (tem);
3018 tem = XCDR (tem);
178c5d9c 3019
82641697
GM
3020 if (EQ (k, QCline_width))
3021 {
89624b8b 3022 if (!INTEGERP (v) || XINT (v) == 0)
82641697
GM
3023 break;
3024 }
3025 else if (EQ (k, QCcolor))
3026 {
91c212f1 3027 if (!NILP (v) && (!STRINGP (v) || SCHARS (v) == 0))
82641697
GM
3028 break;
3029 }
3030 else if (EQ (k, QCstyle))
3031 {
3032 if (!EQ (v, Qpressed_button) && !EQ (v, Qreleased_button))
3033 break;
3034 }
3035 else
3036 break;
3037 }
3038
3039 valid_p = NILP (tem);
3040 }
3041 else
3042 valid_p = 0;
3043
3044 if (!valid_p)
3045 signal_error ("Invalid face box", value);
178c5d9c 3046
82641697
GM
3047 old_value = LFACE_BOX (lface);
3048 LFACE_BOX (lface) = value;
3049 }
3050 else if (EQ (attr, QCinverse_video)
3051 || EQ (attr, QCreverse_video))
3052 {
2ff10663 3053 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 3054 {
b7826503 3055 CHECK_SYMBOL (value);
82641697
GM
3056 if (!EQ (value, Qt) && !NILP (value))
3057 signal_error ("Invalid inverse-video face attribute value", value);
3058 }
3059 old_value = LFACE_INVERSE (lface);
3060 LFACE_INVERSE (lface) = value;
3061 }
3062 else if (EQ (attr, QCforeground))
3063 {
ca6888b6
CY
3064 /* Compatibility with 20.x. */
3065 if (NILP (value))
3066 value = Qunspecified;
2ff10663 3067 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
3068 {
3069 /* Don't check for valid color names here because it depends
3070 on the frame (display) whether the color will be valid
3071 when the face is realized. */
b7826503 3072 CHECK_STRING (value);
d5db4077 3073 if (SCHARS (value) == 0)
82641697
GM
3074 signal_error ("Empty foreground color value", value);
3075 }
3076 old_value = LFACE_FOREGROUND (lface);
3077 LFACE_FOREGROUND (lface) = value;
3078 }
3079 else if (EQ (attr, QCbackground))
3080 {
ca6888b6
CY
3081 /* Compatibility with 20.x. */
3082 if (NILP (value))
3083 value = Qunspecified;
2ff10663 3084 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
3085 {
3086 /* Don't check for valid color names here because it depends
3087 on the frame (display) whether the color will be valid
3088 when the face is realized. */
b7826503 3089 CHECK_STRING (value);
d5db4077 3090 if (SCHARS (value) == 0)
82641697
GM
3091 signal_error ("Empty background color value", value);
3092 }
3093 old_value = LFACE_BACKGROUND (lface);
3094 LFACE_BACKGROUND (lface) = value;
3095 }
3096 else if (EQ (attr, QCstipple))
3097 {
5e617bc2 3098#if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
2ff10663 3099 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
82641697 3100 && !NILP (value)
fef04523 3101 && NILP (Fbitmap_spec_p (value)))
82641697
GM
3102 signal_error ("Invalid stipple attribute", value);
3103 old_value = LFACE_STIPPLE (lface);
3104 LFACE_STIPPLE (lface) = value;
edfda783 3105#endif /* HAVE_X_WINDOWS || HAVE_NS */
82641697
GM
3106 }
3107 else if (EQ (attr, QCwidth))
3108 {
2ff10663 3109 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 3110 {
b7826503 3111 CHECK_SYMBOL (value);
2dee4c0b 3112 if (FONT_WIDTH_NAME_NUMERIC (value) < 0)
82641697
GM
3113 signal_error ("Invalid face width", value);
3114 }
3115 old_value = LFACE_SWIDTH (lface);
3116 LFACE_SWIDTH (lface) = value;
2dee4c0b 3117 prop_index = FONT_WIDTH_INDEX;
82641697 3118 }
2dee4c0b 3119 else if (EQ (attr, QCfont))
82641697 3120 {
c3cee013 3121#ifdef HAVE_WINDOW_SYSTEM
3d90c96c 3122 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
96fbd2c6 3123 {
2dee4c0b 3124 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
f4d3bea3 3125 {
2dee4c0b
KH
3126 FRAME_PTR f;
3127
3128 old_value = LFACE_FONT (lface);
3129 if (! FONTP (value))
f4d3bea3 3130 {
2dee4c0b
KH
3131 if (STRINGP (value))
3132 {
21bdb81a
CY
3133 Lisp_Object name = value;
3134 int fontset = fs_query_fontset (name, 0);
2dee4c0b
KH
3135
3136 if (fontset >= 0)
21bdb81a
CY
3137 name = fontset_ascii (fontset);
3138 value = font_spec_from_name (name);
3139 if (!FONTP (value))
3140 signal_error ("Invalid font name", name);
2dee4c0b
KH
3141 }
3142 else
3143 signal_error ("Invalid font or font-spec", value);
f4d3bea3 3144 }
2dee4c0b
KH
3145 if (EQ (frame, Qt))
3146 f = XFRAME (selected_frame);
f4d3bea3 3147 else
2dee4c0b
KH
3148 f = XFRAME (frame);
3149 if (! FONT_OBJECT_P (value))
f4d3bea3 3150 {
2dee4c0b 3151 Lisp_Object *attrs = XVECTOR (lface)->contents;
f4d3bea3
KH
3152 Lisp_Object font_object;
3153
2dee4c0b 3154 font_object = font_load_for_lface (f, attrs, value);
db1c10a2 3155 if (NILP (font_object))
2dee4c0b
KH
3156 signal_error ("Font not available", value);
3157 value = font_object;
f4d3bea3 3158 }
2dee4c0b 3159 set_lface_from_font (f, lface, value, 1);
f4d3bea3
KH
3160 }
3161 else
2dee4c0b
KH
3162 LFACE_FONT (lface) = value;
3163 }
3164#endif /* HAVE_WINDOW_SYSTEM */
3165 }
3166 else if (EQ (attr, QCfontset))
3167 {
3168#ifdef HAVE_WINDOW_SYSTEM
3169 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
3170 {
3171 Lisp_Object tmp;
39506348 3172
2dee4c0b
KH
3173 old_value = LFACE_FONTSET (lface);
3174 tmp = Fquery_fontset (value, Qnil);
3175 if (NILP (tmp))
3176 signal_error ("Invalid fontset name", value);
3177 LFACE_FONTSET (lface) = value = tmp;
96fbd2c6 3178 }
c3cee013 3179#endif /* HAVE_WINDOW_SYSTEM */
82641697 3180 }
2c20458f
MB
3181 else if (EQ (attr, QCinherit))
3182 {
3183 Lisp_Object tail;
3184 if (SYMBOLP (value))
3185 tail = Qnil;
3186 else
3187 for (tail = value; CONSP (tail); tail = XCDR (tail))
3188 if (!SYMBOLP (XCAR (tail)))
3189 break;
3190 if (NILP (tail))
3191 LFACE_INHERIT (lface) = value;
3192 else
6288c62f 3193 signal_error ("Invalid face inheritance", value);
2c20458f 3194 }
82641697
GM
3195 else if (EQ (attr, QCbold))
3196 {
3197 old_value = LFACE_WEIGHT (lface);
3198 LFACE_WEIGHT (lface) = NILP (value) ? Qnormal : Qbold;
2dee4c0b 3199 prop_index = FONT_WEIGHT_INDEX;
82641697
GM
3200 }
3201 else if (EQ (attr, QCitalic))
3202 {
2dee4c0b 3203 attr = QCslant;
82641697
GM
3204 old_value = LFACE_SLANT (lface);
3205 LFACE_SLANT (lface) = NILP (value) ? Qnormal : Qitalic;
2dee4c0b 3206 prop_index = FONT_SLANT_INDEX;
82641697
GM
3207 }
3208 else
3209 signal_error ("Invalid face attribute name", attr);
3210
2dee4c0b 3211 if (prop_index)
e69a00b7
CY
3212 {
3213 /* If a font-related attribute other than QCfont and QCfontset
3214 is specified, and if the original QCfont attribute has a font
3215 (font-spec or font-object), set the corresponding property in
3216 the font to nil so that the font selector doesn't think that
3217 the attribute is mandatory. Also, clear the average
3218 width. */
3219 font_clear_prop (XVECTOR (lface)->contents, prop_index);
e69a00b7 3220 }
39506348 3221
82641697
GM
3222 /* Changing a named face means that all realized faces depending on
3223 that face are invalid. Since we cannot tell which realized faces
3224 depend on the face, make sure they are all removed. This is done
3225 by incrementing face_change_count. The next call to
3226 init_iterator will then free realized faces. */
3227 if (!EQ (frame, Qt)
46b00436 3228 && NILP (Fget (face, Qface_no_inherit))
2dee4c0b 3229 && NILP (Fequal (old_value, value)))
82641697
GM
3230 {
3231 ++face_change_count;
3232 ++windows_or_buffers_changed;
3233 }
3234
2ff10663 3235 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
82641697 3236 && NILP (Fequal (old_value, value)))
8bd201d6
GM
3237 {
3238 Lisp_Object param;
3239
3240 param = Qnil;
178c5d9c 3241
8bd201d6
GM
3242 if (EQ (face, Qdefault))
3243 {
b9c769f8 3244#ifdef HAVE_WINDOW_SYSTEM
8bd201d6
GM
3245 /* Changed font-related attributes of the `default' face are
3246 reflected in changed `font' frame parameters. */
ceeda019 3247 if (FRAMEP (frame)
2dee4c0b 3248 && (prop_index || EQ (attr, QCfont))
8bd201d6
GM
3249 && lface_fully_specified_p (XVECTOR (lface)->contents))
3250 set_font_frame_param (frame, lface);
b9c769f8
EZ
3251 else
3252#endif /* HAVE_WINDOW_SYSTEM */
3253
3254 if (EQ (attr, QCforeground))
8bd201d6
GM
3255 param = Qforeground_color;
3256 else if (EQ (attr, QCbackground))
3257 param = Qbackground_color;
3258 }
b9c769f8 3259#ifdef HAVE_WINDOW_SYSTEM
c3cee013 3260#ifndef WINDOWSNT
8bd201d6
GM
3261 else if (EQ (face, Qscroll_bar))
3262 {
3263 /* Changing the colors of `scroll-bar' sets frame parameters
3264 `scroll-bar-foreground' and `scroll-bar-background'. */
3265 if (EQ (attr, QCforeground))
3266 param = Qscroll_bar_foreground;
3267 else if (EQ (attr, QCbackground))
3268 param = Qscroll_bar_background;
3269 }
d12d0a9b 3270#endif /* not WINDOWSNT */
8bd201d6
GM
3271 else if (EQ (face, Qborder))
3272 {
3273 /* Changing background color of `border' sets frame parameter
3274 `border-color'. */
3275 if (EQ (attr, QCbackground))
3276 param = Qborder_color;
3277 }
3278 else if (EQ (face, Qcursor))
3279 {
3280 /* Changing background color of `cursor' sets frame parameter
3281 `cursor-color'. */
3282 if (EQ (attr, QCbackground))
3283 param = Qcursor_color;
3284 }
3285 else if (EQ (face, Qmouse))
3286 {
3287 /* Changing background color of `mouse' sets frame parameter
3288 `mouse-color'. */
3289 if (EQ (attr, QCbackground))
3290 param = Qmouse_color;
3291 }
b9c769f8 3292#endif /* HAVE_WINDOW_SYSTEM */
563f68f1 3293 else if (EQ (face, Qmenu))
ceeda019
GM
3294 {
3295 /* Indicate that we have to update the menu bar when
3296 realizing faces on FRAME. FRAME t change the
3297 default for new frames. We do this by setting
3298 setting the flag in new face caches */
3299 if (FRAMEP (frame))
3300 {
3301 struct frame *f = XFRAME (frame);
3302 if (FRAME_FACE_CACHE (f) == NULL)
3303 FRAME_FACE_CACHE (f) = make_face_cache (f);
3304 FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
3305 }
3306 else
3307 menu_face_changed_default = 1;
3308 }
8bd201d6 3309
39506348 3310 if (!NILP (param))
ab8469eb
PJ
3311 {
3312 if (EQ (frame, Qt))
3313 /* Update `default-frame-alist', which is used for new frames. */
3314 {
3315 store_in_alist (&Vdefault_frame_alist, param, value);
3316 }
3317 else
3318 /* Update the current frame's parameters. */
3319 {
3320 Lisp_Object cons;
3321 cons = XCAR (Vparam_value_alist);
3322 XSETCAR (cons, param);
3323 XSETCDR (cons, value);
3324 Fmodify_frame_parameters (frame, Vparam_value_alist);
3325 }
3326 }
8bd201d6 3327 }
82641697 3328
82641697
GM
3329 return face;
3330}
3331
3332
8bd201d6
GM
3333/* Update the corresponding face when frame parameter PARAM on frame F
3334 has been assigned the value NEW_VALUE. */
3335
3336void
b5f03016
AS
3337update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
3338 Lisp_Object new_value)
8bd201d6 3339{
46b00436 3340 Lisp_Object face = Qnil;
8bd201d6
GM
3341 Lisp_Object lface;
3342
3343 /* If there are no faces yet, give up. This is the case when called
3344 from Fx_create_frame, and we do the necessary things later in
92610620 3345 face-set-after-frame-defaults. */
8bd201d6
GM
3346 if (NILP (f->face_alist))
3347 return;
178c5d9c 3348
8bd201d6
GM
3349 if (EQ (param, Qforeground_color))
3350 {
46b00436
KS
3351 face = Qdefault;
3352 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3353 LFACE_FOREGROUND (lface) = (STRINGP (new_value)
3354 ? new_value : Qunspecified);
3355 realize_basic_faces (f);
3356 }
3357 else if (EQ (param, Qbackground_color))
3358 {
92610620
GM
3359 Lisp_Object frame;
3360
3361 /* Changing the background color might change the background
c20577bc 3362 mode, so that we have to load new defface specs.
f2cec7a9 3363 Call frame-update-face-colors to do that. */
92610620 3364 XSETFRAME (frame, f);
c20577bc 3365 call1 (Qframe_set_background_mode, frame);
178c5d9c 3366
46b00436
KS
3367 face = Qdefault;
3368 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3369 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3370 ? new_value : Qunspecified);
3371 realize_basic_faces (f);
3372 }
76ea4cc9 3373#ifdef HAVE_WINDOW_SYSTEM
46b00436 3374 else if (EQ (param, Qborder_color))
8bd201d6 3375 {
46b00436
KS
3376 face = Qborder;
3377 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3378 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3379 ? new_value : Qunspecified);
3380 }
3381 else if (EQ (param, Qcursor_color))
3382 {
46b00436
KS
3383 face = Qcursor;
3384 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3385 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3386 ? new_value : Qunspecified);
3387 }
3388 else if (EQ (param, Qmouse_color))
3389 {
46b00436
KS
3390 face = Qmouse;
3391 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
3392 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
3393 ? new_value : Qunspecified);
3394 }
76ea4cc9 3395#endif
46b00436
KS
3396
3397 /* Changing a named face means that all realized faces depending on
3398 that face are invalid. Since we cannot tell which realized faces
3399 depend on the face, make sure they are all removed. This is done
3400 by incrementing face_change_count. The next call to
3401 init_iterator will then free realized faces. */
3402 if (!NILP (face)
3403 && NILP (Fget (face, Qface_no_inherit)))
3404 {
3405 ++face_change_count;
3406 ++windows_or_buffers_changed;
3407 }
8bd201d6
GM
3408}
3409
3410
76ea4cc9
EZ
3411#ifdef HAVE_WINDOW_SYSTEM
3412
3413/* Set the `font' frame parameter of FRAME determined from the
3414 font-object set in `default' face attributes LFACE. */
3415
3416static void
971de7fb 3417set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
76ea4cc9
EZ
3418{
3419 struct frame *f = XFRAME (frame);
3420 Lisp_Object font;
3421
3422 if (FRAME_WINDOW_P (f)
3423 /* Don't do anything if the font is `unspecified'. This can
3424 happen during frame creation. */
3425 && (font = LFACE_FONT (lface),
3426 ! UNSPECIFIEDP (font)))
3427 {
3428 if (FONT_SPEC_P (font))
3429 {
3430 font = font_load_for_lface (f, XVECTOR (lface)->contents, font);
3431 if (NILP (font))
3432 return;
3433 LFACE_FONT (lface) = font;
3434 }
3435 f->default_face_done_p = 0;
3436 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font), Qnil));
3437 }
3438}
3439
3440
82641697
GM
3441/* Get the value of X resource RESOURCE, class CLASS for the display
3442 of frame FRAME. This is here because ordinary `x-get-resource'
3443 doesn't take a frame argument. */
3444
3445DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
7ee72033 3446 Sinternal_face_x_get_resource, 3, 3, 0, doc: /* */)
5842a27b 3447 (Lisp_Object resource, Lisp_Object class, Lisp_Object frame)
82641697 3448{
c3cee013 3449 Lisp_Object value = Qnil;
b7826503
PJ
3450 CHECK_STRING (resource);
3451 CHECK_STRING (class);
3452 CHECK_LIVE_FRAME (frame);
82641697
GM
3453 BLOCK_INPUT;
3454 value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
3455 resource, class, Qnil, Qnil);
3456 UNBLOCK_INPUT;
3457 return value;
3458}
3459
3460
3461/* Return resource string VALUE as a boolean value, i.e. nil, or t.
3462 If VALUE is "on" or "true", return t. If VALUE is "off" or
3463 "false", return nil. Otherwise, if SIGNAL_P is non-zero, signal an
3464 error; if SIGNAL_P is zero, return 0. */
178c5d9c 3465
82641697 3466static Lisp_Object
971de7fb 3467face_boolean_x_resource_value (Lisp_Object value, int signal_p)
82641697
GM
3468{
3469 Lisp_Object result = make_number (0);
3470
3471 xassert (STRINGP (value));
178c5d9c 3472
25a48bd0
PE
3473 if (xstrcasecmp (SSDATA (value), "on") == 0
3474 || xstrcasecmp (SSDATA (value), "true") == 0)
82641697 3475 result = Qt;
25a48bd0
PE
3476 else if (xstrcasecmp (SSDATA (value), "off") == 0
3477 || xstrcasecmp (SSDATA (value), "false") == 0)
82641697 3478 result = Qnil;
25a48bd0 3479 else if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
82641697
GM
3480 result = Qunspecified;
3481 else if (signal_p)
3482 signal_error ("Invalid face attribute value from X resource", value);
3483
3484 return result;
3485}
3486
3487
3488DEFUN ("internal-set-lisp-face-attribute-from-resource",
3489 Finternal_set_lisp_face_attribute_from_resource,
3490 Sinternal_set_lisp_face_attribute_from_resource,
7ee72033 3491 3, 4, 0, doc: /* */)
5842a27b 3492 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
82641697 3493{
b7826503
PJ
3494 CHECK_SYMBOL (face);
3495 CHECK_SYMBOL (attr);
3496 CHECK_STRING (value);
82641697 3497
25a48bd0 3498 if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
82641697
GM
3499 value = Qunspecified;
3500 else if (EQ (attr, QCheight))
3501 {
3502 value = Fstring_to_number (value, make_number (10));
3503 if (XINT (value) <= 0)
3504 signal_error ("Invalid face height from X resource", value);
3505 }
3506 else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
3507 value = face_boolean_x_resource_value (value, 1);
3508 else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
42a5b22f 3509 value = intern (SSDATA (value));
82641697
GM
3510 else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video))
3511 value = face_boolean_x_resource_value (value, 1);
3512 else if (EQ (attr, QCunderline)
3513 || EQ (attr, QCoverline)
27188d11 3514 || EQ (attr, QCstrike_through))
82641697
GM
3515 {
3516 Lisp_Object boolean_value;
3517
3518 /* If the result of face_boolean_x_resource_value is t or nil,
3519 VALUE does NOT specify a color. */
3520 boolean_value = face_boolean_x_resource_value (value, 0);
3521 if (SYMBOLP (boolean_value))
3522 value = boolean_value;
3523 }
0ad040ff 3524 else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
27188d11 3525 value = Fcar (Fread_from_string (value, Qnil, Qnil));
82641697
GM
3526
3527 return Finternal_set_lisp_face_attribute (face, attr, value, frame);
3528}
3529
c3cee013 3530#endif /* HAVE_WINDOW_SYSTEM */
82641697 3531
c7ae3284
GM
3532\f
3533/***********************************************************************
3534 Menu face
3535 ***********************************************************************/
3536
bce72079 3537#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
c7ae3284 3538
bce72079
GM
3539/* Make menus on frame F appear as specified by the `menu' face. */
3540
3541static void
ebd15611 3542x_update_menu_appearance (struct frame *f)
c7ae3284 3543{
a03ad468 3544 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
bce72079 3545 XrmDatabase rdb;
178c5d9c 3546
bce72079
GM
3547 if (dpyinfo
3548 && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
3549 rdb != NULL))
c7ae3284 3550 {
bce72079 3551 char line[512];
670741ab
PE
3552 char *buf = line;
3553 ptrdiff_t bufsize = sizeof line;
bce72079
GM
3554 Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
3555 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
42a5b22f 3556 const char *myname = SSDATA (Vx_resource_name);
bce72079 3557 int changed_p = 0;
8ad582ac
GM
3558#ifdef USE_MOTIF
3559 const char *popup_path = "popup_menu";
3560#else
3561 const char *popup_path = "menu.popup";
3562#endif
177c0ea7 3563
bce72079
GM
3564 if (STRINGP (LFACE_FOREGROUND (lface)))
3565 {
670741ab
PE
3566 exprintf (&buf, &bufsize, line, -1, "%s.%s*foreground: %s",
3567 myname, popup_path,
3568 SDATA (LFACE_FOREGROUND (lface)));
bce72079 3569 XrmPutLineResource (&rdb, line);
670741ab
PE
3570 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s",
3571 myname, SDATA (LFACE_FOREGROUND (lface)));
bce72079
GM
3572 XrmPutLineResource (&rdb, line);
3573 changed_p = 1;
3574 }
178c5d9c 3575
bce72079
GM
3576 if (STRINGP (LFACE_BACKGROUND (lface)))
3577 {
670741ab
PE
3578 exprintf (&buf, &bufsize, line, -1, "%s.%s*background: %s",
3579 myname, popup_path,
3580 SDATA (LFACE_BACKGROUND (lface)));
bce72079 3581 XrmPutLineResource (&rdb, line);
670741ab
PE
3582
3583 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s",
3584 myname, SDATA (LFACE_BACKGROUND (lface)));
bce72079
GM
3585 XrmPutLineResource (&rdb, line);
3586 changed_p = 1;
3587 }
177c0ea7 3588
2dee4c0b 3589 if (face->font
23888717
CY
3590 /* On Solaris 5.8, it's been reported that the `menu' face
3591 can be unspecified here, during startup. Why this
3592 happens remains unknown. -- cyd */
3593 && FONTP (LFACE_FONT (lface))
bce72079 3594 && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
53aaf1e2 3595 || !UNSPECIFIEDP (LFACE_FOUNDRY (lface))
bce72079 3596 || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
bce72079
GM
3597 || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
3598 || !UNSPECIFIEDP (LFACE_SLANT (lface))
3599 || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
3600 {
47ae3723 3601 Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
a03ad468 3602#ifdef USE_MOTIF
bce72079 3603 const char *suffix = "List";
211f2210 3604 Bool motif = True;
a2d7e722
JD
3605#else
3606#if defined HAVE_X_I18N
3607
3608 const char *suffix = "Set";
a03ad468 3609#else
bce72079 3610 const char *suffix = "";
a2d7e722 3611#endif
211f2210 3612 Bool motif = False;
2defe37f 3613#endif
2dee4c0b
KH
3614
3615 if (! NILP (xlfd))
3616 {
211f2210 3617#if defined HAVE_X_I18N
42a5b22f 3618 char *fontsetname = xic_create_fontsetname (SSDATA (xlfd), motif);
2defe37f 3619#else
51b59d79 3620 char *fontsetname = SSDATA (xlfd);
bce72079 3621#endif
670741ab
PE
3622 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*font%s: %s",
3623 myname, suffix, fontsetname);
2dee4c0b 3624 XrmPutLineResource (&rdb, line);
670741ab
PE
3625
3626 exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s",
3627 myname, popup_path, suffix, fontsetname);
2dee4c0b
KH
3628 XrmPutLineResource (&rdb, line);
3629 changed_p = 1;
51b59d79 3630 if (fontsetname != SSDATA (xlfd))
2dee4c0b
KH
3631 xfree (fontsetname);
3632 }
bce72079 3633 }
c7ae3284 3634
bce72079 3635 if (changed_p && f->output_data.x->menubar_widget)
ac17f0bf 3636 free_frame_menubar (f);
670741ab
PE
3637
3638 if (buf != line)
3639 xfree (buf);
c7ae3284
GM
3640 }
3641}
3642
bce72079 3643#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
82641697
GM
3644
3645
177c0ea7 3646DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
cdfaafa9
MB
3647 Sface_attribute_relative_p,
3648 2, 2, 0,
2d6228e7
RS
3649 doc: /* Check whether a face attribute value is relative.
3650Specifically, this function returns t if the attribute ATTRIBUTE
3651with the value VALUE is relative.
3652
3653A relative value is one that doesn't entirely override whatever is
3654inherited from another face. For most possible attributes,
3655the only relative value that users see is `unspecified'.
3656However, for :height, floating point values are also relative. */)
5842a27b 3657 (Lisp_Object attribute, Lisp_Object value)
cdfaafa9 3658{
a3720aa2 3659 if (EQ (value, Qunspecified) || (EQ (value, QCignore_defface)))
cdfaafa9
MB
3660 return Qt;
3661 else if (EQ (attribute, QCheight))
3662 return INTEGERP (value) ? Qnil : Qt;
3663 else
3664 return Qnil;
3665}
3666
3667DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
3668 3, 3, 0,
3669 doc: /* Return face ATTRIBUTE VALUE1 merged with VALUE2.
3670If VALUE1 or VALUE2 are absolute (see `face-attribute-relative-p'), then
3671the result will be absolute, otherwise it will be relative. */)
5842a27b 3672 (Lisp_Object attribute, Lisp_Object value1, Lisp_Object value2)
cdfaafa9 3673{
a3720aa2 3674 if (EQ (value1, Qunspecified) || EQ (value1, QCignore_defface))
cdfaafa9
MB
3675 return value2;
3676 else if (EQ (attribute, QCheight))
e1e419ec 3677 return merge_face_heights (value1, value2, value1);
cdfaafa9
MB
3678 else
3679 return value1;
3680}
3681
82641697
GM
3682
3683DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
3684 Sinternal_get_lisp_face_attribute,
3685 2, 3, 0,
7ee72033 3686 doc: /* Return face attribute KEYWORD of face SYMBOL.
228299fa
GM
3687If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid
3688face attribute name, signal an error.
7fc92635
JB
3689If the optional argument FRAME is given, report on face SYMBOL in that
3690frame. If FRAME is t, report on the defaults for face SYMBOL (for new
7ee72033 3691frames). If FRAME is omitted or nil, use the selected frame. */)
5842a27b 3692 (Lisp_Object symbol, Lisp_Object keyword, Lisp_Object frame)
82641697
GM
3693{
3694 Lisp_Object lface, value = Qnil;
178c5d9c 3695
b7826503
PJ
3696 CHECK_SYMBOL (symbol);
3697 CHECK_SYMBOL (keyword);
82641697
GM
3698
3699 if (EQ (frame, Qt))
3700 lface = lface_from_face_name (NULL, symbol, 1);
3701 else
3702 {
3703 if (NILP (frame))
c0617987 3704 frame = selected_frame;
b7826503 3705 CHECK_LIVE_FRAME (frame);
82641697
GM
3706 lface = lface_from_face_name (XFRAME (frame), symbol, 1);
3707 }
3708
3709 if (EQ (keyword, QCfamily))
3710 value = LFACE_FAMILY (lface);
53aaf1e2
KH
3711 else if (EQ (keyword, QCfoundry))
3712 value = LFACE_FOUNDRY (lface);
82641697
GM
3713 else if (EQ (keyword, QCheight))
3714 value = LFACE_HEIGHT (lface);
3715 else if (EQ (keyword, QCweight))
3716 value = LFACE_WEIGHT (lface);
3717 else if (EQ (keyword, QCslant))
3718 value = LFACE_SLANT (lface);
3719 else if (EQ (keyword, QCunderline))
3720 value = LFACE_UNDERLINE (lface);
3721 else if (EQ (keyword, QCoverline))
3722 value = LFACE_OVERLINE (lface);
3723 else if (EQ (keyword, QCstrike_through))
3724 value = LFACE_STRIKE_THROUGH (lface);
3725 else if (EQ (keyword, QCbox))
3726 value = LFACE_BOX (lface);
3727 else if (EQ (keyword, QCinverse_video)
3728 || EQ (keyword, QCreverse_video))
3729 value = LFACE_INVERSE (lface);
3730 else if (EQ (keyword, QCforeground))
3731 value = LFACE_FOREGROUND (lface);
3732 else if (EQ (keyword, QCbackground))
3733 value = LFACE_BACKGROUND (lface);
3734 else if (EQ (keyword, QCstipple))
3735 value = LFACE_STIPPLE (lface);
3736 else if (EQ (keyword, QCwidth))
3737 value = LFACE_SWIDTH (lface);
2c20458f
MB
3738 else if (EQ (keyword, QCinherit))
3739 value = LFACE_INHERIT (lface);
39506348
KH
3740 else if (EQ (keyword, QCfont))
3741 value = LFACE_FONT (lface);
763bc839
KH
3742 else if (EQ (keyword, QCfontset))
3743 value = LFACE_FONTSET (lface);
82641697
GM
3744 else
3745 signal_error ("Invalid face attribute name", keyword);
3746
0268cef3
CY
3747 if (IGNORE_DEFFACE_P (value))
3748 return Qunspecified;
3749
82641697
GM
3750 return value;
3751}
3752
3753
3754DEFUN ("internal-lisp-face-attribute-values",
3755 Finternal_lisp_face_attribute_values,
3756 Sinternal_lisp_face_attribute_values, 1, 1, 0,
7ee72033
MB
3757 doc: /* Return a list of valid discrete values for face attribute ATTR.
3758Value is nil if ATTR doesn't have a discrete set of valid values. */)
5842a27b 3759 (Lisp_Object attr)
82641697
GM
3760{
3761 Lisp_Object result = Qnil;
178c5d9c 3762
b7826503 3763 CHECK_SYMBOL (attr);
178c5d9c 3764
2dee4c0b 3765 if (EQ (attr, QCunderline))
82641697
GM
3766 result = Fcons (Qt, Fcons (Qnil, Qnil));
3767 else if (EQ (attr, QCoverline))
3768 result = Fcons (Qt, Fcons (Qnil, Qnil));
3769 else if (EQ (attr, QCstrike_through))
3770 result = Fcons (Qt, Fcons (Qnil, Qnil));
3771 else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video))
3772 result = Fcons (Qt, Fcons (Qnil, Qnil));
3773
3774 return result;
3775}
178c5d9c 3776
82641697
GM
3777
3778DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
178c5d9c 3779 Sinternal_merge_in_global_face, 2, 2, 0,
e3cd9e7f 3780 doc: /* Add attributes from frame-default definition of FACE to FACE on FRAME.
7ee72033 3781Default face attributes override any local face attributes. */)
5842a27b 3782 (Lisp_Object face, Lisp_Object frame)
82641697 3783{
aad40737
MB
3784 int i;
3785 Lisp_Object global_lface, local_lface, *gvec, *lvec;
8d3810fd 3786 struct frame *f = XFRAME (frame);
aad40737 3787
b7826503 3788 CHECK_LIVE_FRAME (frame);
82641697 3789 global_lface = lface_from_face_name (NULL, face, 1);
8d3810fd 3790 local_lface = lface_from_face_name (f, face, 0);
82641697
GM
3791 if (NILP (local_lface))
3792 local_lface = Finternal_make_lisp_face (face, frame);
aad40737 3793
cec33c90
SM
3794 /* Make every specified global attribute override the local one.
3795 BEWARE!! This is only used from `face-set-after-frame-default' where
3796 the local frame is defined from default specs in `face-defface-spec'
3797 and those should be overridden by global settings. Hence the strange
3798 "global before local" priority. */
aad40737
MB
3799 lvec = XVECTOR (local_lface)->contents;
3800 gvec = XVECTOR (global_lface)->contents;
3801 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
8d3810fd
CY
3802 if (IGNORE_DEFFACE_P (gvec[i]))
3803 lvec[i] = Qunspecified;
3804 else if (! UNSPECIFIEDP (gvec[i]))
3805 lvec[i] = gvec[i];
3806
fa9fa316 3807 /* If the default face was changed, update the face cache and the
811029d3 3808 `font' frame parameter. */
8d3810fd
CY
3809 if (EQ (face, Qdefault))
3810 {
3811 struct face_cache *c = FRAME_FACE_CACHE (f);
3812 struct face *newface, *oldface = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3813 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3814
0421a7a7
CY
3815 /* This can be NULL (e.g., in batch mode). */
3816 if (oldface)
8d3810fd 3817 {
fa9fa316
CY
3818 /* Ensure that the face vector is fully specified by merging
3819 the previously-cached vector. */
72af86bd 3820 memcpy (attrs, oldface->lface, sizeof attrs);
0421a7a7 3821 merge_face_vectors (f, lvec, attrs, 0);
72af86bd 3822 memcpy (lvec, attrs, sizeof attrs);
fa9fa316 3823 newface = realize_face (c, lvec, DEFAULT_FACE_ID);
0421a7a7
CY
3824
3825 if ((! UNSPECIFIEDP (gvec[LFACE_FAMILY_INDEX])
3826 || ! UNSPECIFIEDP (gvec[LFACE_FOUNDRY_INDEX])
3827 || ! UNSPECIFIEDP (gvec[LFACE_HEIGHT_INDEX])
3828 || ! UNSPECIFIEDP (gvec[LFACE_WEIGHT_INDEX])
3829 || ! UNSPECIFIEDP (gvec[LFACE_SLANT_INDEX])
3830 || ! UNSPECIFIEDP (gvec[LFACE_SWIDTH_INDEX])
3831 || ! UNSPECIFIEDP (gvec[LFACE_FONT_INDEX]))
3832 && newface->font)
3833 {
3834 Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
3835 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, name),
3836 Qnil));
3837 }
1485f4c0
CY
3838
3839 if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
3840 Fmodify_frame_parameters (frame,
3841 Fcons (Fcons (Qforeground_color,
3842 gvec[LFACE_FOREGROUND_INDEX]),
3843 Qnil));
3844
3845 if (STRINGP (gvec[LFACE_BACKGROUND_INDEX]))
3846 Fmodify_frame_parameters (frame,
3847 Fcons (Fcons (Qbackground_color,
3848 gvec[LFACE_BACKGROUND_INDEX]),
3849 Qnil));
8d3810fd
CY
3850 }
3851 }
334a2e2a
GM
3852
3853 return Qnil;
82641697
GM
3854}
3855
3856
3857/* The following function is implemented for compatibility with 20.2.
3858 The function is used in x-resolve-fonts when it is asked to
3859 return fonts with the same size as the font of a face. This is
3860 done in fontset.el. */
3861
2db4bfe5 3862DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
e3cd9e7f 3863 doc: /* Return the font name of face FACE, or nil if it is unspecified.
2db4bfe5 3864The font name is, by default, for ASCII characters.
228299fa
GM
3865If the optional argument FRAME is given, report on face FACE in that frame.
3866If FRAME is t, report on the defaults for face FACE (for new frames).
3867 The font default for a face is either nil, or a list
3868 of the form (bold), (italic) or (bold italic).
2db4bfe5
KH
3869If FRAME is omitted or nil, use the selected frame. And, in this case,
3870if the optional third argument CHARACTER is given,
3871return the font name used for CHARACTER. */)
5842a27b 3872 (Lisp_Object face, Lisp_Object frame, Lisp_Object character)
82641697
GM
3873{
3874 if (EQ (frame, Qt))
3875 {
3876 Lisp_Object result = Qnil;
3877 Lisp_Object lface = lface_from_face_name (NULL, face, 1);
3878
3879 if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
3880 && !EQ (LFACE_WEIGHT (lface), Qnormal))
3881 result = Fcons (Qbold, result);
178c5d9c 3882
0f2c6573 3883 if (!UNSPECIFIEDP (LFACE_SLANT (lface))
82641697
GM
3884 && !EQ (LFACE_SLANT (lface), Qnormal))
3885 result = Fcons (Qitalic, result);
178c5d9c 3886
82641697
GM
3887 return result;
3888 }
3889 else
3890 {
3891 struct frame *f = frame_or_selected_frame (frame, 1);
000fc2b1 3892 int face_id = lookup_named_face (f, face, 1);
071048a3 3893 struct face *fface = FACE_FROM_ID (f, face_id);
2db4bfe5 3894
071048a3 3895 if (! fface)
2db4bfe5 3896 return Qnil;
a1a552b3 3897#ifdef HAVE_WINDOW_SYSTEM
75dad34a 3898 if (FRAME_WINDOW_P (f) && !NILP (character))
a1a552b3
KH
3899 {
3900 CHECK_CHARACTER (character);
071048a3
PE
3901 face_id = FACE_FOR_CHAR (f, fface, XINT (character), -1, Qnil);
3902 fface = FACE_FROM_ID (f, face_id);
a1a552b3 3903 }
071048a3
PE
3904 return (fface->font
3905 ? fface->font->props[FONT_NAME_INDEX]
2dee4c0b 3906 : Qnil);
1ccdfd33
EZ
3907#else /* !HAVE_WINDOW_SYSTEM */
3908 return build_string (FRAME_MSDOS_P (f)
3909 ? "ms-dos"
3910 : FRAME_W32_P (f) ? "w32term"
3911 :"tty");
3912#endif
82641697
GM
3913 }
3914}
3915
3916
9717e36c 3917/* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
82641697
GM
3918 all attributes are `equal'. Tries to be fast because this function
3919 is called quite often. */
3920
55d4c1b2 3921static inline int
971de7fb 3922face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
82641697 3923{
9717e36c
MB
3924 /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
3925 and the other is specified. */
3926 if (XTYPE (v1) != XTYPE (v2))
3927 return 0;
82641697 3928
9717e36c
MB
3929 if (EQ (v1, v2))
3930 return 1;
82641697 3931
9717e36c
MB
3932 switch (XTYPE (v1))
3933 {
3934 case Lisp_String:
3935 if (SBYTES (v1) != SBYTES (v2))
3936 return 0;
82641697 3937
72af86bd 3938 return memcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
178c5d9c 3939
2de9f71c 3940 case_Lisp_Int:
9717e36c
MB
3941 case Lisp_Symbol:
3942 return 0;
178c5d9c 3943
9717e36c
MB
3944 default:
3945 return !NILP (Fequal (v1, v2));
82641697 3946 }
9717e36c
MB
3947}
3948
3949
3950/* Compare face vectors V1 and V2 for equality. Value is non-zero if
3951 all attributes are `equal'. Tries to be fast because this function
3952 is called quite often. */
3953
55d4c1b2 3954static inline int
971de7fb 3955lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
9717e36c
MB
3956{
3957 int i, equal_p = 1;
3958
3959 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
3960 equal_p = face_attr_equal_p (v1[i], v2[i]);
178c5d9c 3961
82641697
GM
3962 return equal_p;
3963}
3964
3965
3966DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
3967 Sinternal_lisp_face_equal_p, 2, 3, 0,
7ee72033 3968 doc: /* True if FACE1 and FACE2 are equal.
03f11322
JB
3969If the optional argument FRAME is given, report on FACE1 and FACE2 in that frame.
3970If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames).
7ee72033 3971If FRAME is omitted or nil, use the selected frame. */)
5842a27b 3972 (Lisp_Object face1, Lisp_Object face2, Lisp_Object frame)
82641697
GM
3973{
3974 int equal_p;
7b953c9c 3975 struct frame *f;
82641697 3976 Lisp_Object lface1, lface2;
178c5d9c 3977
7b953c9c
MB
3978 if (EQ (frame, Qt))
3979 f = NULL;
3980 else
3981 /* Don't use check_x_frame here because this function is called
3982 before X frames exist. At that time, if FRAME is nil,
3983 selected_frame will be used which is the frame dumped with
3984 Emacs. That frame is not an X frame. */
3985 f = frame_or_selected_frame (frame, 2);
3986
03f11322
JB
3987 lface1 = lface_from_face_name (f, face1, 1);
3988 lface2 = lface_from_face_name (f, face2, 1);
82641697
GM
3989 equal_p = lface_equal_p (XVECTOR (lface1)->contents,
3990 XVECTOR (lface2)->contents);
3991 return equal_p ? Qt : Qnil;
3992}
3993
178c5d9c 3994
82641697
GM
3995DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
3996 Sinternal_lisp_face_empty_p, 1, 2, 0,
7ee72033 3997 doc: /* True if FACE has no attribute specified.
228299fa
GM
3998If the optional argument FRAME is given, report on face FACE in that frame.
3999If FRAME is t, report on the defaults for face FACE (for new frames).
7ee72033 4000If FRAME is omitted or nil, use the selected frame. */)
5842a27b 4001 (Lisp_Object face, Lisp_Object frame)
82641697
GM
4002{
4003 struct frame *f;
4004 Lisp_Object lface;
4005 int i;
4006
4007 if (NILP (frame))
c0617987 4008 frame = selected_frame;
b7826503 4009 CHECK_LIVE_FRAME (frame);
c0617987 4010 f = XFRAME (frame);
178c5d9c 4011
82641697
GM
4012 if (EQ (frame, Qt))
4013 lface = lface_from_face_name (NULL, face, 1);
4014 else
4015 lface = lface_from_face_name (f, face, 1);
4016
4017 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
a08332c0 4018 if (!UNSPECIFIEDP (AREF (lface, i)))
82641697 4019 break;
178c5d9c 4020
82641697
GM
4021 return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
4022}
4023
4024
4025DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
178c5d9c 4026 0, 1, 0,
7ee72033
MB
4027 doc: /* Return an alist of frame-local faces defined on FRAME.
4028For internal use only. */)
5842a27b 4029 (Lisp_Object frame)
82641697
GM
4030{
4031 struct frame *f = frame_or_selected_frame (frame, 0);
4032 return f->face_alist;
4033}
4034
4035
4036/* Return a hash code for Lisp string STRING with case ignored. Used
4037 below in computing a hash value for a Lisp face. */
4038
55d4c1b2 4039static inline unsigned
971de7fb 4040hash_string_case_insensitive (Lisp_Object string)
82641697 4041{
53c208f6 4042 const unsigned char *s;
82641697
GM
4043 unsigned hash = 0;
4044 xassert (STRINGP (string));
d5db4077 4045 for (s = SDATA (string); *s; ++s)
82641697
GM
4046 hash = (hash << 1) ^ tolower (*s);
4047 return hash;
4048}
4049
4050
4051/* Return a hash code for face attribute vector V. */
4052
55d4c1b2 4053static inline unsigned
971de7fb 4054lface_hash (Lisp_Object *v)
82641697
GM
4055{
4056 return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
53aaf1e2 4057 ^ hash_string_case_insensitive (v[LFACE_FOUNDRY_INDEX])
82641697
GM
4058 ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
4059 ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
a2bc5bdd
SM
4060 ^ XHASH (v[LFACE_WEIGHT_INDEX])
4061 ^ XHASH (v[LFACE_SLANT_INDEX])
4062 ^ XHASH (v[LFACE_SWIDTH_INDEX])
4063 ^ XHASH (v[LFACE_HEIGHT_INDEX]));
82641697
GM
4064}
4065
4066
4067/* Return non-zero if LFACE1 and LFACE2 specify the same font (without
4068 considering charsets/registries). They do if they specify the same
2dee4c0b 4069 family, point size, weight, width, slant, and font. Both
763bc839 4070 LFACE1 and LFACE2 must be fully-specified. */
82641697 4071
55d4c1b2 4072static inline int
971de7fb 4073lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
82641697
GM
4074{
4075 xassert (lface_fully_specified_p (lface1)
4076 && lface_fully_specified_p (lface2));
25a48bd0 4077 return (xstrcasecmp (SSDATA (lface1[LFACE_FAMILY_INDEX]),
b5f03016 4078 SSDATA (lface2[LFACE_FAMILY_INDEX])) == 0
25a48bd0
PE
4079 && xstrcasecmp (SSDATA (lface1[LFACE_FOUNDRY_INDEX]),
4080 SSDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
2c20458f 4081 && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
82641697
GM
4082 && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
4083 && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
39506348 4084 && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
2dee4c0b 4085 && EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
763bc839
KH
4086 && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
4087 || (STRINGP (lface1[LFACE_FONTSET_INDEX])
4088 && STRINGP (lface2[LFACE_FONTSET_INDEX])
25a48bd0 4089 && ! xstrcasecmp (SSDATA (lface1[LFACE_FONTSET_INDEX]),
b5f03016 4090 SSDATA (lface2[LFACE_FONTSET_INDEX]))))
763bc839 4091 );
82641697
GM
4092}
4093
4094
4095\f
4096/***********************************************************************
4097 Realized Faces
4098 ***********************************************************************/
4099
4100/* Allocate and return a new realized face for Lisp face attribute
39506348 4101 vector ATTR. */
82641697
GM
4102
4103static struct face *
971de7fb 4104make_realized_face (Lisp_Object *attr)
82641697
GM
4105{
4106 struct face *face = (struct face *) xmalloc (sizeof *face);
72af86bd 4107 memset (face, 0, sizeof *face);
39506348 4108 face->ascii_face = face;
72af86bd 4109 memcpy (face->lface, attr, sizeof face->lface);
82641697
GM
4110 return face;
4111}
4112
4113
4114/* Free realized face FACE, including its X resources. FACE may
4115 be null. */
4116
435f4c28 4117static void
971de7fb 4118free_realized_face (struct frame *f, struct face *face)
82641697
GM
4119{
4120 if (face)
4121 {
c3cee013
JR
4122#ifdef HAVE_WINDOW_SYSTEM
4123 if (FRAME_WINDOW_P (f))
82641697 4124 {
39506348
KH
4125 /* Free fontset of FACE if it is ASCII face. */
4126 if (face->fontset >= 0 && face == face->ascii_face)
4127 free_face_fontset (f, face);
82641697
GM
4128 if (face->gc)
4129 {
985773c9 4130 BLOCK_INPUT;
2dee4c0b 4131 if (face->font)
426b2119 4132 font_done_for_face (f, face);
82641697
GM
4133 x_free_gc (f, face->gc);
4134 face->gc = 0;
ed0c79c6 4135 UNBLOCK_INPUT;
82641697 4136 }
178c5d9c 4137
82641697
GM
4138 free_face_colors (f, face);
4139 x_destroy_bitmap (f, face->stipple);
4140 }
c3cee013 4141#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
4142
4143 xfree (face);
4144 }
4145}
4146
4147
4148/* Prepare face FACE for subsequent display on frame F. This
4149 allocated GCs if they haven't been allocated yet or have been freed
4150 by clearing the face cache. */
4151
4152void
971de7fb 4153prepare_face_for_display (struct frame *f, struct face *face)
82641697 4154{
c3cee013
JR
4155#ifdef HAVE_WINDOW_SYSTEM
4156 xassert (FRAME_WINDOW_P (f));
178c5d9c 4157
82641697
GM
4158 if (face->gc == 0)
4159 {
4160 XGCValues xgcv;
4161 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
4162
4163 xgcv.foreground = face->foreground;
4164 xgcv.background = face->background;
c3cee013 4165#ifdef HAVE_X_WINDOWS
82641697 4166 xgcv.graphics_exposures = False;
c3cee013 4167#endif
82641697
GM
4168
4169 BLOCK_INPUT;
c3cee013 4170#ifdef HAVE_X_WINDOWS
82641697
GM
4171 if (face->stipple)
4172 {
be8a72f4 4173 xgcv.fill_style = FillOpaqueStippled;
82641697
GM
4174 xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
4175 mask |= GCFillStyle | GCStipple;
4176 }
c3cee013 4177#endif
82641697 4178 face->gc = x_create_gc (f, mask, &xgcv);
2dee4c0b 4179 if (face->font)
426b2119 4180 font_prepare_for_face (f, face);
82641697
GM
4181 UNBLOCK_INPUT;
4182 }
c3cee013 4183#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
4184}
4185
82641697 4186\f
b35df831
MB
4187/* Returns the `distance' between the colors X and Y. */
4188
4189static int
971de7fb 4190color_distance (XColor *x, XColor *y)
b35df831 4191{
da6062e6 4192 /* This formula is from a paper titled `Colour metric' by Thiadmer Riemersma.
b35df831
MB
4193 Quoting from that paper:
4194
b5f03016
AS
4195 This formula has results that are very close to L*u*v* (with the
4196 modified lightness curve) and, more importantly, it is a more even
da6062e6 4197 algorithm: it does not have a range of colors where it suddenly
b5f03016 4198 gives far from optimal results.
b35df831
MB
4199
4200 See <http://www.compuphase.com/cmetric.htm> for more info. */
4201
4202 long r = (x->red - y->red) >> 8;
4203 long g = (x->green - y->green) >> 8;
4204 long b = (x->blue - y->blue) >> 8;
4205 long r_mean = (x->red + y->red) >> 9;
4206
4207 return
4208 (((512 + r_mean) * r * r) >> 8)
4209 + 4 * g * g
4210 + (((767 - r_mean) * b * b) >> 8);
4211}
4212
4213
4214DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 3, 0,
4215 doc: /* Return an integer distance between COLOR1 and COLOR2 on FRAME.
4216COLOR1 and COLOR2 may be either strings containing the color name,
4217or lists of the form (RED GREEN BLUE).
4218If FRAME is unspecified or nil, the current frame is used. */)
5842a27b 4219 (Lisp_Object color1, Lisp_Object color2, Lisp_Object frame)
b35df831
MB
4220{
4221 struct frame *f;
4222 XColor cdef1, cdef2;
4223
4224 if (NILP (frame))
4225 frame = selected_frame;
4226 CHECK_LIVE_FRAME (frame);
4227 f = XFRAME (frame);
4228
6c8e1d62 4229 if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
42a5b22f 4230 && !(STRINGP (color1) && defined_color (f, SSDATA (color1), &cdef1, 0)))
b35df831 4231 signal_error ("Invalid color", color1);
6c8e1d62 4232 if (!(CONSP (color2) && parse_rgb_list (color2, &cdef2))
42a5b22f 4233 && !(STRINGP (color2) && defined_color (f, SSDATA (color2), &cdef2, 0)))
b35df831
MB
4234 signal_error ("Invalid color", color2);
4235
4236 return make_number (color_distance (&cdef1, &cdef2));
4237}
4238
4239\f
82641697
GM
4240/***********************************************************************
4241 Face Cache
4242 ***********************************************************************/
4243
4244/* Return a new face cache for frame F. */
4245
4246static struct face_cache *
971de7fb 4247make_face_cache (struct frame *f)
82641697
GM
4248{
4249 struct face_cache *c;
4250 int size;
4251
4252 c = (struct face_cache *) xmalloc (sizeof *c);
72af86bd 4253 memset (c, 0, sizeof *c);
82641697
GM
4254 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4255 c->buckets = (struct face **) xmalloc (size);
72af86bd 4256 memset (c->buckets, 0, size);
82641697
GM
4257 c->size = 50;
4258 c->faces_by_id = (struct face **) xmalloc (c->size * sizeof *c->faces_by_id);
4259 c->f = f;
ceeda019 4260 c->menu_face_changed_p = menu_face_changed_default;
82641697
GM
4261 return c;
4262}
4263
4264
4265/* Clear out all graphics contexts for all realized faces, except for
4266 the basic faces. This should be done from time to time just to avoid
4267 keeping too many graphics contexts that are no longer needed. */
4268
4269static void
971de7fb 4270clear_face_gcs (struct face_cache *c)
82641697 4271{
c3cee013 4272 if (c && FRAME_WINDOW_P (c->f))
82641697 4273 {
c3cee013 4274#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
4275 int i;
4276 for (i = BASIC_FACE_ID_SENTINEL; i < c->used; ++i)
4277 {
4278 struct face *face = c->faces_by_id[i];
4279 if (face && face->gc)
4280 {
985773c9 4281 BLOCK_INPUT;
2dee4c0b 4282 if (face->font)
426b2119 4283 font_done_for_face (c->f, face);
82641697
GM
4284 x_free_gc (c->f, face->gc);
4285 face->gc = 0;
ed0c79c6 4286 UNBLOCK_INPUT;
82641697
GM
4287 }
4288 }
c3cee013 4289#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
4290 }
4291}
4292
4293
7fc92635
JB
4294/* Free all realized faces in face cache C, including basic faces.
4295 C may be null. If faces are freed, make sure the frame's current
82641697
GM
4296 matrix is marked invalid, so that a display caused by an expose
4297 event doesn't try to use faces we destroyed. */
4298
4299static void
971de7fb 4300free_realized_faces (struct face_cache *c)
82641697
GM
4301{
4302 if (c && c->used)
4303 {
4304 int i, size;
4305 struct frame *f = c->f;
4306
84ec3b4b
GM
4307 /* We must block input here because we can't process X events
4308 safely while only some faces are freed, or when the frame's
4309 current matrix still references freed faces. */
4310 BLOCK_INPUT;
4311
82641697
GM
4312 for (i = 0; i < c->used; ++i)
4313 {
4314 free_realized_face (f, c->faces_by_id[i]);
4315 c->faces_by_id[i] = NULL;
4316 }
178c5d9c 4317
82641697
GM
4318 c->used = 0;
4319 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
72af86bd 4320 memset (c->buckets, 0, size);
82641697
GM
4321
4322 /* Must do a thorough redisplay the next time. Mark current
4323 matrices as invalid because they will reference faces freed
4324 above. This function is also called when a frame is
4325 destroyed. In this case, the root window of F is nil. */
4326 if (WINDOWP (f->root_window))
4327 {
4328 clear_current_matrices (f);
4329 ++windows_or_buffers_changed;
4330 }
84ec3b4b
GM
4331
4332 UNBLOCK_INPUT;
82641697
GM
4333 }
4334}
4335
4336
4337/* Free all realized faces on FRAME or on all frames if FRAME is nil.
4338 This is done after attributes of a named face have been changed,
4339 because we can't tell which realized faces depend on that face. */
4340
4341void
971de7fb 4342free_all_realized_faces (Lisp_Object frame)
82641697
GM
4343{
4344 if (NILP (frame))
4345 {
4346 Lisp_Object rest;
4347 FOR_EACH_FRAME (rest, frame)
4348 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4349 }
4350 else
4351 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4352}
4353
4354
4355/* Free face cache C and faces in it, including their X resources. */
4356
4357static void
971de7fb 4358free_face_cache (struct face_cache *c)
82641697
GM
4359{
4360 if (c)
4361 {
4362 free_realized_faces (c);
4363 xfree (c->buckets);
4364 xfree (c->faces_by_id);
4365 xfree (c);
4366 }
4367}
4368
4369
4370/* Cache realized face FACE in face cache C. HASH is the hash value
af53b43c
KH
4371 of FACE. If FACE is for ASCII characters (i.e. FACE->ascii_face ==
4372 FACE), insert the new face to the beginning of the collision list
4373 of the face hash table of C. Otherwise, add the new face to the
4374 end of the collision list. This way, lookup_face can quickly find
4375 that a requested face is not cached. */
82641697
GM
4376
4377static void
971de7fb 4378cache_face (struct face_cache *c, struct face *face, unsigned int hash)
82641697
GM
4379{
4380 int i = hash % FACE_CACHE_BUCKETS_SIZE;
4381
4382 face->hash = hash;
4383
af53b43c 4384 if (face->ascii_face != face)
82641697
GM
4385 {
4386 struct face *last = c->buckets[i];
4387 if (last)
4388 {
4389 while (last->next)
4390 last = last->next;
4391 last->next = face;
4392 face->prev = last;
4393 face->next = NULL;
4394 }
4395 else
4396 {
4397 c->buckets[i] = face;
4398 face->prev = face->next = NULL;
4399 }
4400 }
4401 else
4402 {
4403 face->prev = NULL;
4404 face->next = c->buckets[i];
4405 if (face->next)
4406 face->next->prev = face;
4407 c->buckets[i] = face;
4408 }
4409
4410 /* Find a free slot in C->faces_by_id and use the index of the free
4411 slot as FACE->id. */
4412 for (i = 0; i < c->used; ++i)
4413 if (c->faces_by_id[i] == NULL)
4414 break;
4415 face->id = i;
178c5d9c 4416
85fece3e
PE
4417#if GLYPH_DEBUG
4418 /* Check that FACE got a unique id. */
4419 {
4420 int j, n;
4421 struct face *face1;
4422
4423 for (j = n = 0; j < FACE_CACHE_BUCKETS_SIZE; ++j)
4424 for (face1 = c->buckets[j]; face1; face1 = face1->next)
4425 if (face1->id == i)
4426 ++n;
4427
4428 xassert (n == 1);
4429 }
4430#endif /* GLYPH_DEBUG */
4431
82641697 4432 /* Maybe enlarge C->faces_by_id. */
6b61353c 4433 if (i == c->used)
82641697 4434 {
6b61353c 4435 if (c->used == c->size)
0065d054
PE
4436 c->faces_by_id = xpalloc (c->faces_by_id, &c->size, 1, MAX_FACE_ID,
4437 sizeof *c->faces_by_id);
6b61353c 4438 c->used++;
82641697
GM
4439 }
4440
82641697 4441 c->faces_by_id[i] = face;
82641697
GM
4442}
4443
4444
4445/* Remove face FACE from cache C. */
4446
4447static void
971de7fb 4448uncache_face (struct face_cache *c, struct face *face)
82641697
GM
4449{
4450 int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
178c5d9c 4451
82641697
GM
4452 if (face->prev)
4453 face->prev->next = face->next;
4454 else
4455 c->buckets[i] = face->next;
178c5d9c 4456
82641697
GM
4457 if (face->next)
4458 face->next->prev = face->prev;
178c5d9c 4459
82641697
GM
4460 c->faces_by_id[face->id] = NULL;
4461 if (face->id == c->used)
4462 --c->used;
4463}
4464
4465
4466/* Look up a realized face with face attributes ATTR in the face cache
af53b43c
KH
4467 of frame F. The face will be used to display ASCII characters.
4468 Value is the ID of the face found. If no suitable face is found,
4469 realize a new one. */
82641697 4470
55d4c1b2 4471static inline int
971de7fb 4472lookup_face (struct frame *f, Lisp_Object *attr)
82641697 4473{
39506348 4474 struct face_cache *cache = FRAME_FACE_CACHE (f);
82641697
GM
4475 unsigned hash;
4476 int i;
4477 struct face *face;
4478
39506348 4479 xassert (cache != NULL);
82641697
GM
4480 check_lface_attrs (attr);
4481
4482 /* Look up ATTR in the face cache. */
4483 hash = lface_hash (attr);
4484 i = hash % FACE_CACHE_BUCKETS_SIZE;
178c5d9c 4485
39506348 4486 for (face = cache->buckets[i]; face; face = face->next)
af53b43c
KH
4487 {
4488 if (face->ascii_face != face)
4489 {
4490 /* There's no more ASCII face. */
4491 face = NULL;
4492 break;
4493 }
4494 if (face->hash == hash
4495 && lface_equal_p (face->lface, attr))
4496 break;
4497 }
82641697
GM
4498
4499 /* If not found, realize a new face. */
4500 if (face == NULL)
af53b43c 4501 face = realize_face (cache, attr, -1);
82641697
GM
4502
4503#if GLYPH_DEBUG
4504 xassert (face == FACE_FROM_ID (f, face->id));
82641697 4505#endif /* GLYPH_DEBUG */
178c5d9c 4506
82641697
GM
4507 return face->id;
4508}
4509
2dee4c0b
KH
4510#ifdef HAVE_WINDOW_SYSTEM
4511/* Look up a realized face that has the same attributes as BASE_FACE
4512 except for the font in the face cache of frame F. If FONT-OBJECT
4513 is not nil, it is an already opened font. If FONT-OBJECT is nil,
4514 the face has no font. Value is the ID of the face found. If no
4515 suitable face is found, realize a new one. */
426b2119 4516
426b2119 4517int
971de7fb 4518face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
426b2119
KH
4519{
4520 struct face_cache *cache = FRAME_FACE_CACHE (f);
4521 unsigned hash;
4522 int i;
4523 struct face *face;
4524
4525 xassert (cache != NULL);
4526 base_face = base_face->ascii_face;
4527 hash = lface_hash (base_face->lface);
4528 i = hash % FACE_CACHE_BUCKETS_SIZE;
4529
4530 for (face = cache->buckets[i]; face; face = face->next)
4531 {
4532 if (face->ascii_face == face)
4533 continue;
4534 if (face->ascii_face == base_face
2dee4c0b
KH
4535 && face->font == (NILP (font_object) ? NULL
4536 : XFONT_OBJECT (font_object))
4537 && lface_equal_p (face->lface, base_face->lface))
426b2119
KH
4538 return face->id;
4539 }
4540
4541 /* If not found, realize a new face. */
2dee4c0b 4542 face = realize_non_ascii_face (f, font_object, base_face);
426b2119
KH
4543 return face->id;
4544}
8c6204de 4545#endif /* HAVE_WINDOW_SYSTEM */
82641697 4546
82641697 4547/* Return the face id of the realized face for named face SYMBOL on
af53b43c
KH
4548 frame F suitable for displaying ASCII characters. Value is -1 if
4549 the face couldn't be determined, which might happen if the default
4550 face isn't realized and cannot be realized. */
82641697
GM
4551
4552int
971de7fb 4553lookup_named_face (struct frame *f, Lisp_Object symbol, int signal_p)
82641697 4554{
e7d7fd8c
MB
4555 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4556 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
82641697
GM
4557 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4558
b5de343d
GM
4559 if (default_face == NULL)
4560 {
4561 if (!realize_basic_faces (f))
4562 return -1;
4563 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
418ca4d2
RS
4564 if (default_face == NULL)
4565 abort (); /* realize_basic_faces must have set it up */
b5de343d
GM
4566 }
4567
f2cec7a9 4568 if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
2272e967
KS
4569 return -1;
4570
72af86bd 4571 memcpy (attrs, default_face->lface, sizeof attrs);
e7d7fd8c 4572 merge_face_vectors (f, symbol_attrs, attrs, 0);
a0a23346 4573
af53b43c 4574 return lookup_face (f, attrs);
82641697
GM
4575}
4576
4577
f2cec7a9
MB
4578/* Return the display face-id of the basic face who's canonical face-id
4579 is FACE_ID. The return value will usually simply be FACE_ID, unless that
4580 basic face has bee remapped via Vface_remapping_alist. This function is
4581 conservative: if something goes wrong, it will simply return FACE_ID
4582 rather than signal an error. */
4583
4584int
971de7fb 4585lookup_basic_face (struct frame *f, int face_id)
f2cec7a9
MB
4586{
4587 Lisp_Object name, mapping;
4588 int remapped_face_id;
4589
4590 if (NILP (Vface_remapping_alist))
4591 return face_id; /* Nothing to do. */
4592
4593 switch (face_id)
4594 {
4595 case DEFAULT_FACE_ID: name = Qdefault; break;
4596 case MODE_LINE_FACE_ID: name = Qmode_line; break;
4597 case MODE_LINE_INACTIVE_FACE_ID: name = Qmode_line_inactive; break;
4598 case HEADER_LINE_FACE_ID: name = Qheader_line; break;
4599 case TOOL_BAR_FACE_ID: name = Qtool_bar; break;
4600 case FRINGE_FACE_ID: name = Qfringe; break;
4601 case SCROLL_BAR_FACE_ID: name = Qscroll_bar; break;
4602 case BORDER_FACE_ID: name = Qborder; break;
4603 case CURSOR_FACE_ID: name = Qcursor; break;
4604 case MOUSE_FACE_ID: name = Qmouse; break;
4605 case MENU_FACE_ID: name = Qmenu; break;
4606
4607 default:
4608 abort (); /* the caller is supposed to pass us a basic face id */
4609 }
4610
4611 /* Do a quick scan through Vface_remapping_alist, and return immediately
4612 if there is no remapping for face NAME. This is just an optimization
4613 for the very common no-remapping case. */
4614 mapping = assq_no_quit (name, Vface_remapping_alist);
4615 if (NILP (mapping))
4616 return face_id; /* Give up. */
4617
4618 /* If there is a remapping entry, lookup the face using NAME, which will
4619 handle the remapping too. */
4620 remapped_face_id = lookup_named_face (f, name, 0);
4621 if (remapped_face_id < 0)
4622 return face_id; /* Give up. */
4623
4624 return remapped_face_id;
4625}
4626
4627
82641697
GM
4628/* Return a face for charset ASCII that is like the face with id
4629 FACE_ID on frame F, but has a font that is STEPS steps smaller.
4630 STEPS < 0 means larger. Value is the id of the face. */
4631
4632int
971de7fb 4633smaller_face (struct frame *f, int face_id, int steps)
39506348 4634{
c3cee013 4635#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
4636 struct face *face;
4637 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4638 int pt, last_pt, last_height;
4639 int delta;
4640 int new_face_id;
4641 struct face *new_face;
4642
4643 /* If not called for an X frame, just return the original face. */
4644 if (FRAME_TERMCAP_P (f))
4645 return face_id;
4646
4647 /* Try in increments of 1/2 pt. */
4648 delta = steps < 0 ? 5 : -5;
1ea40aa2 4649 steps = eabs (steps);
178c5d9c 4650
82641697 4651 face = FACE_FROM_ID (f, face_id);
72af86bd 4652 memcpy (attrs, face->lface, sizeof attrs);
82641697
GM
4653 pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
4654 new_face_id = face_id;
4655 last_height = FONT_HEIGHT (face->font);
4656
4657 while (steps
4658 && pt + delta > 0
4659 /* Give up if we cannot find a font within 10pt. */
1ea40aa2 4660 && eabs (last_pt - pt) < 100)
82641697
GM
4661 {
4662 /* Look up a face for a slightly smaller/larger font. */
4663 pt += delta;
4664 attrs[LFACE_HEIGHT_INDEX] = make_number (pt);
af53b43c 4665 new_face_id = lookup_face (f, attrs);
82641697
GM
4666 new_face = FACE_FROM_ID (f, new_face_id);
4667
4668 /* If height changes, count that as one step. */
b4c3ca09
GM
4669 if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
4670 || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
82641697
GM
4671 {
4672 --steps;
4673 last_height = FONT_HEIGHT (new_face->font);
4674 last_pt = pt;
4675 }
4676 }
4677
4678 return new_face_id;
4679
c3cee013 4680#else /* not HAVE_WINDOW_SYSTEM */
82641697
GM
4681
4682 return face_id;
178c5d9c 4683
c3cee013 4684#endif /* not HAVE_WINDOW_SYSTEM */
82641697
GM
4685}
4686
4687
4688/* Return a face for charset ASCII that is like the face with id
4689 FACE_ID on frame F, but has height HEIGHT. */
4690
4691int
971de7fb 4692face_with_height (struct frame *f, int face_id, int height)
82641697 4693{
c3cee013 4694#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
4695 struct face *face;
4696 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4697
4698 if (FRAME_TERMCAP_P (f)
4699 || height <= 0)
4700 return face_id;
4701
4702 face = FACE_FROM_ID (f, face_id);
72af86bd 4703 memcpy (attrs, face->lface, sizeof attrs);
82641697 4704 attrs[LFACE_HEIGHT_INDEX] = make_number (height);
a8c0cc18 4705 font_clear_prop (attrs, FONT_SIZE_INDEX);
af53b43c 4706 face_id = lookup_face (f, attrs);
c3cee013 4707#endif /* HAVE_WINDOW_SYSTEM */
178c5d9c 4708
82641697
GM
4709 return face_id;
4710}
4711
b5de343d 4712
44747bd0 4713/* Return the face id of the realized face for named face SYMBOL on
af53b43c
KH
4714 frame F suitable for displaying ASCII characters, and use
4715 attributes of the face FACE_ID for attributes that aren't
4716 completely specified by SYMBOL. This is like lookup_named_face,
4717 except that the default attributes come from FACE_ID, not from the
4718 default face. FACE_ID is assumed to be already realized. */
44747bd0
EZ
4719
4720int
b5f03016
AS
4721lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id,
4722 int signal_p)
44747bd0 4723{
e7d7fd8c 4724 Lisp_Object attrs[LFACE_VECTOR_SIZE];
44747bd0
EZ
4725 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
4726 struct face *default_face = FACE_FROM_ID (f, face_id);
4727
4728 if (!default_face)
4729 abort ();
4730
d8453278
CY
4731 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
4732 return -1;
4733
72af86bd 4734 memcpy (attrs, default_face->lface, sizeof attrs);
e7d7fd8c 4735 merge_face_vectors (f, symbol_attrs, attrs, 0);
af53b43c 4736 return lookup_face (f, attrs);
44747bd0
EZ
4737}
4738
f6608d5c
RS
4739DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
4740 Sface_attributes_as_vector, 1, 1, 0,
4bb962be 4741 doc: /* Return a vector of face attributes corresponding to PLIST. */)
5842a27b 4742 (Lisp_Object plist)
f6608d5c
RS
4743{
4744 Lisp_Object lface;
4745 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4746 Qunspecified);
a0a23346
MB
4747 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents,
4748 1, 0);
f6608d5c
RS
4749 return lface;
4750}
4751
82641697
GM
4752
4753\f
9717e36c
MB
4754/***********************************************************************
4755 Face capability testing
4756 ***********************************************************************/
4757
4758
4759/* If the distance (as returned by color_distance) between two colors is
4760 less than this, then they are considered the same, for determining
4761 whether a color is supported or not. The range of values is 0-65535. */
4762
4763#define TTY_SAME_COLOR_THRESHOLD 10000
4764
ccda4e3c 4765#ifdef HAVE_WINDOW_SYSTEM
9717e36c
MB
4766
4767/* Return non-zero if all the face attributes in ATTRS are supported
4768 on the window-system frame F.
4769
4770 The definition of `supported' is somewhat heuristic, but basically means
4771 that a face containing all the attributes in ATTRS, when merged with the
4772 default face for display, can be represented in a way that's
4773
4774 \(1) different in appearance than the default face, and
8e330b22 4775 \(2) `close in spirit' to what the attributes specify, if not exact. */
9717e36c
MB
4776
4777static int
b5f03016
AS
4778x_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
4779 struct face *def_face)
9717e36c 4780{
8e330b22 4781 Lisp_Object *def_attrs = def_face->lface;
9717e36c
MB
4782
4783 /* Check that other specified attributes are different that the default
4784 face. */
4785 if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
4786 && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
4787 def_attrs[LFACE_UNDERLINE_INDEX]))
4788 || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
4789 && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
4790 def_attrs[LFACE_INVERSE_INDEX]))
4791 || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
4792 && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
4793 def_attrs[LFACE_FOREGROUND_INDEX]))
4794 || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
4795 && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
4796 def_attrs[LFACE_BACKGROUND_INDEX]))
4797 || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
4798 && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
4799 def_attrs[LFACE_STIPPLE_INDEX]))
4800 || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
4801 && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
4802 def_attrs[LFACE_OVERLINE_INDEX]))
4803 || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
4804 && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
4805 def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
4806 || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
4807 && face_attr_equal_p (attrs[LFACE_BOX_INDEX],
4808 def_attrs[LFACE_BOX_INDEX])))
4809 return 0;
4810
4811 /* Check font-related attributes, as those are the most commonly
4812 "unsupported" on a window-system (because of missing fonts). */
4813 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
53aaf1e2 4814 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
9717e36c
MB
4815 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
4816 || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
4817 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
2dee4c0b 4818 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]))
9717e36c 4819 {
327719ee 4820 int face_id;
9717e36c
MB
4821 struct face *face;
4822 Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
2dee4c0b 4823 int i;
9717e36c 4824
72af86bd 4825 memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
9717e36c 4826
a0a23346 4827 merge_face_vectors (f, attrs, merged_attrs, 0);
9717e36c 4828
327719ee
MB
4829 face_id = lookup_face (f, merged_attrs);
4830 face = FACE_FROM_ID (f, face_id);
9717e36c
MB
4831
4832 if (! face)
2010ba8c 4833 error ("Cannot make face");
9717e36c 4834
4fc1984a
KH
4835 /* If the font is the same, or no font is found, then not
4836 supported. */
4837 if (face->font == def_face->font
4838 || ! face->font)
9717e36c 4839 return 0;
2dee4c0b
KH
4840 for (i = FONT_TYPE_INDEX; i <= FONT_SIZE_INDEX; i++)
4841 if (! EQ (face->font->props[i], def_face->font->props[i]))
4842 {
4843 Lisp_Object s1, s2;
4844
4845 if (i < FONT_FOUNDRY_INDEX || i > FONT_REGISTRY_INDEX
4846 || face->font->driver->case_sensitive)
4847 return 1;
4848 s1 = SYMBOL_NAME (face->font->props[i]);
4849 s2 = SYMBOL_NAME (def_face->font->props[i]);
4850 if (! EQ (Fcompare_strings (s1, make_number (0), Qnil,
4851 s2, make_number (0), Qnil, Qt), Qt))
4852 return 1;
4853 }
4854 return 0;
9717e36c
MB
4855 }
4856
4857 /* Everything checks out, this face is supported. */
4858 return 1;
4859}
4860
ccda4e3c 4861#endif /* HAVE_WINDOW_SYSTEM */
9717e36c
MB
4862
4863/* Return non-zero if all the face attributes in ATTRS are supported
4864 on the tty frame F.
4865
4866 The definition of `supported' is somewhat heuristic, but basically means
4867 that a face containing all the attributes in ATTRS, when merged
4868 with the default face for display, can be represented in a way that's
4869
4870 \(1) different in appearance than the default face, and
4871 \(2) `close in spirit' to what the attributes specify, if not exact.
4872
4873 Point (2) implies that a `:weight black' attribute will be satisfied
4874 by any terminal that can display bold, and a `:foreground "yellow"' as
4875 long as the terminal can display a yellowish color, but `:slant italic'
4876 will _not_ be satisfied by the tty display code's automatic
4877 substitution of a `dim' face for italic. */
4878
4879static int
b5f03016
AS
4880tty_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
4881 struct face *def_face)
9717e36c 4882{
734e9514 4883 int weight;
9717e36c
MB
4884 Lisp_Object val, fg, bg;
4885 XColor fg_tty_color, fg_std_color;
4886 XColor bg_tty_color, bg_std_color;
4887 unsigned test_caps = 0;
8e330b22 4888 Lisp_Object *def_attrs = def_face->lface;
9717e36c 4889
9717e36c 4890
8e330b22
MB
4891 /* First check some easy-to-check stuff; ttys support none of the
4892 following attributes, so we can just return false if any are requested
4893 (even if `nominal' values are specified, we should still return false,
4894 as that will be the same value that the default face uses). We
4895 consider :slant unsupportable on ttys, even though the face code
4896 actually `fakes' them using a dim attribute if possible. This is
4897 because the faked result is too different from what the face
4898 specifies. */
4899 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
53aaf1e2 4900 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
8e330b22
MB
4901 || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
4902 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
4903 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
4904 || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
4905 || !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
4906 || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
4907 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]))
9717e36c
MB
4908 return 0;
4909
4910
4911 /* Test for terminal `capabilities' (non-color character attributes). */
4912
4913 /* font weight (bold/dim) */
337fbd17
CY
4914 val = attrs[LFACE_WEIGHT_INDEX];
4915 if (!UNSPECIFIEDP (val)
4916 && (weight = FONT_WEIGHT_NAME_NUMERIC (val), weight >= 0))
9717e36c 4917 {
2dee4c0b 4918 int def_weight = FONT_WEIGHT_NAME_NUMERIC (def_attrs[LFACE_WEIGHT_INDEX]);
8e330b22 4919
2dee4c0b 4920 if (weight > 100)
8e330b22 4921 {
2dee4c0b 4922 if (def_weight > 100)
8e330b22
MB
4923 return 0; /* same as default */
4924 test_caps = TTY_CAP_BOLD;
4925 }
2dee4c0b 4926 else if (weight < 100)
8e330b22 4927 {
2dee4c0b 4928 if (def_weight < 100)
8e330b22
MB
4929 return 0; /* same as default */
4930 test_caps = TTY_CAP_DIM;
4931 }
2dee4c0b 4932 else if (def_weight == 100)
8e330b22 4933 return 0; /* same as default */
9717e36c
MB
4934 }
4935
4936 /* underlining */
4937 val = attrs[LFACE_UNDERLINE_INDEX];
8e330b22 4938 if (!UNSPECIFIEDP (val))
9717e36c
MB
4939 {
4940 if (STRINGP (val))
8e330b22
MB
4941 return 0; /* ttys can't use colored underlines */
4942 else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
4943 return 0; /* same as default */
9717e36c
MB
4944 else
4945 test_caps |= TTY_CAP_UNDERLINE;
4946 }
4947
4948 /* inverse video */
4949 val = attrs[LFACE_INVERSE_INDEX];
8e330b22
MB
4950 if (!UNSPECIFIEDP (val))
4951 {
a13ab63f 4952 if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
8e330b22
MB
4953 return 0; /* same as default */
4954 else
4955 test_caps |= TTY_CAP_INVERSE;
4956 }
9717e36c
MB
4957
4958
4959 /* Color testing. */
4960
4961 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
4962 we use them when calling `tty_capable_p' below, even if the face
4963 specifies no colors. */
4964 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
4965 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
4966
4967 /* Check if foreground color is close enough. */
4968 fg = attrs[LFACE_FOREGROUND_INDEX];
4969 if (STRINGP (fg))
4970 {
8e330b22
MB
4971 Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
4972
4973 if (face_attr_equal_p (fg, def_fg))
4974 return 0; /* same as default */
4975 else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
4976 return 0; /* not a valid color */
9717e36c
MB
4977 else if (color_distance (&fg_tty_color, &fg_std_color)
4978 > TTY_SAME_COLOR_THRESHOLD)
8e330b22
MB
4979 return 0; /* displayed color is too different */
4980 else
4981 /* Make sure the color is really different than the default. */
4982 {
4983 XColor def_fg_color;
4984 if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
4985 && (color_distance (&fg_tty_color, &def_fg_color)
4986 <= TTY_SAME_COLOR_THRESHOLD))
4987 return 0;
4988 }
9717e36c
MB
4989 }
4990
4991 /* Check if background color is close enough. */
4992 bg = attrs[LFACE_BACKGROUND_INDEX];
4993 if (STRINGP (bg))
4994 {
a13ab63f 4995 Lisp_Object def_bg = def_attrs[LFACE_BACKGROUND_INDEX];
8e330b22
MB
4996
4997 if (face_attr_equal_p (bg, def_bg))
4998 return 0; /* same as default */
4999 else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5000 return 0; /* not a valid color */
9717e36c
MB
5001 else if (color_distance (&bg_tty_color, &bg_std_color)
5002 > TTY_SAME_COLOR_THRESHOLD)
8e330b22
MB
5003 return 0; /* displayed color is too different */
5004 else
5005 /* Make sure the color is really different than the default. */
5006 {
5007 XColor def_bg_color;
5008 if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
5009 && (color_distance (&bg_tty_color, &def_bg_color)
5010 <= TTY_SAME_COLOR_THRESHOLD))
5011 return 0;
5012 }
9717e36c
MB
5013 }
5014
5015 /* If both foreground and background are requested, see if the
5016 distance between them is OK. We just check to see if the distance
5017 between the tty's foreground and background is close enough to the
5018 distance between the standard foreground and background. */
5019 if (STRINGP (fg) && STRINGP (bg))
5020 {
5021 int delta_delta
5022 = (color_distance (&fg_std_color, &bg_std_color)
5023 - color_distance (&fg_tty_color, &bg_tty_color));
5024 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5025 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5026 return 0;
5027 }
5028
5029
5030 /* See if the capabilities we selected above are supported, with the
5031 given colors. */
5032 if (test_caps != 0 &&
b5f03016
AS
5033 ! tty_capable_p (FRAME_TTY (f), test_caps, fg_tty_color.pixel,
5034 bg_tty_color.pixel))
9717e36c
MB
5035 return 0;
5036
5037
5038 /* Hmmm, everything checks out, this terminal must support this face. */
5039 return 1;
5040}
5041
5042
5043DEFUN ("display-supports-face-attributes-p",
5044 Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
5045 1, 2, 0,
5046 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
5047The optional argument DISPLAY can be a display name, a frame, or
9fed2905 5048nil (meaning the selected frame's display).
9717e36c
MB
5049
5050The definition of `supported' is somewhat heuristic, but basically means
5051that a face containing all the attributes in ATTRIBUTES, when merged
5052with the default face for display, can be represented in a way that's
5053
5054 \(1) different in appearance than the default face, and
5055 \(2) `close in spirit' to what the attributes specify, if not exact.
5056
5057Point (2) implies that a `:weight black' attribute will be satisfied by
5058any display that can display bold, and a `:foreground \"yellow\"' as long
5059as it can display a yellowish color, but `:slant italic' will _not_ be
5060satisfied by the tty display code's automatic substitution of a `dim'
9fed2905 5061face for italic. */)
5842a27b 5062 (Lisp_Object attributes, Lisp_Object display)
9717e36c 5063{
221439a0 5064 int supports = 0, i;
9717e36c
MB
5065 Lisp_Object frame;
5066 struct frame *f;
8e330b22 5067 struct face *def_face;
9717e36c
MB
5068 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5069
0722292b
MB
5070 if (noninteractive || !initialized)
5071 /* We may not be able to access low-level face information in batch
5072 mode, or before being dumped, and this function is not going to
5073 be very useful in those cases anyway, so just give up. */
5074 return Qnil;
5075
9717e36c
MB
5076 if (NILP (display))
5077 frame = selected_frame;
5078 else if (FRAMEP (display))
5079 frame = display;
5080 else
5081 {
5082 /* Find any frame on DISPLAY. */
5083 Lisp_Object fl_tail;
5084
5085 frame = Qnil;
5086 for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
5087 {
5088 frame = XCAR (fl_tail);
5089 if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
5090 XFRAME (frame)->param_alist)),
5091 display)))
5092 break;
5093 }
5094 }
5095
5096 CHECK_LIVE_FRAME (frame);
5097 f = XFRAME (frame);
5098
5099 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
5100 attrs[i] = Qunspecified;
a0a23346 5101 merge_face_ref (f, attributes, attrs, 1, 0);
9717e36c 5102
8e330b22
MB
5103 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5104 if (def_face == NULL)
5105 {
5106 if (! realize_basic_faces (f))
734e9514 5107 error ("Cannot realize default face");
8e330b22 5108 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
418ca4d2
RS
5109 if (def_face == NULL)
5110 abort (); /* realize_basic_faces must have set it up */
8e330b22
MB
5111 }
5112
9717e36c
MB
5113 /* Dispatch to the appropriate handler. */
5114 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
8e330b22 5115 supports = tty_supports_face_attributes_p (f, attrs, def_face);
ccda4e3c 5116#ifdef HAVE_WINDOW_SYSTEM
9717e36c 5117 else
8e330b22
MB
5118 supports = x_supports_face_attributes_p (f, attrs, def_face);
5119#endif
9717e36c
MB
5120
5121 return supports ? Qt : Qnil;
5122}
5123
5124\f
82641697
GM
5125/***********************************************************************
5126 Font selection
5127 ***********************************************************************/
5128
2c7d1565 5129DEFUN ("internal-set-font-selection-order",
82641697
GM
5130 Finternal_set_font_selection_order,
5131 Sinternal_set_font_selection_order, 1, 1, 0,
7ee72033 5132 doc: /* Set font selection order for face font selection to ORDER.
228299fa
GM
5133ORDER must be a list of length 4 containing the symbols `:width',
5134`:height', `:weight', and `:slant'. Face attributes appearing
5135first in ORDER are matched first, e.g. if `:height' appears before
5136`:weight' in ORDER, font selection first tries to find a font with
5137a suitable height, and then tries to match the font weight.
7ee72033 5138Value is ORDER. */)
5842a27b 5139 (Lisp_Object order)
82641697
GM
5140{
5141 Lisp_Object list;
5142 int i;
a08332c0 5143 int indices[DIM (font_sort_order)];
178c5d9c 5144
b7826503 5145 CHECK_LIST (order);
72af86bd 5146 memset (indices, 0, sizeof indices);
82641697
GM
5147 i = 0;
5148
5149 for (list = order;
5150 CONSP (list) && i < DIM (indices);
5151 list = XCDR (list), ++i)
5152 {
5153 Lisp_Object attr = XCAR (list);
5154 int xlfd;
5155
5156 if (EQ (attr, QCwidth))
5157 xlfd = XLFD_SWIDTH;
5158 else if (EQ (attr, QCheight))
5159 xlfd = XLFD_POINT_SIZE;
5160 else if (EQ (attr, QCweight))
5161 xlfd = XLFD_WEIGHT;
5162 else if (EQ (attr, QCslant))
5163 xlfd = XLFD_SLANT;
5164 else
5165 break;
5166
5167 if (indices[i] != 0)
5168 break;
5169 indices[i] = xlfd;
5170 }
5171
a08332c0 5172 if (!NILP (list) || i != DIM (indices))
82641697 5173 signal_error ("Invalid font sort order", order);
a08332c0
GM
5174 for (i = 0; i < DIM (font_sort_order); ++i)
5175 if (indices[i] == 0)
5176 signal_error ("Invalid font sort order", order);
82641697 5177
72af86bd 5178 if (memcmp (indices, font_sort_order, sizeof indices) != 0)
82641697 5179 {
72af86bd 5180 memcpy (font_sort_order, indices, sizeof font_sort_order);
82641697
GM
5181 free_all_realized_faces (Qnil);
5182 }
178c5d9c 5183
2dee4c0b 5184 font_update_sort_order (font_sort_order);
426b2119 5185
82641697
GM
5186 return Qnil;
5187}
5188
5189
5190DEFUN ("internal-set-alternative-font-family-alist",
5191 Finternal_set_alternative_font_family_alist,
5192 Sinternal_set_alternative_font_family_alist, 1, 1, 0,
c71f3632 5193 doc: /* Define alternative font families to try in face font selection.
228299fa
GM
5194ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
5195Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
7ee72033 5196be found. Value is ALIST. */)
5842a27b 5197 (Lisp_Object alist)
82641697 5198{
a77d5bb2 5199 Lisp_Object entry, tail, tail2;
53aaf1e2 5200
b7826503 5201 CHECK_LIST (alist);
53aaf1e2
KH
5202 alist = Fcopy_sequence (alist);
5203 for (tail = alist; CONSP (tail); tail = XCDR (tail))
a77d5bb2
CY
5204 {
5205 entry = XCAR (tail);
5206 CHECK_LIST (entry);
5207 entry = Fcopy_sequence (entry);
5208 XSETCAR (tail, entry);
5209 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5210 XSETCAR (tail2, Fintern (XCAR (tail2), Qnil));
5211 }
5212
82641697
GM
5213 Vface_alternative_font_family_alist = alist;
5214 free_all_realized_faces (Qnil);
5215 return alist;
5216}
5217
5218
32fcc231
GM
5219DEFUN ("internal-set-alternative-font-registry-alist",
5220 Finternal_set_alternative_font_registry_alist,
5221 Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
e3cd9e7f 5222 doc: /* Define alternative font registries to try in face font selection.
228299fa
GM
5223ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
5224Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
7ee72033 5225be found. Value is ALIST. */)
5842a27b 5226 (Lisp_Object alist)
32fcc231 5227{
a77d5bb2 5228 Lisp_Object entry, tail, tail2;
53aaf1e2 5229
b7826503 5230 CHECK_LIST (alist);
53aaf1e2
KH
5231 alist = Fcopy_sequence (alist);
5232 for (tail = alist; CONSP (tail); tail = XCDR (tail))
a77d5bb2
CY
5233 {
5234 entry = XCAR (tail);
5235 CHECK_LIST (entry);
5236 entry = Fcopy_sequence (entry);
5237 XSETCAR (tail, entry);
5238 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5239 XSETCAR (tail2, Fdowncase (XCAR (tail2)));
5240 }
32fcc231
GM
5241 Vface_alternative_font_registry_alist = alist;
5242 free_all_realized_faces (Qnil);
5243 return alist;
5244}
5245
5246
c3cee013 5247#ifdef HAVE_WINDOW_SYSTEM
82641697 5248
39506348
KH
5249/* Return the fontset id of the base fontset name or alias name given
5250 by the fontset attribute of ATTRS. Value is -1 if the fontset
5251 attribute of ATTRS doesn't name a fontset. */
82641697
GM
5252
5253static int
971de7fb 5254face_fontset (Lisp_Object *attrs)
82641697 5255{
39506348 5256 Lisp_Object name;
178c5d9c 5257
763bc839 5258 name = attrs[LFACE_FONTSET_INDEX];
39506348
KH
5259 if (!STRINGP (name))
5260 return -1;
5261 return fs_query_fontset (name, 0);
82641697
GM
5262}
5263
c3cee013 5264#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5265
5266
5267\f
5268/***********************************************************************
5269 Face Realization
5270 ***********************************************************************/
5271
5272/* Realize basic faces on frame F. Value is zero if frame parameters
5273 of F don't contain enough information needed to realize the default
5274 face. */
5275
5276static int
971de7fb 5277realize_basic_faces (struct frame *f)
82641697
GM
5278{
5279 int success_p = 0;
331379bf 5280 int count = SPECPDL_INDEX ();
17e8204b 5281
04386463
GM
5282 /* Block input here so that we won't be surprised by an X expose
5283 event, for instance, without having the faces set up. */
17e8204b 5284 BLOCK_INPUT;
eeffb293 5285 specbind (Qscalable_fonts_allowed, Qt);
178c5d9c 5286
82641697
GM
5287 if (realize_default_face (f))
5288 {
92610620 5289 realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
039b6394 5290 realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
9ea173e8 5291 realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
4e50fa8b 5292 realize_named_face (f, Qfringe, FRINGE_FACE_ID);
045dee35 5293 realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
8bd201d6
GM
5294 realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
5295 realize_named_face (f, Qborder, BORDER_FACE_ID);
5296 realize_named_face (f, Qcursor, CURSOR_FACE_ID);
5297 realize_named_face (f, Qmouse, MOUSE_FACE_ID);
c7ae3284 5298 realize_named_face (f, Qmenu, MENU_FACE_ID);
53abc3bf 5299 realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
563f68f1 5300
b5de343d 5301 /* Reflect changes in the `menu' face in menu bars. */
ceeda019 5302 if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
563f68f1 5303 {
ceeda019 5304 FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
563f68f1 5305#ifdef USE_X_TOOLKIT
b5f03016
AS
5306 if (FRAME_WINDOW_P (f))
5307 x_update_menu_appearance (f);
a03ad468 5308#endif
563f68f1 5309 }
177c0ea7 5310
82641697
GM
5311 success_p = 1;
5312 }
5313
eeffb293 5314 unbind_to (count, Qnil);
17e8204b 5315 UNBLOCK_INPUT;
82641697
GM
5316 return success_p;
5317}
5318
5319
5320/* Realize the default face on frame F. If the face is not fully
5321 specified, make it fully-specified. Attributes of the default face
5322 that are not explicitly specified are taken from frame parameters. */
5323
5324static int
971de7fb 5325realize_default_face (struct frame *f)
82641697
GM
5326{
5327 struct face_cache *c = FRAME_FACE_CACHE (f);
5328 Lisp_Object lface;
5329 Lisp_Object attrs[LFACE_VECTOR_SIZE];
82641697 5330 struct face *face;
82641697
GM
5331
5332 /* If the `default' face is not yet known, create it. */
5333 lface = lface_from_face_name (f, Qdefault, 0);
5334 if (NILP (lface))
07446869
GM
5335 {
5336 Lisp_Object frame;
5337 XSETFRAME (frame, f);
5338 lface = Finternal_make_lisp_face (Qdefault, frame);
5339 }
5340
c3cee013
JR
5341#ifdef HAVE_WINDOW_SYSTEM
5342 if (FRAME_WINDOW_P (f))
82641697 5343 {
2dee4c0b
KH
5344 Lisp_Object font_object;
5345
5346 XSETFONT (font_object, FRAME_FONT (f));
5347 set_lface_from_font (f, lface, font_object, f->default_face_done_p);
5348 LFACE_FONTSET (lface) = fontset_name (FRAME_FONTSET (f));
a5f696ac 5349 f->default_face_done_p = 1;
82641697 5350 }
c3cee013 5351#endif /* HAVE_WINDOW_SYSTEM */
82641697 5352
44747bd0 5353 if (!FRAME_WINDOW_P (f))
82641697
GM
5354 {
5355 LFACE_FAMILY (lface) = build_string ("default");
53aaf1e2 5356 LFACE_FOUNDRY (lface) = LFACE_FAMILY (lface);
82641697
GM
5357 LFACE_SWIDTH (lface) = Qnormal;
5358 LFACE_HEIGHT (lface) = make_number (1);
c1e7532d
EZ
5359 if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
5360 LFACE_WEIGHT (lface) = Qnormal;
5361 if (UNSPECIFIEDP (LFACE_SLANT (lface)))
5362 LFACE_SLANT (lface) = Qnormal;
70d6ecc6
KH
5363 if (UNSPECIFIEDP (LFACE_FONTSET (lface)))
5364 LFACE_FONTSET (lface) = Qnil;
82641697 5365 }
178c5d9c 5366
82641697
GM
5367 if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
5368 LFACE_UNDERLINE (lface) = Qnil;
178c5d9c 5369
82641697
GM
5370 if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
5371 LFACE_OVERLINE (lface) = Qnil;
178c5d9c 5372
82641697
GM
5373 if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
5374 LFACE_STRIKE_THROUGH (lface) = Qnil;
178c5d9c 5375
82641697
GM
5376 if (UNSPECIFIEDP (LFACE_BOX (lface)))
5377 LFACE_BOX (lface) = Qnil;
178c5d9c 5378
82641697
GM
5379 if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
5380 LFACE_INVERSE (lface) = Qnil;
178c5d9c 5381
82641697
GM
5382 if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
5383 {
5384 /* This function is called so early that colors are not yet
5385 set in the frame parameter list. */
5386 Lisp_Object color = Fassq (Qforeground_color, f->param_alist);
178c5d9c 5387
82641697
GM
5388 if (CONSP (color) && STRINGP (XCDR (color)))
5389 LFACE_FOREGROUND (lface) = XCDR (color);
c3cee013 5390 else if (FRAME_WINDOW_P (f))
82641697 5391 return 0;
3224dac1 5392 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ef917393 5393 LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
f9d2fdc4 5394 else
82641697
GM
5395 abort ();
5396 }
178c5d9c 5397
82641697
GM
5398 if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
5399 {
5400 /* This function is called so early that colors are not yet
5401 set in the frame parameter list. */
5402 Lisp_Object color = Fassq (Qbackground_color, f->param_alist);
5403 if (CONSP (color) && STRINGP (XCDR (color)))
5404 LFACE_BACKGROUND (lface) = XCDR (color);
c3cee013 5405 else if (FRAME_WINDOW_P (f))
82641697 5406 return 0;
3224dac1 5407 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ef917393 5408 LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
f9d2fdc4 5409 else
82641697
GM
5410 abort ();
5411 }
178c5d9c 5412
82641697
GM
5413 if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
5414 LFACE_STIPPLE (lface) = Qnil;
5415
5416 /* Realize the face; it must be fully-specified now. */
5417 xassert (lface_fully_specified_p (XVECTOR (lface)->contents));
5418 check_lface (lface);
72af86bd 5419 memcpy (attrs, XVECTOR (lface)->contents, sizeof attrs);
af53b43c 5420 face = realize_face (c, attrs, DEFAULT_FACE_ID);
4da9c136
KH
5421
5422#ifdef HAVE_WINDOW_SYSTEM
41a9b76e 5423#ifdef HAVE_X_WINDOWS
361c0d6e 5424 if (FRAME_X_P (f) && face->font != FRAME_FONT (f))
73158a39
CY
5425 {
5426 /* This can happen when making a frame on a display that does
b5f03016 5427 not support the default font. */
73158a39 5428 if (!face->font)
b5f03016 5429 return 0;
d5ab09cd 5430
73158a39 5431 /* Otherwise, the font specified for the frame was not
b5f03016
AS
5432 acceptable as a font for the default face (perhaps because
5433 auto-scaled fonts are rejected), so we must adjust the frame
5434 font. */
2dee4c0b 5435 x_set_font (f, LFACE_FONT (lface), Qnil);
73158a39 5436 }
4da9c136
KH
5437#endif /* HAVE_X_WINDOWS */
5438#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5439 return 1;
5440}
5441
5442
5443/* Realize basic faces other than the default face in face cache C.
5444 SYMBOL is the face name, ID is the face id the realized face must
5445 have. The default face must have been realized already. */
5446
5447static void
971de7fb 5448realize_named_face (struct frame *f, Lisp_Object symbol, int id)
82641697 5449{
e7d7fd8c 5450 struct face_cache *c = FRAME_FACE_CACHE (f);
82641697
GM
5451 Lisp_Object lface = lface_from_face_name (f, symbol, 0);
5452 Lisp_Object attrs[LFACE_VECTOR_SIZE];
e7d7fd8c 5453 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
82641697
GM
5454
5455 /* The default face must exist and be fully specified. */
f2cec7a9 5456 get_lface_attributes_no_remap (f, Qdefault, attrs, 1);
82641697
GM
5457 check_lface_attrs (attrs);
5458 xassert (lface_fully_specified_p (attrs));
5459
e7d7fd8c 5460 /* If SYMBOL isn't know as a face, create it. */
82641697
GM
5461 if (NILP (lface))
5462 {
5463 Lisp_Object frame;
5464 XSETFRAME (frame, f);
5465 lface = Finternal_make_lisp_face (symbol, frame);
5466 }
5467
5468 /* Merge SYMBOL's face with the default face. */
f2cec7a9 5469 get_lface_attributes_no_remap (f, symbol, symbol_attrs, 1);
e7d7fd8c
MB
5470 merge_face_vectors (f, symbol_attrs, attrs, 0);
5471
5472 /* Realize the face. */
a5a62657 5473 realize_face (c, attrs, id);
82641697
GM
5474}
5475
5476
5477/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
5478 cache CACHE for ASCII characters. If FORMER_FACE_ID is
5479 non-negative, it is an ID of face to remove before caching the new
5480 face. Value is a pointer to the newly created realized face. */
82641697
GM
5481
5482static struct face *
971de7fb 5483realize_face (struct face_cache *cache, Lisp_Object *attrs, int former_face_id)
82641697
GM
5484{
5485 struct face *face;
178c5d9c 5486
82641697 5487 /* LFACE must be fully specified. */
39506348 5488 xassert (cache != NULL);
82641697
GM
5489 check_lface_attrs (attrs);
5490
39506348
KH
5491 if (former_face_id >= 0 && cache->used > former_face_id)
5492 {
5493 /* Remove the former face. */
5494 struct face *former_face = cache->faces_by_id[former_face_id];
5495 uncache_face (cache, former_face);
5496 free_realized_face (cache->f, former_face);
7c33a057 5497 SET_FRAME_GARBAGED (cache->f);
39506348
KH
5498 }
5499
5500 if (FRAME_WINDOW_P (cache->f))
af53b43c 5501 face = realize_x_face (cache, attrs);
e689ec06 5502 else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
af53b43c 5503 face = realize_tty_face (cache, attrs);
d448e982
KL
5504 else if (FRAME_INITIAL_P (cache->f))
5505 {
5506 /* Create a dummy face. */
5507 face = make_realized_face (attrs);
5508 }
82641697
GM
5509 else
5510 abort ();
5511
39506348
KH
5512 /* Insert the new face. */
5513 cache_face (cache, face, lface_hash (attrs));
af53b43c
KH
5514 return face;
5515}
5516
5517
8c6204de 5518#ifdef HAVE_WINDOW_SYSTEM
2dee4c0b
KH
5519/* Realize the fully-specified face that uses FONT-OBJECT and has the
5520 same attributes as BASE_FACE except for the font on frame F.
5521 FONT-OBJECT may be nil, in which case, realized a face of
5522 no-font. */
af53b43c
KH
5523
5524static struct face *
b5f03016
AS
5525realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
5526 struct face *base_face)
af53b43c
KH
5527{
5528 struct face_cache *cache = FRAME_FACE_CACHE (f);
8f924df7 5529 struct face *face;
af53b43c
KH
5530
5531 face = (struct face *) xmalloc (sizeof *face);
5532 *face = *base_face;
5533 face->gc = 0;
bdd10de6 5534 face->extra = NULL;
2dee4c0b
KH
5535 face->overstrike
5536 = (! NILP (font_object)
5537 && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100
5538 && FONT_WEIGHT_NUMERIC (font_object) <= 100);
af53b43c
KH
5539
5540 /* Don't try to free the colors copied bitwise from BASE_FACE. */
5541 face->colors_copied_bitwise_p = 1;
2dee4c0b 5542 face->font = NILP (font_object) ? NULL : XFONT_OBJECT (font_object);
af53b43c
KH
5543 face->gc = 0;
5544
5545 cache_face (cache, face, face->hash);
5546
82641697
GM
5547 return face;
5548}
8c6204de 5549#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5550
5551
5552/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
5553 cache CACHE for ASCII characters. Do it for X frame CACHE->f. If
5554 the new face doesn't share font with the default face, a fontname
5555 is allocated from the heap and set in `font_name' of the new face,
5556 but it is not yet loaded here. Value is a pointer to the newly
5557 created realized face. */
82641697
GM
5558
5559static struct face *
971de7fb 5560realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
82641697 5561{
7d603e3f 5562 struct face *face = NULL;
c3cee013 5563#ifdef HAVE_WINDOW_SYSTEM
7d603e3f 5564 struct face *default_face;
78d2079c 5565 struct frame *f;
82641697 5566 Lisp_Object stipple, overline, strike_through, box;
82641697 5567
39506348 5568 xassert (FRAME_WINDOW_P (cache->f));
82641697
GM
5569
5570 /* Allocate a new realized face. */
39506348 5571 face = make_realized_face (attrs);
af53b43c 5572 face->ascii_face = face;
39506348
KH
5573
5574 f = cache->f;
5575
82641697
GM
5576 /* Determine the font to use. Most of the time, the font will be
5577 the same as the font of the default face, so try that first. */
5578 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5579 if (default_face
82641697
GM
5580 && lface_same_font_attributes_p (default_face->lface, attrs))
5581 {
5582 face->font = default_face->font;
76f54ecc
KH
5583 face->fontset
5584 = make_fontset_for_ascii_face (f, default_face->fontset, face);
82641697
GM
5585 }
5586 else
5587 {
39506348 5588 /* If the face attribute ATTRS specifies a fontset, use it as
fc8c4797
KH
5589 the base of a new realized fontset. Otherwise, use the same
5590 base fontset as of the default face. The base determines
5591 registry and encoding of a font. It may also determine
5592 foundry and family. The other fields of font name pattern
5593 are constructed from ATTRS. */
5594 int fontset = face_fontset (attrs);
5595
af53b43c
KH
5596 /* If we are realizing the default face, ATTRS should specify a
5597 fontset. In other words, if FONTSET is -1, we are not
5598 realizing the default face, thus the default face should have
5599 already been realized. */
5600 if (fontset == -1)
d78494f9
CY
5601 {
5602 if (default_face)
5603 fontset = default_face->fontset;
5604 if (fontset == -1)
5605 abort ();
5606 }
2dee4c0b
KH
5607 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
5608 attrs[LFACE_FONT_INDEX]
5609 = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]);
5610 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
5611 {
5612 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
5613 face->fontset = make_fontset_for_ascii_face (f, fontset, face);
5614 }
426b2119 5615 else
2dee4c0b
KH
5616 {
5617 face->font = NULL;
5618 face->fontset = -1;
5619 }
82641697
GM
5620 }
5621
2dee4c0b
KH
5622 if (face->font
5623 && FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]) > 100
5624 && FONT_WEIGHT_NUMERIC (attrs[LFACE_FONT_INDEX]) <= 100)
5625 face->overstrike = 1;
5626
82641697 5627 /* Load colors, and set remaining attributes. */
178c5d9c 5628
82641697 5629 load_face_colors (f, face, attrs);
660ed669 5630
82641697
GM
5631 /* Set up box. */
5632 box = attrs[LFACE_BOX_INDEX];
5633 if (STRINGP (box))
cb637678 5634 {
82641697
GM
5635 /* A simple box of line width 1 drawn in color given by
5636 the string. */
5637 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
5638 LFACE_BOX_INDEX);
5639 face->box = FACE_SIMPLE_BOX;
5640 face->box_line_width = 1;
cb637678 5641 }
82641697 5642 else if (INTEGERP (box))
42120bc7 5643 {
82641697 5644 /* Simple box of specified line width in foreground color of the
b5f03016 5645 face. */
89624b8b 5646 xassert (XINT (box) != 0);
82641697 5647 face->box = FACE_SIMPLE_BOX;
89624b8b 5648 face->box_line_width = XINT (box);
82641697
GM
5649 face->box_color = face->foreground;
5650 face->box_color_defaulted_p = 1;
5651 }
5652 else if (CONSP (box))
5653 {
5654 /* `(:width WIDTH :color COLOR :shadow SHADOW)'. SHADOW
5655 being one of `raised' or `sunken'. */
5656 face->box = FACE_SIMPLE_BOX;
5657 face->box_color = face->foreground;
5658 face->box_color_defaulted_p = 1;
5659 face->box_line_width = 1;
5660
5661 while (CONSP (box))
42120bc7 5662 {
82641697
GM
5663 Lisp_Object keyword, value;
5664
5665 keyword = XCAR (box);
5666 box = XCDR (box);
5667
5668 if (!CONSP (box))
5669 break;
5670 value = XCAR (box);
5671 box = XCDR (box);
5672
5673 if (EQ (keyword, QCline_width))
5674 {
89624b8b
KH
5675 if (INTEGERP (value) && XINT (value) != 0)
5676 face->box_line_width = XINT (value);
82641697
GM
5677 }
5678 else if (EQ (keyword, QCcolor))
5679 {
5680 if (STRINGP (value))
5681 {
5682 face->box_color = load_color (f, face, value,
5683 LFACE_BOX_INDEX);
5684 face->use_box_color_for_shadows_p = 1;
5685 }
5686 }
5687 else if (EQ (keyword, QCstyle))
a8517066 5688 {
82641697
GM
5689 if (EQ (value, Qreleased_button))
5690 face->box = FACE_RAISED_BOX;
5691 else if (EQ (value, Qpressed_button))
5692 face->box = FACE_SUNKEN_BOX;
a8517066 5693 }
42120bc7
RS
5694 }
5695 }
195f798e 5696
82641697 5697 /* Text underline, overline, strike-through. */
178c5d9c 5698
82641697 5699 if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt))
178c5d9c 5700 {
82641697
GM
5701 /* Use default color (same as foreground color). */
5702 face->underline_p = 1;
5703 face->underline_defaulted_p = 1;
5704 face->underline_color = 0;
5705 }
5706 else if (STRINGP (attrs[LFACE_UNDERLINE_INDEX]))
195f798e 5707 {
82641697
GM
5708 /* Use specified color. */
5709 face->underline_p = 1;
5710 face->underline_defaulted_p = 0;
5711 face->underline_color
5712 = load_color (f, face, attrs[LFACE_UNDERLINE_INDEX],
5713 LFACE_UNDERLINE_INDEX);
195f798e 5714 }
82641697 5715 else if (NILP (attrs[LFACE_UNDERLINE_INDEX]))
7b00de84 5716 {
82641697
GM
5717 face->underline_p = 0;
5718 face->underline_defaulted_p = 0;
5719 face->underline_color = 0;
7b00de84
JB
5720 }
5721
82641697
GM
5722 overline = attrs[LFACE_OVERLINE_INDEX];
5723 if (STRINGP (overline))
cb637678 5724 {
82641697
GM
5725 face->overline_color
5726 = load_color (f, face, attrs[LFACE_OVERLINE_INDEX],
5727 LFACE_OVERLINE_INDEX);
5728 face->overline_p = 1;
cb637678 5729 }
82641697 5730 else if (EQ (overline, Qt))
cb637678 5731 {
82641697
GM
5732 face->overline_color = face->foreground;
5733 face->overline_color_defaulted_p = 1;
5734 face->overline_p = 1;
cb637678
JB
5735 }
5736
82641697
GM
5737 strike_through = attrs[LFACE_STRIKE_THROUGH_INDEX];
5738 if (STRINGP (strike_through))
5739 {
5740 face->strike_through_color
5741 = load_color (f, face, attrs[LFACE_STRIKE_THROUGH_INDEX],
5742 LFACE_STRIKE_THROUGH_INDEX);
5743 face->strike_through_p = 1;
5744 }
5745 else if (EQ (strike_through, Qt))
5746 {
5747 face->strike_through_color = face->foreground;
5748 face->strike_through_color_defaulted_p = 1;
5749 face->strike_through_p = 1;
5750 }
867dd159 5751
82641697
GM
5752 stipple = attrs[LFACE_STIPPLE_INDEX];
5753 if (!NILP (stipple))
5754 face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
c3cee013 5755#endif /* HAVE_WINDOW_SYSTEM */
660ed669 5756
82641697 5757 return face;
660ed669
JB
5758}
5759
729425b1 5760
ae4b4ba5
GM
5761/* Map a specified color of face FACE on frame F to a tty color index.
5762 IDX is either LFACE_FOREGROUND_INDEX or LFACE_BACKGROUND_INDEX, and
5763 specifies which color to map. Set *DEFAULTED to 1 if mapping to the
5764 default foreground/background colors. */
5765
5766static void
b5f03016
AS
5767map_tty_color (struct frame *f, struct face *face,
5768 enum lface_attribute_index idx, int *defaulted)
ae4b4ba5
GM
5769{
5770 Lisp_Object frame, color, def;
5771 int foreground_p = idx == LFACE_FOREGROUND_INDEX;
a5a62657
PE
5772 unsigned long default_pixel =
5773 foreground_p ? FACE_TTY_DEFAULT_FG_COLOR : FACE_TTY_DEFAULT_BG_COLOR;
5774 unsigned long pixel = default_pixel;
5775#ifdef MSDOS
5776 unsigned long default_other_pixel =
5777 foreground_p ? FACE_TTY_DEFAULT_BG_COLOR : FACE_TTY_DEFAULT_FG_COLOR;
5778#endif
ae4b4ba5
GM
5779
5780 xassert (idx == LFACE_FOREGROUND_INDEX || idx == LFACE_BACKGROUND_INDEX);
5781
ae4b4ba5
GM
5782 XSETFRAME (frame, f);
5783 color = face->lface[idx];
177c0ea7 5784
ae4b4ba5 5785 if (STRINGP (color)
d5db4077 5786 && SCHARS (color)
ae4b4ba5
GM
5787 && CONSP (Vtty_defined_color_alist)
5788 && (def = assq_no_quit (color, call1 (Qtty_color_alist, frame)),
5789 CONSP (def)))
5790 {
5791 /* Associations in tty-defined-color-alist are of the form
5792 (NAME INDEX R G B). We need the INDEX part. */
5793 pixel = XINT (XCAR (XCDR (def)));
5794 }
5795
5796 if (pixel == default_pixel && STRINGP (color))
5797 {
5798 pixel = load_color (f, face, color, idx);
5799
8d05ec51 5800#ifdef MSDOS
ae4b4ba5
GM
5801 /* If the foreground of the default face is the default color,
5802 use the foreground color defined by the frame. */
ae4b4ba5
GM
5803 if (FRAME_MSDOS_P (f))
5804 {
ae4b4ba5
GM
5805 if (pixel == default_pixel
5806 || pixel == FACE_TTY_DEFAULT_COLOR)
5807 {
5808 if (foreground_p)
5809 pixel = FRAME_FOREGROUND_PIXEL (f);
5810 else
5811 pixel = FRAME_BACKGROUND_PIXEL (f);
5812 face->lface[idx] = tty_color_name (f, pixel);
5813 *defaulted = 1;
5814 }
5815 else if (pixel == default_other_pixel)
5816 {
5817 if (foreground_p)
5818 pixel = FRAME_BACKGROUND_PIXEL (f);
5819 else
5820 pixel = FRAME_FOREGROUND_PIXEL (f);
5821 face->lface[idx] = tty_color_name (f, pixel);
5822 *defaulted = 1;
5823 }
b5f03016 5824 }
8d05ec51 5825#endif /* MSDOS */
ae4b4ba5
GM
5826 }
5827
5828 if (foreground_p)
5829 face->foreground = pixel;
5830 else
5831 face->background = pixel;
5832}
5833
5834
82641697 5835/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
5836 cache CACHE for ASCII characters. Do it for TTY frame CACHE->f.
5837 Value is a pointer to the newly created realized face. */
a8517066 5838
82641697 5839static struct face *
971de7fb 5840realize_tty_face (struct face_cache *cache, Lisp_Object *attrs)
82641697
GM
5841{
5842 struct face *face;
5843 int weight, slant;
2d764c78 5844 int face_colors_defaulted = 0;
ae4b4ba5 5845 struct frame *f = cache->f;
729425b1 5846
82641697 5847 /* Frame must be a termcap frame. */
e689ec06 5848 xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
178c5d9c 5849
82641697 5850 /* Allocate a new realized face. */
39506348 5851 face = make_realized_face (attrs);
2dee4c0b 5852#if 0
e689ec06 5853 face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
2dee4c0b 5854#endif
82641697 5855
178c5d9c 5856 /* Map face attributes to TTY appearances. We map slant to
82641697
GM
5857 dimmed text because we want italic text to appear differently
5858 and because dimmed text is probably used infrequently. */
2dee4c0b
KH
5859 weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
5860 slant = FONT_SLANT_NAME_NUMERIC (attrs[LFACE_SLANT_INDEX]);
5861 if (weight > 100)
82641697 5862 face->tty_bold_p = 1;
2dee4c0b 5863 if (weight < 100 || slant != 100)
82641697
GM
5864 face->tty_dim_p = 1;
5865 if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
5866 face->tty_underline_p = 1;
5867 if (!NILP (attrs[LFACE_INVERSE_INDEX]))
5868 face->tty_reverse_p = 1;
5869
5870 /* Map color names to color indices. */
ae4b4ba5
GM
5871 map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
5872 map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
177c0ea7 5873
2d764c78
EZ
5874 /* Swap colors if face is inverse-video. If the colors are taken
5875 from the frame colors, they are already inverted, since the
5876 frame-creation function calls x-handle-reverse-video. */
5877 if (face->tty_reverse_p && !face_colors_defaulted)
44747bd0
EZ
5878 {
5879 unsigned long tem = face->foreground;
44747bd0
EZ
5880 face->foreground = face->background;
5881 face->background = tem;
5882 }
44747bd0 5883
a4a76b61
GM
5884 if (tty_suppress_bold_inverse_default_colors_p
5885 && face->tty_bold_p
5886 && face->background == FACE_TTY_DEFAULT_FG_COLOR
5887 && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
5888 face->tty_bold_p = 0;
5889
82641697 5890 return face;
729425b1 5891}
867dd159 5892
82641697 5893
a4a76b61
GM
5894DEFUN ("tty-suppress-bold-inverse-default-colors",
5895 Ftty_suppress_bold_inverse_default_colors,
5896 Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
e3cd9e7f 5897 doc: /* Suppress/allow boldness of faces with inverse default colors.
228299fa
GM
5898SUPPRESS non-nil means suppress it.
5899This affects bold faces on TTYs whose foreground is the default background
5900color of the display and whose background is the default foreground color.
5901For such faces, the bold face attribute is ignored if this variable
7ee72033 5902is non-nil. */)
5842a27b 5903 (Lisp_Object suppress)
a4a76b61
GM
5904{
5905 tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
5906 ++face_change_count;
5907 return suppress;
5908}
5909
5910
82641697
GM
5911\f
5912/***********************************************************************
5913 Computing Faces
5914 ***********************************************************************/
5915
5916/* Return the ID of the face to use to display character CH with face
5917 property PROP on frame F in current_buffer. */
2e16580f
RS
5918
5919int
971de7fb 5920compute_char_face (struct frame *f, int ch, Lisp_Object prop)
2e16580f 5921{
82641697 5922 int face_id;
39506348 5923
4b4deea2 5924 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
522d42f7 5925 ch = 0;
178c5d9c 5926
82641697 5927 if (NILP (prop))
39506348
KH
5928 {
5929 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
779c6fb6 5930 face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
39506348 5931 }
82641697 5932 else
2e16580f 5933 {
82641697
GM
5934 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5935 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
72af86bd 5936 memcpy (attrs, default_face->lface, sizeof attrs);
a0a23346 5937 merge_face_ref (f, prop, attrs, 1, 0);
af53b43c 5938 face_id = lookup_face (f, attrs);
2e16580f
RS
5939 }
5940
82641697 5941 return face_id;
2e16580f 5942}
bc0db68d 5943
82641697
GM
5944/* Return the face ID associated with buffer position POS for
5945 displaying ASCII characters. Return in *ENDPTR the position at
5946 which a different face is needed, as far as text properties and
5947 overlays are concerned. W is a window displaying current_buffer.
5948
5949 REGION_BEG, REGION_END delimit the region, so it can be
5950 highlighted.
6f134486 5951
82641697
GM
5952 LIMIT is a position not to scan beyond. That is to limit the time
5953 this function can take.
5954
5955 If MOUSE is non-zero, use the character's mouse-face, not its face.
5956
6970f632
CY
5957 BASE_FACE_ID, if non-negative, specifies a base face id to use
5958 instead of DEFAULT_FACE_ID.
5959
39506348 5960 The face returned is suitable for displaying ASCII characters. */
bc0db68d 5961
cb637678 5962int
d5a3eaaf
AS
5963face_at_buffer_position (struct window *w, EMACS_INT pos,
5964 EMACS_INT region_beg, EMACS_INT region_end,
5965 EMACS_INT *endptr, EMACS_INT limit,
5966 int mouse, int base_face_id)
7b7739b1 5967{
82641697
GM
5968 struct frame *f = XFRAME (w->frame);
5969 Lisp_Object attrs[LFACE_VECTOR_SIZE];
b6d40e46 5970 Lisp_Object prop, position;
b081724f 5971 ptrdiff_t i, noverlays;
7b7739b1 5972 Lisp_Object *overlay_vec;
f211082d 5973 Lisp_Object frame;
0f8b27ea 5974 EMACS_INT endpos;
82641697
GM
5975 Lisp_Object propname = mouse ? Qmouse_face : Qface;
5976 Lisp_Object limit1, end;
5977 struct face *default_face;
f6b98e0b
JB
5978
5979 /* W must display the current buffer. We could write this function
5980 to use the frame and buffer of W, but right now it doesn't. */
060fb5c1 5981 /* xassert (XBUFFER (w->buffer) == current_buffer); */
f211082d 5982
ac22a6c4 5983 XSETFRAME (frame, f);
82641697 5984 XSETFASTINT (position, pos);
7b7739b1 5985
f6b98e0b 5986 endpos = ZV;
bc0db68d
RS
5987 if (pos < region_beg && region_beg < endpos)
5988 endpos = region_beg;
f6b98e0b 5989
82641697
GM
5990 /* Get the `face' or `mouse_face' text property at POS, and
5991 determine the next position at which the property changes. */
6f134486 5992 prop = Fget_text_property (position, propname, w->buffer);
82641697
GM
5993 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
5994 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
5995 if (INTEGERP (end))
5996 endpos = XINT (end);
6f134486 5997
82641697 5998 /* Look at properties from overlays. */
b6d40e46 5999 {
a2bc5bdd 6000 EMACS_INT next_overlay;
b6d40e46 6001
0bc90bba 6002 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, 0);
f6b98e0b
JB
6003 if (next_overlay < endpos)
6004 endpos = next_overlay;
b6d40e46
JB
6005 }
6006
6007 *endptr = endpos;
7b7739b1 6008
823564e5
EZ
6009 {
6010 int face_id;
6011
6012 if (base_face_id >= 0)
6013 face_id = base_face_id;
6014 else if (NILP (Vface_remapping_alist))
6015 face_id = DEFAULT_FACE_ID;
6016 else
6017 face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
6018
6019 default_face = FACE_FROM_ID (f, face_id);
6020 }
178c5d9c 6021
82641697
GM
6022 /* Optimize common cases where we can use the default face. */
6023 if (noverlays == 0
6024 && NILP (prop)
39506348 6025 && !(pos >= region_beg && pos < region_end))
f2cec7a9 6026 return default_face->id;
82641697
GM
6027
6028 /* Begin with attributes from the default face. */
72af86bd 6029 memcpy (attrs, default_face->lface, sizeof attrs);
82641697
GM
6030
6031 /* Merge in attributes specified via text properties. */
6032 if (!NILP (prop))
a0a23346 6033 merge_face_ref (f, prop, attrs, 1, 0);
82641697
GM
6034
6035 /* Now merge the overlay data. */
18195655 6036 noverlays = sort_overlays (overlay_vec, noverlays, w);
18195655 6037 for (i = 0; i < noverlays; i++)
4699e6d2 6038 {
18195655
RS
6039 Lisp_Object oend;
6040 int oendpos;
6041
6042 prop = Foverlay_get (overlay_vec[i], propname);
82641697 6043 if (!NILP (prop))
a0a23346 6044 merge_face_ref (f, prop, attrs, 1, 0);
18195655
RS
6045
6046 oend = OVERLAY_END (overlay_vec[i]);
6047 oendpos = OVERLAY_POSITION (oend);
6048 if (oendpos < endpos)
6049 endpos = oendpos;
6050 }
6051
82641697 6052 /* If in the region, merge in the region face. */
18195655
RS
6053 if (pos >= region_beg && pos < region_end)
6054 {
a0a23346 6055 merge_named_face (f, Qregion, attrs, 0);
178c5d9c 6056
18195655
RS
6057 if (region_end < endpos)
6058 endpos = region_end;
18195655
RS
6059 }
6060
6061 *endptr = endpos;
6062
82641697 6063 /* Look up a realized face with the given face attributes,
39506348 6064 or realize a new one for ASCII characters. */
af53b43c 6065 return lookup_face (f, attrs);
18195655
RS
6066}
6067
a193ecf1
RS
6068/* Return the face ID at buffer position POS for displaying ASCII
6069 characters associated with overlay strings for overlay OVERLAY.
6070
6071 Like face_at_buffer_position except for OVERLAY. Currently it
6072 simply disregards the `face' properties of all overlays. */
03e1d617
RS
6073
6074int
d5a3eaaf
AS
6075face_for_overlay_string (struct window *w, EMACS_INT pos,
6076 EMACS_INT region_beg, EMACS_INT region_end,
6077 EMACS_INT *endptr, EMACS_INT limit,
6078 int mouse, Lisp_Object overlay)
03e1d617
RS
6079{
6080 struct frame *f = XFRAME (w->frame);
6081 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6082 Lisp_Object prop, position;
03e1d617
RS
6083 Lisp_Object frame;
6084 int endpos;
6085 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6086 Lisp_Object limit1, end;
6087 struct face *default_face;
6088
6089 /* W must display the current buffer. We could write this function
6090 to use the frame and buffer of W, but right now it doesn't. */
6091 /* xassert (XBUFFER (w->buffer) == current_buffer); */
6092
6093 XSETFRAME (frame, f);
6094 XSETFASTINT (position, pos);
6095
6096 endpos = ZV;
6097 if (pos < region_beg && region_beg < endpos)
6098 endpos = region_beg;
6099
6100 /* Get the `face' or `mouse_face' text property at POS, and
6101 determine the next position at which the property changes. */
6102 prop = Fget_text_property (position, propname, w->buffer);
6103 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6104 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
6105 if (INTEGERP (end))
6106 endpos = XINT (end);
6107
6108 *endptr = endpos;
6109
6110 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6111
6112 /* Optimize common cases where we can use the default face. */
6113 if (NILP (prop)
6114 && !(pos >= region_beg && pos < region_end))
6115 return DEFAULT_FACE_ID;
6116
6117 /* Begin with attributes from the default face. */
72af86bd 6118 memcpy (attrs, default_face->lface, sizeof attrs);
03e1d617
RS
6119
6120 /* Merge in attributes specified via text properties. */
6121 if (!NILP (prop))
6122 merge_face_ref (f, prop, attrs, 1, 0);
6123
6124 /* If in the region, merge in the region face. */
6125 if (pos >= region_beg && pos < region_end)
6126 {
6127 merge_named_face (f, Qregion, attrs, 0);
6128
6129 if (region_end < endpos)
6130 endpos = region_end;
6131 }
6132
6133 *endptr = endpos;
6134
6135 /* Look up a realized face with the given face attributes,
6136 or realize a new one for ASCII characters. */
ce9c2e7b 6137 return lookup_face (f, attrs);
03e1d617
RS
6138}
6139
60573a90 6140
82641697 6141/* Compute the face at character position POS in Lisp string STRING on
39506348 6142 window W, for ASCII characters.
7b7739b1 6143
82641697
GM
6144 If STRING is an overlay string, it comes from position BUFPOS in
6145 current_buffer, otherwise BUFPOS is zero to indicate that STRING is
6146 not an overlay string. W must display the current buffer.
6147 REGION_BEG and REGION_END give the start and end positions of the
8714a182
GM
6148 region; both are -1 if no region is visible.
6149
6150 BASE_FACE_ID is the id of a face to merge with. For strings coming
6151 from overlays or the `display' property it is the face at BUFPOS.
178c5d9c 6152
48a4ca99
GM
6153 If MOUSE_P is non-zero, use the character's mouse-face, not its face.
6154
82641697
GM
6155 Set *ENDPTR to the next position where to check for faces in
6156 STRING; -1 if the face is constant from POS to the end of the
6157 string.
18195655 6158
82641697 6159 Value is the id of the face to use. The face returned is suitable
39506348 6160 for displaying ASCII characters. */
fffc2367 6161
82641697 6162int
d5a3eaaf
AS
6163face_at_string_position (struct window *w, Lisp_Object string,
6164 EMACS_INT pos, EMACS_INT bufpos,
6165 EMACS_INT region_beg, EMACS_INT region_end,
6166 EMACS_INT *endptr, enum face_id base_face_id,
6167 int mouse_p)
660ed669 6168{
82641697
GM
6169 Lisp_Object prop, position, end, limit;
6170 struct frame *f = XFRAME (WINDOW_FRAME (w));
6171 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6172 struct face *base_face;
6173 int multibyte_p = STRING_MULTIBYTE (string);
48a4ca99 6174 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
82641697
GM
6175
6176 /* Get the value of the face property at the current position within
6177 STRING. Value is nil if there is no face property. */
6178 XSETFASTINT (position, pos);
48a4ca99 6179 prop = Fget_text_property (position, prop_name, string);
82641697
GM
6180
6181 /* Get the next position at which to check for faces. Value of end
6182 is nil if face is constant all the way to the end of the string.
6183 Otherwise it is a string position where to check faces next.
6184 Limit is the maximum position up to which to check for property
6185 changes in Fnext_single_property_change. Strings are usually
6186 short, so set the limit to the end of the string. */
d5db4077 6187 XSETFASTINT (limit, SCHARS (string));
48a4ca99 6188 end = Fnext_single_property_change (position, prop_name, string, limit);
82641697
GM
6189 if (INTEGERP (end))
6190 *endptr = XFASTINT (end);
6191 else
6192 *endptr = -1;
6193
6194 base_face = FACE_FROM_ID (f, base_face_id);
6195 xassert (base_face);
6196
6197 /* Optimize the default case that there is no face property and we
6198 are not in the region. */
6199 if (NILP (prop)
6200 && (base_face_id != DEFAULT_FACE_ID
6201 /* BUFPOS <= 0 means STRING is not an overlay string, so
6202 that the region doesn't have to be taken into account. */
6203 || bufpos <= 0
6204 || bufpos < region_beg
6205 || bufpos >= region_end)
6206 && (multibyte_p
6207 /* We can't realize faces for different charsets differently
6208 if we don't have fonts, so we can stop here if not working
6209 on a window-system frame. */
6210 || !FRAME_WINDOW_P (f)
239f9db9 6211 || FACE_SUITABLE_FOR_ASCII_CHAR_P (base_face, 0)))
82641697
GM
6212 return base_face->id;
6213
6214 /* Begin with attributes from the base face. */
72af86bd 6215 memcpy (attrs, base_face->lface, sizeof attrs);
82641697
GM
6216
6217 /* Merge in attributes specified via text properties. */
6218 if (!NILP (prop))
a0a23346 6219 merge_face_ref (f, prop, attrs, 1, 0);
82641697
GM
6220
6221 /* If in the region, merge in the region face. */
6222 if (bufpos
6223 && bufpos >= region_beg
6224 && bufpos < region_end)
a0a23346 6225 merge_named_face (f, Qregion, attrs, 0);
660ed669 6226
82641697 6227 /* Look up a realized face with the given face attributes,
39506348 6228 or realize a new one for ASCII characters. */
af53b43c 6229 return lookup_face (f, attrs);
660ed669
JB
6230}
6231
6232
fd998c7f
KS
6233/* Merge a face into a realized face.
6234
6235 F is frame where faces are (to be) realized.
6236
dc91a0ed
KS
6237 FACE_NAME is named face to merge.
6238
6239 If FACE_NAME is nil, FACE_ID is face_id of realized face to merge.
6240
6241 If FACE_NAME is t, FACE_ID is lface_id of face to merge.
fd998c7f
KS
6242
6243 BASE_FACE_ID is realized face to merge into.
6244
dc91a0ed 6245 Return new face id.
fd998c7f
KS
6246*/
6247
6248int
9910e595
PE
6249merge_faces (struct frame *f, Lisp_Object face_name, EMACS_INT face_id,
6250 int base_face_id)
fd998c7f
KS
6251{
6252 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6253 struct face *base_face;
6254
6255 base_face = FACE_FROM_ID (f, base_face_id);
6256 if (!base_face)
6257 return base_face_id;
6258
dc91a0ed
KS
6259 if (EQ (face_name, Qt))
6260 {
6261 if (face_id < 0 || face_id >= lface_id_to_name_size)
6262 return base_face_id;
6263 face_name = lface_id_to_name[face_id];
d8453278
CY
6264 /* When called during make-frame, lookup_derived_face may fail
6265 if the faces are uninitialized. Don't signal an error. */
6266 face_id = lookup_derived_face (f, face_name, base_face_id, 0);
6267 return (face_id >= 0 ? face_id : base_face_id);
dc91a0ed
KS
6268 }
6269
fd998c7f 6270 /* Begin with attributes from the base face. */
72af86bd 6271 memcpy (attrs, base_face->lface, sizeof attrs);
fd998c7f
KS
6272
6273 if (!NILP (face_name))
6274 {
6275 if (!merge_named_face (f, face_name, attrs, 0))
6276 return base_face_id;
6277 }
6278 else
6279 {
6280 struct face *face;
dc91a0ed
KS
6281 if (face_id < 0)
6282 return base_face_id;
fd998c7f
KS
6283 face = FACE_FROM_ID (f, face_id);
6284 if (!face)
6285 return base_face_id;
6286 merge_face_vectors (f, face->lface, attrs, 0);
6287 }
6288
6289 /* Look up a realized face with the given face attributes,
6290 or realize a new one for ASCII characters. */
0e3ae538 6291 return lookup_face (f, attrs);
fd998c7f
KS
6292}
6293
c115973b 6294\f
7ded3383
AR
6295
6296#ifndef HAVE_X_WINDOWS
6297DEFUN ("x-load-color-file", Fx_load_color_file,
6298 Sx_load_color_file, 1, 1, 0,
6299 doc: /* Create an alist of color entries from an external file.
6300
6301The file should define one named RGB color per line like so:
6302 R G B name
6303where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
5842a27b 6304 (Lisp_Object filename)
7ded3383
AR
6305{
6306 FILE *fp;
6307 Lisp_Object cmap = Qnil;
6308 Lisp_Object abspath;
6309
6310 CHECK_STRING (filename);
6311 abspath = Fexpand_file_name (filename, Qnil);
6312
45763476 6313 fp = fopen (SDATA (abspath), "rt");
7ded3383
AR
6314 if (fp)
6315 {
6316 char buf[512];
6317 int red, green, blue;
6318 int num;
6319
6320 BLOCK_INPUT;
6321
6322 while (fgets (buf, sizeof (buf), fp) != NULL) {
6323 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
6324 {
6325 char *name = buf + num;
6326 num = strlen (name) - 1;
40aa3f13 6327 if (num >= 0 && name[num] == '\n')
7ded3383
AR
6328 name[num] = 0;
6329 cmap = Fcons (Fcons (build_string (name),
dee8cd43
JB
6330#ifdef WINDOWSNT
6331 make_number (RGB (red, green, blue))),
ebadbfa6 6332#else
dee8cd43 6333 make_number ((red << 16) | (green << 8) | blue)),
ebadbfa6 6334#endif
7ded3383
AR
6335 cmap);
6336 }
6337 }
6338 fclose (fp);
6339
6340 UNBLOCK_INPUT;
6341 }
6342
6343 return cmap;
6344}
6345#endif
6346
6347\f
82641697
GM
6348/***********************************************************************
6349 Tests
6350 ***********************************************************************/
c115973b 6351
82641697 6352#if GLYPH_DEBUG
c115973b 6353
82641697 6354/* Print the contents of the realized face FACE to stderr. */
c115973b 6355
82641697 6356static void
7d7d0045 6357dump_realized_face (struct face *face)
82641697
GM
6358{
6359 fprintf (stderr, "ID: %d\n", face->id);
6360#ifdef HAVE_X_WINDOWS
2defe37f 6361 fprintf (stderr, "gc: %ld\n", (long) face->gc);
82641697
GM
6362#endif
6363 fprintf (stderr, "foreground: 0x%lx (%s)\n",
6364 face->foreground,
d5db4077 6365 SDATA (face->lface[LFACE_FOREGROUND_INDEX]));
82641697
GM
6366 fprintf (stderr, "background: 0x%lx (%s)\n",
6367 face->background,
d5db4077 6368 SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
2dee4c0b
KH
6369 if (face->font)
6370 fprintf (stderr, "font_name: %s (%s)\n",
6371 SDATA (face->font->props[FONT_NAME_INDEX]),
6372 SDATA (face->lface[LFACE_FAMILY_INDEX]));
82641697
GM
6373#ifdef HAVE_X_WINDOWS
6374 fprintf (stderr, "font = %p\n", face->font);
6375#endif
82641697
GM
6376 fprintf (stderr, "fontset: %d\n", face->fontset);
6377 fprintf (stderr, "underline: %d (%s)\n",
6378 face->underline_p,
d5db4077 6379 SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
82641697 6380 fprintf (stderr, "hash: %d\n", face->hash);
c115973b
JB
6381}
6382
6383
a7ca3326 6384DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */)
5842a27b 6385 (Lisp_Object n)
c115973b 6386{
82641697 6387 if (NILP (n))
c115973b 6388 {
82641697 6389 int i;
178c5d9c 6390
82641697
GM
6391 fprintf (stderr, "font selection order: ");
6392 for (i = 0; i < DIM (font_sort_order); ++i)
6393 fprintf (stderr, "%d ", font_sort_order[i]);
6394 fprintf (stderr, "\n");
6395
6396 fprintf (stderr, "alternative fonts: ");
6397 debug_print (Vface_alternative_font_family_alist);
6398 fprintf (stderr, "\n");
178c5d9c 6399
c0617987 6400 for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
82641697 6401 Fdump_face (make_number (i));
c115973b
JB
6402 }
6403 else
f5e278c7 6404 {
82641697 6405 struct face *face;
b7826503 6406 CHECK_NUMBER (n);
c0617987 6407 face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
82641697
GM
6408 if (face == NULL)
6409 error ("Not a valid face");
6410 dump_realized_face (face);
f5e278c7 6411 }
178c5d9c 6412
c115973b
JB
6413 return Qnil;
6414}
b5c53576 6415
b5c53576 6416
a7ca3326 6417DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
7ee72033 6418 0, 0, 0, doc: /* */)
5842a27b 6419 (void)
b5c53576 6420{
82641697
GM
6421 fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
6422 fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
6423 fprintf (stderr, "number of GCs = %d\n", ngcs);
6424 return Qnil;
b5c53576
RS
6425}
6426
82641697
GM
6427#endif /* GLYPH_DEBUG != 0 */
6428
b5c53576 6429
c115973b 6430\f
82641697
GM
6431/***********************************************************************
6432 Initialization
6433 ***********************************************************************/
cb637678 6434
c115973b 6435void
971de7fb 6436syms_of_xfaces (void)
c115973b 6437{
cd3520a4
JB
6438 DEFSYM (Qface, "face");
6439 DEFSYM (Qface_no_inherit, "face-no-inherit");
6440 DEFSYM (Qbitmap_spec_p, "bitmap-spec-p");
6441 DEFSYM (Qframe_set_background_mode, "frame-set-background-mode");
178c5d9c 6442
82641697 6443 /* Lisp face attribute keywords. */
cd3520a4
JB
6444 DEFSYM (QCfamily, ":family");
6445 DEFSYM (QCheight, ":height");
6446 DEFSYM (QCweight, ":weight");
6447 DEFSYM (QCslant, ":slant");
6448 DEFSYM (QCunderline, ":underline");
6449 DEFSYM (QCinverse_video, ":inverse-video");
6450 DEFSYM (QCreverse_video, ":reverse-video");
6451 DEFSYM (QCforeground, ":foreground");
6452 DEFSYM (QCbackground, ":background");
6453 DEFSYM (QCstipple, ":stipple");
6454 DEFSYM (QCwidth, ":width");
6455 DEFSYM (QCfont, ":font");
6456 DEFSYM (QCfontset, ":fontset");
6457 DEFSYM (QCbold, ":bold");
6458 DEFSYM (QCitalic, ":italic");
6459 DEFSYM (QCoverline, ":overline");
6460 DEFSYM (QCstrike_through, ":strike-through");
6461 DEFSYM (QCbox, ":box");
6462 DEFSYM (QCinherit, ":inherit");
82641697
GM
6463
6464 /* Symbols used for Lisp face attribute values. */
cd3520a4
JB
6465 DEFSYM (QCcolor, ":color");
6466 DEFSYM (QCline_width, ":line-width");
6467 DEFSYM (QCstyle, ":style");
6468 DEFSYM (Qreleased_button, "released-button");
6469 DEFSYM (Qpressed_button, "pressed-button");
6470 DEFSYM (Qnormal, "normal");
6471 DEFSYM (Qultra_light, "ultra-light");
6472 DEFSYM (Qextra_light, "extra-light");
6473 DEFSYM (Qlight, "light");
6474 DEFSYM (Qsemi_light, "semi-light");
6475 DEFSYM (Qsemi_bold, "semi-bold");
6476 DEFSYM (Qbold, "bold");
6477 DEFSYM (Qextra_bold, "extra-bold");
6478 DEFSYM (Qultra_bold, "ultra-bold");
6479 DEFSYM (Qoblique, "oblique");
6480 DEFSYM (Qitalic, "italic");
6481 DEFSYM (Qreverse_oblique, "reverse-oblique");
6482 DEFSYM (Qreverse_italic, "reverse-italic");
6483 DEFSYM (Qultra_condensed, "ultra-condensed");
6484 DEFSYM (Qextra_condensed, "extra-condensed");
6485 DEFSYM (Qcondensed, "condensed");
6486 DEFSYM (Qsemi_condensed, "semi-condensed");
6487 DEFSYM (Qsemi_expanded, "semi-expanded");
6488 DEFSYM (Qexpanded, "expanded");
6489 DEFSYM (Qextra_expanded, "extra-expanded");
6490 DEFSYM (Qultra_expanded, "ultra-expanded");
6491 DEFSYM (Qbackground_color, "background-color");
6492 DEFSYM (Qforeground_color, "foreground-color");
6493 DEFSYM (Qunspecified, "unspecified");
a3720aa2 6494 DEFSYM (QCignore_defface, ":ignore-defface");
cd3520a4
JB
6495
6496 DEFSYM (Qface_alias, "face-alias");
6497 DEFSYM (Qdefault, "default");
6498 DEFSYM (Qtool_bar, "tool-bar");
6499 DEFSYM (Qregion, "region");
6500 DEFSYM (Qfringe, "fringe");
6501 DEFSYM (Qheader_line, "header-line");
6502 DEFSYM (Qscroll_bar, "scroll-bar");
6503 DEFSYM (Qmenu, "menu");
6504 DEFSYM (Qcursor, "cursor");
6505 DEFSYM (Qborder, "border");
6506 DEFSYM (Qmouse, "mouse");
6507 DEFSYM (Qmode_line_inactive, "mode-line-inactive");
6508 DEFSYM (Qvertical_border, "vertical-border");
6509 DEFSYM (Qtty_color_desc, "tty-color-desc");
6510 DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
6511 DEFSYM (Qtty_color_by_index, "tty-color-by-index");
6512 DEFSYM (Qtty_color_alist, "tty-color-alist");
6513 DEFSYM (Qscalable_fonts_allowed, "scalable-fonts-allowed");
82641697 6514
dbc968b8
GM
6515 Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
6516 staticpro (&Vparam_value_alist);
434b9cc5
GM
6517 Vface_alternative_font_family_alist = Qnil;
6518 staticpro (&Vface_alternative_font_family_alist);
32fcc231
GM
6519 Vface_alternative_font_registry_alist = Qnil;
6520 staticpro (&Vface_alternative_font_registry_alist);
434b9cc5 6521
82641697
GM
6522 defsubr (&Sinternal_make_lisp_face);
6523 defsubr (&Sinternal_lisp_face_p);
6524 defsubr (&Sinternal_set_lisp_face_attribute);
c3cee013 6525#ifdef HAVE_WINDOW_SYSTEM
82641697 6526 defsubr (&Sinternal_set_lisp_face_attribute_from_resource);
42608ba8 6527#endif
ea4fa0af
GM
6528 defsubr (&Scolor_gray_p);
6529 defsubr (&Scolor_supported_p);
7ded3383
AR
6530#ifndef HAVE_X_WINDOWS
6531 defsubr (&Sx_load_color_file);
6532#endif
cdfaafa9
MB
6533 defsubr (&Sface_attribute_relative_p);
6534 defsubr (&Smerge_face_attribute);
82641697
GM
6535 defsubr (&Sinternal_get_lisp_face_attribute);
6536 defsubr (&Sinternal_lisp_face_attribute_values);
6537 defsubr (&Sinternal_lisp_face_equal_p);
6538 defsubr (&Sinternal_lisp_face_empty_p);
6539 defsubr (&Sinternal_copy_lisp_face);
6540 defsubr (&Sinternal_merge_in_global_face);
6541 defsubr (&Sface_font);
6542 defsubr (&Sframe_face_alist);
9717e36c 6543 defsubr (&Sdisplay_supports_face_attributes_p);
b35df831 6544 defsubr (&Scolor_distance);
82641697
GM
6545 defsubr (&Sinternal_set_font_selection_order);
6546 defsubr (&Sinternal_set_alternative_font_family_alist);
32fcc231 6547 defsubr (&Sinternal_set_alternative_font_registry_alist);
f6608d5c 6548 defsubr (&Sface_attributes_as_vector);
82641697
GM
6549#if GLYPH_DEBUG
6550 defsubr (&Sdump_face);
6551 defsubr (&Sshow_face_resources);
6552#endif /* GLYPH_DEBUG */
6553 defsubr (&Sclear_face_cache);
a4a76b61 6554 defsubr (&Stty_suppress_bold_inverse_default_colors);
82641697 6555
38426dee 6556#if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
08dc08dc
GM
6557 defsubr (&Sdump_colors);
6558#endif
6559
29208e82 6560 DEFVAR_LISP ("font-list-limit", Vfont_list_limit,
7ee72033 6561 doc: /* *Limit for font matching.
228299fa
GM
6562If an integer > 0, font matching functions won't load more than
6563that number of fonts when searching for a matching font. */);
057df17c
GM
6564 Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
6565
29208e82 6566 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults,
7ee72033 6567 doc: /* List of global face definitions (for internal use only.) */);
82641697 6568 Vface_new_frame_defaults = Qnil;
178c5d9c 6569
29208e82 6570 DEFVAR_LISP ("face-default-stipple", Vface_default_stipple,
7ee72033 6571 doc: /* *Default stipple pattern used on monochrome displays.
228299fa
GM
6572This stipple pattern is used on monochrome displays
6573instead of shades of gray for a face background color.
6574See `set-face-stipple' for possible values for this variable. */);
a4ada374 6575 Vface_default_stipple = make_pure_c_string ("gray3");
82641697 6576
29208e82 6577 DEFVAR_LISP ("tty-defined-color-alist", Vtty_defined_color_alist,
46710489
GM
6578 doc: /* An alist of defined terminal colors and their RGB values.
6579See the docstring of `tty-color-alist' for the details. */);
ae4b4ba5
GM
6580 Vtty_defined_color_alist = Qnil;
6581
29208e82 6582 DEFVAR_LISP ("scalable-fonts-allowed", Vscalable_fonts_allowed,
7ee72033 6583 doc: /* Allowed scalable fonts.
228299fa
GM
6584A value of nil means don't allow any scalable fonts.
6585A value of t means allow any scalable font.
6586Otherwise, value must be a list of regular expressions. A font may be
6587scaled if its name matches a regular expression in the list.
6588Note that if value is nil, a scalable font might still be used, if no
6589other font of the appropriate family and registry is available. */);
3cf80731 6590 Vscalable_fonts_allowed = Qnil;
b5c53576 6591
29208e82 6592 DEFVAR_LISP ("face-ignored-fonts", Vface_ignored_fonts,
7ee72033 6593 doc: /* List of ignored fonts.
228299fa
GM
6594Each element is a regular expression that matches names of fonts to
6595ignore. */);
c824bfbc
KH
6596 Vface_ignored_fonts = Qnil;
6597
29208e82 6598 DEFVAR_LISP ("face-remapping-alist", Vface_remapping_alist,
f2cec7a9
MB
6599 doc: /* Alist of face remappings.
6600Each element is of the form:
6601
6602 (FACE REPLACEMENT...),
6603
6604which causes display of the face FACE to use REPLACEMENT... instead.
635c0aa1
CY
6605REPLACEMENT... is interpreted the same way as the value of a `face'
6606text property: it may be (1) A face name, (2) A list of face names,
6607(3) A property-list of face attribute/value pairs, or (4) A list of
6608face names or lists containing face attribute/value pairs.
f2cec7a9
MB
6609
6610Multiple entries in REPLACEMENT... are merged together to form the final
6611result, with faces or attributes earlier in the list taking precedence
6612over those that are later.
6613
6614Face-name remapping cycles are suppressed; recursive references use the
6615underlying face instead of the remapped face. So a remapping of the form:
6616
6617 (FACE EXTRA-FACE... FACE)
6618
6619or:
6620
6621 (FACE (FACE-ATTR VAL ...) FACE)
6622
6623will cause EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
6624existing definition of FACE. Note that for the default face, this isn't
6625necessary, as every face inherits from the default face.
6626
6627Making this variable buffer-local is a good way to allow buffer-specific
6628face definitions. For instance, the mode my-mode could define a face
6629`my-mode-default', and then in the mode setup function, do:
6630
6631 (set (make-local-variable 'face-remapping-alist)
b5f03016 6632 '((default my-mode-default)))).
635c0aa1
CY
6633
6634Because Emacs normally only redraws screen areas when the underlying
6635buffer contents change, you may need to call `redraw-display' after
6636changing this variable for it to take effect. */);
f2cec7a9
MB
6637 Vface_remapping_alist = Qnil;
6638
29208e82 6639 DEFVAR_LISP ("face-font-rescale-alist", Vface_font_rescale_alist,
f70400f2 6640 doc: /* Alist of fonts vs the rescaling factors.
96f9306b
KH
6641Each element is a cons (FONT-PATTERN . RESCALE-RATIO), where
6642FONT-PATTERN is a font-spec or a regular expression matching a font name, and
f70400f2
KH
6643RESCALE-RATIO is a floating point number to specify how much larger
6644\(or smaller) font we should use. For instance, if a face requests
6645a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point. */);
6646 Vface_font_rescale_alist = Qnil;
6647
c3cee013 6648#ifdef HAVE_WINDOW_SYSTEM
fef04523 6649 defsubr (&Sbitmap_spec_p);
82641697
GM
6650 defsubr (&Sx_list_fonts);
6651 defsubr (&Sinternal_face_x_get_resource);
92610620 6652 defsubr (&Sx_family_fonts);
32247e3d 6653#endif
c115973b 6654}