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