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