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