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