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