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