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