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