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