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