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