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