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