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