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