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