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