Include "font.h".
[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
3631 ASET (lface, LFACE_FONT_INDEX, Ffont_xlfd_name (font->entity));
3632 ASET (lface, LFACE_FONTSET_INDEX, fontset_name (fontset));
3633 return 1;
3634 }
3635#endif /* USE_FONT_BACKEND */
25b1546d 3636 if (fontset > 0)
d5db4077 3637 font_name = SDATA (fontset_ascii (fontset));
25b1546d
KH
3638 else if (fontset == 0)
3639 {
3640 if (may_fail_p)
3641 return 0;
3642 abort ();
3643 }
39506348
KH
3644
3645 /* Check if FONT_NAME is surely available on the system. Usually
3646 FONT_NAME is already cached for the frame F and FS_LOAD_FONT
3647 returns quickly. But, even if FONT_NAME is not yet cached,
3648 caching it now is not futail because we anyway load the font
3649 later. */
3650 BLOCK_INPUT;
81b39386 3651 font_info = FS_LOAD_FONT (f, font_name);
39506348 3652 UNBLOCK_INPUT;
82641697 3653
39506348 3654 if (!font_info)
3221576b
GM
3655 {
3656 if (may_fail_p)
3657 return 0;
39506348 3658 abort ();
3221576b 3659 }
39506348
KH
3660
3661 font.name = STRDUPA (font_info->full_name);
3662 have_xlfd_p = split_font_name (f, &font, 1);
3221576b 3663
82641697 3664 /* Set attributes only if unspecified, otherwise face defaults for
39506348
KH
3665 new frames would never take effect. If we couldn't get a font
3666 name conforming to XLFD, set normal values. */
178c5d9c 3667
82641697
GM
3668 if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
3669 {
39506348
KH
3670 Lisp_Object val;
3671 if (have_xlfd_p)
3672 {
3673 buffer = (char *) alloca (strlen (font.fields[XLFD_FAMILY])
3674 + strlen (font.fields[XLFD_FOUNDRY])
3675 + 2);
3676 sprintf (buffer, "%s-%s", font.fields[XLFD_FOUNDRY],
3677 font.fields[XLFD_FAMILY]);
3678 val = build_string (buffer);
3679 }
3680 else
3681 val = build_string ("*");
3682 LFACE_FAMILY (lface) = val;
82641697
GM
3683 }
3684
3685 if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
3686 {
39506348
KH
3687 if (have_xlfd_p)
3688 pt = xlfd_point_size (f, &font);
3689 else
3690 pt = pixel_point_size (f, font_info->height * 10);
82641697
GM
3691 xassert (pt > 0);
3692 LFACE_HEIGHT (lface) = make_number (pt);
3693 }
3694
3695 if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
39506348
KH
3696 LFACE_SWIDTH (lface)
3697 = have_xlfd_p ? xlfd_symbolic_swidth (&font) : Qnormal;
82641697 3698
a08332c0
GM
3699 if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
3700 LFACE_AVGWIDTH (lface)
3701 = (have_xlfd_p
3702 ? make_number (font.numeric[XLFD_AVGWIDTH])
3703 : Qunspecified);
3704
82641697 3705 if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
39506348
KH
3706 LFACE_WEIGHT (lface)
3707 = have_xlfd_p ? xlfd_symbolic_weight (&font) : Qnormal;
82641697
GM
3708
3709 if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
39506348
KH
3710 LFACE_SLANT (lface)
3711 = have_xlfd_p ? xlfd_symbolic_slant (&font) : Qnormal;
82641697 3712
21228b3d 3713 if (fontset > 0)
763bc839
KH
3714 {
3715 LFACE_FONT (lface) = build_string (font_info->full_name);
3716 LFACE_FONTSET (lface) = fontset_name (fontset);
3717 }
3718 else
7f8005cd
KH
3719 {
3720 LFACE_FONT (lface) = fontname;
3721 fontset
3722 = new_fontset_from_font_name (build_string (font_info->full_name));
3723 LFACE_FONTSET (lface) = fontset_name (fontset);
3724 }
82641697
GM
3725 return 1;
3726}
d12d0a9b 3727
c3cee013 3728#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
3729
3730
2c20458f
MB
3731/* Merges the face height FROM with the face height TO, and returns the
3732 merged height. If FROM is an invalid height, then INVALID is
cdfaafa9
MB
3733 returned instead. FROM and TO may be either absolute face heights or
3734 `relative' heights; the returned value is always an absolute height
3735 unless both FROM and TO are relative. GCPRO is a lisp value that
3736 will be protected from garbage-collection if this function makes a
3737 call into lisp. */
2c20458f
MB
3738
3739Lisp_Object
e1e419ec
RS
3740merge_face_heights (from, to, invalid)
3741 Lisp_Object from, to, invalid;
2c20458f 3742{
cdfaafa9 3743 Lisp_Object result = invalid;
2c20458f
MB
3744
3745 if (INTEGERP (from))
cdfaafa9
MB
3746 /* FROM is absolute, just use it as is. */
3747 result = from;
3748 else if (FLOATP (from))
3749 /* FROM is a scale, use it to adjust TO. */
3750 {
3751 if (INTEGERP (to))
3752 /* relative X absolute => absolute */
c319cf24 3753 result = make_number ((EMACS_INT)(XFLOAT_DATA (from) * XINT (to)));
cdfaafa9
MB
3754 else if (FLOATP (to))
3755 /* relative X relative => relative */
3756 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
a0a23346
MB
3757 else if (UNSPECIFIEDP (to))
3758 result = from;
2c20458f 3759 }
2c20458f 3760 else if (FUNCTIONP (from))
cdfaafa9 3761 /* FROM is a function, which use to adjust TO. */
2c20458f
MB
3762 {
3763 /* Call function with current height as argument.
3764 From is the new height. */
cdfaafa9 3765 Lisp_Object args[2];
2c20458f
MB
3766
3767 args[0] = from;
3768 args[1] = to;
cdfaafa9 3769 result = safe_call (2, args);
2c20458f 3770
cdfaafa9
MB
3771 /* Ensure that if TO was absolute, so is the result. */
3772 if (INTEGERP (to) && !INTEGERP (result))
3773 result = invalid;
2c20458f
MB
3774 }
3775
cdfaafa9 3776 return result;
2c20458f
MB
3777}
3778
3779
3780/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
613fa7f2
MB
3781 store the resulting attributes in TO, which must be already be
3782 completely specified and contain only absolute attributes. Every
3783 specified attribute of FROM overrides the corresponding attribute of
3784 TO; relative attributes in FROM are merged with the absolute value in
a0a23346
MB
3785 TO and replace it. NAMED_MERGE_POINTS is used internally to detect
3786 loops in face inheritance; it should be 0 when called from other
3787 places. */
82641697
GM
3788
3789static INLINE void
a0a23346 3790merge_face_vectors (f, from, to, named_merge_points)
2c20458f 3791 struct frame *f;
82641697 3792 Lisp_Object *from, *to;
a0a23346 3793 struct named_merge_point *named_merge_points;
82641697
GM
3794{
3795 int i;
2c20458f
MB
3796
3797 /* If FROM inherits from some other faces, merge their attributes into
3798 TO before merging FROM's direct attributes. Note that an :inherit
3799 attribute of `unspecified' is the same as one of nil; we never
3800 merge :inherit attributes, so nil is more correct, but lots of
3801 other code uses `unspecified' as a generic value for face attributes. */
3802 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
3803 && !NILP (from[LFACE_INHERIT_INDEX]))
a0a23346 3804 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
2c20458f 3805
87188200
MB
3806 /* If TO specifies a :font attribute, and FROM specifies some
3807 font-related attribute, we need to clear TO's :font attribute
3808 (because it will be inconsistent with whatever FROM specifies, and
3809 FROM takes precedence). */
3810 if (!NILP (to[LFACE_FONT_INDEX])
3811 && (!UNSPECIFIEDP (from[LFACE_FAMILY_INDEX])
3812 || !UNSPECIFIEDP (from[LFACE_HEIGHT_INDEX])
3813 || !UNSPECIFIEDP (from[LFACE_WEIGHT_INDEX])
3814 || !UNSPECIFIEDP (from[LFACE_SLANT_INDEX])
a08332c0
GM
3815 || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])
3816 || !UNSPECIFIEDP (from[LFACE_AVGWIDTH_INDEX])))
87188200
MB
3817 to[LFACE_FONT_INDEX] = Qnil;
3818
82641697
GM
3819 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
3820 if (!UNSPECIFIEDP (from[i]))
ab8469eb
PJ
3821 {
3822 if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
e1e419ec 3823 to[i] = merge_face_heights (from[i], to[i], to[i]);
ab8469eb
PJ
3824 else
3825 to[i] = from[i];
3826 }
2c20458f
MB
3827
3828 /* TO is always an absolute face, which should inherit from nothing.
3829 We blindly copy the :inherit attribute above and fix it up here. */
3830 to[LFACE_INHERIT_INDEX] = Qnil;
3831}
3832
a0a23346
MB
3833/* Merge the named face FACE_NAME on frame F, into the vector of face
3834 attributes TO. NAMED_MERGE_POINTS is used to detect loops in face
3835 inheritance. Returns true if FACE_NAME is a valid face name and
3836 merging succeeded. */
6288c62f 3837
a0a23346
MB
3838static int
3839merge_named_face (f, face_name, to, named_merge_points)
2c20458f 3840 struct frame *f;
a0a23346 3841 Lisp_Object face_name;
2c20458f 3842 Lisp_Object *to;
a0a23346 3843 struct named_merge_point *named_merge_points;
2c20458f 3844{
a0a23346 3845 struct named_merge_point named_merge_point;
2c20458f 3846
a0a23346
MB
3847 if (push_named_merge_point (&named_merge_point,
3848 face_name, &named_merge_points))
2c20458f 3849 {
e1e419ec 3850 struct gcpro gcpro1;
a0a23346
MB
3851 Lisp_Object from[LFACE_VECTOR_SIZE];
3852 int ok = get_lface_attributes (f, face_name, from, 0);
2c20458f 3853
a0a23346 3854 if (ok)
e1e419ec
RS
3855 {
3856 GCPRO1 (named_merge_point.face_name);
3857 merge_face_vectors (f, from, to, named_merge_points);
3858 UNGCPRO;
3859 }
2c20458f 3860
a0a23346 3861 return ok;
2c20458f 3862 }
a0a23346
MB
3863 else
3864 return 0;
82641697
GM
3865}
3866
3867
a0a23346
MB
3868/* Merge face attributes from the lisp `face reference' FACE_REF on
3869 frame F into the face attribute vector TO. If ERR_MSGS is non-zero,
3870 problems with FACE_REF cause an error message to be shown. Return
3871 non-zero if no errors occurred (regardless of the value of ERR_MSGS).
3872 NAMED_MERGE_POINTS is used to detect loops in face inheritance or
3873 list structure; it may be 0 for most callers.
3874
3875 FACE_REF may be a single face specification or a list of such
3876 specifications. Each face specification can be:
82641697
GM
3877
3878 1. A symbol or string naming a Lisp face.
3879
3880 2. A property list of the form (KEYWORD VALUE ...) where each
3881 KEYWORD is a face attribute name, and value is an appropriate value
3882 for that attribute.
3883
3884 3. Conses or the form (FOREGROUND-COLOR . COLOR) or
3885 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is
3886 for compatibility with 20.2.
3887
3888 Face specifications earlier in lists take precedence over later
3889 specifications. */
178c5d9c 3890
a0a23346
MB
3891static int
3892merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
82641697 3893 struct frame *f;
a0a23346 3894 Lisp_Object face_ref;
82641697 3895 Lisp_Object *to;
a0a23346
MB
3896 int err_msgs;
3897 struct named_merge_point *named_merge_points;
82641697 3898{
a0a23346
MB
3899 int ok = 1; /* Succeed without an error? */
3900
3901 if (CONSP (face_ref))
82641697 3902 {
a0a23346 3903 Lisp_Object first = XCAR (face_ref);
178c5d9c 3904
82641697
GM
3905 if (EQ (first, Qforeground_color)
3906 || EQ (first, Qbackground_color))
3907 {
3908 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
3909 . COLOR). COLOR must be a string. */
a0a23346 3910 Lisp_Object color_name = XCDR (face_ref);
82641697
GM
3911 Lisp_Object color = first;
3912
3913 if (STRINGP (color_name))
3914 {
3915 if (EQ (color, Qforeground_color))
3916 to[LFACE_FOREGROUND_INDEX] = color_name;
3917 else
3918 to[LFACE_BACKGROUND_INDEX] = color_name;
3919 }
3920 else
a0a23346
MB
3921 {
3922 if (err_msgs)
3923 add_to_log ("Invalid face color", color_name, Qnil);
3924 ok = 0;
3925 }
82641697
GM
3926 }
3927 else if (SYMBOLP (first)
d5db4077 3928 && *SDATA (SYMBOL_NAME (first)) == ':')
82641697
GM
3929 {
3930 /* Assume this is the property list form. */
a0a23346 3931 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
82641697 3932 {
a0a23346
MB
3933 Lisp_Object keyword = XCAR (face_ref);
3934 Lisp_Object value = XCAR (XCDR (face_ref));
3935 int err = 0;
82641697 3936
d9639b25
RS
3937 /* Specifying `unspecified' is a no-op. */
3938 if (EQ (value, Qunspecified))
3939 ;
3940 else if (EQ (keyword, QCfamily))
82641697
GM
3941 {
3942 if (STRINGP (value))
3943 to[LFACE_FAMILY_INDEX] = value;
3944 else
a0a23346 3945 err = 1;
82641697
GM
3946 }
3947 else if (EQ (keyword, QCheight))
3948 {
2c20458f 3949 Lisp_Object new_height =
e1e419ec 3950 merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil);
2c20458f 3951
a0a23346 3952 if (! NILP (new_height))
2c20458f 3953 to[LFACE_HEIGHT_INDEX] = new_height;
a0a23346
MB
3954 else
3955 err = 1;
82641697
GM
3956 }
3957 else if (EQ (keyword, QCweight))
3958 {
3959 if (SYMBOLP (value)
3960 && face_numeric_weight (value) >= 0)
3961 to[LFACE_WEIGHT_INDEX] = value;
3962 else
a0a23346 3963 err = 1;
82641697
GM
3964 }
3965 else if (EQ (keyword, QCslant))
3966 {
3967 if (SYMBOLP (value)
3968 && face_numeric_slant (value) >= 0)
3969 to[LFACE_SLANT_INDEX] = value;
3970 else
a0a23346 3971 err = 1;
82641697
GM
3972 }
3973 else if (EQ (keyword, QCunderline))
3974 {
3975 if (EQ (value, Qt)
3976 || NILP (value)
3977 || STRINGP (value))
3978 to[LFACE_UNDERLINE_INDEX] = value;
3979 else
a0a23346 3980 err = 1;
82641697
GM
3981 }
3982 else if (EQ (keyword, QCoverline))
3983 {
3984 if (EQ (value, Qt)
3985 || NILP (value)
3986 || STRINGP (value))
3987 to[LFACE_OVERLINE_INDEX] = value;
3988 else
a0a23346 3989 err = 1;
82641697
GM
3990 }
3991 else if (EQ (keyword, QCstrike_through))
3992 {
3993 if (EQ (value, Qt)
3994 || NILP (value)
3995 || STRINGP (value))
3996 to[LFACE_STRIKE_THROUGH_INDEX] = value;
3997 else
a0a23346 3998 err = 1;
82641697
GM
3999 }
4000 else if (EQ (keyword, QCbox))
4001 {
4002 if (EQ (value, Qt))
4003 value = make_number (1);
4004 if (INTEGERP (value)
4005 || STRINGP (value)
4006 || CONSP (value)
4007 || NILP (value))
4008 to[LFACE_BOX_INDEX] = value;
4009 else
a0a23346 4010 err = 1;
82641697
GM
4011 }
4012 else if (EQ (keyword, QCinverse_video)
4013 || EQ (keyword, QCreverse_video))
4014 {
4015 if (EQ (value, Qt) || NILP (value))
4016 to[LFACE_INVERSE_INDEX] = value;
4017 else
a0a23346 4018 err = 1;
82641697
GM
4019 }
4020 else if (EQ (keyword, QCforeground))
4021 {
4022 if (STRINGP (value))
4023 to[LFACE_FOREGROUND_INDEX] = value;
4024 else
a0a23346 4025 err = 1;
82641697
GM
4026 }
4027 else if (EQ (keyword, QCbackground))
4028 {
4029 if (STRINGP (value))
4030 to[LFACE_BACKGROUND_INDEX] = value;
4031 else
a0a23346 4032 err = 1;
82641697
GM
4033 }
4034 else if (EQ (keyword, QCstipple))
4035 {
4036#ifdef HAVE_X_WINDOWS
fef04523 4037 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
82641697
GM
4038 if (!NILP (pixmap_p))
4039 to[LFACE_STIPPLE_INDEX] = value;
4040 else
a0a23346 4041 err = 1;
82641697
GM
4042#endif
4043 }
4044 else if (EQ (keyword, QCwidth))
4045 {
4046 if (SYMBOLP (value)
4047 && face_numeric_swidth (value) >= 0)
4048 to[LFACE_SWIDTH_INDEX] = value;
4049 else
a0a23346 4050 err = 1;
82641697 4051 }
2c20458f
MB
4052 else if (EQ (keyword, QCinherit))
4053 {
a0a23346
MB
4054 /* This is not really very useful; it's just like a
4055 normal face reference. */
4056 if (! merge_face_ref (f, value, to,
4057 err_msgs, named_merge_points))
4058 err = 1;
2c20458f 4059 }
82641697 4060 else
a0a23346 4061 err = 1;
82641697 4062
a0a23346
MB
4063 if (err)
4064 {
4065 add_to_log ("Invalid face attribute %S %S", keyword, value);
4066 ok = 0;
4067 }
82641697 4068
a0a23346 4069 face_ref = XCDR (XCDR (face_ref));
82641697
GM
4070 }
4071 }
4072 else
4073 {
a0a23346
MB
4074 /* This is a list of face refs. Those at the beginning of the
4075 list take precedence over what follows, so we have to merge
4076 from the end backwards. */
4077 Lisp_Object next = XCDR (face_ref);
4078
4079 if (! NILP (next))
4080 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points);
4081
4082 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points))
4083 ok = 0;
82641697
GM
4084 }
4085 }
4086 else
4087 {
a0a23346
MB
4088 /* FACE_REF ought to be a face name. */
4089 ok = merge_named_face (f, face_ref, to, named_merge_points);
4090 if (!ok && err_msgs)
4091 add_to_log ("Invalid face reference: %s", face_ref, Qnil);
82641697 4092 }
a0a23346
MB
4093
4094 return ok;
82641697
GM
4095}
4096
4097
4098DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
4099 Sinternal_make_lisp_face, 1, 2, 0,
7ee72033 4100 doc: /* Make FACE, a symbol, a Lisp face with all attributes nil.
228299fa
GM
4101If FACE was not known as a face before, create a new one.
4102If optional argument FRAME is specified, make a frame-local face
4103for that frame. Otherwise operate on the global face definition.
7ee72033
MB
4104Value is a vector of face attributes. */)
4105 (face, frame)
82641697
GM
4106 Lisp_Object face, frame;
4107{
4108 Lisp_Object global_lface, lface;
4109 struct frame *f;
4110 int i;
4111
b7826503 4112 CHECK_SYMBOL (face);
82641697 4113 global_lface = lface_from_face_name (NULL, face, 0);
178c5d9c 4114
82641697
GM
4115 if (!NILP (frame))
4116 {
b7826503 4117 CHECK_LIVE_FRAME (frame);
82641697
GM
4118 f = XFRAME (frame);
4119 lface = lface_from_face_name (f, face, 0);
4120 }
4121 else
4122 f = NULL, lface = Qnil;
4123
4124 /* Add a global definition if there is none. */
4125 if (NILP (global_lface))
4126 {
4127 global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4128 Qunspecified);
a08332c0 4129 AREF (global_lface, 0) = Qface;
178c5d9c 4130 Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
82641697 4131 Vface_new_frame_defaults);
178c5d9c 4132
82641697
GM
4133 /* Assign the new Lisp face a unique ID. The mapping from Lisp
4134 face id to Lisp face is given by the vector lface_id_to_name.
4135 The mapping from Lisp face to Lisp face id is given by the
4136 property `face' of the Lisp face name. */
4137 if (next_lface_id == lface_id_to_name_size)
4138 {
4139 int new_size = max (50, 2 * lface_id_to_name_size);
4140 int sz = new_size * sizeof *lface_id_to_name;
4141 lface_id_to_name = (Lisp_Object *) xrealloc (lface_id_to_name, sz);
4142 lface_id_to_name_size = new_size;
4143 }
178c5d9c 4144
82641697
GM
4145 lface_id_to_name[next_lface_id] = face;
4146 Fput (face, Qface, make_number (next_lface_id));
4147 ++next_lface_id;
4148 }
4149 else if (f == NULL)
4150 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
a08332c0 4151 AREF (global_lface, i) = Qunspecified;
178c5d9c 4152
82641697
GM
4153 /* Add a frame-local definition. */
4154 if (f)
4155 {
4156 if (NILP (lface))
4157 {
4158 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4159 Qunspecified);
a08332c0 4160 AREF (lface, 0) = Qface;
82641697
GM
4161 f->face_alist = Fcons (Fcons (face, lface), f->face_alist);
4162 }
4163 else
4164 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
a08332c0 4165 AREF (lface, i) = Qunspecified;
82641697
GM
4166 }
4167 else
4168 lface = global_lface;
4169
33565969
RS
4170 /* Changing a named face means that all realized faces depending on
4171 that face are invalid. Since we cannot tell which realized faces
4172 depend on the face, make sure they are all removed. This is done
4173 by incrementing face_change_count. The next call to
4174 init_iterator will then free realized faces. */
46b00436
KS
4175 if (NILP (Fget (face, Qface_no_inherit)))
4176 {
4177 ++face_change_count;
4178 ++windows_or_buffers_changed;
4179 }
33565969 4180
82641697
GM
4181 xassert (LFACEP (lface));
4182 check_lface (lface);
4183 return lface;
4184}
4185
4186
4187DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
4188 Sinternal_lisp_face_p, 1, 2, 0,
7ee72033 4189 doc: /* Return non-nil if FACE names a face.
1d256714 4190If optional second argument FRAME is non-nil, check for the
228299fa 4191existence of a frame-local face with name FACE on that frame.
7ee72033
MB
4192Otherwise check for the existence of a global face. */)
4193 (face, frame)
82641697
GM
4194 Lisp_Object face, frame;
4195{
4196 Lisp_Object lface;
178c5d9c 4197
82641697
GM
4198 if (!NILP (frame))
4199 {
b7826503 4200 CHECK_LIVE_FRAME (frame);
82641697
GM
4201 lface = lface_from_face_name (XFRAME (frame), face, 0);
4202 }
4203 else
4204 lface = lface_from_face_name (NULL, face, 0);
4205
4206 return lface;
4207}
4208
4209
4210DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
4211 Sinternal_copy_lisp_face, 4, 4, 0,
7ee72033 4212 doc: /* Copy face FROM to TO.
5e9bab6f
RS
4213If FRAME is t, copy the global face definition of FROM.
4214Otherwise, copy the frame-local definition of FROM on FRAME.
4215If NEW-FRAME is a frame, copy that data into the frame-local
4216definition of TO on NEW-FRAME. If NEW-FRAME is nil.
4217FRAME controls where the data is copied to.
228299fa 4218
5e9bab6f 4219The value is TO. */)
7ee72033 4220 (from, to, frame, new_frame)
82641697
GM
4221 Lisp_Object from, to, frame, new_frame;
4222{
4223 Lisp_Object lface, copy;
178c5d9c 4224
b7826503
PJ
4225 CHECK_SYMBOL (from);
4226 CHECK_SYMBOL (to);
82641697
GM
4227
4228 if (EQ (frame, Qt))
4229 {
4230 /* Copy global definition of FROM. We don't make copies of
4231 strings etc. because 20.2 didn't do it either. */
4232 lface = lface_from_face_name (NULL, from, 1);
4233 copy = Finternal_make_lisp_face (to, Qnil);
4234 }
4235 else
4236 {
4237 /* Copy frame-local definition of FROM. */
5e9bab6f
RS
4238 if (NILP (new_frame))
4239 new_frame = frame;
b7826503
PJ
4240 CHECK_LIVE_FRAME (frame);
4241 CHECK_LIVE_FRAME (new_frame);
82641697
GM
4242 lface = lface_from_face_name (XFRAME (frame), from, 1);
4243 copy = Finternal_make_lisp_face (to, new_frame);
4244 }
178c5d9c 4245
82641697
GM
4246 bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
4247 LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
178c5d9c 4248
33565969
RS
4249 /* Changing a named face means that all realized faces depending on
4250 that face are invalid. Since we cannot tell which realized faces
4251 depend on the face, make sure they are all removed. This is done
4252 by incrementing face_change_count. The next call to
4253 init_iterator will then free realized faces. */
46b00436
KS
4254 if (NILP (Fget (to, Qface_no_inherit)))
4255 {
4256 ++face_change_count;
4257 ++windows_or_buffers_changed;
4258 }
33565969 4259
82641697
GM
4260 return to;
4261}
4262
4263
4264DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
4265 Sinternal_set_lisp_face_attribute, 3, 4, 0,
7ee72033 4266 doc: /* Set attribute ATTR of FACE to VALUE.
228299fa
GM
4267FRAME being a frame means change the face on that frame.
4268FRAME nil means change the face of the selected frame.
4269FRAME t means change the default for new frames.
4270FRAME 0 means change the face on all frames, and change the default
7ee72033
MB
4271 for new frames. */)
4272 (face, attr, value, frame)
82641697
GM
4273 Lisp_Object face, attr, value, frame;
4274{
4275 Lisp_Object lface;
4276 Lisp_Object old_value = Qnil;
39506348
KH
4277 /* Set 1 if ATTR is QCfont. */
4278 int font_attr_p = 0;
4279 /* Set 1 if ATTR is one of font-related attributes other than QCfont. */
82641697 4280 int font_related_attr_p = 0;
178c5d9c 4281
b7826503
PJ
4282 CHECK_SYMBOL (face);
4283 CHECK_SYMBOL (attr);
82641697 4284
d1bf13b3 4285 face = resolve_face_name (face, 1);
c7ae3284 4286
628436fb
GM
4287 /* If FRAME is 0, change face on all frames, and change the
4288 default for new frames. */
4289 if (INTEGERP (frame) && XINT (frame) == 0)
4290 {
4291 Lisp_Object tail;
d12d0a9b 4292 Finternal_set_lisp_face_attribute (face, attr, value, Qt);
628436fb
GM
4293 FOR_EACH_FRAME (tail, frame)
4294 Finternal_set_lisp_face_attribute (face, attr, value, frame);
d12d0a9b 4295 return face;
628436fb
GM
4296 }
4297
82641697
GM
4298 /* Set lface to the Lisp attribute vector of FACE. */
4299 if (EQ (frame, Qt))
0268cef3
CY
4300 {
4301 lface = lface_from_face_name (NULL, face, 1);
67d23e01
CY
4302
4303 /* When updating face-new-frame-defaults, we put :ignore-defface
4304 where the caller wants `unspecified'. This forces the frame
4305 defaults to ignore the defface value. Otherwise, the defface
4306 will take effect, which is generally not what is intended.
4307 The value of that attribute will be inherited from some other
4308 face during face merging. See internal_merge_in_global_face. */
0268cef3 4309 if (UNSPECIFIEDP (value))
67d23e01 4310 value = Qignore_defface;
0268cef3 4311 }
82641697
GM
4312 else
4313 {
4314 if (NILP (frame))
c0617987 4315 frame = selected_frame;
178c5d9c 4316
b7826503 4317 CHECK_LIVE_FRAME (frame);
82641697 4318 lface = lface_from_face_name (XFRAME (frame), face, 0);
178c5d9c 4319
82641697
GM
4320 /* If a frame-local face doesn't exist yet, create one. */
4321 if (NILP (lface))
4322 lface = Finternal_make_lisp_face (face, frame);
4323 }
4324
4325 if (EQ (attr, QCfamily))
4326 {
2ff10663 4327 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 4328 {
b7826503 4329 CHECK_STRING (value);
d5db4077 4330 if (SCHARS (value) == 0)
82641697
GM
4331 signal_error ("Invalid face family", value);
4332 }
4333 old_value = LFACE_FAMILY (lface);
4334 LFACE_FAMILY (lface) = value;
4335 font_related_attr_p = 1;
4336 }
4337 else if (EQ (attr, QCheight))
4338 {
2ff10663 4339 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 4340 {
d8055bfc 4341 Lisp_Object test;
2c20458f 4342
d8055bfc
GM
4343 test = (EQ (face, Qdefault)
4344 ? value
4345 /* The default face must have an absolute size,
4346 otherwise, we do a test merge with a random
4347 height to see if VALUE's ok. */
e1e419ec 4348 : merge_face_heights (value, make_number (10), Qnil));
d8055bfc
GM
4349
4350 if (!INTEGERP (test) || XINT (test) <= 0)
82641697
GM
4351 signal_error ("Invalid face height", value);
4352 }
2c20458f 4353
82641697
GM
4354 old_value = LFACE_HEIGHT (lface);
4355 LFACE_HEIGHT (lface) = value;
4356 font_related_attr_p = 1;
4357 }
4358 else if (EQ (attr, QCweight))
4359 {
2ff10663 4360 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 4361 {
b7826503 4362 CHECK_SYMBOL (value);
82641697
GM
4363 if (face_numeric_weight (value) < 0)
4364 signal_error ("Invalid face weight", value);
4365 }
4366 old_value = LFACE_WEIGHT (lface);
4367 LFACE_WEIGHT (lface) = value;
4368 font_related_attr_p = 1;
4369 }
4370 else if (EQ (attr, QCslant))
4371 {
2ff10663 4372 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 4373 {
b7826503 4374 CHECK_SYMBOL (value);
82641697
GM
4375 if (face_numeric_slant (value) < 0)
4376 signal_error ("Invalid face slant", value);
4377 }
4378 old_value = LFACE_SLANT (lface);
4379 LFACE_SLANT (lface) = value;
4380 font_related_attr_p = 1;
4381 }
4382 else if (EQ (attr, QCunderline))
4383 {
2ff10663 4384 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
4385 if ((SYMBOLP (value)
4386 && !EQ (value, Qt)
4387 && !EQ (value, Qnil))
4388 /* Underline color. */
4389 || (STRINGP (value)
d5db4077 4390 && SCHARS (value) == 0))
82641697 4391 signal_error ("Invalid face underline", value);
178c5d9c 4392
82641697
GM
4393 old_value = LFACE_UNDERLINE (lface);
4394 LFACE_UNDERLINE (lface) = value;
4395 }
4396 else if (EQ (attr, QCoverline))
4397 {
2ff10663 4398 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
4399 if ((SYMBOLP (value)
4400 && !EQ (value, Qt)
4401 && !EQ (value, Qnil))
4402 /* Overline color. */
4403 || (STRINGP (value)
d5db4077 4404 && SCHARS (value) == 0))
82641697 4405 signal_error ("Invalid face overline", value);
178c5d9c 4406
82641697
GM
4407 old_value = LFACE_OVERLINE (lface);
4408 LFACE_OVERLINE (lface) = value;
4409 }
4410 else if (EQ (attr, QCstrike_through))
4411 {
2ff10663 4412 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
4413 if ((SYMBOLP (value)
4414 && !EQ (value, Qt)
4415 && !EQ (value, Qnil))
4416 /* Strike-through color. */
4417 || (STRINGP (value)
d5db4077 4418 && SCHARS (value) == 0))
82641697 4419 signal_error ("Invalid face strike-through", value);
178c5d9c 4420
82641697
GM
4421 old_value = LFACE_STRIKE_THROUGH (lface);
4422 LFACE_STRIKE_THROUGH (lface) = value;
4423 }
4424 else if (EQ (attr, QCbox))
4425 {
4426 int valid_p;
178c5d9c 4427
82641697
GM
4428 /* Allow t meaning a simple box of width 1 in foreground color
4429 of the face. */
4430 if (EQ (value, Qt))
4431 value = make_number (1);
4432
2ff10663 4433 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
82641697
GM
4434 valid_p = 1;
4435 else if (NILP (value))
4436 valid_p = 1;
4437 else if (INTEGERP (value))
89624b8b 4438 valid_p = XINT (value) != 0;
82641697 4439 else if (STRINGP (value))
d5db4077 4440 valid_p = SCHARS (value) > 0;
82641697
GM
4441 else if (CONSP (value))
4442 {
4443 Lisp_Object tem;
178c5d9c 4444
82641697
GM
4445 tem = value;
4446 while (CONSP (tem))
4447 {
4448 Lisp_Object k, v;
4449
4450 k = XCAR (tem);
4451 tem = XCDR (tem);
4452 if (!CONSP (tem))
4453 break;
4454 v = XCAR (tem);
4455 tem = XCDR (tem);
178c5d9c 4456
82641697
GM
4457 if (EQ (k, QCline_width))
4458 {
89624b8b 4459 if (!INTEGERP (v) || XINT (v) == 0)
82641697
GM
4460 break;
4461 }
4462 else if (EQ (k, QCcolor))
4463 {
91c212f1 4464 if (!NILP (v) && (!STRINGP (v) || SCHARS (v) == 0))
82641697
GM
4465 break;
4466 }
4467 else if (EQ (k, QCstyle))
4468 {
4469 if (!EQ (v, Qpressed_button) && !EQ (v, Qreleased_button))
4470 break;
4471 }
4472 else
4473 break;
4474 }
4475
4476 valid_p = NILP (tem);
4477 }
4478 else
4479 valid_p = 0;
4480
4481 if (!valid_p)
4482 signal_error ("Invalid face box", value);
178c5d9c 4483
82641697
GM
4484 old_value = LFACE_BOX (lface);
4485 LFACE_BOX (lface) = value;
4486 }
4487 else if (EQ (attr, QCinverse_video)
4488 || EQ (attr, QCreverse_video))
4489 {
2ff10663 4490 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 4491 {
b7826503 4492 CHECK_SYMBOL (value);
82641697
GM
4493 if (!EQ (value, Qt) && !NILP (value))
4494 signal_error ("Invalid inverse-video face attribute value", value);
4495 }
4496 old_value = LFACE_INVERSE (lface);
4497 LFACE_INVERSE (lface) = value;
4498 }
4499 else if (EQ (attr, QCforeground))
4500 {
2ff10663 4501 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
4502 {
4503 /* Don't check for valid color names here because it depends
4504 on the frame (display) whether the color will be valid
4505 when the face is realized. */
b7826503 4506 CHECK_STRING (value);
d5db4077 4507 if (SCHARS (value) == 0)
82641697
GM
4508 signal_error ("Empty foreground color value", value);
4509 }
4510 old_value = LFACE_FOREGROUND (lface);
4511 LFACE_FOREGROUND (lface) = value;
4512 }
4513 else if (EQ (attr, QCbackground))
4514 {
2ff10663 4515 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697
GM
4516 {
4517 /* Don't check for valid color names here because it depends
4518 on the frame (display) whether the color will be valid
4519 when the face is realized. */
b7826503 4520 CHECK_STRING (value);
d5db4077 4521 if (SCHARS (value) == 0)
82641697
GM
4522 signal_error ("Empty background color value", value);
4523 }
4524 old_value = LFACE_BACKGROUND (lface);
4525 LFACE_BACKGROUND (lface) = value;
4526 }
4527 else if (EQ (attr, QCstipple))
4528 {
4529#ifdef HAVE_X_WINDOWS
2ff10663 4530 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
82641697 4531 && !NILP (value)
fef04523 4532 && NILP (Fbitmap_spec_p (value)))
82641697
GM
4533 signal_error ("Invalid stipple attribute", value);
4534 old_value = LFACE_STIPPLE (lface);
4535 LFACE_STIPPLE (lface) = value;
4536#endif /* HAVE_X_WINDOWS */
4537 }
4538 else if (EQ (attr, QCwidth))
4539 {
2ff10663 4540 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
82641697 4541 {
b7826503 4542 CHECK_SYMBOL (value);
82641697
GM
4543 if (face_numeric_swidth (value) < 0)
4544 signal_error ("Invalid face width", value);
4545 }
4546 old_value = LFACE_SWIDTH (lface);
4547 LFACE_SWIDTH (lface) = value;
4548 font_related_attr_p = 1;
4549 }
763bc839 4550 else if (EQ (attr, QCfont) || EQ (attr, QCfontset))
82641697 4551 {
c3cee013 4552#ifdef HAVE_WINDOW_SYSTEM
3d90c96c 4553 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
96fbd2c6
EZ
4554 {
4555 /* Set font-related attributes of the Lisp face from an XLFD
4556 font name. */
4557 struct frame *f;
4558 Lisp_Object tmp;
82641697 4559
96fbd2c6
EZ
4560 if (EQ (frame, Qt))
4561 f = SELECTED_FRAME ();
4562 else
4563 f = check_x_frame (frame);
178c5d9c 4564
2ff10663 4565 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
e67f5ccc
RS
4566 {
4567 CHECK_STRING (value);
39506348 4568
e67f5ccc
RS
4569 /* VALUE may be a fontset name or an alias of fontset. In
4570 such a case, use the base fontset name. */
4571 tmp = Fquery_fontset (value, Qnil);
4572 if (!NILP (tmp))
4573 value = tmp;
8f924df7
KH
4574 else if (EQ (attr, QCfontset))
4575 signal_error ("Invalid fontset name", value);
e67f5ccc 4576
8f924df7
KH
4577 if (EQ (attr, QCfont))
4578 {
4579 if (!set_lface_from_font_name (f, lface, value, 1, 1))
4580 signal_error ("Invalid font or fontset name", value);
4581 }
4582 else
4583 LFACE_FONTSET (lface) = value;
e67f5ccc 4584 }
39506348 4585
96fbd2c6
EZ
4586 font_attr_p = 1;
4587 }
c3cee013 4588#endif /* HAVE_WINDOW_SYSTEM */
82641697 4589 }
2c20458f
MB
4590 else if (EQ (attr, QCinherit))
4591 {
4592 Lisp_Object tail;
4593 if (SYMBOLP (value))
4594 tail = Qnil;
4595 else
4596 for (tail = value; CONSP (tail); tail = XCDR (tail))
4597 if (!SYMBOLP (XCAR (tail)))
4598 break;
4599 if (NILP (tail))
4600 LFACE_INHERIT (lface) = value;
4601 else
6288c62f 4602 signal_error ("Invalid face inheritance", value);
2c20458f 4603 }
82641697
GM
4604 else if (EQ (attr, QCbold))
4605 {
4606 old_value = LFACE_WEIGHT (lface);
4607 LFACE_WEIGHT (lface) = NILP (value) ? Qnormal : Qbold;
4608 font_related_attr_p = 1;
4609 }
4610 else if (EQ (attr, QCitalic))
4611 {
4612 old_value = LFACE_SLANT (lface);
4613 LFACE_SLANT (lface) = NILP (value) ? Qnormal : Qitalic;
4614 font_related_attr_p = 1;
4615 }
4616 else
4617 signal_error ("Invalid face attribute name", attr);
4618
39506348 4619 if (font_related_attr_p
2ff10663 4620 && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
39506348
KH
4621 /* If a font-related attribute other than QCfont is specified, the
4622 original `font' attribute nor that of default face is useless
4623 to determine a new font. Thus, we set it to nil so that font
4624 selection mechanism doesn't use it. */
4625 LFACE_FONT (lface) = Qnil;
4626
82641697
GM
4627 /* Changing a named face means that all realized faces depending on
4628 that face are invalid. Since we cannot tell which realized faces
4629 depend on the face, make sure they are all removed. This is done
4630 by incrementing face_change_count. The next call to
4631 init_iterator will then free realized faces. */
4632 if (!EQ (frame, Qt)
46b00436 4633 && NILP (Fget (face, Qface_no_inherit))
82641697 4634 && (EQ (attr, QCfont)
763bc839 4635 || EQ (attr, QCfontset)
82641697
GM
4636 || NILP (Fequal (old_value, value))))
4637 {
4638 ++face_change_count;
4639 ++windows_or_buffers_changed;
4640 }
4641
2ff10663 4642 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
82641697 4643 && NILP (Fequal (old_value, value)))
8bd201d6
GM
4644 {
4645 Lisp_Object param;
4646
4647 param = Qnil;
178c5d9c 4648
8bd201d6
GM
4649 if (EQ (face, Qdefault))
4650 {
b9c769f8 4651#ifdef HAVE_WINDOW_SYSTEM
8bd201d6
GM
4652 /* Changed font-related attributes of the `default' face are
4653 reflected in changed `font' frame parameters. */
ceeda019
GM
4654 if (FRAMEP (frame)
4655 && (font_related_attr_p || font_attr_p)
8bd201d6
GM
4656 && lface_fully_specified_p (XVECTOR (lface)->contents))
4657 set_font_frame_param (frame, lface);
b9c769f8
EZ
4658 else
4659#endif /* HAVE_WINDOW_SYSTEM */
4660
4661 if (EQ (attr, QCforeground))
8bd201d6
GM
4662 param = Qforeground_color;
4663 else if (EQ (attr, QCbackground))
4664 param = Qbackground_color;
4665 }
b9c769f8 4666#ifdef HAVE_WINDOW_SYSTEM
c3cee013 4667#ifndef WINDOWSNT
8bd201d6
GM
4668 else if (EQ (face, Qscroll_bar))
4669 {
4670 /* Changing the colors of `scroll-bar' sets frame parameters
4671 `scroll-bar-foreground' and `scroll-bar-background'. */
4672 if (EQ (attr, QCforeground))
4673 param = Qscroll_bar_foreground;
4674 else if (EQ (attr, QCbackground))
4675 param = Qscroll_bar_background;
4676 }
d12d0a9b 4677#endif /* not WINDOWSNT */
8bd201d6
GM
4678 else if (EQ (face, Qborder))
4679 {
4680 /* Changing background color of `border' sets frame parameter
4681 `border-color'. */
4682 if (EQ (attr, QCbackground))
4683 param = Qborder_color;
4684 }
4685 else if (EQ (face, Qcursor))
4686 {
4687 /* Changing background color of `cursor' sets frame parameter
4688 `cursor-color'. */
4689 if (EQ (attr, QCbackground))
4690 param = Qcursor_color;
4691 }
4692 else if (EQ (face, Qmouse))
4693 {
4694 /* Changing background color of `mouse' sets frame parameter
4695 `mouse-color'. */
4696 if (EQ (attr, QCbackground))
4697 param = Qmouse_color;
4698 }
b9c769f8 4699#endif /* HAVE_WINDOW_SYSTEM */
563f68f1 4700 else if (EQ (face, Qmenu))
ceeda019
GM
4701 {
4702 /* Indicate that we have to update the menu bar when
4703 realizing faces on FRAME. FRAME t change the
4704 default for new frames. We do this by setting
4705 setting the flag in new face caches */
4706 if (FRAMEP (frame))
4707 {
4708 struct frame *f = XFRAME (frame);
4709 if (FRAME_FACE_CACHE (f) == NULL)
4710 FRAME_FACE_CACHE (f) = make_face_cache (f);
4711 FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
4712 }
4713 else
4714 menu_face_changed_default = 1;
4715 }
8bd201d6 4716
39506348 4717 if (!NILP (param))
ab8469eb
PJ
4718 {
4719 if (EQ (frame, Qt))
4720 /* Update `default-frame-alist', which is used for new frames. */
4721 {
4722 store_in_alist (&Vdefault_frame_alist, param, value);
4723 }
4724 else
4725 /* Update the current frame's parameters. */
4726 {
4727 Lisp_Object cons;
4728 cons = XCAR (Vparam_value_alist);
4729 XSETCAR (cons, param);
4730 XSETCDR (cons, value);
4731 Fmodify_frame_parameters (frame, Vparam_value_alist);
4732 }
4733 }
8bd201d6 4734 }
82641697 4735
82641697
GM
4736 return face;
4737}
4738
4739
c3cee013 4740#ifdef HAVE_WINDOW_SYSTEM
82641697 4741
39506348 4742/* Set the `font' frame parameter of FRAME determined from `default'
763bc839 4743 face attributes LFACE. If a font name is explicitely
39506348
KH
4744 specfied in LFACE, use it as is. Otherwise, determine a font name
4745 from the other font-related atrributes of LFACE. In that case, if
4746 there's no matching font, signals an error. */
82641697
GM
4747
4748static void
4749set_font_frame_param (frame, lface)
4750 Lisp_Object frame, lface;
4751{
4752 struct frame *f = XFRAME (frame);
82641697 4753
482cca61 4754 if (FRAME_WINDOW_P (f))
82641697 4755 {
482cca61
GM
4756 Lisp_Object font_name;
4757 char *font;
177c0ea7 4758
482cca61
GM
4759 if (STRINGP (LFACE_FONT (lface)))
4760 font_name = LFACE_FONT (lface);
426b2119
KH
4761#ifdef USE_FONT_BACKEND
4762 else if (enable_font_backend)
4763 {
4764 Lisp_Object entity = font_find_for_lface (f, &AREF (lface, 0), Qnil);
4765
4766 if (NILP (entity))
4767 error ("No font matches the specified attribute");
4768 font_name = font_open_for_lface (f, &AREF (lface, 0), entity);
4769 if (NILP (font_name))
4770 error ("No font matches the specified attribute");
4771 }
4772#endif
482cca61
GM
4773 else
4774 {
4775 /* Choose a font name that reflects LFACE's attributes and has
4776 the registry and encoding pattern specified in the default
4777 fontset (3rd arg: -1) for ASCII characters (4th arg: 0). */
8f924df7 4778 font = choose_face_font (f, XVECTOR (lface)->contents, Qnil, NULL);
482cca61
GM
4779 if (!font)
4780 error ("No font matches the specified attribute");
4781 font_name = build_string (font);
4782 xfree (font);
4783 }
177c0ea7 4784
a5f696ac 4785 f->default_face_done_p = 0;
482cca61
GM
4786 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), Qnil));
4787 }
82641697
GM
4788}
4789
4790
8bd201d6
GM
4791/* Update the corresponding face when frame parameter PARAM on frame F
4792 has been assigned the value NEW_VALUE. */
4793
4794void
4795update_face_from_frame_parameter (f, param, new_value)
4796 struct frame *f;
4797 Lisp_Object param, new_value;
4798{
46b00436 4799 Lisp_Object face = Qnil;
8bd201d6
GM
4800 Lisp_Object lface;
4801
4802 /* If there are no faces yet, give up. This is the case when called
4803 from Fx_create_frame, and we do the necessary things later in
92610620 4804 face-set-after-frame-defaults. */
8bd201d6
GM
4805 if (NILP (f->face_alist))
4806 return;
178c5d9c 4807
8bd201d6
GM
4808 if (EQ (param, Qforeground_color))
4809 {
46b00436
KS
4810 face = Qdefault;
4811 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
4812 LFACE_FOREGROUND (lface) = (STRINGP (new_value)
4813 ? new_value : Qunspecified);
4814 realize_basic_faces (f);
4815 }
4816 else if (EQ (param, Qbackground_color))
4817 {
92610620
GM
4818 Lisp_Object frame;
4819
4820 /* Changing the background color might change the background
c20577bc
JL
4821 mode, so that we have to load new defface specs.
4822 Call frame-set-background-mode to do that. */
92610620 4823 XSETFRAME (frame, f);
c20577bc 4824 call1 (Qframe_set_background_mode, frame);
178c5d9c 4825
46b00436
KS
4826 face = Qdefault;
4827 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
4828 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
4829 ? new_value : Qunspecified);
4830 realize_basic_faces (f);
4831 }
46b00436 4832 else if (EQ (param, Qborder_color))
8bd201d6 4833 {
46b00436
KS
4834 face = Qborder;
4835 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
4836 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
4837 ? new_value : Qunspecified);
4838 }
4839 else if (EQ (param, Qcursor_color))
4840 {
46b00436
KS
4841 face = Qcursor;
4842 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
4843 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
4844 ? new_value : Qunspecified);
4845 }
4846 else if (EQ (param, Qmouse_color))
4847 {
46b00436
KS
4848 face = Qmouse;
4849 lface = lface_from_face_name (f, face, 1);
8bd201d6
GM
4850 LFACE_BACKGROUND (lface) = (STRINGP (new_value)
4851 ? new_value : Qunspecified);
4852 }
46b00436
KS
4853
4854 /* Changing a named face means that all realized faces depending on
4855 that face are invalid. Since we cannot tell which realized faces
4856 depend on the face, make sure they are all removed. This is done
4857 by incrementing face_change_count. The next call to
4858 init_iterator will then free realized faces. */
4859 if (!NILP (face)
4860 && NILP (Fget (face, Qface_no_inherit)))
4861 {
4862 ++face_change_count;
4863 ++windows_or_buffers_changed;
4864 }
8bd201d6
GM
4865}
4866
4867
82641697
GM
4868/* Get the value of X resource RESOURCE, class CLASS for the display
4869 of frame FRAME. This is here because ordinary `x-get-resource'
4870 doesn't take a frame argument. */
4871
4872DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
7ee72033
MB
4873 Sinternal_face_x_get_resource, 3, 3, 0, doc: /* */)
4874 (resource, class, frame)
82641697
GM
4875 Lisp_Object resource, class, frame;
4876{
c3cee013 4877 Lisp_Object value = Qnil;
b7826503
PJ
4878 CHECK_STRING (resource);
4879 CHECK_STRING (class);
4880 CHECK_LIVE_FRAME (frame);
82641697
GM
4881 BLOCK_INPUT;
4882 value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
4883 resource, class, Qnil, Qnil);
4884 UNBLOCK_INPUT;
4885 return value;
4886}
4887
4888
4889/* Return resource string VALUE as a boolean value, i.e. nil, or t.
4890 If VALUE is "on" or "true", return t. If VALUE is "off" or
4891 "false", return nil. Otherwise, if SIGNAL_P is non-zero, signal an
4892 error; if SIGNAL_P is zero, return 0. */
178c5d9c 4893
82641697
GM
4894static Lisp_Object
4895face_boolean_x_resource_value (value, signal_p)
4896 Lisp_Object value;
4897 int signal_p;
4898{
4899 Lisp_Object result = make_number (0);
4900
4901 xassert (STRINGP (value));
178c5d9c 4902
d5db4077
KR
4903 if (xstricmp (SDATA (value), "on") == 0
4904 || xstricmp (SDATA (value), "true") == 0)
82641697 4905 result = Qt;
d5db4077
KR
4906 else if (xstricmp (SDATA (value), "off") == 0
4907 || xstricmp (SDATA (value), "false") == 0)
82641697 4908 result = Qnil;
d5db4077 4909 else if (xstricmp (SDATA (value), "unspecified") == 0)
82641697
GM
4910 result = Qunspecified;
4911 else if (signal_p)
4912 signal_error ("Invalid face attribute value from X resource", value);
4913
4914 return result;
4915}
4916
4917
4918DEFUN ("internal-set-lisp-face-attribute-from-resource",
4919 Finternal_set_lisp_face_attribute_from_resource,
4920 Sinternal_set_lisp_face_attribute_from_resource,
7ee72033
MB
4921 3, 4, 0, doc: /* */)
4922 (face, attr, value, frame)
82641697
GM
4923 Lisp_Object face, attr, value, frame;
4924{
b7826503
PJ
4925 CHECK_SYMBOL (face);
4926 CHECK_SYMBOL (attr);
4927 CHECK_STRING (value);
82641697 4928
d5db4077 4929 if (xstricmp (SDATA (value), "unspecified") == 0)
82641697
GM
4930 value = Qunspecified;
4931 else if (EQ (attr, QCheight))
4932 {
4933 value = Fstring_to_number (value, make_number (10));
4934 if (XINT (value) <= 0)
4935 signal_error ("Invalid face height from X resource", value);
4936 }
4937 else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
4938 value = face_boolean_x_resource_value (value, 1);
4939 else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
d5db4077 4940 value = intern (SDATA (value));
82641697
GM
4941 else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video))
4942 value = face_boolean_x_resource_value (value, 1);
4943 else if (EQ (attr, QCunderline)
4944 || EQ (attr, QCoverline)
27188d11 4945 || EQ (attr, QCstrike_through))
82641697
GM
4946 {
4947 Lisp_Object boolean_value;
4948
4949 /* If the result of face_boolean_x_resource_value is t or nil,
4950 VALUE does NOT specify a color. */
4951 boolean_value = face_boolean_x_resource_value (value, 0);
4952 if (SYMBOLP (boolean_value))
4953 value = boolean_value;
4954 }
0ad040ff 4955 else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
27188d11 4956 value = Fcar (Fread_from_string (value, Qnil, Qnil));
82641697
GM
4957
4958 return Finternal_set_lisp_face_attribute (face, attr, value, frame);
4959}
4960
c3cee013 4961#endif /* HAVE_WINDOW_SYSTEM */
82641697 4962
c7ae3284
GM
4963\f
4964/***********************************************************************
4965 Menu face
4966 ***********************************************************************/
4967
bce72079 4968#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
c7ae3284 4969
bce72079
GM
4970/* Make menus on frame F appear as specified by the `menu' face. */
4971
4972static void
4973x_update_menu_appearance (f)
c7ae3284 4974 struct frame *f;
c7ae3284 4975{
a03ad468 4976 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
bce72079 4977 XrmDatabase rdb;
178c5d9c 4978
bce72079
GM
4979 if (dpyinfo
4980 && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
4981 rdb != NULL))
c7ae3284 4982 {
bce72079
GM
4983 char line[512];
4984 Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
4985 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
53c208f6 4986 const char *myname = SDATA (Vx_resource_name);
bce72079 4987 int changed_p = 0;
8ad582ac
GM
4988#ifdef USE_MOTIF
4989 const char *popup_path = "popup_menu";
4990#else
4991 const char *popup_path = "menu.popup";
4992#endif
177c0ea7 4993
bce72079
GM
4994 if (STRINGP (LFACE_FOREGROUND (lface)))
4995 {
8ad582ac
GM
4996 sprintf (line, "%s.%s*foreground: %s",
4997 myname, popup_path,
d5db4077 4998 SDATA (LFACE_FOREGROUND (lface)));
bce72079
GM
4999 XrmPutLineResource (&rdb, line);
5000 sprintf (line, "%s.pane.menubar*foreground: %s",
d5db4077 5001 myname, SDATA (LFACE_FOREGROUND (lface)));
bce72079
GM
5002 XrmPutLineResource (&rdb, line);
5003 changed_p = 1;
5004 }
178c5d9c 5005
bce72079
GM
5006 if (STRINGP (LFACE_BACKGROUND (lface)))
5007 {
8ad582ac
GM
5008 sprintf (line, "%s.%s*background: %s",
5009 myname, popup_path,
d5db4077 5010 SDATA (LFACE_BACKGROUND (lface)));
bce72079
GM
5011 XrmPutLineResource (&rdb, line);
5012 sprintf (line, "%s.pane.menubar*background: %s",
d5db4077 5013 myname, SDATA (LFACE_BACKGROUND (lface)));
bce72079
GM
5014 XrmPutLineResource (&rdb, line);
5015 changed_p = 1;
5016 }
177c0ea7 5017
bce72079
GM
5018 if (face->font_name
5019 && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
5020 || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
5021 || !UNSPECIFIEDP (LFACE_AVGWIDTH (lface))
5022 || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
5023 || !UNSPECIFIEDP (LFACE_SLANT (lface))
5024 || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
5025 {
a03ad468 5026#ifdef USE_MOTIF
bce72079 5027 const char *suffix = "List";
211f2210 5028 Bool motif = True;
a2d7e722
JD
5029#else
5030#if defined HAVE_X_I18N
5031
5032 const char *suffix = "Set";
a03ad468 5033#else
bce72079 5034 const char *suffix = "";
a2d7e722 5035#endif
211f2210 5036 Bool motif = False;
2defe37f 5037#endif
211f2210 5038#if defined HAVE_X_I18N
2defe37f
SM
5039 extern char *xic_create_fontsetname
5040 P_ ((char *base_fontname, Bool motif));
211f2210 5041 char *fontsetname = xic_create_fontsetname (face->font_name, motif);
2defe37f
SM
5042#else
5043 char *fontsetname = face->font_name;
bce72079
GM
5044#endif
5045 sprintf (line, "%s.pane.menubar*font%s: %s",
2defe37f 5046 myname, suffix, fontsetname);
bce72079 5047 XrmPutLineResource (&rdb, line);
2eddf899 5048 sprintf (line, "%s.%s*font%s: %s",
2defe37f 5049 myname, popup_path, suffix, fontsetname);
bce72079
GM
5050 XrmPutLineResource (&rdb, line);
5051 changed_p = 1;
211f2210
SM
5052 if (fontsetname != face->font_name)
5053 xfree (fontsetname);
bce72079 5054 }
c7ae3284 5055
bce72079 5056 if (changed_p && f->output_data.x->menubar_widget)
ac17f0bf 5057 free_frame_menubar (f);
c7ae3284
GM
5058 }
5059}
5060
bce72079 5061#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
82641697
GM
5062
5063
177c0ea7 5064DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
cdfaafa9
MB
5065 Sface_attribute_relative_p,
5066 2, 2, 0,
5067 doc: /* Return non-nil if face ATTRIBUTE VALUE is relative. */)
5068 (attribute, value)
d0930289 5069 Lisp_Object attribute, value;
cdfaafa9 5070{
05338727 5071 if (EQ (value, Qunspecified) || (EQ (value, Qignore_defface)))
cdfaafa9
MB
5072 return Qt;
5073 else if (EQ (attribute, QCheight))
5074 return INTEGERP (value) ? Qnil : Qt;
5075 else
5076 return Qnil;
5077}
5078
5079DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
5080 3, 3, 0,
5081 doc: /* Return face ATTRIBUTE VALUE1 merged with VALUE2.
5082If VALUE1 or VALUE2 are absolute (see `face-attribute-relative-p'), then
5083the result will be absolute, otherwise it will be relative. */)
5084 (attribute, value1, value2)
5085 Lisp_Object attribute, value1, value2;
5086{
05338727 5087 if (EQ (value1, Qunspecified) || EQ (value1, Qignore_defface))
cdfaafa9
MB
5088 return value2;
5089 else if (EQ (attribute, QCheight))
e1e419ec 5090 return merge_face_heights (value1, value2, value1);
cdfaafa9
MB
5091 else
5092 return value1;
5093}
5094
82641697
GM
5095
5096DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
5097 Sinternal_get_lisp_face_attribute,
5098 2, 3, 0,
7ee72033 5099 doc: /* Return face attribute KEYWORD of face SYMBOL.
228299fa
GM
5100If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid
5101face attribute name, signal an error.
7fc92635
JB
5102If the optional argument FRAME is given, report on face SYMBOL in that
5103frame. If FRAME is t, report on the defaults for face SYMBOL (for new
7ee72033
MB
5104frames). If FRAME is omitted or nil, use the selected frame. */)
5105 (symbol, keyword, frame)
82641697
GM
5106 Lisp_Object symbol, keyword, frame;
5107{
5108 Lisp_Object lface, value = Qnil;
178c5d9c 5109
b7826503
PJ
5110 CHECK_SYMBOL (symbol);
5111 CHECK_SYMBOL (keyword);
82641697
GM
5112
5113 if (EQ (frame, Qt))
5114 lface = lface_from_face_name (NULL, symbol, 1);
5115 else
5116 {
5117 if (NILP (frame))
c0617987 5118 frame = selected_frame;
b7826503 5119 CHECK_LIVE_FRAME (frame);
82641697
GM
5120 lface = lface_from_face_name (XFRAME (frame), symbol, 1);
5121 }
5122
5123 if (EQ (keyword, QCfamily))
5124 value = LFACE_FAMILY (lface);
5125 else if (EQ (keyword, QCheight))
5126 value = LFACE_HEIGHT (lface);
5127 else if (EQ (keyword, QCweight))
5128 value = LFACE_WEIGHT (lface);
5129 else if (EQ (keyword, QCslant))
5130 value = LFACE_SLANT (lface);
5131 else if (EQ (keyword, QCunderline))
5132 value = LFACE_UNDERLINE (lface);
5133 else if (EQ (keyword, QCoverline))
5134 value = LFACE_OVERLINE (lface);
5135 else if (EQ (keyword, QCstrike_through))
5136 value = LFACE_STRIKE_THROUGH (lface);
5137 else if (EQ (keyword, QCbox))
5138 value = LFACE_BOX (lface);
5139 else if (EQ (keyword, QCinverse_video)
5140 || EQ (keyword, QCreverse_video))
5141 value = LFACE_INVERSE (lface);
5142 else if (EQ (keyword, QCforeground))
5143 value = LFACE_FOREGROUND (lface);
5144 else if (EQ (keyword, QCbackground))
5145 value = LFACE_BACKGROUND (lface);
5146 else if (EQ (keyword, QCstipple))
5147 value = LFACE_STIPPLE (lface);
5148 else if (EQ (keyword, QCwidth))
5149 value = LFACE_SWIDTH (lface);
2c20458f
MB
5150 else if (EQ (keyword, QCinherit))
5151 value = LFACE_INHERIT (lface);
39506348
KH
5152 else if (EQ (keyword, QCfont))
5153 value = LFACE_FONT (lface);
763bc839
KH
5154 else if (EQ (keyword, QCfontset))
5155 value = LFACE_FONTSET (lface);
82641697
GM
5156 else
5157 signal_error ("Invalid face attribute name", keyword);
5158
0268cef3
CY
5159 if (IGNORE_DEFFACE_P (value))
5160 return Qunspecified;
5161
82641697
GM
5162 return value;
5163}
5164
5165
5166DEFUN ("internal-lisp-face-attribute-values",
5167 Finternal_lisp_face_attribute_values,
5168 Sinternal_lisp_face_attribute_values, 1, 1, 0,
7ee72033
MB
5169 doc: /* Return a list of valid discrete values for face attribute ATTR.
5170Value is nil if ATTR doesn't have a discrete set of valid values. */)
5171 (attr)
82641697
GM
5172 Lisp_Object attr;
5173{
5174 Lisp_Object result = Qnil;
178c5d9c 5175
b7826503 5176 CHECK_SYMBOL (attr);
178c5d9c 5177
82641697
GM
5178 if (EQ (attr, QCweight)
5179 || EQ (attr, QCslant)
5180 || EQ (attr, QCwidth))
5181 {
5182 /* Extract permissible symbols from tables. */
5183 struct table_entry *table;
5184 int i, dim;
178c5d9c 5185
82641697
GM
5186 if (EQ (attr, QCweight))
5187 table = weight_table, dim = DIM (weight_table);
5188 else if (EQ (attr, QCslant))
5189 table = slant_table, dim = DIM (slant_table);
5190 else
5191 table = swidth_table, dim = DIM (swidth_table);
5192
5193 for (i = 0; i < dim; ++i)
5194 {
5195 Lisp_Object symbol = *table[i].symbol;
5196 Lisp_Object tail = result;
5197
5198 while (!NILP (tail)
5199 && !EQ (XCAR (tail), symbol))
5200 tail = XCDR (tail);
5201
5202 if (NILP (tail))
5203 result = Fcons (symbol, result);
5204 }
5205 }
5206 else if (EQ (attr, QCunderline))
5207 result = Fcons (Qt, Fcons (Qnil, Qnil));
5208 else if (EQ (attr, QCoverline))
5209 result = Fcons (Qt, Fcons (Qnil, Qnil));
5210 else if (EQ (attr, QCstrike_through))
5211 result = Fcons (Qt, Fcons (Qnil, Qnil));
5212 else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video))
5213 result = Fcons (Qt, Fcons (Qnil, Qnil));
5214
5215 return result;
5216}
178c5d9c 5217
82641697
GM
5218
5219DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
178c5d9c 5220 Sinternal_merge_in_global_face, 2, 2, 0,
e3cd9e7f 5221 doc: /* Add attributes from frame-default definition of FACE to FACE on FRAME.
7ee72033
MB
5222Default face attributes override any local face attributes. */)
5223 (face, frame)
82641697
GM
5224 Lisp_Object face, frame;
5225{
aad40737
MB
5226 int i;
5227 Lisp_Object global_lface, local_lface, *gvec, *lvec;
5228
b7826503 5229 CHECK_LIVE_FRAME (frame);
82641697
GM
5230 global_lface = lface_from_face_name (NULL, face, 1);
5231 local_lface = lface_from_face_name (XFRAME (frame), face, 0);
5232 if (NILP (local_lface))
5233 local_lface = Finternal_make_lisp_face (face, frame);
aad40737 5234
cec33c90
SM
5235 /* Make every specified global attribute override the local one.
5236 BEWARE!! This is only used from `face-set-after-frame-default' where
5237 the local frame is defined from default specs in `face-defface-spec'
5238 and those should be overridden by global settings. Hence the strange
5239 "global before local" priority. */
aad40737
MB
5240 lvec = XVECTOR (local_lface)->contents;
5241 gvec = XVECTOR (global_lface)->contents;
5242 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
5243 if (! UNSPECIFIEDP (gvec[i]))
27d744ae
YM
5244 {
5245 if (IGNORE_DEFFACE_P (gvec[i]))
5246 lvec[i] = Qunspecified;
5247 else
5248 lvec[i] = gvec[i];
5249 }
334a2e2a
GM
5250
5251 return Qnil;
82641697
GM
5252}
5253
5254
5255/* The following function is implemented for compatibility with 20.2.
5256 The function is used in x-resolve-fonts when it is asked to
5257 return fonts with the same size as the font of a face. This is
5258 done in fontset.el. */
5259
2db4bfe5 5260DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
e3cd9e7f 5261 doc: /* Return the font name of face FACE, or nil if it is unspecified.
2db4bfe5 5262The font name is, by default, for ASCII characters.
228299fa
GM
5263If the optional argument FRAME is given, report on face FACE in that frame.
5264If FRAME is t, report on the defaults for face FACE (for new frames).
5265 The font default for a face is either nil, or a list
5266 of the form (bold), (italic) or (bold italic).
2db4bfe5
KH
5267If FRAME is omitted or nil, use the selected frame. And, in this case,
5268if the optional third argument CHARACTER is given,
5269return the font name used for CHARACTER. */)
5270 (face, frame, character)
5271 Lisp_Object face, frame, character;
82641697
GM
5272{
5273 if (EQ (frame, Qt))
5274 {
5275 Lisp_Object result = Qnil;
5276 Lisp_Object lface = lface_from_face_name (NULL, face, 1);
5277
5278 if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
5279 && !EQ (LFACE_WEIGHT (lface), Qnormal))
5280 result = Fcons (Qbold, result);
178c5d9c 5281
0f2c6573 5282 if (!UNSPECIFIEDP (LFACE_SLANT (lface))
82641697
GM
5283 && !EQ (LFACE_SLANT (lface), Qnormal))
5284 result = Fcons (Qitalic, result);
178c5d9c 5285
82641697
GM
5286 return result;
5287 }
5288 else
5289 {
5290 struct frame *f = frame_or_selected_frame (frame, 1);
000fc2b1 5291 int face_id = lookup_named_face (f, face, 1);
82641697 5292 struct face *face = FACE_FROM_ID (f, face_id);
2db4bfe5
KH
5293
5294 if (! face)
5295 return Qnil;
a1a552b3 5296#ifdef HAVE_WINDOW_SYSTEM
75dad34a 5297 if (FRAME_WINDOW_P (f) && !NILP (character))
a1a552b3
KH
5298 {
5299 CHECK_CHARACTER (character);
5300 face_id = FACE_FOR_CHAR (f, face, XINT (character), -1, Qnil);
5301 face = FACE_FROM_ID (f, face_id);
5302 return (face->font && face->font_name
5303 ? build_string (face->font_name)
5304 : Qnil);
5305 }
5306#endif
5307 return build_string (face->font_name);
82641697
GM
5308 }
5309}
5310
5311
9717e36c 5312/* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
82641697
GM
5313 all attributes are `equal'. Tries to be fast because this function
5314 is called quite often. */
5315
5316static INLINE int
9717e36c 5317face_attr_equal_p (v1, v2)
3ebc0939 5318 Lisp_Object v1, v2;
82641697 5319{
9717e36c
MB
5320 /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
5321 and the other is specified. */
5322 if (XTYPE (v1) != XTYPE (v2))
5323 return 0;
82641697 5324
9717e36c
MB
5325 if (EQ (v1, v2))
5326 return 1;
82641697 5327
9717e36c
MB
5328 switch (XTYPE (v1))
5329 {
5330 case Lisp_String:
5331 if (SBYTES (v1) != SBYTES (v2))
5332 return 0;
82641697 5333
9717e36c 5334 return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
178c5d9c 5335
9717e36c
MB
5336 case Lisp_Int:
5337 case Lisp_Symbol:
5338 return 0;
178c5d9c 5339
9717e36c
MB
5340 default:
5341 return !NILP (Fequal (v1, v2));
82641697 5342 }
9717e36c
MB
5343}
5344
5345
5346/* Compare face vectors V1 and V2 for equality. Value is non-zero if
5347 all attributes are `equal'. Tries to be fast because this function
5348 is called quite often. */
5349
5350static INLINE int
5351lface_equal_p (v1, v2)
5352 Lisp_Object *v1, *v2;
5353{
5354 int i, equal_p = 1;
5355
5356 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
5357 equal_p = face_attr_equal_p (v1[i], v2[i]);
178c5d9c 5358
82641697
GM
5359 return equal_p;
5360}
5361
5362
5363DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
5364 Sinternal_lisp_face_equal_p, 2, 3, 0,
7ee72033 5365 doc: /* True if FACE1 and FACE2 are equal.
03f11322
JB
5366If the optional argument FRAME is given, report on FACE1 and FACE2 in that frame.
5367If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames).
7ee72033
MB
5368If FRAME is omitted or nil, use the selected frame. */)
5369 (face1, face2, frame)
82641697
GM
5370 Lisp_Object face1, face2, frame;
5371{
5372 int equal_p;
7b953c9c 5373 struct frame *f;
82641697 5374 Lisp_Object lface1, lface2;
178c5d9c 5375
7b953c9c
MB
5376 if (EQ (frame, Qt))
5377 f = NULL;
5378 else
5379 /* Don't use check_x_frame here because this function is called
5380 before X frames exist. At that time, if FRAME is nil,
5381 selected_frame will be used which is the frame dumped with
5382 Emacs. That frame is not an X frame. */
5383 f = frame_or_selected_frame (frame, 2);
5384
03f11322
JB
5385 lface1 = lface_from_face_name (f, face1, 1);
5386 lface2 = lface_from_face_name (f, face2, 1);
82641697
GM
5387 equal_p = lface_equal_p (XVECTOR (lface1)->contents,
5388 XVECTOR (lface2)->contents);
5389 return equal_p ? Qt : Qnil;
5390}
5391
178c5d9c 5392
82641697
GM
5393DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
5394 Sinternal_lisp_face_empty_p, 1, 2, 0,
7ee72033 5395 doc: /* True if FACE has no attribute specified.
228299fa
GM
5396If the optional argument FRAME is given, report on face FACE in that frame.
5397If FRAME is t, report on the defaults for face FACE (for new frames).
7ee72033
MB
5398If FRAME is omitted or nil, use the selected frame. */)
5399 (face, frame)
82641697
GM
5400 Lisp_Object face, frame;
5401{
5402 struct frame *f;
5403 Lisp_Object lface;
5404 int i;
5405
5406 if (NILP (frame))
c0617987 5407 frame = selected_frame;
b7826503 5408 CHECK_LIVE_FRAME (frame);
c0617987 5409 f = XFRAME (frame);
178c5d9c 5410
82641697
GM
5411 if (EQ (frame, Qt))
5412 lface = lface_from_face_name (NULL, face, 1);
5413 else
5414 lface = lface_from_face_name (f, face, 1);
5415
5416 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
a08332c0 5417 if (!UNSPECIFIEDP (AREF (lface, i)))
82641697 5418 break;
178c5d9c 5419
82641697
GM
5420 return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
5421}
5422
5423
5424DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
178c5d9c 5425 0, 1, 0,
7ee72033
MB
5426 doc: /* Return an alist of frame-local faces defined on FRAME.
5427For internal use only. */)
5428 (frame)
82641697
GM
5429 Lisp_Object frame;
5430{
5431 struct frame *f = frame_or_selected_frame (frame, 0);
5432 return f->face_alist;
5433}
5434
5435
5436/* Return a hash code for Lisp string STRING with case ignored. Used
5437 below in computing a hash value for a Lisp face. */
5438
5439static INLINE unsigned
5440hash_string_case_insensitive (string)
5441 Lisp_Object string;
5442{
53c208f6 5443 const unsigned char *s;
82641697
GM
5444 unsigned hash = 0;
5445 xassert (STRINGP (string));
d5db4077 5446 for (s = SDATA (string); *s; ++s)
82641697
GM
5447 hash = (hash << 1) ^ tolower (*s);
5448 return hash;
5449}
5450
5451
5452/* Return a hash code for face attribute vector V. */
5453
5454static INLINE unsigned
5455lface_hash (v)
5456 Lisp_Object *v;
5457{
5458 return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
5459 ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
5460 ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
6fc556fd
KR
5461 ^ XFASTINT (v[LFACE_WEIGHT_INDEX])
5462 ^ XFASTINT (v[LFACE_SLANT_INDEX])
5463 ^ XFASTINT (v[LFACE_SWIDTH_INDEX])
82641697
GM
5464 ^ XFASTINT (v[LFACE_HEIGHT_INDEX]));
5465}
5466
5467
5468/* Return non-zero if LFACE1 and LFACE2 specify the same font (without
5469 considering charsets/registries). They do if they specify the same
763bc839
KH
5470 family, point size, weight, width, slant, font, and fontset. Both
5471 LFACE1 and LFACE2 must be fully-specified. */
82641697
GM
5472
5473static INLINE int
5474lface_same_font_attributes_p (lface1, lface2)
5475 Lisp_Object *lface1, *lface2;
5476{
5477 xassert (lface_fully_specified_p (lface1)
5478 && lface_fully_specified_p (lface2));
d5db4077
KR
5479 return (xstricmp (SDATA (lface1[LFACE_FAMILY_INDEX]),
5480 SDATA (lface2[LFACE_FAMILY_INDEX])) == 0
2c20458f 5481 && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
82641697 5482 && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
a08332c0 5483 && EQ (lface1[LFACE_AVGWIDTH_INDEX], lface2[LFACE_AVGWIDTH_INDEX])
82641697 5484 && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
39506348
KH
5485 && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
5486 && (EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
5487 || (STRINGP (lface1[LFACE_FONT_INDEX])
d00b1b63 5488 && STRINGP (lface2[LFACE_FONT_INDEX])
8f924df7
KH
5489 && ! xstricmp (SDATA (lface1[LFACE_FONT_INDEX]),
5490 SDATA (lface2[LFACE_FONT_INDEX]))))
763bc839
KH
5491 && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
5492 || (STRINGP (lface1[LFACE_FONTSET_INDEX])
5493 && STRINGP (lface2[LFACE_FONTSET_INDEX])
8f924df7
KH
5494 && ! xstricmp (SDATA (lface1[LFACE_FONTSET_INDEX]),
5495 SDATA (lface2[LFACE_FONTSET_INDEX]))))
763bc839 5496 );
82641697
GM
5497}
5498
5499
5500\f
5501/***********************************************************************
5502 Realized Faces
5503 ***********************************************************************/
5504
5505/* Allocate and return a new realized face for Lisp face attribute
39506348 5506 vector ATTR. */
82641697
GM
5507
5508static struct face *
39506348 5509make_realized_face (attr)
82641697 5510 Lisp_Object *attr;
82641697
GM
5511{
5512 struct face *face = (struct face *) xmalloc (sizeof *face);
5513 bzero (face, sizeof *face);
39506348 5514 face->ascii_face = face;
82641697
GM
5515 bcopy (attr, face->lface, sizeof face->lface);
5516 return face;
5517}
5518
5519
5520/* Free realized face FACE, including its X resources. FACE may
5521 be null. */
5522
81b39386 5523void
82641697
GM
5524free_realized_face (f, face)
5525 struct frame *f;
5526 struct face *face;
5527{
5528 if (face)
5529 {
c3cee013
JR
5530#ifdef HAVE_WINDOW_SYSTEM
5531 if (FRAME_WINDOW_P (f))
82641697 5532 {
39506348
KH
5533 /* Free fontset of FACE if it is ASCII face. */
5534 if (face->fontset >= 0 && face == face->ascii_face)
5535 free_face_fontset (f, face);
82641697
GM
5536 if (face->gc)
5537 {
426b2119
KH
5538#ifdef USE_FONT_BACKEND
5539 if (enable_font_backend && face->font_info)
5540 font_done_for_face (f, face);
5541#endif /* USE_FONT_BACKEND */
82641697
GM
5542 x_free_gc (f, face->gc);
5543 face->gc = 0;
5544 }
178c5d9c 5545
82641697
GM
5546 free_face_colors (f, face);
5547 x_destroy_bitmap (f, face->stipple);
5548 }
c3cee013 5549#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5550
5551 xfree (face);
5552 }
5553}
5554
5555
5556/* Prepare face FACE for subsequent display on frame F. This
5557 allocated GCs if they haven't been allocated yet or have been freed
5558 by clearing the face cache. */
5559
5560void
5561prepare_face_for_display (f, face)
5562 struct frame *f;
5563 struct face *face;
5564{
c3cee013
JR
5565#ifdef HAVE_WINDOW_SYSTEM
5566 xassert (FRAME_WINDOW_P (f));
178c5d9c 5567
82641697
GM
5568 if (face->gc == 0)
5569 {
5570 XGCValues xgcv;
5571 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
5572
5573 xgcv.foreground = face->foreground;
5574 xgcv.background = face->background;
c3cee013 5575#ifdef HAVE_X_WINDOWS
82641697 5576 xgcv.graphics_exposures = False;
c3cee013 5577#endif
82641697
GM
5578 /* The font of FACE may be null if we couldn't load it. */
5579 if (face->font)
5580 {
c3cee013 5581#ifdef HAVE_X_WINDOWS
82641697 5582 xgcv.font = face->font->fid;
c3cee013
JR
5583#endif
5584#ifdef WINDOWSNT
5585 xgcv.font = face->font;
1a578e9b 5586#endif
e0f712ba 5587#ifdef MAC_OS
1a578e9b 5588 xgcv.font = face->font;
c3cee013 5589#endif
82641697
GM
5590 mask |= GCFont;
5591 }
5592
5593 BLOCK_INPUT;
c3cee013 5594#ifdef HAVE_X_WINDOWS
82641697
GM
5595 if (face->stipple)
5596 {
be8a72f4 5597 xgcv.fill_style = FillOpaqueStippled;
82641697
GM
5598 xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
5599 mask |= GCFillStyle | GCStipple;
5600 }
c3cee013 5601#endif
82641697 5602 face->gc = x_create_gc (f, mask, &xgcv);
426b2119
KH
5603#ifdef USE_FONT_BACKEND
5604 if (enable_font_backend && face->font)
5605 font_prepare_for_face (f, face);
5606#endif /* USE_FONT_BACKEND */
82641697
GM
5607 UNBLOCK_INPUT;
5608 }
c3cee013 5609#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5610}
5611
82641697 5612\f
b35df831
MB
5613/* Returns the `distance' between the colors X and Y. */
5614
5615static int
5616color_distance (x, y)
5617 XColor *x, *y;
5618{
5619 /* This formula is from a paper title `Colour metric' by Thiadmer Riemersma.
5620 Quoting from that paper:
5621
5622 This formula has results that are very close to L*u*v* (with the
5623 modified lightness curve) and, more importantly, it is a more even
5624 algorithm: it does not have a range of colours where it suddenly
5625 gives far from optimal results.
5626
5627 See <http://www.compuphase.com/cmetric.htm> for more info. */
5628
5629 long r = (x->red - y->red) >> 8;
5630 long g = (x->green - y->green) >> 8;
5631 long b = (x->blue - y->blue) >> 8;
5632 long r_mean = (x->red + y->red) >> 9;
5633
5634 return
5635 (((512 + r_mean) * r * r) >> 8)
5636 + 4 * g * g
5637 + (((767 - r_mean) * b * b) >> 8);
5638}
5639
5640
5641DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 3, 0,
5642 doc: /* Return an integer distance between COLOR1 and COLOR2 on FRAME.
5643COLOR1 and COLOR2 may be either strings containing the color name,
5644or lists of the form (RED GREEN BLUE).
5645If FRAME is unspecified or nil, the current frame is used. */)
5646 (color1, color2, frame)
5647 Lisp_Object color1, color2, frame;
5648{
5649 struct frame *f;
5650 XColor cdef1, cdef2;
5651
5652 if (NILP (frame))
5653 frame = selected_frame;
5654 CHECK_LIVE_FRAME (frame);
5655 f = XFRAME (frame);
5656
5657 if ((CONSP (color1) && !parse_rgb_list (color1, &cdef1))
5658 || !STRINGP (color1)
d5db4077 5659 || !defined_color (f, SDATA (color1), &cdef1, 0))
b35df831
MB
5660 signal_error ("Invalid color", color1);
5661 if ((CONSP (color2) && !parse_rgb_list (color2, &cdef2))
5662 || !STRINGP (color2)
d5db4077 5663 || !defined_color (f, SDATA (color2), &cdef2, 0))
b35df831
MB
5664 signal_error ("Invalid color", color2);
5665
5666 return make_number (color_distance (&cdef1, &cdef2));
5667}
5668
5669\f
82641697
GM
5670/***********************************************************************
5671 Face Cache
5672 ***********************************************************************/
5673
5674/* Return a new face cache for frame F. */
5675
5676static struct face_cache *
5677make_face_cache (f)
5678 struct frame *f;
5679{
5680 struct face_cache *c;
5681 int size;
5682
5683 c = (struct face_cache *) xmalloc (sizeof *c);
5684 bzero (c, sizeof *c);
5685 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5686 c->buckets = (struct face **) xmalloc (size);
5687 bzero (c->buckets, size);
5688 c->size = 50;
5689 c->faces_by_id = (struct face **) xmalloc (c->size * sizeof *c->faces_by_id);
5690 c->f = f;
ceeda019 5691 c->menu_face_changed_p = menu_face_changed_default;
82641697
GM
5692 return c;
5693}
5694
5695
5696/* Clear out all graphics contexts for all realized faces, except for
5697 the basic faces. This should be done from time to time just to avoid
5698 keeping too many graphics contexts that are no longer needed. */
5699
5700static void
5701clear_face_gcs (c)
5702 struct face_cache *c;
5703{
c3cee013 5704 if (c && FRAME_WINDOW_P (c->f))
82641697 5705 {
c3cee013 5706#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
5707 int i;
5708 for (i = BASIC_FACE_ID_SENTINEL; i < c->used; ++i)
5709 {
5710 struct face *face = c->faces_by_id[i];
5711 if (face && face->gc)
5712 {
426b2119
KH
5713#ifdef USE_FONT_BACKEND
5714 if (enable_font_backend && face->font_info)
5715 font_done_for_face (c->f, face);
5716#endif /* USE_FONT_BACKEND */
82641697
GM
5717 x_free_gc (c->f, face->gc);
5718 face->gc = 0;
5719 }
5720 }
c3cee013 5721#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
5722 }
5723}
5724
5725
7fc92635
JB
5726/* Free all realized faces in face cache C, including basic faces.
5727 C may be null. If faces are freed, make sure the frame's current
82641697
GM
5728 matrix is marked invalid, so that a display caused by an expose
5729 event doesn't try to use faces we destroyed. */
5730
5731static void
5732free_realized_faces (c)
5733 struct face_cache *c;
5734{
5735 if (c && c->used)
5736 {
5737 int i, size;
5738 struct frame *f = c->f;
5739
84ec3b4b
GM
5740 /* We must block input here because we can't process X events
5741 safely while only some faces are freed, or when the frame's
5742 current matrix still references freed faces. */
5743 BLOCK_INPUT;
5744
82641697
GM
5745 for (i = 0; i < c->used; ++i)
5746 {
5747 free_realized_face (f, c->faces_by_id[i]);
5748 c->faces_by_id[i] = NULL;
5749 }
178c5d9c 5750
82641697
GM
5751 c->used = 0;
5752 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5753 bzero (c->buckets, size);
5754
5755 /* Must do a thorough redisplay the next time. Mark current
5756 matrices as invalid because they will reference faces freed
5757 above. This function is also called when a frame is
5758 destroyed. In this case, the root window of F is nil. */
5759 if (WINDOWP (f->root_window))
5760 {
5761 clear_current_matrices (f);
5762 ++windows_or_buffers_changed;
5763 }
84ec3b4b
GM
5764
5765 UNBLOCK_INPUT;
82641697
GM
5766 }
5767}
5768
5769
81b39386 5770/* Free all realized faces that are using FONTSET on frame F. */
39506348
KH
5771
5772void
81b39386 5773free_realized_faces_for_fontset (f, fontset)
39506348
KH
5774 struct frame *f;
5775 int fontset;
5776{
5777 struct face_cache *cache = FRAME_FACE_CACHE (f);
5778 struct face *face;
5779 int i;
5780
84ec3b4b
GM
5781 /* We must block input here because we can't process X events safely
5782 while only some faces are freed, or when the frame's current
5783 matrix still references freed faces. */
5784 BLOCK_INPUT;
178c5d9c 5785
39506348
KH
5786 for (i = 0; i < cache->used; i++)
5787 {
5788 face = cache->faces_by_id[i];
5789 if (face
39506348
KH
5790 && face->fontset == fontset)
5791 {
5792 uncache_face (cache, face);
5793 free_realized_face (f, face);
5794 }
5795 }
178c5d9c 5796
84ec3b4b
GM
5797 /* Must do a thorough redisplay the next time. Mark current
5798 matrices as invalid because they will reference faces freed
5799 above. This function is also called when a frame is destroyed.
5800 In this case, the root window of F is nil. */
39506348
KH
5801 if (WINDOWP (f->root_window))
5802 {
5803 clear_current_matrices (f);
5804 ++windows_or_buffers_changed;
5805 }
178c5d9c 5806
84ec3b4b 5807 UNBLOCK_INPUT;
39506348
KH
5808}
5809
5810
82641697
GM
5811/* Free all realized faces on FRAME or on all frames if FRAME is nil.
5812 This is done after attributes of a named face have been changed,
5813 because we can't tell which realized faces depend on that face. */
5814
5815void
5816free_all_realized_faces (frame)
5817 Lisp_Object frame;
5818{
5819 if (NILP (frame))
5820 {
5821 Lisp_Object rest;
5822 FOR_EACH_FRAME (rest, frame)
5823 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
5824 }
5825 else
5826 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
5827}
5828
5829
5830/* Free face cache C and faces in it, including their X resources. */
5831
5832static void
5833free_face_cache (c)
5834 struct face_cache *c;
5835{
5836 if (c)
5837 {
5838 free_realized_faces (c);
5839 xfree (c->buckets);
5840 xfree (c->faces_by_id);
5841 xfree (c);
5842 }
5843}
5844
5845
5846/* Cache realized face FACE in face cache C. HASH is the hash value
af53b43c
KH
5847 of FACE. If FACE is for ASCII characters (i.e. FACE->ascii_face ==
5848 FACE), insert the new face to the beginning of the collision list
5849 of the face hash table of C. Otherwise, add the new face to the
5850 end of the collision list. This way, lookup_face can quickly find
5851 that a requested face is not cached. */
82641697
GM
5852
5853static void
5854cache_face (c, face, hash)
5855 struct face_cache *c;
5856 struct face *face;
5857 unsigned hash;
5858{
5859 int i = hash % FACE_CACHE_BUCKETS_SIZE;
5860
5861 face->hash = hash;
5862
af53b43c 5863 if (face->ascii_face != face)
82641697
GM
5864 {
5865 struct face *last = c->buckets[i];
5866 if (last)
5867 {
5868 while (last->next)
5869 last = last->next;
5870 last->next = face;
5871 face->prev = last;
5872 face->next = NULL;
5873 }
5874 else
5875 {
5876 c->buckets[i] = face;
5877 face->prev = face->next = NULL;
5878 }
5879 }
5880 else
5881 {
5882 face->prev = NULL;
5883 face->next = c->buckets[i];
5884 if (face->next)
5885 face->next->prev = face;
5886 c->buckets[i] = face;
5887 }
5888
5889 /* Find a free slot in C->faces_by_id and use the index of the free
5890 slot as FACE->id. */
5891 for (i = 0; i < c->used; ++i)
5892 if (c->faces_by_id[i] == NULL)
5893 break;
5894 face->id = i;
178c5d9c 5895
82641697 5896 /* Maybe enlarge C->faces_by_id. */
6b61353c 5897 if (i == c->used)
82641697 5898 {
6b61353c
KH
5899 if (c->used == c->size)
5900 {
5901 int new_size, sz;
5902 new_size = min (2 * c->size, MAX_FACE_ID);
5903 if (new_size == c->size)
5904 abort (); /* Alternatives? ++kfs */
5905 sz = new_size * sizeof *c->faces_by_id;
5906 c->faces_by_id = (struct face **) xrealloc (c->faces_by_id, sz);
5907 c->size = new_size;
5908 }
5909 c->used++;
82641697
GM
5910 }
5911
5912#if GLYPH_DEBUG
5913 /* Check that FACE got a unique id. */
5914 {
5915 int j, n;
5916 struct face *face;
5917
5918 for (j = n = 0; j < FACE_CACHE_BUCKETS_SIZE; ++j)
5919 for (face = c->buckets[j]; face; face = face->next)
5920 if (face->id == i)
5921 ++n;
5922
5923 xassert (n == 1);
5924 }
5925#endif /* GLYPH_DEBUG */
178c5d9c 5926
82641697 5927 c->faces_by_id[i] = face;
82641697
GM
5928}
5929
5930
5931/* Remove face FACE from cache C. */
5932
5933static void
5934uncache_face (c, face)
5935 struct face_cache *c;
5936 struct face *face;
5937{
5938 int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
178c5d9c 5939
82641697
GM
5940 if (face->prev)
5941 face->prev->next = face->next;
5942 else
5943 c->buckets[i] = face->next;
178c5d9c 5944
82641697
GM
5945 if (face->next)
5946 face->next->prev = face->prev;
178c5d9c 5947
82641697
GM
5948 c->faces_by_id[face->id] = NULL;
5949 if (face->id == c->used)
5950 --c->used;
5951}
5952
5953
5954/* Look up a realized face with face attributes ATTR in the face cache
af53b43c
KH
5955 of frame F. The face will be used to display ASCII characters.
5956 Value is the ID of the face found. If no suitable face is found,
5957 realize a new one. */
82641697
GM
5958
5959INLINE int
af53b43c 5960lookup_face (f, attr)
82641697
GM
5961 struct frame *f;
5962 Lisp_Object *attr;
82641697 5963{
39506348 5964 struct face_cache *cache = FRAME_FACE_CACHE (f);
82641697
GM
5965 unsigned hash;
5966 int i;
5967 struct face *face;
5968
39506348 5969 xassert (cache != NULL);
82641697
GM
5970 check_lface_attrs (attr);
5971
5972 /* Look up ATTR in the face cache. */
5973 hash = lface_hash (attr);
5974 i = hash % FACE_CACHE_BUCKETS_SIZE;
178c5d9c 5975
39506348 5976 for (face = cache->buckets[i]; face; face = face->next)
af53b43c
KH
5977 {
5978 if (face->ascii_face != face)
5979 {
5980 /* There's no more ASCII face. */
5981 face = NULL;
5982 break;
5983 }
5984 if (face->hash == hash
5985 && lface_equal_p (face->lface, attr))
5986 break;
5987 }
82641697
GM
5988
5989 /* If not found, realize a new face. */
5990 if (face == NULL)
af53b43c 5991 face = realize_face (cache, attr, -1);
82641697
GM
5992
5993#if GLYPH_DEBUG
5994 xassert (face == FACE_FROM_ID (f, face->id));
82641697 5995#endif /* GLYPH_DEBUG */
178c5d9c 5996
82641697
GM
5997 return face->id;
5998}
5999
8c6204de 6000#ifdef HAVE_WINDOW_SYSTEM
af53b43c
KH
6001/* Look up a realized face that has the same attributes as BASE_FACE
6002 except for the font in the face cache of frame F. If FONT_ID is
6003 not negative, it is an ID number of an already opened font that is
6004 used by the face. If FONT_ID is negative, the face has no font.
6005 Value is the ID of the face found. If no suitable face is found,
6006 realize a new one. */
6007
8f924df7 6008int
af53b43c
KH
6009lookup_non_ascii_face (f, font_id, base_face)
6010 struct frame *f;
6011 int font_id;
6012 struct face *base_face;
6013{
6014 struct face_cache *cache = FRAME_FACE_CACHE (f);
6015 unsigned hash;
6016 int i;
6017 struct face *face;
6018
6019 xassert (cache != NULL);
6020 base_face = base_face->ascii_face;
6021 hash = lface_hash (base_face->lface);
6022 i = hash % FACE_CACHE_BUCKETS_SIZE;
6023
6024 for (face = cache->buckets[i]; face; face = face->next)
6025 {
6026 if (face->ascii_face == face)
6027 continue;
6028 if (face->ascii_face == base_face
6029 && face->font_info_id == font_id)
6030 break;
6031 }
6032
6033 /* If not found, realize a new face. */
6034 if (face == NULL)
6035 face = realize_non_ascii_face (f, font_id, base_face);
6036
6037#if GLYPH_DEBUG
6038 xassert (face == FACE_FROM_ID (f, face->id));
82641697 6039#endif /* GLYPH_DEBUG */
178c5d9c 6040
82641697
GM
6041 return face->id;
6042}
426b2119
KH
6043
6044#ifdef USE_FONT_BACKEND
6045int
6046face_for_font (f, font, base_face)
6047 struct frame *f;
6048 struct font *font;
6049 struct face *base_face;
6050{
6051 struct face_cache *cache = FRAME_FACE_CACHE (f);
6052 unsigned hash;
6053 int i;
6054 struct face *face;
6055
6056 xassert (cache != NULL);
6057 base_face = base_face->ascii_face;
6058 hash = lface_hash (base_face->lface);
6059 i = hash % FACE_CACHE_BUCKETS_SIZE;
6060
6061 for (face = cache->buckets[i]; face; face = face->next)
6062 {
6063 if (face->ascii_face == face)
6064 continue;
6065 if (face->ascii_face == base_face
6066 && face->font_info == (struct font_info *) font)
6067 return face->id;
6068 }
6069
6070 /* If not found, realize a new face. */
6071 face = realize_non_ascii_face (f, -1, base_face);
6072 face->font = font->font.font;
6073 face->font_info = (struct font_info *) font;
6074 face->font_info_id = 0;
6075 face->font_name = font->font.full_name;
6076 return face->id;
6077}
6078#endif /* USE_FONT_BACKEND */
6079
8c6204de 6080#endif /* HAVE_WINDOW_SYSTEM */
82641697 6081
82641697 6082/* Return the face id of the realized face for named face SYMBOL on
af53b43c
KH
6083 frame F suitable for displaying ASCII characters. Value is -1 if
6084 the face couldn't be determined, which might happen if the default
6085 face isn't realized and cannot be realized. */
82641697
GM
6086
6087int
000fc2b1 6088lookup_named_face (f, symbol, signal_p)
82641697
GM
6089 struct frame *f;
6090 Lisp_Object symbol;
2272e967 6091 int signal_p;
82641697
GM
6092{
6093 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6094 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
6095 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6096
b5de343d
GM
6097 if (default_face == NULL)
6098 {
6099 if (!realize_basic_faces (f))
6100 return -1;
6101 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6102 }
6103
2272e967
KS
6104 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p))
6105 return -1;
6106
82641697 6107 bcopy (default_face->lface, attrs, sizeof attrs);
a0a23346
MB
6108 merge_face_vectors (f, symbol_attrs, attrs, 0);
6109
af53b43c 6110 return lookup_face (f, attrs);
82641697
GM
6111}
6112
6113
6114/* Return the ID of the realized ASCII face of Lisp face with ID
6115 LFACE_ID on frame F. Value is -1 if LFACE_ID isn't valid. */
6116
6117int
6118ascii_face_of_lisp_face (f, lface_id)
6119 struct frame *f;
6120 int lface_id;
6121{
6122 int face_id;
178c5d9c 6123
82641697
GM
6124 if (lface_id >= 0 && lface_id < lface_id_to_name_size)
6125 {
6126 Lisp_Object face_name = lface_id_to_name[lface_id];
000fc2b1 6127 face_id = lookup_named_face (f, face_name, 1);
82641697
GM
6128 }
6129 else
6130 face_id = -1;
6131
6132 return face_id;
6133}
6134
6135
6136/* Return a face for charset ASCII that is like the face with id
6137 FACE_ID on frame F, but has a font that is STEPS steps smaller.
6138 STEPS < 0 means larger. Value is the id of the face. */
6139
6140int
6141smaller_face (f, face_id, steps)
6142 struct frame *f;
6143 int face_id, steps;
39506348 6144{
c3cee013 6145#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
6146 struct face *face;
6147 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6148 int pt, last_pt, last_height;
6149 int delta;
6150 int new_face_id;
6151 struct face *new_face;
6152
6153 /* If not called for an X frame, just return the original face. */
6154 if (FRAME_TERMCAP_P (f))
6155 return face_id;
6156
6157 /* Try in increments of 1/2 pt. */
6158 delta = steps < 0 ? 5 : -5;
6159 steps = abs (steps);
178c5d9c 6160
82641697
GM
6161 face = FACE_FROM_ID (f, face_id);
6162 bcopy (face->lface, attrs, sizeof attrs);
6163 pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
6164 new_face_id = face_id;
6165 last_height = FONT_HEIGHT (face->font);
6166
6167 while (steps
6168 && pt + delta > 0
6169 /* Give up if we cannot find a font within 10pt. */
6170 && abs (last_pt - pt) < 100)
6171 {
6172 /* Look up a face for a slightly smaller/larger font. */
6173 pt += delta;
6174 attrs[LFACE_HEIGHT_INDEX] = make_number (pt);
af53b43c 6175 new_face_id = lookup_face (f, attrs);
82641697
GM
6176 new_face = FACE_FROM_ID (f, new_face_id);
6177
6178 /* If height changes, count that as one step. */
b4c3ca09
GM
6179 if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
6180 || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
82641697
GM
6181 {
6182 --steps;
6183 last_height = FONT_HEIGHT (new_face->font);
6184 last_pt = pt;
6185 }
6186 }
6187
6188 return new_face_id;
6189
c3cee013 6190#else /* not HAVE_WINDOW_SYSTEM */
82641697
GM
6191
6192 return face_id;
178c5d9c 6193
c3cee013 6194#endif /* not HAVE_WINDOW_SYSTEM */
82641697
GM
6195}
6196
6197
6198/* Return a face for charset ASCII that is like the face with id
6199 FACE_ID on frame F, but has height HEIGHT. */
6200
6201int
6202face_with_height (f, face_id, height)
6203 struct frame *f;
6204 int face_id;
6205 int height;
6206{
c3cee013 6207#ifdef HAVE_WINDOW_SYSTEM
82641697
GM
6208 struct face *face;
6209 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6210
6211 if (FRAME_TERMCAP_P (f)
6212 || height <= 0)
6213 return face_id;
6214
6215 face = FACE_FROM_ID (f, face_id);
6216 bcopy (face->lface, attrs, sizeof attrs);
6217 attrs[LFACE_HEIGHT_INDEX] = make_number (height);
af53b43c 6218 face_id = lookup_face (f, attrs);
c3cee013 6219#endif /* HAVE_WINDOW_SYSTEM */
178c5d9c 6220
82641697
GM
6221 return face_id;
6222}
6223
b5de343d 6224
44747bd0 6225/* Return the face id of the realized face for named face SYMBOL on
af53b43c
KH
6226 frame F suitable for displaying ASCII characters, and use
6227 attributes of the face FACE_ID for attributes that aren't
6228 completely specified by SYMBOL. This is like lookup_named_face,
6229 except that the default attributes come from FACE_ID, not from the
6230 default face. FACE_ID is assumed to be already realized. */
44747bd0
EZ
6231
6232int
5c538596 6233lookup_derived_face (f, symbol, face_id, signal_p)
44747bd0
EZ
6234 struct frame *f;
6235 Lisp_Object symbol;
44747bd0 6236 int face_id;
5c538596 6237 int signal_p;
44747bd0
EZ
6238{
6239 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6240 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
6241 struct face *default_face = FACE_FROM_ID (f, face_id);
6242
6243 if (!default_face)
6244 abort ();
6245
d196a547 6246 get_lface_attributes (f, symbol, symbol_attrs, signal_p);
44747bd0 6247 bcopy (default_face->lface, attrs, sizeof attrs);
a0a23346 6248 merge_face_vectors (f, symbol_attrs, attrs, 0);
af53b43c 6249 return lookup_face (f, attrs);
44747bd0
EZ
6250}
6251
f6608d5c
RS
6252DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
6253 Sface_attributes_as_vector, 1, 1, 0,
4bb962be 6254 doc: /* Return a vector of face attributes corresponding to PLIST. */)
f6608d5c
RS
6255 (plist)
6256 Lisp_Object plist;
6257{
6258 Lisp_Object lface;
6259 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
6260 Qunspecified);
a0a23346
MB
6261 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents,
6262 1, 0);
f6608d5c
RS
6263 return lface;
6264}
6265
82641697
GM
6266
6267\f
9717e36c
MB
6268/***********************************************************************
6269 Face capability testing
6270 ***********************************************************************/
6271
6272
6273/* If the distance (as returned by color_distance) between two colors is
6274 less than this, then they are considered the same, for determining
6275 whether a color is supported or not. The range of values is 0-65535. */
6276
6277#define TTY_SAME_COLOR_THRESHOLD 10000
6278
ccda4e3c 6279#ifdef HAVE_WINDOW_SYSTEM
9717e36c
MB
6280
6281/* Return non-zero if all the face attributes in ATTRS are supported
6282 on the window-system frame F.
6283
6284 The definition of `supported' is somewhat heuristic, but basically means
6285 that a face containing all the attributes in ATTRS, when merged with the
6286 default face for display, can be represented in a way that's
6287
6288 \(1) different in appearance than the default face, and
8e330b22 6289 \(2) `close in spirit' to what the attributes specify, if not exact. */
9717e36c
MB
6290
6291static int
8e330b22 6292x_supports_face_attributes_p (f, attrs, def_face)
9717e36c
MB
6293 struct frame *f;
6294 Lisp_Object *attrs;
8e330b22 6295 struct face *def_face;
9717e36c 6296{
8e330b22 6297 Lisp_Object *def_attrs = def_face->lface;
9717e36c
MB
6298
6299 /* Check that other specified attributes are different that the default
6300 face. */
6301 if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
6302 && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
6303 def_attrs[LFACE_UNDERLINE_INDEX]))
6304 || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
6305 && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
6306 def_attrs[LFACE_INVERSE_INDEX]))
6307 || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
6308 && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
6309 def_attrs[LFACE_FOREGROUND_INDEX]))
6310 || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
6311 && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
6312 def_attrs[LFACE_BACKGROUND_INDEX]))
6313 || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
6314 && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
6315 def_attrs[LFACE_STIPPLE_INDEX]))
6316 || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
6317 && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
6318 def_attrs[LFACE_OVERLINE_INDEX]))
6319 || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
6320 && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
6321 def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
6322 || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
6323 && face_attr_equal_p (attrs[LFACE_BOX_INDEX],
6324 def_attrs[LFACE_BOX_INDEX])))
6325 return 0;
6326
6327 /* Check font-related attributes, as those are the most commonly
6328 "unsupported" on a window-system (because of missing fonts). */
6329 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
6330 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
6331 || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
6332 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
6333 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
6334 || !UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX]))
6335 {
327719ee 6336 int face_id;
9717e36c
MB
6337 struct face *face;
6338 Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
6339
6340 bcopy (def_attrs, merged_attrs, sizeof merged_attrs);
6341
a0a23346 6342 merge_face_vectors (f, attrs, merged_attrs, 0);
9717e36c 6343
327719ee
MB
6344 face_id = lookup_face (f, merged_attrs);
6345 face = FACE_FROM_ID (f, face_id);
9717e36c
MB
6346
6347 if (! face)
2010ba8c 6348 error ("Cannot make face");
9717e36c
MB
6349
6350 /* If the font is the same, then not supported. */
6351 if (face->font == def_face->font)
6352 return 0;
6353 }
6354
6355 /* Everything checks out, this face is supported. */
6356 return 1;
6357}
6358
ccda4e3c 6359#endif /* HAVE_WINDOW_SYSTEM */
9717e36c
MB
6360
6361/* Return non-zero if all the face attributes in ATTRS are supported
6362 on the tty frame F.
6363
6364 The definition of `supported' is somewhat heuristic, but basically means
6365 that a face containing all the attributes in ATTRS, when merged
6366 with the default face for display, can be represented in a way that's
6367
6368 \(1) different in appearance than the default face, and
6369 \(2) `close in spirit' to what the attributes specify, if not exact.
6370
6371 Point (2) implies that a `:weight black' attribute will be satisfied
6372 by any terminal that can display bold, and a `:foreground "yellow"' as
6373 long as the terminal can display a yellowish color, but `:slant italic'
6374 will _not_ be satisfied by the tty display code's automatic
6375 substitution of a `dim' face for italic. */
6376
6377static int
8e330b22 6378tty_supports_face_attributes_p (f, attrs, def_face)
9717e36c
MB
6379 struct frame *f;
6380 Lisp_Object *attrs;
8e330b22 6381 struct face *def_face;
9717e36c 6382{
734e9514 6383 int weight;
9717e36c
MB
6384 Lisp_Object val, fg, bg;
6385 XColor fg_tty_color, fg_std_color;
6386 XColor bg_tty_color, bg_std_color;
6387 unsigned test_caps = 0;
8e330b22 6388 Lisp_Object *def_attrs = def_face->lface;
9717e36c 6389
9717e36c 6390
8e330b22
MB
6391 /* First check some easy-to-check stuff; ttys support none of the
6392 following attributes, so we can just return false if any are requested
6393 (even if `nominal' values are specified, we should still return false,
6394 as that will be the same value that the default face uses). We
6395 consider :slant unsupportable on ttys, even though the face code
6396 actually `fakes' them using a dim attribute if possible. This is
6397 because the faked result is too different from what the face
6398 specifies. */
6399 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
6400 || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
6401 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
6402 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
6403 || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
6404 || !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
6405 || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
6406 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]))
9717e36c
MB
6407 return 0;
6408
6409
6410 /* Test for terminal `capabilities' (non-color character attributes). */
6411
6412 /* font weight (bold/dim) */
6413 weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
6414 if (weight >= 0)
6415 {
8e330b22
MB
6416 int def_weight = face_numeric_weight (def_attrs[LFACE_WEIGHT_INDEX]);
6417
9717e36c 6418 if (weight > XLFD_WEIGHT_MEDIUM)
8e330b22
MB
6419 {
6420 if (def_weight > XLFD_WEIGHT_MEDIUM)
6421 return 0; /* same as default */
6422 test_caps = TTY_CAP_BOLD;
6423 }
9717e36c 6424 else if (weight < XLFD_WEIGHT_MEDIUM)
8e330b22
MB
6425 {
6426 if (def_weight < XLFD_WEIGHT_MEDIUM)
6427 return 0; /* same as default */
6428 test_caps = TTY_CAP_DIM;
6429 }
6430 else if (def_weight == XLFD_WEIGHT_MEDIUM)
6431 return 0; /* same as default */
9717e36c
MB
6432 }
6433
6434 /* underlining */
6435 val = attrs[LFACE_UNDERLINE_INDEX];
8e330b22 6436 if (!UNSPECIFIEDP (val))
9717e36c
MB
6437 {
6438 if (STRINGP (val))
8e330b22
MB
6439 return 0; /* ttys can't use colored underlines */
6440 else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
6441 return 0; /* same as default */
9717e36c
MB
6442 else
6443 test_caps |= TTY_CAP_UNDERLINE;
6444 }
6445
6446 /* inverse video */
6447 val = attrs[LFACE_INVERSE_INDEX];
8e330b22
MB
6448 if (!UNSPECIFIEDP (val))
6449 {
6450 if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
6451 return 0; /* same as default */
6452 else
6453 test_caps |= TTY_CAP_INVERSE;
6454 }
9717e36c
MB
6455
6456
6457 /* Color testing. */
6458
6459 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
6460 we use them when calling `tty_capable_p' below, even if the face
6461 specifies no colors. */
6462 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
6463 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
6464
6465 /* Check if foreground color is close enough. */
6466 fg = attrs[LFACE_FOREGROUND_INDEX];
6467 if (STRINGP (fg))
6468 {
8e330b22
MB
6469 Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
6470
6471 if (face_attr_equal_p (fg, def_fg))
6472 return 0; /* same as default */
6473 else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
6474 return 0; /* not a valid color */
9717e36c
MB
6475 else if (color_distance (&fg_tty_color, &fg_std_color)
6476 > TTY_SAME_COLOR_THRESHOLD)
8e330b22
MB
6477 return 0; /* displayed color is too different */
6478 else
6479 /* Make sure the color is really different than the default. */
6480 {
6481 XColor def_fg_color;
6482 if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
6483 && (color_distance (&fg_tty_color, &def_fg_color)
6484 <= TTY_SAME_COLOR_THRESHOLD))
6485 return 0;
6486 }
9717e36c
MB
6487 }
6488
6489 /* Check if background color is close enough. */
6490 bg = attrs[LFACE_BACKGROUND_INDEX];
6491 if (STRINGP (bg))
6492 {
8e330b22
MB
6493 Lisp_Object def_bg = def_attrs[LFACE_FOREGROUND_INDEX];
6494
6495 if (face_attr_equal_p (bg, def_bg))
6496 return 0; /* same as default */
6497 else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
6498 return 0; /* not a valid color */
9717e36c
MB
6499 else if (color_distance (&bg_tty_color, &bg_std_color)
6500 > TTY_SAME_COLOR_THRESHOLD)
8e330b22
MB
6501 return 0; /* displayed color is too different */
6502 else
6503 /* Make sure the color is really different than the default. */
6504 {
6505 XColor def_bg_color;
6506 if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
6507 && (color_distance (&bg_tty_color, &def_bg_color)
6508 <= TTY_SAME_COLOR_THRESHOLD))
6509 return 0;
6510 }
9717e36c
MB
6511 }
6512
6513 /* If both foreground and background are requested, see if the
6514 distance between them is OK. We just check to see if the distance
6515 between the tty's foreground and background is close enough to the
6516 distance between the standard foreground and background. */
6517 if (STRINGP (fg) && STRINGP (bg))
6518 {
6519 int delta_delta
6520 = (color_distance (&fg_std_color, &bg_std_color)
6521 - color_distance (&fg_tty_color, &bg_tty_color));
6522 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
6523 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
6524 return 0;
6525 }
6526
6527
6528 /* See if the capabilities we selected above are supported, with the
6529 given colors. */
6530 if (test_caps != 0 &&
6531 ! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
6532 return 0;
6533
6534
6535 /* Hmmm, everything checks out, this terminal must support this face. */
6536 return 1;
6537}
6538
6539
6540DEFUN ("display-supports-face-attributes-p",
6541 Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
6542 1, 2, 0,
6543 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
6544The optional argument DISPLAY can be a display name, a frame, or
9fed2905 6545nil (meaning the selected frame's display).
9717e36c
MB
6546
6547The definition of `supported' is somewhat heuristic, but basically means
6548that a face containing all the attributes in ATTRIBUTES, when merged
6549with the default face for display, can be represented in a way that's
6550
6551 \(1) different in appearance than the default face, and
6552 \(2) `close in spirit' to what the attributes specify, if not exact.
6553
6554Point (2) implies that a `:weight black' attribute will be satisfied by
6555any display that can display bold, and a `:foreground \"yellow\"' as long
6556as it can display a yellowish color, but `:slant italic' will _not_ be
6557satisfied by the tty display code's automatic substitution of a `dim'
9fed2905 6558face for italic. */)
9717e36c
MB
6559 (attributes, display)
6560 Lisp_Object attributes, display;
6561{
6562 int supports, i;
6563 Lisp_Object frame;
6564 struct frame *f;
8e330b22 6565 struct face *def_face;
9717e36c
MB
6566 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6567
0722292b
MB
6568 if (noninteractive || !initialized)
6569 /* We may not be able to access low-level face information in batch
6570 mode, or before being dumped, and this function is not going to
6571 be very useful in those cases anyway, so just give up. */
6572 return Qnil;
6573
9717e36c
MB
6574 if (NILP (display))
6575 frame = selected_frame;
6576 else if (FRAMEP (display))
6577 frame = display;
6578 else
6579 {
6580 /* Find any frame on DISPLAY. */
6581 Lisp_Object fl_tail;
6582
6583 frame = Qnil;
6584 for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
6585 {
6586 frame = XCAR (fl_tail);
6587 if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
6588 XFRAME (frame)->param_alist)),
6589 display)))
6590 break;
6591 }
6592 }
6593
6594 CHECK_LIVE_FRAME (frame);
6595 f = XFRAME (frame);
6596
6597 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
6598 attrs[i] = Qunspecified;
a0a23346 6599 merge_face_ref (f, attributes, attrs, 1, 0);
9717e36c 6600
8e330b22
MB
6601 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6602 if (def_face == NULL)
6603 {
6604 if (! realize_basic_faces (f))
734e9514 6605 error ("Cannot realize default face");
8e330b22
MB
6606 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6607 }
6608
9717e36c
MB
6609 /* Dispatch to the appropriate handler. */
6610 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
8e330b22 6611 supports = tty_supports_face_attributes_p (f, attrs, def_face);
ccda4e3c 6612#ifdef HAVE_WINDOW_SYSTEM
9717e36c 6613 else
8e330b22
MB
6614 supports = x_supports_face_attributes_p (f, attrs, def_face);
6615#endif
9717e36c
MB
6616
6617 return supports ? Qt : Qnil;
6618}
6619
6620\f
82641697
GM
6621/***********************************************************************
6622 Font selection
6623 ***********************************************************************/
6624
8f924df7 6625 DEFUN ("internal-set-font-selection-order",
82641697
GM
6626 Finternal_set_font_selection_order,
6627 Sinternal_set_font_selection_order, 1, 1, 0,
7ee72033 6628 doc: /* Set font selection order for face font selection to ORDER.
228299fa
GM
6629ORDER must be a list of length 4 containing the symbols `:width',
6630`:height', `:weight', and `:slant'. Face attributes appearing
6631first in ORDER are matched first, e.g. if `:height' appears before
6632`:weight' in ORDER, font selection first tries to find a font with
6633a suitable height, and then tries to match the font weight.
7ee72033
MB
6634Value is ORDER. */)
6635 (order)
228299fa 6636 Lisp_Object order;
82641697
GM
6637{
6638 Lisp_Object list;
6639 int i;
a08332c0 6640 int indices[DIM (font_sort_order)];
178c5d9c 6641
b7826503 6642 CHECK_LIST (order);
82641697
GM
6643 bzero (indices, sizeof indices);
6644 i = 0;
6645
6646 for (list = order;
6647 CONSP (list) && i < DIM (indices);
6648 list = XCDR (list), ++i)
6649 {
6650 Lisp_Object attr = XCAR (list);
6651 int xlfd;
6652
6653 if (EQ (attr, QCwidth))
6654 xlfd = XLFD_SWIDTH;
6655 else if (EQ (attr, QCheight))
6656 xlfd = XLFD_POINT_SIZE;
6657 else if (EQ (attr, QCweight))
6658 xlfd = XLFD_WEIGHT;
6659 else if (EQ (attr, QCslant))
6660 xlfd = XLFD_SLANT;
6661 else
6662 break;
6663
6664 if (indices[i] != 0)
6665 break;
6666 indices[i] = xlfd;
6667 }
6668
a08332c0 6669 if (!NILP (list) || i != DIM (indices))
82641697 6670 signal_error ("Invalid font sort order", order);
a08332c0
GM
6671 for (i = 0; i < DIM (font_sort_order); ++i)
6672 if (indices[i] == 0)
6673 signal_error ("Invalid font sort order", order);
82641697
GM
6674
6675 if (bcmp (indices, font_sort_order, sizeof indices) != 0)
6676 {
6677 bcopy (indices, font_sort_order, sizeof font_sort_order);
6678 free_all_realized_faces (Qnil);
6679 }
178c5d9c 6680
426b2119
KH
6681#ifdef USE_FONT_BACKEND
6682 font_update_sort_order (font_sort_order);
6683#endif /* USE_FONT_BACKEND */
6684
82641697
GM
6685 return Qnil;
6686}
6687
6688
6689DEFUN ("internal-set-alternative-font-family-alist",
6690 Finternal_set_alternative_font_family_alist,
6691 Sinternal_set_alternative_font_family_alist, 1, 1, 0,
c71f3632 6692 doc: /* Define alternative font families to try in face font selection.
228299fa
GM
6693ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
6694Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
7ee72033
MB
6695be found. Value is ALIST. */)
6696 (alist)
82641697
GM
6697 Lisp_Object alist;
6698{
b7826503 6699 CHECK_LIST (alist);
82641697
GM
6700 Vface_alternative_font_family_alist = alist;
6701 free_all_realized_faces (Qnil);
6702 return alist;
6703}
6704
6705
32fcc231
GM
6706DEFUN ("internal-set-alternative-font-registry-alist",
6707 Finternal_set_alternative_font_registry_alist,
6708 Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
e3cd9e7f 6709 doc: /* Define alternative font registries to try in face font selection.
228299fa
GM
6710ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
6711Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
7ee72033
MB
6712be found. Value is ALIST. */)
6713 (alist)
32fcc231
GM
6714 Lisp_Object alist;
6715{
b7826503 6716 CHECK_LIST (alist);
32fcc231
GM
6717 Vface_alternative_font_registry_alist = alist;
6718 free_all_realized_faces (Qnil);
6719 return alist;
6720}
6721
6722
c3cee013 6723#ifdef HAVE_WINDOW_SYSTEM
82641697 6724
82641697
GM
6725/* Value is non-zero if FONT is the name of a scalable font. The
6726 X11R6 XLFD spec says that point size, pixel size, and average width
6727 are zero for scalable fonts. Intlfonts contain at least one
6728 scalable font ("*-muleindian-1") for which this isn't true, so we
6729 just test average width. */
6730
6731static int
6732font_scalable_p (font)
6733 struct font_name *font;
6734{
6735 char *s = font->fields[XLFD_AVGWIDTH];
c3cee013
JR
6736 return (*s == '0' && *(s + 1) == '\0')
6737#ifdef WINDOWSNT
6738 /* Windows implementation of XLFD is slightly broken for backward
6739 compatibility with previous broken versions, so test for
6740 wildcards as well as 0. */
6741 || *s == '*'
6742#endif
6743 ;
82641697
GM
6744}
6745
6746
8e1b21a7
KH
6747/* Ignore the difference of font point size less than this value. */
6748
6749#define FONT_POINT_SIZE_QUANTUM 5
6750
82641697
GM
6751/* Value is non-zero if FONT1 is a better match for font attributes
6752 VALUES than FONT2. VALUES is an array of face attribute values in
6753 font sort order. COMPARE_PT_P zero means don't compare point
a08332c0
GM
6754 sizes. AVGWIDTH, if not zero, is a specified font average width
6755 to compare with. */
82641697
GM
6756
6757static int
a08332c0 6758better_font_p (values, font1, font2, compare_pt_p, avgwidth)
82641697
GM
6759 int *values;
6760 struct font_name *font1, *font2;
a08332c0 6761 int compare_pt_p, avgwidth;
82641697
GM
6762{
6763 int i;
178c5d9c 6764
a08332c0 6765 for (i = 0; i < DIM (font_sort_order); ++i)
82641697
GM
6766 {
6767 int xlfd_idx = font_sort_order[i];
6768
6769 if (compare_pt_p || xlfd_idx != XLFD_POINT_SIZE)
6770 {
f70400f2
KH
6771 int delta1, delta2;
6772
6773 if (xlfd_idx == XLFD_POINT_SIZE)
6774 {
6775 delta1 = abs (values[i] - (font1->numeric[xlfd_idx]
6776 / font1->rescale_ratio));
6777 delta2 = abs (values[i] - (font2->numeric[xlfd_idx]
6778 / font2->rescale_ratio));
6779 if (abs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
6780 continue;
6781 }
6782 else
6783 {
6784 delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
6785 delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
6786 }
178c5d9c 6787
82641697
GM
6788 if (delta1 > delta2)
6789 return 0;
6790 else if (delta1 < delta2)
6791 return 1;
6792 else
6793 {
6794 /* The difference may be equal because, e.g., the face
6795 specifies `italic' but we have only `regular' and
6796 `oblique'. Prefer `oblique' in this case. */
6797 if ((xlfd_idx == XLFD_WEIGHT || xlfd_idx == XLFD_SLANT)
6798 && font1->numeric[xlfd_idx] > values[i]
6799 && font2->numeric[xlfd_idx] < values[i])
6800 return 1;
6801 }
6802 }
6803 }
178c5d9c 6804
a08332c0
GM
6805 if (avgwidth)
6806 {
6807 int delta1 = abs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
6808 int delta2 = abs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
6809 if (delta1 > delta2)
6810 return 0;
6811 else if (delta1 < delta2)
6812 return 1;
6813 }
6814
6b61353c
KH
6815 if (! compare_pt_p)
6816 {
6817 /* We prefer a real scalable font; i.e. not what autoscaled. */
6818 int auto_scaled_1 = (font1->numeric[XLFD_POINT_SIZE] == 0
6819 && font1->numeric[XLFD_RESY] > 0);
6820 int auto_scaled_2 = (font2->numeric[XLFD_POINT_SIZE] == 0
6821 && font2->numeric[XLFD_RESY] > 0);
6822
6823 if (auto_scaled_1 != auto_scaled_2)
6824 return auto_scaled_2;
6825 }
6826
a08332c0 6827 return font1->registry_priority < font2->registry_priority;
82641697
GM
6828}
6829
6830
82641697
GM
6831/* Value is non-zero if FONT is an exact match for face attributes in
6832 SPECIFIED. SPECIFIED is an array of face attribute values in font
a08332c0
GM
6833 sort order. AVGWIDTH, if non-zero, is an average width to compare
6834 with. */
82641697
GM
6835
6836static int
a08332c0 6837exact_face_match_p (specified, font, avgwidth)
82641697
GM
6838 int *specified;
6839 struct font_name *font;
a08332c0 6840 int avgwidth;
82641697
GM
6841{
6842 int i;
178c5d9c 6843
a08332c0 6844 for (i = 0; i < DIM (font_sort_order); ++i)
82641697
GM
6845 if (specified[i] != font->numeric[font_sort_order[i]])
6846 break;
6847
a08332c0
GM
6848 return (i == DIM (font_sort_order)
6849 && (avgwidth <= 0
6850 || avgwidth == font->numeric[XLFD_AVGWIDTH]));
82641697
GM
6851}
6852
6853
6854/* Value is the name of a scaled font, generated from scalable font
6855 FONT on frame F. SPECIFIED_PT is the point-size to scale FONT to.
6856 Value is allocated from heap. */
6857
6858static char *
6859build_scalable_font_name (f, font, specified_pt)
6860 struct frame *f;
6861 struct font_name *font;
6862 int specified_pt;
6863{
a7255152 6864 char pixel_size[20];
82641697
GM
6865 int pixel_value;
6866 double resy = FRAME_X_DISPLAY_INFO (f)->resy;
6867 double pt;
6868
bb229eec
KH
6869 if (font->numeric[XLFD_PIXEL_SIZE] != 0
6870 || font->numeric[XLFD_POINT_SIZE] != 0)
6871 /* This is a scalable font but is requested for a specific size.
6872 We should not change that size. */
6873 return build_font_name (font);
6874
82641697
GM
6875 /* If scalable font is for a specific resolution, compute
6876 the point size we must specify from the resolution of
6877 the display and the specified resolution of the font. */
6878 if (font->numeric[XLFD_RESY] != 0)
6879 {
6880 pt = resy / font->numeric[XLFD_RESY] * specified_pt + 0.5;
02a6375c 6881 pixel_value = font->numeric[XLFD_RESY] / (PT_PER_INCH * 10.0) * pt + 0.5;
82641697
GM
6882 }
6883 else
6884 {
6885 pt = specified_pt;
02a6375c 6886 pixel_value = resy / (PT_PER_INCH * 10.0) * pt + 0.5;
82641697 6887 }
f70400f2
KH
6888 /* We may need a font of the different size. */
6889 pixel_value *= font->rescale_ratio;
178c5d9c 6890
f70400f2
KH
6891 /* We should keep POINT_SIZE 0. Otherwise, X server can't open a
6892 font of the specified PIXEL_SIZE. */
6893#if 0
a7255152
SM
6894 { /* Set point size of the font. */
6895 char point_size[20];
6896 sprintf (point_size, "%d", (int) pt);
6897 font->fields[XLFD_POINT_SIZE] = point_size;
6898 font->numeric[XLFD_POINT_SIZE] = pt;
6899 }
f70400f2 6900#endif
178c5d9c 6901
82641697
GM
6902 /* Set pixel size. */
6903 sprintf (pixel_size, "%d", pixel_value);
6904 font->fields[XLFD_PIXEL_SIZE] = pixel_size;
6905 font->numeric[XLFD_PIXEL_SIZE] = pixel_value;
178c5d9c 6906
82641697
GM
6907 /* If font doesn't specify its resolution, use the
6908 resolution of the display. */
6909 if (font->numeric[XLFD_RESY] == 0)
6910 {
6911 char buffer[20];
6912 sprintf (buffer, "%d", (int) resy);
6913 font->fields[XLFD_RESY] = buffer;
6914 font->numeric[XLFD_RESY] = resy;
6915 }
178c5d9c 6916
82641697
GM
6917 if (strcmp (font->fields[XLFD_RESX], "0") == 0)
6918 {
6919 char buffer[20];
6920 int resx = FRAME_X_DISPLAY_INFO (f)->resx;
6921 sprintf (buffer, "%d", resx);
6922 font->fields[XLFD_RESX] = buffer;
6923 font->numeric[XLFD_RESX] = resx;
6924 }
6925
6926 return build_font_name (font);
6927}
6928
6929
6930/* Value is non-zero if we are allowed to use scalable font FONT. We
6931 can't run a Lisp function here since this function may be called
6932 with input blocked. */
6933
6934static int
702a1e8e 6935may_use_scalable_font_p (font)
53c208f6 6936 const char *font;
82641697
GM
6937{
6938 if (EQ (Vscalable_fonts_allowed, Qt))
6939 return 1;
6940 else if (CONSP (Vscalable_fonts_allowed))
6941 {
6942 Lisp_Object tail, regexp;
178c5d9c 6943
82641697
GM
6944 for (tail = Vscalable_fonts_allowed; CONSP (tail); tail = XCDR (tail))
6945 {
6946 regexp = XCAR (tail);
6947 if (STRINGP (regexp)
702a1e8e 6948 && fast_c_string_match_ignore_case (regexp, font) >= 0)
82641697
GM
6949 return 1;
6950 }
6951 }
178c5d9c 6952
82641697
GM
6953 return 0;
6954}
6955
82641697
GM
6956
6957
2e6621ca
GM
6958/* Return the name of the best matching font for face attributes ATTRS
6959 in the array of font_name structures FONTS which contains NFONTS
6960 elements. WIDTH_RATIO is a factor with which to multiply average
6961 widths if ATTRS specifies such a width.
6962
6963 Value is a font name which is allocated from the heap. FONTS is
6ae2cd57
MB
6964 freed by this function.
6965
6966 If NEEDS_OVERSTRIKE is non-zero, a boolean is returned in it to
6967 indicate whether the resulting font should be drawn using overstrike
6968 to simulate bold-face. */
82641697
GM
6969
6970static char *
6ae2cd57 6971best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
82641697
GM
6972 struct frame *f;
6973 Lisp_Object *attrs;
6974 struct font_name *fonts;
6975 int nfonts;
2e6621ca 6976 int width_ratio;
6ae2cd57 6977 int *needs_overstrike;
82641697
GM
6978{
6979 char *font_name;
6980 struct font_name *best;
334a2e2a 6981 int i, pt = 0;
a08332c0
GM
6982 int specified[5];
6983 int exact_p, avgwidth;
82641697
GM
6984
6985 if (nfonts == 0)
6986 return NULL;
6987
6988 /* Make specified font attributes available in `specified',
6989 indexed by sort order. */
6990 for (i = 0; i < DIM (font_sort_order); ++i)
6991 {
6992 int xlfd_idx = font_sort_order[i];
178c5d9c 6993
82641697
GM
6994 if (xlfd_idx == XLFD_SWIDTH)
6995 specified[i] = face_numeric_swidth (attrs[LFACE_SWIDTH_INDEX]);
6996 else if (xlfd_idx == XLFD_POINT_SIZE)
6997 specified[i] = pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
6998 else if (xlfd_idx == XLFD_WEIGHT)
6999 specified[i] = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
7000 else if (xlfd_idx == XLFD_SLANT)
7001 specified[i] = face_numeric_slant (attrs[LFACE_SLANT_INDEX]);
7002 else
7003 abort ();
7004 }
7005
a08332c0
GM
7006 avgwidth = (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
7007 ? 0
2e6621ca 7008 : XFASTINT (attrs[LFACE_AVGWIDTH_INDEX]) * width_ratio);
a08332c0 7009
82641697 7010 exact_p = 0;
178c5d9c 7011
6ae2cd57
MB
7012 if (needs_overstrike)
7013 *needs_overstrike = 0;
7014
82641697
GM
7015 /* Start with the first non-scalable font in the list. */
7016 for (i = 0; i < nfonts; ++i)
7017 if (!font_scalable_p (fonts + i))
7018 break;
7019
7020 /* Find the best match among the non-scalable fonts. */
7021 if (i < nfonts)
7022 {
7023 best = fonts + i;
178c5d9c 7024
82641697
GM
7025 for (i = 1; i < nfonts; ++i)
7026 if (!font_scalable_p (fonts + i)
a08332c0 7027 && better_font_p (specified, fonts + i, best, 1, avgwidth))
82641697
GM
7028 {
7029 best = fonts + i;
7030
a08332c0 7031 exact_p = exact_face_match_p (specified, best, avgwidth);
82641697
GM
7032 if (exact_p)
7033 break;
7034 }
82641697
GM
7035 }
7036 else
7037 best = NULL;
7038
7039 /* Unless we found an exact match among non-scalable fonts, see if
7040 we can find a better match among scalable fonts. */
7041 if (!exact_p)
7042 {
7043 /* A scalable font is better if
7044
7045 1. its weight, slant, swidth attributes are better, or.
178c5d9c 7046
82641697
GM
7047 2. the best non-scalable font doesn't have the required
7048 point size, and the scalable fonts weight, slant, swidth
7049 isn't worse. */
7050
7051 int non_scalable_has_exact_height_p;
7052
7053 if (best && best->numeric[XLFD_POINT_SIZE] == pt)
7054 non_scalable_has_exact_height_p = 1;
7055 else
7056 non_scalable_has_exact_height_p = 0;
178c5d9c 7057
82641697
GM
7058 for (i = 0; i < nfonts; ++i)
7059 if (font_scalable_p (fonts + i))
7060 {
7061 if (best == NULL
a08332c0 7062 || better_font_p (specified, fonts + i, best, 0, 0)
82641697 7063 || (!non_scalable_has_exact_height_p
a08332c0 7064 && !better_font_p (specified, best, fonts + i, 0, 0)))
6b61353c
KH
7065 {
7066 non_scalable_has_exact_height_p = 1;
7067 best = fonts + i;
7068 }
82641697 7069 }
6ae2cd57
MB
7070
7071 if (needs_overstrike)
7072 {
7073 enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
7074 enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
7075
7076 if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
7077 {
7078 /* We want a bold font, but didn't get one; try to use
7079 overstriking instead to simulate bold-face. However,
7080 don't overstrike an already-bold fontn unless the
7081 desired weight grossly exceeds the available weight. */
7082 if (got_weight > XLFD_WEIGHT_MEDIUM)
7083 *needs_overstrike = (got_weight - want_weight) > 2;
7084 else
7085 *needs_overstrike = 1;
7086 }
7087 }
82641697
GM
7088 }
7089
7090 if (font_scalable_p (best))
7091 font_name = build_scalable_font_name (f, best, pt);
7092 else
7093 font_name = build_font_name (best);
178c5d9c 7094
82641697
GM
7095 /* Free font_name structures. */
7096 free_font_names (fonts, nfonts);
178c5d9c 7097
82641697
GM
7098 return font_name;
7099}
7100
7101
3cf80731
SM
7102/* Get a list of matching fonts on frame F, considering FAMILY
7103 and alternative font families from Vface_alternative_font_registry_alist.
4a529c42
GM
7104
7105 FAMILY is the font family whose alternatives are considered.
7106
7107 REGISTRY, if a string, specifies a font registry and encoding to
7108 match. A value of nil means include fonts of any registry and
7109 encoding.
177c0ea7 7110
4a529c42
GM
7111 Return in *FONTS a pointer to a vector of font_name structures for
7112 the fonts matched. Value is the number of fonts found. */
7113
7114static int
7115try_alternative_families (f, family, registry, fonts)
7116 struct frame *f;
7117 Lisp_Object family, registry;
7118 struct font_name **fonts;
7119{
7120 Lisp_Object alter;
7121 int nfonts = 0;
7122
3cf80731
SM
7123 nfonts = font_list (f, Qnil, family, registry, fonts);
7124 if (nfonts == 0)
4a529c42 7125 {
3cf80731
SM
7126 /* Try alternative font families. */
7127 alter = Fassoc (family, Vface_alternative_font_family_alist);
7128 if (CONSP (alter))
7129 {
7130 for (alter = XCDR (alter);
7131 CONSP (alter) && nfonts == 0;
7132 alter = XCDR (alter))
7133 {
7134 if (STRINGP (XCAR (alter)))
7135 nfonts = font_list (f, Qnil, XCAR (alter), registry, fonts);
7136 }
7137 }
177c0ea7 7138
f9a45bb3
KH
7139 /* Try all scalable fonts before giving up. */
7140 if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
4a529c42 7141 {
331379bf 7142 int count = SPECPDL_INDEX ();
3cf80731
SM
7143 specbind (Qscalable_fonts_allowed, Qt);
7144 nfonts = try_alternative_families (f, family, registry, fonts);
7145 unbind_to (count, Qnil);
4a529c42
GM
7146 }
7147 }
4a529c42
GM
7148 return nfonts;
7149}
7150
7151
702a1e8e
GM
7152/* Get a list of matching fonts on frame F.
7153
af53b43c
KH
7154 PATTERN, if a string, specifies a font name pattern to match while
7155 ignoring FAMILY and REGISTRY.
702a1e8e 7156
af53b43c 7157 FAMILY, if a list, specifies a list of font families to try.
177c0ea7 7158
af53b43c
KH
7159 REGISTRY, if a list, specifies a list of font registries and
7160 encodinging to try.
54580ab2 7161
702a1e8e
GM
7162 Return in *FONTS a pointer to a vector of font_name structures for
7163 the fonts matched. Value is the number of fonts found. */
82641697
GM
7164
7165static int
af53b43c 7166try_font_list (f, pattern, family, registry, fonts)
82641697 7167 struct frame *f;
a55a1dc6 7168 Lisp_Object pattern, family, registry;
82641697
GM
7169 struct font_name **fonts;
7170{
4a529c42 7171 int nfonts = 0;
3cf80731 7172
af53b43c 7173 if (STRINGP (pattern))
bb229eec
KH
7174 {
7175 nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
7176 if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
7177 {
7178 int count = SPECPDL_INDEX ();
7179 specbind (Qscalable_fonts_allowed, Qt);
7180 nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
7181 unbind_to (count, Qnil);
7182 }
7183 }
af53b43c 7184 else
82641697 7185 {
af53b43c 7186 Lisp_Object tail;
f00691a3 7187
af53b43c
KH
7188 if (NILP (family))
7189 nfonts = font_list (f, Qnil, Qnil, registry, fonts);
3cf80731 7190 else
af53b43c
KH
7191 for (tail = family; ! nfonts && CONSP (tail); tail = XCDR (tail))
7192 nfonts = try_alternative_families (f, XCAR (tail), registry, fonts);
54580ab2 7193
af53b43c
KH
7194 /* Try font family of the default face or "fixed". */
7195 if (nfonts == 0 && !NILP (family))
7196 {
7197 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
7198 if (default_face)
7199 family = default_face->lface[LFACE_FAMILY_INDEX];
7200 else
7201 family = build_string ("fixed");
8f924df7 7202 nfonts = try_alternative_families (f, family, registry, fonts);
af53b43c 7203 }
178c5d9c 7204
af53b43c
KH
7205 /* Try any family with the given registry. */
7206 if (nfonts == 0 && !NILP (family))
8f924df7 7207 nfonts = try_alternative_families (f, Qnil, registry, fonts);
82641697 7208 }
177c0ea7 7209
82641697
GM
7210 return nfonts;
7211}
7212
82641697 7213
39506348
KH
7214/* Return the fontset id of the base fontset name or alias name given
7215 by the fontset attribute of ATTRS. Value is -1 if the fontset
7216 attribute of ATTRS doesn't name a fontset. */
82641697
GM
7217
7218static int
39506348 7219face_fontset (attrs)
82641697
GM
7220 Lisp_Object *attrs;
7221{
39506348 7222 Lisp_Object name;
178c5d9c 7223
763bc839 7224 name = attrs[LFACE_FONTSET_INDEX];
39506348
KH
7225 if (!STRINGP (name))
7226 return -1;
7227 return fs_query_fontset (name, 0);
82641697
GM
7228}
7229
7230
af53b43c 7231/* Choose a name of font to use on frame F to display characters with
39506348 7232 Lisp face attributes specified by ATTRS. The font name is
af53b43c
KH
7233 determined by the font-related attributes in ATTRS and FONT-SPEC
7234 (if specified).
6ae2cd57 7235
af53b43c
KH
7236 When we are choosing a font for ASCII characters, FONT-SPEC is
7237 always nil. Otherwise FONT-SPEC is a list
7238 [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
7239 or a string specifying a font name pattern.
82641697 7240
8f924df7
KH
7241 If NEEDS_OVERSTRIKE is not NULL, a boolean is returned in it to
7242 indicate whether the resulting font should be drawn using
7243 overstrike to simulate bold-face.
7244
af53b43c
KH
7245 Value is the font name which is allocated from the heap and must be
7246 freed by the caller. */
7247
7248char *
8f924df7 7249choose_face_font (f, attrs, font_spec, needs_overstrike)
82641697
GM
7250 struct frame *f;
7251 Lisp_Object *attrs;
af53b43c 7252 Lisp_Object font_spec;
6ae2cd57 7253 int *needs_overstrike;
82641697 7254{
af53b43c 7255 Lisp_Object pattern, family, adstyle, registry;
82641697 7256 char *font_name = NULL;
82641697 7257 struct font_name *fonts;
af53b43c 7258 int nfonts;
178c5d9c 7259
774666fb
MB
7260 if (needs_overstrike)
7261 *needs_overstrike = 0;
7262
af53b43c
KH
7263 /* If we are choosing an ASCII font and a font name is explicitly
7264 specified in ATTRS, return it. */
af53b43c 7265 if (NILP (font_spec) && STRINGP (attrs[LFACE_FONT_INDEX]))
8f924df7 7266 return xstrdup (SDATA (attrs[LFACE_FONT_INDEX]));
81b39386 7267
af53b43c 7268 if (NILP (attrs[LFACE_FAMILY_INDEX]))
81b39386 7269 family = Qnil;
af53b43c
KH
7270 else
7271 family = Fcons (attrs[LFACE_FAMILY_INDEX], Qnil);
7272
154c2d39
KH
7273 /* Decide FAMILY, ADSTYLE, and REGISTRY from FONT_SPEC. But,
7274 ADSTYLE is not used in the font selector for the moment. */
af53b43c 7275 if (VECTORP (font_spec))
39506348 7276 {
af53b43c
KH
7277 pattern = Qnil;
7278 if (STRINGP (AREF (font_spec, FONT_SPEC_FAMILY_INDEX)))
7279 family = Fcons (AREF (font_spec, FONT_SPEC_FAMILY_INDEX), family);
7280 adstyle = AREF (font_spec, FONT_SPEC_ADSTYLE_INDEX);
154c2d39 7281 registry = Fcons (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX), Qnil);
af53b43c
KH
7282 }
7283 else if (STRINGP (font_spec))
7284 {
7285 pattern = font_spec;
7286 family = Qnil;
7287 adstyle = Qnil;
7288 registry = Qnil;
7289 }
7290 else
7291 {
154c2d39
KH
7292 /* We are choosing an ASCII font. By default, use the registry
7293 name "iso8859-1". But, if the registry name of the ASCII
7294 font specified in the fontset of ATTRS is not "iso8859-1"
7295 (e.g "iso10646-1"), use also that name with higher
7296 priority. */
7297 int fontset = face_fontset (attrs);
7298 Lisp_Object ascii;
7299 int len;
7300 struct font_name font;
7301
af53b43c
KH
7302 pattern = Qnil;
7303 adstyle = Qnil;
154c2d39
KH
7304 registry = Fcons (build_string ("iso8859-1"), Qnil);
7305
7306 ascii = fontset_ascii (fontset);
8f924df7 7307 len = SBYTES (ascii);
154c2d39 7308 if (len < 9
8f924df7 7309 || strcmp (SDATA (ascii) + len - 9, "iso8859-1"))
154c2d39
KH
7310 {
7311 font.name = LSTRDUPA (ascii);
7312 /* Check if the name is in XLFD. */
7313 if (split_font_name (f, &font, 0))
7314 {
7315 font.fields[XLFD_ENCODING][-1] = '-';
7316 registry = Fcons (build_string (font.fields[XLFD_REGISTRY]),
7317 registry);
7318 }
7319 }
39506348 7320 }
82641697 7321
178c5d9c 7322 /* Get a list of fonts matching that pattern and choose the
82641697 7323 best match for the specified face attributes from it. */
af53b43c 7324 nfonts = try_font_list (f, pattern, family, registry, &fonts);
8f924df7 7325 font_name = best_matching_font (f, attrs, fonts, nfonts, NILP (font_spec),
6ae2cd57 7326 needs_overstrike);
82641697
GM
7327 return font_name;
7328}
7329
c3cee013 7330#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
7331
7332
7333\f
7334/***********************************************************************
7335 Face Realization
7336 ***********************************************************************/
7337
7338/* Realize basic faces on frame F. Value is zero if frame parameters
7339 of F don't contain enough information needed to realize the default
7340 face. */
7341
7342static int
7343realize_basic_faces (f)
7344 struct frame *f;
7345{
7346 int success_p = 0;
331379bf 7347 int count = SPECPDL_INDEX ();
17e8204b 7348
04386463
GM
7349 /* Block input here so that we won't be surprised by an X expose
7350 event, for instance, without having the faces set up. */
17e8204b 7351 BLOCK_INPUT;
eeffb293 7352 specbind (Qscalable_fonts_allowed, Qt);
178c5d9c 7353
82641697
GM
7354 if (realize_default_face (f))
7355 {
92610620 7356 realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
039b6394 7357 realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
9ea173e8 7358 realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
4e50fa8b 7359 realize_named_face (f, Qfringe, FRINGE_FACE_ID);
045dee35 7360 realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
8bd201d6
GM
7361 realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
7362 realize_named_face (f, Qborder, BORDER_FACE_ID);
7363 realize_named_face (f, Qcursor, CURSOR_FACE_ID);
7364 realize_named_face (f, Qmouse, MOUSE_FACE_ID);
c7ae3284 7365 realize_named_face (f, Qmenu, MENU_FACE_ID);
53abc3bf 7366 realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
563f68f1 7367
b5de343d 7368 /* Reflect changes in the `menu' face in menu bars. */
ceeda019 7369 if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
563f68f1 7370 {
ceeda019 7371 FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
563f68f1 7372#ifdef USE_X_TOOLKIT
bce72079 7373 x_update_menu_appearance (f);
a03ad468 7374#endif
563f68f1 7375 }
177c0ea7 7376
82641697
GM
7377 success_p = 1;
7378 }
7379
eeffb293 7380 unbind_to (count, Qnil);
17e8204b 7381 UNBLOCK_INPUT;
82641697
GM
7382 return success_p;
7383}
7384
7385
7386/* Realize the default face on frame F. If the face is not fully
7387 specified, make it fully-specified. Attributes of the default face
7388 that are not explicitly specified are taken from frame parameters. */
7389
7390static int
7391realize_default_face (f)
7392 struct frame *f;
7393{
7394 struct face_cache *c = FRAME_FACE_CACHE (f);
7395 Lisp_Object lface;
7396 Lisp_Object attrs[LFACE_VECTOR_SIZE];
82641697
GM
7397 Lisp_Object frame_font;
7398 struct face *face;
82641697
GM
7399
7400 /* If the `default' face is not yet known, create it. */
7401 lface = lface_from_face_name (f, Qdefault, 0);
7402 if (NILP (lface))
07446869
GM
7403 {
7404 Lisp_Object frame;
7405 XSETFRAME (frame, f);
7406 lface = Finternal_make_lisp_face (Qdefault, frame);
7407 }
7408
82641697 7409
c3cee013
JR
7410#ifdef HAVE_WINDOW_SYSTEM
7411 if (FRAME_WINDOW_P (f))
82641697
GM
7412 {
7413 /* Set frame_font to the value of the `font' frame parameter. */
7414 frame_font = Fassq (Qfont, f->param_alist);
7415 xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
7416 frame_font = XCDR (frame_font);
a5f696ac
JD
7417 set_lface_from_font_name (f, lface, frame_font,
7418 f->default_face_done_p, 1);
7419 f->default_face_done_p = 1;
82641697 7420 }
c3cee013 7421#endif /* HAVE_WINDOW_SYSTEM */
82641697 7422
44747bd0 7423 if (!FRAME_WINDOW_P (f))
82641697
GM
7424 {
7425 LFACE_FAMILY (lface) = build_string ("default");
7426 LFACE_SWIDTH (lface) = Qnormal;
7427 LFACE_HEIGHT (lface) = make_number (1);
c1e7532d
EZ
7428 if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
7429 LFACE_WEIGHT (lface) = Qnormal;
7430 if (UNSPECIFIEDP (LFACE_SLANT (lface)))
7431 LFACE_SLANT (lface) = Qnormal;
a08332c0 7432 LFACE_AVGWIDTH (lface) = Qunspecified;
82641697 7433 }
178c5d9c 7434
82641697
GM
7435 if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
7436 LFACE_UNDERLINE (lface) = Qnil;
178c5d9c 7437
82641697
GM
7438 if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
7439 LFACE_OVERLINE (lface) = Qnil;
178c5d9c 7440
82641697
GM
7441 if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
7442 LFACE_STRIKE_THROUGH (lface) = Qnil;
178c5d9c 7443
82641697
GM
7444 if (UNSPECIFIEDP (LFACE_BOX (lface)))
7445 LFACE_BOX (lface) = Qnil;
178c5d9c 7446
82641697
GM
7447 if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
7448 LFACE_INVERSE (lface) = Qnil;
178c5d9c 7449
82641697
GM
7450 if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
7451 {
7452 /* This function is called so early that colors are not yet
7453 set in the frame parameter list. */
7454 Lisp_Object color = Fassq (Qforeground_color, f->param_alist);
178c5d9c 7455
82641697
GM
7456 if (CONSP (color) && STRINGP (XCDR (color)))
7457 LFACE_FOREGROUND (lface) = XCDR (color);
c3cee013 7458 else if (FRAME_WINDOW_P (f))
82641697 7459 return 0;
e689ec06 7460 else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ef917393 7461 LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
f9d2fdc4 7462 else
82641697
GM
7463 abort ();
7464 }
178c5d9c 7465
82641697
GM
7466 if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
7467 {
7468 /* This function is called so early that colors are not yet
7469 set in the frame parameter list. */
7470 Lisp_Object color = Fassq (Qbackground_color, f->param_alist);
7471 if (CONSP (color) && STRINGP (XCDR (color)))
7472 LFACE_BACKGROUND (lface) = XCDR (color);
c3cee013 7473 else if (FRAME_WINDOW_P (f))
82641697 7474 return 0;
e689ec06 7475 else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ef917393 7476 LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
f9d2fdc4 7477 else
82641697
GM
7478 abort ();
7479 }
178c5d9c 7480
82641697
GM
7481 if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
7482 LFACE_STIPPLE (lface) = Qnil;
7483
7484 /* Realize the face; it must be fully-specified now. */
7485 xassert (lface_fully_specified_p (XVECTOR (lface)->contents));
7486 check_lface (lface);
7487 bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
af53b43c 7488 face = realize_face (c, attrs, DEFAULT_FACE_ID);
4da9c136
KH
7489
7490#ifdef HAVE_WINDOW_SYSTEM
7491#ifdef HAVE_X_WINDOWS
7492 if (face->font != FRAME_FONT (f))
7493 /* As the font specified for the frame was not acceptable as a
7494 font for the default face (perhaps because auto-scaled fonts
7495 are rejected), we must adjust the frame font. */
7496 x_set_font (f, build_string (face->font_name), Qnil);
7497#endif /* HAVE_X_WINDOWS */
7498#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
7499 return 1;
7500}
7501
7502
7503/* Realize basic faces other than the default face in face cache C.
7504 SYMBOL is the face name, ID is the face id the realized face must
7505 have. The default face must have been realized already. */
7506
7507static void
7508realize_named_face (f, symbol, id)
7509 struct frame *f;
7510 Lisp_Object symbol;
7511 int id;
7512{
7513 struct face_cache *c = FRAME_FACE_CACHE (f);
7514 Lisp_Object lface = lface_from_face_name (f, symbol, 0);
7515 Lisp_Object attrs[LFACE_VECTOR_SIZE];
7516 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
7517 struct face *new_face;
7518
7519 /* The default face must exist and be fully specified. */
7520 get_lface_attributes (f, Qdefault, attrs, 1);
7521 check_lface_attrs (attrs);
7522 xassert (lface_fully_specified_p (attrs));
7523
7524 /* If SYMBOL isn't know as a face, create it. */
7525 if (NILP (lface))
7526 {
7527 Lisp_Object frame;
7528 XSETFRAME (frame, f);
7529 lface = Finternal_make_lisp_face (symbol, frame);
7530 }
7531
7532 /* Merge SYMBOL's face with the default face. */
7533 get_lface_attributes (f, symbol, symbol_attrs, 1);
a0a23346 7534 merge_face_vectors (f, symbol_attrs, attrs, 0);
82641697
GM
7535
7536 /* Realize the face. */
af53b43c 7537 new_face = realize_face (c, attrs, id);
82641697
GM
7538}
7539
7540
7541/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
7542 cache CACHE for ASCII characters. If FORMER_FACE_ID is
7543 non-negative, it is an ID of face to remove before caching the new
7544 face. Value is a pointer to the newly created realized face. */
82641697
GM
7545
7546static struct face *
af53b43c 7547realize_face (cache, attrs, former_face_id)
39506348 7548 struct face_cache *cache;
82641697 7549 Lisp_Object *attrs;
39506348 7550 int former_face_id;
82641697
GM
7551{
7552 struct face *face;
178c5d9c 7553
82641697 7554 /* LFACE must be fully specified. */
39506348 7555 xassert (cache != NULL);
82641697
GM
7556 check_lface_attrs (attrs);
7557
39506348
KH
7558 if (former_face_id >= 0 && cache->used > former_face_id)
7559 {
7560 /* Remove the former face. */
7561 struct face *former_face = cache->faces_by_id[former_face_id];
7562 uncache_face (cache, former_face);
7563 free_realized_face (cache->f, former_face);
7564 }
7565
7566 if (FRAME_WINDOW_P (cache->f))
af53b43c 7567 face = realize_x_face (cache, attrs);
e689ec06 7568 else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
af53b43c 7569 face = realize_tty_face (cache, attrs);
82641697
GM
7570 else
7571 abort ();
7572
39506348
KH
7573 /* Insert the new face. */
7574 cache_face (cache, face, lface_hash (attrs));
af53b43c
KH
7575 return face;
7576}
7577
7578
8c6204de 7579#ifdef HAVE_WINDOW_SYSTEM
af53b43c
KH
7580/* Realize the fully-specified face that has the same attributes as
7581 BASE_FACE except for the font on frame F. If FONT_ID is not
7582 negative, it is an ID number of an already opened font that should
7583 be used by the face. If FONT_ID is negative, the face has no font,
7584 i.e., characters are displayed by empty boxes. */
7585
7586static struct face *
7587realize_non_ascii_face (f, font_id, base_face)
7588 struct frame *f;
7589 int font_id;
7590 struct face *base_face;
7591{
7592 struct face_cache *cache = FRAME_FACE_CACHE (f);
8f924df7 7593 struct face *face;
af53b43c
KH
7594 struct font_info *font_info;
7595
7596 face = (struct face *) xmalloc (sizeof *face);
7597 *face = *base_face;
7598 face->gc = 0;
7599
7600 /* Don't try to free the colors copied bitwise from BASE_FACE. */
7601 face->colors_copied_bitwise_p = 1;
7602
7603 face->font_info_id = font_id;
7604 if (font_id >= 0)
7605 {
7606 font_info = FONT_INFO_FROM_ID (f, font_id);
7607 face->font = font_info->font;
7608 face->font_name = font_info->full_name;
7609 }
7610 else
7611 {
7612 face->font = NULL;
7613 face->font_name = NULL;
7614 }
7615
7616 face->gc = 0;
7617
7618 cache_face (cache, face, face->hash);
7619
82641697
GM
7620 return face;
7621}
8c6204de 7622#endif /* HAVE_WINDOW_SYSTEM */
82641697
GM
7623
7624
7625/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
7626 cache CACHE for ASCII characters. Do it for X frame CACHE->f. If
7627 the new face doesn't share font with the default face, a fontname
7628 is allocated from the heap and set in `font_name' of the new face,
7629 but it is not yet loaded here. Value is a pointer to the newly
7630 created realized face. */
82641697
GM
7631
7632static struct face *
af53b43c 7633realize_x_face (cache, attrs)
39506348 7634 struct face_cache *cache;
82641697 7635 Lisp_Object *attrs;
82641697 7636{
7d603e3f 7637 struct face *face = NULL;
c3cee013 7638#ifdef HAVE_WINDOW_SYSTEM
7d603e3f 7639 struct face *default_face;
78d2079c 7640 struct frame *f;
82641697 7641 Lisp_Object stipple, overline, strike_through, box;
82641697 7642
39506348 7643 xassert (FRAME_WINDOW_P (cache->f));
82641697
GM
7644
7645 /* Allocate a new realized face. */
39506348 7646 face = make_realized_face (attrs);
af53b43c 7647 face->ascii_face = face;
39506348
KH
7648
7649 f = cache->f;
7650
82641697
GM
7651 /* Determine the font to use. Most of the time, the font will be
7652 the same as the font of the default face, so try that first. */
7653 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
7654 if (default_face
82641697
GM
7655 && lface_same_font_attributes_p (default_face->lface, attrs))
7656 {
7657 face->font = default_face->font;
82641697 7658 face->font_info_id = default_face->font_info_id;
426b2119
KH
7659#ifdef USE_FONT_BACKEND
7660 face->font_info = default_face->font_info;
7661#endif /* USE_FONT_BACKEND */
82641697 7662 face->font_name = default_face->font_name;
39506348 7663 face->fontset
af53b43c 7664 = make_fontset_for_ascii_face (f, default_face->fontset, face);
82641697
GM
7665 }
7666 else
7667 {
39506348 7668 /* If the face attribute ATTRS specifies a fontset, use it as
fc8c4797
KH
7669 the base of a new realized fontset. Otherwise, use the same
7670 base fontset as of the default face. The base determines
7671 registry and encoding of a font. It may also determine
7672 foundry and family. The other fields of font name pattern
7673 are constructed from ATTRS. */
7674 int fontset = face_fontset (attrs);
7675
af53b43c
KH
7676 /* If we are realizing the default face, ATTRS should specify a
7677 fontset. In other words, if FONTSET is -1, we are not
7678 realizing the default face, thus the default face should have
7679 already been realized. */
7680 if (fontset == -1)
fc8c4797 7681 fontset = default_face->fontset;
af53b43c
KH
7682 if (fontset == -1)
7683 abort ();
426b2119
KH
7684#ifdef USE_FONT_BACKEND
7685 if (enable_font_backend)
7686 font_load_for_face (f, face);
7687 else
7688#endif /* USE_FONT_BACKEND */
8f924df7 7689 load_face_font (f, face);
426b2119
KH
7690 if (face->font)
7691 face->fontset = make_fontset_for_ascii_face (f, fontset, face);
7692 else
7693 face->fontset = -1;
82641697
GM
7694 }
7695
7696 /* Load colors, and set remaining attributes. */
178c5d9c 7697
82641697 7698 load_face_colors (f, face, attrs);
660ed669 7699
82641697
GM
7700 /* Set up box. */
7701 box = attrs[LFACE_BOX_INDEX];
7702 if (STRINGP (box))
cb637678 7703 {
82641697
GM
7704 /* A simple box of line width 1 drawn in color given by
7705 the string. */
7706 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
7707 LFACE_BOX_INDEX);
7708 face->box = FACE_SIMPLE_BOX;
7709 face->box_line_width = 1;
cb637678 7710 }
82641697 7711 else if (INTEGERP (box))
42120bc7 7712 {
82641697
GM
7713 /* Simple box of specified line width in foreground color of the
7714 face. */
89624b8b 7715 xassert (XINT (box) != 0);
82641697 7716 face->box = FACE_SIMPLE_BOX;
89624b8b 7717 face->box_line_width = XINT (box);
82641697
GM
7718 face->box_color = face->foreground;
7719 face->box_color_defaulted_p = 1;
7720 }
7721 else if (CONSP (box))
7722 {
7723 /* `(:width WIDTH :color COLOR :shadow SHADOW)'. SHADOW
7724 being one of `raised' or `sunken'. */
7725 face->box = FACE_SIMPLE_BOX;
7726 face->box_color = face->foreground;
7727 face->box_color_defaulted_p = 1;
7728 face->box_line_width = 1;
7729
7730 while (CONSP (box))
42120bc7 7731 {
82641697
GM
7732 Lisp_Object keyword, value;
7733
7734 keyword = XCAR (box);
7735 box = XCDR (box);
7736
7737 if (!CONSP (box))
7738 break;
7739 value = XCAR (box);
7740 box = XCDR (box);
7741
7742 if (EQ (keyword, QCline_width))
7743 {
89624b8b
KH
7744 if (INTEGERP (value) && XINT (value) != 0)
7745 face->box_line_width = XINT (value);
82641697
GM
7746 }
7747 else if (EQ (keyword, QCcolor))
7748 {
7749 if (STRINGP (value))
7750 {
7751 face->box_color = load_color (f, face, value,
7752 LFACE_BOX_INDEX);
7753 face->use_box_color_for_shadows_p = 1;
7754 }
7755 }
7756 else if (EQ (keyword, QCstyle))
a8517066 7757 {
82641697
GM
7758 if (EQ (value, Qreleased_button))
7759 face->box = FACE_RAISED_BOX;
7760 else if (EQ (value, Qpressed_button))
7761 face->box = FACE_SUNKEN_BOX;
a8517066 7762 }
42120bc7
RS
7763 }
7764 }
195f798e 7765
82641697 7766 /* Text underline, overline, strike-through. */
178c5d9c 7767
82641697 7768 if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt))
178c5d9c 7769 {
82641697
GM
7770 /* Use default color (same as foreground color). */
7771 face->underline_p = 1;
7772 face->underline_defaulted_p = 1;
7773 face->underline_color = 0;
7774 }
7775 else if (STRINGP (attrs[LFACE_UNDERLINE_INDEX]))
195f798e 7776 {
82641697
GM
7777 /* Use specified color. */
7778 face->underline_p = 1;
7779 face->underline_defaulted_p = 0;
7780 face->underline_color
7781 = load_color (f, face, attrs[LFACE_UNDERLINE_INDEX],
7782 LFACE_UNDERLINE_INDEX);
195f798e 7783 }
82641697 7784 else if (NILP (attrs[LFACE_UNDERLINE_INDEX]))
7b00de84 7785 {
82641697
GM
7786 face->underline_p = 0;
7787 face->underline_defaulted_p = 0;
7788 face->underline_color = 0;
7b00de84
JB
7789 }
7790
82641697
GM
7791 overline = attrs[LFACE_OVERLINE_INDEX];
7792 if (STRINGP (overline))
cb637678 7793 {
82641697
GM
7794 face->overline_color
7795 = load_color (f, face, attrs[LFACE_OVERLINE_INDEX],
7796 LFACE_OVERLINE_INDEX);
7797 face->overline_p = 1;
cb637678 7798 }
82641697 7799 else if (EQ (overline, Qt))
cb637678 7800 {
82641697
GM
7801 face->overline_color = face->foreground;
7802 face->overline_color_defaulted_p = 1;
7803 face->overline_p = 1;
cb637678
JB
7804 }
7805
82641697
GM
7806 strike_through = attrs[LFACE_STRIKE_THROUGH_INDEX];
7807 if (STRINGP (strike_through))
7808 {
7809 face->strike_through_color
7810 = load_color (f, face, attrs[LFACE_STRIKE_THROUGH_INDEX],
7811 LFACE_STRIKE_THROUGH_INDEX);
7812 face->strike_through_p = 1;
7813 }
7814 else if (EQ (strike_through, Qt))
7815 {
7816 face->strike_through_color = face->foreground;
7817 face->strike_through_color_defaulted_p = 1;
7818 face->strike_through_p = 1;
7819 }
867dd159 7820
82641697
GM
7821 stipple = attrs[LFACE_STIPPLE_INDEX];
7822 if (!NILP (stipple))
7823 face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
c3cee013 7824#endif /* HAVE_WINDOW_SYSTEM */
660ed669 7825
82641697 7826 return face;
660ed669
JB
7827}
7828
729425b1 7829
ae4b4ba5
GM
7830/* Map a specified color of face FACE on frame F to a tty color index.
7831 IDX is either LFACE_FOREGROUND_INDEX or LFACE_BACKGROUND_INDEX, and
7832 specifies which color to map. Set *DEFAULTED to 1 if mapping to the
7833 default foreground/background colors. */
7834
7835static void
7836map_tty_color (f, face, idx, defaulted)
7837 struct frame *f;
7838 struct face *face;
7839 enum lface_attribute_index idx;
7840 int *defaulted;
7841{
7842 Lisp_Object frame, color, def;
7843 int foreground_p = idx == LFACE_FOREGROUND_INDEX;
7844 unsigned long default_pixel, default_other_pixel, pixel;
7845
7846 xassert (idx == LFACE_FOREGROUND_INDEX || idx == LFACE_BACKGROUND_INDEX);
7847
7848 if (foreground_p)
7849 {
7850 pixel = default_pixel = FACE_TTY_DEFAULT_FG_COLOR;
7851 default_other_pixel = FACE_TTY_DEFAULT_BG_COLOR;
7852 }
7853 else
7854 {
7855 pixel = default_pixel = FACE_TTY_DEFAULT_BG_COLOR;
7856 default_other_pixel = FACE_TTY_DEFAULT_FG_COLOR;
7857 }
177c0ea7 7858
ae4b4ba5
GM
7859 XSETFRAME (frame, f);
7860 color = face->lface[idx];
177c0ea7 7861
ae4b4ba5 7862 if (STRINGP (color)
d5db4077 7863 && SCHARS (color)
ae4b4ba5
GM
7864 && CONSP (Vtty_defined_color_alist)
7865 && (def = assq_no_quit (color, call1 (Qtty_color_alist, frame)),
7866 CONSP (def)))
7867 {
7868 /* Associations in tty-defined-color-alist are of the form
7869 (NAME INDEX R G B). We need the INDEX part. */
7870 pixel = XINT (XCAR (XCDR (def)));
7871 }
7872
7873 if (pixel == default_pixel && STRINGP (color))
7874 {
7875 pixel = load_color (f, face, color, idx);
7876
7877#if defined (MSDOS) || defined (WINDOWSNT)
7878 /* If the foreground of the default face is the default color,
7879 use the foreground color defined by the frame. */
7880#ifdef MSDOS
7881 if (FRAME_MSDOS_P (f))
7882 {
7883#endif /* MSDOS */
7884 if (pixel == default_pixel
7885 || pixel == FACE_TTY_DEFAULT_COLOR)
7886 {
7887 if (foreground_p)
7888 pixel = FRAME_FOREGROUND_PIXEL (f);
7889 else
7890 pixel = FRAME_BACKGROUND_PIXEL (f);
7891 face->lface[idx] = tty_color_name (f, pixel);
7892 *defaulted = 1;
7893 }
7894 else if (pixel == default_other_pixel)
7895 {
7896 if (foreground_p)
7897 pixel = FRAME_BACKGROUND_PIXEL (f);
7898 else
7899 pixel = FRAME_FOREGROUND_PIXEL (f);
7900 face->lface[idx] = tty_color_name (f, pixel);
7901 *defaulted = 1;
7902 }
7903#ifdef MSDOS
7904 }
7905#endif
7906#endif /* MSDOS or WINDOWSNT */
7907 }
7908
7909 if (foreground_p)
7910 face->foreground = pixel;
7911 else
7912 face->background = pixel;
7913}
7914
7915
82641697 7916/* Realize the fully-specified face with attributes ATTRS in face
af53b43c
KH
7917 cache CACHE for ASCII characters. Do it for TTY frame CACHE->f.
7918 Value is a pointer to the newly created realized face. */
a8517066 7919
82641697 7920static struct face *
af53b43c 7921realize_tty_face (cache, attrs)
39506348 7922 struct face_cache *cache;
82641697 7923 Lisp_Object *attrs;
82641697
GM
7924{
7925 struct face *face;
7926 int weight, slant;
2d764c78 7927 int face_colors_defaulted = 0;
ae4b4ba5 7928 struct frame *f = cache->f;
729425b1 7929
82641697 7930 /* Frame must be a termcap frame. */
e689ec06 7931 xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
178c5d9c 7932
82641697 7933 /* Allocate a new realized face. */
39506348 7934 face = make_realized_face (attrs);
e689ec06 7935 face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
82641697 7936
178c5d9c 7937 /* Map face attributes to TTY appearances. We map slant to
82641697
GM
7938 dimmed text because we want italic text to appear differently
7939 and because dimmed text is probably used infrequently. */
7940 weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
7941 slant = face_numeric_slant (attrs[LFACE_SLANT_INDEX]);
7942
7943 if (weight > XLFD_WEIGHT_MEDIUM)
7944 face->tty_bold_p = 1;
7945 if (weight < XLFD_WEIGHT_MEDIUM || slant != XLFD_SLANT_ROMAN)
7946 face->tty_dim_p = 1;
7947 if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
7948 face->tty_underline_p = 1;
7949 if (!NILP (attrs[LFACE_INVERSE_INDEX]))
7950 face->tty_reverse_p = 1;
7951
7952 /* Map color names to color indices. */
ae4b4ba5
GM
7953 map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
7954 map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
177c0ea7 7955
2d764c78
EZ
7956 /* Swap colors if face is inverse-video. If the colors are taken
7957 from the frame colors, they are already inverted, since the
7958 frame-creation function calls x-handle-reverse-video. */
7959 if (face->tty_reverse_p && !face_colors_defaulted)
44747bd0
EZ
7960 {
7961 unsigned long tem = face->foreground;
44747bd0
EZ
7962 face->foreground = face->background;
7963 face->background = tem;
7964 }
44747bd0 7965
a4a76b61
GM
7966 if (tty_suppress_bold_inverse_default_colors_p
7967 && face->tty_bold_p
7968 && face->background == FACE_TTY_DEFAULT_FG_COLOR
7969 && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
7970 face->tty_bold_p = 0;
7971
82641697 7972 return face;
729425b1 7973}
867dd159 7974
82641697 7975
a4a76b61
GM
7976DEFUN ("tty-suppress-bold-inverse-default-colors",
7977 Ftty_suppress_bold_inverse_default_colors,
7978 Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
e3cd9e7f 7979 doc: /* Suppress/allow boldness of faces with inverse default colors.
228299fa
GM
7980SUPPRESS non-nil means suppress it.
7981This affects bold faces on TTYs whose foreground is the default background
7982color of the display and whose background is the default foreground color.
7983For such faces, the bold face attribute is ignored if this variable
7ee72033
MB
7984is non-nil. */)
7985 (suppress)
a4a76b61
GM
7986 Lisp_Object suppress;
7987{
7988 tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
7989 ++face_change_count;
7990 return suppress;
7991}
7992
7993
82641697
GM
7994\f
7995/***********************************************************************
7996 Computing Faces
7997 ***********************************************************************/
7998
7999/* Return the ID of the face to use to display character CH with face
8000 property PROP on frame F in current_buffer. */
2e16580f
RS
8001
8002int
82641697 8003compute_char_face (f, ch, prop)
2e16580f 8004 struct frame *f;
82641697
GM
8005 int ch;
8006 Lisp_Object prop;
2e16580f 8007{
82641697 8008 int face_id;
39506348
KH
8009
8010 if (NILP (current_buffer->enable_multibyte_characters))
522d42f7 8011 ch = 0;
178c5d9c 8012
82641697 8013 if (NILP (prop))
39506348
KH
8014 {
8015 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
779c6fb6 8016 face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
39506348 8017 }
82641697 8018 else
2e16580f 8019 {
82641697
GM
8020 Lisp_Object attrs[LFACE_VECTOR_SIZE];
8021 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
8022 bcopy (default_face->lface, attrs, sizeof attrs);
a0a23346 8023 merge_face_ref (f, prop, attrs, 1, 0);
af53b43c 8024 face_id = lookup_face (f, attrs);
2e16580f
RS
8025 }
8026
82641697 8027 return face_id;
2e16580f 8028}
bc0db68d 8029
82641697
GM
8030/* Return the face ID associated with buffer position POS for
8031 displaying ASCII characters. Return in *ENDPTR the position at
8032 which a different face is needed, as far as text properties and
8033 overlays are concerned. W is a window displaying current_buffer.
8034
8035 REGION_BEG, REGION_END delimit the region, so it can be
8036 highlighted.
6f134486 8037
82641697
GM
8038 LIMIT is a position not to scan beyond. That is to limit the time
8039 this function can take.
8040
8041 If MOUSE is non-zero, use the character's mouse-face, not its face.
8042
39506348 8043 The face returned is suitable for displaying ASCII characters. */
bc0db68d 8044
cb637678 8045int
82641697
GM
8046face_at_buffer_position (w, pos, region_beg, region_end,
8047 endptr, limit, mouse)
f211082d 8048 struct window *w;
7b7739b1 8049 int pos;
bc0db68d 8050 int region_beg, region_end;
7b7739b1 8051 int *endptr;
b349f4fb 8052 int limit;
6f134486 8053 int mouse;
7b7739b1 8054{
82641697
GM
8055 struct frame *f = XFRAME (w->frame);
8056 Lisp_Object attrs[LFACE_VECTOR_SIZE];
b6d40e46 8057 Lisp_Object prop, position;
82641697 8058 int i, noverlays;
7b7739b1 8059 Lisp_Object *overlay_vec;
f211082d 8060 Lisp_Object frame;
f6b98e0b 8061 int endpos;
82641697
GM
8062 Lisp_Object propname = mouse ? Qmouse_face : Qface;
8063 Lisp_Object limit1, end;
8064 struct face *default_face;
f6b98e0b
JB
8065
8066 /* W must display the current buffer. We could write this function
8067 to use the frame and buffer of W, but right now it doesn't. */
060fb5c1 8068 /* xassert (XBUFFER (w->buffer) == current_buffer); */
f211082d 8069
ac22a6c4 8070 XSETFRAME (frame, f);
82641697 8071 XSETFASTINT (position, pos);
7b7739b1 8072
f6b98e0b 8073 endpos = ZV;
bc0db68d
RS
8074 if (pos < region_beg && region_beg < endpos)
8075 endpos = region_beg;
f6b98e0b 8076
82641697
GM
8077 /* Get the `face' or `mouse_face' text property at POS, and
8078 determine the next position at which the property changes. */
6f134486 8079 prop = Fget_text_property (position, propname, w->buffer);
82641697
GM
8080 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
8081 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
8082 if (INTEGERP (end))
8083 endpos = XINT (end);
6f134486 8084
82641697 8085 /* Look at properties from overlays. */
b6d40e46 8086 {
f6b98e0b 8087 int next_overlay;
b6d40e46 8088
0bc90bba 8089 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, 0);
f6b98e0b
JB
8090 if (next_overlay < endpos)
8091 endpos = next_overlay;
b6d40e46
JB
8092 }
8093
8094 *endptr = endpos;
7b7739b1 8095
82641697 8096 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
178c5d9c 8097
82641697
GM
8098 /* Optimize common cases where we can use the default face. */
8099 if (noverlays == 0
8100 && NILP (prop)
39506348 8101 && !(pos >= region_beg && pos < region_end))
82641697
GM
8102 return DEFAULT_FACE_ID;
8103
8104 /* Begin with attributes from the default face. */
8105 bcopy (default_face->lface, attrs, sizeof attrs);
8106
8107 /* Merge in attributes specified via text properties. */
8108 if (!NILP (prop))
a0a23346 8109 merge_face_ref (f, prop, attrs, 1, 0);
82641697
GM
8110
8111 /* Now merge the overlay data. */
18195655 8112 noverlays = sort_overlays (overlay_vec, noverlays, w);
18195655 8113 for (i = 0; i < noverlays; i++)
4699e6d2 8114 {
18195655
RS
8115 Lisp_Object oend;
8116 int oendpos;
8117
8118 prop = Foverlay_get (overlay_vec[i], propname);
82641697 8119 if (!NILP (prop))
a0a23346 8120 merge_face_ref (f, prop, attrs, 1, 0);
18195655
RS
8121
8122 oend = OVERLAY_END (overlay_vec[i]);
8123 oendpos = OVERLAY_POSITION (oend);
8124 if (oendpos < endpos)
8125 endpos = oendpos;
8126 }
8127
82641697 8128 /* If in the region, merge in the region face. */
18195655
RS
8129 if (pos >= region_beg && pos < region_end)
8130 {
a0a23346 8131 merge_named_face (f, Qregion, attrs, 0);
178c5d9c 8132
18195655
RS
8133 if (region_end < endpos)
8134 endpos = region_end;
18195655
RS
8135 }
8136
8137 *endptr = endpos;
8138
82641697 8139 /* Look up a realized face with the given face attributes,
39506348 8140 or realize a new one for ASCII characters. */
af53b43c 8141 return lookup_face (f, attrs);
18195655
RS
8142}
8143
60573a90 8144
82641697 8145/* Compute the face at character position POS in Lisp string STRING on
39506348 8146 window W, for ASCII characters.
7b7739b1 8147
82641697
GM
8148 If STRING is an overlay string, it comes from position BUFPOS in
8149 current_buffer, otherwise BUFPOS is zero to indicate that STRING is
8150 not an overlay string. W must display the current buffer.
8151 REGION_BEG and REGION_END give the start and end positions of the
8714a182
GM
8152 region; both are -1 if no region is visible.
8153
8154 BASE_FACE_ID is the id of a face to merge with. For strings coming
8155 from overlays or the `display' property it is the face at BUFPOS.
178c5d9c 8156
48a4ca99
GM
8157 If MOUSE_P is non-zero, use the character's mouse-face, not its face.
8158
82641697
GM
8159 Set *ENDPTR to the next position where to check for faces in
8160 STRING; -1 if the face is constant from POS to the end of the
8161 string.
18195655 8162
82641697 8163 Value is the id of the face to use. The face returned is suitable
39506348 8164 for displaying ASCII characters. */
fffc2367 8165
82641697
GM
8166int
8167face_at_string_position (w, string, pos, bufpos, region_beg,
48a4ca99 8168 region_end, endptr, base_face_id, mouse_p)
82641697
GM
8169 struct window *w;
8170 Lisp_Object string;
8171 int pos, bufpos;
8172 int region_beg, region_end;
8173 int *endptr;
8174 enum face_id base_face_id;
48a4ca99 8175 int mouse_p;
660ed669 8176{
82641697
GM
8177 Lisp_Object prop, position, end, limit;
8178 struct frame *f = XFRAME (WINDOW_FRAME (w));
8179 Lisp_Object attrs[LFACE_VECTOR_SIZE];
8180 struct face *base_face;
8181 int multibyte_p = STRING_MULTIBYTE (string);
48a4ca99 8182 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
82641697
GM
8183
8184 /* Get the value of the face property at the current position within
8185 STRING. Value is nil if there is no face property. */
8186 XSETFASTINT (position, pos);
48a4ca99 8187 prop = Fget_text_property (position, prop_name, string);
82641697
GM
8188
8189 /* Get the next position at which to check for faces. Value of end
8190 is nil if face is constant all the way to the end of the string.
8191 Otherwise it is a string position where to check faces next.
8192 Limit is the maximum position up to which to check for property
8193 changes in Fnext_single_property_change. Strings are usually
8194 short, so set the limit to the end of the string. */
d5db4077 8195 XSETFASTINT (limit, SCHARS (string));
48a4ca99 8196 end = Fnext_single_property_change (position, prop_name, string, limit);
82641697
GM
8197 if (INTEGERP (end))
8198 *endptr = XFASTINT (end);
8199 else
8200 *endptr = -1;
8201
8202 base_face = FACE_FROM_ID (f, base_face_id);
8203 xassert (base_face);
8204
8205 /* Optimize the default case that there is no face property and we
8206 are not in the region. */
8207 if (NILP (prop)
8208 && (base_face_id != DEFAULT_FACE_ID
8209 /* BUFPOS <= 0 means STRING is not an overlay string, so
8210 that the region doesn't have to be taken into account. */
8211 || bufpos <= 0
8212 || bufpos < region_beg
8213 || bufpos >= region_end)
8214 && (multibyte_p
8215 /* We can't realize faces for different charsets differently
8216 if we don't have fonts, so we can stop here if not working
8217 on a window-system frame. */
8218 || !FRAME_WINDOW_P (f)
39506348 8219 || FACE_SUITABLE_FOR_CHAR_P (base_face, 0)))
82641697
GM
8220 return base_face->id;
8221
8222 /* Begin with attributes from the base face. */
8223 bcopy (base_face->lface, attrs, sizeof attrs);
8224
8225 /* Merge in attributes specified via text properties. */
8226 if (!NILP (prop))
a0a23346 8227 merge_face_ref (f, prop, attrs, 1, 0);
82641697
GM
8228
8229 /* If in the region, merge in the region face. */
8230 if (bufpos
8231 && bufpos >= region_beg
8232 && bufpos < region_end)
a0a23346 8233 merge_named_face (f, Qregion, attrs, 0);
660ed669 8234
82641697 8235 /* Look up a realized face with the given face attributes,
39506348 8236 or realize a new one for ASCII characters. */
af53b43c 8237 return lookup_face (f, attrs);
660ed669
JB
8238}
8239
8240
fd998c7f
KS
8241/* Merge a face into a realized face.
8242
8243 F is frame where faces are (to be) realized.
8244
dc91a0ed
KS
8245 FACE_NAME is named face to merge.
8246
8247 If FACE_NAME is nil, FACE_ID is face_id of realized face to merge.
8248
8249 If FACE_NAME is t, FACE_ID is lface_id of face to merge.
fd998c7f
KS
8250
8251 BASE_FACE_ID is realized face to merge into.
8252
dc91a0ed 8253 Return new face id.
fd998c7f
KS
8254*/
8255
8256int
dc91a0ed 8257merge_faces (f, face_name, face_id, base_face_id)
fd998c7f
KS
8258 struct frame *f;
8259 Lisp_Object face_name;
8260 int face_id, base_face_id;
8261{
8262 Lisp_Object attrs[LFACE_VECTOR_SIZE];
8263 struct face *base_face;
8264
8265 base_face = FACE_FROM_ID (f, base_face_id);
8266 if (!base_face)
8267 return base_face_id;
8268
dc91a0ed
KS
8269 if (EQ (face_name, Qt))
8270 {
8271 if (face_id < 0 || face_id >= lface_id_to_name_size)
8272 return base_face_id;
8273 face_name = lface_id_to_name[face_id];
5c538596 8274 face_id = lookup_derived_face (f, face_name, base_face_id, 1);
dc91a0ed
KS
8275 if (face_id >= 0)
8276 return face_id;
8277 return base_face_id;
8278 }
8279
fd998c7f
KS
8280 /* Begin with attributes from the base face. */
8281 bcopy (base_face->lface, attrs, sizeof attrs);
8282
8283 if (!NILP (face_name))
8284 {
8285 if (!merge_named_face (f, face_name, attrs, 0))
8286 return base_face_id;
8287 }
8288 else
8289 {
8290 struct face *face;
dc91a0ed
KS
8291 if (face_id < 0)
8292 return base_face_id;
fd998c7f
KS
8293 face = FACE_FROM_ID (f, face_id);
8294 if (!face)
8295 return base_face_id;
8296 merge_face_vectors (f, face->lface, attrs, 0);
8297 }
8298
8299 /* Look up a realized face with the given face attributes,
8300 or realize a new one for ASCII characters. */
0e3ae538 8301 return lookup_face (f, attrs);
fd998c7f
KS
8302}
8303
c115973b 8304\f
82641697
GM
8305/***********************************************************************
8306 Tests
8307 ***********************************************************************/
c115973b 8308
82641697 8309#if GLYPH_DEBUG
c115973b 8310
82641697 8311/* Print the contents of the realized face FACE to stderr. */
c115973b 8312
82641697
GM
8313static void
8314dump_realized_face (face)
8315 struct face *face;
8316{
8317 fprintf (stderr, "ID: %d\n", face->id);
8318#ifdef HAVE_X_WINDOWS
2defe37f 8319 fprintf (stderr, "gc: %ld\n", (long) face->gc);
82641697
GM
8320#endif
8321 fprintf (stderr, "foreground: 0x%lx (%s)\n",
8322 face->foreground,
d5db4077 8323 SDATA (face->lface[LFACE_FOREGROUND_INDEX]));
82641697
GM
8324 fprintf (stderr, "background: 0x%lx (%s)\n",
8325 face->background,
d5db4077 8326 SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
82641697
GM
8327 fprintf (stderr, "font_name: %s (%s)\n",
8328 face->font_name,
d5db4077 8329 SDATA (face->lface[LFACE_FAMILY_INDEX]));
82641697
GM
8330#ifdef HAVE_X_WINDOWS
8331 fprintf (stderr, "font = %p\n", face->font);
8332#endif
8333 fprintf (stderr, "font_info_id = %d\n", face->font_info_id);
8334 fprintf (stderr, "fontset: %d\n", face->fontset);
8335 fprintf (stderr, "underline: %d (%s)\n",
8336 face->underline_p,
d5db4077 8337 SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
82641697 8338 fprintf (stderr, "hash: %d\n", face->hash);
c115973b
JB
8339}
8340
8341
7ee72033
MB
8342DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */)
8343 (n)
82641697 8344 Lisp_Object n;
c115973b 8345{
82641697 8346 if (NILP (n))
c115973b 8347 {
82641697 8348 int i;
178c5d9c 8349
82641697
GM
8350 fprintf (stderr, "font selection order: ");
8351 for (i = 0; i < DIM (font_sort_order); ++i)
8352 fprintf (stderr, "%d ", font_sort_order[i]);
8353 fprintf (stderr, "\n");
8354
8355 fprintf (stderr, "alternative fonts: ");
8356 debug_print (Vface_alternative_font_family_alist);
8357 fprintf (stderr, "\n");
178c5d9c 8358
c0617987 8359 for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
82641697 8360 Fdump_face (make_number (i));
c115973b
JB
8361 }
8362 else
f5e278c7 8363 {
82641697 8364 struct face *face;
b7826503 8365 CHECK_NUMBER (n);
c0617987 8366 face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
82641697
GM
8367 if (face == NULL)
8368 error ("Not a valid face");
8369 dump_realized_face (face);
f5e278c7 8370 }
178c5d9c 8371
c115973b
JB
8372 return Qnil;
8373}
b5c53576 8374
b5c53576 8375
82641697 8376DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
7ee72033
MB
8377 0, 0, 0, doc: /* */)
8378 ()
b5c53576 8379{
82641697
GM
8380 fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
8381 fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
8382 fprintf (stderr, "number of GCs = %d\n", ngcs);
8383 return Qnil;
b5c53576
RS
8384}
8385
82641697
GM
8386#endif /* GLYPH_DEBUG != 0 */
8387
b5c53576 8388
c115973b 8389\f
82641697
GM
8390/***********************************************************************
8391 Initialization
8392 ***********************************************************************/
cb637678 8393
c115973b 8394void
f211082d 8395syms_of_xfaces ()
c115973b 8396{
f211082d
JB
8397 Qface = intern ("face");
8398 staticpro (&Qface);
46b00436
KS
8399 Qface_no_inherit = intern ("face-no-inherit");
8400 staticpro (&Qface_no_inherit);
fef04523
GM
8401 Qbitmap_spec_p = intern ("bitmap-spec-p");
8402 staticpro (&Qbitmap_spec_p);
c20577bc
JL
8403 Qframe_set_background_mode = intern ("frame-set-background-mode");
8404 staticpro (&Qframe_set_background_mode);
178c5d9c 8405
82641697
GM
8406 /* Lisp face attribute keywords. */
8407 QCfamily = intern (":family");
8408 staticpro (&QCfamily);
8409 QCheight = intern (":height");
8410 staticpro (&QCheight);
8411 QCweight = intern (":weight");
8412 staticpro (&QCweight);
8413 QCslant = intern (":slant");
8414 staticpro (&QCslant);
8415 QCunderline = intern (":underline");
8416 staticpro (&QCunderline);
8417 QCinverse_video = intern (":inverse-video");
178c5d9c 8418 staticpro (&QCinverse_video);
82641697
GM
8419 QCreverse_video = intern (":reverse-video");
8420 staticpro (&QCreverse_video);
8421 QCforeground = intern (":foreground");
8422 staticpro (&QCforeground);
8423 QCbackground = intern (":background");
8424 staticpro (&QCbackground);
8425 QCstipple = intern (":stipple");;
8426 staticpro (&QCstipple);
8427 QCwidth = intern (":width");
8428 staticpro (&QCwidth);
8429 QCfont = intern (":font");
8430 staticpro (&QCfont);
763bc839
KH
8431 QCfontset = intern (":fontset");
8432 staticpro (&QCfontset);
82641697
GM
8433 QCbold = intern (":bold");
8434 staticpro (&QCbold);
8435 QCitalic = intern (":italic");
8436 staticpro (&QCitalic);
8437 QCoverline = intern (":overline");
8438 staticpro (&QCoverline);
8439 QCstrike_through = intern (":strike-through");
8440 staticpro (&QCstrike_through);
8441 QCbox = intern (":box");
8442 staticpro (&QCbox);
2c20458f
MB
8443 QCinherit = intern (":inherit");
8444 staticpro (&QCinherit);
82641697
GM
8445
8446 /* Symbols used for Lisp face attribute values. */
8447 QCcolor = intern (":color");
8448 staticpro (&QCcolor);
8449 QCline_width = intern (":line-width");
8450 staticpro (&QCline_width);
8451 QCstyle = intern (":style");
8452 staticpro (&QCstyle);
8453 Qreleased_button = intern ("released-button");
8454 staticpro (&Qreleased_button);
8455 Qpressed_button = intern ("pressed-button");
8456 staticpro (&Qpressed_button);
8457 Qnormal = intern ("normal");
8458 staticpro (&Qnormal);
8459 Qultra_light = intern ("ultra-light");
8460 staticpro (&Qultra_light);
8461 Qextra_light = intern ("extra-light");
8462 staticpro (&Qextra_light);
8463 Qlight = intern ("light");
8464 staticpro (&Qlight);
8465 Qsemi_light = intern ("semi-light");
8466 staticpro (&Qsemi_light);
8467 Qsemi_bold = intern ("semi-bold");
8468 staticpro (&Qsemi_bold);
8469 Qbold = intern ("bold");
8470 staticpro (&Qbold);
8471 Qextra_bold = intern ("extra-bold");
8472 staticpro (&Qextra_bold);
8473 Qultra_bold = intern ("ultra-bold");
8474 staticpro (&Qultra_bold);
8475 Qoblique = intern ("oblique");
8476 staticpro (&Qoblique);
8477 Qitalic = intern ("italic");
8478 staticpro (&Qitalic);
8479 Qreverse_oblique = intern ("reverse-oblique");
8480 staticpro (&Qreverse_oblique);
8481 Qreverse_italic = intern ("reverse-italic");
8482 staticpro (&Qreverse_italic);
8483 Qultra_condensed = intern ("ultra-condensed");
8484 staticpro (&Qultra_condensed);
8485 Qextra_condensed = intern ("extra-condensed");
8486 staticpro (&Qextra_condensed);
8487 Qcondensed = intern ("condensed");
8488 staticpro (&Qcondensed);
8489 Qsemi_condensed = intern ("semi-condensed");
8490 staticpro (&Qsemi_condensed);
8491 Qsemi_expanded = intern ("semi-expanded");
8492 staticpro (&Qsemi_expanded);
8493 Qexpanded = intern ("expanded");
8494 staticpro (&Qexpanded);
8495 Qextra_expanded = intern ("extra-expanded");
8496 staticpro (&Qextra_expanded);
8497 Qultra_expanded = intern ("ultra-expanded");
8498 staticpro (&Qultra_expanded);
8499 Qbackground_color = intern ("background-color");
8500 staticpro (&Qbackground_color);
8501 Qforeground_color = intern ("foreground-color");
8502 staticpro (&Qforeground_color);
8503 Qunspecified = intern ("unspecified");
8504 staticpro (&Qunspecified);
2ff10663
CY
8505 Qignore_defface = intern (":ignore-defface");
8506 staticpro (&Qignore_defface);
82641697 8507
92610620
GM
8508 Qface_alias = intern ("face-alias");
8509 staticpro (&Qface_alias);
82641697
GM
8510 Qdefault = intern ("default");
8511 staticpro (&Qdefault);
9ea173e8
GM
8512 Qtool_bar = intern ("tool-bar");
8513 staticpro (&Qtool_bar);
82641697
GM
8514 Qregion = intern ("region");
8515 staticpro (&Qregion);
8bd201d6
GM
8516 Qfringe = intern ("fringe");
8517 staticpro (&Qfringe);
045dee35
GM
8518 Qheader_line = intern ("header-line");
8519 staticpro (&Qheader_line);
8bd201d6
GM
8520 Qscroll_bar = intern ("scroll-bar");
8521 staticpro (&Qscroll_bar);
c7ae3284
GM
8522 Qmenu = intern ("menu");
8523 staticpro (&Qmenu);
8bd201d6
GM
8524 Qcursor = intern ("cursor");
8525 staticpro (&Qcursor);
8526 Qborder = intern ("border");
8527 staticpro (&Qborder);
8528 Qmouse = intern ("mouse");
8529 staticpro (&Qmouse);
039b6394
KS
8530 Qmode_line_inactive = intern ("mode-line-inactive");
8531 staticpro (&Qmode_line_inactive);
53abc3bf
MB
8532 Qvertical_border = intern ("vertical-border");
8533 staticpro (&Qvertical_border);
2d764c78
EZ
8534 Qtty_color_desc = intern ("tty-color-desc");
8535 staticpro (&Qtty_color_desc);
b35df831
MB
8536 Qtty_color_standard_values = intern ("tty-color-standard-values");
8537 staticpro (&Qtty_color_standard_values);
2d764c78
EZ
8538 Qtty_color_by_index = intern ("tty-color-by-index");
8539 staticpro (&Qtty_color_by_index);
ae4b4ba5
GM
8540 Qtty_color_alist = intern ("tty-color-alist");
8541 staticpro (&Qtty_color_alist);
eeffb293
GM
8542 Qscalable_fonts_allowed = intern ("scalable-fonts-allowed");
8543 staticpro (&Qscalable_fonts_allowed);
82641697 8544
dbc968b8
GM
8545 Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
8546 staticpro (&Vparam_value_alist);
434b9cc5
GM
8547 Vface_alternative_font_family_alist = Qnil;
8548 staticpro (&Vface_alternative_font_family_alist);
32fcc231
GM
8549 Vface_alternative_font_registry_alist = Qnil;
8550 staticpro (&Vface_alternative_font_registry_alist);
434b9cc5 8551
82641697
GM
8552 defsubr (&Sinternal_make_lisp_face);
8553 defsubr (&Sinternal_lisp_face_p);
8554 defsubr (&Sinternal_set_lisp_face_attribute);
c3cee013 8555#ifdef HAVE_WINDOW_SYSTEM
82641697 8556 defsubr (&Sinternal_set_lisp_face_attribute_from_resource);
42608ba8 8557#endif
ea4fa0af
GM
8558 defsubr (&Scolor_gray_p);
8559 defsubr (&Scolor_supported_p);
cdfaafa9
MB
8560 defsubr (&Sface_attribute_relative_p);
8561 defsubr (&Smerge_face_attribute);
82641697
GM
8562 defsubr (&Sinternal_get_lisp_face_attribute);
8563 defsubr (&Sinternal_lisp_face_attribute_values);
8564 defsubr (&Sinternal_lisp_face_equal_p);
8565 defsubr (&Sinternal_lisp_face_empty_p);
8566 defsubr (&Sinternal_copy_lisp_face);
8567 defsubr (&Sinternal_merge_in_global_face);
8568 defsubr (&Sface_font);
8569 defsubr (&Sframe_face_alist);
9717e36c 8570 defsubr (&Sdisplay_supports_face_attributes_p);
b35df831 8571 defsubr (&Scolor_distance);
82641697
GM
8572 defsubr (&Sinternal_set_font_selection_order);
8573 defsubr (&Sinternal_set_alternative_font_family_alist);
32fcc231 8574 defsubr (&Sinternal_set_alternative_font_registry_alist);
f6608d5c 8575 defsubr (&Sface_attributes_as_vector);
82641697
GM
8576#if GLYPH_DEBUG
8577 defsubr (&Sdump_face);
8578 defsubr (&Sshow_face_resources);
8579#endif /* GLYPH_DEBUG */
8580 defsubr (&Sclear_face_cache);
a4a76b61 8581 defsubr (&Stty_suppress_bold_inverse_default_colors);
82641697 8582
38426dee 8583#if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
08dc08dc
GM
8584 defsubr (&Sdump_colors);
8585#endif
8586
7ee72033
MB
8587 DEFVAR_LISP ("font-list-limit", &Vfont_list_limit,
8588 doc: /* *Limit for font matching.
228299fa
GM
8589If an integer > 0, font matching functions won't load more than
8590that number of fonts when searching for a matching font. */);
057df17c
GM
8591 Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
8592
7ee72033
MB
8593 DEFVAR_LISP ("face-new-frame-defaults", &Vface_new_frame_defaults,
8594 doc: /* List of global face definitions (for internal use only.) */);
82641697 8595 Vface_new_frame_defaults = Qnil;
178c5d9c 8596
7ee72033
MB
8597 DEFVAR_LISP ("face-default-stipple", &Vface_default_stipple,
8598 doc: /* *Default stipple pattern used on monochrome displays.
228299fa
GM
8599This stipple pattern is used on monochrome displays
8600instead of shades of gray for a face background color.
8601See `set-face-stipple' for possible values for this variable. */);
82641697
GM
8602 Vface_default_stipple = build_string ("gray3");
8603
7ee72033
MB
8604 DEFVAR_LISP ("tty-defined-color-alist", &Vtty_defined_color_alist,
8605 doc: /* An alist of defined terminal colors and their RGB values. */);
ae4b4ba5
GM
8606 Vtty_defined_color_alist = Qnil;
8607
7ee72033
MB
8608 DEFVAR_LISP ("scalable-fonts-allowed", &Vscalable_fonts_allowed,
8609 doc: /* Allowed scalable fonts.
228299fa
GM
8610A value of nil means don't allow any scalable fonts.
8611A value of t means allow any scalable font.
8612Otherwise, value must be a list of regular expressions. A font may be
8613scaled if its name matches a regular expression in the list.
8614Note that if value is nil, a scalable font might still be used, if no
8615other font of the appropriate family and registry is available. */);
3cf80731 8616 Vscalable_fonts_allowed = Qnil;
b5c53576 8617
7ee72033
MB
8618 DEFVAR_LISP ("face-ignored-fonts", &Vface_ignored_fonts,
8619 doc: /* List of ignored fonts.
228299fa
GM
8620Each element is a regular expression that matches names of fonts to
8621ignore. */);
c824bfbc
KH
8622 Vface_ignored_fonts = Qnil;
8623
f70400f2
KH
8624 DEFVAR_LISP ("face-font-rescale-alist", &Vface_font_rescale_alist,
8625 doc: /* Alist of fonts vs the rescaling factors.
8626Each element is a cons (FONT-NAME-PATTERN . RESCALE-RATIO), where
8627FONT-NAME-PATTERN is a regular expression matching a font name, and
8628RESCALE-RATIO is a floating point number to specify how much larger
8629\(or smaller) font we should use. For instance, if a face requests
8630a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point. */);
8631 Vface_font_rescale_alist = Qnil;
8632
c3cee013 8633#ifdef HAVE_WINDOW_SYSTEM
fef04523 8634 defsubr (&Sbitmap_spec_p);
82641697
GM
8635 defsubr (&Sx_list_fonts);
8636 defsubr (&Sinternal_face_x_get_resource);
92610620 8637 defsubr (&Sx_family_fonts);
82641697 8638 defsubr (&Sx_font_family_list);
c3cee013 8639#endif /* HAVE_WINDOW_SYSTEM */
c115973b 8640}
6b61353c
KH
8641
8642/* arch-tag: 8a0f7598-5517-408d-9ab3-1da6fcd4c749
8643 (do not change this comment) */