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