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