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