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