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