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