Use "ASET (a, i, v)" rather than "AREF (a, i) = v".
[emacs.git] / src / xfaces.c
blobb5eeca09210cd03e2ce897dfa2804dbb4770a4f6
1 /* xfaces.c -- "Face" primitives.
3 Copyright (C) 1993-1994, 1998-2012 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New face implementation by Gerd Moellmann <gerd@gnu.org>. */
22 /* Faces.
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:
28 1. Font family name.
30 2. Font foundry name.
32 3. Relative proportionate width, aka character set width or set
33 width (swidth), e.g. `semi-compressed'.
35 4. Font height in 1/10pt.
37 5. Font weight, e.g. `bold'.
39 6. Font slant, e.g. `italic'.
41 7. Foreground color.
43 8. Background color.
45 9. Whether or not characters should be underlined, and in what color.
47 10. Whether or not characters should be displayed in inverse video.
49 11. A background stipple, a bitmap.
51 12. Whether or not characters should be overlined, and in what color.
53 13. Whether or not characters should be strike-through, and in what
54 color.
56 14. Whether or not a box should be drawn around characters, the box
57 type, and, for simple boxes, in what color.
59 15. Font-spec, or nil. This is a special attribute.
61 A font-spec is a collection of font attributes (specs).
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.
68 On the other hand, if one of the other font-related attributes are
69 specified, the corresponding specs in this attribute is set to nil.
71 15. A face name or list of face names from which to inherit attributes.
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.
77 17. A fontset name. This is another special attribute.
79 A fontset is a mappings from characters to font-specs, and the
80 specs overwrite the font-spec in the 14th attribute.
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
87 with the symbol `face' in slot 0, and a slot for each of the face
88 attributes mentioned above.
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.
94 A face doesn't have to specify all attributes. Those not specified
95 have a value of `unspecified'. Faces specifying all attributes but
96 the 14th are called `fully-specified'.
99 Face merging.
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.
109 Face realization.
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.
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
122 them.
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.
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.
134 Thus, all realized faces have a realized fontset.
137 Unibyte text.
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.
145 Font selection.
147 Font selection tries to find the best available matching font for a
148 given (character, face) combination.
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.
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.
161 Font selection can be influenced by the user.
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.
172 2. Setting face-font-family-alternatives allows the user to
173 specify alternative font families to try if a family specified by a
174 face doesn't exist.
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.
180 4. Setting face-ignored-fonts allows the user to ignore specific
181 fonts.
184 Character composition.
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.
195 Initialization of basic faces.
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. */
202 #include <config.h>
203 #include <stdio.h>
204 #include <sys/types.h>
205 #include <sys/stat.h>
206 #include <stdio.h> /* This needs to be before termchar.h */
207 #include <setjmp.h>
209 #include "lisp.h"
210 #include "character.h"
211 #include "charset.h"
212 #include "keyboard.h"
213 #include "frame.h"
214 #include "termhooks.h"
216 #ifdef HAVE_X_WINDOWS
217 #include "xterm.h"
218 #ifdef USE_MOTIF
219 #include <Xm/Xm.h>
220 #include <Xm/XmStrDefs.h>
221 #endif /* USE_MOTIF */
222 #endif /* HAVE_X_WINDOWS */
224 #ifdef MSDOS
225 #include "dosfns.h"
226 #endif
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. */
233 #undef FRAME_X_DISPLAY_INFO
234 #define FRAME_X_DISPLAY_INFO FRAME_W32_DISPLAY_INFO
235 #define x_display_info w32_display_info
236 #define check_x check_w32
237 #define GCGraphicsExposures 0
238 #endif /* WINDOWSNT */
240 #ifdef HAVE_NS
241 #include "nsterm.h"
242 #undef FRAME_X_DISPLAY_INFO
243 #define FRAME_X_DISPLAY_INFO FRAME_NS_DISPLAY_INFO
244 #define x_display_info ns_display_info
245 #define check_x check_ns
246 #define GCGraphicsExposures 0
247 #endif /* HAVE_NS */
249 #include "buffer.h"
250 #include "dispextern.h"
251 #include "blockinput.h"
252 #include "window.h"
253 #include "intervals.h"
254 #include "termchar.h"
256 #include "font.h"
257 #ifdef HAVE_WINDOW_SYSTEM
258 #include "fontset.h"
259 #endif /* HAVE_WINDOW_SYSTEM */
261 #ifdef HAVE_X_WINDOWS
263 /* Compensate for a bug in Xos.h on some systems, on which it requires
264 time.h. On some such systems, Xos.h tries to redefine struct
265 timeval and struct timezone if USG is #defined while it is
266 #included. */
268 #ifdef XOS_NEEDS_TIME_H
269 #include <time.h>
270 #undef USG
271 #include <X11/Xos.h>
272 #define USG
273 #define __TIMEVAL__
274 #if defined USG || defined __TIMEVAL__ /* Don't warn about unused macros. */
275 #endif
276 #else /* not XOS_NEEDS_TIME_H */
277 #include <X11/Xos.h>
278 #endif /* not XOS_NEEDS_TIME_H */
280 #endif /* HAVE_X_WINDOWS */
282 #include <ctype.h>
284 /* Number of pt per inch (from the TeXbook). */
286 #define PT_PER_INCH 72.27
288 /* Non-zero if face attribute ATTR is unspecified. */
290 #define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
292 /* Non-zero if face attribute ATTR is `ignore-defface'. */
294 #define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface)
296 /* Value is the number of elements of VECTOR. */
298 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
300 /* Size of hash table of realized faces in face caches (should be a
301 prime number). */
303 #define FACE_CACHE_BUCKETS_SIZE 1001
305 /* Keyword symbols used for face attribute names. */
307 Lisp_Object QCfamily, QCheight, QCweight, QCslant;
308 static Lisp_Object QCunderline;
309 static Lisp_Object QCinverse_video, QCstipple;
310 Lisp_Object QCforeground, QCbackground;
311 Lisp_Object QCwidth;
312 static Lisp_Object QCfont, QCbold, QCitalic;
313 static Lisp_Object QCreverse_video;
314 static Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
315 static Lisp_Object QCfontset;
317 /* Symbols used for attribute values. */
319 Lisp_Object Qnormal;
320 Lisp_Object Qbold;
321 static Lisp_Object Qline, Qwave;
322 static Lisp_Object Qultra_light, Qextra_light, Qlight;
323 static Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold;
324 static Lisp_Object Qoblique, Qreverse_oblique, Qreverse_italic;
325 Lisp_Object Qitalic;
326 static Lisp_Object Qultra_condensed, Qextra_condensed;
327 Lisp_Object Qcondensed;
328 static Lisp_Object Qsemi_condensed, Qsemi_expanded, Qextra_expanded;
329 Lisp_Object Qexpanded;
330 static Lisp_Object Qultra_expanded;
331 static Lisp_Object Qreleased_button, Qpressed_button;
332 static Lisp_Object QCstyle, QCcolor, QCline_width;
333 Lisp_Object Qunspecified; /* used in dosfns.c */
334 static Lisp_Object QCignore_defface;
336 char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
338 /* The name of the function to call when the background of the frame
339 has changed, frame_set_background_mode. */
341 static Lisp_Object Qframe_set_background_mode;
343 /* Names of basic faces. */
345 Lisp_Object Qdefault, Qtool_bar, Qfringe;
346 static Lisp_Object Qregion;
347 Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
348 static Lisp_Object Qborder, Qmouse, Qmenu;
349 Lisp_Object Qmode_line_inactive;
350 static Lisp_Object Qvertical_border;
352 /* The symbol `face-alias'. A symbols having that property is an
353 alias for another face. Value of the property is the name of
354 the aliased face. */
356 static Lisp_Object Qface_alias;
358 /* Alist of alternative font families. Each element is of the form
359 (FAMILY FAMILY1 FAMILY2 ...). If fonts of FAMILY can't be loaded,
360 try FAMILY1, then FAMILY2, ... */
362 Lisp_Object Vface_alternative_font_family_alist;
364 /* Alist of alternative font registries. Each element is of the form
365 (REGISTRY REGISTRY1 REGISTRY2...). If fonts of REGISTRY can't be
366 loaded, try REGISTRY1, then REGISTRY2, ... */
368 Lisp_Object Vface_alternative_font_registry_alist;
370 /* Allowed scalable fonts. A value of nil means don't allow any
371 scalable fonts. A value of t means allow the use of any scalable
372 font. Otherwise, value must be a list of regular expressions. A
373 font may be scaled if its name matches a regular expression in the
374 list. */
376 static Lisp_Object Qscalable_fonts_allowed;
378 #define DEFAULT_FONT_LIST_LIMIT 100
380 /* The symbols `foreground-color' and `background-color' which can be
381 used as part of a `face' property. This is for compatibility with
382 Emacs 20.2. */
384 Lisp_Object Qforeground_color, Qbackground_color;
386 /* The symbols `face' and `mouse-face' used as text properties. */
388 Lisp_Object Qface;
390 /* Property for basic faces which other faces cannot inherit. */
392 static Lisp_Object Qface_no_inherit;
394 /* Error symbol for wrong_type_argument in load_pixmap. */
396 static Lisp_Object Qbitmap_spec_p;
398 /* The next ID to assign to Lisp faces. */
400 static int next_lface_id;
402 /* A vector mapping Lisp face Id's to face names. */
404 static Lisp_Object *lface_id_to_name;
405 static ptrdiff_t lface_id_to_name_size;
407 /* TTY color-related functions (defined in tty-colors.el). */
409 static Lisp_Object Qtty_color_desc, Qtty_color_by_index, Qtty_color_standard_values;
411 /* The name of the function used to compute colors on TTYs. */
413 static Lisp_Object Qtty_color_alist;
415 /* Counter for calls to clear_face_cache. If this counter reaches
416 CLEAR_FONT_TABLE_COUNT, and a frame has more than
417 CLEAR_FONT_TABLE_NFONTS load, unused fonts are freed. */
419 static int clear_font_table_count;
420 #define CLEAR_FONT_TABLE_COUNT 100
421 #define CLEAR_FONT_TABLE_NFONTS 10
423 /* Non-zero means face attributes have been changed since the last
424 redisplay. Used in redisplay_internal. */
426 int face_change_count;
428 /* Non-zero means don't display bold text if a face's foreground
429 and background colors are the inverse of the default colors of the
430 display. This is a kluge to suppress `bold black' foreground text
431 which is hard to read on an LCD monitor. */
433 static int tty_suppress_bold_inverse_default_colors_p;
435 /* A list of the form `((x . y))' used to avoid consing in
436 Finternal_set_lisp_face_attribute. */
438 static Lisp_Object Vparam_value_alist;
440 /* The total number of colors currently allocated. */
442 #ifdef GLYPH_DEBUG
443 static int ncolors_allocated;
444 static int npixmaps_allocated;
445 static int ngcs;
446 #endif
448 /* Non-zero means the definition of the `menu' face for new frames has
449 been changed. */
451 static int menu_face_changed_default;
454 /* Function prototypes. */
456 struct table_entry;
457 struct named_merge_point;
459 static void map_tty_color (struct frame *, struct face *,
460 enum lface_attribute_index, int *);
461 static Lisp_Object resolve_face_name (Lisp_Object, int);
462 static void set_font_frame_param (Lisp_Object, Lisp_Object);
463 static int get_lface_attributes (struct frame *, Lisp_Object, Lisp_Object *,
464 int, struct named_merge_point *);
465 static ptrdiff_t load_pixmap (struct frame *, Lisp_Object,
466 unsigned *, unsigned *);
467 static struct frame *frame_or_selected_frame (Lisp_Object, int);
468 static void load_face_colors (struct frame *, struct face *, Lisp_Object *);
469 static void free_face_colors (struct frame *, struct face *);
470 static int face_color_gray_p (struct frame *, const char *);
471 static struct face *realize_face (struct face_cache *, Lisp_Object *,
472 int);
473 static struct face *realize_non_ascii_face (struct frame *, Lisp_Object,
474 struct face *);
475 static struct face *realize_x_face (struct face_cache *, Lisp_Object *);
476 static struct face *realize_tty_face (struct face_cache *, Lisp_Object *);
477 static int realize_basic_faces (struct frame *);
478 static int realize_default_face (struct frame *);
479 static void realize_named_face (struct frame *, Lisp_Object, int);
480 static int lface_fully_specified_p (Lisp_Object *);
481 static int lface_equal_p (Lisp_Object *, Lisp_Object *);
482 static unsigned hash_string_case_insensitive (Lisp_Object);
483 static unsigned lface_hash (Lisp_Object *);
484 static int lface_same_font_attributes_p (Lisp_Object *, Lisp_Object *);
485 static struct face_cache *make_face_cache (struct frame *);
486 static void clear_face_gcs (struct face_cache *);
487 static void free_face_cache (struct face_cache *);
488 static int face_fontset (Lisp_Object *);
489 static void merge_face_vectors (struct frame *, Lisp_Object *, Lisp_Object*,
490 struct named_merge_point *);
491 static int merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *,
492 int, struct named_merge_point *);
493 static int set_lface_from_font (struct frame *, Lisp_Object, Lisp_Object,
494 int);
495 static Lisp_Object lface_from_face_name (struct frame *, Lisp_Object, int);
496 static struct face *make_realized_face (Lisp_Object *);
497 static void cache_face (struct face_cache *, struct face *, unsigned);
498 static void uncache_face (struct face_cache *, struct face *);
500 #ifdef HAVE_WINDOW_SYSTEM
502 static GC x_create_gc (struct frame *, unsigned long, XGCValues *);
503 static void x_free_gc (struct frame *, GC);
505 #ifdef USE_X_TOOLKIT
506 static void x_update_menu_appearance (struct frame *);
508 extern void free_frame_menubar (struct frame *);
509 #endif /* USE_X_TOOLKIT */
511 #endif /* HAVE_WINDOW_SYSTEM */
514 /***********************************************************************
515 Utilities
516 ***********************************************************************/
518 #ifdef HAVE_X_WINDOWS
520 #ifdef DEBUG_X_COLORS
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. */
531 /* Reference counts for pixel colors. */
533 int color_count[256];
535 /* Register color PIXEL as allocated. */
537 void
538 register_color (unsigned long pixel)
540 eassert (pixel < 256);
541 ++color_count[pixel];
545 /* Register color PIXEL as deallocated. */
547 void
548 unregister_color (unsigned long pixel)
550 eassert (pixel < 256);
551 if (color_count[pixel] > 0)
552 --color_count[pixel];
553 else
554 abort ();
558 /* Register N colors from PIXELS as deallocated. */
560 void
561 unregister_colors (unsigned long *pixels, int n)
563 int i;
564 for (i = 0; i < n; ++i)
565 unregister_color (pixels[i]);
569 DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
570 doc: /* Dump currently allocated colors to stderr. */)
571 (void)
573 int i, n;
575 fputc ('\n', stderr);
577 for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i)
578 if (color_count[i])
580 fprintf (stderr, "%3d: %5d", i, color_count[i]);
581 ++n;
582 if (n % 5 == 0)
583 fputc ('\n', stderr);
584 else
585 fputc ('\t', stderr);
588 if (n % 5 != 0)
589 fputc ('\n', stderr);
590 return Qnil;
593 #endif /* DEBUG_X_COLORS */
596 /* Free colors used on frame F. PIXELS is an array of NPIXELS pixel
597 color values. Interrupt input must be blocked when this function
598 is called. */
600 void
601 x_free_colors (struct frame *f, long unsigned int *pixels, int npixels)
603 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
605 /* If display has an immutable color map, freeing colors is not
606 necessary and some servers don't allow it. So don't do it. */
607 if (class != StaticColor && class != StaticGray && class != TrueColor)
609 #ifdef DEBUG_X_COLORS
610 unregister_colors (pixels, npixels);
611 #endif
612 XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
613 pixels, npixels, 0);
618 #ifdef USE_X_TOOLKIT
620 /* Free colors used on frame F. PIXELS is an array of NPIXELS pixel
621 color values. Interrupt input must be blocked when this function
622 is called. */
624 void
625 x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap,
626 long unsigned int *pixels, int npixels)
628 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
629 int class = dpyinfo->visual->class;
631 /* If display has an immutable color map, freeing colors is not
632 necessary and some servers don't allow it. So don't do it. */
633 if (class != StaticColor && class != StaticGray && class != TrueColor)
635 #ifdef DEBUG_X_COLORS
636 unregister_colors (pixels, npixels);
637 #endif
638 XFreeColors (dpy, cmap, pixels, npixels, 0);
641 #endif /* USE_X_TOOLKIT */
643 /* Create and return a GC for use on frame F. GC values and mask
644 are given by XGCV and MASK. */
646 static inline GC
647 x_create_gc (struct frame *f, long unsigned int mask, XGCValues *xgcv)
649 GC gc;
650 BLOCK_INPUT;
651 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv);
652 UNBLOCK_INPUT;
653 IF_DEBUG (++ngcs);
654 return gc;
658 /* Free GC which was used on frame F. */
660 static inline void
661 x_free_gc (struct frame *f, GC gc)
663 eassert (interrupt_input_blocked);
664 IF_DEBUG (eassert (--ngcs >= 0));
665 XFreeGC (FRAME_X_DISPLAY (f), gc);
668 #endif /* HAVE_X_WINDOWS */
670 #ifdef WINDOWSNT
671 /* W32 emulation of GCs */
673 static inline GC
674 x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
676 GC gc;
677 BLOCK_INPUT;
678 gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, xgcv);
679 UNBLOCK_INPUT;
680 IF_DEBUG (++ngcs);
681 return gc;
685 /* Free GC which was used on frame F. */
687 static inline void
688 x_free_gc (struct frame *f, GC gc)
690 IF_DEBUG (eassert (--ngcs >= 0));
691 xfree (gc);
694 #endif /* WINDOWSNT */
696 #ifdef HAVE_NS
697 /* NS emulation of GCs */
699 static inline GC
700 x_create_gc (struct frame *f,
701 unsigned long mask,
702 XGCValues *xgcv)
704 GC gc = xmalloc (sizeof *gc);
705 memcpy (gc, xgcv, sizeof (XGCValues));
706 return gc;
709 static inline void
710 x_free_gc (struct frame *f, GC gc)
712 xfree (gc);
714 #endif /* HAVE_NS */
716 /* If FRAME is nil, return a pointer to the selected frame.
717 Otherwise, check that FRAME is a live frame, and return a pointer
718 to it. NPARAM is the parameter number of FRAME, for
719 CHECK_LIVE_FRAME. This is here because it's a frequent pattern in
720 Lisp function definitions. */
722 static inline struct frame *
723 frame_or_selected_frame (Lisp_Object frame, int nparam)
725 if (NILP (frame))
726 frame = selected_frame;
728 CHECK_LIVE_FRAME (frame);
729 return XFRAME (frame);
733 /***********************************************************************
734 Frames and faces
735 ***********************************************************************/
737 /* Initialize face cache and basic faces for frame F. */
739 void
740 init_frame_faces (struct frame *f)
742 /* Make a face cache, if F doesn't have one. */
743 if (FRAME_FACE_CACHE (f) == NULL)
744 FRAME_FACE_CACHE (f) = make_face_cache (f);
746 #ifdef HAVE_WINDOW_SYSTEM
747 /* Make the image cache. */
748 if (FRAME_WINDOW_P (f))
750 /* We initialize the image cache when creating the first frame
751 on a terminal, and not during terminal creation. This way,
752 `x-open-connection' on a tty won't create an image cache. */
753 if (FRAME_IMAGE_CACHE (f) == NULL)
754 FRAME_IMAGE_CACHE (f) = make_image_cache ();
755 ++FRAME_IMAGE_CACHE (f)->refcount;
757 #endif /* HAVE_WINDOW_SYSTEM */
759 /* Realize basic faces. Must have enough information in frame
760 parameters to realize basic faces at this point. */
761 #ifdef HAVE_X_WINDOWS
762 if (!FRAME_X_P (f) || FRAME_X_WINDOW (f))
763 #endif
764 #ifdef WINDOWSNT
765 if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f))
766 #endif
767 #ifdef HAVE_NS
768 if (!FRAME_NS_P (f) || FRAME_NS_WINDOW (f))
769 #endif
770 if (!realize_basic_faces (f))
771 abort ();
775 /* Free face cache of frame F. Called from delete_frame. */
777 void
778 free_frame_faces (struct frame *f)
780 struct face_cache *face_cache = FRAME_FACE_CACHE (f);
782 if (face_cache)
784 free_face_cache (face_cache);
785 FRAME_FACE_CACHE (f) = NULL;
788 #ifdef HAVE_WINDOW_SYSTEM
789 if (FRAME_WINDOW_P (f))
791 struct image_cache *image_cache = FRAME_IMAGE_CACHE (f);
792 if (image_cache)
794 --image_cache->refcount;
795 if (image_cache->refcount == 0)
796 free_image_cache (f);
799 #endif /* HAVE_WINDOW_SYSTEM */
803 /* Clear face caches, and recompute basic faces for frame F. Call
804 this after changing frame parameters on which those faces depend,
805 or when realized faces have been freed due to changing attributes
806 of named faces. */
808 void
809 recompute_basic_faces (struct frame *f)
811 if (FRAME_FACE_CACHE (f))
813 clear_face_cache (0);
814 if (!realize_basic_faces (f))
815 abort ();
820 /* Clear the face caches of all frames. CLEAR_FONTS_P non-zero means
821 try to free unused fonts, too. */
823 void
824 clear_face_cache (int clear_fonts_p)
826 #ifdef HAVE_WINDOW_SYSTEM
827 Lisp_Object tail, frame;
829 if (clear_fonts_p
830 || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
832 #if 0
833 /* Not yet implemented. */
834 clear_font_cache (frame);
835 #endif
837 /* From time to time see if we can unload some fonts. This also
838 frees all realized faces on all frames. Fonts needed by
839 faces will be loaded again when faces are realized again. */
840 clear_font_table_count = 0;
842 FOR_EACH_FRAME (tail, frame)
844 struct frame *f = XFRAME (frame);
845 if (FRAME_WINDOW_P (f)
846 && FRAME_X_DISPLAY_INFO (f)->n_fonts > CLEAR_FONT_TABLE_NFONTS)
847 free_all_realized_faces (frame);
850 else
852 /* Clear GCs of realized faces. */
853 FOR_EACH_FRAME (tail, frame)
855 struct frame *f = XFRAME (frame);
856 if (FRAME_WINDOW_P (f))
857 clear_face_gcs (FRAME_FACE_CACHE (f));
859 clear_image_caches (Qnil);
861 #endif /* HAVE_WINDOW_SYSTEM */
865 DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0,
866 doc: /* Clear face caches on all frames.
867 Optional THOROUGHLY non-nil means try to free unused fonts, too. */)
868 (Lisp_Object thoroughly)
870 clear_face_cache (!NILP (thoroughly));
871 ++face_change_count;
872 ++windows_or_buffers_changed;
873 return Qnil;
877 /***********************************************************************
878 X Pixmaps
879 ***********************************************************************/
881 #ifdef HAVE_WINDOW_SYSTEM
883 DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
884 doc: /* Value is non-nil if OBJECT is a valid bitmap specification.
885 A bitmap specification is either a string, a file name, or a list
886 \(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,
887 HEIGHT is its height, and DATA is a string containing the bits of
888 the pixmap. Bits are stored row by row, each row occupies
889 \(WIDTH + 7)/8 bytes. */)
890 (Lisp_Object object)
892 int pixmap_p = 0;
894 if (STRINGP (object))
895 /* If OBJECT is a string, it's a file name. */
896 pixmap_p = 1;
897 else if (CONSP (object))
899 /* Otherwise OBJECT must be (WIDTH HEIGHT DATA), WIDTH and
900 HEIGHT must be ints > 0, and DATA must be string large
901 enough to hold a bitmap of the specified size. */
902 Lisp_Object width, height, data;
904 height = width = data = Qnil;
906 if (CONSP (object))
908 width = XCAR (object);
909 object = XCDR (object);
910 if (CONSP (object))
912 height = XCAR (object);
913 object = XCDR (object);
914 if (CONSP (object))
915 data = XCAR (object);
919 if (STRINGP (data)
920 && RANGED_INTEGERP (1, width, INT_MAX)
921 && RANGED_INTEGERP (1, height, INT_MAX))
923 int bytes_per_row = ((XINT (width) + BITS_PER_CHAR - 1)
924 / BITS_PER_CHAR);
925 if (XINT (height) <= SBYTES (data) / bytes_per_row)
926 pixmap_p = 1;
930 return pixmap_p ? Qt : Qnil;
934 /* Load a bitmap according to NAME (which is either a file name or a
935 pixmap spec) for use on frame F. Value is the bitmap_id (see
936 xfns.c). If NAME is nil, return with a bitmap id of zero. If
937 bitmap cannot be loaded, display a message saying so, and return
938 zero. Store the bitmap width in *W_PTR and its height in *H_PTR,
939 if these pointers are not null. */
941 static ptrdiff_t
942 load_pixmap (FRAME_PTR f, Lisp_Object name, unsigned int *w_ptr,
943 unsigned int *h_ptr)
945 ptrdiff_t bitmap_id;
947 if (NILP (name))
948 return 0;
950 CHECK_TYPE (!NILP (Fbitmap_spec_p (name)), Qbitmap_spec_p, name);
952 BLOCK_INPUT;
953 if (CONSP (name))
955 /* Decode a bitmap spec into a bitmap. */
957 int h, w;
958 Lisp_Object bits;
960 w = XINT (Fcar (name));
961 h = XINT (Fcar (Fcdr (name)));
962 bits = Fcar (Fcdr (Fcdr (name)));
964 bitmap_id = x_create_bitmap_from_data (f, SSDATA (bits),
965 w, h);
967 else
969 /* It must be a string -- a file name. */
970 bitmap_id = x_create_bitmap_from_file (f, name);
972 UNBLOCK_INPUT;
974 if (bitmap_id < 0)
976 add_to_log ("Invalid or undefined bitmap `%s'", name, Qnil);
977 bitmap_id = 0;
979 if (w_ptr)
980 *w_ptr = 0;
981 if (h_ptr)
982 *h_ptr = 0;
984 else
986 #ifdef GLYPH_DEBUG
987 ++npixmaps_allocated;
988 #endif
989 if (w_ptr)
990 *w_ptr = x_bitmap_width (f, bitmap_id);
992 if (h_ptr)
993 *h_ptr = x_bitmap_height (f, bitmap_id);
996 return bitmap_id;
999 #endif /* HAVE_WINDOW_SYSTEM */
1003 /***********************************************************************
1004 X Colors
1005 ***********************************************************************/
1007 /* Parse RGB_LIST, and fill in the RGB fields of COLOR.
1008 RGB_LIST should contain (at least) 3 lisp integers.
1009 Return 0 if there's a problem with RGB_LIST, otherwise return 1. */
1011 static int
1012 parse_rgb_list (Lisp_Object rgb_list, XColor *color)
1014 #define PARSE_RGB_LIST_FIELD(field) \
1015 if (CONSP (rgb_list) && INTEGERP (XCAR (rgb_list))) \
1017 color->field = XINT (XCAR (rgb_list)); \
1018 rgb_list = XCDR (rgb_list); \
1020 else \
1021 return 0;
1023 PARSE_RGB_LIST_FIELD (red);
1024 PARSE_RGB_LIST_FIELD (green);
1025 PARSE_RGB_LIST_FIELD (blue);
1027 return 1;
1031 /* Lookup on frame F the color described by the lisp string COLOR.
1032 The resulting tty color is returned in TTY_COLOR; if STD_COLOR is
1033 non-zero, then the `standard' definition of the same color is
1034 returned in it. */
1036 static int
1037 tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
1038 XColor *std_color)
1040 Lisp_Object frame, color_desc;
1042 if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc)))
1043 return 0;
1045 XSETFRAME (frame, f);
1047 color_desc = call2 (Qtty_color_desc, color, frame);
1048 if (CONSP (color_desc) && CONSP (XCDR (color_desc)))
1050 Lisp_Object rgb;
1052 if (! INTEGERP (XCAR (XCDR (color_desc))))
1053 return 0;
1055 tty_color->pixel = XINT (XCAR (XCDR (color_desc)));
1057 rgb = XCDR (XCDR (color_desc));
1058 if (! parse_rgb_list (rgb, tty_color))
1059 return 0;
1061 /* Should we fill in STD_COLOR too? */
1062 if (std_color)
1064 /* Default STD_COLOR to the same as TTY_COLOR. */
1065 *std_color = *tty_color;
1067 /* Do a quick check to see if the returned descriptor is
1068 actually _exactly_ equal to COLOR, otherwise we have to
1069 lookup STD_COLOR separately. If it's impossible to lookup
1070 a standard color, we just give up and use TTY_COLOR. */
1071 if ((!STRINGP (XCAR (color_desc))
1072 || NILP (Fstring_equal (color, XCAR (color_desc))))
1073 && !NILP (Ffboundp (Qtty_color_standard_values)))
1075 /* Look up STD_COLOR separately. */
1076 rgb = call1 (Qtty_color_standard_values, color);
1077 if (! parse_rgb_list (rgb, std_color))
1078 return 0;
1082 return 1;
1084 else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
1085 /* We were called early during startup, and the colors are not
1086 yet set up in tty-defined-color-alist. Don't return a failure
1087 indication, since this produces the annoying "Unable to
1088 load color" messages in the *Messages* buffer. */
1089 return 1;
1090 else
1091 /* tty-color-desc seems to have returned a bad value. */
1092 return 0;
1095 /* A version of defined_color for non-X frames. */
1097 static int
1098 tty_defined_color (struct frame *f, const char *color_name,
1099 XColor *color_def, int alloc)
1101 int status = 1;
1103 /* Defaults. */
1104 color_def->pixel = FACE_TTY_DEFAULT_COLOR;
1105 color_def->red = 0;
1106 color_def->blue = 0;
1107 color_def->green = 0;
1109 if (*color_name)
1110 status = tty_lookup_color (f, build_string (color_name), color_def, NULL);
1112 if (color_def->pixel == FACE_TTY_DEFAULT_COLOR && *color_name)
1114 if (strcmp (color_name, "unspecified-fg") == 0)
1115 color_def->pixel = FACE_TTY_DEFAULT_FG_COLOR;
1116 else if (strcmp (color_name, "unspecified-bg") == 0)
1117 color_def->pixel = FACE_TTY_DEFAULT_BG_COLOR;
1120 if (color_def->pixel != FACE_TTY_DEFAULT_COLOR)
1121 status = 1;
1123 return status;
1127 /* Decide if color named COLOR_NAME is valid for the display
1128 associated with the frame F; if so, return the rgb values in
1129 COLOR_DEF. If ALLOC is nonzero, allocate a new colormap cell.
1131 This does the right thing for any type of frame. */
1133 static int
1134 defined_color (struct frame *f, const char *color_name, XColor *color_def,
1135 int alloc)
1137 if (!FRAME_WINDOW_P (f))
1138 return tty_defined_color (f, color_name, color_def, alloc);
1139 #ifdef HAVE_X_WINDOWS
1140 else if (FRAME_X_P (f))
1141 return x_defined_color (f, color_name, color_def, alloc);
1142 #endif
1143 #ifdef WINDOWSNT
1144 else if (FRAME_W32_P (f))
1145 return w32_defined_color (f, color_name, color_def, alloc);
1146 #endif
1147 #ifdef HAVE_NS
1148 else if (FRAME_NS_P (f))
1149 return ns_defined_color (f, color_name, color_def, alloc, 1);
1150 #endif
1151 else
1152 abort ();
1156 /* Given the index IDX of a tty color on frame F, return its name, a
1157 Lisp string. */
1159 Lisp_Object
1160 tty_color_name (struct frame *f, int idx)
1162 if (idx >= 0 && !NILP (Ffboundp (Qtty_color_by_index)))
1164 Lisp_Object frame;
1165 Lisp_Object coldesc;
1167 XSETFRAME (frame, f);
1168 coldesc = call2 (Qtty_color_by_index, make_number (idx), frame);
1170 if (!NILP (coldesc))
1171 return XCAR (coldesc);
1173 #ifdef MSDOS
1174 /* We can have an MSDOG frame under -nw for a short window of
1175 opportunity before internal_terminal_init is called. DTRT. */
1176 if (FRAME_MSDOS_P (f) && !inhibit_window_system)
1177 return msdos_stdcolor_name (idx);
1178 #endif
1180 if (idx == FACE_TTY_DEFAULT_FG_COLOR)
1181 return build_string (unspecified_fg);
1182 if (idx == FACE_TTY_DEFAULT_BG_COLOR)
1183 return build_string (unspecified_bg);
1185 return Qunspecified;
1189 /* Return non-zero if COLOR_NAME is a shade of gray (or white or
1190 black) on frame F.
1192 The criterion implemented here is not a terribly sophisticated one. */
1194 static int
1195 face_color_gray_p (struct frame *f, const char *color_name)
1197 XColor color;
1198 int gray_p;
1200 if (defined_color (f, color_name, &color, 0))
1201 gray_p = (/* Any color sufficiently close to black counts as gray. */
1202 (color.red < 5000 && color.green < 5000 && color.blue < 5000)
1204 ((eabs (color.red - color.green)
1205 < max (color.red, color.green) / 20)
1206 && (eabs (color.green - color.blue)
1207 < max (color.green, color.blue) / 20)
1208 && (eabs (color.blue - color.red)
1209 < max (color.blue, color.red) / 20)));
1210 else
1211 gray_p = 0;
1213 return gray_p;
1217 /* Return non-zero if color COLOR_NAME can be displayed on frame F.
1218 BACKGROUND_P non-zero means the color will be used as background
1219 color. */
1221 static int
1222 face_color_supported_p (struct frame *f, const char *color_name,
1223 int background_p)
1225 Lisp_Object frame;
1226 XColor not_used;
1228 XSETFRAME (frame, f);
1229 return
1230 #ifdef HAVE_WINDOW_SYSTEM
1231 FRAME_WINDOW_P (f)
1232 ? (!NILP (Fxw_display_color_p (frame))
1233 || xstrcasecmp (color_name, "black") == 0
1234 || xstrcasecmp (color_name, "white") == 0
1235 || (background_p
1236 && face_color_gray_p (f, color_name))
1237 || (!NILP (Fx_display_grayscale_p (frame))
1238 && face_color_gray_p (f, color_name)))
1240 #endif
1241 tty_defined_color (f, color_name, &not_used, 0);
1245 DEFUN ("color-gray-p", Fcolor_gray_p, Scolor_gray_p, 1, 2, 0,
1246 doc: /* Return non-nil if COLOR is a shade of gray (or white or black).
1247 FRAME specifies the frame and thus the display for interpreting COLOR.
1248 If FRAME is nil or omitted, use the selected frame. */)
1249 (Lisp_Object color, Lisp_Object frame)
1251 struct frame *f;
1253 CHECK_STRING (color);
1254 if (NILP (frame))
1255 frame = selected_frame;
1256 else
1257 CHECK_FRAME (frame);
1258 f = XFRAME (frame);
1259 return face_color_gray_p (f, SSDATA (color)) ? Qt : Qnil;
1263 DEFUN ("color-supported-p", Fcolor_supported_p,
1264 Scolor_supported_p, 1, 3, 0,
1265 doc: /* Return non-nil if COLOR can be displayed on FRAME.
1266 BACKGROUND-P non-nil means COLOR is used as a background.
1267 Otherwise, this function tells whether it can be used as a foreground.
1268 If FRAME is nil or omitted, use the selected frame.
1269 COLOR must be a valid color name. */)
1270 (Lisp_Object color, Lisp_Object frame, Lisp_Object background_p)
1272 struct frame *f;
1274 CHECK_STRING (color);
1275 if (NILP (frame))
1276 frame = selected_frame;
1277 else
1278 CHECK_FRAME (frame);
1279 f = XFRAME (frame);
1280 if (face_color_supported_p (f, SSDATA (color), !NILP (background_p)))
1281 return Qt;
1282 return Qnil;
1286 /* Load color with name NAME for use by face FACE on frame F.
1287 TARGET_INDEX must be one of LFACE_FOREGROUND_INDEX,
1288 LFACE_BACKGROUND_INDEX, LFACE_UNDERLINE_INDEX, LFACE_OVERLINE_INDEX,
1289 LFACE_STRIKE_THROUGH_INDEX, or LFACE_BOX_INDEX. Value is the
1290 pixel color. If color cannot be loaded, display a message, and
1291 return the foreground, background or underline color of F, but
1292 record that fact in flags of the face so that we don't try to free
1293 these colors. */
1295 unsigned long
1296 load_color (struct frame *f, struct face *face, Lisp_Object name,
1297 enum lface_attribute_index target_index)
1299 XColor color;
1301 eassert (STRINGP (name));
1302 eassert (target_index == LFACE_FOREGROUND_INDEX
1303 || target_index == LFACE_BACKGROUND_INDEX
1304 || target_index == LFACE_UNDERLINE_INDEX
1305 || target_index == LFACE_OVERLINE_INDEX
1306 || target_index == LFACE_STRIKE_THROUGH_INDEX
1307 || target_index == LFACE_BOX_INDEX);
1309 /* if the color map is full, defined_color will return a best match
1310 to the values in an existing cell. */
1311 if (!defined_color (f, SSDATA (name), &color, 1))
1313 add_to_log ("Unable to load color \"%s\"", name, Qnil);
1315 switch (target_index)
1317 case LFACE_FOREGROUND_INDEX:
1318 face->foreground_defaulted_p = 1;
1319 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1320 break;
1322 case LFACE_BACKGROUND_INDEX:
1323 face->background_defaulted_p = 1;
1324 color.pixel = FRAME_BACKGROUND_PIXEL (f);
1325 break;
1327 case LFACE_UNDERLINE_INDEX:
1328 face->underline_defaulted_p = 1;
1329 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1330 break;
1332 case LFACE_OVERLINE_INDEX:
1333 face->overline_color_defaulted_p = 1;
1334 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1335 break;
1337 case LFACE_STRIKE_THROUGH_INDEX:
1338 face->strike_through_color_defaulted_p = 1;
1339 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1340 break;
1342 case LFACE_BOX_INDEX:
1343 face->box_color_defaulted_p = 1;
1344 color.pixel = FRAME_FOREGROUND_PIXEL (f);
1345 break;
1347 default:
1348 abort ();
1351 #ifdef GLYPH_DEBUG
1352 else
1353 ++ncolors_allocated;
1354 #endif
1356 return color.pixel;
1360 #ifdef HAVE_WINDOW_SYSTEM
1362 /* Load colors for face FACE which is used on frame F. Colors are
1363 specified by slots LFACE_BACKGROUND_INDEX and LFACE_FOREGROUND_INDEX
1364 of ATTRS. If the background color specified is not supported on F,
1365 try to emulate gray colors with a stipple from Vface_default_stipple. */
1367 static void
1368 load_face_colors (struct frame *f, struct face *face, Lisp_Object *attrs)
1370 Lisp_Object fg, bg;
1372 bg = attrs[LFACE_BACKGROUND_INDEX];
1373 fg = attrs[LFACE_FOREGROUND_INDEX];
1375 /* Swap colors if face is inverse-video. */
1376 if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
1378 Lisp_Object tmp;
1379 tmp = fg;
1380 fg = bg;
1381 bg = tmp;
1384 /* Check for support for foreground, not for background because
1385 face_color_supported_p is smart enough to know that grays are
1386 "supported" as background because we are supposed to use stipple
1387 for them. */
1388 if (!face_color_supported_p (f, SSDATA (bg), 0)
1389 && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
1391 x_destroy_bitmap (f, face->stipple);
1392 face->stipple = load_pixmap (f, Vface_default_stipple,
1393 &face->pixmap_w, &face->pixmap_h);
1396 face->background = load_color (f, face, bg, LFACE_BACKGROUND_INDEX);
1397 face->foreground = load_color (f, face, fg, LFACE_FOREGROUND_INDEX);
1401 /* Free color PIXEL on frame F. */
1403 void
1404 unload_color (struct frame *f, long unsigned int pixel)
1406 #ifdef HAVE_X_WINDOWS
1407 if (pixel != -1)
1409 BLOCK_INPUT;
1410 x_free_colors (f, &pixel, 1);
1411 UNBLOCK_INPUT;
1413 #endif
1417 /* Free colors allocated for FACE. */
1419 static void
1420 free_face_colors (struct frame *f, struct face *face)
1422 /* PENDING(NS): need to do something here? */
1423 #ifdef HAVE_X_WINDOWS
1424 if (face->colors_copied_bitwise_p)
1425 return;
1427 BLOCK_INPUT;
1429 if (!face->foreground_defaulted_p)
1431 x_free_colors (f, &face->foreground, 1);
1432 IF_DEBUG (--ncolors_allocated);
1435 if (!face->background_defaulted_p)
1437 x_free_colors (f, &face->background, 1);
1438 IF_DEBUG (--ncolors_allocated);
1441 if (face->underline_p
1442 && !face->underline_defaulted_p)
1444 x_free_colors (f, &face->underline_color, 1);
1445 IF_DEBUG (--ncolors_allocated);
1448 if (face->overline_p
1449 && !face->overline_color_defaulted_p)
1451 x_free_colors (f, &face->overline_color, 1);
1452 IF_DEBUG (--ncolors_allocated);
1455 if (face->strike_through_p
1456 && !face->strike_through_color_defaulted_p)
1458 x_free_colors (f, &face->strike_through_color, 1);
1459 IF_DEBUG (--ncolors_allocated);
1462 if (face->box != FACE_NO_BOX
1463 && !face->box_color_defaulted_p)
1465 x_free_colors (f, &face->box_color, 1);
1466 IF_DEBUG (--ncolors_allocated);
1469 UNBLOCK_INPUT;
1470 #endif /* HAVE_X_WINDOWS */
1473 #endif /* HAVE_WINDOW_SYSTEM */
1477 /***********************************************************************
1478 XLFD Font Names
1479 ***********************************************************************/
1481 /* An enumerator for each field of an XLFD font name. */
1483 enum xlfd_field
1485 XLFD_FOUNDRY,
1486 XLFD_FAMILY,
1487 XLFD_WEIGHT,
1488 XLFD_SLANT,
1489 XLFD_SWIDTH,
1490 XLFD_ADSTYLE,
1491 XLFD_PIXEL_SIZE,
1492 XLFD_POINT_SIZE,
1493 XLFD_RESX,
1494 XLFD_RESY,
1495 XLFD_SPACING,
1496 XLFD_AVGWIDTH,
1497 XLFD_REGISTRY,
1498 XLFD_ENCODING,
1499 XLFD_LAST
1502 /* An enumerator for each possible slant value of a font. Taken from
1503 the XLFD specification. */
1505 enum xlfd_slant
1507 XLFD_SLANT_UNKNOWN,
1508 XLFD_SLANT_ROMAN,
1509 XLFD_SLANT_ITALIC,
1510 XLFD_SLANT_OBLIQUE,
1511 XLFD_SLANT_REVERSE_ITALIC,
1512 XLFD_SLANT_REVERSE_OBLIQUE,
1513 XLFD_SLANT_OTHER
1516 /* Relative font weight according to XLFD documentation. */
1518 enum xlfd_weight
1520 XLFD_WEIGHT_UNKNOWN,
1521 XLFD_WEIGHT_ULTRA_LIGHT, /* 10 */
1522 XLFD_WEIGHT_EXTRA_LIGHT, /* 20 */
1523 XLFD_WEIGHT_LIGHT, /* 30 */
1524 XLFD_WEIGHT_SEMI_LIGHT, /* 40: SemiLight, Book, ... */
1525 XLFD_WEIGHT_MEDIUM, /* 50: Medium, Normal, Regular, ... */
1526 XLFD_WEIGHT_SEMI_BOLD, /* 60: SemiBold, DemiBold, ... */
1527 XLFD_WEIGHT_BOLD, /* 70: Bold, ... */
1528 XLFD_WEIGHT_EXTRA_BOLD, /* 80: ExtraBold, Heavy, ... */
1529 XLFD_WEIGHT_ULTRA_BOLD /* 90: UltraBold, Black, ... */
1532 /* Relative proportionate width. */
1534 enum xlfd_swidth
1536 XLFD_SWIDTH_UNKNOWN,
1537 XLFD_SWIDTH_ULTRA_CONDENSED, /* 10 */
1538 XLFD_SWIDTH_EXTRA_CONDENSED, /* 20 */
1539 XLFD_SWIDTH_CONDENSED, /* 30: Condensed, Narrow, Compressed, ... */
1540 XLFD_SWIDTH_SEMI_CONDENSED, /* 40: semicondensed */
1541 XLFD_SWIDTH_MEDIUM, /* 50: Medium, Normal, Regular, ... */
1542 XLFD_SWIDTH_SEMI_EXPANDED, /* 60: SemiExpanded, DemiExpanded, ... */
1543 XLFD_SWIDTH_EXPANDED, /* 70: Expanded... */
1544 XLFD_SWIDTH_EXTRA_EXPANDED, /* 80: ExtraExpanded, Wide... */
1545 XLFD_SWIDTH_ULTRA_EXPANDED /* 90: UltraExpanded... */
1548 /* Order by which font selection chooses fonts. The default values
1549 mean `first, find a best match for the font width, then for the
1550 font height, then for weight, then for slant.' This variable can be
1551 set via set-face-font-sort-order. */
1553 static int font_sort_order[4];
1555 #ifdef HAVE_WINDOW_SYSTEM
1557 static enum font_property_index font_props_for_sorting[FONT_SIZE_INDEX];
1559 static int
1560 compare_fonts_by_sort_order (const void *v1, const void *v2)
1562 Lisp_Object font1 = *(Lisp_Object *) v1;
1563 Lisp_Object font2 = *(Lisp_Object *) v2;
1564 int i;
1566 for (i = 0; i < FONT_SIZE_INDEX; i++)
1568 enum font_property_index idx = font_props_for_sorting[i];
1569 Lisp_Object val1 = AREF (font1, idx), val2 = AREF (font2, idx);
1570 int result;
1572 if (idx <= FONT_REGISTRY_INDEX)
1574 if (STRINGP (val1))
1575 result = STRINGP (val2) ? strcmp (SSDATA (val1), SSDATA (val2)) : -1;
1576 else
1577 result = STRINGP (val2) ? 1 : 0;
1579 else
1581 if (INTEGERP (val1))
1582 result = (INTEGERP (val2) && XINT (val1) >= XINT (val2)
1583 ? XINT (val1) > XINT (val2)
1584 : -1);
1585 else
1586 result = INTEGERP (val2) ? 1 : 0;
1588 if (result)
1589 return result;
1591 return 0;
1594 DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
1595 doc: /* Return a list of available fonts of family FAMILY on FRAME.
1596 If FAMILY is omitted or nil, list all families.
1597 Otherwise, FAMILY must be a string, possibly containing wildcards
1598 `?' and `*'.
1599 If FRAME is omitted or nil, use the selected frame.
1600 Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
1601 SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
1602 FAMILY is the font family name. POINT-SIZE is the size of the
1603 font in 1/10 pt. WIDTH, WEIGHT, and SLANT are symbols describing the
1604 width, weight and slant of the font. These symbols are the same as for
1605 face attributes. FIXED-P is non-nil if the font is fixed-pitch.
1606 FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
1607 giving the registry and encoding of the font.
1608 The result list is sorted according to the current setting of
1609 the face font sort order. */)
1610 (Lisp_Object family, Lisp_Object frame)
1612 Lisp_Object font_spec, list, *drivers, vec;
1613 ptrdiff_t i, nfonts;
1614 EMACS_INT ndrivers;
1615 Lisp_Object result;
1616 USE_SAFE_ALLOCA;
1618 if (NILP (frame))
1619 frame = selected_frame;
1620 CHECK_LIVE_FRAME (frame);
1622 font_spec = Ffont_spec (0, NULL);
1623 if (!NILP (family))
1625 CHECK_STRING (family);
1626 font_parse_family_registry (family, Qnil, font_spec);
1629 list = font_list_entities (frame, font_spec);
1630 if (NILP (list))
1631 return Qnil;
1633 /* Sort the font entities. */
1634 for (i = 0; i < 4; i++)
1635 switch (font_sort_order[i])
1637 case XLFD_SWIDTH:
1638 font_props_for_sorting[i] = FONT_WIDTH_INDEX; break;
1639 case XLFD_POINT_SIZE:
1640 font_props_for_sorting[i] = FONT_SIZE_INDEX; break;
1641 case XLFD_WEIGHT:
1642 font_props_for_sorting[i] = FONT_WEIGHT_INDEX; break;
1643 default:
1644 font_props_for_sorting[i] = FONT_SLANT_INDEX; break;
1646 font_props_for_sorting[i++] = FONT_FAMILY_INDEX;
1647 font_props_for_sorting[i++] = FONT_FOUNDRY_INDEX;
1648 font_props_for_sorting[i++] = FONT_ADSTYLE_INDEX;
1649 font_props_for_sorting[i++] = FONT_REGISTRY_INDEX;
1651 ndrivers = XINT (Flength (list));
1652 SAFE_ALLOCA_LISP (drivers, ndrivers);
1653 for (i = 0; i < ndrivers; i++, list = XCDR (list))
1654 drivers[i] = XCAR (list);
1655 vec = Fvconcat (ndrivers, drivers);
1656 nfonts = ASIZE (vec);
1658 qsort (XVECTOR (vec)->contents, nfonts, sizeof (Lisp_Object),
1659 compare_fonts_by_sort_order);
1661 result = Qnil;
1662 for (i = nfonts - 1; i >= 0; --i)
1664 Lisp_Object font = AREF (vec, i);
1665 Lisp_Object v = Fmake_vector (make_number (8), Qnil);
1666 int point;
1667 Lisp_Object spacing;
1669 ASET (v, 0, AREF (font, FONT_FAMILY_INDEX));
1670 ASET (v, 1, FONT_WIDTH_SYMBOLIC (font));
1671 point = PIXEL_TO_POINT (XINT (AREF (font, FONT_SIZE_INDEX)) * 10,
1672 XFRAME (frame)->resy);
1673 ASET (v, 2, make_number (point));
1674 ASET (v, 3, FONT_WEIGHT_SYMBOLIC (font));
1675 ASET (v, 4, FONT_SLANT_SYMBOLIC (font));
1676 spacing = Ffont_get (font, QCspacing);
1677 ASET (v, 5, (NILP (spacing) || EQ (spacing, Qp)) ? Qnil : Qt);
1678 ASET (v, 6, Ffont_xlfd_name (font, Qnil));
1679 ASET (v, 7, AREF (font, FONT_REGISTRY_INDEX));
1681 result = Fcons (v, result);
1684 SAFE_FREE ();
1685 return result;
1688 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
1689 doc: /* Return a list of the names of available fonts matching PATTERN.
1690 If optional arguments FACE and FRAME are specified, return only fonts
1691 the same size as FACE on FRAME.
1693 PATTERN should be a string containing a font name in the XLFD,
1694 Fontconfig, or GTK format. A font name given in the XLFD format may
1695 contain wildcard characters:
1696 the * character matches any substring, and
1697 the ? character matches any single character.
1698 PATTERN is case-insensitive.
1700 The return value is a list of strings, suitable as arguments to
1701 `set-face-font'.
1703 Fonts Emacs can't use may or may not be excluded
1704 even if they match PATTERN and FACE.
1705 The optional fourth argument MAXIMUM sets a limit on how many
1706 fonts to match. The first MAXIMUM fonts are reported.
1707 The optional fifth argument WIDTH, if specified, is a number of columns
1708 occupied by a character of a font. In that case, return only fonts
1709 the WIDTH times as wide as FACE on FRAME. */)
1710 (Lisp_Object pattern, Lisp_Object face, Lisp_Object frame,
1711 Lisp_Object maximum, Lisp_Object width)
1713 struct frame *f;
1714 int size, avgwidth IF_LINT (= 0);
1716 check_x ();
1717 CHECK_STRING (pattern);
1719 if (! NILP (maximum))
1720 CHECK_NATNUM (maximum);
1722 if (!NILP (width))
1723 CHECK_NUMBER (width);
1725 /* We can't simply call check_x_frame because this function may be
1726 called before any frame is created. */
1727 if (NILP (frame))
1728 frame = selected_frame;
1729 f = frame_or_selected_frame (frame, 2);
1730 if (! FRAME_WINDOW_P (f))
1732 /* Perhaps we have not yet created any frame. */
1733 f = NULL;
1734 frame = Qnil;
1735 face = Qnil;
1738 /* Determine the width standard for comparison with the fonts we find. */
1740 if (NILP (face))
1741 size = 0;
1742 else
1744 /* This is of limited utility since it works with character
1745 widths. Keep it for compatibility. --gerd. */
1746 int face_id = lookup_named_face (f, face, 0);
1747 struct face *width_face = (face_id < 0
1748 ? NULL
1749 : FACE_FROM_ID (f, face_id));
1751 if (width_face && width_face->font)
1753 size = width_face->font->pixel_size;
1754 avgwidth = width_face->font->average_width;
1756 else
1758 size = FRAME_FONT (f)->pixel_size;
1759 avgwidth = FRAME_FONT (f)->average_width;
1761 if (!NILP (width))
1762 avgwidth *= XINT (width);
1766 Lisp_Object font_spec;
1767 Lisp_Object args[2], tail;
1769 font_spec = font_spec_from_name (pattern);
1770 if (!FONTP (font_spec))
1771 signal_error ("Invalid font name", pattern);
1773 if (size)
1775 Ffont_put (font_spec, QCsize, make_number (size));
1776 Ffont_put (font_spec, QCavgwidth, make_number (avgwidth));
1778 args[0] = Flist_fonts (font_spec, frame, maximum, font_spec);
1779 for (tail = args[0]; CONSP (tail); tail = XCDR (tail))
1781 Lisp_Object font_entity;
1783 font_entity = XCAR (tail);
1784 if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
1785 || XINT (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
1786 && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
1788 /* This is a scalable font. For backward compatibility,
1789 we set the specified size. */
1790 font_entity = copy_font_spec (font_entity);
1791 ASET (font_entity, FONT_SIZE_INDEX,
1792 AREF (font_spec, FONT_SIZE_INDEX));
1794 XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
1796 if (NILP (frame))
1797 /* We don't have to check fontsets. */
1798 return args[0];
1799 args[1] = list_fontsets (f, pattern, size);
1800 return Fnconc (2, args);
1804 #endif /* HAVE_WINDOW_SYSTEM */
1807 /***********************************************************************
1808 Lisp Faces
1809 ***********************************************************************/
1811 /* Access face attributes of face LFACE, a Lisp vector. */
1813 #define LFACE_FAMILY(LFACE) AREF ((LFACE), LFACE_FAMILY_INDEX)
1814 #define LFACE_FOUNDRY(LFACE) AREF ((LFACE), LFACE_FOUNDRY_INDEX)
1815 #define LFACE_HEIGHT(LFACE) AREF ((LFACE), LFACE_HEIGHT_INDEX)
1816 #define LFACE_WEIGHT(LFACE) AREF ((LFACE), LFACE_WEIGHT_INDEX)
1817 #define LFACE_SLANT(LFACE) AREF ((LFACE), LFACE_SLANT_INDEX)
1818 #define LFACE_UNDERLINE(LFACE) AREF ((LFACE), LFACE_UNDERLINE_INDEX)
1819 #define LFACE_INVERSE(LFACE) AREF ((LFACE), LFACE_INVERSE_INDEX)
1820 #define LFACE_FOREGROUND(LFACE) AREF ((LFACE), LFACE_FOREGROUND_INDEX)
1821 #define LFACE_BACKGROUND(LFACE) AREF ((LFACE), LFACE_BACKGROUND_INDEX)
1822 #define LFACE_STIPPLE(LFACE) AREF ((LFACE), LFACE_STIPPLE_INDEX)
1823 #define LFACE_SWIDTH(LFACE) AREF ((LFACE), LFACE_SWIDTH_INDEX)
1824 #define LFACE_OVERLINE(LFACE) AREF ((LFACE), LFACE_OVERLINE_INDEX)
1825 #define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
1826 #define LFACE_BOX(LFACE) AREF ((LFACE), LFACE_BOX_INDEX)
1827 #define LFACE_FONT(LFACE) AREF ((LFACE), LFACE_FONT_INDEX)
1828 #define LFACE_INHERIT(LFACE) AREF ((LFACE), LFACE_INHERIT_INDEX)
1829 #define LFACE_FONTSET(LFACE) AREF ((LFACE), LFACE_FONTSET_INDEX)
1831 /* Non-zero if LFACE is a Lisp face. A Lisp face is a vector of size
1832 LFACE_VECTOR_SIZE which has the symbol `face' in slot 0. */
1834 #define LFACEP(LFACE) \
1835 (VECTORP (LFACE) \
1836 && ASIZE (LFACE) == LFACE_VECTOR_SIZE \
1837 && EQ (AREF (LFACE, 0), Qface))
1840 #ifdef GLYPH_DEBUG
1842 /* Check consistency of Lisp face attribute vector ATTRS. */
1844 static void
1845 check_lface_attrs (Lisp_Object *attrs)
1847 eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
1848 || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
1849 || STRINGP (attrs[LFACE_FAMILY_INDEX]));
1850 eassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
1851 || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX])
1852 || STRINGP (attrs[LFACE_FOUNDRY_INDEX]));
1853 eassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
1854 || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
1855 || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
1856 eassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
1857 || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
1858 || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
1859 || FLOATP (attrs[LFACE_HEIGHT_INDEX])
1860 || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
1861 eassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
1862 || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX])
1863 || SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
1864 eassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
1865 || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX])
1866 || SYMBOLP (attrs[LFACE_SLANT_INDEX]));
1867 eassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
1868 || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
1869 || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
1870 || STRINGP (attrs[LFACE_UNDERLINE_INDEX])
1871 || CONSP (attrs[LFACE_UNDERLINE_INDEX]));
1872 eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
1873 || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
1874 || SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
1875 || STRINGP (attrs[LFACE_OVERLINE_INDEX]));
1876 eassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
1877 || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
1878 || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX])
1879 || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX]));
1880 eassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
1881 || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX])
1882 || SYMBOLP (attrs[LFACE_BOX_INDEX])
1883 || STRINGP (attrs[LFACE_BOX_INDEX])
1884 || INTEGERP (attrs[LFACE_BOX_INDEX])
1885 || CONSP (attrs[LFACE_BOX_INDEX]));
1886 eassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
1887 || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX])
1888 || SYMBOLP (attrs[LFACE_INVERSE_INDEX]));
1889 eassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
1890 || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX])
1891 || STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
1892 eassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
1893 || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX])
1894 || STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
1895 eassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
1896 || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX])
1897 || NILP (attrs[LFACE_INHERIT_INDEX])
1898 || SYMBOLP (attrs[LFACE_INHERIT_INDEX])
1899 || CONSP (attrs[LFACE_INHERIT_INDEX]));
1900 #ifdef HAVE_WINDOW_SYSTEM
1901 eassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
1902 || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX])
1903 || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
1904 || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
1905 eassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
1906 || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
1907 || FONTP (attrs[LFACE_FONT_INDEX]));
1908 eassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
1909 || STRINGP (attrs[LFACE_FONTSET_INDEX])
1910 || NILP (attrs[LFACE_FONTSET_INDEX]));
1911 #endif
1915 /* Check consistency of attributes of Lisp face LFACE (a Lisp vector). */
1917 static void
1918 check_lface (Lisp_Object lface)
1920 if (!NILP (lface))
1922 eassert (LFACEP (lface));
1923 check_lface_attrs (XVECTOR (lface)->contents);
1927 #else /* not GLYPH_DEBUG */
1929 #define check_lface_attrs(attrs) (void) 0
1930 #define check_lface(lface) (void) 0
1932 #endif /* GLYPH_DEBUG */
1936 /* Face-merge cycle checking. */
1938 enum named_merge_point_kind
1940 NAMED_MERGE_POINT_NORMAL,
1941 NAMED_MERGE_POINT_REMAP
1944 /* A `named merge point' is simply a point during face-merging where we
1945 look up a face by name. We keep a stack of which named lookups we're
1946 currently processing so that we can easily detect cycles, using a
1947 linked- list of struct named_merge_point structures, typically
1948 allocated on the stack frame of the named lookup functions which are
1949 active (so no consing is required). */
1950 struct named_merge_point
1952 Lisp_Object face_name;
1953 enum named_merge_point_kind named_merge_point_kind;
1954 struct named_merge_point *prev;
1958 /* If a face merging cycle is detected for FACE_NAME, return 0,
1959 otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
1960 FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
1961 pointed to by NAMED_MERGE_POINTS, and return 1. */
1963 static inline int
1964 push_named_merge_point (struct named_merge_point *new_named_merge_point,
1965 Lisp_Object face_name,
1966 enum named_merge_point_kind named_merge_point_kind,
1967 struct named_merge_point **named_merge_points)
1969 struct named_merge_point *prev;
1971 for (prev = *named_merge_points; prev; prev = prev->prev)
1972 if (EQ (face_name, prev->face_name))
1974 if (prev->named_merge_point_kind == named_merge_point_kind)
1975 /* A cycle, so fail. */
1976 return 0;
1977 else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
1978 /* A remap `hides ' any previous normal merge points
1979 (because the remap means that it's actually different face),
1980 so as we know the current merge point must be normal, we
1981 can just assume it's OK. */
1982 break;
1985 new_named_merge_point->face_name = face_name;
1986 new_named_merge_point->named_merge_point_kind = named_merge_point_kind;
1987 new_named_merge_point->prev = *named_merge_points;
1989 *named_merge_points = new_named_merge_point;
1991 return 1;
1995 /* Resolve face name FACE_NAME. If FACE_NAME is a string, intern it
1996 to make it a symbol. If FACE_NAME is an alias for another face,
1997 return that face's name.
1999 Return default face in case of errors. */
2001 static Lisp_Object
2002 resolve_face_name (Lisp_Object face_name, int signal_p)
2004 Lisp_Object orig_face;
2005 Lisp_Object tortoise, hare;
2007 if (STRINGP (face_name))
2008 face_name = intern (SSDATA (face_name));
2010 if (NILP (face_name) || !SYMBOLP (face_name))
2011 return face_name;
2013 orig_face = face_name;
2014 tortoise = hare = face_name;
2016 while (1)
2018 face_name = hare;
2019 hare = Fget (hare, Qface_alias);
2020 if (NILP (hare) || !SYMBOLP (hare))
2021 break;
2023 face_name = hare;
2024 hare = Fget (hare, Qface_alias);
2025 if (NILP (hare) || !SYMBOLP (hare))
2026 break;
2028 tortoise = Fget (tortoise, Qface_alias);
2029 if (EQ (hare, tortoise))
2031 if (signal_p)
2032 xsignal1 (Qcircular_list, orig_face);
2033 return Qdefault;
2037 return face_name;
2041 /* Return the face definition of FACE_NAME on frame F. F null means
2042 return the definition for new frames. FACE_NAME may be a string or
2043 a symbol (apparently Emacs 20.2 allowed strings as face names in
2044 face text properties; Ediff uses that). If SIGNAL_P is non-zero,
2045 signal an error if FACE_NAME is not a valid face name. If SIGNAL_P
2046 is zero, value is nil if FACE_NAME is not a valid face name. */
2047 static inline Lisp_Object
2048 lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
2049 int signal_p)
2051 Lisp_Object lface;
2053 if (f)
2054 lface = assq_no_quit (face_name, FVAR (f, face_alist));
2055 else
2056 lface = assq_no_quit (face_name, Vface_new_frame_defaults);
2058 if (CONSP (lface))
2059 lface = XCDR (lface);
2060 else if (signal_p)
2061 signal_error ("Invalid face", face_name);
2063 check_lface (lface);
2065 return lface;
2068 /* Return the face definition of FACE_NAME on frame F. F null means
2069 return the definition for new frames. FACE_NAME may be a string or
2070 a symbol (apparently Emacs 20.2 allowed strings as face names in
2071 face text properties; Ediff uses that). If FACE_NAME is an alias
2072 for another face, return that face's definition. If SIGNAL_P is
2073 non-zero, signal an error if FACE_NAME is not a valid face name.
2074 If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
2075 name. */
2076 static inline Lisp_Object
2077 lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
2079 face_name = resolve_face_name (face_name, signal_p);
2080 return lface_from_face_name_no_resolve (f, face_name, signal_p);
2084 /* Get face attributes of face FACE_NAME from frame-local faces on
2085 frame F. Store the resulting attributes in ATTRS which must point
2086 to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If SIGNAL_P
2087 is non-zero, signal an error if FACE_NAME does not name a face.
2088 Otherwise, value is zero if FACE_NAME is not a face. */
2090 static inline int
2091 get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
2092 Lisp_Object *attrs, int signal_p)
2094 Lisp_Object lface;
2096 lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
2098 if (! NILP (lface))
2099 memcpy (attrs, XVECTOR (lface)->contents,
2100 LFACE_VECTOR_SIZE * sizeof *attrs);
2102 return !NILP (lface);
2105 /* Get face attributes of face FACE_NAME from frame-local faces on frame
2106 F. Store the resulting attributes in ATTRS which must point to a
2107 vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an
2108 alias for another face, use that face's definition. If SIGNAL_P is
2109 non-zero, signal an error if FACE_NAME does not name a face.
2110 Otherwise, value is zero if FACE_NAME is not a face. */
2112 static inline int
2113 get_lface_attributes (struct frame *f, Lisp_Object face_name,
2114 Lisp_Object *attrs, int signal_p,
2115 struct named_merge_point *named_merge_points)
2117 Lisp_Object face_remapping;
2119 face_name = resolve_face_name (face_name, signal_p);
2121 /* See if SYMBOL has been remapped to some other face (usually this
2122 is done buffer-locally). */
2123 face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
2124 if (CONSP (face_remapping))
2126 struct named_merge_point named_merge_point;
2128 if (push_named_merge_point (&named_merge_point,
2129 face_name, NAMED_MERGE_POINT_REMAP,
2130 &named_merge_points))
2132 int i;
2134 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2135 attrs[i] = Qunspecified;
2137 return merge_face_ref (f, XCDR (face_remapping), attrs,
2138 signal_p, named_merge_points);
2142 /* Default case, no remapping. */
2143 return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
2147 /* Non-zero if all attributes in face attribute vector ATTRS are
2148 specified, i.e. are non-nil. */
2150 static int
2151 lface_fully_specified_p (Lisp_Object *attrs)
2153 int i;
2155 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2156 if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX)
2157 if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i])))
2158 break;
2160 return i == LFACE_VECTOR_SIZE;
2163 #ifdef HAVE_WINDOW_SYSTEM
2165 /* Set font-related attributes of Lisp face LFACE from FONT-OBJECT.
2166 If FORCE_P is zero, set only unspecified attributes of LFACE. The
2167 exception is `font' attribute. It is set to FONT_OBJECT regardless
2168 of FORCE_P. */
2170 static int
2171 set_lface_from_font (struct frame *f, Lisp_Object lface,
2172 Lisp_Object font_object, int force_p)
2174 Lisp_Object val;
2175 struct font *font = XFONT_OBJECT (font_object);
2177 /* Set attributes only if unspecified, otherwise face defaults for
2178 new frames would never take effect. If the font doesn't have a
2179 specific property, set a normal value for that. */
2181 if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
2183 Lisp_Object family = AREF (font_object, FONT_FAMILY_INDEX);
2185 ASET (lface, LFACE_FAMILY_INDEX, SYMBOL_NAME (family));
2188 if (force_p || UNSPECIFIEDP (LFACE_FOUNDRY (lface)))
2190 Lisp_Object foundry = AREF (font_object, FONT_FOUNDRY_INDEX);
2192 ASET (lface, LFACE_FOUNDRY_INDEX, SYMBOL_NAME (foundry));
2195 if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
2197 int pt = PIXEL_TO_POINT (font->pixel_size * 10, f->resy);
2199 eassert (pt > 0);
2200 ASET (lface, LFACE_HEIGHT_INDEX, make_number (pt));
2203 if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
2205 val = FONT_WEIGHT_FOR_FACE (font_object);
2206 ASET (lface, LFACE_WEIGHT_INDEX, ! NILP (val) ? val :Qnormal);
2208 if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
2210 val = FONT_SLANT_FOR_FACE (font_object);
2211 ASET (lface, LFACE_SLANT_INDEX, ! NILP (val) ? val : Qnormal);
2213 if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
2215 val = FONT_WIDTH_FOR_FACE (font_object);
2216 ASET (lface, LFACE_SWIDTH_INDEX, ! NILP (val) ? val : Qnormal);
2219 ASET (lface, LFACE_FONT_INDEX, font_object);
2220 return 1;
2223 #endif /* HAVE_WINDOW_SYSTEM */
2226 /* Merges the face height FROM with the face height TO, and returns the
2227 merged height. If FROM is an invalid height, then INVALID is
2228 returned instead. FROM and TO may be either absolute face heights or
2229 `relative' heights; the returned value is always an absolute height
2230 unless both FROM and TO are relative. */
2232 static Lisp_Object
2233 merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2235 Lisp_Object result = invalid;
2237 if (INTEGERP (from))
2238 /* FROM is absolute, just use it as is. */
2239 result = from;
2240 else if (FLOATP (from))
2241 /* FROM is a scale, use it to adjust TO. */
2243 if (INTEGERP (to))
2244 /* relative X absolute => absolute */
2245 result = make_number (XFLOAT_DATA (from) * XINT (to));
2246 else if (FLOATP (to))
2247 /* relative X relative => relative */
2248 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
2249 else if (UNSPECIFIEDP (to))
2250 result = from;
2252 else if (FUNCTIONP (from))
2253 /* FROM is a function, which use to adjust TO. */
2255 /* Call function with current height as argument.
2256 From is the new height. */
2257 result = safe_call1 (from, to);
2259 /* Ensure that if TO was absolute, so is the result. */
2260 if (INTEGERP (to) && !INTEGERP (result))
2261 result = invalid;
2264 return result;
2268 /* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
2269 store the resulting attributes in TO, which must be already be
2270 completely specified and contain only absolute attributes. Every
2271 specified attribute of FROM overrides the corresponding attribute of
2272 TO; relative attributes in FROM are merged with the absolute value in
2273 TO and replace it. NAMED_MERGE_POINTS is used internally to detect
2274 loops in face inheritance/remapping; it should be 0 when called from
2275 other places. */
2277 static inline void
2278 merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2279 struct named_merge_point *named_merge_points)
2281 int i;
2283 /* If FROM inherits from some other faces, merge their attributes into
2284 TO before merging FROM's direct attributes. Note that an :inherit
2285 attribute of `unspecified' is the same as one of nil; we never
2286 merge :inherit attributes, so nil is more correct, but lots of
2287 other code uses `unspecified' as a generic value for face attributes. */
2288 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2289 && !NILP (from[LFACE_INHERIT_INDEX]))
2290 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
2292 i = LFACE_FONT_INDEX;
2293 if (!UNSPECIFIEDP (from[i]))
2295 if (!UNSPECIFIEDP (to[i]))
2296 to[i] = merge_font_spec (from[i], to[i]);
2297 else
2298 to[i] = copy_font_spec (from[i]);
2299 if (! NILP (AREF (to[i], FONT_FOUNDRY_INDEX)))
2300 to[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FOUNDRY_INDEX));
2301 if (! NILP (AREF (to[i], FONT_FAMILY_INDEX)))
2302 to[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FAMILY_INDEX));
2303 if (! NILP (AREF (to[i], FONT_WEIGHT_INDEX)))
2304 to[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (to[i]);
2305 if (! NILP (AREF (to[i], FONT_SLANT_INDEX)))
2306 to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (to[i]);
2307 if (! NILP (AREF (to[i], FONT_WIDTH_INDEX)))
2308 to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (to[i]);
2309 ASET (to[i], FONT_SIZE_INDEX, Qnil);
2312 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2313 if (!UNSPECIFIEDP (from[i]))
2315 if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
2317 to[i] = merge_face_heights (from[i], to[i], to[i]);
2318 font_clear_prop (to, FONT_SIZE_INDEX);
2320 else if (i != LFACE_FONT_INDEX
2321 && ! EQ (to[i], from[i]))
2323 to[i] = from[i];
2324 if (i >= LFACE_FAMILY_INDEX && i <=LFACE_SLANT_INDEX)
2325 font_clear_prop (to,
2326 (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX
2327 : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX
2328 : i == LFACE_SWIDTH_INDEX ? FONT_WIDTH_INDEX
2329 : i == LFACE_HEIGHT_INDEX ? FONT_SIZE_INDEX
2330 : i == LFACE_WEIGHT_INDEX ? FONT_WEIGHT_INDEX
2331 : FONT_SLANT_INDEX));
2335 /* TO is always an absolute face, which should inherit from nothing.
2336 We blindly copy the :inherit attribute above and fix it up here. */
2337 to[LFACE_INHERIT_INDEX] = Qnil;
2340 /* Merge the named face FACE_NAME on frame F, into the vector of face
2341 attributes TO. NAMED_MERGE_POINTS is used to detect loops in face
2342 inheritance. Returns true if FACE_NAME is a valid face name and
2343 merging succeeded. */
2345 static int
2346 merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2347 struct named_merge_point *named_merge_points)
2349 struct named_merge_point named_merge_point;
2351 if (push_named_merge_point (&named_merge_point,
2352 face_name, NAMED_MERGE_POINT_NORMAL,
2353 &named_merge_points))
2355 struct gcpro gcpro1;
2356 Lisp_Object from[LFACE_VECTOR_SIZE];
2357 int ok = get_lface_attributes (f, face_name, from, 0, named_merge_points);
2359 if (ok)
2361 GCPRO1 (named_merge_point.face_name);
2362 merge_face_vectors (f, from, to, named_merge_points);
2363 UNGCPRO;
2366 return ok;
2368 else
2369 return 0;
2373 /* Merge face attributes from the lisp `face reference' FACE_REF on
2374 frame F into the face attribute vector TO. If ERR_MSGS is non-zero,
2375 problems with FACE_REF cause an error message to be shown. Return
2376 non-zero if no errors occurred (regardless of the value of ERR_MSGS).
2377 NAMED_MERGE_POINTS is used to detect loops in face inheritance or
2378 list structure; it may be 0 for most callers.
2380 FACE_REF may be a single face specification or a list of such
2381 specifications. Each face specification can be:
2383 1. A symbol or string naming a Lisp face.
2385 2. A property list of the form (KEYWORD VALUE ...) where each
2386 KEYWORD is a face attribute name, and value is an appropriate value
2387 for that attribute.
2389 3. Conses or the form (FOREGROUND-COLOR . COLOR) or
2390 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is
2391 for compatibility with 20.2.
2393 Face specifications earlier in lists take precedence over later
2394 specifications. */
2396 static int
2397 merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2398 int err_msgs, struct named_merge_point *named_merge_points)
2400 int ok = 1; /* Succeed without an error? */
2402 if (CONSP (face_ref))
2404 Lisp_Object first = XCAR (face_ref);
2406 if (EQ (first, Qforeground_color)
2407 || EQ (first, Qbackground_color))
2409 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
2410 . COLOR). COLOR must be a string. */
2411 Lisp_Object color_name = XCDR (face_ref);
2412 Lisp_Object color = first;
2414 if (STRINGP (color_name))
2416 if (EQ (color, Qforeground_color))
2417 to[LFACE_FOREGROUND_INDEX] = color_name;
2418 else
2419 to[LFACE_BACKGROUND_INDEX] = color_name;
2421 else
2423 if (err_msgs)
2424 add_to_log ("Invalid face color", color_name, Qnil);
2425 ok = 0;
2428 else if (SYMBOLP (first)
2429 && *SDATA (SYMBOL_NAME (first)) == ':')
2431 /* Assume this is the property list form. */
2432 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
2434 Lisp_Object keyword = XCAR (face_ref);
2435 Lisp_Object value = XCAR (XCDR (face_ref));
2436 int err = 0;
2438 /* Specifying `unspecified' is a no-op. */
2439 if (EQ (value, Qunspecified))
2441 else if (EQ (keyword, QCfamily))
2443 if (STRINGP (value))
2445 to[LFACE_FAMILY_INDEX] = value;
2446 font_clear_prop (to, FONT_FAMILY_INDEX);
2448 else
2449 err = 1;
2451 else if (EQ (keyword, QCfoundry))
2453 if (STRINGP (value))
2455 to[LFACE_FOUNDRY_INDEX] = value;
2456 font_clear_prop (to, FONT_FOUNDRY_INDEX);
2458 else
2459 err = 1;
2461 else if (EQ (keyword, QCheight))
2463 Lisp_Object new_height =
2464 merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil);
2466 if (! NILP (new_height))
2468 to[LFACE_HEIGHT_INDEX] = new_height;
2469 font_clear_prop (to, FONT_SIZE_INDEX);
2471 else
2472 err = 1;
2474 else if (EQ (keyword, QCweight))
2476 if (SYMBOLP (value) && FONT_WEIGHT_NAME_NUMERIC (value) >= 0)
2478 to[LFACE_WEIGHT_INDEX] = value;
2479 font_clear_prop (to, FONT_WEIGHT_INDEX);
2481 else
2482 err = 1;
2484 else if (EQ (keyword, QCslant))
2486 if (SYMBOLP (value) && FONT_SLANT_NAME_NUMERIC (value) >= 0)
2488 to[LFACE_SLANT_INDEX] = value;
2489 font_clear_prop (to, FONT_SLANT_INDEX);
2491 else
2492 err = 1;
2494 else if (EQ (keyword, QCunderline))
2496 if (EQ (value, Qt)
2497 || NILP (value)
2498 || STRINGP (value)
2499 || CONSP (value))
2500 to[LFACE_UNDERLINE_INDEX] = value;
2501 else
2502 err = 1;
2504 else if (EQ (keyword, QCoverline))
2506 if (EQ (value, Qt)
2507 || NILP (value)
2508 || STRINGP (value))
2509 to[LFACE_OVERLINE_INDEX] = value;
2510 else
2511 err = 1;
2513 else if (EQ (keyword, QCstrike_through))
2515 if (EQ (value, Qt)
2516 || NILP (value)
2517 || STRINGP (value))
2518 to[LFACE_STRIKE_THROUGH_INDEX] = value;
2519 else
2520 err = 1;
2522 else if (EQ (keyword, QCbox))
2524 if (EQ (value, Qt))
2525 value = make_number (1);
2526 if (INTEGERP (value)
2527 || STRINGP (value)
2528 || CONSP (value)
2529 || NILP (value))
2530 to[LFACE_BOX_INDEX] = value;
2531 else
2532 err = 1;
2534 else if (EQ (keyword, QCinverse_video)
2535 || EQ (keyword, QCreverse_video))
2537 if (EQ (value, Qt) || NILP (value))
2538 to[LFACE_INVERSE_INDEX] = value;
2539 else
2540 err = 1;
2542 else if (EQ (keyword, QCforeground))
2544 if (STRINGP (value))
2545 to[LFACE_FOREGROUND_INDEX] = value;
2546 else
2547 err = 1;
2549 else if (EQ (keyword, QCbackground))
2551 if (STRINGP (value))
2552 to[LFACE_BACKGROUND_INDEX] = value;
2553 else
2554 err = 1;
2556 else if (EQ (keyword, QCstipple))
2558 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
2559 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
2560 if (!NILP (pixmap_p))
2561 to[LFACE_STIPPLE_INDEX] = value;
2562 else
2563 err = 1;
2564 #endif
2566 else if (EQ (keyword, QCwidth))
2568 if (SYMBOLP (value) && FONT_WIDTH_NAME_NUMERIC (value) >= 0)
2570 to[LFACE_SWIDTH_INDEX] = value;
2571 font_clear_prop (to, FONT_WIDTH_INDEX);
2573 else
2574 err = 1;
2576 else if (EQ (keyword, QCinherit))
2578 /* This is not really very useful; it's just like a
2579 normal face reference. */
2580 if (! merge_face_ref (f, value, to,
2581 err_msgs, named_merge_points))
2582 err = 1;
2584 else
2585 err = 1;
2587 if (err)
2589 add_to_log ("Invalid face attribute %S %S", keyword, value);
2590 ok = 0;
2593 face_ref = XCDR (XCDR (face_ref));
2596 else
2598 /* This is a list of face refs. Those at the beginning of the
2599 list take precedence over what follows, so we have to merge
2600 from the end backwards. */
2601 Lisp_Object next = XCDR (face_ref);
2603 if (! NILP (next))
2604 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points);
2606 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points))
2607 ok = 0;
2610 else
2612 /* FACE_REF ought to be a face name. */
2613 ok = merge_named_face (f, face_ref, to, named_merge_points);
2614 if (!ok && err_msgs)
2615 add_to_log ("Invalid face reference: %s", face_ref, Qnil);
2618 return ok;
2622 DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
2623 Sinternal_make_lisp_face, 1, 2, 0,
2624 doc: /* Make FACE, a symbol, a Lisp face with all attributes nil.
2625 If FACE was not known as a face before, create a new one.
2626 If optional argument FRAME is specified, make a frame-local face
2627 for that frame. Otherwise operate on the global face definition.
2628 Value is a vector of face attributes. */)
2629 (Lisp_Object face, Lisp_Object frame)
2631 Lisp_Object global_lface, lface;
2632 struct frame *f;
2633 int i;
2635 CHECK_SYMBOL (face);
2636 global_lface = lface_from_face_name (NULL, face, 0);
2638 if (!NILP (frame))
2640 CHECK_LIVE_FRAME (frame);
2641 f = XFRAME (frame);
2642 lface = lface_from_face_name (f, face, 0);
2644 else
2645 f = NULL, lface = Qnil;
2647 /* Add a global definition if there is none. */
2648 if (NILP (global_lface))
2650 global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
2651 Qunspecified);
2652 ASET (global_lface, 0, Qface);
2653 Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
2654 Vface_new_frame_defaults);
2656 /* Assign the new Lisp face a unique ID. The mapping from Lisp
2657 face id to Lisp face is given by the vector lface_id_to_name.
2658 The mapping from Lisp face to Lisp face id is given by the
2659 property `face' of the Lisp face name. */
2660 if (next_lface_id == lface_id_to_name_size)
2661 lface_id_to_name =
2662 xpalloc (lface_id_to_name, &lface_id_to_name_size, 1, MAX_FACE_ID,
2663 sizeof *lface_id_to_name);
2665 lface_id_to_name[next_lface_id] = face;
2666 Fput (face, Qface, make_number (next_lface_id));
2667 ++next_lface_id;
2669 else if (f == NULL)
2670 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2671 ASET (global_lface, i, Qunspecified);
2673 /* Add a frame-local definition. */
2674 if (f)
2676 if (NILP (lface))
2678 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
2679 Qunspecified);
2680 ASET (lface, 0, Qface);
2681 FVAR (f, face_alist) = Fcons (Fcons (face, lface), FVAR (f,
2682 face_alist));
2684 else
2685 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2686 ASET (lface, i, Qunspecified);
2688 else
2689 lface = global_lface;
2691 /* Changing a named face means that all realized faces depending on
2692 that face are invalid. Since we cannot tell which realized faces
2693 depend on the face, make sure they are all removed. This is done
2694 by incrementing face_change_count. The next call to
2695 init_iterator will then free realized faces. */
2696 if (NILP (Fget (face, Qface_no_inherit)))
2698 ++face_change_count;
2699 ++windows_or_buffers_changed;
2702 eassert (LFACEP (lface));
2703 check_lface (lface);
2704 return lface;
2708 DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
2709 Sinternal_lisp_face_p, 1, 2, 0,
2710 doc: /* Return non-nil if FACE names a face.
2711 FACE should be a symbol or string.
2712 If optional second argument FRAME is non-nil, check for the
2713 existence of a frame-local face with name FACE on that frame.
2714 Otherwise check for the existence of a global face. */)
2715 (Lisp_Object face, Lisp_Object frame)
2717 Lisp_Object lface;
2719 face = resolve_face_name (face, 1);
2721 if (!NILP (frame))
2723 CHECK_LIVE_FRAME (frame);
2724 lface = lface_from_face_name (XFRAME (frame), face, 0);
2726 else
2727 lface = lface_from_face_name (NULL, face, 0);
2729 return lface;
2733 DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
2734 Sinternal_copy_lisp_face, 4, 4, 0,
2735 doc: /* Copy face FROM to TO.
2736 If FRAME is t, copy the global face definition of FROM.
2737 Otherwise, copy the frame-local definition of FROM on FRAME.
2738 If NEW-FRAME is a frame, copy that data into the frame-local
2739 definition of TO on NEW-FRAME. If NEW-FRAME is nil,
2740 FRAME controls where the data is copied to.
2742 The value is TO. */)
2743 (Lisp_Object from, Lisp_Object to, Lisp_Object frame, Lisp_Object new_frame)
2745 Lisp_Object lface, copy;
2747 CHECK_SYMBOL (from);
2748 CHECK_SYMBOL (to);
2750 if (EQ (frame, Qt))
2752 /* Copy global definition of FROM. We don't make copies of
2753 strings etc. because 20.2 didn't do it either. */
2754 lface = lface_from_face_name (NULL, from, 1);
2755 copy = Finternal_make_lisp_face (to, Qnil);
2757 else
2759 /* Copy frame-local definition of FROM. */
2760 if (NILP (new_frame))
2761 new_frame = frame;
2762 CHECK_LIVE_FRAME (frame);
2763 CHECK_LIVE_FRAME (new_frame);
2764 lface = lface_from_face_name (XFRAME (frame), from, 1);
2765 copy = Finternal_make_lisp_face (to, new_frame);
2768 memcpy (XVECTOR (copy)->contents, XVECTOR (lface)->contents,
2769 LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
2771 /* Changing a named face means that all realized faces depending on
2772 that face are invalid. Since we cannot tell which realized faces
2773 depend on the face, make sure they are all removed. This is done
2774 by incrementing face_change_count. The next call to
2775 init_iterator will then free realized faces. */
2776 if (NILP (Fget (to, Qface_no_inherit)))
2778 ++face_change_count;
2779 ++windows_or_buffers_changed;
2782 return to;
2786 DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
2787 Sinternal_set_lisp_face_attribute, 3, 4, 0,
2788 doc: /* Set attribute ATTR of FACE to VALUE.
2789 FRAME being a frame means change the face on that frame.
2790 FRAME nil means change the face of the selected frame.
2791 FRAME t means change the default for new frames.
2792 FRAME 0 means change the face on all frames, and change the default
2793 for new frames. */)
2794 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
2796 Lisp_Object lface;
2797 Lisp_Object old_value = Qnil;
2798 /* Set one of enum font_property_index (> 0) if ATTR is one of
2799 font-related attributes other than QCfont and QCfontset. */
2800 enum font_property_index prop_index = 0;
2802 CHECK_SYMBOL (face);
2803 CHECK_SYMBOL (attr);
2805 face = resolve_face_name (face, 1);
2807 /* If FRAME is 0, change face on all frames, and change the
2808 default for new frames. */
2809 if (INTEGERP (frame) && XINT (frame) == 0)
2811 Lisp_Object tail;
2812 Finternal_set_lisp_face_attribute (face, attr, value, Qt);
2813 FOR_EACH_FRAME (tail, frame)
2814 Finternal_set_lisp_face_attribute (face, attr, value, frame);
2815 return face;
2818 /* Set lface to the Lisp attribute vector of FACE. */
2819 if (EQ (frame, Qt))
2821 lface = lface_from_face_name (NULL, face, 1);
2823 /* When updating face-new-frame-defaults, we put :ignore-defface
2824 where the caller wants `unspecified'. This forces the frame
2825 defaults to ignore the defface value. Otherwise, the defface
2826 will take effect, which is generally not what is intended.
2827 The value of that attribute will be inherited from some other
2828 face during face merging. See internal_merge_in_global_face. */
2829 if (UNSPECIFIEDP (value))
2830 value = QCignore_defface;
2832 else
2834 if (NILP (frame))
2835 frame = selected_frame;
2837 CHECK_LIVE_FRAME (frame);
2838 lface = lface_from_face_name (XFRAME (frame), face, 0);
2840 /* If a frame-local face doesn't exist yet, create one. */
2841 if (NILP (lface))
2842 lface = Finternal_make_lisp_face (face, frame);
2845 if (EQ (attr, QCfamily))
2847 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2849 CHECK_STRING (value);
2850 if (SCHARS (value) == 0)
2851 signal_error ("Invalid face family", value);
2853 old_value = LFACE_FAMILY (lface);
2854 ASET (lface, LFACE_FAMILY_INDEX, value);
2855 prop_index = FONT_FAMILY_INDEX;
2857 else if (EQ (attr, QCfoundry))
2859 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2861 CHECK_STRING (value);
2862 if (SCHARS (value) == 0)
2863 signal_error ("Invalid face foundry", value);
2865 old_value = LFACE_FOUNDRY (lface);
2866 ASET (lface, LFACE_FOUNDRY_INDEX, value);
2867 prop_index = FONT_FOUNDRY_INDEX;
2869 else if (EQ (attr, QCheight))
2871 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2873 if (EQ (face, Qdefault))
2875 /* The default face must have an absolute size. */
2876 if (!INTEGERP (value) || XINT (value) <= 0)
2877 signal_error ("Default face height not absolute and positive",
2878 value);
2880 else
2882 /* For non-default faces, do a test merge with a random
2883 height to see if VALUE's ok. */
2884 Lisp_Object test = merge_face_heights (value,
2885 make_number (10),
2886 Qnil);
2887 if (!INTEGERP (test) || XINT (test) <= 0)
2888 signal_error ("Face height does not produce a positive integer",
2889 value);
2893 old_value = LFACE_HEIGHT (lface);
2894 ASET (lface, LFACE_HEIGHT_INDEX, value);
2895 prop_index = FONT_SIZE_INDEX;
2897 else if (EQ (attr, QCweight))
2899 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2901 CHECK_SYMBOL (value);
2902 if (FONT_WEIGHT_NAME_NUMERIC (value) < 0)
2903 signal_error ("Invalid face weight", value);
2905 old_value = LFACE_WEIGHT (lface);
2906 ASET (lface, LFACE_WEIGHT_INDEX, value);
2907 prop_index = FONT_WEIGHT_INDEX;
2909 else if (EQ (attr, QCslant))
2911 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2913 CHECK_SYMBOL (value);
2914 if (FONT_SLANT_NAME_NUMERIC (value) < 0)
2915 signal_error ("Invalid face slant", value);
2917 old_value = LFACE_SLANT (lface);
2918 ASET (lface, LFACE_SLANT_INDEX, value);
2919 prop_index = FONT_SLANT_INDEX;
2921 else if (EQ (attr, QCunderline))
2923 int valid_p = 0;
2925 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
2926 valid_p = 1;
2927 else if (NILP (value) || EQ (value, Qt))
2928 valid_p = 1;
2929 else if (STRINGP (value) && SCHARS (value) > 0)
2930 valid_p = 1;
2931 else if (CONSP (value))
2933 Lisp_Object key, val, list;
2935 list = value;
2936 valid_p = 1;
2938 while (!NILP (CAR_SAFE(list)))
2940 key = CAR_SAFE (list);
2941 list = CDR_SAFE (list);
2942 val = CAR_SAFE (list);
2943 list = CDR_SAFE (list);
2945 if (NILP (key) || NILP (val))
2947 valid_p = 0;
2948 break;
2951 else if (EQ (key, QCcolor)
2952 && !(EQ (val, Qforeground_color)
2953 || (STRINGP (val) && SCHARS (val) > 0)))
2955 valid_p = 0;
2956 break;
2959 else if (EQ (key, QCstyle)
2960 && !(EQ (val, Qline) || EQ (val, Qwave)))
2962 valid_p = 0;
2963 break;
2968 if (!valid_p)
2969 signal_error ("Invalid face underline", value);
2971 old_value = LFACE_UNDERLINE (lface);
2972 ASET (lface, LFACE_UNDERLINE_INDEX, value);
2974 else if (EQ (attr, QCoverline))
2976 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2977 if ((SYMBOLP (value)
2978 && !EQ (value, Qt)
2979 && !EQ (value, Qnil))
2980 /* Overline color. */
2981 || (STRINGP (value)
2982 && SCHARS (value) == 0))
2983 signal_error ("Invalid face overline", value);
2985 old_value = LFACE_OVERLINE (lface);
2986 ASET (lface, LFACE_OVERLINE_INDEX, value);
2988 else if (EQ (attr, QCstrike_through))
2990 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
2991 if ((SYMBOLP (value)
2992 && !EQ (value, Qt)
2993 && !EQ (value, Qnil))
2994 /* Strike-through color. */
2995 || (STRINGP (value)
2996 && SCHARS (value) == 0))
2997 signal_error ("Invalid face strike-through", value);
2999 old_value = LFACE_STRIKE_THROUGH (lface);
3000 ASET (lface, LFACE_STRIKE_THROUGH_INDEX, value);
3002 else if (EQ (attr, QCbox))
3004 int valid_p;
3006 /* Allow t meaning a simple box of width 1 in foreground color
3007 of the face. */
3008 if (EQ (value, Qt))
3009 value = make_number (1);
3011 if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
3012 valid_p = 1;
3013 else if (NILP (value))
3014 valid_p = 1;
3015 else if (INTEGERP (value))
3016 valid_p = XINT (value) != 0;
3017 else if (STRINGP (value))
3018 valid_p = SCHARS (value) > 0;
3019 else if (CONSP (value))
3021 Lisp_Object tem;
3023 tem = value;
3024 while (CONSP (tem))
3026 Lisp_Object k, v;
3028 k = XCAR (tem);
3029 tem = XCDR (tem);
3030 if (!CONSP (tem))
3031 break;
3032 v = XCAR (tem);
3033 tem = XCDR (tem);
3035 if (EQ (k, QCline_width))
3037 if (!INTEGERP (v) || XINT (v) == 0)
3038 break;
3040 else if (EQ (k, QCcolor))
3042 if (!NILP (v) && (!STRINGP (v) || SCHARS (v) == 0))
3043 break;
3045 else if (EQ (k, QCstyle))
3047 if (!EQ (v, Qpressed_button) && !EQ (v, Qreleased_button))
3048 break;
3050 else
3051 break;
3054 valid_p = NILP (tem);
3056 else
3057 valid_p = 0;
3059 if (!valid_p)
3060 signal_error ("Invalid face box", value);
3062 old_value = LFACE_BOX (lface);
3063 ASET (lface, LFACE_BOX_INDEX, value);
3065 else if (EQ (attr, QCinverse_video)
3066 || EQ (attr, QCreverse_video))
3068 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
3070 CHECK_SYMBOL (value);
3071 if (!EQ (value, Qt) && !NILP (value))
3072 signal_error ("Invalid inverse-video face attribute value", value);
3074 old_value = LFACE_INVERSE (lface);
3075 ASET (lface, LFACE_INVERSE_INDEX, value);
3077 else if (EQ (attr, QCforeground))
3079 /* Compatibility with 20.x. */
3080 if (NILP (value))
3081 value = Qunspecified;
3082 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
3084 /* Don't check for valid color names here because it depends
3085 on the frame (display) whether the color will be valid
3086 when the face is realized. */
3087 CHECK_STRING (value);
3088 if (SCHARS (value) == 0)
3089 signal_error ("Empty foreground color value", value);
3091 old_value = LFACE_FOREGROUND (lface);
3092 ASET (lface, LFACE_FOREGROUND_INDEX, value);
3094 else if (EQ (attr, QCbackground))
3096 /* Compatibility with 20.x. */
3097 if (NILP (value))
3098 value = Qunspecified;
3099 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
3101 /* Don't check for valid color names here because it depends
3102 on the frame (display) whether the color will be valid
3103 when the face is realized. */
3104 CHECK_STRING (value);
3105 if (SCHARS (value) == 0)
3106 signal_error ("Empty background color value", value);
3108 old_value = LFACE_BACKGROUND (lface);
3109 ASET (lface, LFACE_BACKGROUND_INDEX, value);
3111 else if (EQ (attr, QCstipple))
3113 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
3114 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
3115 && !NILP (value)
3116 && NILP (Fbitmap_spec_p (value)))
3117 signal_error ("Invalid stipple attribute", value);
3118 old_value = LFACE_STIPPLE (lface);
3119 ASET (lface, LFACE_STIPPLE_INDEX, value);
3120 #endif /* HAVE_X_WINDOWS || HAVE_NS */
3122 else if (EQ (attr, QCwidth))
3124 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
3126 CHECK_SYMBOL (value);
3127 if (FONT_WIDTH_NAME_NUMERIC (value) < 0)
3128 signal_error ("Invalid face width", value);
3130 old_value = LFACE_SWIDTH (lface);
3131 ASET (lface, LFACE_SWIDTH_INDEX, value);
3132 prop_index = FONT_WIDTH_INDEX;
3134 else if (EQ (attr, QCfont))
3136 #ifdef HAVE_WINDOW_SYSTEM
3137 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
3139 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
3141 FRAME_PTR f;
3143 old_value = LFACE_FONT (lface);
3144 if (! FONTP (value))
3146 if (STRINGP (value))
3148 Lisp_Object name = value;
3149 int fontset = fs_query_fontset (name, 0);
3151 if (fontset >= 0)
3152 name = fontset_ascii (fontset);
3153 value = font_spec_from_name (name);
3154 if (!FONTP (value))
3155 signal_error ("Invalid font name", name);
3157 else
3158 signal_error ("Invalid font or font-spec", value);
3160 if (EQ (frame, Qt))
3161 f = XFRAME (selected_frame);
3162 else
3163 f = XFRAME (frame);
3164 if (! FONT_OBJECT_P (value))
3166 Lisp_Object *attrs = XVECTOR (lface)->contents;
3167 Lisp_Object font_object;
3169 font_object = font_load_for_lface (f, attrs, value);
3170 if (NILP (font_object))
3171 signal_error ("Font not available", value);
3172 value = font_object;
3174 set_lface_from_font (f, lface, value, 1);
3176 else
3177 ASET (lface, LFACE_FONT_INDEX, value);
3179 #endif /* HAVE_WINDOW_SYSTEM */
3181 else if (EQ (attr, QCfontset))
3183 #ifdef HAVE_WINDOW_SYSTEM
3184 if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
3186 Lisp_Object tmp;
3188 old_value = LFACE_FONTSET (lface);
3189 tmp = Fquery_fontset (value, Qnil);
3190 if (NILP (tmp))
3191 signal_error ("Invalid fontset name", value);
3192 ASET (lface, LFACE_FONTSET_INDEX, value = tmp);
3194 #endif /* HAVE_WINDOW_SYSTEM */
3196 else if (EQ (attr, QCinherit))
3198 Lisp_Object tail;
3199 if (SYMBOLP (value))
3200 tail = Qnil;
3201 else
3202 for (tail = value; CONSP (tail); tail = XCDR (tail))
3203 if (!SYMBOLP (XCAR (tail)))
3204 break;
3205 if (NILP (tail))
3206 ASET (lface, LFACE_INHERIT_INDEX, value);
3207 else
3208 signal_error ("Invalid face inheritance", value);
3210 else if (EQ (attr, QCbold))
3212 old_value = LFACE_WEIGHT (lface);
3213 ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold);
3214 prop_index = FONT_WEIGHT_INDEX;
3216 else if (EQ (attr, QCitalic))
3218 attr = QCslant;
3219 old_value = LFACE_SLANT (lface);
3220 ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic);
3221 prop_index = FONT_SLANT_INDEX;
3223 else
3224 signal_error ("Invalid face attribute name", attr);
3226 if (prop_index)
3228 /* If a font-related attribute other than QCfont and QCfontset
3229 is specified, and if the original QCfont attribute has a font
3230 (font-spec or font-object), set the corresponding property in
3231 the font to nil so that the font selector doesn't think that
3232 the attribute is mandatory. Also, clear the average
3233 width. */
3234 font_clear_prop (XVECTOR (lface)->contents, prop_index);
3237 /* Changing a named face means that all realized faces depending on
3238 that face are invalid. Since we cannot tell which realized faces
3239 depend on the face, make sure they are all removed. This is done
3240 by incrementing face_change_count. The next call to
3241 init_iterator will then free realized faces. */
3242 if (!EQ (frame, Qt)
3243 && NILP (Fget (face, Qface_no_inherit))
3244 && NILP (Fequal (old_value, value)))
3246 ++face_change_count;
3247 ++windows_or_buffers_changed;
3250 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
3251 && NILP (Fequal (old_value, value)))
3253 Lisp_Object param;
3255 param = Qnil;
3257 if (EQ (face, Qdefault))
3259 #ifdef HAVE_WINDOW_SYSTEM
3260 /* Changed font-related attributes of the `default' face are
3261 reflected in changed `font' frame parameters. */
3262 if (FRAMEP (frame)
3263 && (prop_index || EQ (attr, QCfont))
3264 && lface_fully_specified_p (XVECTOR (lface)->contents))
3265 set_font_frame_param (frame, lface);
3266 else
3267 #endif /* HAVE_WINDOW_SYSTEM */
3269 if (EQ (attr, QCforeground))
3270 param = Qforeground_color;
3271 else if (EQ (attr, QCbackground))
3272 param = Qbackground_color;
3274 #ifdef HAVE_WINDOW_SYSTEM
3275 #ifndef WINDOWSNT
3276 else if (EQ (face, Qscroll_bar))
3278 /* Changing the colors of `scroll-bar' sets frame parameters
3279 `scroll-bar-foreground' and `scroll-bar-background'. */
3280 if (EQ (attr, QCforeground))
3281 param = Qscroll_bar_foreground;
3282 else if (EQ (attr, QCbackground))
3283 param = Qscroll_bar_background;
3285 #endif /* not WINDOWSNT */
3286 else if (EQ (face, Qborder))
3288 /* Changing background color of `border' sets frame parameter
3289 `border-color'. */
3290 if (EQ (attr, QCbackground))
3291 param = Qborder_color;
3293 else if (EQ (face, Qcursor))
3295 /* Changing background color of `cursor' sets frame parameter
3296 `cursor-color'. */
3297 if (EQ (attr, QCbackground))
3298 param = Qcursor_color;
3300 else if (EQ (face, Qmouse))
3302 /* Changing background color of `mouse' sets frame parameter
3303 `mouse-color'. */
3304 if (EQ (attr, QCbackground))
3305 param = Qmouse_color;
3307 #endif /* HAVE_WINDOW_SYSTEM */
3308 else if (EQ (face, Qmenu))
3310 /* Indicate that we have to update the menu bar when
3311 realizing faces on FRAME. FRAME t change the
3312 default for new frames. We do this by setting
3313 setting the flag in new face caches */
3314 if (FRAMEP (frame))
3316 struct frame *f = XFRAME (frame);
3317 if (FRAME_FACE_CACHE (f) == NULL)
3318 FRAME_FACE_CACHE (f) = make_face_cache (f);
3319 FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
3321 else
3322 menu_face_changed_default = 1;
3325 if (!NILP (param))
3327 if (EQ (frame, Qt))
3328 /* Update `default-frame-alist', which is used for new frames. */
3330 store_in_alist (&Vdefault_frame_alist, param, value);
3332 else
3333 /* Update the current frame's parameters. */
3335 Lisp_Object cons;
3336 cons = XCAR (Vparam_value_alist);
3337 XSETCAR (cons, param);
3338 XSETCDR (cons, value);
3339 Fmodify_frame_parameters (frame, Vparam_value_alist);
3344 return face;
3348 /* Update the corresponding face when frame parameter PARAM on frame F
3349 has been assigned the value NEW_VALUE. */
3351 void
3352 update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
3353 Lisp_Object new_value)
3355 Lisp_Object face = Qnil;
3356 Lisp_Object lface;
3358 /* If there are no faces yet, give up. This is the case when called
3359 from Fx_create_frame, and we do the necessary things later in
3360 face-set-after-frame-defaults. */
3361 if (NILP (FVAR (f, face_alist)))
3362 return;
3364 if (EQ (param, Qforeground_color))
3366 face = Qdefault;
3367 lface = lface_from_face_name (f, face, 1);
3368 ASET (lface, LFACE_FOREGROUND_INDEX,
3369 (STRINGP (new_value) ? new_value : Qunspecified));
3370 realize_basic_faces (f);
3372 else if (EQ (param, Qbackground_color))
3374 Lisp_Object frame;
3376 /* Changing the background color might change the background
3377 mode, so that we have to load new defface specs.
3378 Call frame-set-background-mode to do that. */
3379 XSETFRAME (frame, f);
3380 call1 (Qframe_set_background_mode, frame);
3382 face = Qdefault;
3383 lface = lface_from_face_name (f, face, 1);
3384 ASET (lface, LFACE_BACKGROUND_INDEX,
3385 (STRINGP (new_value) ? new_value : Qunspecified));
3386 realize_basic_faces (f);
3388 #ifdef HAVE_WINDOW_SYSTEM
3389 else if (EQ (param, Qborder_color))
3391 face = Qborder;
3392 lface = lface_from_face_name (f, face, 1);
3393 ASET (lface, LFACE_BACKGROUND_INDEX,
3394 (STRINGP (new_value) ? new_value : Qunspecified));
3396 else if (EQ (param, Qcursor_color))
3398 face = Qcursor;
3399 lface = lface_from_face_name (f, face, 1);
3400 ASET (lface, LFACE_BACKGROUND_INDEX,
3401 (STRINGP (new_value) ? new_value : Qunspecified));
3403 else if (EQ (param, Qmouse_color))
3405 face = Qmouse;
3406 lface = lface_from_face_name (f, face, 1);
3407 ASET (lface, LFACE_BACKGROUND_INDEX,
3408 (STRINGP (new_value) ? new_value : Qunspecified));
3410 #endif
3412 /* Changing a named face means that all realized faces depending on
3413 that face are invalid. Since we cannot tell which realized faces
3414 depend on the face, make sure they are all removed. This is done
3415 by incrementing face_change_count. The next call to
3416 init_iterator will then free realized faces. */
3417 if (!NILP (face)
3418 && NILP (Fget (face, Qface_no_inherit)))
3420 ++face_change_count;
3421 ++windows_or_buffers_changed;
3426 #ifdef HAVE_WINDOW_SYSTEM
3428 /* Set the `font' frame parameter of FRAME determined from the
3429 font-object set in `default' face attributes LFACE. */
3431 static void
3432 set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
3434 struct frame *f = XFRAME (frame);
3435 Lisp_Object font;
3437 if (FRAME_WINDOW_P (f)
3438 /* Don't do anything if the font is `unspecified'. This can
3439 happen during frame creation. */
3440 && (font = LFACE_FONT (lface),
3441 ! UNSPECIFIEDP (font)))
3443 if (FONT_SPEC_P (font))
3445 font = font_load_for_lface (f, XVECTOR (lface)->contents, font);
3446 if (NILP (font))
3447 return;
3448 ASET (lface, LFACE_FONT_INDEX, font);
3450 f->default_face_done_p = 0;
3451 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font), Qnil));
3456 /* Get the value of X resource RESOURCE, class CLASS for the display
3457 of frame FRAME. This is here because ordinary `x-get-resource'
3458 doesn't take a frame argument. */
3460 DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
3461 Sinternal_face_x_get_resource, 3, 3, 0, doc: /* */)
3462 (Lisp_Object resource, Lisp_Object class, Lisp_Object frame)
3464 Lisp_Object value = Qnil;
3465 CHECK_STRING (resource);
3466 CHECK_STRING (class);
3467 CHECK_LIVE_FRAME (frame);
3468 BLOCK_INPUT;
3469 value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
3470 resource, class, Qnil, Qnil);
3471 UNBLOCK_INPUT;
3472 return value;
3476 /* Return resource string VALUE as a boolean value, i.e. nil, or t.
3477 If VALUE is "on" or "true", return t. If VALUE is "off" or
3478 "false", return nil. Otherwise, if SIGNAL_P is non-zero, signal an
3479 error; if SIGNAL_P is zero, return 0. */
3481 static Lisp_Object
3482 face_boolean_x_resource_value (Lisp_Object value, int signal_p)
3484 Lisp_Object result = make_number (0);
3486 eassert (STRINGP (value));
3488 if (xstrcasecmp (SSDATA (value), "on") == 0
3489 || xstrcasecmp (SSDATA (value), "true") == 0)
3490 result = Qt;
3491 else if (xstrcasecmp (SSDATA (value), "off") == 0
3492 || xstrcasecmp (SSDATA (value), "false") == 0)
3493 result = Qnil;
3494 else if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
3495 result = Qunspecified;
3496 else if (signal_p)
3497 signal_error ("Invalid face attribute value from X resource", value);
3499 return result;
3503 DEFUN ("internal-set-lisp-face-attribute-from-resource",
3504 Finternal_set_lisp_face_attribute_from_resource,
3505 Sinternal_set_lisp_face_attribute_from_resource,
3506 3, 4, 0, doc: /* */)
3507 (Lisp_Object face, Lisp_Object attr, Lisp_Object value, Lisp_Object frame)
3509 CHECK_SYMBOL (face);
3510 CHECK_SYMBOL (attr);
3511 CHECK_STRING (value);
3513 if (xstrcasecmp (SSDATA (value), "unspecified") == 0)
3514 value = Qunspecified;
3515 else if (EQ (attr, QCheight))
3517 value = Fstring_to_number (value, make_number (10));
3518 if (XINT (value) <= 0)
3519 signal_error ("Invalid face height from X resource", value);
3521 else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
3522 value = face_boolean_x_resource_value (value, 1);
3523 else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
3524 value = intern (SSDATA (value));
3525 else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video))
3526 value = face_boolean_x_resource_value (value, 1);
3527 else if (EQ (attr, QCunderline)
3528 || EQ (attr, QCoverline)
3529 || EQ (attr, QCstrike_through))
3531 Lisp_Object boolean_value;
3533 /* If the result of face_boolean_x_resource_value is t or nil,
3534 VALUE does NOT specify a color. */
3535 boolean_value = face_boolean_x_resource_value (value, 0);
3536 if (SYMBOLP (boolean_value))
3537 value = boolean_value;
3539 else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
3540 value = Fcar (Fread_from_string (value, Qnil, Qnil));
3542 return Finternal_set_lisp_face_attribute (face, attr, value, frame);
3545 #endif /* HAVE_WINDOW_SYSTEM */
3548 /***********************************************************************
3549 Menu face
3550 ***********************************************************************/
3552 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
3554 /* Make menus on frame F appear as specified by the `menu' face. */
3556 static void
3557 x_update_menu_appearance (struct frame *f)
3559 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3560 XrmDatabase rdb;
3562 if (dpyinfo
3563 && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
3564 rdb != NULL))
3566 char line[512];
3567 char *buf = line;
3568 ptrdiff_t bufsize = sizeof line;
3569 Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
3570 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
3571 const char *myname = SSDATA (Vx_resource_name);
3572 int changed_p = 0;
3573 #ifdef USE_MOTIF
3574 const char *popup_path = "popup_menu";
3575 #else
3576 const char *popup_path = "menu.popup";
3577 #endif
3579 if (STRINGP (LFACE_FOREGROUND (lface)))
3581 exprintf (&buf, &bufsize, line, -1, "%s.%s*foreground: %s",
3582 myname, popup_path,
3583 SDATA (LFACE_FOREGROUND (lface)));
3584 XrmPutLineResource (&rdb, line);
3585 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s",
3586 myname, SDATA (LFACE_FOREGROUND (lface)));
3587 XrmPutLineResource (&rdb, line);
3588 changed_p = 1;
3591 if (STRINGP (LFACE_BACKGROUND (lface)))
3593 exprintf (&buf, &bufsize, line, -1, "%s.%s*background: %s",
3594 myname, popup_path,
3595 SDATA (LFACE_BACKGROUND (lface)));
3596 XrmPutLineResource (&rdb, line);
3598 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s",
3599 myname, SDATA (LFACE_BACKGROUND (lface)));
3600 XrmPutLineResource (&rdb, line);
3601 changed_p = 1;
3604 if (face->font
3605 /* On Solaris 5.8, it's been reported that the `menu' face
3606 can be unspecified here, during startup. Why this
3607 happens remains unknown. -- cyd */
3608 && FONTP (LFACE_FONT (lface))
3609 && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
3610 || !UNSPECIFIEDP (LFACE_FOUNDRY (lface))
3611 || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
3612 || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
3613 || !UNSPECIFIEDP (LFACE_SLANT (lface))
3614 || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
3616 Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
3617 #ifdef USE_MOTIF
3618 const char *suffix = "List";
3619 Bool motif = True;
3620 #else
3621 #if defined HAVE_X_I18N
3623 const char *suffix = "Set";
3624 #else
3625 const char *suffix = "";
3626 #endif
3627 Bool motif = False;
3628 #endif
3630 if (! NILP (xlfd))
3632 #if defined HAVE_X_I18N
3633 char *fontsetname = xic_create_fontsetname (SSDATA (xlfd), motif);
3634 #else
3635 char *fontsetname = SSDATA (xlfd);
3636 #endif
3637 exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*font%s: %s",
3638 myname, suffix, fontsetname);
3639 XrmPutLineResource (&rdb, line);
3641 exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s",
3642 myname, popup_path, suffix, fontsetname);
3643 XrmPutLineResource (&rdb, line);
3644 changed_p = 1;
3645 if (fontsetname != SSDATA (xlfd))
3646 xfree (fontsetname);
3650 if (changed_p && f->output_data.x->menubar_widget)
3651 free_frame_menubar (f);
3653 if (buf != line)
3654 xfree (buf);
3658 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
3661 DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
3662 Sface_attribute_relative_p,
3663 2, 2, 0,
3664 doc: /* Check whether a face attribute value is relative.
3665 Specifically, this function returns t if the attribute ATTRIBUTE
3666 with the value VALUE is relative.
3668 A relative value is one that doesn't entirely override whatever is
3669 inherited from another face. For most possible attributes,
3670 the only relative value that users see is `unspecified'.
3671 However, for :height, floating point values are also relative. */)
3672 (Lisp_Object attribute, Lisp_Object value)
3674 if (EQ (value, Qunspecified) || (EQ (value, QCignore_defface)))
3675 return Qt;
3676 else if (EQ (attribute, QCheight))
3677 return INTEGERP (value) ? Qnil : Qt;
3678 else
3679 return Qnil;
3682 DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
3683 3, 3, 0,
3684 doc: /* Return face ATTRIBUTE VALUE1 merged with VALUE2.
3685 If VALUE1 or VALUE2 are absolute (see `face-attribute-relative-p'), then
3686 the result will be absolute, otherwise it will be relative. */)
3687 (Lisp_Object attribute, Lisp_Object value1, Lisp_Object value2)
3689 if (EQ (value1, Qunspecified) || EQ (value1, QCignore_defface))
3690 return value2;
3691 else if (EQ (attribute, QCheight))
3692 return merge_face_heights (value1, value2, value1);
3693 else
3694 return value1;
3698 DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
3699 Sinternal_get_lisp_face_attribute,
3700 2, 3, 0,
3701 doc: /* Return face attribute KEYWORD of face SYMBOL.
3702 If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid
3703 face attribute name, signal an error.
3704 If the optional argument FRAME is given, report on face SYMBOL in that
3705 frame. If FRAME is t, report on the defaults for face SYMBOL (for new
3706 frames). If FRAME is omitted or nil, use the selected frame. */)
3707 (Lisp_Object symbol, Lisp_Object keyword, Lisp_Object frame)
3709 Lisp_Object lface, value = Qnil;
3711 CHECK_SYMBOL (symbol);
3712 CHECK_SYMBOL (keyword);
3714 if (EQ (frame, Qt))
3715 lface = lface_from_face_name (NULL, symbol, 1);
3716 else
3718 if (NILP (frame))
3719 frame = selected_frame;
3720 CHECK_LIVE_FRAME (frame);
3721 lface = lface_from_face_name (XFRAME (frame), symbol, 1);
3724 if (EQ (keyword, QCfamily))
3725 value = LFACE_FAMILY (lface);
3726 else if (EQ (keyword, QCfoundry))
3727 value = LFACE_FOUNDRY (lface);
3728 else if (EQ (keyword, QCheight))
3729 value = LFACE_HEIGHT (lface);
3730 else if (EQ (keyword, QCweight))
3731 value = LFACE_WEIGHT (lface);
3732 else if (EQ (keyword, QCslant))
3733 value = LFACE_SLANT (lface);
3734 else if (EQ (keyword, QCunderline))
3735 value = LFACE_UNDERLINE (lface);
3736 else if (EQ (keyword, QCoverline))
3737 value = LFACE_OVERLINE (lface);
3738 else if (EQ (keyword, QCstrike_through))
3739 value = LFACE_STRIKE_THROUGH (lface);
3740 else if (EQ (keyword, QCbox))
3741 value = LFACE_BOX (lface);
3742 else if (EQ (keyword, QCinverse_video)
3743 || EQ (keyword, QCreverse_video))
3744 value = LFACE_INVERSE (lface);
3745 else if (EQ (keyword, QCforeground))
3746 value = LFACE_FOREGROUND (lface);
3747 else if (EQ (keyword, QCbackground))
3748 value = LFACE_BACKGROUND (lface);
3749 else if (EQ (keyword, QCstipple))
3750 value = LFACE_STIPPLE (lface);
3751 else if (EQ (keyword, QCwidth))
3752 value = LFACE_SWIDTH (lface);
3753 else if (EQ (keyword, QCinherit))
3754 value = LFACE_INHERIT (lface);
3755 else if (EQ (keyword, QCfont))
3756 value = LFACE_FONT (lface);
3757 else if (EQ (keyword, QCfontset))
3758 value = LFACE_FONTSET (lface);
3759 else
3760 signal_error ("Invalid face attribute name", keyword);
3762 if (IGNORE_DEFFACE_P (value))
3763 return Qunspecified;
3765 return value;
3769 DEFUN ("internal-lisp-face-attribute-values",
3770 Finternal_lisp_face_attribute_values,
3771 Sinternal_lisp_face_attribute_values, 1, 1, 0,
3772 doc: /* Return a list of valid discrete values for face attribute ATTR.
3773 Value is nil if ATTR doesn't have a discrete set of valid values. */)
3774 (Lisp_Object attr)
3776 Lisp_Object result = Qnil;
3778 CHECK_SYMBOL (attr);
3780 if (EQ (attr, QCunderline))
3781 result = Fcons (Qt, Fcons (Qnil, Qnil));
3782 else if (EQ (attr, QCoverline))
3783 result = Fcons (Qt, Fcons (Qnil, Qnil));
3784 else if (EQ (attr, QCstrike_through))
3785 result = Fcons (Qt, Fcons (Qnil, Qnil));
3786 else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video))
3787 result = Fcons (Qt, Fcons (Qnil, Qnil));
3789 return result;
3793 DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
3794 Sinternal_merge_in_global_face, 2, 2, 0,
3795 doc: /* Add attributes from frame-default definition of FACE to FACE on FRAME.
3796 Default face attributes override any local face attributes. */)
3797 (Lisp_Object face, Lisp_Object frame)
3799 int i;
3800 Lisp_Object global_lface, local_lface, *gvec, *lvec;
3801 struct frame *f = XFRAME (frame);
3803 CHECK_LIVE_FRAME (frame);
3804 global_lface = lface_from_face_name (NULL, face, 1);
3805 local_lface = lface_from_face_name (f, face, 0);
3806 if (NILP (local_lface))
3807 local_lface = Finternal_make_lisp_face (face, frame);
3809 /* Make every specified global attribute override the local one.
3810 BEWARE!! This is only used from `face-set-after-frame-default' where
3811 the local frame is defined from default specs in `face-defface-spec'
3812 and those should be overridden by global settings. Hence the strange
3813 "global before local" priority. */
3814 lvec = XVECTOR (local_lface)->contents;
3815 gvec = XVECTOR (global_lface)->contents;
3816 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
3817 if (IGNORE_DEFFACE_P (gvec[i]))
3818 lvec[i] = Qunspecified;
3819 else if (! UNSPECIFIEDP (gvec[i]))
3820 lvec[i] = gvec[i];
3822 /* If the default face was changed, update the face cache and the
3823 `font' frame parameter. */
3824 if (EQ (face, Qdefault))
3826 struct face_cache *c = FRAME_FACE_CACHE (f);
3827 struct face *newface, *oldface = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3828 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3830 /* This can be NULL (e.g., in batch mode). */
3831 if (oldface)
3833 /* Ensure that the face vector is fully specified by merging
3834 the previously-cached vector. */
3835 memcpy (attrs, oldface->lface, sizeof attrs);
3836 merge_face_vectors (f, lvec, attrs, 0);
3837 memcpy (lvec, attrs, sizeof attrs);
3838 newface = realize_face (c, lvec, DEFAULT_FACE_ID);
3840 if ((! UNSPECIFIEDP (gvec[LFACE_FAMILY_INDEX])
3841 || ! UNSPECIFIEDP (gvec[LFACE_FOUNDRY_INDEX])
3842 || ! UNSPECIFIEDP (gvec[LFACE_HEIGHT_INDEX])
3843 || ! UNSPECIFIEDP (gvec[LFACE_WEIGHT_INDEX])
3844 || ! UNSPECIFIEDP (gvec[LFACE_SLANT_INDEX])
3845 || ! UNSPECIFIEDP (gvec[LFACE_SWIDTH_INDEX])
3846 || ! UNSPECIFIEDP (gvec[LFACE_FONT_INDEX]))
3847 && newface->font)
3849 Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
3850 Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, name),
3851 Qnil));
3854 if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
3855 Fmodify_frame_parameters (frame,
3856 Fcons (Fcons (Qforeground_color,
3857 gvec[LFACE_FOREGROUND_INDEX]),
3858 Qnil));
3860 if (STRINGP (gvec[LFACE_BACKGROUND_INDEX]))
3861 Fmodify_frame_parameters (frame,
3862 Fcons (Fcons (Qbackground_color,
3863 gvec[LFACE_BACKGROUND_INDEX]),
3864 Qnil));
3868 return Qnil;
3872 /* The following function is implemented for compatibility with 20.2.
3873 The function is used in x-resolve-fonts when it is asked to
3874 return fonts with the same size as the font of a face. This is
3875 done in fontset.el. */
3877 DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
3878 doc: /* Return the font name of face FACE, or nil if it is unspecified.
3879 The font name is, by default, for ASCII characters.
3880 If the optional argument FRAME is given, report on face FACE in that frame.
3881 If FRAME is t, report on the defaults for face FACE (for new frames).
3882 The font default for a face is either nil, or a list
3883 of the form (bold), (italic) or (bold italic).
3884 If FRAME is omitted or nil, use the selected frame. And, in this case,
3885 if the optional third argument CHARACTER is given,
3886 return the font name used for CHARACTER. */)
3887 (Lisp_Object face, Lisp_Object frame, Lisp_Object character)
3889 if (EQ (frame, Qt))
3891 Lisp_Object result = Qnil;
3892 Lisp_Object lface = lface_from_face_name (NULL, face, 1);
3894 if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
3895 && !EQ (LFACE_WEIGHT (lface), Qnormal))
3896 result = Fcons (Qbold, result);
3898 if (!UNSPECIFIEDP (LFACE_SLANT (lface))
3899 && !EQ (LFACE_SLANT (lface), Qnormal))
3900 result = Fcons (Qitalic, result);
3902 return result;
3904 else
3906 struct frame *f = frame_or_selected_frame (frame, 1);
3907 int face_id = lookup_named_face (f, face, 1);
3908 struct face *fface = FACE_FROM_ID (f, face_id);
3910 if (! fface)
3911 return Qnil;
3912 #ifdef HAVE_WINDOW_SYSTEM
3913 if (FRAME_WINDOW_P (f) && !NILP (character))
3915 CHECK_CHARACTER (character);
3916 face_id = FACE_FOR_CHAR (f, fface, XINT (character), -1, Qnil);
3917 fface = FACE_FROM_ID (f, face_id);
3919 return (fface->font
3920 ? fface->font->props[FONT_NAME_INDEX]
3921 : Qnil);
3922 #else /* !HAVE_WINDOW_SYSTEM */
3923 return build_string (FRAME_MSDOS_P (f)
3924 ? "ms-dos"
3925 : FRAME_W32_P (f) ? "w32term"
3926 :"tty");
3927 #endif
3932 /* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
3933 all attributes are `equal'. Tries to be fast because this function
3934 is called quite often. */
3936 static inline int
3937 face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
3939 /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
3940 and the other is specified. */
3941 if (XTYPE (v1) != XTYPE (v2))
3942 return 0;
3944 if (EQ (v1, v2))
3945 return 1;
3947 switch (XTYPE (v1))
3949 case Lisp_String:
3950 if (SBYTES (v1) != SBYTES (v2))
3951 return 0;
3953 return memcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
3955 case_Lisp_Int:
3956 case Lisp_Symbol:
3957 return 0;
3959 default:
3960 return !NILP (Fequal (v1, v2));
3965 /* Compare face vectors V1 and V2 for equality. Value is non-zero if
3966 all attributes are `equal'. Tries to be fast because this function
3967 is called quite often. */
3969 static inline int
3970 lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
3972 int i, equal_p = 1;
3974 for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
3975 equal_p = face_attr_equal_p (v1[i], v2[i]);
3977 return equal_p;
3981 DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
3982 Sinternal_lisp_face_equal_p, 2, 3, 0,
3983 doc: /* True if FACE1 and FACE2 are equal.
3984 If the optional argument FRAME is given, report on FACE1 and FACE2 in that frame.
3985 If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames).
3986 If FRAME is omitted or nil, use the selected frame. */)
3987 (Lisp_Object face1, Lisp_Object face2, Lisp_Object frame)
3989 int equal_p;
3990 struct frame *f;
3991 Lisp_Object lface1, lface2;
3993 if (EQ (frame, Qt))
3994 f = NULL;
3995 else
3996 /* Don't use check_x_frame here because this function is called
3997 before X frames exist. At that time, if FRAME is nil,
3998 selected_frame will be used which is the frame dumped with
3999 Emacs. That frame is not an X frame. */
4000 f = frame_or_selected_frame (frame, 2);
4002 lface1 = lface_from_face_name (f, face1, 1);
4003 lface2 = lface_from_face_name (f, face2, 1);
4004 equal_p = lface_equal_p (XVECTOR (lface1)->contents,
4005 XVECTOR (lface2)->contents);
4006 return equal_p ? Qt : Qnil;
4010 DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
4011 Sinternal_lisp_face_empty_p, 1, 2, 0,
4012 doc: /* True if FACE has no attribute specified.
4013 If the optional argument FRAME is given, report on face FACE in that frame.
4014 If FRAME is t, report on the defaults for face FACE (for new frames).
4015 If FRAME is omitted or nil, use the selected frame. */)
4016 (Lisp_Object face, Lisp_Object frame)
4018 struct frame *f;
4019 Lisp_Object lface;
4020 int i;
4022 if (NILP (frame))
4023 frame = selected_frame;
4024 CHECK_LIVE_FRAME (frame);
4025 f = XFRAME (frame);
4027 if (EQ (frame, Qt))
4028 lface = lface_from_face_name (NULL, face, 1);
4029 else
4030 lface = lface_from_face_name (f, face, 1);
4032 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
4033 if (!UNSPECIFIEDP (AREF (lface, i)))
4034 break;
4036 return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
4040 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
4041 0, 1, 0,
4042 doc: /* Return an alist of frame-local faces defined on FRAME.
4043 For internal use only. */)
4044 (Lisp_Object frame)
4046 struct frame *f = frame_or_selected_frame (frame, 0);
4047 return FVAR (f, face_alist);
4051 /* Return a hash code for Lisp string STRING with case ignored. Used
4052 below in computing a hash value for a Lisp face. */
4054 static inline unsigned
4055 hash_string_case_insensitive (Lisp_Object string)
4057 const unsigned char *s;
4058 unsigned hash = 0;
4059 eassert (STRINGP (string));
4060 for (s = SDATA (string); *s; ++s)
4061 hash = (hash << 1) ^ tolower (*s);
4062 return hash;
4066 /* Return a hash code for face attribute vector V. */
4068 static inline unsigned
4069 lface_hash (Lisp_Object *v)
4071 return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
4072 ^ hash_string_case_insensitive (v[LFACE_FOUNDRY_INDEX])
4073 ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
4074 ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
4075 ^ XHASH (v[LFACE_WEIGHT_INDEX])
4076 ^ XHASH (v[LFACE_SLANT_INDEX])
4077 ^ XHASH (v[LFACE_SWIDTH_INDEX])
4078 ^ XHASH (v[LFACE_HEIGHT_INDEX]));
4082 /* Return non-zero if LFACE1 and LFACE2 specify the same font (without
4083 considering charsets/registries). They do if they specify the same
4084 family, point size, weight, width, slant, and font. Both
4085 LFACE1 and LFACE2 must be fully-specified. */
4087 static inline int
4088 lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
4090 eassert (lface_fully_specified_p (lface1)
4091 && lface_fully_specified_p (lface2));
4092 return (xstrcasecmp (SSDATA (lface1[LFACE_FAMILY_INDEX]),
4093 SSDATA (lface2[LFACE_FAMILY_INDEX])) == 0
4094 && xstrcasecmp (SSDATA (lface1[LFACE_FOUNDRY_INDEX]),
4095 SSDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
4096 && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
4097 && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
4098 && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
4099 && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
4100 && EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
4101 && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
4102 || (STRINGP (lface1[LFACE_FONTSET_INDEX])
4103 && STRINGP (lface2[LFACE_FONTSET_INDEX])
4104 && ! xstrcasecmp (SSDATA (lface1[LFACE_FONTSET_INDEX]),
4105 SSDATA (lface2[LFACE_FONTSET_INDEX]))))
4111 /***********************************************************************
4112 Realized Faces
4113 ***********************************************************************/
4115 /* Allocate and return a new realized face for Lisp face attribute
4116 vector ATTR. */
4118 static struct face *
4119 make_realized_face (Lisp_Object *attr)
4121 struct face *face = xzalloc (sizeof *face);
4122 face->ascii_face = face;
4123 memcpy (face->lface, attr, sizeof face->lface);
4124 return face;
4128 /* Free realized face FACE, including its X resources. FACE may
4129 be null. */
4131 static void
4132 free_realized_face (struct frame *f, struct face *face)
4134 if (face)
4136 #ifdef HAVE_WINDOW_SYSTEM
4137 if (FRAME_WINDOW_P (f))
4139 /* Free fontset of FACE if it is ASCII face. */
4140 if (face->fontset >= 0 && face == face->ascii_face)
4141 free_face_fontset (f, face);
4142 if (face->gc)
4144 BLOCK_INPUT;
4145 if (face->font)
4146 font_done_for_face (f, face);
4147 x_free_gc (f, face->gc);
4148 face->gc = 0;
4149 UNBLOCK_INPUT;
4152 free_face_colors (f, face);
4153 x_destroy_bitmap (f, face->stipple);
4155 #endif /* HAVE_WINDOW_SYSTEM */
4157 xfree (face);
4162 /* Prepare face FACE for subsequent display on frame F. This
4163 allocated GCs if they haven't been allocated yet or have been freed
4164 by clearing the face cache. */
4166 void
4167 prepare_face_for_display (struct frame *f, struct face *face)
4169 #ifdef HAVE_WINDOW_SYSTEM
4170 eassert (FRAME_WINDOW_P (f));
4172 if (face->gc == 0)
4174 XGCValues xgcv;
4175 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
4177 xgcv.foreground = face->foreground;
4178 xgcv.background = face->background;
4179 #ifdef HAVE_X_WINDOWS
4180 xgcv.graphics_exposures = False;
4181 #endif
4183 BLOCK_INPUT;
4184 #ifdef HAVE_X_WINDOWS
4185 if (face->stipple)
4187 xgcv.fill_style = FillOpaqueStippled;
4188 xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
4189 mask |= GCFillStyle | GCStipple;
4191 #endif
4192 face->gc = x_create_gc (f, mask, &xgcv);
4193 if (face->font)
4194 font_prepare_for_face (f, face);
4195 UNBLOCK_INPUT;
4197 #endif /* HAVE_WINDOW_SYSTEM */
4201 /* Returns the `distance' between the colors X and Y. */
4203 static int
4204 color_distance (XColor *x, XColor *y)
4206 /* This formula is from a paper titled `Colour metric' by Thiadmer Riemersma.
4207 Quoting from that paper:
4209 This formula has results that are very close to L*u*v* (with the
4210 modified lightness curve) and, more importantly, it is a more even
4211 algorithm: it does not have a range of colors where it suddenly
4212 gives far from optimal results.
4214 See <http://www.compuphase.com/cmetric.htm> for more info. */
4216 long r = (x->red - y->red) >> 8;
4217 long g = (x->green - y->green) >> 8;
4218 long b = (x->blue - y->blue) >> 8;
4219 long r_mean = (x->red + y->red) >> 9;
4221 return
4222 (((512 + r_mean) * r * r) >> 8)
4223 + 4 * g * g
4224 + (((767 - r_mean) * b * b) >> 8);
4228 DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 3, 0,
4229 doc: /* Return an integer distance between COLOR1 and COLOR2 on FRAME.
4230 COLOR1 and COLOR2 may be either strings containing the color name,
4231 or lists of the form (RED GREEN BLUE).
4232 If FRAME is unspecified or nil, the current frame is used. */)
4233 (Lisp_Object color1, Lisp_Object color2, Lisp_Object frame)
4235 struct frame *f;
4236 XColor cdef1, cdef2;
4238 if (NILP (frame))
4239 frame = selected_frame;
4240 CHECK_LIVE_FRAME (frame);
4241 f = XFRAME (frame);
4243 if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
4244 && !(STRINGP (color1) && defined_color (f, SSDATA (color1), &cdef1, 0)))
4245 signal_error ("Invalid color", color1);
4246 if (!(CONSP (color2) && parse_rgb_list (color2, &cdef2))
4247 && !(STRINGP (color2) && defined_color (f, SSDATA (color2), &cdef2, 0)))
4248 signal_error ("Invalid color", color2);
4250 return make_number (color_distance (&cdef1, &cdef2));
4254 /***********************************************************************
4255 Face Cache
4256 ***********************************************************************/
4258 /* Return a new face cache for frame F. */
4260 static struct face_cache *
4261 make_face_cache (struct frame *f)
4263 struct face_cache *c;
4264 int size;
4266 c = xzalloc (sizeof *c);
4267 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4268 c->buckets = xzalloc (size);
4269 c->size = 50;
4270 c->faces_by_id = xmalloc (c->size * sizeof *c->faces_by_id);
4271 c->f = f;
4272 c->menu_face_changed_p = menu_face_changed_default;
4273 return c;
4277 /* Clear out all graphics contexts for all realized faces, except for
4278 the basic faces. This should be done from time to time just to avoid
4279 keeping too many graphics contexts that are no longer needed. */
4281 static void
4282 clear_face_gcs (struct face_cache *c)
4284 if (c && FRAME_WINDOW_P (c->f))
4286 #ifdef HAVE_WINDOW_SYSTEM
4287 int i;
4288 for (i = BASIC_FACE_ID_SENTINEL; i < c->used; ++i)
4290 struct face *face = c->faces_by_id[i];
4291 if (face && face->gc)
4293 BLOCK_INPUT;
4294 if (face->font)
4295 font_done_for_face (c->f, face);
4296 x_free_gc (c->f, face->gc);
4297 face->gc = 0;
4298 UNBLOCK_INPUT;
4301 #endif /* HAVE_WINDOW_SYSTEM */
4306 /* Free all realized faces in face cache C, including basic faces.
4307 C may be null. If faces are freed, make sure the frame's current
4308 matrix is marked invalid, so that a display caused by an expose
4309 event doesn't try to use faces we destroyed. */
4311 static void
4312 free_realized_faces (struct face_cache *c)
4314 if (c && c->used)
4316 int i, size;
4317 struct frame *f = c->f;
4319 /* We must block input here because we can't process X events
4320 safely while only some faces are freed, or when the frame's
4321 current matrix still references freed faces. */
4322 BLOCK_INPUT;
4324 for (i = 0; i < c->used; ++i)
4326 free_realized_face (f, c->faces_by_id[i]);
4327 c->faces_by_id[i] = NULL;
4330 c->used = 0;
4331 size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4332 memset (c->buckets, 0, size);
4334 /* Must do a thorough redisplay the next time. Mark current
4335 matrices as invalid because they will reference faces freed
4336 above. This function is also called when a frame is
4337 destroyed. In this case, the root window of F is nil. */
4338 if (WINDOWP (FVAR (f, root_window)))
4340 clear_current_matrices (f);
4341 ++windows_or_buffers_changed;
4344 UNBLOCK_INPUT;
4349 /* Free all realized faces on FRAME or on all frames if FRAME is nil.
4350 This is done after attributes of a named face have been changed,
4351 because we can't tell which realized faces depend on that face. */
4353 void
4354 free_all_realized_faces (Lisp_Object frame)
4356 if (NILP (frame))
4358 Lisp_Object rest;
4359 FOR_EACH_FRAME (rest, frame)
4360 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4362 else
4363 free_realized_faces (FRAME_FACE_CACHE (XFRAME (frame)));
4367 /* Free face cache C and faces in it, including their X resources. */
4369 static void
4370 free_face_cache (struct face_cache *c)
4372 if (c)
4374 free_realized_faces (c);
4375 xfree (c->buckets);
4376 xfree (c->faces_by_id);
4377 xfree (c);
4382 /* Cache realized face FACE in face cache C. HASH is the hash value
4383 of FACE. If FACE is for ASCII characters (i.e. FACE->ascii_face ==
4384 FACE), insert the new face to the beginning of the collision list
4385 of the face hash table of C. Otherwise, add the new face to the
4386 end of the collision list. This way, lookup_face can quickly find
4387 that a requested face is not cached. */
4389 static void
4390 cache_face (struct face_cache *c, struct face *face, unsigned int hash)
4392 int i = hash % FACE_CACHE_BUCKETS_SIZE;
4394 face->hash = hash;
4396 if (face->ascii_face != face)
4398 struct face *last = c->buckets[i];
4399 if (last)
4401 while (last->next)
4402 last = last->next;
4403 last->next = face;
4404 face->prev = last;
4405 face->next = NULL;
4407 else
4409 c->buckets[i] = face;
4410 face->prev = face->next = NULL;
4413 else
4415 face->prev = NULL;
4416 face->next = c->buckets[i];
4417 if (face->next)
4418 face->next->prev = face;
4419 c->buckets[i] = face;
4422 /* Find a free slot in C->faces_by_id and use the index of the free
4423 slot as FACE->id. */
4424 for (i = 0; i < c->used; ++i)
4425 if (c->faces_by_id[i] == NULL)
4426 break;
4427 face->id = i;
4429 #ifdef GLYPH_DEBUG
4430 /* Check that FACE got a unique id. */
4432 int j, n;
4433 struct face *face1;
4435 for (j = n = 0; j < FACE_CACHE_BUCKETS_SIZE; ++j)
4436 for (face1 = c->buckets[j]; face1; face1 = face1->next)
4437 if (face1->id == i)
4438 ++n;
4440 eassert (n == 1);
4442 #endif /* GLYPH_DEBUG */
4444 /* Maybe enlarge C->faces_by_id. */
4445 if (i == c->used)
4447 if (c->used == c->size)
4448 c->faces_by_id = xpalloc (c->faces_by_id, &c->size, 1, MAX_FACE_ID,
4449 sizeof *c->faces_by_id);
4450 c->used++;
4453 c->faces_by_id[i] = face;
4457 /* Remove face FACE from cache C. */
4459 static void
4460 uncache_face (struct face_cache *c, struct face *face)
4462 int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
4464 if (face->prev)
4465 face->prev->next = face->next;
4466 else
4467 c->buckets[i] = face->next;
4469 if (face->next)
4470 face->next->prev = face->prev;
4472 c->faces_by_id[face->id] = NULL;
4473 if (face->id == c->used)
4474 --c->used;
4478 /* Look up a realized face with face attributes ATTR in the face cache
4479 of frame F. The face will be used to display ASCII characters.
4480 Value is the ID of the face found. If no suitable face is found,
4481 realize a new one. */
4483 static inline int
4484 lookup_face (struct frame *f, Lisp_Object *attr)
4486 struct face_cache *cache = FRAME_FACE_CACHE (f);
4487 unsigned hash;
4488 int i;
4489 struct face *face;
4491 eassert (cache != NULL);
4492 check_lface_attrs (attr);
4494 /* Look up ATTR in the face cache. */
4495 hash = lface_hash (attr);
4496 i = hash % FACE_CACHE_BUCKETS_SIZE;
4498 for (face = cache->buckets[i]; face; face = face->next)
4500 if (face->ascii_face != face)
4502 /* There's no more ASCII face. */
4503 face = NULL;
4504 break;
4506 if (face->hash == hash
4507 && lface_equal_p (face->lface, attr))
4508 break;
4511 /* If not found, realize a new face. */
4512 if (face == NULL)
4513 face = realize_face (cache, attr, -1);
4515 #ifdef GLYPH_DEBUG
4516 eassert (face == FACE_FROM_ID (f, face->id));
4517 #endif /* GLYPH_DEBUG */
4519 return face->id;
4522 #ifdef HAVE_WINDOW_SYSTEM
4523 /* Look up a realized face that has the same attributes as BASE_FACE
4524 except for the font in the face cache of frame F. If FONT-OBJECT
4525 is not nil, it is an already opened font. If FONT-OBJECT is nil,
4526 the face has no font. Value is the ID of the face found. If no
4527 suitable face is found, realize a new one. */
4530 face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
4532 struct face_cache *cache = FRAME_FACE_CACHE (f);
4533 unsigned hash;
4534 int i;
4535 struct face *face;
4537 eassert (cache != NULL);
4538 base_face = base_face->ascii_face;
4539 hash = lface_hash (base_face->lface);
4540 i = hash % FACE_CACHE_BUCKETS_SIZE;
4542 for (face = cache->buckets[i]; face; face = face->next)
4544 if (face->ascii_face == face)
4545 continue;
4546 if (face->ascii_face == base_face
4547 && face->font == (NILP (font_object) ? NULL
4548 : XFONT_OBJECT (font_object))
4549 && lface_equal_p (face->lface, base_face->lface))
4550 return face->id;
4553 /* If not found, realize a new face. */
4554 face = realize_non_ascii_face (f, font_object, base_face);
4555 return face->id;
4557 #endif /* HAVE_WINDOW_SYSTEM */
4559 /* Return the face id of the realized face for named face SYMBOL on
4560 frame F suitable for displaying ASCII characters. Value is -1 if
4561 the face couldn't be determined, which might happen if the default
4562 face isn't realized and cannot be realized. */
4565 lookup_named_face (struct frame *f, Lisp_Object symbol, int signal_p)
4567 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4568 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
4569 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4571 if (default_face == NULL)
4573 if (!realize_basic_faces (f))
4574 return -1;
4575 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4576 if (default_face == NULL)
4577 abort (); /* realize_basic_faces must have set it up */
4580 if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
4581 return -1;
4583 memcpy (attrs, default_face->lface, sizeof attrs);
4584 merge_face_vectors (f, symbol_attrs, attrs, 0);
4586 return lookup_face (f, attrs);
4590 /* Return the display face-id of the basic face whose canonical face-id
4591 is FACE_ID. The return value will usually simply be FACE_ID, unless that
4592 basic face has bee remapped via Vface_remapping_alist. This function is
4593 conservative: if something goes wrong, it will simply return FACE_ID
4594 rather than signal an error. */
4597 lookup_basic_face (struct frame *f, int face_id)
4599 Lisp_Object name, mapping;
4600 int remapped_face_id;
4602 if (NILP (Vface_remapping_alist))
4603 return face_id; /* Nothing to do. */
4605 switch (face_id)
4607 case DEFAULT_FACE_ID: name = Qdefault; break;
4608 case MODE_LINE_FACE_ID: name = Qmode_line; break;
4609 case MODE_LINE_INACTIVE_FACE_ID: name = Qmode_line_inactive; break;
4610 case HEADER_LINE_FACE_ID: name = Qheader_line; break;
4611 case TOOL_BAR_FACE_ID: name = Qtool_bar; break;
4612 case FRINGE_FACE_ID: name = Qfringe; break;
4613 case SCROLL_BAR_FACE_ID: name = Qscroll_bar; break;
4614 case BORDER_FACE_ID: name = Qborder; break;
4615 case CURSOR_FACE_ID: name = Qcursor; break;
4616 case MOUSE_FACE_ID: name = Qmouse; break;
4617 case MENU_FACE_ID: name = Qmenu; break;
4619 default:
4620 abort (); /* the caller is supposed to pass us a basic face id */
4623 /* Do a quick scan through Vface_remapping_alist, and return immediately
4624 if there is no remapping for face NAME. This is just an optimization
4625 for the very common no-remapping case. */
4626 mapping = assq_no_quit (name, Vface_remapping_alist);
4627 if (NILP (mapping))
4628 return face_id; /* Give up. */
4630 /* If there is a remapping entry, lookup the face using NAME, which will
4631 handle the remapping too. */
4632 remapped_face_id = lookup_named_face (f, name, 0);
4633 if (remapped_face_id < 0)
4634 return face_id; /* Give up. */
4636 return remapped_face_id;
4640 /* Return a face for charset ASCII that is like the face with id
4641 FACE_ID on frame F, but has a font that is STEPS steps smaller.
4642 STEPS < 0 means larger. Value is the id of the face. */
4645 smaller_face (struct frame *f, int face_id, int steps)
4647 #ifdef HAVE_WINDOW_SYSTEM
4648 struct face *face;
4649 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4650 int pt, last_pt, last_height;
4651 int delta;
4652 int new_face_id;
4653 struct face *new_face;
4655 /* If not called for an X frame, just return the original face. */
4656 if (FRAME_TERMCAP_P (f))
4657 return face_id;
4659 /* Try in increments of 1/2 pt. */
4660 delta = steps < 0 ? 5 : -5;
4661 steps = eabs (steps);
4663 face = FACE_FROM_ID (f, face_id);
4664 memcpy (attrs, face->lface, sizeof attrs);
4665 pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
4666 new_face_id = face_id;
4667 last_height = FONT_HEIGHT (face->font);
4669 while (steps
4670 && pt + delta > 0
4671 /* Give up if we cannot find a font within 10pt. */
4672 && eabs (last_pt - pt) < 100)
4674 /* Look up a face for a slightly smaller/larger font. */
4675 pt += delta;
4676 attrs[LFACE_HEIGHT_INDEX] = make_number (pt);
4677 new_face_id = lookup_face (f, attrs);
4678 new_face = FACE_FROM_ID (f, new_face_id);
4680 /* If height changes, count that as one step. */
4681 if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
4682 || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
4684 --steps;
4685 last_height = FONT_HEIGHT (new_face->font);
4686 last_pt = pt;
4690 return new_face_id;
4692 #else /* not HAVE_WINDOW_SYSTEM */
4694 return face_id;
4696 #endif /* not HAVE_WINDOW_SYSTEM */
4700 /* Return a face for charset ASCII that is like the face with id
4701 FACE_ID on frame F, but has height HEIGHT. */
4704 face_with_height (struct frame *f, int face_id, int height)
4706 #ifdef HAVE_WINDOW_SYSTEM
4707 struct face *face;
4708 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4710 if (FRAME_TERMCAP_P (f)
4711 || height <= 0)
4712 return face_id;
4714 face = FACE_FROM_ID (f, face_id);
4715 memcpy (attrs, face->lface, sizeof attrs);
4716 attrs[LFACE_HEIGHT_INDEX] = make_number (height);
4717 font_clear_prop (attrs, FONT_SIZE_INDEX);
4718 face_id = lookup_face (f, attrs);
4719 #endif /* HAVE_WINDOW_SYSTEM */
4721 return face_id;
4725 /* Return the face id of the realized face for named face SYMBOL on
4726 frame F suitable for displaying ASCII characters, and use
4727 attributes of the face FACE_ID for attributes that aren't
4728 completely specified by SYMBOL. This is like lookup_named_face,
4729 except that the default attributes come from FACE_ID, not from the
4730 default face. FACE_ID is assumed to be already realized. */
4733 lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id,
4734 int signal_p)
4736 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4737 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
4738 struct face *default_face = FACE_FROM_ID (f, face_id);
4740 if (!default_face)
4741 abort ();
4743 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
4744 return -1;
4746 memcpy (attrs, default_face->lface, sizeof attrs);
4747 merge_face_vectors (f, symbol_attrs, attrs, 0);
4748 return lookup_face (f, attrs);
4751 DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
4752 Sface_attributes_as_vector, 1, 1, 0,
4753 doc: /* Return a vector of face attributes corresponding to PLIST. */)
4754 (Lisp_Object plist)
4756 Lisp_Object lface;
4757 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4758 Qunspecified);
4759 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents,
4760 1, 0);
4761 return lface;
4766 /***********************************************************************
4767 Face capability testing
4768 ***********************************************************************/
4771 /* If the distance (as returned by color_distance) between two colors is
4772 less than this, then they are considered the same, for determining
4773 whether a color is supported or not. The range of values is 0-65535. */
4775 #define TTY_SAME_COLOR_THRESHOLD 10000
4777 #ifdef HAVE_WINDOW_SYSTEM
4779 /* Return non-zero if all the face attributes in ATTRS are supported
4780 on the window-system frame F.
4782 The definition of `supported' is somewhat heuristic, but basically means
4783 that a face containing all the attributes in ATTRS, when merged with the
4784 default face for display, can be represented in a way that's
4786 \(1) different in appearance than the default face, and
4787 \(2) `close in spirit' to what the attributes specify, if not exact. */
4789 static int
4790 x_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
4791 struct face *def_face)
4793 Lisp_Object *def_attrs = def_face->lface;
4795 /* Check that other specified attributes are different that the default
4796 face. */
4797 if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
4798 && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
4799 def_attrs[LFACE_UNDERLINE_INDEX]))
4800 || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
4801 && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
4802 def_attrs[LFACE_INVERSE_INDEX]))
4803 || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
4804 && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
4805 def_attrs[LFACE_FOREGROUND_INDEX]))
4806 || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
4807 && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
4808 def_attrs[LFACE_BACKGROUND_INDEX]))
4809 || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
4810 && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
4811 def_attrs[LFACE_STIPPLE_INDEX]))
4812 || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
4813 && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
4814 def_attrs[LFACE_OVERLINE_INDEX]))
4815 || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
4816 && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
4817 def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
4818 || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
4819 && face_attr_equal_p (attrs[LFACE_BOX_INDEX],
4820 def_attrs[LFACE_BOX_INDEX])))
4821 return 0;
4823 /* Check font-related attributes, as those are the most commonly
4824 "unsupported" on a window-system (because of missing fonts). */
4825 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
4826 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
4827 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
4828 || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
4829 || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
4830 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]))
4832 int face_id;
4833 struct face *face;
4834 Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
4835 int i;
4837 memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
4839 merge_face_vectors (f, attrs, merged_attrs, 0);
4841 face_id = lookup_face (f, merged_attrs);
4842 face = FACE_FROM_ID (f, face_id);
4844 if (! face)
4845 error ("Cannot make face");
4847 /* If the font is the same, or no font is found, then not
4848 supported. */
4849 if (face->font == def_face->font
4850 || ! face->font)
4851 return 0;
4852 for (i = FONT_TYPE_INDEX; i <= FONT_SIZE_INDEX; i++)
4853 if (! EQ (face->font->props[i], def_face->font->props[i]))
4855 Lisp_Object s1, s2;
4857 if (i < FONT_FOUNDRY_INDEX || i > FONT_REGISTRY_INDEX
4858 || face->font->driver->case_sensitive)
4859 return 1;
4860 s1 = SYMBOL_NAME (face->font->props[i]);
4861 s2 = SYMBOL_NAME (def_face->font->props[i]);
4862 if (! EQ (Fcompare_strings (s1, make_number (0), Qnil,
4863 s2, make_number (0), Qnil, Qt), Qt))
4864 return 1;
4866 return 0;
4869 /* Everything checks out, this face is supported. */
4870 return 1;
4873 #endif /* HAVE_WINDOW_SYSTEM */
4875 /* Return non-zero if all the face attributes in ATTRS are supported
4876 on the tty frame F.
4878 The definition of `supported' is somewhat heuristic, but basically means
4879 that a face containing all the attributes in ATTRS, when merged
4880 with the default face for display, can be represented in a way that's
4882 \(1) different in appearance than the default face, and
4883 \(2) `close in spirit' to what the attributes specify, if not exact.
4885 Point (2) implies that a `:weight black' attribute will be satisfied
4886 by any terminal that can display bold, and a `:foreground "yellow"' as
4887 long as the terminal can display a yellowish color, but `:slant italic'
4888 will _not_ be satisfied by the tty display code's automatic
4889 substitution of a `dim' face for italic. */
4891 static int
4892 tty_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
4893 struct face *def_face)
4895 int weight, slant;
4896 Lisp_Object val, fg, bg;
4897 XColor fg_tty_color, fg_std_color;
4898 XColor bg_tty_color, bg_std_color;
4899 unsigned test_caps = 0;
4900 Lisp_Object *def_attrs = def_face->lface;
4902 /* First check some easy-to-check stuff; ttys support none of the
4903 following attributes, so we can just return false if any are requested
4904 (even if `nominal' values are specified, we should still return false,
4905 as that will be the same value that the default face uses). We
4906 consider :slant unsupportable on ttys, even though the face code
4907 actually `fakes' them using a dim attribute if possible. This is
4908 because the faked result is too different from what the face
4909 specifies. */
4910 if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
4911 || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
4912 || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
4913 || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
4914 || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
4915 || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
4916 || !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
4917 || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]))
4918 return 0;
4920 /* Test for terminal `capabilities' (non-color character attributes). */
4922 /* font weight (bold/dim) */
4923 val = attrs[LFACE_WEIGHT_INDEX];
4924 if (!UNSPECIFIEDP (val)
4925 && (weight = FONT_WEIGHT_NAME_NUMERIC (val), weight >= 0))
4927 int def_weight = FONT_WEIGHT_NAME_NUMERIC (def_attrs[LFACE_WEIGHT_INDEX]);
4929 if (weight > 100)
4931 if (def_weight > 100)
4932 return 0; /* same as default */
4933 test_caps = TTY_CAP_BOLD;
4935 else if (weight < 100)
4937 if (def_weight < 100)
4938 return 0; /* same as default */
4939 test_caps = TTY_CAP_DIM;
4941 else if (def_weight == 100)
4942 return 0; /* same as default */
4945 /* font slant */
4946 val = attrs[LFACE_SLANT_INDEX];
4947 if (!UNSPECIFIEDP (val)
4948 && (slant = FONT_SLANT_NAME_NUMERIC (val), slant >= 0))
4950 int def_slant = FONT_SLANT_NAME_NUMERIC (def_attrs[LFACE_SLANT_INDEX]);
4951 if (slant == 100 || slant == def_slant)
4952 return 0; /* same as default */
4953 else
4954 test_caps |= TTY_CAP_ITALIC;
4957 /* underlining */
4958 val = attrs[LFACE_UNDERLINE_INDEX];
4959 if (!UNSPECIFIEDP (val))
4961 if (STRINGP (val))
4962 return 0; /* ttys can't use colored underlines */
4963 else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
4964 return 0; /* same as default */
4965 else
4966 test_caps |= TTY_CAP_UNDERLINE;
4969 /* inverse video */
4970 val = attrs[LFACE_INVERSE_INDEX];
4971 if (!UNSPECIFIEDP (val))
4973 if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
4974 return 0; /* same as default */
4975 else
4976 test_caps |= TTY_CAP_INVERSE;
4980 /* Color testing. */
4982 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
4983 we use them when calling `tty_capable_p' below, even if the face
4984 specifies no colors. */
4985 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
4986 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
4988 /* Check if foreground color is close enough. */
4989 fg = attrs[LFACE_FOREGROUND_INDEX];
4990 if (STRINGP (fg))
4992 Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
4994 if (face_attr_equal_p (fg, def_fg))
4995 return 0; /* same as default */
4996 else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
4997 return 0; /* not a valid color */
4998 else if (color_distance (&fg_tty_color, &fg_std_color)
4999 > TTY_SAME_COLOR_THRESHOLD)
5000 return 0; /* displayed color is too different */
5001 else
5002 /* Make sure the color is really different than the default. */
5004 XColor def_fg_color;
5005 if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
5006 && (color_distance (&fg_tty_color, &def_fg_color)
5007 <= TTY_SAME_COLOR_THRESHOLD))
5008 return 0;
5012 /* Check if background color is close enough. */
5013 bg = attrs[LFACE_BACKGROUND_INDEX];
5014 if (STRINGP (bg))
5016 Lisp_Object def_bg = def_attrs[LFACE_BACKGROUND_INDEX];
5018 if (face_attr_equal_p (bg, def_bg))
5019 return 0; /* same as default */
5020 else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5021 return 0; /* not a valid color */
5022 else if (color_distance (&bg_tty_color, &bg_std_color)
5023 > TTY_SAME_COLOR_THRESHOLD)
5024 return 0; /* displayed color is too different */
5025 else
5026 /* Make sure the color is really different than the default. */
5028 XColor def_bg_color;
5029 if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
5030 && (color_distance (&bg_tty_color, &def_bg_color)
5031 <= TTY_SAME_COLOR_THRESHOLD))
5032 return 0;
5036 /* If both foreground and background are requested, see if the
5037 distance between them is OK. We just check to see if the distance
5038 between the tty's foreground and background is close enough to the
5039 distance between the standard foreground and background. */
5040 if (STRINGP (fg) && STRINGP (bg))
5042 int delta_delta
5043 = (color_distance (&fg_std_color, &bg_std_color)
5044 - color_distance (&fg_tty_color, &bg_tty_color));
5045 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5046 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5047 return 0;
5051 /* See if the capabilities we selected above are supported, with the
5052 given colors. */
5053 if (test_caps != 0 &&
5054 ! tty_capable_p (FRAME_TTY (f), test_caps, fg_tty_color.pixel,
5055 bg_tty_color.pixel))
5056 return 0;
5059 /* Hmmm, everything checks out, this terminal must support this face. */
5060 return 1;
5064 DEFUN ("display-supports-face-attributes-p",
5065 Fdisplay_supports_face_attributes_p, Sdisplay_supports_face_attributes_p,
5066 1, 2, 0,
5067 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
5068 The optional argument DISPLAY can be a display name, a frame, or
5069 nil (meaning the selected frame's display).
5071 The definition of `supported' is somewhat heuristic, but basically means
5072 that a face containing all the attributes in ATTRIBUTES, when merged
5073 with the default face for display, can be represented in a way that's
5075 \(1) different in appearance than the default face, and
5076 \(2) `close in spirit' to what the attributes specify, if not exact.
5078 Point (2) implies that a `:weight black' attribute will be satisfied by
5079 any display that can display bold, and a `:foreground \"yellow\"' as long
5080 as it can display a yellowish color, but `:slant italic' will _not_ be
5081 satisfied by the tty display code's automatic substitution of a `dim'
5082 face for italic. */)
5083 (Lisp_Object attributes, Lisp_Object display)
5085 int supports = 0, i;
5086 Lisp_Object frame;
5087 struct frame *f;
5088 struct face *def_face;
5089 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5091 if (noninteractive || !initialized)
5092 /* We may not be able to access low-level face information in batch
5093 mode, or before being dumped, and this function is not going to
5094 be very useful in those cases anyway, so just give up. */
5095 return Qnil;
5097 if (NILP (display))
5098 frame = selected_frame;
5099 else if (FRAMEP (display))
5100 frame = display;
5101 else
5103 /* Find any frame on DISPLAY. */
5104 Lisp_Object fl_tail;
5106 frame = Qnil;
5107 for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
5109 frame = XCAR (fl_tail);
5110 if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
5111 FVAR (XFRAME (frame), param_alist))),
5112 display)))
5113 break;
5117 CHECK_LIVE_FRAME (frame);
5118 f = XFRAME (frame);
5120 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
5121 attrs[i] = Qunspecified;
5122 merge_face_ref (f, attributes, attrs, 1, 0);
5124 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5125 if (def_face == NULL)
5127 if (! realize_basic_faces (f))
5128 error ("Cannot realize default face");
5129 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5130 if (def_face == NULL)
5131 abort (); /* realize_basic_faces must have set it up */
5134 /* Dispatch to the appropriate handler. */
5135 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
5136 supports = tty_supports_face_attributes_p (f, attrs, def_face);
5137 #ifdef HAVE_WINDOW_SYSTEM
5138 else
5139 supports = x_supports_face_attributes_p (f, attrs, def_face);
5140 #endif
5142 return supports ? Qt : Qnil;
5146 /***********************************************************************
5147 Font selection
5148 ***********************************************************************/
5150 DEFUN ("internal-set-font-selection-order",
5151 Finternal_set_font_selection_order,
5152 Sinternal_set_font_selection_order, 1, 1, 0,
5153 doc: /* Set font selection order for face font selection to ORDER.
5154 ORDER must be a list of length 4 containing the symbols `:width',
5155 `:height', `:weight', and `:slant'. Face attributes appearing
5156 first in ORDER are matched first, e.g. if `:height' appears before
5157 `:weight' in ORDER, font selection first tries to find a font with
5158 a suitable height, and then tries to match the font weight.
5159 Value is ORDER. */)
5160 (Lisp_Object order)
5162 Lisp_Object list;
5163 int i;
5164 int indices[DIM (font_sort_order)];
5166 CHECK_LIST (order);
5167 memset (indices, 0, sizeof indices);
5168 i = 0;
5170 for (list = order;
5171 CONSP (list) && i < DIM (indices);
5172 list = XCDR (list), ++i)
5174 Lisp_Object attr = XCAR (list);
5175 int xlfd;
5177 if (EQ (attr, QCwidth))
5178 xlfd = XLFD_SWIDTH;
5179 else if (EQ (attr, QCheight))
5180 xlfd = XLFD_POINT_SIZE;
5181 else if (EQ (attr, QCweight))
5182 xlfd = XLFD_WEIGHT;
5183 else if (EQ (attr, QCslant))
5184 xlfd = XLFD_SLANT;
5185 else
5186 break;
5188 if (indices[i] != 0)
5189 break;
5190 indices[i] = xlfd;
5193 if (!NILP (list) || i != DIM (indices))
5194 signal_error ("Invalid font sort order", order);
5195 for (i = 0; i < DIM (font_sort_order); ++i)
5196 if (indices[i] == 0)
5197 signal_error ("Invalid font sort order", order);
5199 if (memcmp (indices, font_sort_order, sizeof indices) != 0)
5201 memcpy (font_sort_order, indices, sizeof font_sort_order);
5202 free_all_realized_faces (Qnil);
5205 font_update_sort_order (font_sort_order);
5207 return Qnil;
5211 DEFUN ("internal-set-alternative-font-family-alist",
5212 Finternal_set_alternative_font_family_alist,
5213 Sinternal_set_alternative_font_family_alist, 1, 1, 0,
5214 doc: /* Define alternative font families to try in face font selection.
5215 ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
5216 Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
5217 be found. Value is ALIST. */)
5218 (Lisp_Object alist)
5220 Lisp_Object entry, tail, tail2;
5222 CHECK_LIST (alist);
5223 alist = Fcopy_sequence (alist);
5224 for (tail = alist; CONSP (tail); tail = XCDR (tail))
5226 entry = XCAR (tail);
5227 CHECK_LIST (entry);
5228 entry = Fcopy_sequence (entry);
5229 XSETCAR (tail, entry);
5230 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5231 XSETCAR (tail2, Fintern (XCAR (tail2), Qnil));
5234 Vface_alternative_font_family_alist = alist;
5235 free_all_realized_faces (Qnil);
5236 return alist;
5240 DEFUN ("internal-set-alternative-font-registry-alist",
5241 Finternal_set_alternative_font_registry_alist,
5242 Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
5243 doc: /* Define alternative font registries to try in face font selection.
5244 ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
5245 Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
5246 be found. Value is ALIST. */)
5247 (Lisp_Object alist)
5249 Lisp_Object entry, tail, tail2;
5251 CHECK_LIST (alist);
5252 alist = Fcopy_sequence (alist);
5253 for (tail = alist; CONSP (tail); tail = XCDR (tail))
5255 entry = XCAR (tail);
5256 CHECK_LIST (entry);
5257 entry = Fcopy_sequence (entry);
5258 XSETCAR (tail, entry);
5259 for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
5260 XSETCAR (tail2, Fdowncase (XCAR (tail2)));
5262 Vface_alternative_font_registry_alist = alist;
5263 free_all_realized_faces (Qnil);
5264 return alist;
5268 #ifdef HAVE_WINDOW_SYSTEM
5270 /* Return the fontset id of the base fontset name or alias name given
5271 by the fontset attribute of ATTRS. Value is -1 if the fontset
5272 attribute of ATTRS doesn't name a fontset. */
5274 static int
5275 face_fontset (Lisp_Object *attrs)
5277 Lisp_Object name;
5279 name = attrs[LFACE_FONTSET_INDEX];
5280 if (!STRINGP (name))
5281 return -1;
5282 return fs_query_fontset (name, 0);
5285 #endif /* HAVE_WINDOW_SYSTEM */
5289 /***********************************************************************
5290 Face Realization
5291 ***********************************************************************/
5293 /* Realize basic faces on frame F. Value is zero if frame parameters
5294 of F don't contain enough information needed to realize the default
5295 face. */
5297 static int
5298 realize_basic_faces (struct frame *f)
5300 int success_p = 0;
5301 ptrdiff_t count = SPECPDL_INDEX ();
5303 /* Block input here so that we won't be surprised by an X expose
5304 event, for instance, without having the faces set up. */
5305 BLOCK_INPUT;
5306 specbind (Qscalable_fonts_allowed, Qt);
5308 if (realize_default_face (f))
5310 realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
5311 realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
5312 realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
5313 realize_named_face (f, Qfringe, FRINGE_FACE_ID);
5314 realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
5315 realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
5316 realize_named_face (f, Qborder, BORDER_FACE_ID);
5317 realize_named_face (f, Qcursor, CURSOR_FACE_ID);
5318 realize_named_face (f, Qmouse, MOUSE_FACE_ID);
5319 realize_named_face (f, Qmenu, MENU_FACE_ID);
5320 realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
5322 /* Reflect changes in the `menu' face in menu bars. */
5323 if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
5325 FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
5326 #ifdef USE_X_TOOLKIT
5327 if (FRAME_WINDOW_P (f))
5328 x_update_menu_appearance (f);
5329 #endif
5332 success_p = 1;
5335 unbind_to (count, Qnil);
5336 UNBLOCK_INPUT;
5337 return success_p;
5341 /* Realize the default face on frame F. If the face is not fully
5342 specified, make it fully-specified. Attributes of the default face
5343 that are not explicitly specified are taken from frame parameters. */
5345 static int
5346 realize_default_face (struct frame *f)
5348 struct face_cache *c = FRAME_FACE_CACHE (f);
5349 Lisp_Object lface;
5350 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5351 struct face *face;
5353 /* If the `default' face is not yet known, create it. */
5354 lface = lface_from_face_name (f, Qdefault, 0);
5355 if (NILP (lface))
5357 Lisp_Object frame;
5358 XSETFRAME (frame, f);
5359 lface = Finternal_make_lisp_face (Qdefault, frame);
5362 #ifdef HAVE_WINDOW_SYSTEM
5363 if (FRAME_WINDOW_P (f))
5365 Lisp_Object font_object;
5367 XSETFONT (font_object, FRAME_FONT (f));
5368 set_lface_from_font (f, lface, font_object, f->default_face_done_p);
5369 ASET (lface, LFACE_FONTSET_INDEX, fontset_name (FRAME_FONTSET (f)));
5370 f->default_face_done_p = 1;
5372 #endif /* HAVE_WINDOW_SYSTEM */
5374 if (!FRAME_WINDOW_P (f))
5376 ASET (lface, LFACE_FAMILY_INDEX, build_string ("default"));
5377 ASET (lface, LFACE_FOUNDRY_INDEX, LFACE_FAMILY (lface));
5378 ASET (lface, LFACE_SWIDTH_INDEX, Qnormal);
5379 ASET (lface, LFACE_HEIGHT_INDEX, make_number (1));
5380 if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
5381 ASET (lface, LFACE_WEIGHT_INDEX, Qnormal);
5382 if (UNSPECIFIEDP (LFACE_SLANT (lface)))
5383 ASET (lface, LFACE_SLANT_INDEX, Qnormal);
5384 if (UNSPECIFIEDP (LFACE_FONTSET (lface)))
5385 ASET (lface, LFACE_FONTSET_INDEX, Qnil);
5388 if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
5389 ASET (lface, LFACE_UNDERLINE_INDEX, Qnil);
5391 if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
5392 ASET (lface, LFACE_OVERLINE_INDEX, Qnil);
5394 if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
5395 ASET (lface, LFACE_STRIKE_THROUGH_INDEX, Qnil);
5397 if (UNSPECIFIEDP (LFACE_BOX (lface)))
5398 ASET (lface, LFACE_BOX_INDEX, Qnil);
5400 if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
5401 ASET (lface, LFACE_INVERSE_INDEX, Qnil);
5403 if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
5405 /* This function is called so early that colors are not yet
5406 set in the frame parameter list. */
5407 Lisp_Object color = Fassq (Qforeground_color, FVAR (f, param_alist));
5409 if (CONSP (color) && STRINGP (XCDR (color)))
5410 ASET (lface, LFACE_FOREGROUND_INDEX, XCDR (color));
5411 else if (FRAME_WINDOW_P (f))
5412 return 0;
5413 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
5414 ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg));
5415 else
5416 abort ();
5419 if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
5421 /* This function is called so early that colors are not yet
5422 set in the frame parameter list. */
5423 Lisp_Object color = Fassq (Qbackground_color, FVAR (f, param_alist));
5424 if (CONSP (color) && STRINGP (XCDR (color)))
5425 ASET (lface, LFACE_BACKGROUND_INDEX, XCDR (color));
5426 else if (FRAME_WINDOW_P (f))
5427 return 0;
5428 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
5429 ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg));
5430 else
5431 abort ();
5434 if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
5435 ASET (lface, LFACE_STIPPLE_INDEX, Qnil);
5437 /* Realize the face; it must be fully-specified now. */
5438 eassert (lface_fully_specified_p (XVECTOR (lface)->contents));
5439 check_lface (lface);
5440 memcpy (attrs, XVECTOR (lface)->contents, sizeof attrs);
5441 face = realize_face (c, attrs, DEFAULT_FACE_ID);
5443 #ifdef HAVE_WINDOW_SYSTEM
5444 #ifdef HAVE_X_WINDOWS
5445 if (FRAME_X_P (f) && face->font != FRAME_FONT (f))
5447 /* This can happen when making a frame on a display that does
5448 not support the default font. */
5449 if (!face->font)
5450 return 0;
5452 /* Otherwise, the font specified for the frame was not
5453 acceptable as a font for the default face (perhaps because
5454 auto-scaled fonts are rejected), so we must adjust the frame
5455 font. */
5456 x_set_font (f, LFACE_FONT (lface), Qnil);
5458 #endif /* HAVE_X_WINDOWS */
5459 #endif /* HAVE_WINDOW_SYSTEM */
5460 return 1;
5464 /* Realize basic faces other than the default face in face cache C.
5465 SYMBOL is the face name, ID is the face id the realized face must
5466 have. The default face must have been realized already. */
5468 static void
5469 realize_named_face (struct frame *f, Lisp_Object symbol, int id)
5471 struct face_cache *c = FRAME_FACE_CACHE (f);
5472 Lisp_Object lface = lface_from_face_name (f, symbol, 0);
5473 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5474 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
5476 /* The default face must exist and be fully specified. */
5477 get_lface_attributes_no_remap (f, Qdefault, attrs, 1);
5478 check_lface_attrs (attrs);
5479 eassert (lface_fully_specified_p (attrs));
5481 /* If SYMBOL isn't know as a face, create it. */
5482 if (NILP (lface))
5484 Lisp_Object frame;
5485 XSETFRAME (frame, f);
5486 lface = Finternal_make_lisp_face (symbol, frame);
5489 /* Merge SYMBOL's face with the default face. */
5490 get_lface_attributes_no_remap (f, symbol, symbol_attrs, 1);
5491 merge_face_vectors (f, symbol_attrs, attrs, 0);
5493 /* Realize the face. */
5494 realize_face (c, attrs, id);
5498 /* Realize the fully-specified face with attributes ATTRS in face
5499 cache CACHE for ASCII characters. If FORMER_FACE_ID is
5500 non-negative, it is an ID of face to remove before caching the new
5501 face. Value is a pointer to the newly created realized face. */
5503 static struct face *
5504 realize_face (struct face_cache *cache, Lisp_Object *attrs, int former_face_id)
5506 struct face *face;
5508 /* LFACE must be fully specified. */
5509 eassert (cache != NULL);
5510 check_lface_attrs (attrs);
5512 if (former_face_id >= 0 && cache->used > former_face_id)
5514 /* Remove the former face. */
5515 struct face *former_face = cache->faces_by_id[former_face_id];
5516 uncache_face (cache, former_face);
5517 free_realized_face (cache->f, former_face);
5518 SET_FRAME_GARBAGED (cache->f);
5521 if (FRAME_WINDOW_P (cache->f))
5522 face = realize_x_face (cache, attrs);
5523 else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
5524 face = realize_tty_face (cache, attrs);
5525 else if (FRAME_INITIAL_P (cache->f))
5527 /* Create a dummy face. */
5528 face = make_realized_face (attrs);
5530 else
5531 abort ();
5533 /* Insert the new face. */
5534 cache_face (cache, face, lface_hash (attrs));
5535 return face;
5539 #ifdef HAVE_WINDOW_SYSTEM
5540 /* Realize the fully-specified face that uses FONT-OBJECT and has the
5541 same attributes as BASE_FACE except for the font on frame F.
5542 FONT-OBJECT may be nil, in which case, realized a face of
5543 no-font. */
5545 static struct face *
5546 realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
5547 struct face *base_face)
5549 struct face_cache *cache = FRAME_FACE_CACHE (f);
5550 struct face *face;
5552 face = xmalloc (sizeof *face);
5553 *face = *base_face;
5554 face->gc = 0;
5555 face->extra = NULL;
5556 face->overstrike
5557 = (! NILP (font_object)
5558 && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100
5559 && FONT_WEIGHT_NUMERIC (font_object) <= 100);
5561 /* Don't try to free the colors copied bitwise from BASE_FACE. */
5562 face->colors_copied_bitwise_p = 1;
5563 face->font = NILP (font_object) ? NULL : XFONT_OBJECT (font_object);
5564 face->gc = 0;
5566 cache_face (cache, face, face->hash);
5568 return face;
5570 #endif /* HAVE_WINDOW_SYSTEM */
5573 /* Realize the fully-specified face with attributes ATTRS in face
5574 cache CACHE for ASCII characters. Do it for X frame CACHE->f. If
5575 the new face doesn't share font with the default face, a fontname
5576 is allocated from the heap and set in `font_name' of the new face,
5577 but it is not yet loaded here. Value is a pointer to the newly
5578 created realized face. */
5580 static struct face *
5581 realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
5583 struct face *face = NULL;
5584 #ifdef HAVE_WINDOW_SYSTEM
5585 struct face *default_face;
5586 struct frame *f;
5587 Lisp_Object stipple, underline, overline, strike_through, box;
5589 eassert (FRAME_WINDOW_P (cache->f));
5591 /* Allocate a new realized face. */
5592 face = make_realized_face (attrs);
5593 face->ascii_face = face;
5595 f = cache->f;
5597 /* Determine the font to use. Most of the time, the font will be
5598 the same as the font of the default face, so try that first. */
5599 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5600 if (default_face
5601 && lface_same_font_attributes_p (default_face->lface, attrs))
5603 face->font = default_face->font;
5604 face->fontset
5605 = make_fontset_for_ascii_face (f, default_face->fontset, face);
5607 else
5609 /* If the face attribute ATTRS specifies a fontset, use it as
5610 the base of a new realized fontset. Otherwise, use the same
5611 base fontset as of the default face. The base determines
5612 registry and encoding of a font. It may also determine
5613 foundry and family. The other fields of font name pattern
5614 are constructed from ATTRS. */
5615 int fontset = face_fontset (attrs);
5617 /* If we are realizing the default face, ATTRS should specify a
5618 fontset. In other words, if FONTSET is -1, we are not
5619 realizing the default face, thus the default face should have
5620 already been realized. */
5621 if (fontset == -1)
5623 if (default_face)
5624 fontset = default_face->fontset;
5625 if (fontset == -1)
5626 abort ();
5628 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
5629 attrs[LFACE_FONT_INDEX]
5630 = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]);
5631 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
5633 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
5634 face->fontset = make_fontset_for_ascii_face (f, fontset, face);
5636 else
5638 face->font = NULL;
5639 face->fontset = -1;
5643 if (face->font
5644 && FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]) > 100
5645 && FONT_WEIGHT_NUMERIC (attrs[LFACE_FONT_INDEX]) <= 100)
5646 face->overstrike = 1;
5648 /* Load colors, and set remaining attributes. */
5650 load_face_colors (f, face, attrs);
5652 /* Set up box. */
5653 box = attrs[LFACE_BOX_INDEX];
5654 if (STRINGP (box))
5656 /* A simple box of line width 1 drawn in color given by
5657 the string. */
5658 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
5659 LFACE_BOX_INDEX);
5660 face->box = FACE_SIMPLE_BOX;
5661 face->box_line_width = 1;
5663 else if (INTEGERP (box))
5665 /* Simple box of specified line width in foreground color of the
5666 face. */
5667 eassert (XINT (box) != 0);
5668 face->box = FACE_SIMPLE_BOX;
5669 face->box_line_width = XINT (box);
5670 face->box_color = face->foreground;
5671 face->box_color_defaulted_p = 1;
5673 else if (CONSP (box))
5675 /* `(:width WIDTH :color COLOR :shadow SHADOW)'. SHADOW
5676 being one of `raised' or `sunken'. */
5677 face->box = FACE_SIMPLE_BOX;
5678 face->box_color = face->foreground;
5679 face->box_color_defaulted_p = 1;
5680 face->box_line_width = 1;
5682 while (CONSP (box))
5684 Lisp_Object keyword, value;
5686 keyword = XCAR (box);
5687 box = XCDR (box);
5689 if (!CONSP (box))
5690 break;
5691 value = XCAR (box);
5692 box = XCDR (box);
5694 if (EQ (keyword, QCline_width))
5696 if (INTEGERP (value) && XINT (value) != 0)
5697 face->box_line_width = XINT (value);
5699 else if (EQ (keyword, QCcolor))
5701 if (STRINGP (value))
5703 face->box_color = load_color (f, face, value,
5704 LFACE_BOX_INDEX);
5705 face->use_box_color_for_shadows_p = 1;
5708 else if (EQ (keyword, QCstyle))
5710 if (EQ (value, Qreleased_button))
5711 face->box = FACE_RAISED_BOX;
5712 else if (EQ (value, Qpressed_button))
5713 face->box = FACE_SUNKEN_BOX;
5718 /* Text underline, overline, strike-through. */
5720 underline = attrs[LFACE_UNDERLINE_INDEX];
5721 if (EQ (underline, Qt))
5723 /* Use default color (same as foreground color). */
5724 face->underline_p = 1;
5725 face->underline_type = FACE_UNDER_LINE;
5726 face->underline_defaulted_p = 1;
5727 face->underline_color = 0;
5729 else if (STRINGP (underline))
5731 /* Use specified color. */
5732 face->underline_p = 1;
5733 face->underline_type = FACE_UNDER_LINE;
5734 face->underline_defaulted_p = 0;
5735 face->underline_color
5736 = load_color (f, face, underline,
5737 LFACE_UNDERLINE_INDEX);
5739 else if (NILP (underline))
5741 face->underline_p = 0;
5742 face->underline_defaulted_p = 0;
5743 face->underline_color = 0;
5745 else if (CONSP (underline))
5747 /* `(:color COLOR :style STYLE)'.
5748 STYLE being one of `line' or `wave'. */
5749 face->underline_p = 1;
5750 face->underline_color = 0;
5751 face->underline_defaulted_p = 1;
5752 face->underline_type = FACE_UNDER_LINE;
5754 while (CONSP (underline))
5756 Lisp_Object keyword, value;
5758 keyword = XCAR (underline);
5759 underline = XCDR (underline);
5761 if (!CONSP (underline))
5762 break;
5763 value = XCAR (underline);
5764 underline = XCDR (underline);
5766 if (EQ (keyword, QCcolor))
5768 if (EQ (value, Qforeground_color))
5770 face->underline_defaulted_p = 1;
5771 face->underline_color = 0;
5773 else if (STRINGP (value))
5775 face->underline_defaulted_p = 0;
5776 face->underline_color = load_color (f, face, value,
5777 LFACE_UNDERLINE_INDEX);
5780 else if (EQ (keyword, QCstyle))
5782 if (EQ (value, Qline))
5783 face->underline_type = FACE_UNDER_LINE;
5784 else if (EQ (value, Qwave))
5785 face->underline_type = FACE_UNDER_WAVE;
5790 overline = attrs[LFACE_OVERLINE_INDEX];
5791 if (STRINGP (overline))
5793 face->overline_color
5794 = load_color (f, face, attrs[LFACE_OVERLINE_INDEX],
5795 LFACE_OVERLINE_INDEX);
5796 face->overline_p = 1;
5798 else if (EQ (overline, Qt))
5800 face->overline_color = face->foreground;
5801 face->overline_color_defaulted_p = 1;
5802 face->overline_p = 1;
5805 strike_through = attrs[LFACE_STRIKE_THROUGH_INDEX];
5806 if (STRINGP (strike_through))
5808 face->strike_through_color
5809 = load_color (f, face, attrs[LFACE_STRIKE_THROUGH_INDEX],
5810 LFACE_STRIKE_THROUGH_INDEX);
5811 face->strike_through_p = 1;
5813 else if (EQ (strike_through, Qt))
5815 face->strike_through_color = face->foreground;
5816 face->strike_through_color_defaulted_p = 1;
5817 face->strike_through_p = 1;
5820 stipple = attrs[LFACE_STIPPLE_INDEX];
5821 if (!NILP (stipple))
5822 face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
5823 #endif /* HAVE_WINDOW_SYSTEM */
5825 return face;
5829 /* Map a specified color of face FACE on frame F to a tty color index.
5830 IDX is either LFACE_FOREGROUND_INDEX or LFACE_BACKGROUND_INDEX, and
5831 specifies which color to map. Set *DEFAULTED to 1 if mapping to the
5832 default foreground/background colors. */
5834 static void
5835 map_tty_color (struct frame *f, struct face *face,
5836 enum lface_attribute_index idx, int *defaulted)
5838 Lisp_Object frame, color, def;
5839 int foreground_p = idx == LFACE_FOREGROUND_INDEX;
5840 unsigned long default_pixel =
5841 foreground_p ? FACE_TTY_DEFAULT_FG_COLOR : FACE_TTY_DEFAULT_BG_COLOR;
5842 unsigned long pixel = default_pixel;
5843 #ifdef MSDOS
5844 unsigned long default_other_pixel =
5845 foreground_p ? FACE_TTY_DEFAULT_BG_COLOR : FACE_TTY_DEFAULT_FG_COLOR;
5846 #endif
5848 eassert (idx == LFACE_FOREGROUND_INDEX || idx == LFACE_BACKGROUND_INDEX);
5850 XSETFRAME (frame, f);
5851 color = face->lface[idx];
5853 if (STRINGP (color)
5854 && SCHARS (color)
5855 && CONSP (Vtty_defined_color_alist)
5856 && (def = assq_no_quit (color, call1 (Qtty_color_alist, frame)),
5857 CONSP (def)))
5859 /* Associations in tty-defined-color-alist are of the form
5860 (NAME INDEX R G B). We need the INDEX part. */
5861 pixel = XINT (XCAR (XCDR (def)));
5864 if (pixel == default_pixel && STRINGP (color))
5866 pixel = load_color (f, face, color, idx);
5868 #ifdef MSDOS
5869 /* If the foreground of the default face is the default color,
5870 use the foreground color defined by the frame. */
5871 if (FRAME_MSDOS_P (f))
5873 if (pixel == default_pixel
5874 || pixel == FACE_TTY_DEFAULT_COLOR)
5876 if (foreground_p)
5877 pixel = FRAME_FOREGROUND_PIXEL (f);
5878 else
5879 pixel = FRAME_BACKGROUND_PIXEL (f);
5880 face->lface[idx] = tty_color_name (f, pixel);
5881 *defaulted = 1;
5883 else if (pixel == default_other_pixel)
5885 if (foreground_p)
5886 pixel = FRAME_BACKGROUND_PIXEL (f);
5887 else
5888 pixel = FRAME_FOREGROUND_PIXEL (f);
5889 face->lface[idx] = tty_color_name (f, pixel);
5890 *defaulted = 1;
5893 #endif /* MSDOS */
5896 if (foreground_p)
5897 face->foreground = pixel;
5898 else
5899 face->background = pixel;
5903 /* Realize the fully-specified face with attributes ATTRS in face
5904 cache CACHE for ASCII characters. Do it for TTY frame CACHE->f.
5905 Value is a pointer to the newly created realized face. */
5907 static struct face *
5908 realize_tty_face (struct face_cache *cache, Lisp_Object *attrs)
5910 struct face *face;
5911 int weight, slant;
5912 int face_colors_defaulted = 0;
5913 struct frame *f = cache->f;
5915 /* Frame must be a termcap frame. */
5916 eassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
5918 /* Allocate a new realized face. */
5919 face = make_realized_face (attrs);
5920 #if 0
5921 face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
5922 #endif
5924 /* Map face attributes to TTY appearances. */
5925 weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
5926 slant = FONT_SLANT_NAME_NUMERIC (attrs[LFACE_SLANT_INDEX]);
5927 if (weight > 100)
5928 face->tty_bold_p = 1;
5929 if (slant != 100)
5930 face->tty_italic_p = 1;
5931 if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
5932 face->tty_underline_p = 1;
5933 if (!NILP (attrs[LFACE_INVERSE_INDEX]))
5934 face->tty_reverse_p = 1;
5936 /* Map color names to color indices. */
5937 map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
5938 map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
5940 /* Swap colors if face is inverse-video. If the colors are taken
5941 from the frame colors, they are already inverted, since the
5942 frame-creation function calls x-handle-reverse-video. */
5943 if (face->tty_reverse_p && !face_colors_defaulted)
5945 unsigned long tem = face->foreground;
5946 face->foreground = face->background;
5947 face->background = tem;
5950 if (tty_suppress_bold_inverse_default_colors_p
5951 && face->tty_bold_p
5952 && face->background == FACE_TTY_DEFAULT_FG_COLOR
5953 && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
5954 face->tty_bold_p = 0;
5956 return face;
5960 DEFUN ("tty-suppress-bold-inverse-default-colors",
5961 Ftty_suppress_bold_inverse_default_colors,
5962 Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
5963 doc: /* Suppress/allow boldness of faces with inverse default colors.
5964 SUPPRESS non-nil means suppress it.
5965 This affects bold faces on TTYs whose foreground is the default background
5966 color of the display and whose background is the default foreground color.
5967 For such faces, the bold face attribute is ignored if this variable
5968 is non-nil. */)
5969 (Lisp_Object suppress)
5971 tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
5972 ++face_change_count;
5973 return suppress;
5978 /***********************************************************************
5979 Computing Faces
5980 ***********************************************************************/
5982 /* Return the ID of the face to use to display character CH with face
5983 property PROP on frame F in current_buffer. */
5986 compute_char_face (struct frame *f, int ch, Lisp_Object prop)
5988 int face_id;
5990 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
5991 ch = 0;
5993 if (NILP (prop))
5995 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5996 face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
5998 else
6000 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6001 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6002 memcpy (attrs, default_face->lface, sizeof attrs);
6003 merge_face_ref (f, prop, attrs, 1, 0);
6004 face_id = lookup_face (f, attrs);
6007 return face_id;
6010 /* Return the face ID associated with buffer position POS for
6011 displaying ASCII characters. Return in *ENDPTR the position at
6012 which a different face is needed, as far as text properties and
6013 overlays are concerned. W is a window displaying current_buffer.
6015 REGION_BEG, REGION_END delimit the region, so it can be
6016 highlighted.
6018 LIMIT is a position not to scan beyond. That is to limit the time
6019 this function can take.
6021 If MOUSE is non-zero, use the character's mouse-face, not its face.
6023 BASE_FACE_ID, if non-negative, specifies a base face id to use
6024 instead of DEFAULT_FACE_ID.
6026 The face returned is suitable for displaying ASCII characters. */
6029 face_at_buffer_position (struct window *w, ptrdiff_t pos,
6030 ptrdiff_t region_beg, ptrdiff_t region_end,
6031 ptrdiff_t *endptr, ptrdiff_t limit,
6032 int mouse, int base_face_id)
6034 struct frame *f = XFRAME (WVAR (w, frame));
6035 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6036 Lisp_Object prop, position;
6037 ptrdiff_t i, noverlays;
6038 Lisp_Object *overlay_vec;
6039 Lisp_Object frame;
6040 ptrdiff_t endpos;
6041 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6042 Lisp_Object limit1, end;
6043 struct face *default_face;
6045 /* W must display the current buffer. We could write this function
6046 to use the frame and buffer of W, but right now it doesn't. */
6047 /* eassert (XBUFFER (w->buffer) == current_buffer); */
6049 XSETFRAME (frame, f);
6050 XSETFASTINT (position, pos);
6052 endpos = ZV;
6053 if (pos < region_beg && region_beg < endpos)
6054 endpos = region_beg;
6056 /* Get the `face' or `mouse_face' text property at POS, and
6057 determine the next position at which the property changes. */
6058 prop = Fget_text_property (position, propname, WVAR (w, buffer));
6059 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6060 end = Fnext_single_property_change (position, propname, WVAR (w, buffer), limit1);
6061 if (INTEGERP (end))
6062 endpos = XINT (end);
6064 /* Look at properties from overlays. */
6066 ptrdiff_t next_overlay;
6068 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, 0);
6069 if (next_overlay < endpos)
6070 endpos = next_overlay;
6073 *endptr = endpos;
6076 int face_id;
6078 if (base_face_id >= 0)
6079 face_id = base_face_id;
6080 else if (NILP (Vface_remapping_alist))
6081 face_id = DEFAULT_FACE_ID;
6082 else
6083 face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
6085 default_face = FACE_FROM_ID (f, face_id);
6088 /* Optimize common cases where we can use the default face. */
6089 if (noverlays == 0
6090 && NILP (prop)
6091 && !(pos >= region_beg && pos < region_end))
6092 return default_face->id;
6094 /* Begin with attributes from the default face. */
6095 memcpy (attrs, default_face->lface, sizeof attrs);
6097 /* Merge in attributes specified via text properties. */
6098 if (!NILP (prop))
6099 merge_face_ref (f, prop, attrs, 1, 0);
6101 /* Now merge the overlay data. */
6102 noverlays = sort_overlays (overlay_vec, noverlays, w);
6103 for (i = 0; i < noverlays; i++)
6105 Lisp_Object oend;
6106 int oendpos;
6108 prop = Foverlay_get (overlay_vec[i], propname);
6109 if (!NILP (prop))
6110 merge_face_ref (f, prop, attrs, 1, 0);
6112 oend = OVERLAY_END (overlay_vec[i]);
6113 oendpos = OVERLAY_POSITION (oend);
6114 if (oendpos < endpos)
6115 endpos = oendpos;
6118 /* If in the region, merge in the region face. */
6119 if (pos >= region_beg && pos < region_end)
6121 merge_named_face (f, Qregion, attrs, 0);
6123 if (region_end < endpos)
6124 endpos = region_end;
6127 *endptr = endpos;
6129 /* Look up a realized face with the given face attributes,
6130 or realize a new one for ASCII characters. */
6131 return lookup_face (f, attrs);
6134 /* Return the face ID at buffer position POS for displaying ASCII
6135 characters associated with overlay strings for overlay OVERLAY.
6137 Like face_at_buffer_position except for OVERLAY. Currently it
6138 simply disregards the `face' properties of all overlays. */
6141 face_for_overlay_string (struct window *w, ptrdiff_t pos,
6142 ptrdiff_t region_beg, ptrdiff_t region_end,
6143 ptrdiff_t *endptr, ptrdiff_t limit,
6144 int mouse, Lisp_Object overlay)
6146 struct frame *f = XFRAME (WVAR (w, frame));
6147 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6148 Lisp_Object prop, position;
6149 Lisp_Object frame;
6150 int endpos;
6151 Lisp_Object propname = mouse ? Qmouse_face : Qface;
6152 Lisp_Object limit1, end;
6153 struct face *default_face;
6155 /* W must display the current buffer. We could write this function
6156 to use the frame and buffer of W, but right now it doesn't. */
6157 /* eassert (XBUFFER (w->buffer) == current_buffer); */
6159 XSETFRAME (frame, f);
6160 XSETFASTINT (position, pos);
6162 endpos = ZV;
6163 if (pos < region_beg && region_beg < endpos)
6164 endpos = region_beg;
6166 /* Get the `face' or `mouse_face' text property at POS, and
6167 determine the next position at which the property changes. */
6168 prop = Fget_text_property (position, propname, WVAR (w, buffer));
6169 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6170 end = Fnext_single_property_change (position, propname, WVAR (w, buffer), limit1);
6171 if (INTEGERP (end))
6172 endpos = XINT (end);
6174 *endptr = endpos;
6176 /* Optimize common case where we can use the default face. */
6177 if (NILP (prop)
6178 && !(pos >= region_beg && pos < region_end)
6179 && NILP (Vface_remapping_alist))
6180 return DEFAULT_FACE_ID;
6182 /* Begin with attributes from the default face. */
6183 default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
6184 memcpy (attrs, default_face->lface, sizeof attrs);
6186 /* Merge in attributes specified via text properties. */
6187 if (!NILP (prop))
6188 merge_face_ref (f, prop, attrs, 1, 0);
6190 /* If in the region, merge in the region face. */
6191 if (pos >= region_beg && pos < region_end)
6193 merge_named_face (f, Qregion, attrs, 0);
6195 if (region_end < endpos)
6196 endpos = region_end;
6199 *endptr = endpos;
6201 /* Look up a realized face with the given face attributes,
6202 or realize a new one for ASCII characters. */
6203 return lookup_face (f, attrs);
6207 /* Compute the face at character position POS in Lisp string STRING on
6208 window W, for ASCII characters.
6210 If STRING is an overlay string, it comes from position BUFPOS in
6211 current_buffer, otherwise BUFPOS is zero to indicate that STRING is
6212 not an overlay string. W must display the current buffer.
6213 REGION_BEG and REGION_END give the start and end positions of the
6214 region; both are -1 if no region is visible.
6216 BASE_FACE_ID is the id of a face to merge with. For strings coming
6217 from overlays or the `display' property it is the face at BUFPOS.
6219 If MOUSE_P is non-zero, use the character's mouse-face, not its face.
6221 Set *ENDPTR to the next position where to check for faces in
6222 STRING; -1 if the face is constant from POS to the end of the
6223 string.
6225 Value is the id of the face to use. The face returned is suitable
6226 for displaying ASCII characters. */
6229 face_at_string_position (struct window *w, Lisp_Object string,
6230 ptrdiff_t pos, ptrdiff_t bufpos,
6231 ptrdiff_t region_beg, ptrdiff_t region_end,
6232 ptrdiff_t *endptr, enum face_id base_face_id,
6233 int mouse_p)
6235 Lisp_Object prop, position, end, limit;
6236 struct frame *f = XFRAME (WINDOW_FRAME (w));
6237 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6238 struct face *base_face;
6239 int multibyte_p = STRING_MULTIBYTE (string);
6240 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
6242 /* Get the value of the face property at the current position within
6243 STRING. Value is nil if there is no face property. */
6244 XSETFASTINT (position, pos);
6245 prop = Fget_text_property (position, prop_name, string);
6247 /* Get the next position at which to check for faces. Value of end
6248 is nil if face is constant all the way to the end of the string.
6249 Otherwise it is a string position where to check faces next.
6250 Limit is the maximum position up to which to check for property
6251 changes in Fnext_single_property_change. Strings are usually
6252 short, so set the limit to the end of the string. */
6253 XSETFASTINT (limit, SCHARS (string));
6254 end = Fnext_single_property_change (position, prop_name, string, limit);
6255 if (INTEGERP (end))
6256 *endptr = XFASTINT (end);
6257 else
6258 *endptr = -1;
6260 base_face = FACE_FROM_ID (f, base_face_id);
6261 eassert (base_face);
6263 /* Optimize the default case that there is no face property and we
6264 are not in the region. */
6265 if (NILP (prop)
6266 && (base_face_id != DEFAULT_FACE_ID
6267 /* BUFPOS <= 0 means STRING is not an overlay string, so
6268 that the region doesn't have to be taken into account. */
6269 || bufpos <= 0
6270 || bufpos < region_beg
6271 || bufpos >= region_end)
6272 && (multibyte_p
6273 /* We can't realize faces for different charsets differently
6274 if we don't have fonts, so we can stop here if not working
6275 on a window-system frame. */
6276 || !FRAME_WINDOW_P (f)
6277 || FACE_SUITABLE_FOR_ASCII_CHAR_P (base_face, 0)))
6278 return base_face->id;
6280 /* Begin with attributes from the base face. */
6281 memcpy (attrs, base_face->lface, sizeof attrs);
6283 /* Merge in attributes specified via text properties. */
6284 if (!NILP (prop))
6285 merge_face_ref (f, prop, attrs, 1, 0);
6287 /* If in the region, merge in the region face. */
6288 if (bufpos
6289 && bufpos >= region_beg
6290 && bufpos < region_end)
6291 merge_named_face (f, Qregion, attrs, 0);
6293 /* Look up a realized face with the given face attributes,
6294 or realize a new one for ASCII characters. */
6295 return lookup_face (f, attrs);
6299 /* Merge a face into a realized face.
6301 F is frame where faces are (to be) realized.
6303 FACE_NAME is named face to merge.
6305 If FACE_NAME is nil, FACE_ID is face_id of realized face to merge.
6307 If FACE_NAME is t, FACE_ID is lface_id of face to merge.
6309 BASE_FACE_ID is realized face to merge into.
6311 Return new face id.
6315 merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6316 int base_face_id)
6318 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6319 struct face *base_face;
6321 base_face = FACE_FROM_ID (f, base_face_id);
6322 if (!base_face)
6323 return base_face_id;
6325 if (EQ (face_name, Qt))
6327 if (face_id < 0 || face_id >= lface_id_to_name_size)
6328 return base_face_id;
6329 face_name = lface_id_to_name[face_id];
6330 /* When called during make-frame, lookup_derived_face may fail
6331 if the faces are uninitialized. Don't signal an error. */
6332 face_id = lookup_derived_face (f, face_name, base_face_id, 0);
6333 return (face_id >= 0 ? face_id : base_face_id);
6336 /* Begin with attributes from the base face. */
6337 memcpy (attrs, base_face->lface, sizeof attrs);
6339 if (!NILP (face_name))
6341 if (!merge_named_face (f, face_name, attrs, 0))
6342 return base_face_id;
6344 else
6346 struct face *face;
6347 if (face_id < 0)
6348 return base_face_id;
6349 face = FACE_FROM_ID (f, face_id);
6350 if (!face)
6351 return base_face_id;
6352 merge_face_vectors (f, face->lface, attrs, 0);
6355 /* Look up a realized face with the given face attributes,
6356 or realize a new one for ASCII characters. */
6357 return lookup_face (f, attrs);
6362 #ifndef HAVE_X_WINDOWS
6363 DEFUN ("x-load-color-file", Fx_load_color_file,
6364 Sx_load_color_file, 1, 1, 0,
6365 doc: /* Create an alist of color entries from an external file.
6367 The file should define one named RGB color per line like so:
6368 R G B name
6369 where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
6370 (Lisp_Object filename)
6372 FILE *fp;
6373 Lisp_Object cmap = Qnil;
6374 Lisp_Object abspath;
6376 CHECK_STRING (filename);
6377 abspath = Fexpand_file_name (filename, Qnil);
6379 fp = fopen (SSDATA (abspath), "rt");
6380 if (fp)
6382 char buf[512];
6383 int red, green, blue;
6384 int num;
6386 BLOCK_INPUT;
6388 while (fgets (buf, sizeof (buf), fp) != NULL) {
6389 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
6391 char *name = buf + num;
6392 num = strlen (name) - 1;
6393 if (num >= 0 && name[num] == '\n')
6394 name[num] = 0;
6395 cmap = Fcons (Fcons (build_string (name),
6396 #ifdef WINDOWSNT
6397 make_number (RGB (red, green, blue))),
6398 #else
6399 make_number ((red << 16) | (green << 8) | blue)),
6400 #endif
6401 cmap);
6404 fclose (fp);
6406 UNBLOCK_INPUT;
6409 return cmap;
6411 #endif
6414 /***********************************************************************
6415 Tests
6416 ***********************************************************************/
6418 #ifdef GLYPH_DEBUG
6420 /* Print the contents of the realized face FACE to stderr. */
6422 static void
6423 dump_realized_face (struct face *face)
6425 fprintf (stderr, "ID: %d\n", face->id);
6426 #ifdef HAVE_X_WINDOWS
6427 fprintf (stderr, "gc: %ld\n", (long) face->gc);
6428 #endif
6429 fprintf (stderr, "foreground: 0x%lx (%s)\n",
6430 face->foreground,
6431 SDATA (face->lface[LFACE_FOREGROUND_INDEX]));
6432 fprintf (stderr, "background: 0x%lx (%s)\n",
6433 face->background,
6434 SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
6435 if (face->font)
6436 fprintf (stderr, "font_name: %s (%s)\n",
6437 SDATA (face->font->props[FONT_NAME_INDEX]),
6438 SDATA (face->lface[LFACE_FAMILY_INDEX]));
6439 #ifdef HAVE_X_WINDOWS
6440 fprintf (stderr, "font = %p\n", face->font);
6441 #endif
6442 fprintf (stderr, "fontset: %d\n", face->fontset);
6443 fprintf (stderr, "underline: %d (%s)\n",
6444 face->underline_p,
6445 SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
6446 fprintf (stderr, "hash: %d\n", face->hash);
6450 DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */)
6451 (Lisp_Object n)
6453 if (NILP (n))
6455 int i;
6457 fprintf (stderr, "font selection order: ");
6458 for (i = 0; i < DIM (font_sort_order); ++i)
6459 fprintf (stderr, "%d ", font_sort_order[i]);
6460 fprintf (stderr, "\n");
6462 fprintf (stderr, "alternative fonts: ");
6463 debug_print (Vface_alternative_font_family_alist);
6464 fprintf (stderr, "\n");
6466 for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
6467 Fdump_face (make_number (i));
6469 else
6471 struct face *face;
6472 CHECK_NUMBER (n);
6473 face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
6474 if (face == NULL)
6475 error ("Not a valid face");
6476 dump_realized_face (face);
6479 return Qnil;
6483 DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
6484 0, 0, 0, doc: /* */)
6485 (void)
6487 fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
6488 fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
6489 fprintf (stderr, "number of GCs = %d\n", ngcs);
6490 return Qnil;
6493 #endif /* GLYPH_DEBUG */
6497 /***********************************************************************
6498 Initialization
6499 ***********************************************************************/
6501 void
6502 syms_of_xfaces (void)
6504 DEFSYM (Qface, "face");
6505 DEFSYM (Qface_no_inherit, "face-no-inherit");
6506 DEFSYM (Qbitmap_spec_p, "bitmap-spec-p");
6507 DEFSYM (Qframe_set_background_mode, "frame-set-background-mode");
6509 /* Lisp face attribute keywords. */
6510 DEFSYM (QCfamily, ":family");
6511 DEFSYM (QCheight, ":height");
6512 DEFSYM (QCweight, ":weight");
6513 DEFSYM (QCslant, ":slant");
6514 DEFSYM (QCunderline, ":underline");
6515 DEFSYM (QCinverse_video, ":inverse-video");
6516 DEFSYM (QCreverse_video, ":reverse-video");
6517 DEFSYM (QCforeground, ":foreground");
6518 DEFSYM (QCbackground, ":background");
6519 DEFSYM (QCstipple, ":stipple");
6520 DEFSYM (QCwidth, ":width");
6521 DEFSYM (QCfont, ":font");
6522 DEFSYM (QCfontset, ":fontset");
6523 DEFSYM (QCbold, ":bold");
6524 DEFSYM (QCitalic, ":italic");
6525 DEFSYM (QCoverline, ":overline");
6526 DEFSYM (QCstrike_through, ":strike-through");
6527 DEFSYM (QCbox, ":box");
6528 DEFSYM (QCinherit, ":inherit");
6530 /* Symbols used for Lisp face attribute values. */
6531 DEFSYM (QCcolor, ":color");
6532 DEFSYM (QCline_width, ":line-width");
6533 DEFSYM (QCstyle, ":style");
6534 DEFSYM (Qline, "line");
6535 DEFSYM (Qwave, "wave");
6536 DEFSYM (Qreleased_button, "released-button");
6537 DEFSYM (Qpressed_button, "pressed-button");
6538 DEFSYM (Qnormal, "normal");
6539 DEFSYM (Qultra_light, "ultra-light");
6540 DEFSYM (Qextra_light, "extra-light");
6541 DEFSYM (Qlight, "light");
6542 DEFSYM (Qsemi_light, "semi-light");
6543 DEFSYM (Qsemi_bold, "semi-bold");
6544 DEFSYM (Qbold, "bold");
6545 DEFSYM (Qextra_bold, "extra-bold");
6546 DEFSYM (Qultra_bold, "ultra-bold");
6547 DEFSYM (Qoblique, "oblique");
6548 DEFSYM (Qitalic, "italic");
6549 DEFSYM (Qreverse_oblique, "reverse-oblique");
6550 DEFSYM (Qreverse_italic, "reverse-italic");
6551 DEFSYM (Qultra_condensed, "ultra-condensed");
6552 DEFSYM (Qextra_condensed, "extra-condensed");
6553 DEFSYM (Qcondensed, "condensed");
6554 DEFSYM (Qsemi_condensed, "semi-condensed");
6555 DEFSYM (Qsemi_expanded, "semi-expanded");
6556 DEFSYM (Qexpanded, "expanded");
6557 DEFSYM (Qextra_expanded, "extra-expanded");
6558 DEFSYM (Qultra_expanded, "ultra-expanded");
6559 DEFSYM (Qbackground_color, "background-color");
6560 DEFSYM (Qforeground_color, "foreground-color");
6561 DEFSYM (Qunspecified, "unspecified");
6562 DEFSYM (QCignore_defface, ":ignore-defface");
6564 DEFSYM (Qface_alias, "face-alias");
6565 DEFSYM (Qdefault, "default");
6566 DEFSYM (Qtool_bar, "tool-bar");
6567 DEFSYM (Qregion, "region");
6568 DEFSYM (Qfringe, "fringe");
6569 DEFSYM (Qheader_line, "header-line");
6570 DEFSYM (Qscroll_bar, "scroll-bar");
6571 DEFSYM (Qmenu, "menu");
6572 DEFSYM (Qcursor, "cursor");
6573 DEFSYM (Qborder, "border");
6574 DEFSYM (Qmouse, "mouse");
6575 DEFSYM (Qmode_line_inactive, "mode-line-inactive");
6576 DEFSYM (Qvertical_border, "vertical-border");
6577 DEFSYM (Qtty_color_desc, "tty-color-desc");
6578 DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
6579 DEFSYM (Qtty_color_by_index, "tty-color-by-index");
6580 DEFSYM (Qtty_color_alist, "tty-color-alist");
6581 DEFSYM (Qscalable_fonts_allowed, "scalable-fonts-allowed");
6583 Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
6584 staticpro (&Vparam_value_alist);
6585 Vface_alternative_font_family_alist = Qnil;
6586 staticpro (&Vface_alternative_font_family_alist);
6587 Vface_alternative_font_registry_alist = Qnil;
6588 staticpro (&Vface_alternative_font_registry_alist);
6590 defsubr (&Sinternal_make_lisp_face);
6591 defsubr (&Sinternal_lisp_face_p);
6592 defsubr (&Sinternal_set_lisp_face_attribute);
6593 #ifdef HAVE_WINDOW_SYSTEM
6594 defsubr (&Sinternal_set_lisp_face_attribute_from_resource);
6595 #endif
6596 defsubr (&Scolor_gray_p);
6597 defsubr (&Scolor_supported_p);
6598 #ifndef HAVE_X_WINDOWS
6599 defsubr (&Sx_load_color_file);
6600 #endif
6601 defsubr (&Sface_attribute_relative_p);
6602 defsubr (&Smerge_face_attribute);
6603 defsubr (&Sinternal_get_lisp_face_attribute);
6604 defsubr (&Sinternal_lisp_face_attribute_values);
6605 defsubr (&Sinternal_lisp_face_equal_p);
6606 defsubr (&Sinternal_lisp_face_empty_p);
6607 defsubr (&Sinternal_copy_lisp_face);
6608 defsubr (&Sinternal_merge_in_global_face);
6609 defsubr (&Sface_font);
6610 defsubr (&Sframe_face_alist);
6611 defsubr (&Sdisplay_supports_face_attributes_p);
6612 defsubr (&Scolor_distance);
6613 defsubr (&Sinternal_set_font_selection_order);
6614 defsubr (&Sinternal_set_alternative_font_family_alist);
6615 defsubr (&Sinternal_set_alternative_font_registry_alist);
6616 defsubr (&Sface_attributes_as_vector);
6617 #ifdef GLYPH_DEBUG
6618 defsubr (&Sdump_face);
6619 defsubr (&Sshow_face_resources);
6620 #endif /* GLYPH_DEBUG */
6621 defsubr (&Sclear_face_cache);
6622 defsubr (&Stty_suppress_bold_inverse_default_colors);
6624 #if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
6625 defsubr (&Sdump_colors);
6626 #endif
6628 DEFVAR_LISP ("font-list-limit", Vfont_list_limit,
6629 doc: /* Limit for font matching.
6630 If an integer > 0, font matching functions won't load more than
6631 that number of fonts when searching for a matching font. */);
6632 Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
6634 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults,
6635 doc: /* List of global face definitions (for internal use only.) */);
6636 Vface_new_frame_defaults = Qnil;
6638 DEFVAR_LISP ("face-default-stipple", Vface_default_stipple,
6639 doc: /* Default stipple pattern used on monochrome displays.
6640 This stipple pattern is used on monochrome displays
6641 instead of shades of gray for a face background color.
6642 See `set-face-stipple' for possible values for this variable. */);
6643 Vface_default_stipple = build_pure_c_string ("gray3");
6645 DEFVAR_LISP ("tty-defined-color-alist", Vtty_defined_color_alist,
6646 doc: /* An alist of defined terminal colors and their RGB values.
6647 See the docstring of `tty-color-alist' for the details. */);
6648 Vtty_defined_color_alist = Qnil;
6650 DEFVAR_LISP ("scalable-fonts-allowed", Vscalable_fonts_allowed,
6651 doc: /* Allowed scalable fonts.
6652 A value of nil means don't allow any scalable fonts.
6653 A value of t means allow any scalable font.
6654 Otherwise, value must be a list of regular expressions. A font may be
6655 scaled if its name matches a regular expression in the list.
6656 Note that if value is nil, a scalable font might still be used, if no
6657 other font of the appropriate family and registry is available. */);
6658 Vscalable_fonts_allowed = Qnil;
6660 DEFVAR_LISP ("face-ignored-fonts", Vface_ignored_fonts,
6661 doc: /* List of ignored fonts.
6662 Each element is a regular expression that matches names of fonts to
6663 ignore. */);
6664 Vface_ignored_fonts = Qnil;
6666 DEFVAR_LISP ("face-remapping-alist", Vface_remapping_alist,
6667 doc: /* Alist of face remappings.
6668 Each element is of the form:
6670 (FACE . REPLACEMENT),
6672 which causes display of the face FACE to use REPLACEMENT instead.
6673 REPLACEMENT is a face specification, i.e. one of the following:
6675 (1) a face name
6676 (2) a property list of attribute/value pairs, or
6677 (3) a list in which each element has the form of (1) or (2).
6679 List values for REPLACEMENT are merged to form the final face
6680 specification, with earlier entries taking precedence, in the same as
6681 as in the `face' text property.
6683 Face-name remapping cycles are suppressed; recursive references use
6684 the underlying face instead of the remapped face. So a remapping of
6685 the form:
6687 (FACE EXTRA-FACE... FACE)
6691 (FACE (FACE-ATTR VAL ...) FACE)
6693 causes EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
6694 existing definition of FACE. Note that this isn't necessary for the
6695 default face, since every face inherits from the default face.
6697 If this variable is made buffer-local, the face remapping takes effect
6698 only in that buffer. For instance, the mode my-mode could define a
6699 face `my-mode-default', and then in the mode setup function, do:
6701 (set (make-local-variable 'face-remapping-alist)
6702 '((default my-mode-default)))).
6704 Because Emacs normally only redraws screen areas when the underlying
6705 buffer contents change, you may need to call `redraw-display' after
6706 changing this variable for it to take effect. */);
6707 Vface_remapping_alist = Qnil;
6709 DEFVAR_LISP ("face-font-rescale-alist", Vface_font_rescale_alist,
6710 doc: /* Alist of fonts vs the rescaling factors.
6711 Each element is a cons (FONT-PATTERN . RESCALE-RATIO), where
6712 FONT-PATTERN is a font-spec or a regular expression matching a font name, and
6713 RESCALE-RATIO is a floating point number to specify how much larger
6714 \(or smaller) font we should use. For instance, if a face requests
6715 a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point. */);
6716 Vface_font_rescale_alist = Qnil;
6718 #ifdef HAVE_WINDOW_SYSTEM
6719 defsubr (&Sbitmap_spec_p);
6720 defsubr (&Sx_list_fonts);
6721 defsubr (&Sinternal_face_x_get_resource);
6722 defsubr (&Sx_family_fonts);
6723 #endif