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