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