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