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