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