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