import xemacs-21.2.37
[chise/xemacs-chise.git] / src / faces.c
1 /* "Face" primitives
2    Copyright (C) 1994 Free Software Foundation, Inc.
3    Copyright (C) 1995 Board of Trustees, University of Illinois.
4    Copyright (C) 1995, 1996 Ben Wing.
5    Copyright (C) 1995 Sun Microsystems, Inc.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING.  If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 /* Synched up with: Not in FSF. */
25
26 /* Written by Chuck Thompson and Ben Wing,
27    based loosely on old face code by Jamie Zawinski. */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "buffer.h"
33 #include "device.h"
34 #include "elhash.h"
35 #include "extents.h"
36 #include "faces.h"
37 #include "frame.h"
38 #include "glyphs.h"
39 #include "objects.h"
40 #include "specifier.h"
41 #include "window.h"
42
43 Lisp_Object Qfacep;
44 Lisp_Object Qforeground, Qbackground, Qdisplay_table;
45 Lisp_Object Qbackground_pixmap, Qunderline, Qdim;
46 Lisp_Object Qblinking, Qstrikethru;
47
48 Lisp_Object Qinit_face_from_resources;
49 Lisp_Object Qinit_frame_faces;
50 Lisp_Object Qinit_device_faces;
51 Lisp_Object Qinit_global_faces;
52
53 /* These faces are used directly internally.  We use these variables
54    to be able to reference them directly and save the overhead of
55    calling Ffind_face. */
56 Lisp_Object Vdefault_face, Vmodeline_face, Vgui_element_face;
57 Lisp_Object Vleft_margin_face, Vright_margin_face, Vtext_cursor_face;
58 Lisp_Object Vpointer_face, Vvertical_divider_face, Vtoolbar_face, Vwidget_face;
59
60 /* Qdefault, Qhighlight, Qleft_margin, Qright_margin defined in general.c */
61 Lisp_Object Qmodeline, Qgui_element, Qtext_cursor, Qvertical_divider;
62
63 /* In the old implementation Vface_list was a list of the face names,
64    not the faces themselves.  We now distinguish between permanent and
65    temporary faces.  Permanent faces are kept in a regular hash table,
66    temporary faces in a weak hash table. */
67 Lisp_Object Vpermanent_faces_cache;
68 Lisp_Object Vtemporary_faces_cache;
69
70 Lisp_Object Vbuilt_in_face_specifiers;
71
72 \f
73
74 static Lisp_Object
75 mark_face (Lisp_Object obj)
76 {
77   Lisp_Face *face =  XFACE (obj);
78
79   mark_object (face->name);
80   mark_object (face->doc_string);
81
82   mark_object (face->foreground);
83   mark_object (face->background);
84   mark_object (face->font);
85   mark_object (face->display_table);
86   mark_object (face->background_pixmap);
87   mark_object (face->underline);
88   mark_object (face->strikethru);
89   mark_object (face->highlight);
90   mark_object (face->dim);
91   mark_object (face->blinking);
92   mark_object (face->reverse);
93
94   mark_object (face->charsets_warned_about);
95
96   return face->plist;
97 }
98
99 static void
100 print_face (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
101 {
102   Lisp_Face *face = XFACE (obj);
103
104   if (print_readably)
105     {
106       write_c_string ("#s(face name ", printcharfun);
107       print_internal (face->name, printcharfun, 1);
108       write_c_string (")", printcharfun);
109     }
110   else
111     {
112       write_c_string ("#<face ", printcharfun);
113       print_internal (face->name, printcharfun, 1);
114       if (!NILP (face->doc_string))
115         {
116           write_c_string (" ", printcharfun);
117           print_internal (face->doc_string, printcharfun, 1);
118         }
119       write_c_string (">", printcharfun);
120     }
121 }
122
123 /* Faces are equal if all of their display attributes are equal.  We
124    don't compare names or doc-strings, because that would make equal
125    be eq.
126
127    This isn't concerned with "unspecified" attributes, that's what
128    #'face-differs-from-default-p is for. */
129 static int
130 face_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
131 {
132   Lisp_Face *f1 = XFACE (obj1);
133   Lisp_Face *f2 = XFACE (obj2);
134
135   depth++;
136
137   return
138     (internal_equal (f1->foreground,         f2->foreground,        depth) &&
139      internal_equal (f1->background,         f2->background,        depth) &&
140      internal_equal (f1->font,               f2->font,              depth) &&
141      internal_equal (f1->display_table,      f2->display_table,     depth) &&
142      internal_equal (f1->background_pixmap,  f2->background_pixmap, depth) &&
143      internal_equal (f1->underline,          f2->underline,         depth) &&
144      internal_equal (f1->strikethru,         f2->strikethru,        depth) &&
145      internal_equal (f1->highlight,          f2->highlight,         depth) &&
146      internal_equal (f1->dim,                f2->dim,               depth) &&
147      internal_equal (f1->blinking,           f2->blinking,          depth) &&
148      internal_equal (f1->reverse,            f2->reverse,           depth) &&
149
150      ! plists_differ (f1->plist, f2->plist, 0, 0, depth + 1));
151 }
152
153 static unsigned long
154 face_hash (Lisp_Object obj, int depth)
155 {
156   Lisp_Face *f = XFACE (obj);
157
158   depth++;
159
160   /* No need to hash all of the elements; that would take too long.
161      Just hash the most common ones. */
162   return HASH3 (internal_hash (f->foreground, depth),
163                 internal_hash (f->background, depth),
164                 internal_hash (f->font,       depth));
165 }
166
167 static Lisp_Object
168 face_getprop (Lisp_Object obj, Lisp_Object prop)
169 {
170   Lisp_Face *f = XFACE (obj);
171
172   return
173     (EQ (prop, Qforeground)        ? f->foreground        :
174      EQ (prop, Qbackground)        ? f->background        :
175      EQ (prop, Qfont)              ? f->font              :
176      EQ (prop, Qdisplay_table)     ? f->display_table     :
177      EQ (prop, Qbackground_pixmap) ? f->background_pixmap :
178      EQ (prop, Qunderline)         ? f->underline         :
179      EQ (prop, Qstrikethru)        ? f->strikethru        :
180      EQ (prop, Qhighlight)         ? f->highlight         :
181      EQ (prop, Qdim)               ? f->dim               :
182      EQ (prop, Qblinking)          ? f->blinking          :
183      EQ (prop, Qreverse)           ? f->reverse           :
184      EQ (prop, Qdoc_string)        ? f->doc_string        :
185      external_plist_get (&f->plist, prop, 0, ERROR_ME));
186 }
187
188 static int
189 face_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
190 {
191   Lisp_Face *f = XFACE (obj);
192
193   if (EQ (prop, Qforeground)        ||
194       EQ (prop, Qbackground)        ||
195       EQ (prop, Qfont)              ||
196       EQ (prop, Qdisplay_table)     ||
197       EQ (prop, Qbackground_pixmap) ||
198       EQ (prop, Qunderline)         ||
199       EQ (prop, Qstrikethru)        ||
200       EQ (prop, Qhighlight)         ||
201       EQ (prop, Qdim)               ||
202       EQ (prop, Qblinking)          ||
203       EQ (prop, Qreverse))
204     return 0;
205
206   if (EQ (prop, Qdoc_string))
207     {
208       if (!NILP (value))
209         CHECK_STRING (value);
210       f->doc_string = value;
211       return 1;
212     }
213
214   external_plist_put (&f->plist, prop, value, 0, ERROR_ME);
215   return 1;
216 }
217
218 static int
219 face_remprop (Lisp_Object obj, Lisp_Object prop)
220 {
221   Lisp_Face *f = XFACE (obj);
222
223   if (EQ (prop, Qforeground)        ||
224       EQ (prop, Qbackground)        ||
225       EQ (prop, Qfont)              ||
226       EQ (prop, Qdisplay_table)     ||
227       EQ (prop, Qbackground_pixmap) ||
228       EQ (prop, Qunderline)         ||
229       EQ (prop, Qstrikethru)        ||
230       EQ (prop, Qhighlight)         ||
231       EQ (prop, Qdim)               ||
232       EQ (prop, Qblinking)          ||
233       EQ (prop, Qreverse))
234     return -1;
235
236   if (EQ (prop, Qdoc_string))
237     {
238       f->doc_string = Qnil;
239       return 1;
240     }
241
242   return external_remprop (&f->plist, prop, 0, ERROR_ME);
243 }
244
245 static Lisp_Object
246 face_plist (Lisp_Object obj)
247 {
248   Lisp_Face *face = XFACE (obj);
249   Lisp_Object result = face->plist;
250
251   result = cons3 (Qreverse,           face->reverse,           result);
252   result = cons3 (Qblinking,          face->blinking,          result);
253   result = cons3 (Qdim,               face->dim,               result);
254   result = cons3 (Qhighlight,         face->highlight,         result);
255   result = cons3 (Qstrikethru,        face->strikethru,        result);
256   result = cons3 (Qunderline,         face->underline,         result);
257   result = cons3 (Qbackground_pixmap, face->background_pixmap, result);
258   result = cons3 (Qdisplay_table,     face->display_table,     result);
259   result = cons3 (Qfont,              face->font,              result);
260   result = cons3 (Qbackground,        face->background,        result);
261   result = cons3 (Qforeground,        face->foreground,        result);
262
263   return result;
264 }
265
266 static const struct lrecord_description face_description[] = {
267   { XD_LISP_OBJECT, offsetof (Lisp_Face, name) },
268   { XD_LISP_OBJECT, offsetof (Lisp_Face, doc_string) },
269   { XD_LISP_OBJECT, offsetof (Lisp_Face, foreground) },
270   { XD_LISP_OBJECT, offsetof (Lisp_Face, background) },
271   { XD_LISP_OBJECT, offsetof (Lisp_Face, font) },
272   { XD_LISP_OBJECT, offsetof (Lisp_Face, display_table) },
273   { XD_LISP_OBJECT, offsetof (Lisp_Face, background_pixmap) },
274   { XD_LISP_OBJECT, offsetof (Lisp_Face, underline) },
275   { XD_LISP_OBJECT, offsetof (Lisp_Face, strikethru) },
276   { XD_LISP_OBJECT, offsetof (Lisp_Face, highlight) },
277   { XD_LISP_OBJECT, offsetof (Lisp_Face, dim) },
278   { XD_LISP_OBJECT, offsetof (Lisp_Face, blinking) },
279   { XD_LISP_OBJECT, offsetof (Lisp_Face, reverse) },
280   { XD_LISP_OBJECT, offsetof (Lisp_Face, plist) },
281   { XD_LISP_OBJECT, offsetof (Lisp_Face, charsets_warned_about) },
282   { XD_END }
283 };
284
285 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("face", face,
286                                           mark_face, print_face, 0, face_equal,
287                                           face_hash, face_description, face_getprop,
288                                           face_putprop, face_remprop,
289                                           face_plist, Lisp_Face);
290 \f
291 /************************************************************************/
292 /*                             face read syntax                         */
293 /************************************************************************/
294
295 static int
296 face_name_validate (Lisp_Object keyword, Lisp_Object value,
297                     Error_behavior errb)
298 {
299   if (ERRB_EQ (errb, ERROR_ME))
300     {
301       CHECK_SYMBOL (value);
302       return 1;
303     }
304
305   return SYMBOLP (value);
306 }
307
308 static int
309 face_validate (Lisp_Object data, Error_behavior errb)
310 {
311   int name_seen = 0;
312   Lisp_Object valw = Qnil;
313
314   data = Fcdr (data); /* skip over Qface */
315   while (!NILP (data))
316     {
317       Lisp_Object keyw = Fcar (data);
318
319       data = Fcdr (data);
320       valw = Fcar (data);
321       data = Fcdr (data);
322       if (EQ (keyw, Qname))
323         name_seen = 1;
324       else
325         abort ();
326     }
327
328   if (!name_seen)
329     {
330       maybe_error (Qface, errb, "No face name given");
331       return 0;
332     }
333
334   if (NILP (Ffind_face (valw)))
335     {
336       maybe_signal_simple_error ("No such face", valw, Qface, errb);
337       return 0;
338     }
339
340   return 1;
341 }
342
343 static Lisp_Object
344 face_instantiate (Lisp_Object data)
345 {
346   return Fget_face (Fcar (Fcdr (data)));
347 }
348
349 \f
350 /****************************************************************************
351  *                             utility functions                            *
352  ****************************************************************************/
353
354 static void
355 reset_face (Lisp_Face *f)
356 {
357   f->name = Qnil;
358   f->doc_string = Qnil;
359   f->dirty = 0;
360   f->foreground = Qnil;
361   f->background = Qnil;
362   f->font = Qnil;
363   f->display_table = Qnil;
364   f->background_pixmap = Qnil;
365   f->underline = Qnil;
366   f->strikethru = Qnil;
367   f->highlight = Qnil;
368   f->dim = Qnil;
369   f->blinking = Qnil;
370   f->reverse = Qnil;
371   f->plist = Qnil;
372   f->charsets_warned_about = Qnil;
373 }
374
375 static Lisp_Face *
376 allocate_face (void)
377 {
378   Lisp_Face *result = alloc_lcrecord_type (Lisp_Face, &lrecord_face);
379
380   reset_face (result);
381   return result;
382 }
383
384 \f
385 /* We store the faces in hash tables with the names as the key and the
386    actual face object as the value.  Occasionally we need to use them
387    in a list format.  These routines provide us with that. */
388 struct face_list_closure
389 {
390   Lisp_Object *face_list;
391 };
392
393 static int
394 add_face_to_list_mapper (Lisp_Object key, Lisp_Object value,
395                          void *face_list_closure)
396 {
397   /* This function can GC */
398   struct face_list_closure *fcl =
399     (struct face_list_closure *) face_list_closure;
400
401   *(fcl->face_list) = Fcons (XFACE (value)->name, (*fcl->face_list));
402   return 0;
403 }
404
405 static Lisp_Object
406 faces_list_internal (Lisp_Object list)
407 {
408   Lisp_Object face_list = Qnil;
409   struct gcpro gcpro1;
410   struct face_list_closure face_list_closure;
411
412   GCPRO1 (face_list);
413   face_list_closure.face_list = &face_list;
414   elisp_maphash (add_face_to_list_mapper, list, &face_list_closure);
415   UNGCPRO;
416
417   return face_list;
418 }
419
420 static Lisp_Object
421 permanent_faces_list (void)
422 {
423   return faces_list_internal (Vpermanent_faces_cache);
424 }
425
426 static Lisp_Object
427 temporary_faces_list (void)
428 {
429   return faces_list_internal (Vtemporary_faces_cache);
430 }
431
432 \f
433 static int
434 mark_face_as_clean_mapper (Lisp_Object key, Lisp_Object value,
435                            void *flag_closure)
436 {
437   /* This function can GC */
438   int *flag = (int *) flag_closure;
439   XFACE (value)->dirty = *flag;
440   return 0;
441 }
442
443 static void
444 mark_all_faces_internal (int flag)
445 {
446   elisp_maphash (mark_face_as_clean_mapper, Vpermanent_faces_cache, &flag);
447   elisp_maphash (mark_face_as_clean_mapper, Vtemporary_faces_cache, &flag);
448 }
449
450 void
451 mark_all_faces_as_clean (void)
452 {
453   mark_all_faces_internal (0);
454 }
455
456 /* Currently unused (see the comment in face_property_was_changed()).  */
457 #if 0
458 /* #### OBSOLETE ME, PLEASE.  Maybe.  Maybe this is just as good as
459    any other solution. */
460 struct face_inheritance_closure
461 {
462   Lisp_Object face;
463   Lisp_Object property;
464 };
465
466 static void
467 update_inheritance_mapper_internal (Lisp_Object cur_face,
468                                     Lisp_Object inh_face,
469                                     Lisp_Object property)
470 {
471   /* #### fix this function */
472   Lisp_Object elt = Qnil;
473   struct gcpro gcpro1;
474
475   GCPRO1 (elt);
476
477   for (elt = FACE_PROPERTY_SPEC_LIST (cur_face, property, Qall);
478        !NILP (elt);
479        elt = XCDR (elt))
480     {
481       Lisp_Object values = XCDR (XCAR (elt));
482
483       for (; !NILP (values); values = XCDR (values))
484         {
485           Lisp_Object value = XCDR (XCAR (values));
486           if (VECTORP (value) && XVECTOR_LENGTH (value))
487             {
488               if (EQ (Ffind_face (XVECTOR_DATA (value)[0]), inh_face))
489                 Fset_specifier_dirty_flag
490                   (FACE_PROPERTY_SPECIFIER (inh_face, property));
491             }
492         }
493     }
494
495   UNGCPRO;
496 }
497
498 static int
499 update_face_inheritance_mapper (const void *hash_key, void *hash_contents,
500                                 void *face_inheritance_closure)
501 {
502   Lisp_Object key, contents;
503   struct face_inheritance_closure *fcl =
504     (struct face_inheritance_closure *) face_inheritance_closure;
505
506   CVOID_TO_LISP (key, hash_key);
507   VOID_TO_LISP (contents, hash_contents);
508
509   if (EQ (fcl->property, Qfont))
510     {
511       update_inheritance_mapper_internal (contents, fcl->face, Qfont);
512     }
513   else if (EQ (fcl->property, Qforeground) ||
514            EQ (fcl->property, Qbackground))
515     {
516       update_inheritance_mapper_internal (contents, fcl->face, Qforeground);
517       update_inheritance_mapper_internal (contents, fcl->face, Qbackground);
518     }
519   else if (EQ (fcl->property, Qunderline)  ||
520            EQ (fcl->property, Qstrikethru) ||
521            EQ (fcl->property, Qhighlight)  ||
522            EQ (fcl->property, Qdim)        ||
523            EQ (fcl->property, Qblinking)   ||
524            EQ (fcl->property, Qreverse))
525     {
526       update_inheritance_mapper_internal (contents, fcl->face, Qunderline);
527       update_inheritance_mapper_internal (contents, fcl->face, Qstrikethru);
528       update_inheritance_mapper_internal (contents, fcl->face, Qhighlight);
529       update_inheritance_mapper_internal (contents, fcl->face, Qdim);
530       update_inheritance_mapper_internal (contents, fcl->face, Qblinking);
531       update_inheritance_mapper_internal (contents, fcl->face, Qreverse);
532     }
533   return 0;
534 }
535
536 static void
537 update_faces_inheritance (Lisp_Object face, Lisp_Object property)
538 {
539   struct face_inheritance_closure face_inheritance_closure;
540   struct gcpro gcpro1, gcpro2;
541
542   GCPRO2 (face, property);
543   face_inheritance_closure.face = face;
544   face_inheritance_closure.property = property;
545
546   elisp_maphash (update_face_inheritance_mapper, Vpermanent_faces_cache,
547                  &face_inheritance_closure);
548   elisp_maphash (update_face_inheritance_mapper, Vtemporary_faces_cache,
549                  &face_inheritance_closure);
550
551   UNGCPRO;
552 }
553 #endif /* 0 */
554
555 Lisp_Object
556 face_property_matching_instance (Lisp_Object face, Lisp_Object property,
557                                  Lisp_Object charset, Lisp_Object domain,
558                                  Error_behavior errb, int no_fallback,
559                                  Lisp_Object depth)
560 {
561   Lisp_Object retval =
562     specifier_instance_no_quit (Fget (face, property, Qnil), charset,
563                                 domain, errb, no_fallback, depth);
564
565   if (UNBOUNDP (retval) && !no_fallback)
566     {
567       if (EQ (property, Qfont))
568         {
569           if (NILP (memq_no_quit (charset,
570                                   XFACE (face)->charsets_warned_about)))
571             {
572 #ifdef MULE
573               if (! UNBOUNDP (charset))
574                 warn_when_safe
575                   (Qfont, Qwarning,
576                    "Unable to instantiate font for face %s, charset %s",
577                    string_data (symbol_name
578                                 (XSYMBOL (XFACE (face)->name))),
579                    string_data (symbol_name
580                                 (XSYMBOL (XCHARSET_NAME (charset)))));
581               else
582 #endif
583                 warn_when_safe (Qfont, Qwarning,
584                                 "Unable to instantiate font for face %s",
585                                 string_data (symbol_name
586                                              (XSYMBOL (XFACE (face)->name))));
587               XFACE (face)->charsets_warned_about =
588                 Fcons (charset, XFACE (face)->charsets_warned_about);
589             }
590           retval = Vthe_null_font_instance;
591         }
592     }
593
594   return retval;
595 }
596
597 \f
598 DEFUN ("facep", Ffacep, 1, 1, 0, /*
599 Return t if OBJECT is a face.
600 */
601        (object))
602 {
603   return FACEP (object) ? Qt : Qnil;
604 }
605
606 DEFUN ("find-face", Ffind_face, 1, 1, 0, /*
607 Retrieve the face of the given name.
608 If FACE-OR-NAME is a face object, it is simply returned.
609 Otherwise, FACE-OR-NAME should be a symbol.  If there is no such face,
610 nil is returned.  Otherwise the associated face object is returned.
611 */
612        (face_or_name))
613 {
614   Lisp_Object retval;
615
616   if (FACEP (face_or_name))
617     return face_or_name;
618   CHECK_SYMBOL (face_or_name);
619
620   /* Check if the name represents a permanent face. */
621   retval = Fgethash (face_or_name, Vpermanent_faces_cache, Qnil);
622   if (!NILP (retval))
623     return retval;
624
625   /* Check if the name represents a temporary face. */
626   return Fgethash (face_or_name, Vtemporary_faces_cache, Qnil);
627 }
628
629 DEFUN ("get-face", Fget_face, 1, 1, 0, /*
630 Retrieve the face of the given name.
631 Same as `find-face' except an error is signalled if there is no such
632 face instead of returning nil.
633 */
634        (name))
635 {
636   Lisp_Object face = Ffind_face (name);
637
638   if (NILP (face))
639     signal_simple_error ("No such face", name);
640   return face;
641 }
642
643 DEFUN ("face-name", Fface_name, 1, 1, 0, /*
644 Return the name of the given face.
645 */
646        (face))
647 {
648   return XFACE (Fget_face (face))->name;
649 }
650
651 DEFUN ("built-in-face-specifiers", Fbuilt_in_face_specifiers, 0, 0, 0, /*
652 Return a list of all built-in face specifier properties.
653 Don't modify this list!
654 */
655        ())
656 {
657   return Vbuilt_in_face_specifiers;
658 }
659
660 /* These values are retrieved so often that we make a special
661    function.
662 */
663
664 void
665 default_face_font_info (Lisp_Object domain, int *ascent, int *descent,
666                         int *height, int *width, int *proportional_p)
667 {
668   Lisp_Object font_instance;
669
670   if (noninteractive)
671     {
672       if (ascent)
673         *ascent = 1;
674       if (descent)
675         *descent = 0;
676       if (height)
677         *height = 1;
678       if (width)
679         *width = 1;
680       if (proportional_p)
681         *proportional_p = 0;
682       return;
683     }
684
685   /* We use ASCII here.  This is probably reasonable because the
686      people calling this function are using the resulting values to
687      come up with overall sizes for windows and frames. */
688   if (WINDOWP (domain))
689     {
690       struct face_cachel *cachel;
691       struct window *w = XWINDOW (domain);
692
693       /* #### It's possible for this function to get called when the
694          face cachels have not been initialized.  I don't know why. */
695       if (!Dynarr_length (w->face_cachels))
696         reset_face_cachels (w);
697       cachel = WINDOW_FACE_CACHEL (w, DEFAULT_INDEX);
698       font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
699     }
700   else
701     {
702       font_instance = FACE_FONT (Vdefault_face, domain, Vcharset_ascii);
703     }
704
705   if (height)
706     *height = XFONT_INSTANCE (font_instance)->height;
707   if (width)
708     *width = XFONT_INSTANCE (font_instance)->width;
709   if (ascent)
710     *ascent = XFONT_INSTANCE (font_instance)->ascent;
711   if (descent)
712     *descent = XFONT_INSTANCE (font_instance)->descent;
713   if (proportional_p)
714     *proportional_p = XFONT_INSTANCE (font_instance)->proportional_p;
715 }
716
717 void
718 default_face_height_and_width (Lisp_Object domain,
719                                int *height, int *width)
720 {
721   default_face_font_info (domain, 0, 0, height, width, 0);
722 }
723
724 void
725 default_face_height_and_width_1 (Lisp_Object domain,
726                                  int *height, int *width)
727 {
728   if (window_system_pixelated_geometry (domain))
729     {
730       if (height)
731         *height = 1;
732       if (width)
733         *width = 1;
734     }
735   else
736     default_face_height_and_width (domain, height, width);
737 }
738
739 DEFUN ("face-list", Fface_list, 0, 1, 0, /*
740 Return a list of the names of all defined faces.
741 If TEMPORARY is nil, only the permanent faces are included.
742 If it is t, only the temporary faces are included.  If it is any
743 other non-nil value both permanent and temporary are included.
744 */
745        (temporary))
746 {
747   Lisp_Object face_list = Qnil;
748
749   /* Added the permanent faces, if requested. */
750   if (NILP (temporary) || !EQ (Qt, temporary))
751     face_list = permanent_faces_list ();
752
753   if (!NILP (temporary))
754     {
755       struct gcpro gcpro1;
756       GCPRO1 (face_list);
757       face_list = nconc2 (face_list, temporary_faces_list ());
758       UNGCPRO;
759     }
760
761   return face_list;
762 }
763
764 DEFUN ("make-face", Fmake_face, 1, 3, 0, /*
765 Define a new face with name NAME (a symbol), described by DOC-STRING.
766 You can modify the font, color, etc. of a face with the set-face-* functions.
767 If the face already exists, it is unmodified.
768 If TEMPORARY is non-nil, this face will cease to exist if not in use.
769 */
770        (name, doc_string, temporary))
771 {
772   /* This function can GC if initialized is non-zero */
773   Lisp_Face *f;
774   Lisp_Object face;
775
776   CHECK_SYMBOL (name);
777   if (!NILP (doc_string))
778     CHECK_STRING (doc_string);
779
780   face = Ffind_face (name);
781   if (!NILP (face))
782     return face;
783
784   f = allocate_face ();
785   XSETFACE (face, f);
786
787   f->name = name;
788   f->doc_string = doc_string;
789   f->foreground = Fmake_specifier (Qcolor);
790   set_color_attached_to (f->foreground, face, Qforeground);
791   f->background = Fmake_specifier (Qcolor);
792   set_color_attached_to (f->background, face, Qbackground);
793   f->font = Fmake_specifier (Qfont);
794   set_font_attached_to (f->font, face, Qfont);
795   f->background_pixmap = Fmake_specifier (Qimage);
796   set_image_attached_to (f->background_pixmap, face, Qbackground_pixmap);
797   f->display_table = Fmake_specifier (Qdisplay_table);
798   f->underline = Fmake_specifier (Qface_boolean);
799   set_face_boolean_attached_to (f->underline, face, Qunderline);
800   f->strikethru = Fmake_specifier (Qface_boolean);
801   set_face_boolean_attached_to (f->strikethru, face, Qstrikethru);
802   f->highlight = Fmake_specifier (Qface_boolean);
803   set_face_boolean_attached_to (f->highlight, face, Qhighlight);
804   f->dim = Fmake_specifier (Qface_boolean);
805   set_face_boolean_attached_to (f->dim, face, Qdim);
806   f->blinking = Fmake_specifier (Qface_boolean);
807   set_face_boolean_attached_to (f->blinking, face, Qblinking);
808   f->reverse = Fmake_specifier (Qface_boolean);
809   set_face_boolean_attached_to (f->reverse, face, Qreverse);
810   if (!NILP (Vdefault_face))
811     {
812       /* If the default face has already been created, set it as
813          the default fallback specifier for all the specifiers we
814          just created.  This implements the standard "all faces
815          inherit from default" behavior. */
816       set_specifier_fallback (f->foreground,
817                              Fget (Vdefault_face, Qforeground, Qunbound));
818       set_specifier_fallback (f->background,
819                              Fget (Vdefault_face, Qbackground, Qunbound));
820       set_specifier_fallback (f->font,
821                              Fget (Vdefault_face, Qfont, Qunbound));
822       set_specifier_fallback (f->background_pixmap,
823                              Fget (Vdefault_face, Qbackground_pixmap,
824                                    Qunbound));
825       set_specifier_fallback (f->display_table,
826                              Fget (Vdefault_face, Qdisplay_table, Qunbound));
827       set_specifier_fallback (f->underline,
828                              Fget (Vdefault_face, Qunderline, Qunbound));
829       set_specifier_fallback (f->strikethru,
830                              Fget (Vdefault_face, Qstrikethru, Qunbound));
831       set_specifier_fallback (f->highlight,
832                              Fget (Vdefault_face, Qhighlight, Qunbound));
833       set_specifier_fallback (f->dim,
834                              Fget (Vdefault_face, Qdim, Qunbound));
835       set_specifier_fallback (f->blinking,
836                              Fget (Vdefault_face, Qblinking, Qunbound));
837       set_specifier_fallback (f->reverse,
838                              Fget (Vdefault_face, Qreverse, Qunbound));
839     }
840
841   /* Add the face to the appropriate list. */
842   if (NILP (temporary))
843     Fputhash (name, face, Vpermanent_faces_cache);
844   else
845     Fputhash (name, face, Vtemporary_faces_cache);
846
847   /* Note that it's OK if we dump faces.
848      When we start up again when we're not noninteractive,
849      `init-global-faces' is called and it resources all
850      existing faces. */
851   if (initialized && !noninteractive)
852     {
853       struct gcpro gcpro1, gcpro2;
854
855       GCPRO2 (name, face);
856       call1 (Qinit_face_from_resources, name);
857       UNGCPRO;
858     }
859
860   return face;
861 }
862
863 \f
864 /*****************************************************************************
865  initialization code
866  ****************************************************************************/
867
868 void
869 init_global_faces (struct device *d)
870 {
871   /* When making the initial terminal device, there is no Lisp code
872      loaded, so we can't do this. */
873   if (initialized && !noninteractive)
874     {
875       call_critical_lisp_code (d, Qinit_global_faces, Qnil);
876     }
877 }
878
879 void
880 init_device_faces (struct device *d)
881 {
882   /* This function can call lisp */
883
884   /* When making the initial terminal device, there is no Lisp code
885      loaded, so we can't do this. */
886   if (initialized)
887     {
888       Lisp_Object tdevice;
889       XSETDEVICE (tdevice, d);
890       call_critical_lisp_code (d, Qinit_device_faces, tdevice);
891     }
892 }
893
894 void
895 init_frame_faces (struct frame *frm)
896 {
897   /* When making the initial terminal device, there is no Lisp code
898      loaded, so we can't do this. */
899   if (initialized)
900     {
901       Lisp_Object tframe;
902       XSETFRAME (tframe, frm);
903
904       /* DO NOT change the selected frame here.  If the debugger goes off
905          it will try and display on the frame being created, but it is not
906          ready for that yet and a horrible death will occur.  Any random
907          code depending on the selected-frame as an implicit arg should be
908          tracked down and shot.  For the benefit of the one known,
909          xpm-color-symbols, make-frame sets the variable
910          Vframe_being_created to the frame it is making and sets it to nil
911          when done.  Internal functions that this could trigger which are
912          currently depending on selected-frame should use this instead.  It
913          is not currently visible at the lisp level. */
914       call_critical_lisp_code (XDEVICE (FRAME_DEVICE (frm)),
915                                Qinit_frame_faces, tframe);
916     }
917 }
918
919 \f
920 /****************************************************************************
921  *                        face cache element functions                      *
922  ****************************************************************************/
923
924 /*
925
926 #### Here is a description of how the face cache elements ought
927 to be redone.  It is *NOT* how they work currently:
928
929 However, when I started to go about implementing this, I realized
930 that there are all sorts of subtle problems with cache coherency
931 that are coming up.  As it turns out, these problems don't
932 manifest themselves now due to the brute-force "kill 'em all"
933 approach to cache invalidation when faces change; but if this
934 is ever made smarter, these problems are going to come up, and
935 some of them are very non-obvious.
936
937 I'm thinking of redoing the cache code a bit to avoid these
938 coherency problems.  The bulk of the problems will arise because
939 the current display structures have simple indices into the
940 face cache, but the cache can be changed at various times,
941 which could make the current display structures incorrect.
942 I guess the dirty and updated flags are an attempt to fix
943 this, but this approach doesn't really work.
944
945 Here's an approach that should keep things clean and unconfused:
946
947 1) Imagine a "virtual face cache" that can grow arbitrarily
948    big and for which the only thing allowed is to add new
949    elements.  Existing elements cannot be removed or changed.
950    This way, any pointers in the existing redisplay structure
951    into the cache never get screwed up. (This is important
952    because even if a cache element is out of date, if there's
953    a pointer to it then its contents still accurately describe
954    the way the text currently looks on the screen.)
955 2) Each element in the virtual cache either describes exactly
956    one face, or describes the merger of a number of faces
957    by some process.  In order to simplify things, for mergers
958    we do not record which faces or ordering was used, but
959    simply that this cache element is the result of merging.
960    Unlike the current implementation, it's important that a
961    single cache element not be used to both describe a
962    single face and describe a merger, even if all the property
963    values are the same.
964 3) Each cache element can be clean or dirty.  "Dirty" means
965    that the face that the element points to has been changed;
966    this gets set at the time the face is changed.  This
967    way, when looking up a value in the cache, you can determine
968    whether it's out of date or not.  For merged faces it
969    does not matter -- we don't record the faces or priority
970    used to create the merger, so it's impossible to look up
971    one of these faces.  We have to recompute it each time.
972    Luckily, this is fine -- doing the merge is much
973    less expensive than recomputing the properties of a
974    single face.
975 4) For each cache element, we keep a hash value. (In order
976    to hash the boolean properties, we convert each of them
977    into a different large prime number so that the hashing works
978    well.) This allows us, when comparing runes, to properly
979    determine whether the face for that rune has changed.
980    This will be especially important for TTY's, where there
981    aren't that many faces and minimizing redraw is very
982    important.
983 5) We can't actually keep an infinite cache, but that doesn't
984    really matter that much.  The only elements we care about
985    are those that are used by either the current or desired
986    display structs.  Therefore, we keep a per-window
987    redisplay iteration number, and mark each element with
988    that number as we use it.  Just after outputting the
989    window and synching the redisplay structs, we go through
990    the cache and invalidate all elements that are not clean
991    elements referring to a particular face and that do not
992    have an iteration number equal to the current one.  We
993    keep them in a chain, and use them to allocate new
994    elements when possible instead of increasing the Dynarr.
995
996    */
997
998 /* mark for GC a dynarr of face cachels. */
999
1000 void
1001 mark_face_cachels (face_cachel_dynarr *elements)
1002 {
1003   int elt;
1004
1005   if (!elements)
1006     return;
1007
1008   for (elt = 0; elt < Dynarr_length (elements); elt++)
1009     {
1010       struct face_cachel *cachel = Dynarr_atp (elements, elt);
1011
1012       {
1013         int i;
1014
1015         for (i = 0; i < NUM_LEADING_BYTES; i++)
1016           if (!NILP (cachel->font[i]) && !UNBOUNDP (cachel->font[i]))
1017             mark_object (cachel->font[i]);
1018       }
1019       mark_object (cachel->face);
1020       mark_object (cachel->foreground);
1021       mark_object (cachel->background);
1022       mark_object (cachel->display_table);
1023       mark_object (cachel->background_pixmap);
1024     }
1025 }
1026
1027 /* ensure that the given cachel contains an updated font value for
1028    the given charset.  Return the updated font value. */
1029
1030 Lisp_Object
1031 ensure_face_cachel_contains_charset (struct face_cachel *cachel,
1032                                      Lisp_Object domain, Lisp_Object charset)
1033 {
1034   Lisp_Object new_val;
1035   Lisp_Object face = cachel->face;
1036   int bound = 1;
1037   int offs = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
1038
1039   if (!UNBOUNDP (cachel->font[offs])
1040       && cachel->font_updated[offs])
1041     return cachel->font[offs];
1042
1043   if (UNBOUNDP (face))
1044     {
1045       /* a merged face. */
1046       int i;
1047       struct window *w = XWINDOW (domain);
1048
1049       new_val = Qunbound;
1050       cachel->font_specified[offs] = 0;
1051       for (i = 0; i < cachel->nfaces; i++)
1052         {
1053           struct face_cachel *oth;
1054
1055           oth = Dynarr_atp (w->face_cachels,
1056                             FACE_CACHEL_FINDEX_UNSAFE (cachel, i));
1057           /* Tout le monde aime la recursion */
1058           ensure_face_cachel_contains_charset (oth, domain, charset);
1059
1060           if (oth->font_specified[offs])
1061             {
1062               new_val = oth->font[offs];
1063               cachel->font_specified[offs] = 1;
1064               break;
1065             }
1066         }
1067
1068       if (!cachel->font_specified[offs])
1069         /* need to do the default face. */
1070         {
1071           struct face_cachel *oth =
1072             Dynarr_atp (w->face_cachels, DEFAULT_INDEX);
1073           ensure_face_cachel_contains_charset (oth, domain, charset);
1074
1075           new_val = oth->font[offs];
1076         }
1077
1078       if (!UNBOUNDP (cachel->font[offs]) && !EQ (cachel->font[offs], new_val))
1079         cachel->dirty = 1;
1080       cachel->font_updated[offs] = 1;
1081       cachel->font[offs] = new_val;
1082       return new_val;
1083     }
1084
1085   new_val = face_property_matching_instance (face, Qfont, charset, domain,
1086                                              /* #### look into ERROR_ME_NOT */
1087                                              ERROR_ME_NOT, 1, Qzero);
1088   if (UNBOUNDP (new_val))
1089     {
1090       bound = 0;
1091       new_val = face_property_matching_instance (face, Qfont,
1092                                                  charset, domain,
1093                                                  /* #### look into
1094                                                     ERROR_ME_NOT */
1095                                                  ERROR_ME_NOT, 0, Qzero);
1096     }
1097   if (!UNBOUNDP (cachel->font[offs]) && !EQ (new_val, cachel->font[offs]))
1098     cachel->dirty = 1;
1099   cachel->font_updated[offs] = 1;
1100   cachel->font[offs] = new_val;
1101   cachel->font_specified[offs] = (bound || EQ (face, Vdefault_face));
1102   return new_val;
1103 }
1104
1105 /* Ensure that the given cachel contains updated fonts for all
1106    the charsets specified. */
1107
1108 void
1109 ensure_face_cachel_complete (struct face_cachel *cachel,
1110                              Lisp_Object domain, unsigned char *charsets)
1111 {
1112   int i;
1113
1114   for (i = 0; i < NUM_LEADING_BYTES; i++)
1115     if (charsets[i])
1116       {
1117         Lisp_Object charset = CHARSET_BY_LEADING_BYTE (i + MIN_LEADING_BYTE);
1118         assert (CHARSETP (charset));
1119         ensure_face_cachel_contains_charset (cachel, domain, charset);
1120       }
1121 }
1122
1123 void
1124 face_cachel_charset_font_metric_info (struct face_cachel *cachel,
1125                                       unsigned char *charsets,
1126                                       struct font_metric_info *fm)
1127 {
1128   int i;
1129
1130   fm->width = 1;
1131   fm->height = fm->ascent = 1;
1132   fm->descent = 0;
1133   fm->proportional_p = 0;
1134
1135   for (i = 0; i < NUM_LEADING_BYTES; i++)
1136     {
1137       if (charsets[i])
1138         {
1139           Lisp_Object charset = CHARSET_BY_LEADING_BYTE (i + MIN_LEADING_BYTE);
1140           Lisp_Object font_instance = FACE_CACHEL_FONT (cachel, charset);
1141           Lisp_Font_Instance *fi = XFONT_INSTANCE (font_instance);
1142
1143           assert (CHARSETP (charset));
1144           assert (FONT_INSTANCEP (font_instance));
1145
1146           if (fm->ascent  < (int) fi->ascent)  fm->ascent  = (int) fi->ascent;
1147           if (fm->descent < (int) fi->descent) fm->descent = (int) fi->descent;
1148           fm->height = fm->ascent + fm->descent;
1149           if (fi->proportional_p)
1150             fm->proportional_p = 1;
1151           if (EQ (charset, Vcharset_ascii))
1152             fm->width = fi->width;
1153         }
1154     }
1155 }
1156
1157 /* Called when the updated flag has been cleared on a cachel. */
1158
1159 void
1160 update_face_cachel_data (struct face_cachel *cachel,
1161                          Lisp_Object domain,
1162                          Lisp_Object face)
1163 {
1164   if (XFACE (face)->dirty || UNBOUNDP (cachel->face))
1165     {
1166       int default_face = EQ (face, Vdefault_face);
1167       cachel->face = face;
1168
1169       /* We normally only set the _specified flags if the value was
1170          actually bound.  The exception is for the default face where
1171          we always set it since it is the ultimate fallback. */
1172
1173 #define FROB(field)                                                          \
1174   do {                                                                       \
1175     Lisp_Object new_val =                                                    \
1176       FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero);             \
1177     int bound = 1;                                                           \
1178     if (UNBOUNDP (new_val))                                                  \
1179       {                                                                      \
1180         bound = 0;                                                           \
1181         new_val = FACE_PROPERTY_INSTANCE (face, Q##field, domain, 0, Qzero); \
1182       }                                                                      \
1183     if (!EQ (new_val, cachel->field))                                        \
1184       {                                                                      \
1185         cachel->field = new_val;                                             \
1186         cachel->dirty = 1;                                                   \
1187       }                                                                      \
1188     cachel->field##_specified = (bound || default_face);                     \
1189   } while (0)
1190
1191       FROB (foreground);
1192       FROB (background);
1193       FROB (display_table);
1194       FROB (background_pixmap);
1195
1196       /*
1197        * A face's background pixmap will override the face's
1198        * background color.  But the background pixmap of the
1199        * default face should not override the background color of
1200        * a face if the background color has been specified or
1201        * inherited.
1202        *
1203        * To accomplish this we remove the background pixmap of the
1204        * cachel and mark it as having been specified so that cachel
1205        * merging won't override it later.
1206        */
1207       if (! default_face
1208           && cachel->background_specified
1209           && ! cachel->background_pixmap_specified)
1210         {
1211           cachel->background_pixmap = Qunbound;
1212           cachel->background_pixmap_specified = 1;
1213         }
1214
1215 #undef FROB
1216
1217       ensure_face_cachel_contains_charset (cachel, domain, Vcharset_ascii);
1218
1219 #define FROB(field)                                                          \
1220   do {                                                                       \
1221     Lisp_Object new_val =                                                    \
1222       FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero);             \
1223     int bound = 1;                                                           \
1224     unsigned int new_val_int;                                                \
1225     if (UNBOUNDP (new_val))                                                  \
1226       {                                                                      \
1227         bound = 0;                                                           \
1228         new_val = FACE_PROPERTY_INSTANCE (face, Q##field, domain, 0, Qzero); \
1229       }                                                                      \
1230     new_val_int = EQ (new_val, Qt);                                          \
1231     if (cachel->field != new_val_int)                                        \
1232       {                                                                      \
1233         cachel->field = new_val_int;                                         \
1234         cachel->dirty = 1;                                                   \
1235       }                                                                      \
1236     cachel->field##_specified = bound;                                       \
1237   } while (0)
1238
1239       FROB (underline);
1240       FROB (strikethru);
1241       FROB (highlight);
1242       FROB (dim);
1243       FROB (reverse);
1244       FROB (blinking);
1245 #undef FROB
1246     }
1247
1248   cachel->updated = 1;
1249 }
1250
1251 /* Merge the cachel identified by FINDEX in window W into the given
1252    cachel. */
1253
1254 static void
1255 merge_face_cachel_data (struct window *w, face_index findex,
1256                         struct face_cachel *cachel)
1257 {
1258 #define FINDEX_FIELD(field)                                             \
1259   Dynarr_atp (w->face_cachels, findex)->field
1260
1261 #define FROB(field)                                                     \
1262   do {                                                                  \
1263     if (!cachel->field##_specified && FINDEX_FIELD (field##_specified)) \
1264       {                                                                 \
1265         cachel->field = FINDEX_FIELD (field);                           \
1266         cachel->field##_specified = 1;                                  \
1267         cachel->dirty = 1;                                              \
1268       }                                                                 \
1269   } while (0)
1270
1271   FROB (foreground);
1272   FROB (background);
1273   FROB (display_table);
1274   FROB (background_pixmap);
1275   FROB (underline);
1276   FROB (strikethru);
1277   FROB (highlight);
1278   FROB (dim);
1279   FROB (reverse);
1280   FROB (blinking);
1281   /* And do ASCII, of course. */
1282   {
1283     int offs = LEADING_BYTE_ASCII - MIN_LEADING_BYTE;
1284
1285     if (!cachel->font_specified[offs] && FINDEX_FIELD (font_specified[offs]))
1286       {
1287         cachel->font[offs] = FINDEX_FIELD (font[offs]);
1288         cachel->font_specified[offs] = 1;
1289         cachel->dirty = 1;
1290       }
1291   }
1292
1293 #undef FROB
1294 #undef FINDEX_FIELD
1295
1296   cachel->updated = 1;
1297 }
1298
1299 /* Initialize a cachel. */
1300
1301 void
1302 reset_face_cachel (struct face_cachel *cachel)
1303 {
1304   xzero (*cachel);
1305   cachel->face = Qunbound;
1306   cachel->nfaces = 0;
1307   cachel->merged_faces = 0;
1308   cachel->foreground = Qunbound;
1309   cachel->background = Qunbound;
1310   {
1311     int i;
1312
1313     for (i = 0; i < NUM_LEADING_BYTES; i++)
1314       cachel->font[i] = Qunbound;
1315   }
1316   cachel->display_table = Qunbound;
1317   cachel->background_pixmap = Qunbound;
1318 }
1319
1320 /* Add a cachel for the given face to the given window's cache. */
1321
1322 static void
1323 add_face_cachel (struct window *w, Lisp_Object face)
1324 {
1325   struct face_cachel new_cachel;
1326   Lisp_Object window;
1327
1328   reset_face_cachel (&new_cachel);
1329   XSETWINDOW (window, w);
1330   update_face_cachel_data (&new_cachel, window, face);
1331   Dynarr_add (w->face_cachels, new_cachel);
1332 }
1333
1334 /* Retrieve the index to a cachel for window W that corresponds to
1335    the specified face.  If necessary, add a new element to the
1336    cache. */
1337
1338 face_index
1339 get_builtin_face_cache_index (struct window *w, Lisp_Object face)
1340 {
1341   int elt;
1342
1343   if (noninteractive)
1344     return 0;
1345
1346   for (elt = 0; elt < Dynarr_length (w->face_cachels); elt++)
1347     {
1348       struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, elt);
1349
1350       if (EQ (cachel->face, face))
1351         {
1352           Lisp_Object window;
1353           XSETWINDOW (window, w);
1354           if (!cachel->updated)
1355             update_face_cachel_data (cachel, window, face);
1356           return elt;
1357         }
1358     }
1359
1360   /* If we didn't find the face, add it and then return its index. */
1361   add_face_cachel (w, face);
1362   return elt;
1363 }
1364
1365 void
1366 reset_face_cachels (struct window *w)
1367 {
1368   /* #### Not initialized in batch mode for the stream device. */
1369   if (w->face_cachels)
1370     {
1371       int i;
1372
1373       for (i = 0; i < Dynarr_length (w->face_cachels); i++)
1374         {
1375           struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
1376           if (cachel->merged_faces)
1377             Dynarr_free (cachel->merged_faces);
1378         }
1379       Dynarr_reset (w->face_cachels);
1380       get_builtin_face_cache_index (w, Vdefault_face);
1381       get_builtin_face_cache_index (w, Vmodeline_face);
1382       XFRAME (w->frame)->window_face_cache_reset = 1;
1383     }
1384 }
1385
1386 void
1387 mark_face_cachels_as_clean (struct window *w)
1388 {
1389   int elt;
1390
1391   for (elt = 0; elt < Dynarr_length (w->face_cachels); elt++)
1392     Dynarr_atp (w->face_cachels, elt)->dirty = 0;
1393 }
1394
1395 void
1396 mark_face_cachels_as_not_updated (struct window *w)
1397 {
1398   int elt;
1399
1400   for (elt = 0; elt < Dynarr_length (w->face_cachels); elt++)
1401     {
1402       struct face_cachel *cachel = Dynarr_atp (w->face_cachels, elt);
1403       int i;
1404
1405       cachel->updated = 0;
1406       for (i = 0; i < NUM_LEADING_BYTES; i++)
1407         cachel->font_updated[i] = 0;
1408     }
1409 }
1410
1411 #ifdef MEMORY_USAGE_STATS
1412
1413 int
1414 compute_face_cachel_usage (face_cachel_dynarr *face_cachels,
1415                            struct overhead_stats *ovstats)
1416 {
1417   int total = 0;
1418
1419   if (face_cachels)
1420     {
1421       int i;
1422
1423       total += Dynarr_memory_usage (face_cachels, ovstats);
1424       for (i = 0; i < Dynarr_length (face_cachels); i++)
1425         {
1426           int_dynarr *merged = Dynarr_at (face_cachels, i).merged_faces;
1427           if (merged)
1428             total += Dynarr_memory_usage (merged, ovstats);
1429         }
1430     }
1431
1432   return total;
1433 }
1434
1435 #endif /* MEMORY_USAGE_STATS */
1436
1437 \f
1438 /*****************************************************************************
1439  *                             merged face functions                         *
1440  *****************************************************************************/
1441
1442 /* Compare two merged face cachels to determine whether we have to add
1443    a new entry to the face cache.
1444
1445    Note that we do not compare the attributes, but just the faces the
1446    cachels are based on.  If they are the same, then the cachels certainly
1447    ought to have the same attributes, except in the case where fonts
1448    for different charsets have been determined in the two -- and in that
1449    case this difference is fine. */
1450
1451 static int
1452 compare_merged_face_cachels (struct face_cachel *cachel1,
1453                              struct face_cachel *cachel2)
1454 {
1455   int i;
1456
1457   if (!EQ (cachel1->face, cachel2->face)
1458       || cachel1->nfaces != cachel2->nfaces)
1459     return 0;
1460
1461   for (i = 0; i < cachel1->nfaces; i++)
1462     if (FACE_CACHEL_FINDEX_UNSAFE (cachel1, i)
1463         != FACE_CACHEL_FINDEX_UNSAFE (cachel2, i))
1464       return 0;
1465
1466   return 1;
1467 }
1468
1469 /* Retrieve the index to a cachel for window W that corresponds to
1470    the specified cachel.  If necessary, add a new element to the
1471    cache.  This is similar to get_builtin_face_cache_index() but
1472    is intended for merged cachels rather than for cachels representing
1473    just a face.
1474
1475    Note that a merged cachel for just one face is not the same as
1476    the simple cachel for that face, because it is also merged with
1477    the default face. */
1478
1479 static face_index
1480 get_merged_face_cache_index (struct window *w,
1481                              struct face_cachel *merged_cachel)
1482 {
1483   int elt;
1484   int cache_size = Dynarr_length (w->face_cachels);
1485
1486   for (elt = 0; elt < cache_size; elt++)
1487     {
1488       struct face_cachel *cachel =
1489         Dynarr_atp (w->face_cachels, elt);
1490
1491       if (compare_merged_face_cachels (cachel, merged_cachel))
1492         return elt;
1493     }
1494
1495   /* We didn't find it so add this instance to the cache. */
1496   merged_cachel->updated = 1;
1497   merged_cachel->dirty = 1;
1498   Dynarr_add (w->face_cachels, *merged_cachel);
1499   return cache_size;
1500 }
1501
1502 face_index
1503 get_extent_fragment_face_cache_index (struct window *w,
1504                                       struct extent_fragment *ef)
1505 {
1506   struct face_cachel cachel;
1507   int len = Dynarr_length (ef->extents);
1508   face_index findex = 0;
1509   Lisp_Object window;
1510   XSETWINDOW (window, w);
1511
1512   /* Optimize the default case. */
1513   if (len == 0)
1514     return DEFAULT_INDEX;
1515   else
1516     {
1517       int i;
1518
1519       /* Merge the faces of the extents together in order. */
1520
1521       reset_face_cachel (&cachel);
1522
1523       for (i = len - 1; i >= 0; i--)
1524         {
1525           EXTENT current = Dynarr_at (ef->extents, i);
1526           int has_findex = 0;
1527           Lisp_Object face = extent_face (current);
1528
1529           if (FACEP (face))
1530             {
1531               findex = get_builtin_face_cache_index (w, face);
1532               has_findex = 1;
1533               merge_face_cachel_data (w, findex, &cachel);
1534             }
1535           /* remember, we're called from within redisplay
1536              so we can't error. */
1537           else while (CONSP (face))
1538             {
1539               Lisp_Object one_face = XCAR (face);
1540               if (FACEP (one_face))
1541                 {
1542                   findex = get_builtin_face_cache_index (w, one_face);
1543                   merge_face_cachel_data (w, findex, &cachel);
1544
1545                   /* code duplication here but there's no clean
1546                      way to avoid it. */
1547                   if (cachel.nfaces >= NUM_STATIC_CACHEL_FACES)
1548                     {
1549                       if (!cachel.merged_faces)
1550                         cachel.merged_faces = Dynarr_new (int);
1551                       Dynarr_add (cachel.merged_faces, findex);
1552                     }
1553                   else
1554                     cachel.merged_faces_static[cachel.nfaces] = findex;
1555                   cachel.nfaces++;
1556                 }
1557               face = XCDR (face);
1558             }
1559
1560           if (has_findex)
1561             {
1562               if (cachel.nfaces >= NUM_STATIC_CACHEL_FACES)
1563                 {
1564                   if (!cachel.merged_faces)
1565                     cachel.merged_faces = Dynarr_new (int);
1566                   Dynarr_add (cachel.merged_faces, findex);
1567                 }
1568               else
1569                 cachel.merged_faces_static[cachel.nfaces] = findex;
1570               cachel.nfaces++;
1571             }
1572         }
1573
1574       /* Now finally merge in the default face. */
1575       findex = get_builtin_face_cache_index (w, Vdefault_face);
1576       merge_face_cachel_data (w, findex, &cachel);
1577
1578       findex = get_merged_face_cache_index (w, &cachel);
1579       if (cachel.merged_faces &&
1580           /* merged_faces did not get stored and available via return value */
1581           Dynarr_at (w->face_cachels, findex).merged_faces !=
1582           cachel.merged_faces)
1583         {
1584           Dynarr_free (cachel.merged_faces);
1585           cachel.merged_faces = 0;
1586         }
1587       return findex;
1588     }
1589 }
1590
1591 \f
1592 /*****************************************************************************
1593  interface functions
1594  ****************************************************************************/
1595
1596 static void
1597 update_EmacsFrame (Lisp_Object frame, Lisp_Object name)
1598 {
1599   struct frame *frm = XFRAME (frame);
1600
1601   if (EQ (name, Qfont))
1602     MARK_FRAME_SIZE_SLIPPED (frm);
1603
1604   MAYBE_FRAMEMETH (frm, update_frame_external_traits, (frm, name));
1605 }
1606
1607 static void
1608 update_EmacsFrames (Lisp_Object locale, Lisp_Object name)
1609 {
1610   if (FRAMEP (locale))
1611     {
1612       update_EmacsFrame (locale, name);
1613     }
1614   else if (DEVICEP (locale))
1615     {
1616       Lisp_Object frmcons;
1617
1618       DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
1619         update_EmacsFrame (XCAR (frmcons), name);
1620     }
1621   else if (EQ (locale, Qglobal) || EQ (locale, Qfallback))
1622     {
1623       Lisp_Object frmcons, devcons, concons;
1624
1625       FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
1626         update_EmacsFrame (XCAR (frmcons), name);
1627     }
1628 }
1629
1630 void
1631 update_frame_face_values (struct frame *f)
1632 {
1633   Lisp_Object frm;
1634
1635   XSETFRAME (frm, f);
1636   update_EmacsFrame (frm, Qforeground);
1637   update_EmacsFrame (frm, Qbackground);
1638   update_EmacsFrame (frm, Qfont);
1639 }
1640
1641 void
1642 face_property_was_changed (Lisp_Object face, Lisp_Object property,
1643                            Lisp_Object locale)
1644 {
1645   int default_face = EQ (face, Vdefault_face);
1646
1647   /* If the locale could affect the frame value, then call
1648      update_EmacsFrames just in case. */
1649   if (default_face &&
1650       (EQ (property, Qforeground) ||
1651        EQ (property, Qbackground) ||
1652        EQ (property, Qfont)))
1653     update_EmacsFrames (locale, property);
1654
1655   if (WINDOWP (locale))
1656     {
1657       MARK_FRAME_FACES_CHANGED (XFRAME (XWINDOW (locale)->frame));
1658     }
1659   else if (FRAMEP (locale))
1660     {
1661       MARK_FRAME_FACES_CHANGED (XFRAME (locale));
1662     }
1663   else if (DEVICEP (locale))
1664     {
1665       MARK_DEVICE_FRAMES_FACES_CHANGED (XDEVICE (locale));
1666     }
1667   else
1668     {
1669       Lisp_Object devcons, concons;
1670       DEVICE_LOOP_NO_BREAK (devcons, concons)
1671         MARK_DEVICE_FRAMES_FACES_CHANGED (XDEVICE (XCAR (devcons)));
1672     }
1673
1674   /*
1675    * This call to update_faces_inheritance isn't needed and makes
1676    * creating and modifying faces _very_ slow.  The point of
1677    * update_face_inheritances is to find all faces that inherit
1678    * directly from this face property and set the specifier "dirty"
1679    * flag on the corresponding specifier.  This forces recaching of
1680    * cached specifier values in frame and window struct slots.  But
1681    * currently no face properties are cached in frame and window
1682    * struct slots, so calling this function does nothing useful!
1683    *
1684    * Further, since update_faces_inheritance maps over the whole
1685    * face table every time it is called, it gets terribly slow when
1686    * there are many faces.  Creating 500 faces on a 50Mhz 486 took
1687    * 433 seconds when update_faces_inheritance was called.  With the
1688    * call commented out, creating those same 500 faces took 0.72
1689    * seconds.
1690    */
1691   /* update_faces_inheritance (face, property);*/
1692   XFACE (face)->dirty = 1;
1693 }
1694
1695 DEFUN ("copy-face", Fcopy_face, 2, 6, 0, /*
1696 Define and return a new face which is a copy of an existing one,
1697 or makes an already-existing face be exactly like another.
1698 LOCALE, TAG-SET, EXACT-P, and HOW-TO-ADD are as in `copy-specifier'.
1699 */
1700        (old_face, new_name, locale, tag_set, exact_p, how_to_add))
1701 {
1702   Lisp_Face *fold, *fnew;
1703   Lisp_Object new_face = Qnil;
1704   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1705
1706   old_face = Fget_face (old_face);
1707
1708   /* We GCPRO old_face because it might be temporary, and GCing could
1709      occur in various places below. */
1710   GCPRO4 (tag_set, locale, old_face, new_face);
1711   /* check validity of how_to_add now. */
1712   decode_how_to_add_specification (how_to_add);
1713   /* and of tag_set. */
1714   tag_set = decode_specifier_tag_set (tag_set);
1715   /* and of locale. */
1716   locale = decode_locale_list (locale);
1717
1718   new_face = Ffind_face (new_name);
1719   if (NILP (new_face))
1720     {
1721       Lisp_Object temp;
1722
1723       CHECK_SYMBOL (new_name);
1724
1725       /* Create the new face with the same status as the old face. */
1726       temp = (NILP (Fgethash (old_face, Vtemporary_faces_cache, Qnil))
1727               ? Qnil
1728               : Qt);
1729
1730       new_face = Fmake_face (new_name, Qnil, temp);
1731     }
1732
1733   fold = XFACE (old_face);
1734   fnew = XFACE (new_face);
1735
1736 #define COPY_PROPERTY(property) \
1737   Fcopy_specifier (fold->property, fnew->property, \
1738                    locale, tag_set, exact_p, how_to_add);
1739
1740   COPY_PROPERTY (foreground);
1741   COPY_PROPERTY (background);
1742   COPY_PROPERTY (font);
1743   COPY_PROPERTY (display_table);
1744   COPY_PROPERTY (background_pixmap);
1745   COPY_PROPERTY (underline);
1746   COPY_PROPERTY (strikethru);
1747   COPY_PROPERTY (highlight);
1748   COPY_PROPERTY (dim);
1749   COPY_PROPERTY (blinking);
1750   COPY_PROPERTY (reverse);
1751 #undef COPY_PROPERTY
1752   /* #### should it copy the individual specifiers, if they exist? */
1753   fnew->plist = Fcopy_sequence (fold->plist);
1754
1755   UNGCPRO;
1756
1757   return new_name;
1758 }
1759
1760 \f
1761 void
1762 syms_of_faces (void)
1763 {
1764   INIT_LRECORD_IMPLEMENTATION (face);
1765
1766   /* Qdefault, Qwidget, Qleft_margin, Qright_margin defined in general.c */
1767   defsymbol (&Qmodeline, "modeline");
1768   defsymbol (&Qgui_element, "gui-element");
1769   defsymbol (&Qtext_cursor, "text-cursor");
1770   defsymbol (&Qvertical_divider, "vertical-divider");
1771
1772   DEFSUBR (Ffacep);
1773   DEFSUBR (Ffind_face);
1774   DEFSUBR (Fget_face);
1775   DEFSUBR (Fface_name);
1776   DEFSUBR (Fbuilt_in_face_specifiers);
1777   DEFSUBR (Fface_list);
1778   DEFSUBR (Fmake_face);
1779   DEFSUBR (Fcopy_face);
1780
1781   defsymbol (&Qfacep, "facep");
1782   defsymbol (&Qforeground, "foreground");
1783   defsymbol (&Qbackground, "background");
1784   /* Qfont defined in general.c */
1785   defsymbol (&Qdisplay_table, "display-table");
1786   defsymbol (&Qbackground_pixmap, "background-pixmap");
1787   defsymbol (&Qunderline, "underline");
1788   defsymbol (&Qstrikethru, "strikethru");
1789   /* Qhighlight, Qreverse defined in general.c */
1790   defsymbol (&Qdim, "dim");
1791   defsymbol (&Qblinking, "blinking");
1792
1793   defsymbol (&Qinit_face_from_resources, "init-face-from-resources");
1794   defsymbol (&Qinit_global_faces, "init-global-faces");
1795   defsymbol (&Qinit_device_faces, "init-device-faces");
1796   defsymbol (&Qinit_frame_faces, "init-frame-faces");
1797 }
1798
1799 void
1800 structure_type_create_faces (void)
1801 {
1802   struct structure_type *st;
1803
1804   st = define_structure_type (Qface, face_validate, face_instantiate);
1805
1806   define_structure_type_keyword (st, Qname, face_name_validate);
1807 }
1808
1809 void
1810 vars_of_faces (void)
1811 {
1812   staticpro (&Vpermanent_faces_cache);
1813   Vpermanent_faces_cache = Qnil;
1814   staticpro (&Vtemporary_faces_cache);
1815   Vtemporary_faces_cache = Qnil;
1816
1817   staticpro (&Vdefault_face);
1818   Vdefault_face = Qnil;
1819   staticpro (&Vgui_element_face);
1820   Vgui_element_face = Qnil;
1821   staticpro (&Vwidget_face);
1822   Vwidget_face = Qnil;
1823   staticpro (&Vmodeline_face);
1824   Vmodeline_face = Qnil;
1825   staticpro (&Vtoolbar_face);
1826   Vtoolbar_face = Qnil;
1827
1828   staticpro (&Vvertical_divider_face);
1829   Vvertical_divider_face = Qnil;
1830   staticpro (&Vleft_margin_face);
1831   Vleft_margin_face = Qnil;
1832   staticpro (&Vright_margin_face);
1833   Vright_margin_face = Qnil;
1834   staticpro (&Vtext_cursor_face);
1835   Vtext_cursor_face = Qnil;
1836   staticpro (&Vpointer_face);
1837   Vpointer_face = Qnil;
1838
1839   {
1840     Lisp_Object syms[20];
1841     int n = 0;
1842
1843     syms[n++] = Qforeground;
1844     syms[n++] = Qbackground;
1845     syms[n++] = Qfont;
1846     syms[n++] = Qdisplay_table;
1847     syms[n++] = Qbackground_pixmap;
1848     syms[n++] = Qunderline;
1849     syms[n++] = Qstrikethru;
1850     syms[n++] = Qhighlight;
1851     syms[n++] = Qdim;
1852     syms[n++] = Qblinking;
1853     syms[n++] = Qreverse;
1854
1855     Vbuilt_in_face_specifiers = Flist (n, syms);
1856     staticpro (&Vbuilt_in_face_specifiers);
1857   }
1858 }
1859
1860 void
1861 complex_vars_of_faces (void)
1862 {
1863   Vpermanent_faces_cache =
1864     make_lisp_hash_table (10, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1865   Vtemporary_faces_cache =
1866     make_lisp_hash_table (0, HASH_TABLE_WEAK, HASH_TABLE_EQ);
1867
1868   /* Create the default face now so we know what it is immediately. */
1869
1870   Vdefault_face = Qnil; /* so that Fmake_face() doesn't set up a bogus
1871                            default value */
1872   Vdefault_face = Fmake_face (Qdefault, build_string ("default face"),
1873                               Qnil);
1874
1875   /* Provide some last-resort fallbacks to avoid utter fuckage if
1876      someone provides invalid values for the global specifications. */
1877
1878   {
1879     Lisp_Object fg_fb = Qnil, bg_fb = Qnil;
1880
1881 #ifdef HAVE_X_WINDOWS
1882     fg_fb = acons (list1 (Qx), build_string ("black"), fg_fb);
1883     bg_fb = acons (list1 (Qx), build_string ("white"), bg_fb);
1884 #endif
1885 #ifdef HAVE_TTY
1886     fg_fb = acons (list1 (Qtty), Fvector (0, 0), fg_fb);
1887     bg_fb = acons (list1 (Qtty), Fvector (0, 0), bg_fb);
1888 #endif
1889 #ifdef HAVE_MS_WINDOWS
1890     fg_fb = acons (list1 (Qmsprinter), build_string ("black"), fg_fb);
1891     bg_fb = acons (list1 (Qmsprinter), build_string ("white"), bg_fb);
1892     fg_fb = acons (list1 (Qmswindows), build_string ("black"), fg_fb);
1893     bg_fb = acons (list1 (Qmswindows), build_string ("white"), bg_fb);
1894 #endif
1895     set_specifier_fallback (Fget (Vdefault_face, Qforeground, Qnil), fg_fb);
1896     set_specifier_fallback (Fget (Vdefault_face, Qbackground, Qnil), bg_fb);
1897   }
1898
1899   /* #### We may want to have different fallback values if NeXTstep
1900      support is compiled in. */
1901   {
1902     Lisp_Object inst_list = Qnil;
1903 #ifdef HAVE_X_WINDOWS
1904     /* The same gory list from x-faces.el.
1905        (#### Perhaps we should remove the stuff from x-faces.el
1906        and only depend on this stuff here?  That should work.)
1907      */
1908     const char *fonts[] =
1909     {
1910       "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*",
1911       "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*",
1912       "-*-courier-*-r-*-*-*-120-*-*-*-*-iso8859-*",
1913       "-*-*-medium-r-*-*-*-120-*-*-m-*-iso8859-*",
1914       "-*-*-medium-r-*-*-*-120-*-*-c-*-iso8859-*",
1915       "-*-*-*-r-*-*-*-120-*-*-m-*-iso8859-*",
1916       "-*-*-*-r-*-*-*-120-*-*-c-*-iso8859-*",
1917       "-*-*-*-r-*-*-*-120-*-*-*-*-iso8859-*",
1918       "-*-*-medium-r-*-*-*-120-*-*-m-*-*-*",
1919       "-*-*-medium-r-*-*-*-120-*-*-c-*-*-*",
1920       "-*-*-*-r-*-*-*-120-*-*-m-*-*-*",
1921       "-*-*-*-r-*-*-*-120-*-*-c-*-*-*",
1922       "-*-*-*-r-*-*-*-120-*-*-*-*-*-*",
1923       "-*-*-*-*-*-*-*-120-*-*-*-*-*-*",
1924       "*"
1925     };
1926     const char **fontptr;
1927
1928     for (fontptr = fonts + countof(fonts) - 1; fontptr >= fonts; fontptr--)
1929       inst_list = Fcons (Fcons (list1 (Qx), build_string (*fontptr)),
1930                          inst_list);
1931 #endif /* HAVE_X_WINDOWS */
1932
1933 #ifdef HAVE_TTY
1934     inst_list = Fcons (Fcons (list1 (Qtty), build_string ("normal")),
1935                        inst_list);
1936 #endif /* HAVE_TTY */
1937 #ifdef HAVE_MS_WINDOWS
1938     /* Fixedsys does not exist for printers */
1939     inst_list = Fcons (Fcons (list1 (Qmsprinter),
1940                        build_string ("Courier:Regular:10::Western")), inst_list);
1941     inst_list = Fcons (Fcons (list1 (Qmsprinter),
1942                        build_string ("Courier New:Regular:10::Western")), inst_list);
1943
1944     inst_list = Fcons (Fcons (list1 (Qmswindows),
1945                        build_string ("Fixedsys:Regular:9::Western")), inst_list);
1946     inst_list = Fcons (Fcons (list1 (Qmswindows),
1947                        build_string ("Courier:Regular:10::Western")), inst_list);
1948     inst_list = Fcons (Fcons (list1 (Qmswindows),
1949                        build_string ("Courier New:Regular:10::Western")), inst_list);
1950 #endif /* HAVE_MS_WINDOWS */
1951     set_specifier_fallback (Fget (Vdefault_face, Qfont, Qnil), inst_list);
1952   }
1953
1954   set_specifier_fallback (Fget (Vdefault_face, Qunderline, Qnil),
1955                          list1 (Fcons (Qnil, Qnil)));
1956   set_specifier_fallback (Fget (Vdefault_face, Qstrikethru, Qnil),
1957                          list1 (Fcons (Qnil, Qnil)));
1958   set_specifier_fallback (Fget (Vdefault_face, Qhighlight, Qnil),
1959                          list1 (Fcons (Qnil, Qnil)));
1960   set_specifier_fallback (Fget (Vdefault_face, Qdim, Qnil),
1961                          list1 (Fcons (Qnil, Qnil)));
1962   set_specifier_fallback (Fget (Vdefault_face, Qblinking, Qnil),
1963                          list1 (Fcons (Qnil, Qnil)));
1964   set_specifier_fallback (Fget (Vdefault_face, Qreverse, Qnil),
1965                          list1 (Fcons (Qnil, Qnil)));
1966
1967   /* gui-element is the parent face of all gui elements such as
1968      modeline, vertical divider and toolbar. */
1969   Vgui_element_face = Fmake_face (Qgui_element,
1970                                   build_string ("gui element face"),
1971                                   Qnil);
1972
1973   /* Provide some last-resort fallbacks for gui-element face which
1974      mustn't default to default. */
1975   {
1976     Lisp_Object fg_fb = Qnil, bg_fb = Qnil;
1977
1978 #ifdef HAVE_X_WINDOWS
1979     fg_fb = acons (list1 (Qx), build_string ("black"), fg_fb);
1980     bg_fb = acons (list1 (Qx), build_string ("Gray80"), bg_fb);
1981 #endif
1982 #ifdef HAVE_TTY
1983     fg_fb = acons (list1 (Qtty), Fvector (0, 0), fg_fb);
1984     bg_fb = acons (list1 (Qtty), Fvector (0, 0), bg_fb);
1985 #endif
1986 #ifdef HAVE_MS_WINDOWS
1987     fg_fb = acons (list1 (Qmsprinter), build_string ("black"), fg_fb);
1988     bg_fb = acons (list1 (Qmsprinter), build_string ("white"), bg_fb);
1989     fg_fb = acons (list1 (Qmswindows), build_string ("black"), fg_fb);
1990     bg_fb = acons (list1 (Qmswindows), build_string ("Gray75"), bg_fb);
1991 #endif
1992     set_specifier_fallback (Fget (Vgui_element_face, Qforeground, Qnil), fg_fb);
1993     set_specifier_fallback (Fget (Vgui_element_face, Qbackground, Qnil), bg_fb);
1994   }
1995
1996   /* Now create the other faces that redisplay needs to refer to
1997      directly.  We could create them in Lisp but it's simpler this
1998      way since we need to get them anyway. */
1999
2000   /* modeline is gui element. */
2001   Vmodeline_face = Fmake_face (Qmodeline, build_string ("modeline face"),
2002                                Qnil);
2003
2004   set_specifier_fallback (Fget (Vmodeline_face, Qforeground, Qunbound),
2005                           Fget (Vgui_element_face, Qforeground, Qunbound));
2006   set_specifier_fallback (Fget (Vmodeline_face, Qbackground, Qunbound),
2007                           Fget (Vgui_element_face, Qbackground, Qunbound));
2008   set_specifier_fallback (Fget (Vmodeline_face, Qbackground_pixmap, Qnil),
2009                           Fget (Vgui_element_face, Qbackground_pixmap,
2010                                 Qunbound));
2011
2012   /* toolbar is another gui element */
2013   Vtoolbar_face = Fmake_face (Qtoolbar,
2014                               build_string ("toolbar face"),
2015                               Qnil);
2016   set_specifier_fallback (Fget (Vtoolbar_face, Qforeground, Qunbound),
2017                           Fget (Vgui_element_face, Qforeground, Qunbound));
2018   set_specifier_fallback (Fget (Vtoolbar_face, Qbackground, Qunbound),
2019                           Fget (Vgui_element_face, Qbackground, Qunbound));
2020   set_specifier_fallback (Fget (Vtoolbar_face, Qbackground_pixmap, Qnil),
2021                           Fget (Vgui_element_face, Qbackground_pixmap,
2022                                 Qunbound));
2023
2024   /* vertical divider is another gui element */
2025   Vvertical_divider_face = Fmake_face (Qvertical_divider,
2026                                        build_string ("vertical divider face"),
2027                                        Qnil);
2028
2029   set_specifier_fallback (Fget (Vvertical_divider_face, Qforeground, Qunbound),
2030                           Fget (Vgui_element_face, Qforeground, Qunbound));
2031   set_specifier_fallback (Fget (Vvertical_divider_face, Qbackground, Qunbound),
2032                           Fget (Vgui_element_face, Qbackground, Qunbound));
2033   set_specifier_fallback (Fget (Vvertical_divider_face, Qbackground_pixmap,
2034                                 Qunbound),
2035                           Fget (Vgui_element_face, Qbackground_pixmap,
2036                                 Qunbound));
2037
2038   /* widget is another gui element */
2039   Vwidget_face = Fmake_face (Qwidget,
2040                              build_string ("widget face"),
2041                              Qnil);
2042   set_specifier_fallback (Fget (Vwidget_face, Qfont, Qunbound),
2043                           Fget (Vgui_element_face, Qfont, Qunbound));
2044   set_specifier_fallback (Fget (Vwidget_face, Qforeground, Qunbound),
2045                           Fget (Vgui_element_face, Qforeground, Qunbound));
2046   set_specifier_fallback (Fget (Vwidget_face, Qbackground, Qunbound),
2047                           Fget (Vgui_element_face, Qbackground, Qunbound));
2048   /* We don't want widgets to have a default background pixmap. */
2049
2050   Vleft_margin_face = Fmake_face (Qleft_margin,
2051                                   build_string ("left margin face"),
2052                                   Qnil);
2053   Vright_margin_face = Fmake_face (Qright_margin,
2054                                    build_string ("right margin face"),
2055                                    Qnil);
2056   Vtext_cursor_face = Fmake_face (Qtext_cursor,
2057                                   build_string ("face for text cursor"),
2058                                   Qnil);
2059   Vpointer_face =
2060     Fmake_face (Qpointer,
2061                 build_string
2062                 ("face for foreground/background colors of mouse pointer"),
2063                 Qnil);
2064 }