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