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