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