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